diff options
Diffstat (limited to 'net/ipv6/udp.c')
| -rw-r--r-- | net/ipv6/udp.c | 38 |
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 | ||
| 105 | static void udp_v6_rehash(struct sock *sk) | 105 | void 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 | */ |
| 421 | static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb, | 421 | static 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; |
