diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 60 |
1 files changed, 35 insertions, 25 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1c12b8ec849d..7963e03f1068 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -808,20 +808,38 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req) | |||
808 | kfree(inet_rsk(req)->opt); | 808 | kfree(inet_rsk(req)->opt); |
809 | } | 809 | } |
810 | 810 | ||
811 | static void syn_flood_warning(const struct sk_buff *skb) | 811 | /* |
812 | * Return 1 if a syncookie should be sent | ||
813 | */ | ||
814 | int tcp_syn_flood_action(struct sock *sk, | ||
815 | const struct sk_buff *skb, | ||
816 | const char *proto) | ||
812 | { | 817 | { |
813 | const char *msg; | 818 | const char *msg = "Dropping request"; |
819 | int want_cookie = 0; | ||
820 | struct listen_sock *lopt; | ||
821 | |||
822 | |||
814 | 823 | ||
815 | #ifdef CONFIG_SYN_COOKIES | 824 | #ifdef CONFIG_SYN_COOKIES |
816 | if (sysctl_tcp_syncookies) | 825 | if (sysctl_tcp_syncookies) { |
817 | msg = "Sending cookies"; | 826 | msg = "Sending cookies"; |
818 | else | 827 | want_cookie = 1; |
828 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES); | ||
829 | } else | ||
819 | #endif | 830 | #endif |
820 | msg = "Dropping request"; | 831 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP); |
821 | 832 | ||
822 | pr_info("TCP: Possible SYN flooding on port %d. %s.\n", | 833 | lopt = inet_csk(sk)->icsk_accept_queue.listen_opt; |
823 | ntohs(tcp_hdr(skb)->dest), msg); | 834 | if (!lopt->synflood_warned) { |
835 | lopt->synflood_warned = 1; | ||
836 | pr_info("%s: Possible SYN flooding on port %d. %s. " | ||
837 | " Check SNMP counters.\n", | ||
838 | proto, ntohs(tcp_hdr(skb)->dest), msg); | ||
839 | } | ||
840 | return want_cookie; | ||
824 | } | 841 | } |
842 | EXPORT_SYMBOL(tcp_syn_flood_action); | ||
825 | 843 | ||
826 | /* | 844 | /* |
827 | * Save and compile IPv4 options into the request_sock if needed. | 845 | * Save and compile IPv4 options into the request_sock if needed. |
@@ -909,18 +927,21 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
909 | } | 927 | } |
910 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | 928 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
911 | } | 929 | } |
912 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 930 | |
931 | md5sig = tp->md5sig_info; | ||
932 | if (md5sig->entries4 == 0 && | ||
933 | tcp_alloc_md5sig_pool(sk) == NULL) { | ||
913 | kfree(newkey); | 934 | kfree(newkey); |
914 | return -ENOMEM; | 935 | return -ENOMEM; |
915 | } | 936 | } |
916 | md5sig = tp->md5sig_info; | ||
917 | 937 | ||
918 | if (md5sig->alloced4 == md5sig->entries4) { | 938 | if (md5sig->alloced4 == md5sig->entries4) { |
919 | keys = kmalloc((sizeof(*keys) * | 939 | keys = kmalloc((sizeof(*keys) * |
920 | (md5sig->entries4 + 1)), GFP_ATOMIC); | 940 | (md5sig->entries4 + 1)), GFP_ATOMIC); |
921 | if (!keys) { | 941 | if (!keys) { |
922 | kfree(newkey); | 942 | kfree(newkey); |
923 | tcp_free_md5sig_pool(); | 943 | if (md5sig->entries4 == 0) |
944 | tcp_free_md5sig_pool(); | ||
924 | return -ENOMEM; | 945 | return -ENOMEM; |
925 | } | 946 | } |
926 | 947 | ||
@@ -964,6 +985,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | |||
964 | kfree(tp->md5sig_info->keys4); | 985 | kfree(tp->md5sig_info->keys4); |
965 | tp->md5sig_info->keys4 = NULL; | 986 | tp->md5sig_info->keys4 = NULL; |
966 | tp->md5sig_info->alloced4 = 0; | 987 | tp->md5sig_info->alloced4 = 0; |
988 | tcp_free_md5sig_pool(); | ||
967 | } else if (tp->md5sig_info->entries4 != i) { | 989 | } else if (tp->md5sig_info->entries4 != i) { |
968 | /* Need to do some manipulation */ | 990 | /* Need to do some manipulation */ |
969 | memmove(&tp->md5sig_info->keys4[i], | 991 | memmove(&tp->md5sig_info->keys4[i], |
@@ -971,7 +993,6 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) | |||
971 | (tp->md5sig_info->entries4 - i) * | 993 | (tp->md5sig_info->entries4 - i) * |
972 | sizeof(struct tcp4_md5sig_key)); | 994 | sizeof(struct tcp4_md5sig_key)); |
973 | } | 995 | } |
974 | tcp_free_md5sig_pool(); | ||
975 | return 0; | 996 | return 0; |
976 | } | 997 | } |
977 | } | 998 | } |
@@ -1235,11 +1256,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1235 | __be32 saddr = ip_hdr(skb)->saddr; | 1256 | __be32 saddr = ip_hdr(skb)->saddr; |
1236 | __be32 daddr = ip_hdr(skb)->daddr; | 1257 | __be32 daddr = ip_hdr(skb)->daddr; |
1237 | __u32 isn = TCP_SKB_CB(skb)->when; | 1258 | __u32 isn = TCP_SKB_CB(skb)->when; |
1238 | #ifdef CONFIG_SYN_COOKIES | ||
1239 | int want_cookie = 0; | 1259 | int want_cookie = 0; |
1240 | #else | ||
1241 | #define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */ | ||
1242 | #endif | ||
1243 | 1260 | ||
1244 | /* Never answer to SYNs send to broadcast or multicast */ | 1261 | /* Never answer to SYNs send to broadcast or multicast */ |
1245 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | 1262 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) |
@@ -1250,14 +1267,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1250 | * evidently real one. | 1267 | * evidently real one. |
1251 | */ | 1268 | */ |
1252 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1269 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1253 | if (net_ratelimit()) | 1270 | want_cookie = tcp_syn_flood_action(sk, skb, "TCP"); |
1254 | syn_flood_warning(skb); | 1271 | if (!want_cookie) |
1255 | #ifdef CONFIG_SYN_COOKIES | 1272 | goto drop; |
1256 | if (sysctl_tcp_syncookies) { | ||
1257 | want_cookie = 1; | ||
1258 | } else | ||
1259 | #endif | ||
1260 | goto drop; | ||
1261 | } | 1273 | } |
1262 | 1274 | ||
1263 | /* Accept backlog is full. If we have already queued enough | 1275 | /* Accept backlog is full. If we have already queued enough |
@@ -1303,9 +1315,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1303 | while (l-- > 0) | 1315 | while (l-- > 0) |
1304 | *c++ ^= *hash_location++; | 1316 | *c++ ^= *hash_location++; |
1305 | 1317 | ||
1306 | #ifdef CONFIG_SYN_COOKIES | ||
1307 | want_cookie = 0; /* not our kind of cookie */ | 1318 | want_cookie = 0; /* not our kind of cookie */ |
1308 | #endif | ||
1309 | tmp_ext.cookie_out_never = 0; /* false */ | 1319 | tmp_ext.cookie_out_never = 0; /* false */ |
1310 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | 1320 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; |
1311 | } else if (!tp->rx_opt.cookie_in_always) { | 1321 | } else if (!tp->rx_opt.cookie_in_always) { |