aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/tcp.c3
-rw-r--r--net/ipv4/udp.c55
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_input.c2
-rw-r--r--net/ipv6/ip6mr.c23
-rw-r--r--net/ipv6/route.c2
7 files changed, 64 insertions, 27 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0cd71b84e483..76b148bcb0dc 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -524,7 +524,8 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
524 struct tcp_splice_state *tss = rd_desc->arg.data; 524 struct tcp_splice_state *tss = rd_desc->arg.data;
525 int ret; 525 int ret;
526 526
527 ret = skb_splice_bits(skb, offset, tss->pipe, rd_desc->count, tss->flags); 527 ret = skb_splice_bits(skb, offset, tss->pipe, min(rd_desc->count, len),
528 tss->flags);
528 if (ret > 0) 529 if (ret > 0)
529 rd_desc->count -= ret; 530 rd_desc->count -= ret;
530 return ret; 531 return ret;
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);
120atomic_t udp_memory_allocated; 120atomic_t udp_memory_allocated;
121EXPORT_SYMBOL(udp_memory_allocated); 121EXPORT_SYMBOL(udp_memory_allocated);
122 122
123#define PORTS_PER_CHAIN (65536 / UDP_HTABLE_SIZE)
124
123static int udp_lib_lport_inuse(struct net *net, __u16 num, 125static 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 }
211found:
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)) {
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e92ad8455c63..f9afb452249c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4250,7 +4250,7 @@ static struct addrconf_sysctl_table
4250 .procname = "mc_forwarding", 4250 .procname = "mc_forwarding",
4251 .data = &ipv6_devconf.mc_forwarding, 4251 .data = &ipv6_devconf.mc_forwarding,
4252 .maxlen = sizeof(int), 4252 .maxlen = sizeof(int),
4253 .mode = 0644, 4253 .mode = 0444,
4254 .proc_handler = proc_dointvec, 4254 .proc_handler = proc_dointvec,
4255 }, 4255 },
4256#endif 4256#endif
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 4f433847d95f..36dff8807183 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -443,10 +443,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
443 if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) 443 if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
444 goto relookup_failed; 444 goto relookup_failed;
445 445
446 if (ip6_dst_lookup(sk, &dst2, &fl)) 446 if (ip6_dst_lookup(sk, &dst2, &fl2))
447 goto relookup_failed; 447 goto relookup_failed;
448 448
449 err = xfrm_lookup(net, &dst2, &fl, sk, XFRM_LOOKUP_ICMP); 449 err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP);
450 switch (err) { 450 switch (err) {
451 case 0: 451 case 0:
452 dst_release(dst); 452 dst_release(dst);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 936f48946e20..f171e8dbac91 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -255,6 +255,7 @@ int ip6_mc_input(struct sk_buff *skb)
255 * IPv6 multicast router mode is now supported ;) 255 * IPv6 multicast router mode is now supported ;)
256 */ 256 */
257 if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && 257 if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
258 !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) &&
258 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { 259 likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
259 /* 260 /*
260 * Okay, we try to forward - split and duplicate 261 * Okay, we try to forward - split and duplicate
@@ -316,7 +317,6 @@ int ip6_mc_input(struct sk_buff *skb)
316 } 317 }
317 318
318 if (skb2) { 319 if (skb2) {
319 skb2->dev = skb2->dst->dev;
320 ip6_mr_input(skb2); 320 ip6_mr_input(skb2);
321 } 321 }
322 } 322 }
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 3c51b2d827f4..d19a84b79503 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -365,7 +365,9 @@ static int pim6_rcv(struct sk_buff *skb)
365 pim = (struct pimreghdr *)skb_transport_header(skb); 365 pim = (struct pimreghdr *)skb_transport_header(skb);
366 if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) || 366 if (pim->type != ((PIM_VERSION << 4) | PIM_REGISTER) ||
367 (pim->flags & PIM_NULL_REGISTER) || 367 (pim->flags & PIM_NULL_REGISTER) ||
368 (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && 368 (csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
369 sizeof(*pim), IPPROTO_PIM,
370 csum_partial((void *)pim, sizeof(*pim), 0)) &&
369 csum_fold(skb_checksum(skb, 0, skb->len, 0)))) 371 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
370 goto drop; 372 goto drop;
371 373
@@ -392,7 +394,7 @@ static int pim6_rcv(struct sk_buff *skb)
392 skb_pull(skb, (u8 *)encap - skb->data); 394 skb_pull(skb, (u8 *)encap - skb->data);
393 skb_reset_network_header(skb); 395 skb_reset_network_header(skb);
394 skb->dev = reg_dev; 396 skb->dev = reg_dev;
395 skb->protocol = htons(ETH_P_IP); 397 skb->protocol = htons(ETH_P_IPV6);
396 skb->ip_summed = 0; 398 skb->ip_summed = 0;
397 skb->pkt_type = PACKET_HOST; 399 skb->pkt_type = PACKET_HOST;
398 dst_release(skb->dst); 400 dst_release(skb->dst);
@@ -481,6 +483,7 @@ static int mif6_delete(struct net *net, int vifi)
481{ 483{
482 struct mif_device *v; 484 struct mif_device *v;
483 struct net_device *dev; 485 struct net_device *dev;
486 struct inet6_dev *in6_dev;
484 if (vifi < 0 || vifi >= net->ipv6.maxvif) 487 if (vifi < 0 || vifi >= net->ipv6.maxvif)
485 return -EADDRNOTAVAIL; 488 return -EADDRNOTAVAIL;
486 489
@@ -513,6 +516,10 @@ static int mif6_delete(struct net *net, int vifi)
513 516
514 dev_set_allmulti(dev, -1); 517 dev_set_allmulti(dev, -1);
515 518
519 in6_dev = __in6_dev_get(dev);
520 if (in6_dev)
521 in6_dev->cnf.mc_forwarding--;
522
516 if (v->flags & MIFF_REGISTER) 523 if (v->flags & MIFF_REGISTER)
517 unregister_netdevice(dev); 524 unregister_netdevice(dev);
518 525
@@ -622,6 +629,7 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock)
622 int vifi = vifc->mif6c_mifi; 629 int vifi = vifc->mif6c_mifi;
623 struct mif_device *v = &net->ipv6.vif6_table[vifi]; 630 struct mif_device *v = &net->ipv6.vif6_table[vifi];
624 struct net_device *dev; 631 struct net_device *dev;
632 struct inet6_dev *in6_dev;
625 int err; 633 int err;
626 634
627 /* Is vif busy ? */ 635 /* Is vif busy ? */
@@ -662,6 +670,10 @@ static int mif6_add(struct net *net, struct mif6ctl *vifc, int mrtsock)
662 return -EINVAL; 670 return -EINVAL;
663 } 671 }
664 672
673 in6_dev = __in6_dev_get(dev);
674 if (in6_dev)
675 in6_dev->cnf.mc_forwarding++;
676
665 /* 677 /*
666 * Fill in the VIF structures 678 * Fill in the VIF structures
667 */ 679 */
@@ -838,8 +850,6 @@ static int ip6mr_cache_report(struct net *net, struct sk_buff *pkt, mifi_t mifi,
838 850
839 skb->dst = dst_clone(pkt->dst); 851 skb->dst = dst_clone(pkt->dst);
840 skb->ip_summed = CHECKSUM_UNNECESSARY; 852 skb->ip_summed = CHECKSUM_UNNECESSARY;
841
842 skb_pull(skb, sizeof(struct ipv6hdr));
843 } 853 }
844 854
845 if (net->ipv6.mroute6_sk == NULL) { 855 if (net->ipv6.mroute6_sk == NULL) {
@@ -1222,8 +1232,10 @@ static int ip6mr_sk_init(struct sock *sk)
1222 1232
1223 rtnl_lock(); 1233 rtnl_lock();
1224 write_lock_bh(&mrt_lock); 1234 write_lock_bh(&mrt_lock);
1225 if (likely(net->ipv6.mroute6_sk == NULL)) 1235 if (likely(net->ipv6.mroute6_sk == NULL)) {
1226 net->ipv6.mroute6_sk = sk; 1236 net->ipv6.mroute6_sk = sk;
1237 net->ipv6.devconf_all->mc_forwarding++;
1238 }
1227 else 1239 else
1228 err = -EADDRINUSE; 1240 err = -EADDRINUSE;
1229 write_unlock_bh(&mrt_lock); 1241 write_unlock_bh(&mrt_lock);
@@ -1242,6 +1254,7 @@ int ip6mr_sk_done(struct sock *sk)
1242 if (sk == net->ipv6.mroute6_sk) { 1254 if (sk == net->ipv6.mroute6_sk) {
1243 write_lock_bh(&mrt_lock); 1255 write_lock_bh(&mrt_lock);
1244 net->ipv6.mroute6_sk = NULL; 1256 net->ipv6.mroute6_sk = NULL;
1257 net->ipv6.devconf_all->mc_forwarding--;
1245 write_unlock_bh(&mrt_lock); 1258 write_unlock_bh(&mrt_lock);
1246 1259
1247 mroute_clean_tables(net); 1260 mroute_clean_tables(net);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index c4a59824ac2c..9c574235c905 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -794,7 +794,7 @@ void ip6_route_input(struct sk_buff *skb)
794 .proto = iph->nexthdr, 794 .proto = iph->nexthdr,
795 }; 795 };
796 796
797 if (rt6_need_strict(&iph->daddr)) 797 if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
798 flags |= RT6_LOOKUP_F_IFACE; 798 flags |= RT6_LOOKUP_F_IFACE;
799 799
800 skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input); 800 skb->dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input);