diff options
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 154 |
1 files changed, 81 insertions, 73 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5acb3560ff15..328985c40883 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -54,8 +54,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
54 | { | 54 | { |
55 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | 55 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; |
56 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 56 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
57 | __be32 sk1_rcv_saddr = inet_sk(sk)->inet_rcv_saddr; | 57 | __be32 sk1_rcv_saddr = sk_rcv_saddr(sk); |
58 | __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); | 58 | __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); |
59 | int sk_ipv6only = ipv6_only_sock(sk); | 59 | int sk_ipv6only = ipv6_only_sock(sk); |
60 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 60 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
61 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | 61 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); |
@@ -122,8 +122,8 @@ static void udp_v6_rehash(struct sock *sk) | |||
122 | 122 | ||
123 | static inline int compute_score(struct sock *sk, struct net *net, | 123 | static inline int compute_score(struct sock *sk, struct net *net, |
124 | unsigned short hnum, | 124 | unsigned short hnum, |
125 | struct in6_addr *saddr, __be16 sport, | 125 | const struct in6_addr *saddr, __be16 sport, |
126 | struct in6_addr *daddr, __be16 dport, | 126 | const struct in6_addr *daddr, __be16 dport, |
127 | int dif) | 127 | int dif) |
128 | { | 128 | { |
129 | int score = -1; | 129 | int score = -1; |
@@ -227,7 +227,7 @@ begin: | |||
227 | 227 | ||
228 | if (result) { | 228 | if (result) { |
229 | exact_match: | 229 | exact_match: |
230 | if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) | 230 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
231 | result = NULL; | 231 | result = NULL; |
232 | else if (unlikely(compute_score2(result, net, saddr, sport, | 232 | else if (unlikely(compute_score2(result, net, saddr, sport, |
233 | daddr, hnum, dif) < badness)) { | 233 | daddr, hnum, dif) < badness)) { |
@@ -239,8 +239,8 @@ exact_match: | |||
239 | } | 239 | } |
240 | 240 | ||
241 | static struct sock *__udp6_lib_lookup(struct net *net, | 241 | static struct sock *__udp6_lib_lookup(struct net *net, |
242 | struct in6_addr *saddr, __be16 sport, | 242 | const struct in6_addr *saddr, __be16 sport, |
243 | struct in6_addr *daddr, __be16 dport, | 243 | const struct in6_addr *daddr, __be16 dport, |
244 | int dif, struct udp_table *udptable) | 244 | int dif, struct udp_table *udptable) |
245 | { | 245 | { |
246 | struct sock *sk, *result; | 246 | struct sock *sk, *result; |
@@ -294,7 +294,7 @@ begin: | |||
294 | goto begin; | 294 | goto begin; |
295 | 295 | ||
296 | if (result) { | 296 | if (result) { |
297 | if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) | 297 | if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2))) |
298 | result = NULL; | 298 | result = NULL; |
299 | else if (unlikely(compute_score(result, net, hnum, saddr, sport, | 299 | else if (unlikely(compute_score(result, net, hnum, saddr, sport, |
300 | daddr, dport, dif) < badness)) { | 300 | daddr, dport, dif) < badness)) { |
@@ -311,7 +311,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | |||
311 | struct udp_table *udptable) | 311 | struct udp_table *udptable) |
312 | { | 312 | { |
313 | struct sock *sk; | 313 | struct sock *sk; |
314 | struct ipv6hdr *iph = ipv6_hdr(skb); | 314 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
315 | 315 | ||
316 | if (unlikely(sk = skb_steal_sock(skb))) | 316 | if (unlikely(sk = skb_steal_sock(skb))) |
317 | return sk; | 317 | return sk; |
@@ -320,6 +320,14 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | |||
320 | udptable); | 320 | udptable); |
321 | } | 321 | } |
322 | 322 | ||
323 | struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, | ||
324 | const struct in6_addr *daddr, __be16 dport, int dif) | ||
325 | { | ||
326 | return __udp6_lib_lookup(net, saddr, sport, daddr, dport, dif, &udp_table); | ||
327 | } | ||
328 | EXPORT_SYMBOL_GPL(udp6_lib_lookup); | ||
329 | |||
330 | |||
323 | /* | 331 | /* |
324 | * This should be easy, if there is something there we | 332 | * This should be easy, if there is something there we |
325 | * return it, otherwise we block. | 333 | * return it, otherwise we block. |
@@ -445,8 +453,11 @@ csum_copy_err: | |||
445 | } | 453 | } |
446 | unlock_sock_fast(sk, slow); | 454 | unlock_sock_fast(sk, slow); |
447 | 455 | ||
448 | if (flags & MSG_DONTWAIT) | 456 | if (noblock) |
449 | return -EAGAIN; | 457 | return -EAGAIN; |
458 | |||
459 | /* starting over for a new packet */ | ||
460 | msg->msg_flags &= ~MSG_TRUNC; | ||
450 | goto try_again; | 461 | goto try_again; |
451 | } | 462 | } |
452 | 463 | ||
@@ -455,9 +466,9 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
455 | struct udp_table *udptable) | 466 | struct udp_table *udptable) |
456 | { | 467 | { |
457 | struct ipv6_pinfo *np; | 468 | struct ipv6_pinfo *np; |
458 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 469 | const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; |
459 | struct in6_addr *saddr = &hdr->saddr; | 470 | const struct in6_addr *saddr = &hdr->saddr; |
460 | struct in6_addr *daddr = &hdr->daddr; | 471 | const struct in6_addr *daddr = &hdr->daddr; |
461 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 472 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
462 | struct sock *sk; | 473 | struct sock *sk; |
463 | int err; | 474 | int err; |
@@ -497,6 +508,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
497 | int rc; | 508 | int rc; |
498 | int is_udplite = IS_UDPLITE(sk); | 509 | int is_udplite = IS_UDPLITE(sk); |
499 | 510 | ||
511 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | ||
512 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
513 | |||
500 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 514 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
501 | goto drop; | 515 | goto drop; |
502 | 516 | ||
@@ -519,7 +533,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
519 | } | 533 | } |
520 | } | 534 | } |
521 | 535 | ||
522 | if (sk->sk_filter) { | 536 | if (rcu_dereference_raw(sk->sk_filter)) { |
523 | if (udp_lib_checksum_complete(skb)) | 537 | if (udp_lib_checksum_complete(skb)) |
524 | goto drop; | 538 | goto drop; |
525 | } | 539 | } |
@@ -542,8 +556,8 @@ drop_no_sk_drops_inc: | |||
542 | } | 556 | } |
543 | 557 | ||
544 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | 558 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, |
545 | __be16 loc_port, struct in6_addr *loc_addr, | 559 | __be16 loc_port, const struct in6_addr *loc_addr, |
546 | __be16 rmt_port, struct in6_addr *rmt_addr, | 560 | __be16 rmt_port, const struct in6_addr *rmt_addr, |
547 | int dif) | 561 | int dif) |
548 | { | 562 | { |
549 | struct hlist_nulls_node *node; | 563 | struct hlist_nulls_node *node; |
@@ -594,7 +608,7 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
594 | 608 | ||
595 | sk = stack[i]; | 609 | sk = stack[i]; |
596 | if (skb1) { | 610 | if (skb1) { |
597 | if (sk_rcvqueues_full(sk, skb)) { | 611 | if (sk_rcvqueues_full(sk, skb1)) { |
598 | kfree_skb(skb1); | 612 | kfree_skb(skb1); |
599 | goto drop; | 613 | goto drop; |
600 | } | 614 | } |
@@ -622,7 +636,7 @@ drop: | |||
622 | * so we don't need to lock the hashes. | 636 | * so we don't need to lock the hashes. |
623 | */ | 637 | */ |
624 | static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | 638 | static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
625 | struct in6_addr *saddr, struct in6_addr *daddr, | 639 | const struct in6_addr *saddr, const struct in6_addr *daddr, |
626 | struct udp_table *udptable) | 640 | struct udp_table *udptable) |
627 | { | 641 | { |
628 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; | 642 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
@@ -705,7 +719,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
705 | struct net *net = dev_net(skb->dev); | 719 | struct net *net = dev_net(skb->dev); |
706 | struct sock *sk; | 720 | struct sock *sk; |
707 | struct udphdr *uh; | 721 | struct udphdr *uh; |
708 | struct in6_addr *saddr, *daddr; | 722 | const struct in6_addr *saddr, *daddr; |
709 | u32 ulen = 0; | 723 | u32 ulen = 0; |
710 | 724 | ||
711 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 725 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
@@ -878,7 +892,7 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
878 | struct udphdr *uh; | 892 | struct udphdr *uh; |
879 | struct udp_sock *up = udp_sk(sk); | 893 | struct udp_sock *up = udp_sk(sk); |
880 | struct inet_sock *inet = inet_sk(sk); | 894 | struct inet_sock *inet = inet_sk(sk); |
881 | struct flowi *fl = &inet->cork.fl; | 895 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
882 | int err = 0; | 896 | int err = 0; |
883 | int is_udplite = IS_UDPLITE(sk); | 897 | int is_udplite = IS_UDPLITE(sk); |
884 | __wsum csum = 0; | 898 | __wsum csum = 0; |
@@ -891,23 +905,23 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
891 | * Create a UDP header | 905 | * Create a UDP header |
892 | */ | 906 | */ |
893 | uh = udp_hdr(skb); | 907 | uh = udp_hdr(skb); |
894 | uh->source = fl->fl_ip_sport; | 908 | uh->source = fl6->fl6_sport; |
895 | uh->dest = fl->fl_ip_dport; | 909 | uh->dest = fl6->fl6_dport; |
896 | uh->len = htons(up->len); | 910 | uh->len = htons(up->len); |
897 | uh->check = 0; | 911 | uh->check = 0; |
898 | 912 | ||
899 | if (is_udplite) | 913 | if (is_udplite) |
900 | csum = udplite_csum_outgoing(sk, skb); | 914 | csum = udplite_csum_outgoing(sk, skb); |
901 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ | 915 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |
902 | udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst, | 916 | udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, |
903 | up->len); | 917 | up->len); |
904 | goto send; | 918 | goto send; |
905 | } else | 919 | } else |
906 | csum = udp_csum_outgoing(sk, skb); | 920 | csum = udp_csum_outgoing(sk, skb); |
907 | 921 | ||
908 | /* add protocol-dependent pseudo-header */ | 922 | /* add protocol-dependent pseudo-header */ |
909 | uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, | 923 | uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, |
910 | up->len, fl->proto, csum ); | 924 | up->len, fl6->flowi6_proto, csum); |
911 | if (uh->check == 0) | 925 | if (uh->check == 0) |
912 | uh->check = CSUM_MANGLED_0; | 926 | uh->check = CSUM_MANGLED_0; |
913 | 927 | ||
@@ -939,7 +953,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
939 | struct in6_addr *daddr, *final_p, final; | 953 | struct in6_addr *daddr, *final_p, final; |
940 | struct ipv6_txoptions *opt = NULL; | 954 | struct ipv6_txoptions *opt = NULL; |
941 | struct ip6_flowlabel *flowlabel = NULL; | 955 | struct ip6_flowlabel *flowlabel = NULL; |
942 | struct flowi fl; | 956 | struct flowi6 fl6; |
943 | struct dst_entry *dst; | 957 | struct dst_entry *dst; |
944 | int addr_len = msg->msg_namelen; | 958 | int addr_len = msg->msg_namelen; |
945 | int ulen = len; | 959 | int ulen = len; |
@@ -1022,19 +1036,19 @@ do_udp_sendmsg: | |||
1022 | } | 1036 | } |
1023 | ulen += sizeof(struct udphdr); | 1037 | ulen += sizeof(struct udphdr); |
1024 | 1038 | ||
1025 | memset(&fl, 0, sizeof(fl)); | 1039 | memset(&fl6, 0, sizeof(fl6)); |
1026 | 1040 | ||
1027 | if (sin6) { | 1041 | if (sin6) { |
1028 | if (sin6->sin6_port == 0) | 1042 | if (sin6->sin6_port == 0) |
1029 | return -EINVAL; | 1043 | return -EINVAL; |
1030 | 1044 | ||
1031 | fl.fl_ip_dport = sin6->sin6_port; | 1045 | fl6.fl6_dport = sin6->sin6_port; |
1032 | daddr = &sin6->sin6_addr; | 1046 | daddr = &sin6->sin6_addr; |
1033 | 1047 | ||
1034 | if (np->sndflow) { | 1048 | if (np->sndflow) { |
1035 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 1049 | fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
1036 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 1050 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
1037 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1051 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1038 | if (flowlabel == NULL) | 1052 | if (flowlabel == NULL) |
1039 | return -EINVAL; | 1053 | return -EINVAL; |
1040 | daddr = &flowlabel->dst; | 1054 | daddr = &flowlabel->dst; |
@@ -1052,38 +1066,38 @@ do_udp_sendmsg: | |||
1052 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1066 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1053 | sin6->sin6_scope_id && | 1067 | sin6->sin6_scope_id && |
1054 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 1068 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
1055 | fl.oif = sin6->sin6_scope_id; | 1069 | fl6.flowi6_oif = sin6->sin6_scope_id; |
1056 | } else { | 1070 | } else { |
1057 | if (sk->sk_state != TCP_ESTABLISHED) | 1071 | if (sk->sk_state != TCP_ESTABLISHED) |
1058 | return -EDESTADDRREQ; | 1072 | return -EDESTADDRREQ; |
1059 | 1073 | ||
1060 | fl.fl_ip_dport = inet->inet_dport; | 1074 | fl6.fl6_dport = inet->inet_dport; |
1061 | daddr = &np->daddr; | 1075 | daddr = &np->daddr; |
1062 | fl.fl6_flowlabel = np->flow_label; | 1076 | fl6.flowlabel = np->flow_label; |
1063 | connected = 1; | 1077 | connected = 1; |
1064 | } | 1078 | } |
1065 | 1079 | ||
1066 | if (!fl.oif) | 1080 | if (!fl6.flowi6_oif) |
1067 | fl.oif = sk->sk_bound_dev_if; | 1081 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
1068 | 1082 | ||
1069 | if (!fl.oif) | 1083 | if (!fl6.flowi6_oif) |
1070 | fl.oif = np->sticky_pktinfo.ipi6_ifindex; | 1084 | fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; |
1071 | 1085 | ||
1072 | fl.mark = sk->sk_mark; | 1086 | fl6.flowi6_mark = sk->sk_mark; |
1073 | 1087 | ||
1074 | if (msg->msg_controllen) { | 1088 | if (msg->msg_controllen) { |
1075 | opt = &opt_space; | 1089 | opt = &opt_space; |
1076 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1090 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1077 | opt->tot_len = sizeof(*opt); | 1091 | opt->tot_len = sizeof(*opt); |
1078 | 1092 | ||
1079 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, | 1093 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, |
1080 | &tclass, &dontfrag); | 1094 | &tclass, &dontfrag); |
1081 | if (err < 0) { | 1095 | if (err < 0) { |
1082 | fl6_sock_release(flowlabel); | 1096 | fl6_sock_release(flowlabel); |
1083 | return err; | 1097 | return err; |
1084 | } | 1098 | } |
1085 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 1099 | if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
1086 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1100 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1087 | if (flowlabel == NULL) | 1101 | if (flowlabel == NULL) |
1088 | return -EINVAL; | 1102 | return -EINVAL; |
1089 | } | 1103 | } |
@@ -1097,42 +1111,35 @@ do_udp_sendmsg: | |||
1097 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 1111 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
1098 | opt = ipv6_fixup_options(&opt_space, opt); | 1112 | opt = ipv6_fixup_options(&opt_space, opt); |
1099 | 1113 | ||
1100 | fl.proto = sk->sk_protocol; | 1114 | fl6.flowi6_proto = sk->sk_protocol; |
1101 | if (!ipv6_addr_any(daddr)) | 1115 | if (!ipv6_addr_any(daddr)) |
1102 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 1116 | ipv6_addr_copy(&fl6.daddr, daddr); |
1103 | else | 1117 | else |
1104 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 1118 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
1105 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 1119 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
1106 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1120 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
1107 | fl.fl_ip_sport = inet->inet_sport; | 1121 | fl6.fl6_sport = inet->inet_sport; |
1108 | 1122 | ||
1109 | final_p = fl6_update_dst(&fl, opt, &final); | 1123 | final_p = fl6_update_dst(&fl6, opt, &final); |
1110 | if (final_p) | 1124 | if (final_p) |
1111 | connected = 0; | 1125 | connected = 0; |
1112 | 1126 | ||
1113 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1127 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { |
1114 | fl.oif = np->mcast_oif; | 1128 | fl6.flowi6_oif = np->mcast_oif; |
1115 | connected = 0; | 1129 | connected = 0; |
1116 | } | 1130 | } |
1117 | 1131 | ||
1118 | security_sk_classify_flow(sk, &fl); | 1132 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
1119 | 1133 | ||
1120 | err = ip6_sk_dst_lookup(sk, &dst, &fl); | 1134 | dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, true); |
1121 | if (err) | 1135 | if (IS_ERR(dst)) { |
1136 | err = PTR_ERR(dst); | ||
1137 | dst = NULL; | ||
1122 | goto out; | 1138 | goto out; |
1123 | if (final_p) | ||
1124 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
1125 | |||
1126 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
1127 | if (err < 0) { | ||
1128 | if (err == -EREMOTE) | ||
1129 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
1130 | if (err < 0) | ||
1131 | goto out; | ||
1132 | } | 1139 | } |
1133 | 1140 | ||
1134 | if (hlimit < 0) { | 1141 | if (hlimit < 0) { |
1135 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 1142 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
1136 | hlimit = np->mcast_hops; | 1143 | hlimit = np->mcast_hops; |
1137 | else | 1144 | else |
1138 | hlimit = np->hop_limit; | 1145 | hlimit = np->hop_limit; |
@@ -1167,7 +1174,7 @@ do_append_data: | |||
1167 | up->len += ulen; | 1174 | up->len += ulen; |
1168 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 1175 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1169 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1176 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1170 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1177 | sizeof(struct udphdr), hlimit, tclass, opt, &fl6, |
1171 | (struct rt6_info*)dst, | 1178 | (struct rt6_info*)dst, |
1172 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); | 1179 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1173 | if (err) | 1180 | if (err) |
@@ -1180,10 +1187,10 @@ do_append_data: | |||
1180 | if (dst) { | 1187 | if (dst) { |
1181 | if (connected) { | 1188 | if (connected) { |
1182 | ip6_dst_store(sk, dst, | 1189 | ip6_dst_store(sk, dst, |
1183 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? | 1190 | ipv6_addr_equal(&fl6.daddr, &np->daddr) ? |
1184 | &np->daddr : NULL, | 1191 | &np->daddr : NULL, |
1185 | #ifdef CONFIG_IPV6_SUBTREES | 1192 | #ifdef CONFIG_IPV6_SUBTREES |
1186 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? | 1193 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? |
1187 | &np->saddr : | 1194 | &np->saddr : |
1188 | #endif | 1195 | #endif |
1189 | NULL); | 1196 | NULL); |
@@ -1274,7 +1281,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, | |||
1274 | 1281 | ||
1275 | static int udp6_ufo_send_check(struct sk_buff *skb) | 1282 | static int udp6_ufo_send_check(struct sk_buff *skb) |
1276 | { | 1283 | { |
1277 | struct ipv6hdr *ipv6h; | 1284 | const struct ipv6hdr *ipv6h; |
1278 | struct udphdr *uh; | 1285 | struct udphdr *uh; |
1279 | 1286 | ||
1280 | if (!pskb_may_pull(skb, sizeof(*uh))) | 1287 | if (!pskb_may_pull(skb, sizeof(*uh))) |
@@ -1291,7 +1298,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
1291 | return 0; | 1298 | return 0; |
1292 | } | 1299 | } |
1293 | 1300 | ||
1294 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | 1301 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) |
1295 | { | 1302 | { |
1296 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1303 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1297 | unsigned int mss; | 1304 | unsigned int mss; |
@@ -1324,14 +1331,14 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | |||
1324 | /* Do software UFO. Complete and fill in the UDP checksum as HW cannot | 1331 | /* Do software UFO. Complete and fill in the UDP checksum as HW cannot |
1325 | * do checksum of UDP packets sent as multiple IP fragments. | 1332 | * do checksum of UDP packets sent as multiple IP fragments. |
1326 | */ | 1333 | */ |
1327 | offset = skb->csum_start - skb_headroom(skb); | 1334 | offset = skb_checksum_start_offset(skb); |
1328 | csum = skb_checksum(skb, offset, skb->len- offset, 0); | 1335 | csum = skb_checksum(skb, offset, skb->len- offset, 0); |
1329 | offset += skb->csum_offset; | 1336 | offset += skb->csum_offset; |
1330 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); | 1337 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); |
1331 | skb->ip_summed = CHECKSUM_NONE; | 1338 | skb->ip_summed = CHECKSUM_NONE; |
1332 | 1339 | ||
1333 | /* Check if there is enough headroom to insert fragment header. */ | 1340 | /* Check if there is enough headroom to insert fragment header. */ |
1334 | if ((skb_headroom(skb) < frag_hdr_sz) && | 1341 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && |
1335 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 1342 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) |
1336 | goto out; | 1343 | goto out; |
1337 | 1344 | ||
@@ -1378,7 +1385,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1378 | { | 1385 | { |
1379 | struct inet_sock *inet = inet_sk(sp); | 1386 | struct inet_sock *inet = inet_sk(sp); |
1380 | struct ipv6_pinfo *np = inet6_sk(sp); | 1387 | struct ipv6_pinfo *np = inet6_sk(sp); |
1381 | struct in6_addr *dest, *src; | 1388 | const struct in6_addr *dest, *src; |
1382 | __u16 destp, srcp; | 1389 | __u16 destp, srcp; |
1383 | 1390 | ||
1384 | dest = &np->daddr; | 1391 | dest = &np->daddr; |
@@ -1387,7 +1394,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1387 | srcp = ntohs(inet->inet_sport); | 1394 | srcp = ntohs(inet->inet_sport); |
1388 | seq_printf(seq, | 1395 | seq_printf(seq, |
1389 | "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 1396 | "%5d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
1390 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", | 1397 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d\n", |
1391 | bucket, | 1398 | bucket, |
1392 | src->s6_addr32[0], src->s6_addr32[1], | 1399 | src->s6_addr32[0], src->s6_addr32[1], |
1393 | src->s6_addr32[2], src->s6_addr32[3], srcp, | 1400 | src->s6_addr32[2], src->s6_addr32[3], srcp, |
@@ -1469,6 +1476,7 @@ struct proto udpv6_prot = { | |||
1469 | .compat_setsockopt = compat_udpv6_setsockopt, | 1476 | .compat_setsockopt = compat_udpv6_setsockopt, |
1470 | .compat_getsockopt = compat_udpv6_getsockopt, | 1477 | .compat_getsockopt = compat_udpv6_getsockopt, |
1471 | #endif | 1478 | #endif |
1479 | .clear_sk = sk_prot_clear_portaddr_nulls, | ||
1472 | }; | 1480 | }; |
1473 | 1481 | ||
1474 | static struct inet_protosw udpv6_protosw = { | 1482 | static struct inet_protosw udpv6_protosw = { |