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.c96
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
1302static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features) 1298static 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