diff options
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 96 |
1 files changed, 46 insertions, 50 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9a009c66c8a3..9e305d74b3d4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -505,6 +505,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
505 | int rc; | 505 | int rc; |
506 | int is_udplite = IS_UDPLITE(sk); | 506 | int is_udplite = IS_UDPLITE(sk); |
507 | 507 | ||
508 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | ||
509 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
510 | |||
508 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 511 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
509 | goto drop; | 512 | goto drop; |
510 | 513 | ||
@@ -886,7 +889,7 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
886 | struct udphdr *uh; | 889 | struct udphdr *uh; |
887 | struct udp_sock *up = udp_sk(sk); | 890 | struct udp_sock *up = udp_sk(sk); |
888 | struct inet_sock *inet = inet_sk(sk); | 891 | struct inet_sock *inet = inet_sk(sk); |
889 | struct flowi *fl = &inet->cork.fl; | 892 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
890 | int err = 0; | 893 | int err = 0; |
891 | int is_udplite = IS_UDPLITE(sk); | 894 | int is_udplite = IS_UDPLITE(sk); |
892 | __wsum csum = 0; | 895 | __wsum csum = 0; |
@@ -899,23 +902,23 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
899 | * Create a UDP header | 902 | * Create a UDP header |
900 | */ | 903 | */ |
901 | uh = udp_hdr(skb); | 904 | uh = udp_hdr(skb); |
902 | uh->source = fl->fl_ip_sport; | 905 | uh->source = fl6->fl6_sport; |
903 | uh->dest = fl->fl_ip_dport; | 906 | uh->dest = fl6->fl6_dport; |
904 | uh->len = htons(up->len); | 907 | uh->len = htons(up->len); |
905 | uh->check = 0; | 908 | uh->check = 0; |
906 | 909 | ||
907 | if (is_udplite) | 910 | if (is_udplite) |
908 | csum = udplite_csum_outgoing(sk, skb); | 911 | csum = udplite_csum_outgoing(sk, skb); |
909 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ | 912 | else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |
910 | udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst, | 913 | udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, |
911 | up->len); | 914 | up->len); |
912 | goto send; | 915 | goto send; |
913 | } else | 916 | } else |
914 | csum = udp_csum_outgoing(sk, skb); | 917 | csum = udp_csum_outgoing(sk, skb); |
915 | 918 | ||
916 | /* add protocol-dependent pseudo-header */ | 919 | /* add protocol-dependent pseudo-header */ |
917 | uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, | 920 | uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, |
918 | up->len, fl->proto, csum ); | 921 | up->len, fl6->flowi6_proto, csum); |
919 | if (uh->check == 0) | 922 | if (uh->check == 0) |
920 | uh->check = CSUM_MANGLED_0; | 923 | uh->check = CSUM_MANGLED_0; |
921 | 924 | ||
@@ -947,7 +950,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
947 | struct in6_addr *daddr, *final_p, final; | 950 | struct in6_addr *daddr, *final_p, final; |
948 | struct ipv6_txoptions *opt = NULL; | 951 | struct ipv6_txoptions *opt = NULL; |
949 | struct ip6_flowlabel *flowlabel = NULL; | 952 | struct ip6_flowlabel *flowlabel = NULL; |
950 | struct flowi fl; | 953 | struct flowi6 fl6; |
951 | struct dst_entry *dst; | 954 | struct dst_entry *dst; |
952 | int addr_len = msg->msg_namelen; | 955 | int addr_len = msg->msg_namelen; |
953 | int ulen = len; | 956 | int ulen = len; |
@@ -1030,19 +1033,19 @@ do_udp_sendmsg: | |||
1030 | } | 1033 | } |
1031 | ulen += sizeof(struct udphdr); | 1034 | ulen += sizeof(struct udphdr); |
1032 | 1035 | ||
1033 | memset(&fl, 0, sizeof(fl)); | 1036 | memset(&fl6, 0, sizeof(fl6)); |
1034 | 1037 | ||
1035 | if (sin6) { | 1038 | if (sin6) { |
1036 | if (sin6->sin6_port == 0) | 1039 | if (sin6->sin6_port == 0) |
1037 | return -EINVAL; | 1040 | return -EINVAL; |
1038 | 1041 | ||
1039 | fl.fl_ip_dport = sin6->sin6_port; | 1042 | fl6.fl6_dport = sin6->sin6_port; |
1040 | daddr = &sin6->sin6_addr; | 1043 | daddr = &sin6->sin6_addr; |
1041 | 1044 | ||
1042 | if (np->sndflow) { | 1045 | if (np->sndflow) { |
1043 | fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; | 1046 | fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; |
1044 | if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) { | 1047 | if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { |
1045 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1048 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1046 | if (flowlabel == NULL) | 1049 | if (flowlabel == NULL) |
1047 | return -EINVAL; | 1050 | return -EINVAL; |
1048 | daddr = &flowlabel->dst; | 1051 | daddr = &flowlabel->dst; |
@@ -1060,38 +1063,38 @@ do_udp_sendmsg: | |||
1060 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1063 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1061 | sin6->sin6_scope_id && | 1064 | sin6->sin6_scope_id && |
1062 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 1065 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) |
1063 | fl.oif = sin6->sin6_scope_id; | 1066 | fl6.flowi6_oif = sin6->sin6_scope_id; |
1064 | } else { | 1067 | } else { |
1065 | if (sk->sk_state != TCP_ESTABLISHED) | 1068 | if (sk->sk_state != TCP_ESTABLISHED) |
1066 | return -EDESTADDRREQ; | 1069 | return -EDESTADDRREQ; |
1067 | 1070 | ||
1068 | fl.fl_ip_dport = inet->inet_dport; | 1071 | fl6.fl6_dport = inet->inet_dport; |
1069 | daddr = &np->daddr; | 1072 | daddr = &np->daddr; |
1070 | fl.fl6_flowlabel = np->flow_label; | 1073 | fl6.flowlabel = np->flow_label; |
1071 | connected = 1; | 1074 | connected = 1; |
1072 | } | 1075 | } |
1073 | 1076 | ||
1074 | if (!fl.oif) | 1077 | if (!fl6.flowi6_oif) |
1075 | fl.oif = sk->sk_bound_dev_if; | 1078 | fl6.flowi6_oif = sk->sk_bound_dev_if; |
1076 | 1079 | ||
1077 | if (!fl.oif) | 1080 | if (!fl6.flowi6_oif) |
1078 | fl.oif = np->sticky_pktinfo.ipi6_ifindex; | 1081 | fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; |
1079 | 1082 | ||
1080 | fl.mark = sk->sk_mark; | 1083 | fl6.flowi6_mark = sk->sk_mark; |
1081 | 1084 | ||
1082 | if (msg->msg_controllen) { | 1085 | if (msg->msg_controllen) { |
1083 | opt = &opt_space; | 1086 | opt = &opt_space; |
1084 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1087 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
1085 | opt->tot_len = sizeof(*opt); | 1088 | opt->tot_len = sizeof(*opt); |
1086 | 1089 | ||
1087 | err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit, | 1090 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, |
1088 | &tclass, &dontfrag); | 1091 | &tclass, &dontfrag); |
1089 | if (err < 0) { | 1092 | if (err < 0) { |
1090 | fl6_sock_release(flowlabel); | 1093 | fl6_sock_release(flowlabel); |
1091 | return err; | 1094 | return err; |
1092 | } | 1095 | } |
1093 | if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { | 1096 | if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { |
1094 | flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel); | 1097 | flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
1095 | if (flowlabel == NULL) | 1098 | if (flowlabel == NULL) |
1096 | return -EINVAL; | 1099 | return -EINVAL; |
1097 | } | 1100 | } |
@@ -1105,42 +1108,35 @@ do_udp_sendmsg: | |||
1105 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 1108 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
1106 | opt = ipv6_fixup_options(&opt_space, opt); | 1109 | opt = ipv6_fixup_options(&opt_space, opt); |
1107 | 1110 | ||
1108 | fl.proto = sk->sk_protocol; | 1111 | fl6.flowi6_proto = sk->sk_protocol; |
1109 | if (!ipv6_addr_any(daddr)) | 1112 | if (!ipv6_addr_any(daddr)) |
1110 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 1113 | ipv6_addr_copy(&fl6.daddr, daddr); |
1111 | else | 1114 | else |
1112 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | 1115 | fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
1113 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 1116 | if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
1114 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 1117 | ipv6_addr_copy(&fl6.saddr, &np->saddr); |
1115 | fl.fl_ip_sport = inet->inet_sport; | 1118 | fl6.fl6_sport = inet->inet_sport; |
1116 | 1119 | ||
1117 | final_p = fl6_update_dst(&fl, opt, &final); | 1120 | final_p = fl6_update_dst(&fl6, opt, &final); |
1118 | if (final_p) | 1121 | if (final_p) |
1119 | connected = 0; | 1122 | connected = 0; |
1120 | 1123 | ||
1121 | if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) { | 1124 | if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { |
1122 | fl.oif = np->mcast_oif; | 1125 | fl6.flowi6_oif = np->mcast_oif; |
1123 | connected = 0; | 1126 | connected = 0; |
1124 | } | 1127 | } |
1125 | 1128 | ||
1126 | security_sk_classify_flow(sk, &fl); | 1129 | security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
1127 | 1130 | ||
1128 | err = ip6_sk_dst_lookup(sk, &dst, &fl); | 1131 | dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, true); |
1129 | if (err) | 1132 | if (IS_ERR(dst)) { |
1133 | err = PTR_ERR(dst); | ||
1134 | dst = NULL; | ||
1130 | goto out; | 1135 | goto out; |
1131 | if (final_p) | ||
1132 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
1133 | |||
1134 | err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT); | ||
1135 | if (err < 0) { | ||
1136 | if (err == -EREMOTE) | ||
1137 | err = ip6_dst_blackhole(sk, &dst, &fl); | ||
1138 | if (err < 0) | ||
1139 | goto out; | ||
1140 | } | 1136 | } |
1141 | 1137 | ||
1142 | if (hlimit < 0) { | 1138 | if (hlimit < 0) { |
1143 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 1139 | if (ipv6_addr_is_multicast(&fl6.daddr)) |
1144 | hlimit = np->mcast_hops; | 1140 | hlimit = np->mcast_hops; |
1145 | else | 1141 | else |
1146 | hlimit = np->hop_limit; | 1142 | hlimit = np->hop_limit; |
@@ -1175,7 +1171,7 @@ do_append_data: | |||
1175 | up->len += ulen; | 1171 | up->len += ulen; |
1176 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 1172 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1177 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1173 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, |
1178 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 1174 | sizeof(struct udphdr), hlimit, tclass, opt, &fl6, |
1179 | (struct rt6_info*)dst, | 1175 | (struct rt6_info*)dst, |
1180 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); | 1176 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
1181 | if (err) | 1177 | if (err) |
@@ -1188,10 +1184,10 @@ do_append_data: | |||
1188 | if (dst) { | 1184 | if (dst) { |
1189 | if (connected) { | 1185 | if (connected) { |
1190 | ip6_dst_store(sk, dst, | 1186 | ip6_dst_store(sk, dst, |
1191 | ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? | 1187 | ipv6_addr_equal(&fl6.daddr, &np->daddr) ? |
1192 | &np->daddr : NULL, | 1188 | &np->daddr : NULL, |
1193 | #ifdef CONFIG_IPV6_SUBTREES | 1189 | #ifdef CONFIG_IPV6_SUBTREES |
1194 | ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? | 1190 | ipv6_addr_equal(&fl6.saddr, &np->saddr) ? |
1195 | &np->saddr : | 1191 | &np->saddr : |
1196 | #endif | 1192 | #endif |
1197 | NULL); | 1193 | NULL); |
@@ -1299,7 +1295,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb) | |||
1299 | return 0; | 1295 | return 0; |
1300 | } | 1296 | } |
1301 | 1297 | ||
1302 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | 1298 | static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) |
1303 | { | 1299 | { |
1304 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1300 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
1305 | unsigned int mss; | 1301 | unsigned int mss; |
@@ -1339,7 +1335,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) | |||
1339 | skb->ip_summed = CHECKSUM_NONE; | 1335 | skb->ip_summed = CHECKSUM_NONE; |
1340 | 1336 | ||
1341 | /* Check if there is enough headroom to insert fragment header. */ | 1337 | /* Check if there is enough headroom to insert fragment header. */ |
1342 | if ((skb_headroom(skb) < frag_hdr_sz) && | 1338 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && |
1343 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 1339 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) |
1344 | goto out; | 1340 | goto out; |
1345 | 1341 | ||