diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/ipconfig.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_filter.c | 7 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_mangle.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_raw.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/iptable_security.c | 6 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 25 | ||||
-rw-r--r-- | net/ipv4/udp.c | 55 |
9 files changed, 65 insertions, 53 deletions
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 42a0f3dd3fd6..d722013c1cae 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -1268,6 +1268,9 @@ __be32 __init root_nfs_parse_addr(char *name) | |||
1268 | static int __init ip_auto_config(void) | 1268 | static int __init ip_auto_config(void) |
1269 | { | 1269 | { |
1270 | __be32 addr; | 1270 | __be32 addr; |
1271 | #ifdef IPCONFIG_DYNAMIC | ||
1272 | int retries = CONF_OPEN_RETRIES; | ||
1273 | #endif | ||
1271 | 1274 | ||
1272 | #ifdef CONFIG_PROC_FS | 1275 | #ifdef CONFIG_PROC_FS |
1273 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); | 1276 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); |
@@ -1304,9 +1307,6 @@ static int __init ip_auto_config(void) | |||
1304 | #endif | 1307 | #endif |
1305 | ic_first_dev->next) { | 1308 | ic_first_dev->next) { |
1306 | #ifdef IPCONFIG_DYNAMIC | 1309 | #ifdef IPCONFIG_DYNAMIC |
1307 | |||
1308 | int retries = CONF_OPEN_RETRIES; | ||
1309 | |||
1310 | if (ic_dynamic() < 0) { | 1310 | if (ic_dynamic() < 0) { |
1311 | ic_close_devs(); | 1311 | ic_close_devs(); |
1312 | 1312 | ||
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index c9224310ebae..52cb6939d093 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -93,13 +93,8 @@ ipt_local_out_hook(unsigned int hook, | |||
93 | { | 93 | { |
94 | /* root is playing with raw sockets. */ | 94 | /* root is playing with raw sockets. */ |
95 | if (skb->len < sizeof(struct iphdr) || | 95 | if (skb->len < sizeof(struct iphdr) || |
96 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | 96 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
97 | if (net_ratelimit()) | ||
98 | printk("iptable_filter: ignoring short SOCK_RAW " | ||
99 | "packet.\n"); | ||
100 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
101 | } | ||
102 | |||
103 | return ipt_do_table(skb, hook, in, out, | 98 | return ipt_do_table(skb, hook, in, out, |
104 | dev_net(out)->ipv4.iptable_filter); | 99 | dev_net(out)->ipv4.iptable_filter); |
105 | } | 100 | } |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 69f2c4287146..3929d20b9e45 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -132,12 +132,8 @@ ipt_local_hook(unsigned int hook, | |||
132 | 132 | ||
133 | /* root is playing with raw sockets. */ | 133 | /* root is playing with raw sockets. */ |
134 | if (skb->len < sizeof(struct iphdr) | 134 | if (skb->len < sizeof(struct iphdr) |
135 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { | 135 | || ip_hdrlen(skb) < sizeof(struct iphdr)) |
136 | if (net_ratelimit()) | ||
137 | printk("iptable_mangle: ignoring short SOCK_RAW " | ||
138 | "packet.\n"); | ||
139 | return NF_ACCEPT; | 136 | return NF_ACCEPT; |
140 | } | ||
141 | 137 | ||
142 | /* Save things which could affect route */ | 138 | /* Save things which could affect route */ |
143 | mark = skb->mark; | 139 | mark = skb->mark; |
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 8faebfe638f1..7f65d18333e3 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -65,12 +65,8 @@ ipt_local_hook(unsigned int hook, | |||
65 | { | 65 | { |
66 | /* root is playing with raw sockets. */ | 66 | /* root is playing with raw sockets. */ |
67 | if (skb->len < sizeof(struct iphdr) || | 67 | if (skb->len < sizeof(struct iphdr) || |
68 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | 68 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
69 | if (net_ratelimit()) | ||
70 | printk("iptable_raw: ignoring short SOCK_RAW " | ||
71 | "packet.\n"); | ||
72 | return NF_ACCEPT; | 69 | return NF_ACCEPT; |
73 | } | ||
74 | return ipt_do_table(skb, hook, in, out, | 70 | return ipt_do_table(skb, hook, in, out, |
75 | dev_net(out)->ipv4.iptable_raw); | 71 | dev_net(out)->ipv4.iptable_raw); |
76 | } | 72 | } |
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 36f3be3cc428..a52a35f4a584 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -96,12 +96,8 @@ ipt_local_out_hook(unsigned int hook, | |||
96 | { | 96 | { |
97 | /* Somebody is playing with raw sockets. */ | 97 | /* Somebody is playing with raw sockets. */ |
98 | if (skb->len < sizeof(struct iphdr) | 98 | if (skb->len < sizeof(struct iphdr) |
99 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { | 99 | || ip_hdrlen(skb) < sizeof(struct iphdr)) |
100 | if (net_ratelimit()) | ||
101 | printk(KERN_INFO "iptable_security: ignoring short " | ||
102 | "SOCK_RAW packet.\n"); | ||
103 | return NF_ACCEPT; | 100 | return NF_ACCEPT; |
104 | } | ||
105 | return ipt_do_table(skb, hook, in, out, | 101 | return ipt_do_table(skb, hook, in, out, |
106 | dev_net(out)->ipv4.iptable_security); | 102 | dev_net(out)->ipv4.iptable_security); |
107 | } | 103 | } |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index b2141e11575e..4beb04fac588 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -145,11 +145,8 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum, | |||
145 | { | 145 | { |
146 | /* root is playing with raw sockets. */ | 146 | /* root is playing with raw sockets. */ |
147 | if (skb->len < sizeof(struct iphdr) || | 147 | if (skb->len < sizeof(struct iphdr) || |
148 | ip_hdrlen(skb) < sizeof(struct iphdr)) { | 148 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
149 | if (net_ratelimit()) | ||
150 | printk("ipt_hook: happy cracking.\n"); | ||
151 | return NF_ACCEPT; | 149 | return NF_ACCEPT; |
152 | } | ||
153 | return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb); | 150 | return nf_conntrack_in(dev_net(out), PF_INET, hooknum, skb); |
154 | } | 151 | } |
155 | 152 | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 1fd3ef7718b6..2a8bee26f43d 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <net/netfilter/nf_conntrack_core.h> | 20 | #include <net/netfilter/nf_conntrack_core.h> |
21 | #include <net/netfilter/nf_log.h> | 21 | #include <net/netfilter/nf_log.h> |
22 | 22 | ||
23 | static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; | 23 | static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; |
24 | 24 | ||
25 | static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, | 25 | static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, |
26 | struct nf_conntrack_tuple *tuple) | 26 | struct nf_conntrack_tuple *tuple) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ce572f9dff02..76b148bcb0dc 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -522,8 +522,13 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, | |||
522 | unsigned int offset, size_t len) | 522 | unsigned int offset, size_t len) |
523 | { | 523 | { |
524 | struct tcp_splice_state *tss = rd_desc->arg.data; | 524 | struct tcp_splice_state *tss = rd_desc->arg.data; |
525 | int ret; | ||
525 | 526 | ||
526 | return skb_splice_bits(skb, offset, tss->pipe, tss->len, tss->flags); | 527 | ret = skb_splice_bits(skb, offset, tss->pipe, min(rd_desc->count, len), |
528 | tss->flags); | ||
529 | if (ret > 0) | ||
530 | rd_desc->count -= ret; | ||
531 | return ret; | ||
527 | } | 532 | } |
528 | 533 | ||
529 | static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) | 534 | static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) |
@@ -531,6 +536,7 @@ static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss) | |||
531 | /* Store TCP splice context information in read_descriptor_t. */ | 536 | /* Store TCP splice context information in read_descriptor_t. */ |
532 | read_descriptor_t rd_desc = { | 537 | read_descriptor_t rd_desc = { |
533 | .arg.data = tss, | 538 | .arg.data = tss, |
539 | .count = tss->len, | ||
534 | }; | 540 | }; |
535 | 541 | ||
536 | return tcp_read_sock(sk, &rd_desc, tcp_splice_data_recv); | 542 | return tcp_read_sock(sk, &rd_desc, tcp_splice_data_recv); |
@@ -611,11 +617,13 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos, | |||
611 | tss.len -= ret; | 617 | tss.len -= ret; |
612 | spliced += ret; | 618 | spliced += ret; |
613 | 619 | ||
620 | if (!timeo) | ||
621 | break; | ||
614 | release_sock(sk); | 622 | release_sock(sk); |
615 | lock_sock(sk); | 623 | lock_sock(sk); |
616 | 624 | ||
617 | if (sk->sk_err || sk->sk_state == TCP_CLOSE || | 625 | if (sk->sk_err || sk->sk_state == TCP_CLOSE || |
618 | (sk->sk_shutdown & RCV_SHUTDOWN) || !timeo || | 626 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
619 | signal_pending(current)) | 627 | signal_pending(current)) |
620 | break; | 628 | break; |
621 | } | 629 | } |
@@ -2382,7 +2390,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2382 | unsigned int seq; | 2390 | unsigned int seq; |
2383 | __be32 delta; | 2391 | __be32 delta; |
2384 | unsigned int oldlen; | 2392 | unsigned int oldlen; |
2385 | unsigned int len; | 2393 | unsigned int mss; |
2386 | 2394 | ||
2387 | if (!pskb_may_pull(skb, sizeof(*th))) | 2395 | if (!pskb_may_pull(skb, sizeof(*th))) |
2388 | goto out; | 2396 | goto out; |
@@ -2398,10 +2406,13 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2398 | oldlen = (u16)~skb->len; | 2406 | oldlen = (u16)~skb->len; |
2399 | __skb_pull(skb, thlen); | 2407 | __skb_pull(skb, thlen); |
2400 | 2408 | ||
2409 | mss = skb_shinfo(skb)->gso_size; | ||
2410 | if (unlikely(skb->len <= mss)) | ||
2411 | goto out; | ||
2412 | |||
2401 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | 2413 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { |
2402 | /* Packet is from an untrusted source, reset gso_segs. */ | 2414 | /* Packet is from an untrusted source, reset gso_segs. */ |
2403 | int type = skb_shinfo(skb)->gso_type; | 2415 | int type = skb_shinfo(skb)->gso_type; |
2404 | int mss; | ||
2405 | 2416 | ||
2406 | if (unlikely(type & | 2417 | if (unlikely(type & |
2407 | ~(SKB_GSO_TCPV4 | | 2418 | ~(SKB_GSO_TCPV4 | |
@@ -2412,7 +2423,6 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2412 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | 2423 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) |
2413 | goto out; | 2424 | goto out; |
2414 | 2425 | ||
2415 | mss = skb_shinfo(skb)->gso_size; | ||
2416 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); | 2426 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss); |
2417 | 2427 | ||
2418 | segs = NULL; | 2428 | segs = NULL; |
@@ -2423,8 +2433,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2423 | if (IS_ERR(segs)) | 2433 | if (IS_ERR(segs)) |
2424 | goto out; | 2434 | goto out; |
2425 | 2435 | ||
2426 | len = skb_shinfo(skb)->gso_size; | 2436 | delta = htonl(oldlen + (thlen + mss)); |
2427 | delta = htonl(oldlen + (thlen + len)); | ||
2428 | 2437 | ||
2429 | skb = segs; | 2438 | skb = segs; |
2430 | th = tcp_hdr(skb); | 2439 | th = tcp_hdr(skb); |
@@ -2440,7 +2449,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
2440 | csum_fold(csum_partial(skb_transport_header(skb), | 2449 | csum_fold(csum_partial(skb_transport_header(skb), |
2441 | thlen, skb->csum)); | 2450 | thlen, skb->csum)); |
2442 | 2451 | ||
2443 | seq += len; | 2452 | seq += mss; |
2444 | skb = skb->next; | 2453 | skb = skb->next; |
2445 | th = tcp_hdr(skb); | 2454 | th = tcp_hdr(skb); |
2446 | 2455 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cf5ab0581eba..b7faffe5c029 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -120,8 +120,11 @@ EXPORT_SYMBOL(sysctl_udp_wmem_min); | |||
120 | atomic_t udp_memory_allocated; | 120 | atomic_t udp_memory_allocated; |
121 | EXPORT_SYMBOL(udp_memory_allocated); | 121 | EXPORT_SYMBOL(udp_memory_allocated); |
122 | 122 | ||
123 | #define PORTS_PER_CHAIN (65536 / UDP_HTABLE_SIZE) | ||
124 | |||
123 | static int udp_lib_lport_inuse(struct net *net, __u16 num, | 125 | static int udp_lib_lport_inuse(struct net *net, __u16 num, |
124 | const struct udp_hslot *hslot, | 126 | const struct udp_hslot *hslot, |
127 | unsigned long *bitmap, | ||
125 | struct sock *sk, | 128 | struct sock *sk, |
126 | int (*saddr_comp)(const struct sock *sk1, | 129 | int (*saddr_comp)(const struct sock *sk1, |
127 | const struct sock *sk2)) | 130 | const struct sock *sk2)) |
@@ -132,12 +135,17 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, | |||
132 | sk_nulls_for_each(sk2, node, &hslot->head) | 135 | sk_nulls_for_each(sk2, node, &hslot->head) |
133 | if (net_eq(sock_net(sk2), net) && | 136 | if (net_eq(sock_net(sk2), net) && |
134 | sk2 != sk && | 137 | sk2 != sk && |
135 | sk2->sk_hash == num && | 138 | (bitmap || sk2->sk_hash == num) && |
136 | (!sk2->sk_reuse || !sk->sk_reuse) && | 139 | (!sk2->sk_reuse || !sk->sk_reuse) && |
137 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 140 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
138 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 141 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
139 | (*saddr_comp)(sk, sk2)) | 142 | (*saddr_comp)(sk, sk2)) { |
140 | return 1; | 143 | if (bitmap) |
144 | __set_bit(sk2->sk_hash / UDP_HTABLE_SIZE, | ||
145 | bitmap); | ||
146 | else | ||
147 | return 1; | ||
148 | } | ||
141 | return 0; | 149 | return 0; |
142 | } | 150 | } |
143 | 151 | ||
@@ -160,32 +168,47 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
160 | if (!snum) { | 168 | if (!snum) { |
161 | int low, high, remaining; | 169 | int low, high, remaining; |
162 | unsigned rand; | 170 | unsigned rand; |
163 | unsigned short first; | 171 | unsigned short first, last; |
172 | DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN); | ||
164 | 173 | ||
165 | inet_get_local_port_range(&low, &high); | 174 | inet_get_local_port_range(&low, &high); |
166 | remaining = (high - low) + 1; | 175 | remaining = (high - low) + 1; |
167 | 176 | ||
168 | rand = net_random(); | 177 | rand = net_random(); |
169 | snum = first = rand % remaining + low; | 178 | first = (((u64)rand * remaining) >> 32) + low; |
170 | rand |= 1; | 179 | /* |
171 | for (;;) { | 180 | * force rand to be an odd multiple of UDP_HTABLE_SIZE |
172 | hslot = &udptable->hash[udp_hashfn(net, snum)]; | 181 | */ |
182 | rand = (rand | 1) * UDP_HTABLE_SIZE; | ||
183 | for (last = first + UDP_HTABLE_SIZE; first != last; first++) { | ||
184 | hslot = &udptable->hash[udp_hashfn(net, first)]; | ||
185 | bitmap_zero(bitmap, PORTS_PER_CHAIN); | ||
173 | spin_lock_bh(&hslot->lock); | 186 | spin_lock_bh(&hslot->lock); |
174 | if (!udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp)) | 187 | udp_lib_lport_inuse(net, snum, hslot, bitmap, sk, |
175 | break; | 188 | saddr_comp); |
176 | spin_unlock_bh(&hslot->lock); | 189 | |
190 | snum = first; | ||
191 | /* | ||
192 | * Iterate on all possible values of snum for this hash. | ||
193 | * Using steps of an odd multiple of UDP_HTABLE_SIZE | ||
194 | * give us randomization and full range coverage. | ||
195 | */ | ||
177 | do { | 196 | do { |
178 | snum = snum + rand; | 197 | if (low <= snum && snum <= high && |
179 | } while (snum < low || snum > high); | 198 | !test_bit(snum / UDP_HTABLE_SIZE, bitmap)) |
180 | if (snum == first) | 199 | goto found; |
181 | goto fail; | 200 | snum += rand; |
201 | } while (snum != first); | ||
202 | spin_unlock_bh(&hslot->lock); | ||
182 | } | 203 | } |
204 | goto fail; | ||
183 | } else { | 205 | } else { |
184 | hslot = &udptable->hash[udp_hashfn(net, snum)]; | 206 | hslot = &udptable->hash[udp_hashfn(net, snum)]; |
185 | spin_lock_bh(&hslot->lock); | 207 | spin_lock_bh(&hslot->lock); |
186 | if (udp_lib_lport_inuse(net, snum, hslot, sk, saddr_comp)) | 208 | if (udp_lib_lport_inuse(net, snum, hslot, NULL, sk, saddr_comp)) |
187 | goto fail_unlock; | 209 | goto fail_unlock; |
188 | } | 210 | } |
211 | found: | ||
189 | inet_sk(sk)->num = snum; | 212 | inet_sk(sk)->num = snum; |
190 | sk->sk_hash = snum; | 213 | sk->sk_hash = snum; |
191 | if (sk_unhashed(sk)) { | 214 | if (sk_unhashed(sk)) { |