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.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9cbf363172bd..b444483cdb2b 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -102,7 +102,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
102 return udp_lib_get_port(sk, snum, hash2_nulladdr); 102 return udp_lib_get_port(sk, snum, hash2_nulladdr);
103} 103}
104 104
105static void udp_v6_rehash(struct sock *sk) 105void udp_v6_rehash(struct sock *sk)
106{ 106{
107 u16 new_hash = ipv6_portaddr_hash(sock_net(sk), 107 u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
108 &sk->sk_v6_rcv_saddr, 108 &sk->sk_v6_rcv_saddr,
@@ -288,8 +288,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
288 int peeked, peeking, off; 288 int peeked, peeking, off;
289 int err; 289 int err;
290 int is_udplite = IS_UDPLITE(sk); 290 int is_udplite = IS_UDPLITE(sk);
291 struct udp_mib __percpu *mib;
291 bool checksum_valid = false; 292 bool checksum_valid = false;
292 struct udp_mib *mib;
293 int is_udp4; 293 int is_udp4;
294 294
295 if (flags & MSG_ERRQUEUE) 295 if (flags & MSG_ERRQUEUE)
@@ -420,17 +420,19 @@ EXPORT_SYMBOL(udpv6_encap_enable);
420 */ 420 */
421static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb, 421static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
422 struct inet6_skb_parm *opt, 422 struct inet6_skb_parm *opt,
423 u8 type, u8 code, int offset, u32 info) 423 u8 type, u8 code, int offset, __be32 info)
424{ 424{
425 int i; 425 int i;
426 426
427 for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) { 427 for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
428 int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, 428 int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
429 u8 type, u8 code, int offset, u32 info); 429 u8 type, u8 code, int offset, __be32 info);
430 const struct ip6_tnl_encap_ops *encap;
430 431
431 if (!ip6tun_encaps[i]) 432 encap = rcu_dereference(ip6tun_encaps[i]);
433 if (!encap)
432 continue; 434 continue;
433 handler = rcu_dereference(ip6tun_encaps[i]->err_handler); 435 handler = encap->err_handler;
434 if (handler && !handler(skb, opt, type, code, offset, info)) 436 if (handler && !handler(skb, opt, type, code, offset, info))
435 return 0; 437 return 0;
436 } 438 }
@@ -1132,15 +1134,23 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
1132 const int hlen = skb_network_header_len(skb) + 1134 const int hlen = skb_network_header_len(skb) +
1133 sizeof(struct udphdr); 1135 sizeof(struct udphdr);
1134 1136
1135 if (hlen + cork->gso_size > cork->fragsize) 1137 if (hlen + cork->gso_size > cork->fragsize) {
1138 kfree_skb(skb);
1136 return -EINVAL; 1139 return -EINVAL;
1137 if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) 1140 }
1141 if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
1142 kfree_skb(skb);
1138 return -EINVAL; 1143 return -EINVAL;
1139 if (udp_sk(sk)->no_check6_tx) 1144 }
1145 if (udp_sk(sk)->no_check6_tx) {
1146 kfree_skb(skb);
1140 return -EINVAL; 1147 return -EINVAL;
1148 }
1141 if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite || 1149 if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
1142 dst_xfrm(skb_dst(skb))) 1150 dst_xfrm(skb_dst(skb))) {
1151 kfree_skb(skb);
1143 return -EIO; 1152 return -EIO;
1153 }
1144 1154
1145 skb_shinfo(skb)->gso_size = cork->gso_size; 1155 skb_shinfo(skb)->gso_size = cork->gso_size;
1146 skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4; 1156 skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1390,10 +1400,7 @@ do_udp_sendmsg:
1390 ipc6.opt = opt; 1400 ipc6.opt = opt;
1391 1401
1392 fl6.flowi6_proto = sk->sk_protocol; 1402 fl6.flowi6_proto = sk->sk_protocol;
1393 if (!ipv6_addr_any(daddr)) 1403 fl6.daddr = *daddr;
1394 fl6.daddr = *daddr;
1395 else
1396 fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
1397 if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) 1404 if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
1398 fl6.saddr = np->saddr; 1405 fl6.saddr = np->saddr;
1399 fl6.fl6_sport = inet->inet_sport; 1406 fl6.fl6_sport = inet->inet_sport;
@@ -1421,6 +1428,9 @@ do_udp_sendmsg:
1421 } 1428 }
1422 } 1429 }
1423 1430
1431 if (ipv6_addr_any(&fl6.daddr))
1432 fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
1433
1424 final_p = fl6_update_dst(&fl6, opt, &final); 1434 final_p = fl6_update_dst(&fl6, opt, &final);
1425 if (final_p) 1435 if (final_p)
1426 connected = false; 1436 connected = false;