| .. | .. |
|---|
| 54 | 54 | #include <trace/events/skb.h> |
|---|
| 55 | 55 | #include "udp_impl.h" |
|---|
| 56 | 56 | |
|---|
| 57 | +static void udpv6_destruct_sock(struct sock *sk) |
|---|
| 58 | +{ |
|---|
| 59 | + udp_destruct_common(sk); |
|---|
| 60 | + inet6_sock_destruct(sk); |
|---|
| 61 | +} |
|---|
| 62 | + |
|---|
| 63 | +int udpv6_init_sock(struct sock *sk) |
|---|
| 64 | +{ |
|---|
| 65 | + skb_queue_head_init(&udp_sk(sk)->reader_queue); |
|---|
| 66 | + sk->sk_destruct = udpv6_destruct_sock; |
|---|
| 67 | + return 0; |
|---|
| 68 | +} |
|---|
| 69 | + |
|---|
| 57 | 70 | static u32 udp6_ehashfn(const struct net *net, |
|---|
| 58 | 71 | const struct in6_addr *laddr, |
|---|
| 59 | 72 | const u16 lport, |
|---|
| .. | .. |
|---|
| 74 | 87 | fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret); |
|---|
| 75 | 88 | |
|---|
| 76 | 89 | return __inet6_ehashfn(lhash, lport, fhash, fport, |
|---|
| 77 | | - udp_ipv6_hash_secret + net_hash_mix(net)); |
|---|
| 90 | + udp6_ehash_secret + net_hash_mix(net)); |
|---|
| 78 | 91 | } |
|---|
| 79 | 92 | |
|---|
| 80 | 93 | int udp_v6_get_port(struct sock *sk, unsigned short snum) |
|---|
| .. | .. |
|---|
| 176 | 189 | score = compute_score(sk, net, saddr, sport, |
|---|
| 177 | 190 | daddr, hnum, dif, sdif); |
|---|
| 178 | 191 | if (score > badness) { |
|---|
| 179 | | - result = lookup_reuseport(net, sk, skb, |
|---|
| 180 | | - saddr, sport, daddr, hnum); |
|---|
| 192 | + badness = score; |
|---|
| 193 | + result = lookup_reuseport(net, sk, skb, saddr, sport, daddr, hnum); |
|---|
| 194 | + if (!result) { |
|---|
| 195 | + result = sk; |
|---|
| 196 | + continue; |
|---|
| 197 | + } |
|---|
| 198 | + |
|---|
| 181 | 199 | /* Fall back to scoring if group has connections */ |
|---|
| 182 | | - if (result && !reuseport_has_conns(sk)) |
|---|
| 200 | + if (!reuseport_has_conns(sk)) |
|---|
| 183 | 201 | return result; |
|---|
| 184 | 202 | |
|---|
| 185 | | - result = result ? : sk; |
|---|
| 186 | | - badness = score; |
|---|
| 203 | + /* Reuseport logic returned an error, keep original score. */ |
|---|
| 204 | + if (IS_ERR(result)) |
|---|
| 205 | + continue; |
|---|
| 206 | + |
|---|
| 207 | + badness = compute_score(sk, net, saddr, sport, |
|---|
| 208 | + daddr, hnum, dif, sdif); |
|---|
| 187 | 209 | } |
|---|
| 188 | 210 | } |
|---|
| 189 | 211 | return result; |
|---|
| .. | .. |
|---|
| 1340 | 1362 | msg->msg_name = &sin; |
|---|
| 1341 | 1363 | msg->msg_namelen = sizeof(sin); |
|---|
| 1342 | 1364 | do_udp_sendmsg: |
|---|
| 1343 | | - if (__ipv6_only_sock(sk)) |
|---|
| 1344 | | - return -ENETUNREACH; |
|---|
| 1345 | | - return udp_sendmsg(sk, msg, len); |
|---|
| 1365 | + err = __ipv6_only_sock(sk) ? |
|---|
| 1366 | + -ENETUNREACH : udp_sendmsg(sk, msg, len); |
|---|
| 1367 | + msg->msg_name = sin6; |
|---|
| 1368 | + msg->msg_namelen = addr_len; |
|---|
| 1369 | + return err; |
|---|
| 1346 | 1370 | } |
|---|
| 1347 | 1371 | } |
|---|
| 1348 | 1372 | |
|---|
| .. | .. |
|---|
| 1615 | 1639 | udp_encap_disable(); |
|---|
| 1616 | 1640 | } |
|---|
| 1617 | 1641 | } |
|---|
| 1618 | | - |
|---|
| 1619 | | - inet6_destroy_sock(sk); |
|---|
| 1620 | 1642 | } |
|---|
| 1621 | 1643 | |
|---|
| 1622 | 1644 | /* |
|---|
| .. | .. |
|---|
| 1700 | 1722 | .connect = ip6_datagram_connect, |
|---|
| 1701 | 1723 | .disconnect = udp_disconnect, |
|---|
| 1702 | 1724 | .ioctl = udp_ioctl, |
|---|
| 1703 | | - .init = udp_init_sock, |
|---|
| 1725 | + .init = udpv6_init_sock, |
|---|
| 1704 | 1726 | .destroy = udpv6_destroy_sock, |
|---|
| 1705 | 1727 | .setsockopt = udpv6_setsockopt, |
|---|
| 1706 | 1728 | .getsockopt = udpv6_getsockopt, |
|---|