aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c70
1 files changed, 30 insertions, 40 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index dfaa29b8b293..599e1ba6d1ce 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -45,6 +45,7 @@
45#include <net/tcp_states.h> 45#include <net/tcp_states.h>
46#include <net/ip6_checksum.h> 46#include <net/ip6_checksum.h>
47#include <net/xfrm.h> 47#include <net/xfrm.h>
48#include <net/inet6_hashtables.h>
48 49
49#include <linux/proc_fs.h> 50#include <linux/proc_fs.h>
50#include <linux/seq_file.h> 51#include <linux/seq_file.h>
@@ -203,7 +204,8 @@ static struct sock *udp6_lib_lookup2(struct net *net,
203{ 204{
204 struct sock *sk, *result; 205 struct sock *sk, *result;
205 struct hlist_nulls_node *node; 206 struct hlist_nulls_node *node;
206 int score, badness; 207 int score, badness, matches = 0, reuseport = 0;
208 u32 hash = 0;
207 209
208begin: 210begin:
209 result = NULL; 211 result = NULL;
@@ -214,8 +216,18 @@ begin:
214 if (score > badness) { 216 if (score > badness) {
215 result = sk; 217 result = sk;
216 badness = score; 218 badness = score;
217 if (score == SCORE2_MAX) 219 reuseport = sk->sk_reuseport;
220 if (reuseport) {
221 hash = inet6_ehashfn(net, daddr, hnum,
222 saddr, sport);
223 matches = 1;
224 } else if (score == SCORE2_MAX)
218 goto exact_match; 225 goto exact_match;
226 } else if (score == badness && reuseport) {
227 matches++;
228 if (((u64)hash * matches) >> 32 == 0)
229 result = sk;
230 hash = next_pseudo_random32(hash);
219 } 231 }
220 } 232 }
221 /* 233 /*
@@ -249,7 +261,8 @@ struct sock *__udp6_lib_lookup(struct net *net,
249 unsigned short hnum = ntohs(dport); 261 unsigned short hnum = ntohs(dport);
250 unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); 262 unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask);
251 struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; 263 struct udp_hslot *hslot2, *hslot = &udptable->hash[slot];
252 int score, badness; 264 int score, badness, matches = 0, reuseport = 0;
265 u32 hash = 0;
253 266
254 rcu_read_lock(); 267 rcu_read_lock();
255 if (hslot->count > 10) { 268 if (hslot->count > 10) {
@@ -284,6 +297,17 @@ begin:
284 if (score > badness) { 297 if (score > badness) {
285 result = sk; 298 result = sk;
286 badness = score; 299 badness = score;
300 reuseport = sk->sk_reuseport;
301 if (reuseport) {
302 hash = inet6_ehashfn(net, daddr, hnum,
303 saddr, sport);
304 matches = 1;
305 }
306 } else if (score == badness && reuseport) {
307 matches++;
308 if (((u64)hash * matches) >> 32 == 0)
309 result = sk;
310 hash = next_pseudo_random32(hash);
287 } 311 }
288 } 312 }
289 /* 313 /*
@@ -443,7 +467,7 @@ try_again:
443 ip_cmsg_recv(msg, skb); 467 ip_cmsg_recv(msg, skb);
444 } else { 468 } else {
445 if (np->rxopt.all) 469 if (np->rxopt.all)
446 datagram_recv_ctl(sk, msg, skb); 470 ip6_datagram_recv_ctl(sk, msg, skb);
447 } 471 }
448 472
449 err = copied; 473 err = copied;
@@ -752,40 +776,6 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
752 return 0; 776 return 0;
753} 777}
754 778
755static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
756 int proto)
757{
758 int err;
759
760 UDP_SKB_CB(skb)->partial_cov = 0;
761 UDP_SKB_CB(skb)->cscov = skb->len;
762
763 if (proto == IPPROTO_UDPLITE) {
764 err = udplite_checksum_init(skb, uh);
765 if (err)
766 return err;
767 }
768
769 if (uh->check == 0) {
770 /* RFC 2460 section 8.1 says that we SHOULD log
771 this error. Well, it is reasonable.
772 */
773 LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n");
774 return 1;
775 }
776 if (skb->ip_summed == CHECKSUM_COMPLETE &&
777 !csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
778 skb->len, proto, skb->csum))
779 skb->ip_summed = CHECKSUM_UNNECESSARY;
780
781 if (!skb_csum_unnecessary(skb))
782 skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
783 &ipv6_hdr(skb)->daddr,
784 skb->len, proto, 0));
785
786 return 0;
787}
788
789int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, 779int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
790 int proto) 780 int proto)
791{ 781{
@@ -1153,8 +1143,8 @@ do_udp_sendmsg:
1153 memset(opt, 0, sizeof(struct ipv6_txoptions)); 1143 memset(opt, 0, sizeof(struct ipv6_txoptions));
1154 opt->tot_len = sizeof(*opt); 1144 opt->tot_len = sizeof(*opt);
1155 1145
1156 err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, 1146 err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt,
1157 &hlimit, &tclass, &dontfrag); 1147 &hlimit, &tclass, &dontfrag);
1158 if (err < 0) { 1148 if (err < 0) {
1159 fl6_sock_release(flowlabel); 1149 fl6_sock_release(flowlabel);
1160 return err; 1150 return err;