|
@@ -808,20 +808,38 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req)
|
|
|
kfree(inet_rsk(req)->opt);
|
|
|
}
|
|
|
|
|
|
-static void syn_flood_warning(const struct sk_buff *skb)
|
|
|
+/*
|
|
|
+ * Return 1 if a syncookie should be sent
|
|
|
+ */
|
|
|
+int tcp_syn_flood_action(struct sock *sk,
|
|
|
+ const struct sk_buff *skb,
|
|
|
+ const char *proto)
|
|
|
{
|
|
|
- const char *msg;
|
|
|
+ const char *msg = "Dropping request";
|
|
|
+ int want_cookie = 0;
|
|
|
+ struct listen_sock *lopt;
|
|
|
+
|
|
|
+
|
|
|
|
|
|
#ifdef CONFIG_SYN_COOKIES
|
|
|
- if (sysctl_tcp_syncookies)
|
|
|
+ if (sysctl_tcp_syncookies) {
|
|
|
msg = "Sending cookies";
|
|
|
- else
|
|
|
+ want_cookie = 1;
|
|
|
+ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
|
|
|
+ } else
|
|
|
#endif
|
|
|
- msg = "Dropping request";
|
|
|
+ NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
|
|
|
|
|
|
- pr_info("TCP: Possible SYN flooding on port %d. %s.\n",
|
|
|
- ntohs(tcp_hdr(skb)->dest), msg);
|
|
|
+ lopt = inet_csk(sk)->icsk_accept_queue.listen_opt;
|
|
|
+ if (!lopt->synflood_warned) {
|
|
|
+ lopt->synflood_warned = 1;
|
|
|
+ pr_info("%s: Possible SYN flooding on port %d. %s. "
|
|
|
+ " Check SNMP counters.\n",
|
|
|
+ proto, ntohs(tcp_hdr(skb)->dest), msg);
|
|
|
+ }
|
|
|
+ return want_cookie;
|
|
|
}
|
|
|
+EXPORT_SYMBOL(tcp_syn_flood_action);
|
|
|
|
|
|
/*
|
|
|
* Save and compile IPv4 options into the request_sock if needed.
|
|
@@ -1235,11 +1253,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
|
|
__be32 saddr = ip_hdr(skb)->saddr;
|
|
|
__be32 daddr = ip_hdr(skb)->daddr;
|
|
|
__u32 isn = TCP_SKB_CB(skb)->when;
|
|
|
-#ifdef CONFIG_SYN_COOKIES
|
|
|
int want_cookie = 0;
|
|
|
-#else
|
|
|
-#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
|
|
|
-#endif
|
|
|
|
|
|
/* Never answer to SYNs send to broadcast or multicast */
|
|
|
if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
|
@@ -1250,14 +1264,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
|
|
* evidently real one.
|
|
|
*/
|
|
|
if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
|
|
|
- if (net_ratelimit())
|
|
|
- syn_flood_warning(skb);
|
|
|
-#ifdef CONFIG_SYN_COOKIES
|
|
|
- if (sysctl_tcp_syncookies) {
|
|
|
- want_cookie = 1;
|
|
|
- } else
|
|
|
-#endif
|
|
|
- goto drop;
|
|
|
+ want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
|
|
|
+ if (!want_cookie)
|
|
|
+ goto drop;
|
|
|
}
|
|
|
|
|
|
/* Accept backlog is full. If we have already queued enough
|
|
@@ -1303,9 +1312,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
|
|
while (l-- > 0)
|
|
|
*c++ ^= *hash_location++;
|
|
|
|
|
|
-#ifdef CONFIG_SYN_COOKIES
|
|
|
want_cookie = 0; /* not our kind of cookie */
|
|
|
-#endif
|
|
|
tmp_ext.cookie_out_never = 0; /* false */
|
|
|
tmp_ext.cookie_plus = tmp_opt.cookie_plus;
|
|
|
} else if (!tp->rx_opt.cookie_in_always) {
|