Blame view
net/ipv6/udp.c
44.4 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 |
/* * UDP over IPv6 |
1ab1457c4 [NET] IPV6: Fix w... |
4 |
* Linux INET6 implementation |
1da177e4c Linux-2.6.12-rc2 |
5 6 |
* * Authors: |
1ab1457c4 [NET] IPV6: Fix w... |
7 |
* Pedro Roque <roque@di.fc.ul.pt> |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 |
* * Based on linux/ipv4/udp.c * |
1da177e4c Linux-2.6.12-rc2 |
11 12 13 14 15 16 17 |
* Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which * Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind * a single port at the same time. * Kazunori MIYAZAWA @USAGI: change process style to use ip6_append_data * YOSHIFUJI Hideaki @USAGI: convert /proc/net/udp6 to seq_file. |
1da177e4c Linux-2.6.12-rc2 |
18 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
19 20 21 22 |
#include <linux/errno.h> #include <linux/types.h> #include <linux/socket.h> #include <linux/sockios.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 27 28 29 |
#include <linux/net.h> #include <linux/in6.h> #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/ipv6.h> #include <linux/icmpv6.h> #include <linux/init.h> |
1781f7f58 [UDP]: Restore mi... |
30 |
#include <linux/module.h> |
3305b80c2 [IP]: Simplify an... |
31 |
#include <linux/skbuff.h> |
5a0e3ad6a include cleanup: ... |
32 |
#include <linux/slab.h> |
7c0f6ba68 Replace <asm/uacc... |
33 |
#include <linux/uaccess.h> |
0e219ae48 net: use indirect... |
34 |
#include <linux/indirect_call_wrapper.h> |
1da177e4c Linux-2.6.12-rc2 |
35 |
|
496611d7b inet: create IPv6... |
36 |
#include <net/addrconf.h> |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 |
#include <net/ndisc.h> #include <net/protocol.h> #include <net/transp_v6.h> #include <net/ip6_route.h> |
1da177e4c Linux-2.6.12-rc2 |
41 |
#include <net/raw.h> |
c752f0739 [TCP]: Move the t... |
42 |
#include <net/tcp_states.h> |
1da177e4c Linux-2.6.12-rc2 |
43 |
#include <net/ip6_checksum.h> |
e7cc08245 udp: Support for ... |
44 |
#include <net/ip6_tunnel.h> |
1da177e4c Linux-2.6.12-rc2 |
45 |
#include <net/xfrm.h> |
0bd84065b net: ipv6: Fix UD... |
46 |
#include <net/inet_hashtables.h> |
72289b96c soreuseport: UDP/... |
47 |
#include <net/inet6_hashtables.h> |
076bb0c82 net: rename inclu... |
48 |
#include <net/busy_poll.h> |
e32ea7e74 soreuseport: fast... |
49 |
#include <net/sock_reuseport.h> |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 |
#include <linux/proc_fs.h> #include <linux/seq_file.h> |
22911fc58 net: skb_free_dat... |
53 |
#include <trace/events/skb.h> |
ba4e58eca [NET]: Supporting... |
54 |
#include "udp_impl.h" |
1da177e4c Linux-2.6.12-rc2 |
55 |
|
6eada0110 netns: constify n... |
56 57 58 59 60 |
static u32 udp6_ehashfn(const struct net *net, const struct in6_addr *laddr, const u16 lport, const struct in6_addr *faddr, const __be16 fport) |
b50026b5a ipv6: split inet6... |
61 |
{ |
1bbdceef1 inet: convert ine... |
62 63 64 65 66 67 68 69 70 71 72 73 |
static u32 udp6_ehash_secret __read_mostly; static u32 udp_ipv6_hash_secret __read_mostly; u32 lhash, fhash; net_get_random_once(&udp6_ehash_secret, sizeof(udp6_ehash_secret)); net_get_random_once(&udp_ipv6_hash_secret, sizeof(udp_ipv6_hash_secret)); lhash = (__force u32)laddr->s6_addr32[3]; fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret); |
b50026b5a ipv6: split inet6... |
74 |
return __inet6_ehashfn(lhash, lport, fhash, fport, |
1bbdceef1 inet: convert ine... |
75 |
udp_ipv6_hash_secret + net_hash_mix(net)); |
b50026b5a ipv6: split inet6... |
76 |
} |
6ba5a3c52 [UDP]: Make full ... |
77 |
int udp_v6_get_port(struct sock *sk, unsigned short snum) |
1da177e4c Linux-2.6.12-rc2 |
78 |
{ |
30fff9231 udp: bind() optim... |
79 |
unsigned int hash2_nulladdr = |
f0b1e64c1 udp: Move udp[46]... |
80 |
ipv6_portaddr_hash(sock_net(sk), &in6addr_any, snum); |
9a52e97e2 net:ipv6:fixed a ... |
81 |
unsigned int hash2_partial = |
f0b1e64c1 udp: Move udp[46]... |
82 |
ipv6_portaddr_hash(sock_net(sk), &sk->sk_v6_rcv_saddr, 0); |
30fff9231 udp: bind() optim... |
83 |
|
d4cada4ae udp: split sk_has... |
84 |
/* precompute partial secondary hash */ |
30fff9231 udp: bind() optim... |
85 |
udp_sk(sk)->udp_portaddr_hash = hash2_partial; |
fe38d2a1c inet: collapse ip... |
86 |
return udp_lib_get_port(sk, snum, hash2_nulladdr); |
1da177e4c Linux-2.6.12-rc2 |
87 |
} |
f7c46156f udp6: add missing... |
88 |
void udp_v6_rehash(struct sock *sk) |
719f83585 udp: add rehash o... |
89 |
{ |
f0b1e64c1 udp: Move udp[46]... |
90 |
u16 new_hash = ipv6_portaddr_hash(sock_net(sk), |
efe4208f4 ipv6: make lookup... |
91 |
&sk->sk_v6_rcv_saddr, |
719f83585 udp: add rehash o... |
92 93 94 95 |
inet_sk(sk)->inet_num); udp_lib_rehash(sk, new_hash); } |
d1e37288c udp reuseport: fi... |
96 97 98 |
static int compute_score(struct sock *sk, struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, unsigned short hnum, |
735453730 udp: Remove unuse... |
99 |
int dif, int sdif) |
645ca708f udp: introduce st... |
100 |
{ |
60c04aecd udp: Neaten and r... |
101 102 |
int score; struct inet_sock *inet; |
6da5b0f02 net: ensure unbou... |
103 |
bool dev_match; |
60c04aecd udp: Neaten and r... |
104 105 106 107 108 |
if (!net_eq(sock_net(sk), net) || udp_sk(sk)->udp_port_hash != hnum || sk->sk_family != PF_INET6) return -1; |
23b0269e5 net: udp6: prefer... |
109 110 |
if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) return -1; |
60c04aecd udp: Neaten and r... |
111 112 113 114 115 116 117 118 |
score = 0; inet = inet_sk(sk); if (inet->inet_dport) { if (inet->inet_dport != sport) return -1; score++; } |
60c04aecd udp: Neaten and r... |
119 120 121 122 123 |
if (!ipv6_addr_any(&sk->sk_v6_daddr)) { if (!ipv6_addr_equal(&sk->sk_v6_daddr, saddr)) return -1; score++; } |
6da5b0f02 net: ensure unbou... |
124 125 126 127 |
dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif); if (!dev_match) return -1; score++; |
60c04aecd udp: Neaten and r... |
128 |
|
7170a9777 net: annotate acc... |
129 |
if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
70da268b5 net: SO_INCOMING_... |
130 |
score++; |
645ca708f udp: introduce st... |
131 132 |
return score; } |
a57066b1a Merge git://git.k... |
133 134 135 136 137 138 |
static struct sock *lookup_reuseport(struct net *net, struct sock *sk, struct sk_buff *skb, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, unsigned int hnum) |
2a08748cd udp6: Extract hel... |
139 140 141 142 143 144 145 146 |
{ struct sock *reuse_sk = NULL; u32 hash; if (sk->sk_reuseport && sk->sk_state != TCP_ESTABLISHED) { hash = udp6_ehashfn(net, daddr, hnum, saddr, sport); reuse_sk = reuseport_select_sock(sk, hash, skb, sizeof(struct udphdr)); |
2a08748cd udp6: Extract hel... |
147 148 149 |
} return reuse_sk; } |
d1e37288c udp reuseport: fi... |
150 |
/* called with rcu_read_lock() */ |
fddc17def ipv6: udp: optimi... |
151 152 |
static struct sock *udp6_lib_lookup2(struct net *net, const struct in6_addr *saddr, __be16 sport, |
1801b570d net: ipv6: add se... |
153 |
const struct in6_addr *daddr, unsigned int hnum, |
735453730 udp: Remove unuse... |
154 155 |
int dif, int sdif, struct udp_hslot *hslot2, struct sk_buff *skb) |
fddc17def ipv6: udp: optimi... |
156 157 |
{ struct sock *sk, *result; |
e94a62f50 net/reuseport: dr... |
158 |
int score, badness; |
fddc17def ipv6: udp: optimi... |
159 |
|
fddc17def ipv6: udp: optimi... |
160 161 |
result = NULL; badness = -1; |
ca065d0cf udp: no longer us... |
162 |
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { |
d1e37288c udp reuseport: fi... |
163 |
score = compute_score(sk, net, saddr, sport, |
735453730 udp: Remove unuse... |
164 |
daddr, hnum, dif, sdif); |
fddc17def ipv6: udp: optimi... |
165 |
if (score > badness) { |
2a08748cd udp6: Extract hel... |
166 167 |
result = lookup_reuseport(net, sk, skb, saddr, sport, daddr, hnum); |
a57066b1a Merge git://git.k... |
168 169 |
/* Fall back to scoring if group has connections */ if (result && !reuseport_has_conns(sk, false)) |
2a08748cd udp6: Extract hel... |
170 |
return result; |
a57066b1a Merge git://git.k... |
171 |
result = result ? : sk; |
ca065d0cf udp: no longer us... |
172 |
badness = score; |
fddc17def ipv6: udp: optimi... |
173 174 |
} } |
fddc17def ipv6: udp: optimi... |
175 176 |
return result; } |
6d4201b13 udp6: Run SK_LOOK... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
static inline struct sock *udp6_lookup_run_bpf(struct net *net, struct udp_table *udptable, struct sk_buff *skb, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, u16 hnum) { struct sock *sk, *reuse_sk; bool no_reuseport; if (udptable != &udp_table) return NULL; /* only UDP is supported */ no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP, saddr, sport, daddr, hnum, &sk); if (no_reuseport || IS_ERR_OR_NULL(sk)) return sk; reuse_sk = lookup_reuseport(net, sk, skb, saddr, sport, daddr, hnum); |
c64c9c282 udp, bpf: Ignore ... |
197 |
if (reuse_sk) |
6d4201b13 udp6: Run SK_LOOK... |
198 199 200 |
sk = reuse_sk; return sk; } |
ca065d0cf udp: no longer us... |
201 |
/* rcu_read_lock() must be held */ |
fce823381 udp: Export code ... |
202 |
struct sock *__udp6_lib_lookup(struct net *net, |
1801b570d net: ipv6: add se... |
203 204 205 206 |
const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif, int sdif, struct udp_table *udptable, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
207 |
{ |
1da177e4c Linux-2.6.12-rc2 |
208 |
unsigned short hnum = ntohs(dport); |
23b0269e5 net: udp6: prefer... |
209 210 |
unsigned int hash2, slot2; struct udp_hslot *hslot2; |
6d4201b13 udp6: Run SK_LOOK... |
211 |
struct sock *result, *sk; |
645ca708f udp: introduce st... |
212 |
|
23b0269e5 net: udp6: prefer... |
213 214 215 |
hash2 = ipv6_portaddr_hash(net, daddr, hnum); slot2 = hash2 & udptable->mask; hslot2 = &udptable->hash2[slot2]; |
6d4201b13 udp6: Run SK_LOOK... |
216 |
/* Lookup connected or non-wildcard sockets */ |
23b0269e5 net: udp6: prefer... |
217 |
result = udp6_lib_lookup2(net, saddr, sport, |
735453730 udp: Remove unuse... |
218 |
daddr, hnum, dif, sdif, |
23b0269e5 net: udp6: prefer... |
219 |
hslot2, skb); |
6d4201b13 udp6: Run SK_LOOK... |
220 221 222 223 224 225 226 227 228 229 230 231 |
if (!IS_ERR_OR_NULL(result) && result->sk_state == TCP_ESTABLISHED) goto done; /* Lookup redirect from BPF */ if (static_branch_unlikely(&bpf_sk_lookup_enabled)) { sk = udp6_lookup_run_bpf(net, udptable, skb, saddr, sport, daddr, hnum); if (sk) { result = sk; goto done; } } |
23b0269e5 net: udp6: prefer... |
232 |
|
6d4201b13 udp6: Run SK_LOOK... |
233 234 235 |
/* Got non-wildcard socket or error on first lookup */ if (result) goto done; |
fddc17def ipv6: udp: optimi... |
236 |
|
6d4201b13 udp6: Run SK_LOOK... |
237 238 239 240 241 242 243 244 245 |
/* Lookup wildcard sockets */ hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum); slot2 = hash2 & udptable->mask; hslot2 = &udptable->hash2[slot2]; result = udp6_lib_lookup2(net, saddr, sport, &in6addr_any, hnum, dif, sdif, hslot2, skb); done: |
26f8113cc net: ipv6: drop u... |
246 |
if (IS_ERR(result)) |
23b0269e5 net: udp6: prefer... |
247 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
248 249 |
return result; } |
fce823381 udp: Export code ... |
250 |
EXPORT_SYMBOL_GPL(__udp6_lib_lookup); |
1da177e4c Linux-2.6.12-rc2 |
251 |
|
607c4aaf0 inet: Add udplib_... |
252 253 |
static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport, |
645ca708f udp: introduce st... |
254 |
struct udp_table *udptable) |
607c4aaf0 inet: Add udplib_... |
255 |
{ |
b71d1d426 inet: constify ip... |
256 |
const struct ipv6hdr *iph = ipv6_hdr(skb); |
607c4aaf0 inet: Add udplib_... |
257 |
|
ed7cbbce5 udp: Resolve NULL... |
258 |
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport, |
adf30907d net: skb->dst acc... |
259 |
&iph->daddr, dport, inet6_iif(skb), |
1801b570d net: ipv6: add se... |
260 |
inet6_sdif(skb), udptable, skb); |
607c4aaf0 inet: Add udplib_... |
261 |
} |
63058308c udp: Add udp6_lib... |
262 263 264 265 |
struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport) { const struct ipv6hdr *iph = ipv6_hdr(skb); |
63058308c udp: Add udp6_lib... |
266 |
|
ed7cbbce5 udp: Resolve NULL... |
267 |
return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport, |
63058308c udp: Add udp6_lib... |
268 |
&iph->daddr, dport, inet6_iif(skb), |
257a525fe bpf: udp: Avoid c... |
269 |
inet6_sdif(skb), &udp_table, NULL); |
63058308c udp: Add udp6_lib... |
270 271 |
} EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb); |
ca065d0cf udp: no longer us... |
272 273 274 |
/* Must be called under rcu_read_lock(). * Does increment socket refcount. */ |
6e86000c2 netfilter: provid... |
275 |
#if IS_ENABLED(CONFIG_NF_TPROXY_IPV6) || IS_ENABLED(CONFIG_NF_SOCKET_IPV6) |
aa976fc01 tproxy: added udp... |
276 277 278 |
struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif) { |
ca065d0cf udp: no longer us... |
279 280 281 |
struct sock *sk; sk = __udp6_lib_lookup(net, saddr, sport, daddr, dport, |
1801b570d net: ipv6: add se... |
282 |
dif, 0, &udp_table, NULL); |
41c6d650f net: convert sock... |
283 |
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) |
ca065d0cf udp: no longer us... |
284 285 |
sk = NULL; return sk; |
aa976fc01 tproxy: added udp... |
286 287 |
} EXPORT_SYMBOL_GPL(udp6_lib_lookup); |
ca065d0cf udp: no longer us... |
288 |
#endif |
aa976fc01 tproxy: added udp... |
289 |
|
cb891fa6a udp6: fix jumbogr... |
290 291 292 293 294 295 296 297 |
/* do not use the scratch area len for jumbogram: their length execeeds the * scratch area space; note that the IP6CB flags is still in the first * cacheline, so checking for jumbograms is cheap */ static int udp6_skb_len(struct sk_buff *skb) { return unlikely(inet6_is_jumbogram(skb)) ? skb->len : udp_skb_len(skb); } |
1da177e4c Linux-2.6.12-rc2 |
298 |
/* |
67ba4152e ipv6: White-space... |
299 300 |
* This should be easy, if there is something there we * return it, otherwise we block. |
1da177e4c Linux-2.6.12-rc2 |
301 |
*/ |
1b7841404 net: Remove iocb ... |
302 |
int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, |
1da177e4c Linux-2.6.12-rc2 |
303 304 305 306 |
int noblock, int flags, int *addr_len) { struct ipv6_pinfo *np = inet6_sk(sk); struct inet_sock *inet = inet_sk(sk); |
1ab1457c4 [NET] IPV6: Fix w... |
307 |
struct sk_buff *skb; |
59c2cdae2 Revert "udp: remo... |
308 |
unsigned int ulen, copied; |
fd69c399c datagram: remove ... |
309 |
int off, err, peeking = flags & MSG_PEEK; |
759e5d006 [UDP]: Clean up U... |
310 |
int is_udplite = IS_UDPLITE(sk); |
543fc3fb4 udpv6: add the re... |
311 |
struct udp_mib __percpu *mib; |
197c949e7 udp: properly sup... |
312 |
bool checksum_valid = false; |
f26ba1751 udp: Fix the SNMP... |
313 |
int is_udp4; |
1da177e4c Linux-2.6.12-rc2 |
314 |
|
1da177e4c Linux-2.6.12-rc2 |
315 |
if (flags & MSG_ERRQUEUE) |
85fbaa750 inet: fix addr_le... |
316 |
return ipv6_recv_error(sk, msg, len, addr_len); |
1da177e4c Linux-2.6.12-rc2 |
317 |
|
4b340ae20 IPv6: Complete IP... |
318 |
if (np->rxpmtu && np->rxopt.bits.rxpmtu) |
85fbaa750 inet: fix addr_le... |
319 |
return ipv6_recv_rxpmtu(sk, msg, len, addr_len); |
4b340ae20 IPv6: Complete IP... |
320 |
|
1da177e4c Linux-2.6.12-rc2 |
321 |
try_again: |
a0917e0bc datagram: When pe... |
322 |
off = sk_peek_offset(sk, flags); |
fd69c399c datagram: remove ... |
323 |
skb = __skb_recv_udp(sk, flags, noblock, &off, &err); |
1da177e4c Linux-2.6.12-rc2 |
324 |
if (!skb) |
627d2d6b5 udp: enable MSG_P... |
325 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
326 |
|
cb891fa6a udp6: fix jumbogr... |
327 |
ulen = udp6_skb_len(skb); |
59c2cdae2 Revert "udp: remo... |
328 |
copied = len; |
627d2d6b5 udp: enable MSG_P... |
329 330 |
if (copied > ulen - off) copied = ulen - off; |
59c2cdae2 Revert "udp: remo... |
331 |
else if (copied < ulen) |
1ab1457c4 [NET] IPV6: Fix w... |
332 |
msg->msg_flags |= MSG_TRUNC; |
1da177e4c Linux-2.6.12-rc2 |
333 |
|
f26ba1751 udp: Fix the SNMP... |
334 |
is_udp4 = (skb->protocol == htons(ETH_P_IP)); |
029a37434 udp6: cleanup sta... |
335 |
mib = __UDPX_MIB(sk, is_udp4); |
f26ba1751 udp: Fix the SNMP... |
336 |
|
ba4e58eca [NET]: Supporting... |
337 |
/* |
759e5d006 [UDP]: Clean up U... |
338 339 340 |
* If checksum is needed at all, try to do it while copying the * data. If the data is truncated, or if we only want a partial * coverage checksum (UDP-Lite), do it before the copy. |
ba4e58eca [NET]: Supporting... |
341 |
*/ |
ba4e58eca [NET]: Supporting... |
342 |
|
d21dbdfe0 udp: avoid one ca... |
343 344 |
if (copied < ulen || peeking || (is_udplite && UDP_SKB_CB(skb)->partial_cov)) { |
67a51780a ipv6: udp: levera... |
345 346 |
checksum_valid = udp_skb_csum_unnecessary(skb) || !__udp_lib_checksum_complete(skb); |
197c949e7 udp: properly sup... |
347 |
if (!checksum_valid) |
1da177e4c Linux-2.6.12-rc2 |
348 |
goto csum_copy_err; |
ba4e58eca [NET]: Supporting... |
349 |
} |
67a51780a ipv6: udp: levera... |
350 351 352 353 354 355 |
if (checksum_valid || udp_skb_csum_unnecessary(skb)) { if (udp_skb_is_linear(skb)) err = copy_linear_skb(skb, copied, off, &msg->msg_iter); else err = skb_copy_datagram_msg(skb, off, msg, copied); } else { |
627d2d6b5 udp: enable MSG_P... |
356 |
err = skb_copy_and_csum_datagram_msg(skb, off, msg); |
1da177e4c Linux-2.6.12-rc2 |
357 358 359 |
if (err == -EINVAL) goto csum_copy_err; } |
22911fc58 net: skb_free_dat... |
360 |
if (unlikely(err)) { |
fd69c399c datagram: remove ... |
361 |
if (!peeking) { |
979402b16 udp: increment UD... |
362 |
atomic_inc(&sk->sk_drops); |
029a37434 udp6: cleanup sta... |
363 |
SNMP_INC_STATS(mib, UDP_MIB_INERRORS); |
979402b16 udp: increment UD... |
364 |
} |
850cbaddb udp: use it's own... |
365 |
kfree_skb(skb); |
627d2d6b5 udp: enable MSG_P... |
366 |
return err; |
22911fc58 net: skb_free_dat... |
367 |
} |
fd69c399c datagram: remove ... |
368 |
if (!peeking) |
029a37434 udp6: cleanup sta... |
369 |
SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS); |
cb75994ec [UDP]: Defer InDa... |
370 |
|
3b885787e net: Generalize s... |
371 |
sock_recv_ts_and_drops(msg, sk, skb); |
1da177e4c Linux-2.6.12-rc2 |
372 373 374 |
/* Copy the address. */ if (msg->msg_name) { |
342dfc306 net: add build-ti... |
375 |
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
1da177e4c Linux-2.6.12-rc2 |
376 |
sin6->sin6_family = AF_INET6; |
4bedb4520 [SK_BUFF]: Introd... |
377 |
sin6->sin6_port = udp_hdr(skb)->source; |
1da177e4c Linux-2.6.12-rc2 |
378 |
sin6->sin6_flowinfo = 0; |
1da177e4c Linux-2.6.12-rc2 |
379 |
|
842df0739 ipv6: use newly i... |
380 |
if (is_udp4) { |
b301e82cf IPv6: use ipv6_ad... |
381 382 |
ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, &sin6->sin6_addr); |
842df0739 ipv6: use newly i... |
383 384 |
sin6->sin6_scope_id = 0; } else { |
4e3fd7a06 net: remove ipv6_... |
385 |
sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
842df0739 ipv6: use newly i... |
386 387 |
sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, |
4330487ac net: use inet6_ii... |
388 |
inet6_iif(skb)); |
1da177e4c Linux-2.6.12-rc2 |
389 |
} |
bceaa9024 inet: prevent lea... |
390 |
*addr_len = sizeof(*sin6); |
983695fa6 bpf: fix unconnec... |
391 392 393 394 |
if (cgroup_bpf_enabled) BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk, (struct sockaddr *)sin6); |
1da177e4c Linux-2.6.12-rc2 |
395 |
} |
4b261c75a ipv6: make IPV6_R... |
396 |
|
bcd1665e3 udp: add support ... |
397 398 |
if (udp_sk(sk)->gro_enabled) udp_cmsg_recv(msg, sk, skb); |
4b261c75a ipv6: make IPV6_R... |
399 400 |
if (np->rxopt.all) ip6_datagram_recv_common_ctl(sk, msg, skb); |
f26ba1751 udp: Fix the SNMP... |
401 |
if (is_udp4) { |
1da177e4c Linux-2.6.12-rc2 |
402 |
if (inet->cmsg_flags) |
ad959036a net/sock: add an ... |
403 |
ip_cmsg_recv_offset(msg, sk, skb, |
10df8e615 udp: fix IP_CHECK... |
404 |
sizeof(struct udphdr), off); |
1da177e4c Linux-2.6.12-rc2 |
405 406 |
} else { if (np->rxopt.all) |
4b261c75a ipv6: make IPV6_R... |
407 |
ip6_datagram_recv_specific_ctl(sk, msg, skb); |
1ab1457c4 [NET] IPV6: Fix w... |
408 |
} |
1da177e4c Linux-2.6.12-rc2 |
409 |
|
59c2cdae2 Revert "udp: remo... |
410 |
err = copied; |
1da177e4c Linux-2.6.12-rc2 |
411 |
if (flags & MSG_TRUNC) |
759e5d006 [UDP]: Clean up U... |
412 |
err = ulen; |
1da177e4c Linux-2.6.12-rc2 |
413 |
|
850cbaddb udp: use it's own... |
414 |
skb_consume_udp(sk, skb, peeking ? -err : err); |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 |
return err; csum_copy_err: |
2276f58ac udp: use a separa... |
418 419 |
if (!__sk_queue_drop_skb(sk, &udp_sk(sk)->reader_queue, skb, flags, udp_skb_destructor)) { |
029a37434 udp6: cleanup sta... |
420 421 |
SNMP_INC_STATS(mib, UDP_MIB_CSUMERRORS); SNMP_INC_STATS(mib, UDP_MIB_INERRORS); |
0856f9395 udp: Fix the SNMP... |
422 |
} |
850cbaddb udp: use it's own... |
423 |
kfree_skb(skb); |
1da177e4c Linux-2.6.12-rc2 |
424 |
|
beb39db59 udp: fix behavior... |
425 426 |
/* starting over for a new packet, but check if we need to yield */ cond_resched(); |
9cfaa8def udp/recvmsg: Clea... |
427 |
msg->msg_flags &= ~MSG_TRUNC; |
1da177e4c Linux-2.6.12-rc2 |
428 429 |
goto try_again; } |
a36e185e8 udp: Handle ICMP ... |
430 431 432 |
DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key); void udpv6_encap_enable(void) { |
9c4806014 udp: fix jump lab... |
433 |
static_branch_inc(&udpv6_encap_needed_key); |
a36e185e8 udp: Handle ICMP ... |
434 435 |
} EXPORT_SYMBOL(udpv6_encap_enable); |
e7cc08245 udp: Support for ... |
436 437 438 439 440 |
/* Handler for tunnels with arbitrary destination ports: no socket lookup, go * through error handlers in encapsulations looking for a match. */ static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb, struct inet6_skb_parm *opt, |
424a7cd07 udpv6: fix possib... |
441 |
u8 type, u8 code, int offset, __be32 info) |
e7cc08245 udp: Support for ... |
442 443 444 445 446 |
{ int i; for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) { int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, |
424a7cd07 udpv6: fix possib... |
447 448 |
u8 type, u8 code, int offset, __be32 info); const struct ip6_tnl_encap_ops *encap; |
e7cc08245 udp: Support for ... |
449 |
|
424a7cd07 udpv6: fix possib... |
450 451 |
encap = rcu_dereference(ip6tun_encaps[i]); if (!encap) |
e7cc08245 udp: Support for ... |
452 |
continue; |
424a7cd07 udpv6: fix possib... |
453 |
handler = encap->err_handler; |
e7cc08245 udp: Support for ... |
454 455 456 457 458 459 |
if (handler && !handler(skb, opt, type, code, offset, info)) return 0; } return -ENOENT; } |
a36e185e8 udp: Handle ICMP ... |
460 461 462 463 464 465 466 |
/* Try to match ICMP errors to UDP tunnels by looking up a socket without * reversing source and destination port: this will match tunnels that force the * same destination port on both endpoints (e.g. VXLAN, GENEVE). Note that * lwtunnels might actually break this assumption by being configured with * different destination ports on endpoints, in this case we won't be able to * trace ICMP messages back to them. * |
e7cc08245 udp: Support for ... |
467 468 469 470 |
* If this doesn't match any socket, probe tunnels with arbitrary destination * ports (e.g. FoU, GUE): there, the receiving socket is useless, as the port * we've sent packets to won't necessarily match the local destination port. * |
a36e185e8 udp: Handle ICMP ... |
471 472 473 |
* Then ask the tunnel implementation to match the error against a valid * association. * |
e7cc08245 udp: Support for ... |
474 475 |
* Return an error if we can't find a match, the socket if we need further * processing, zero otherwise. |
a36e185e8 udp: Handle ICMP ... |
476 477 478 479 480 |
*/ static struct sock *__udp6_lib_err_encap(struct net *net, const struct ipv6hdr *hdr, int offset, struct udphdr *uh, struct udp_table *udptable, |
e7cc08245 udp: Support for ... |
481 482 483 |
struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, __be32 info) |
a36e185e8 udp: Handle ICMP ... |
484 |
{ |
a36e185e8 udp: Handle ICMP ... |
485 |
int network_offset, transport_offset; |
a36e185e8 udp: Handle ICMP ... |
486 |
struct sock *sk; |
a36e185e8 udp: Handle ICMP ... |
487 488 489 490 491 492 493 494 |
network_offset = skb_network_offset(skb); transport_offset = skb_transport_offset(skb); /* Network header needs to point to the outer IPv6 header inside ICMP */ skb_reset_network_header(skb); /* Transport header needs to point to the UDP header */ skb_set_transport_header(skb, offset); |
e7cc08245 udp: Support for ... |
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
sk = __udp6_lib_lookup(net, &hdr->daddr, uh->source, &hdr->saddr, uh->dest, inet6_iif(skb), 0, udptable, skb); if (sk) { int (*lookup)(struct sock *sk, struct sk_buff *skb); struct udp_sock *up = udp_sk(sk); lookup = READ_ONCE(up->encap_err_lookup); if (!lookup || lookup(sk, skb)) sk = NULL; } if (!sk) { sk = ERR_PTR(__udp6_lib_err_encap_no_sk(skb, opt, type, code, offset, info)); } |
a36e185e8 udp: Handle ICMP ... |
511 512 513 |
skb_set_transport_header(skb, transport_offset); skb_set_network_header(skb, network_offset); |
e7cc08245 udp: Support for ... |
514 |
|
a36e185e8 udp: Handle ICMP ... |
515 516 |
return sk; } |
32bbd8793 net: Convert prot... |
517 518 519 |
int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info, struct udp_table *udptable) |
1da177e4c Linux-2.6.12-rc2 |
520 521 |
{ struct ipv6_pinfo *np; |
b71d1d426 inet: constify ip... |
522 523 524 |
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; const struct in6_addr *saddr = &hdr->saddr; const struct in6_addr *daddr = &hdr->daddr; |
67ba4152e ipv6: White-space... |
525 |
struct udphdr *uh = (struct udphdr *)(skb->data+offset); |
a36e185e8 udp: Handle ICMP ... |
526 |
bool tunnel = false; |
1da177e4c Linux-2.6.12-rc2 |
527 |
struct sock *sk; |
e0d8c1b73 ipv6: pass up EMS... |
528 |
int harderr; |
1da177e4c Linux-2.6.12-rc2 |
529 |
int err; |
7304fe468 net: fix the coun... |
530 |
struct net *net = dev_net(skb->dev); |
1da177e4c Linux-2.6.12-rc2 |
531 |
|
e32ea7e74 soreuseport: fast... |
532 |
sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, |
4ac30c4b3 bpf: udp: ipv6: A... |
533 |
inet6_iif(skb), inet6_sdif(skb), udptable, NULL); |
63159f29b ipv6: coding styl... |
534 |
if (!sk) { |
a36e185e8 udp: Handle ICMP ... |
535 |
/* No socket for error: try tunnels before discarding */ |
e7cc08245 udp: Support for ... |
536 |
sk = ERR_PTR(-ENOENT); |
a36e185e8 udp: Handle ICMP ... |
537 538 |
if (static_branch_unlikely(&udpv6_encap_needed_key)) { sk = __udp6_lib_err_encap(net, hdr, offset, uh, |
e7cc08245 udp: Support for ... |
539 540 541 542 |
udptable, skb, opt, type, code, info); if (!sk) return 0; |
a36e185e8 udp: Handle ICMP ... |
543 |
} |
e7cc08245 udp: Support for ... |
544 |
if (IS_ERR(sk)) { |
a36e185e8 udp: Handle ICMP ... |
545 546 |
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); |
e7cc08245 udp: Support for ... |
547 |
return PTR_ERR(sk); |
a36e185e8 udp: Handle ICMP ... |
548 |
} |
e7cc08245 udp: Support for ... |
549 |
|
a36e185e8 udp: Handle ICMP ... |
550 |
tunnel = true; |
7304fe468 net: fix the coun... |
551 |
} |
1da177e4c Linux-2.6.12-rc2 |
552 |
|
e0d8c1b73 ipv6: pass up EMS... |
553 554 |
harderr = icmpv6_err_convert(type, code, &err); np = inet6_sk(sk); |
93b36cf34 ipv6: support IPV... |
555 556 557 |
if (type == ICMPV6_PKT_TOOBIG) { if (!ip6_sk_accept_pmtu(sk)) goto out; |
81aded246 ipv6: Handle PMTU... |
558 |
ip6_sk_update_pmtu(skb, sk, info); |
e0d8c1b73 ipv6: pass up EMS... |
559 560 |
if (np->pmtudisc != IPV6_PMTUDISC_DONT) harderr = 1; |
93b36cf34 ipv6: support IPV... |
561 |
} |
1a462d189 net: udp: do not ... |
562 |
if (type == NDISC_REDIRECT) { |
a36e185e8 udp: Handle ICMP ... |
563 564 565 566 567 568 |
if (tunnel) { ip6_redirect(skb, sock_net(sk), inet6_iif(skb), sk->sk_mark, sk->sk_uid); } else { ip6_sk_redirect(skb, sk); } |
1a462d189 net: udp: do not ... |
569 570 |
goto out; } |
81aded246 ipv6: Handle PMTU... |
571 |
|
a36e185e8 udp: Handle ICMP ... |
572 573 574 |
/* Tunnels don't have an application socket: don't pass errors back */ if (tunnel) goto out; |
e0d8c1b73 ipv6: pass up EMS... |
575 576 577 578 |
if (!np->recverr) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; } else { |
1da177e4c Linux-2.6.12-rc2 |
579 |
ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1)); |
e0d8c1b73 ipv6: pass up EMS... |
580 |
} |
b1faf5666 net: sock_queue_e... |
581 |
|
1da177e4c Linux-2.6.12-rc2 |
582 583 584 |
sk->sk_err = err; sk->sk_error_report(sk); out: |
32bbd8793 net: Convert prot... |
585 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
586 |
} |
a3f96c47c udp: make *udp*_q... |
587 |
static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
f7ad74fef net/ipv6/udp: UDP... |
588 589 |
{ int rc; |
efe4208f4 ipv6: make lookup... |
590 |
if (!ipv6_addr_any(&sk->sk_v6_daddr)) { |
f7ad74fef net/ipv6/udp: UDP... |
591 |
sock_rps_save_rxhash(sk, skb); |
005ec9743 udp: Only allow b... |
592 |
sk_mark_napi_id(sk, skb); |
2c8c56e15 net: introduce SO... |
593 |
sk_incoming_cpu_update(sk); |
e68b6e50f udp: enable busy ... |
594 595 |
} else { sk_mark_napi_id_once(sk, skb); |
005ec9743 udp: Only allow b... |
596 |
} |
f7ad74fef net/ipv6/udp: UDP... |
597 |
|
850cbaddb udp: use it's own... |
598 |
rc = __udp_enqueue_schedule_skb(sk, skb); |
f7ad74fef net/ipv6/udp: UDP... |
599 600 601 602 603 |
if (rc < 0) { int is_udplite = IS_UDPLITE(sk); /* Note that an ENOMEM error is charged twice */ if (rc == -ENOMEM) |
e61da9e25 udp: prepare for ... |
604 |
UDP6_INC_STATS(sock_net(sk), |
02c223470 net: udp: rename ... |
605 |
UDP_MIB_RCVBUFERRORS, is_udplite); |
e61da9e25 udp: prepare for ... |
606 |
UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
f7ad74fef net/ipv6/udp: UDP... |
607 608 609 |
kfree_skb(skb); return -1; } |
850cbaddb udp: use it's own... |
610 |
|
f7ad74fef net/ipv6/udp: UDP... |
611 612 |
return 0; } |
32bbd8793 net: Convert prot... |
613 614 615 |
static __inline__ int udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, u8 type, u8 code, int offset, __be32 info) |
ba4e58eca [NET]: Supporting... |
616 |
{ |
32bbd8793 net: Convert prot... |
617 |
return __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table); |
ba4e58eca [NET]: Supporting... |
618 |
} |
cf329aa42 udp: cope with UD... |
619 |
static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
620 |
{ |
ba4e58eca [NET]: Supporting... |
621 |
struct udp_sock *up = udp_sk(sk); |
b2bf1e265 [UDP]: Clean up f... |
622 |
int is_udplite = IS_UDPLITE(sk); |
a18135eb9 [IPV6]: Add UDP_M... |
623 |
|
ba4e58eca [NET]: Supporting... |
624 625 |
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto drop; |
1da177e4c Linux-2.6.12-rc2 |
626 |
|
88ab31081 net/udp: Update u... |
627 |
if (static_branch_unlikely(&udpv6_encap_needed_key) && up->encap_type) { |
d7f3f6216 net/ipv6/udp: UDP... |
628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); /* * This is an encapsulation socket so pass the skb to * the socket's udp_encap_rcv() hook. Otherwise, just * fall through and pass this up the UDP socket. * up->encap_rcv() returns the following value: * =0 if skb was successfully passed to the encap * handler or was discarded by it. * >0 if skb should be passed on to UDP. * <0 if skb should be resubmitted as proto -N */ /* if we're overly short, let UDP handle it */ |
6aa7de059 locking/atomics: ... |
642 |
encap_rcv = READ_ONCE(up->encap_rcv); |
e5aed006b udp: prevent skbs... |
643 |
if (encap_rcv) { |
d7f3f6216 net/ipv6/udp: UDP... |
644 |
int ret; |
0a80966b1 net: Verify UDP c... |
645 646 647 |
/* Verify checksum before giving to encap */ if (udp_lib_checksum_complete(skb)) goto csum_error; |
d7f3f6216 net/ipv6/udp: UDP... |
648 649 |
ret = encap_rcv(sk, skb); if (ret <= 0) { |
02c223470 net: udp: rename ... |
650 651 652 |
__UDP_INC_STATS(sock_net(sk), UDP_MIB_INDATAGRAMS, is_udplite); |
d7f3f6216 net/ipv6/udp: UDP... |
653 654 655 656 657 658 |
return -ret; } } /* FALLTHROUGH -- it's a UDP Packet */ } |
ba4e58eca [NET]: Supporting... |
659 660 661 |
/* * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). */ |
b0a422772 net: udp: Fix wro... |
662 |
if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { |
ba4e58eca [NET]: Supporting... |
663 664 |
if (up->pcrlen == 0) { /* full coverage was set */ |
ba7a46f16 net: Convert LIMI... |
665 666 667 |
net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested ", UDP_SKB_CB(skb)->cscov, skb->len); |
ba4e58eca [NET]: Supporting... |
668 669 670 |
goto drop; } if (UDP_SKB_CB(skb)->cscov < up->pcrlen) { |
ba7a46f16 net: Convert LIMI... |
671 672 673 |
net_dbg_ratelimited("UDPLITE6: coverage %d too small, need min %d ", UDP_SKB_CB(skb)->cscov, up->pcrlen); |
ba4e58eca [NET]: Supporting... |
674 675 |
goto drop; } |
1da177e4c Linux-2.6.12-rc2 |
676 |
} |
4b943faed udp/v6: prefetch ... |
677 |
prefetch(&sk->sk_rmem_alloc); |
ce25d66ad Possible problem ... |
678 679 680 |
if (rcu_access_pointer(sk->sk_filter) && udp_lib_checksum_complete(skb)) goto csum_error; |
ba66bbe54 udp: use sk_filte... |
681 |
if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr))) |
a61276977 udp: prevent bugc... |
682 |
goto drop; |
ba4e58eca [NET]: Supporting... |
683 |
|
e6afc8ace udp: remove heade... |
684 |
udp_csum_pull_header(skb); |
cb80ef463 net/ipv6/udp: UDP... |
685 |
|
d826eb14e ipv4: PKTINFO doe... |
686 |
skb_dst_drop(skb); |
cb75994ec [UDP]: Defer InDa... |
687 |
|
850cbaddb udp: use it's own... |
688 |
return __udpv6_queue_rcv_skb(sk, skb); |
3e215c8d1 udp: Add MIB coun... |
689 |
|
6a5dc9e59 net: Add MIB coun... |
690 |
csum_error: |
02c223470 net: udp: rename ... |
691 |
__UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); |
ba4e58eca [NET]: Supporting... |
692 |
drop: |
02c223470 net: udp: rename ... |
693 |
__UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
cb80ef463 net/ipv6/udp: UDP... |
694 |
atomic_inc(&sk->sk_drops); |
ba4e58eca [NET]: Supporting... |
695 696 |
kfree_skb(skb); return -1; |
1da177e4c Linux-2.6.12-rc2 |
697 |
} |
cf329aa42 udp: cope with UD... |
698 699 700 701 702 703 704 705 706 707 |
static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct sk_buff *next, *segs; int ret; if (likely(!udp_unexpected_gso(sk, skb))) return udpv6_queue_rcv_one_skb(sk, skb); __skb_push(skb, -skb_mac_offset(skb)); segs = udp_rcv_segment(sk, skb, false); |
1a186c14c net: udp: use skb... |
708 |
skb_list_walk_safe(segs, skb, next) { |
cf329aa42 udp: cope with UD... |
709 710 711 712 713 714 715 716 717 |
__skb_pull(skb, skb_transport_offset(skb)); ret = udpv6_queue_rcv_one_skb(sk, skb); if (ret > 0) ip6_protocol_deliver_rcu(dev_net(skb->dev), skb, ret, true); } return 0; } |
5cf3d4619 udp: Simplify __u... |
718 719 720 |
static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, __be16 loc_port, const struct in6_addr *loc_addr, __be16 rmt_port, const struct in6_addr *rmt_addr, |
7bd2db404 ipv6: do not drop... |
721 |
int dif, int sdif, unsigned short hnum) |
1da177e4c Linux-2.6.12-rc2 |
722 |
{ |
5cf3d4619 udp: Simplify __u... |
723 |
struct inet_sock *inet = inet_sk(sk); |
1da177e4c Linux-2.6.12-rc2 |
724 |
|
5cf3d4619 udp: Simplify __u... |
725 726 727 728 729 730 731 732 |
if (!net_eq(sock_net(sk), net)) return false; if (udp_sk(sk)->udp_port_hash != hnum || sk->sk_family != PF_INET6 || (inet->inet_dport && inet->inet_dport != rmt_port) || (!ipv6_addr_any(&sk->sk_v6_daddr) && !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || |
7bd2db404 ipv6: do not drop... |
733 |
!udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif) || |
33b4b015e net/ipv6/udp: Fix... |
734 735 |
(!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr))) |
5cf3d4619 udp: Simplify __u... |
736 737 738 739 |
return false; if (!inet6_mc_check(sk, loc_addr, rmt_addr)) return false; return true; |
1da177e4c Linux-2.6.12-rc2 |
740 |
} |
4068579e1 net: Implmement R... |
741 742 743 744 745 |
static void udp6_csum_zero_error(struct sk_buff *skb) { /* RFC 2460 section 8.1 says that we SHOULD log * this error. Well, it is reasonable. */ |
ba7a46f16 net: Convert LIMI... |
746 747 748 749 |
net_dbg_ratelimited("IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u ", &ipv6_hdr(skb)->saddr, ntohs(udp_hdr(skb)->source), &ipv6_hdr(skb)->daddr, ntohs(udp_hdr(skb)->dest)); |
4068579e1 net: Implmement R... |
750 |
} |
1da177e4c Linux-2.6.12-rc2 |
751 752 753 754 |
/* * Note: called only from the BH handler context, * so we don't need to lock the hashes. */ |
e31634931 udp: provide a st... |
755 |
static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
b71d1d426 inet: constify ip... |
756 |
const struct in6_addr *saddr, const struct in6_addr *daddr, |
36cbb2452 udp: Increment UD... |
757 |
struct udp_table *udptable, int proto) |
1da177e4c Linux-2.6.12-rc2 |
758 |
{ |
ca065d0cf udp: no longer us... |
759 |
struct sock *sk, *first = NULL; |
4bedb4520 [SK_BUFF]: Introd... |
760 |
const struct udphdr *uh = udp_hdr(skb); |
5cf3d4619 udp: Simplify __u... |
761 762 |
unsigned short hnum = ntohs(uh->dest); struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); |
ca065d0cf udp: no longer us... |
763 |
unsigned int offset = offsetof(typeof(*sk), sk_node); |
2dc41cff7 udp: Use hash2 fo... |
764 |
unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); |
ca065d0cf udp: no longer us... |
765 |
int dif = inet6_iif(skb); |
7bd2db404 ipv6: do not drop... |
766 |
int sdif = inet6_sdif(skb); |
ca065d0cf udp: no longer us... |
767 768 |
struct hlist_node *node; struct sk_buff *nskb; |
2dc41cff7 udp: Use hash2 fo... |
769 770 |
if (use_hash2) { |
f0b1e64c1 udp: Move udp[46]... |
771 |
hash2_any = ipv6_portaddr_hash(net, &in6addr_any, hnum) & |
73e2d5e34 udp: restore UDPl... |
772 |
udptable->mask; |
f0b1e64c1 udp: Move udp[46]... |
773 |
hash2 = ipv6_portaddr_hash(net, daddr, hnum) & udptable->mask; |
2dc41cff7 udp: Use hash2 fo... |
774 |
start_lookup: |
73e2d5e34 udp: restore UDPl... |
775 |
hslot = &udptable->hash2[hash2]; |
2dc41cff7 udp: Use hash2 fo... |
776 777 |
offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); } |
1da177e4c Linux-2.6.12-rc2 |
778 |
|
ca065d0cf udp: no longer us... |
779 780 |
sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) { if (!__udp_v6_is_mcast_sock(net, sk, uh->dest, daddr, |
7bd2db404 ipv6: do not drop... |
781 782 |
uh->source, saddr, dif, sdif, hnum)) |
ca065d0cf udp: no longer us... |
783 784 785 786 787 788 789 790 791 792 793 794 795 |
continue; /* If zero checksum and no_check is not on for * the socket then skip it. */ if (!uh->check && !udp_sk(sk)->no_check6_rx) continue; if (!first) { first = sk; continue; } nskb = skb_clone(skb, GFP_ATOMIC); if (unlikely(!nskb)) { atomic_inc(&sk->sk_drops); |
02c223470 net: udp: rename ... |
796 797 798 799 |
__UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); __UDP6_INC_STATS(net, UDP_MIB_INERRORS, IS_UDPLITE(sk)); |
ca065d0cf udp: no longer us... |
800 |
continue; |
95766fff6 [UDP]: Add memory... |
801 |
} |
a1ab77f97 ipv6: udp: Optimi... |
802 |
|
ca065d0cf udp: no longer us... |
803 804 805 |
if (udpv6_queue_rcv_skb(sk, nskb) > 0) consume_skb(nskb); } |
a1ab77f97 ipv6: udp: Optimi... |
806 |
|
2dc41cff7 udp: Use hash2 fo... |
807 808 809 810 811 |
/* Also lookup *:port if we are using hash2 and haven't done so yet. */ if (use_hash2 && hash2 != hash2_any) { hash2 = hash2_any; goto start_lookup; } |
ca065d0cf udp: no longer us... |
812 813 814 |
if (first) { if (udpv6_queue_rcv_skb(first, skb) > 0) consume_skb(skb); |
a1ab77f97 ipv6: udp: Optimi... |
815 |
} else { |
ca065d0cf udp: no longer us... |
816 |
kfree_skb(skb); |
02c223470 net: udp: rename ... |
817 818 |
__UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI, proto == IPPROTO_UDPLITE); |
a1ab77f97 ipv6: udp: Optimi... |
819 |
} |
ba4e58eca [NET]: Supporting... |
820 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
821 |
} |
64f0f5d18 udp6: set rx_dst_... |
822 823 824 825 826 827 828 829 |
static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) { if (udp_sk_rx_dst_set(sk, dst)) { const struct rt6_info *rt = (const struct rt6_info *)dst; inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt); } } |
eb63f2964 udp6: add missing... |
830 831 832 833 834 835 836 837 838 |
/* wrapper for udp_queue_rcv_skb tacking care of csum conversion and * return code conversion for ip layer consumption */ static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb, struct udphdr *uh) { int ret; if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk)) |
e4aa33ad5 net: remove unuse... |
839 |
skb_checksum_try_convert(skb, IPPROTO_UDP, ip6_compute_pseudo); |
eb63f2964 udp6: add missing... |
840 841 |
ret = udpv6_queue_rcv_skb(sk, skb); |
84dad5595 udp6: fix encap r... |
842 |
/* a return value > 0 means to resubmit the input */ |
eb63f2964 udp6: add missing... |
843 |
if (ret > 0) |
84dad5595 udp6: fix encap r... |
844 |
return ret; |
eb63f2964 udp6: add missing... |
845 846 |
return 0; } |
645ca708f udp: introduce st... |
847 |
int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, |
759e5d006 [UDP]: Clean up U... |
848 |
int proto) |
1da177e4c Linux-2.6.12-rc2 |
849 |
{ |
ca065d0cf udp: no longer us... |
850 |
const struct in6_addr *saddr, *daddr; |
3ffe533c8 ipv6: drop unused... |
851 |
struct net *net = dev_net(skb->dev); |
1ab1457c4 [NET] IPV6: Fix w... |
852 |
struct udphdr *uh; |
ca065d0cf udp: no longer us... |
853 |
struct sock *sk; |
71489e21d net: Track socket... |
854 |
bool refcounted; |
1da177e4c Linux-2.6.12-rc2 |
855 856 857 |
u32 ulen = 0; if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
d6bc0149d ipv6: udp: make s... |
858 |
goto discard; |
1da177e4c Linux-2.6.12-rc2 |
859 |
|
0660e03f6 [SK_BUFF]: Introd... |
860 861 |
saddr = &ipv6_hdr(skb)->saddr; daddr = &ipv6_hdr(skb)->daddr; |
4bedb4520 [SK_BUFF]: Introd... |
862 |
uh = udp_hdr(skb); |
1da177e4c Linux-2.6.12-rc2 |
863 864 |
ulen = ntohs(uh->len); |
ba4e58eca [NET]: Supporting... |
865 866 |
if (ulen > skb->len) goto short_packet; |
1da177e4c Linux-2.6.12-rc2 |
867 |
|
759e5d006 [UDP]: Clean up U... |
868 869 |
if (proto == IPPROTO_UDP) { /* UDP validates ulen. */ |
1da177e4c Linux-2.6.12-rc2 |
870 |
|
ba4e58eca [NET]: Supporting... |
871 872 873 |
/* Check for jumbo payload */ if (ulen == 0) ulen = skb->len; |
1da177e4c Linux-2.6.12-rc2 |
874 |
|
ba4e58eca [NET]: Supporting... |
875 876 |
if (ulen < sizeof(*uh)) goto short_packet; |
1da177e4c Linux-2.6.12-rc2 |
877 |
|
ba4e58eca [NET]: Supporting... |
878 879 880 |
if (ulen < skb->len) { if (pskb_trim_rcsum(skb, ulen)) goto short_packet; |
0660e03f6 [SK_BUFF]: Introd... |
881 882 |
saddr = &ipv6_hdr(skb)->saddr; daddr = &ipv6_hdr(skb)->daddr; |
4bedb4520 [SK_BUFF]: Introd... |
883 |
uh = udp_hdr(skb); |
ba4e58eca [NET]: Supporting... |
884 |
} |
ba4e58eca [NET]: Supporting... |
885 |
} |
1da177e4c Linux-2.6.12-rc2 |
886 |
|
759e5d006 [UDP]: Clean up U... |
887 |
if (udp6_csum_init(skb, uh, proto)) |
6a5dc9e59 net: Add MIB coun... |
888 |
goto csum_error; |
759e5d006 [UDP]: Clean up U... |
889 |
|
c9f2c1ae1 udp6: fix socket ... |
890 |
/* Check if the socket is already available, e.g. due to early demux */ |
71489e21d net: Track socket... |
891 |
sk = skb_steal_sock(skb, &refcounted); |
c9f2c1ae1 udp6: fix socket ... |
892 893 894 895 896 |
if (sk) { struct dst_entry *dst = skb_dst(skb); int ret; if (unlikely(sk->sk_rx_dst != dst)) |
64f0f5d18 udp6: set rx_dst_... |
897 |
udp6_sk_rx_dst_set(sk, dst); |
c9f2c1ae1 udp6: fix socket ... |
898 |
|
eb63f2964 udp6: add missing... |
899 |
if (!uh->check && !udp_sk(sk)->no_check6_rx) { |
71489e21d net: Track socket... |
900 901 |
if (refcounted) sock_put(sk); |
eb63f2964 udp6: add missing... |
902 903 |
goto report_csum_error; } |
c9f2c1ae1 udp6: fix socket ... |
904 |
|
eb63f2964 udp6: add missing... |
905 |
ret = udp6_unicast_rcv_skb(sk, skb, uh); |
71489e21d net: Track socket... |
906 907 |
if (refcounted) sock_put(sk); |
eb63f2964 udp6: add missing... |
908 |
return ret; |
c9f2c1ae1 udp6: fix socket ... |
909 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
910 911 |
/* * Multicast receive code |
1da177e4c Linux-2.6.12-rc2 |
912 |
*/ |
ba4e58eca [NET]: Supporting... |
913 |
if (ipv6_addr_is_multicast(daddr)) |
e31634931 udp: provide a st... |
914 |
return __udp6_lib_mcast_deliver(net, skb, |
36cbb2452 udp: Increment UD... |
915 |
saddr, daddr, udptable, proto); |
1da177e4c Linux-2.6.12-rc2 |
916 917 |
/* Unicast */ |
607c4aaf0 inet: Add udplib_... |
918 |
sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); |
53b24b8f9 ipv6: coding styl... |
919 |
if (sk) { |
eb63f2964 udp6: add missing... |
920 921 922 |
if (!uh->check && !udp_sk(sk)->no_check6_rx) goto report_csum_error; return udp6_unicast_rcv_skb(sk, skb, uh); |
1da177e4c Linux-2.6.12-rc2 |
923 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
924 |
|
eb63f2964 udp6: add missing... |
925 926 |
if (!uh->check) goto report_csum_error; |
4068579e1 net: Implmement R... |
927 |
|
cb80ef463 net/ipv6/udp: UDP... |
928 |
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
c377411f2 net: sk_add_backl... |
929 |
goto discard; |
cb80ef463 net/ipv6/udp: UDP... |
930 931 |
if (udp_lib_checksum_complete(skb)) |
6a5dc9e59 net: Add MIB coun... |
932 |
goto csum_error; |
cb80ef463 net/ipv6/udp: UDP... |
933 |
|
02c223470 net: udp: rename ... |
934 |
__UDP6_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); |
cb80ef463 net/ipv6/udp: UDP... |
935 936 937 |
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); kfree_skb(skb); |
add459aa1 [UDP]: ipv6 style... |
938 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
939 |
|
1ab1457c4 [NET] IPV6: Fix w... |
940 |
short_packet: |
ba7a46f16 net: Convert LIMI... |
941 942 943 944 945 946 |
net_dbg_ratelimited("UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u ", proto == IPPROTO_UDPLITE ? "-Lite" : "", saddr, ntohs(uh->source), ulen, skb->len, daddr, ntohs(uh->dest)); |
6a5dc9e59 net: Add MIB coun... |
947 |
goto discard; |
eb63f2964 udp6: add missing... |
948 949 950 |
report_csum_error: udp6_csum_zero_error(skb); |
6a5dc9e59 net: Add MIB coun... |
951 |
csum_error: |
02c223470 net: udp: rename ... |
952 |
__UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); |
1da177e4c Linux-2.6.12-rc2 |
953 |
discard: |
02c223470 net: udp: rename ... |
954 |
__UDP6_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
1da177e4c Linux-2.6.12-rc2 |
955 |
kfree_skb(skb); |
add459aa1 [UDP]: ipv6 style... |
956 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
957 |
} |
ba4e58eca [NET]: Supporting... |
958 |
|
0bd84065b net: ipv6: Fix UD... |
959 |
|
5425077d7 net: ipv6: Add ea... |
960 961 962 |
static struct sock *__udp6_lib_demux_lookup(struct net *net, __be16 loc_port, const struct in6_addr *loc_addr, __be16 rmt_port, const struct in6_addr *rmt_addr, |
4297a0ef0 net: ipv6: add se... |
963 |
int dif, int sdif) |
5425077d7 net: ipv6: Add ea... |
964 |
{ |
0bd84065b net: ipv6: Fix UD... |
965 |
unsigned short hnum = ntohs(loc_port); |
f0b1e64c1 udp: Move udp[46]... |
966 |
unsigned int hash2 = ipv6_portaddr_hash(net, loc_addr, hnum); |
0bd84065b net: ipv6: Fix UD... |
967 968 969 |
unsigned int slot2 = hash2 & udp_table.mask; struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); |
5425077d7 net: ipv6: Add ea... |
970 |
struct sock *sk; |
0bd84065b net: ipv6: Fix UD... |
971 |
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { |
85cb73ff9 net: ipv6: reset ... |
972 |
if (sk->sk_state == TCP_ESTABLISHED && |
4297a0ef0 net: ipv6: add se... |
973 |
INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif)) |
0bd84065b net: ipv6: Fix UD... |
974 975 976 977 978 |
return sk; /* Only check first socket in chain */ break; } return NULL; |
5425077d7 net: ipv6: Add ea... |
979 |
} |
97ff7ffb1 net: use indirect... |
980 |
INDIRECT_CALLABLE_SCOPE void udp_v6_early_demux(struct sk_buff *skb) |
5425077d7 net: ipv6: Add ea... |
981 982 983 984 985 986 |
{ struct net *net = dev_net(skb->dev); const struct udphdr *uh; struct sock *sk; struct dst_entry *dst; int dif = skb->dev->ifindex; |
4297a0ef0 net: ipv6: add se... |
987 |
int sdif = inet6_sdif(skb); |
5425077d7 net: ipv6: Add ea... |
988 989 990 991 992 993 994 995 996 997 998 |
if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) return; uh = udp_hdr(skb); if (skb->pkt_type == PACKET_HOST) sk = __udp6_lib_demux_lookup(net, uh->dest, &ipv6_hdr(skb)->daddr, uh->source, &ipv6_hdr(skb)->saddr, |
4297a0ef0 net: ipv6: add se... |
999 |
dif, sdif); |
5425077d7 net: ipv6: Add ea... |
1000 1001 |
else return; |
41c6d650f net: convert sock... |
1002 |
if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt)) |
5425077d7 net: ipv6: Add ea... |
1003 1004 1005 1006 1007 1008 1009 1010 1011 |
return; skb->sk = sk; skb->destructor = sock_efree; dst = READ_ONCE(sk->sk_rx_dst); if (dst) dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); if (dst) { |
d24406c85 udp: call dst_hol... |
1012 1013 1014 1015 1016 |
/* set noref for now. * any place which wants to hold dst has to call * dst_hold_safe() */ skb_dst_set_noref(skb, dst); |
5425077d7 net: ipv6: Add ea... |
1017 1018 |
} } |
0e219ae48 net: use indirect... |
1019 |
INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb) |
ba4e58eca [NET]: Supporting... |
1020 |
{ |
645ca708f udp: introduce st... |
1021 |
return __udp6_lib_rcv(skb, &udp_table, IPPROTO_UDP); |
ba4e58eca [NET]: Supporting... |
1022 |
} |
1da177e4c Linux-2.6.12-rc2 |
1023 1024 1025 1026 1027 1028 |
/* * Throw away all pending data and cancel the corking. Socket is locked. */ static void udp_v6_flush_pending_frames(struct sock *sk) { struct udp_sock *up = udp_sk(sk); |
36d926b94 [IPV6]: inet_sk(s... |
1029 1030 1031 |
if (up->pending == AF_INET) udp_flush_pending_frames(sk); else if (up->pending) { |
1da177e4c Linux-2.6.12-rc2 |
1032 1033 1034 |
up->len = 0; up->pending = 0; ip6_flush_pending_frames(sk); |
1ab1457c4 [NET] IPV6: Fix w... |
1035 |
} |
1da177e4c Linux-2.6.12-rc2 |
1036 |
} |
d74bad4e7 bpf: Hooks for sy... |
1037 1038 1039 |
static int udpv6_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) { |
bddc028a4 udpv6: Check addr... |
1040 1041 |
if (addr_len < offsetofend(struct sockaddr, sa_family)) return -EINVAL; |
d74bad4e7 bpf: Hooks for sy... |
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 |
/* The following checks are replicated from __ip6_datagram_connect() * and intended to prevent BPF program called below from accessing * bytes that are out of the bound specified by user in addr_len. */ if (uaddr->sa_family == AF_INET) { if (__ipv6_only_sock(sk)) return -EAFNOSUPPORT; return udp_pre_connect(sk, uaddr, addr_len); } if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr); } |
493c6be3f udpv6: Fix HW che... |
1057 |
/** |
67ba4152e ipv6: White-space... |
1058 1059 1060 1061 |
* udp6_hwcsum_outgoing - handle outgoing HW checksumming * @sk: socket we are sending on * @skb: sk_buff containing the filled-in UDP header * (checksum field must be zeroed out) |
b51cd7c83 net: ipv6: kernel... |
1062 1063 1064 |
* @saddr: source address * @daddr: destination address * @len: length of packet |
493c6be3f udpv6: Fix HW che... |
1065 1066 1067 1068 1069 1070 1071 |
*/ static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, const struct in6_addr *saddr, const struct in6_addr *daddr, int len) { unsigned int offset; struct udphdr *uh = udp_hdr(skb); |
d39d938c8 ipv6: Introduce u... |
1072 |
struct sk_buff *frags = skb_shinfo(skb)->frag_list; |
493c6be3f udpv6: Fix HW che... |
1073 |
__wsum csum = 0; |
d39d938c8 ipv6: Introduce u... |
1074 |
if (!frags) { |
493c6be3f udpv6: Fix HW che... |
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
/* Only one fragment on the socket. */ skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, 0); } else { /* * HW-checksum won't work as there are two or more * fragments on the socket so that all csums of sk_buffs * should be together */ offset = skb_transport_offset(skb); skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); |
63ecc3d94 udpv6: Fix the ch... |
1087 |
csum = skb->csum; |
493c6be3f udpv6: Fix HW che... |
1088 1089 |
skb->ip_summed = CHECKSUM_NONE; |
d39d938c8 ipv6: Introduce u... |
1090 1091 1092 |
do { csum = csum_add(csum, frags->csum); } while ((frags = frags->next)); |
493c6be3f udpv6: Fix HW che... |
1093 1094 1095 1096 1097 1098 1099 |
uh->check = csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, csum); if (uh->check == 0) uh->check = CSUM_MANGLED_0; } } |
1da177e4c Linux-2.6.12-rc2 |
1100 1101 1102 |
/* * Sending */ |
bec1f6f69 udp: generate gso... |
1103 1104 |
static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6, struct inet_cork *cork) |
1da177e4c Linux-2.6.12-rc2 |
1105 |
{ |
d39d938c8 ipv6: Introduce u... |
1106 |
struct sock *sk = skb->sk; |
1da177e4c Linux-2.6.12-rc2 |
1107 |
struct udphdr *uh; |
1da177e4c Linux-2.6.12-rc2 |
1108 |
int err = 0; |
b2bf1e265 [UDP]: Clean up f... |
1109 |
int is_udplite = IS_UDPLITE(sk); |
868c86bcb [NET]: annotate c... |
1110 |
__wsum csum = 0; |
d39d938c8 ipv6: Introduce u... |
1111 1112 |
int offset = skb_transport_offset(skb); int len = skb->len - offset; |
4094871db udp: only do GSO ... |
1113 |
int datalen = len - sizeof(*uh); |
1da177e4c Linux-2.6.12-rc2 |
1114 1115 1116 1117 |
/* * Create a UDP header */ |
4bedb4520 [SK_BUFF]: Introd... |
1118 |
uh = udp_hdr(skb); |
1958b856c net: Put fl6_* ma... |
1119 1120 |
uh->source = fl6->fl6_sport; uh->dest = fl6->fl6_dport; |
d39d938c8 ipv6: Introduce u... |
1121 |
uh->len = htons(len); |
1da177e4c Linux-2.6.12-rc2 |
1122 |
uh->check = 0; |
bec1f6f69 udp: generate gso... |
1123 1124 1125 |
if (cork->gso_size) { const int hlen = skb_network_header_len(skb) + sizeof(struct udphdr); |
0f149c9fe udp: with udp_seg... |
1126 1127 |
if (hlen + cork->gso_size > cork->fragsize) { kfree_skb(skb); |
bec1f6f69 udp: generate gso... |
1128 |
return -EINVAL; |
0f149c9fe udp: with udp_seg... |
1129 1130 1131 |
} if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { kfree_skb(skb); |
bec1f6f69 udp: generate gso... |
1132 |
return -EINVAL; |
0f149c9fe udp: with udp_seg... |
1133 1134 1135 |
} if (udp_sk(sk)->no_check6_tx) { kfree_skb(skb); |
a8c744a8b udp: disable gso ... |
1136 |
return -EINVAL; |
0f149c9fe udp: with udp_seg... |
1137 |
} |
ff06342cb udp: exclude gso ... |
1138 |
if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite || |
0f149c9fe udp: with udp_seg... |
1139 1140 |
dst_xfrm(skb_dst(skb))) { kfree_skb(skb); |
bec1f6f69 udp: generate gso... |
1141 |
return -EIO; |
0f149c9fe udp: with udp_seg... |
1142 |
} |
bec1f6f69 udp: generate gso... |
1143 |
|
4094871db udp: only do GSO ... |
1144 1145 1146 1147 1148 1149 |
if (datalen > cork->gso_size) { skb_shinfo(skb)->gso_size = cork->gso_size; skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4; skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen, cork->gso_size); } |
a8c744a8b udp: disable gso ... |
1150 |
goto csum_partial; |
bec1f6f69 udp: generate gso... |
1151 |
} |
b2bf1e265 [UDP]: Clean up f... |
1152 |
if (is_udplite) |
d39d938c8 ipv6: Introduce u... |
1153 1154 |
csum = udplite_csum(skb); else if (udp_sk(sk)->no_check6_tx) { /* UDP csum disabled */ |
4068579e1 net: Implmement R... |
1155 1156 1157 |
skb->ip_summed = CHECKSUM_NONE; goto send; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |
a8c744a8b udp: disable gso ... |
1158 |
csum_partial: |
d39d938c8 ipv6: Introduce u... |
1159 |
udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, len); |
493c6be3f udpv6: Fix HW che... |
1160 1161 |
goto send; } else |
d39d938c8 ipv6: Introduce u... |
1162 |
csum = udp_csum(skb); |
1da177e4c Linux-2.6.12-rc2 |
1163 |
|
ba4e58eca [NET]: Supporting... |
1164 |
/* add protocol-dependent pseudo-header */ |
4c9483b2f ipv6: Convert to ... |
1165 |
uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr, |
d39d938c8 ipv6: Introduce u... |
1166 |
len, fl6->flowi6_proto, csum); |
1da177e4c Linux-2.6.12-rc2 |
1167 |
if (uh->check == 0) |
f6ab02880 [NET]: Make mangl... |
1168 |
uh->check = CSUM_MANGLED_0; |
1da177e4c Linux-2.6.12-rc2 |
1169 |
|
493c6be3f udpv6: Fix HW che... |
1170 |
send: |
d39d938c8 ipv6: Introduce u... |
1171 |
err = ip6_send_skb(skb); |
6ce9e7b5f ip: Report qdisc ... |
1172 1173 |
if (err) { if (err == -ENOBUFS && !inet6_sk(sk)->recverr) { |
6aef70a85 net: snmp: kill v... |
1174 1175 |
UDP6_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS, is_udplite); |
6ce9e7b5f ip: Report qdisc ... |
1176 1177 |
err = 0; } |
6aef70a85 net: snmp: kill v... |
1178 1179 1180 1181 |
} else { UDP6_INC_STATS(sock_net(sk), UDP_MIB_OUTDATAGRAMS, is_udplite); } |
d39d938c8 ipv6: Introduce u... |
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 |
return err; } static int udp_v6_push_pending_frames(struct sock *sk) { struct sk_buff *skb; struct udp_sock *up = udp_sk(sk); struct flowi6 fl6; int err = 0; if (up->pending == AF_INET) return udp_push_pending_frames(sk); /* ip6_finish_skb will release the cork, so make a copy of * fl6 here. */ fl6 = inet_sk(sk)->cork.fl.u.ip6; skb = ip6_finish_skb(sk); if (!skb) goto out; |
bec1f6f69 udp: generate gso... |
1203 |
err = udp_v6_send_skb(skb, &fl6, &inet_sk(sk)->cork.base); |
d39d938c8 ipv6: Introduce u... |
1204 |
|
1da177e4c Linux-2.6.12-rc2 |
1205 1206 1207 1208 1209 |
out: up->len = 0; up->pending = 0; return err; } |
1b7841404 net: Remove iocb ... |
1210 |
int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) |
1da177e4c Linux-2.6.12-rc2 |
1211 1212 1213 1214 1215 |
{ struct ipv6_txoptions opt_space; struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); |
342dfc306 net: add build-ti... |
1216 |
DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); |
20c59de2e ipv6: Refactor up... |
1217 |
struct in6_addr *daddr, *final_p, final; |
1da177e4c Linux-2.6.12-rc2 |
1218 |
struct ipv6_txoptions *opt = NULL; |
45f6fad84 ipv6: add complet... |
1219 |
struct ipv6_txoptions *opt_to_free = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1220 |
struct ip6_flowlabel *flowlabel = NULL; |
4c9483b2f ipv6: Convert to ... |
1221 |
struct flowi6 fl6; |
1da177e4c Linux-2.6.12-rc2 |
1222 |
struct dst_entry *dst; |
26879da58 ipv6: add new str... |
1223 |
struct ipcm6_cookie ipc6; |
1da177e4c Linux-2.6.12-rc2 |
1224 |
int addr_len = msg->msg_namelen; |
9f542f616 ipv6: udp: conver... |
1225 |
bool connected = false; |
1da177e4c Linux-2.6.12-rc2 |
1226 |
int ulen = len; |
1da177e4c Linux-2.6.12-rc2 |
1227 1228 |
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; int err; |
b2bf1e265 [UDP]: Clean up f... |
1229 |
int is_udplite = IS_UDPLITE(sk); |
ba4e58eca [NET]: Supporting... |
1230 |
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); |
1da177e4c Linux-2.6.12-rc2 |
1231 |
|
b515430ac ipv6: ipcm6_cooki... |
1232 |
ipcm6_init(&ipc6); |
bec1f6f69 udp: generate gso... |
1233 |
ipc6.gso_size = up->gso_size; |
5fdaa88df ipv6: fold sockcm... |
1234 |
ipc6.sockc.tsflags = sk->sk_tsflags; |
c6af0c227 ip: support SO_MA... |
1235 |
ipc6.sockc.mark = sk->sk_mark; |
26879da58 ipv6: add new str... |
1236 |
|
1da177e4c Linux-2.6.12-rc2 |
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 |
/* destination address check */ if (sin6) { if (addr_len < offsetof(struct sockaddr, sa_data)) return -EINVAL; switch (sin6->sin6_family) { case AF_INET6: if (addr_len < SIN6_LEN_RFC2133) return -EINVAL; daddr = &sin6->sin6_addr; |
052d2369d ipv6: Handle IPv4... |
1247 1248 1249 1250 |
if (ipv6_addr_any(daddr) && ipv6_addr_v4mapped(&np->saddr)) ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK), daddr); |
1da177e4c Linux-2.6.12-rc2 |
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 |
break; case AF_INET: goto do_udp_sendmsg; case AF_UNSPEC: msg->msg_name = sin6 = NULL; msg->msg_namelen = addr_len = 0; daddr = NULL; break; default: return -EINVAL; } } else if (!up->pending) { if (sk->sk_state != TCP_ESTABLISHED) return -EDESTADDRREQ; |
efe4208f4 ipv6: make lookup... |
1265 |
daddr = &sk->sk_v6_daddr; |
1ab1457c4 [NET] IPV6: Fix w... |
1266 |
} else |
1da177e4c Linux-2.6.12-rc2 |
1267 1268 1269 |
daddr = NULL; if (daddr) { |
e773e4faa [IPV6]: Add v4map... |
1270 |
if (ipv6_addr_v4mapped(daddr)) { |
1da177e4c Linux-2.6.12-rc2 |
1271 1272 |
struct sockaddr_in sin; sin.sin_family = AF_INET; |
c720c7e83 inet: rename some... |
1273 |
sin.sin_port = sin6 ? sin6->sin6_port : inet->inet_dport; |
1da177e4c Linux-2.6.12-rc2 |
1274 1275 1276 1277 1278 1279 |
sin.sin_addr.s_addr = daddr->s6_addr32[3]; msg->msg_name = &sin; msg->msg_namelen = sizeof(sin); do_udp_sendmsg: if (__ipv6_only_sock(sk)) return -ENETUNREACH; |
1b7841404 net: Remove iocb ... |
1280 |
return udp_sendmsg(sk, msg, len); |
1da177e4c Linux-2.6.12-rc2 |
1281 1282 1283 1284 |
} } if (up->pending == AF_INET) |
1b7841404 net: Remove iocb ... |
1285 |
return udp_sendmsg(sk, msg, len); |
1da177e4c Linux-2.6.12-rc2 |
1286 1287 |
/* Rough check on arithmetic overflow, |
b59e139bb [IPv6]: Fix incor... |
1288 |
better check is made in ip6_append_data(). |
1da177e4c Linux-2.6.12-rc2 |
1289 1290 1291 |
*/ if (len > INT_MAX - sizeof(struct udphdr)) return -EMSGSIZE; |
1ab1457c4 [NET] IPV6: Fix w... |
1292 |
|
03485f2ad udpv6: Add lockle... |
1293 |
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1da177e4c Linux-2.6.12-rc2 |
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
if (up->pending) { /* * There are pending frames. * The socket lock must be held while it's corked. */ lock_sock(sk); if (likely(up->pending)) { if (unlikely(up->pending != AF_INET6)) { release_sock(sk); return -EAFNOSUPPORT; } dst = NULL; goto do_append_data; } release_sock(sk); } ulen += sizeof(struct udphdr); |
4c9483b2f ipv6: Convert to ... |
1311 |
memset(&fl6, 0, sizeof(fl6)); |
1da177e4c Linux-2.6.12-rc2 |
1312 1313 1314 1315 |
if (sin6) { if (sin6->sin6_port == 0) return -EINVAL; |
1958b856c net: Put fl6_* ma... |
1316 |
fl6.fl6_dport = sin6->sin6_port; |
1da177e4c Linux-2.6.12-rc2 |
1317 1318 1319 |
daddr = &sin6->sin6_addr; if (np->sndflow) { |
4c9483b2f ipv6: Convert to ... |
1320 1321 1322 |
fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK; if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) { flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
59c820b23 ipv6: elide flowl... |
1323 |
if (IS_ERR(flowlabel)) |
1da177e4c Linux-2.6.12-rc2 |
1324 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
1325 1326 1327 1328 1329 1330 1331 1332 |
} } /* * Otherwise it will be difficult to maintain * sk->sk_dst_cache. */ if (sk->sk_state == TCP_ESTABLISHED && |
efe4208f4 ipv6: make lookup... |
1333 1334 |
ipv6_addr_equal(daddr, &sk->sk_v6_daddr)) daddr = &sk->sk_v6_daddr; |
1da177e4c Linux-2.6.12-rc2 |
1335 1336 1337 |
if (addr_len >= sizeof(struct sockaddr_in6) && sin6->sin6_scope_id && |
842df0739 ipv6: use newly i... |
1338 |
__ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr))) |
4c9483b2f ipv6: Convert to ... |
1339 |
fl6.flowi6_oif = sin6->sin6_scope_id; |
1da177e4c Linux-2.6.12-rc2 |
1340 1341 1342 |
} else { if (sk->sk_state != TCP_ESTABLISHED) return -EDESTADDRREQ; |
1958b856c net: Put fl6_* ma... |
1343 |
fl6.fl6_dport = inet->inet_dport; |
efe4208f4 ipv6: make lookup... |
1344 |
daddr = &sk->sk_v6_daddr; |
4c9483b2f ipv6: Convert to ... |
1345 |
fl6.flowlabel = np->flow_label; |
9f542f616 ipv6: udp: conver... |
1346 |
connected = true; |
1da177e4c Linux-2.6.12-rc2 |
1347 |
} |
4c9483b2f ipv6: Convert to ... |
1348 1349 |
if (!fl6.flowi6_oif) fl6.flowi6_oif = sk->sk_bound_dev_if; |
1da177e4c Linux-2.6.12-rc2 |
1350 |
|
4c9483b2f ipv6: Convert to ... |
1351 1352 |
if (!fl6.flowi6_oif) fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; |
9f690db7f ipv6: fix the out... |
1353 |
|
c6af0c227 ip: support SO_MA... |
1354 |
fl6.flowi6_mark = ipc6.sockc.mark; |
e2d118a1c net: inet: Suppor... |
1355 |
fl6.flowi6_uid = sk->sk_uid; |
51953d5bc Use sk_mark for I... |
1356 |
|
1da177e4c Linux-2.6.12-rc2 |
1357 1358 1359 1360 |
if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_txoptions)); opt->tot_len = sizeof(*opt); |
26879da58 ipv6: add new str... |
1361 |
ipc6.opt = opt; |
1da177e4c Linux-2.6.12-rc2 |
1362 |
|
2e8de8576 udp: add gso segm... |
1363 1364 1365 |
err = udp_cmsg_send(sk, msg, &ipc6.gso_size); if (err > 0) err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6, |
5fdaa88df ipv6: fold sockcm... |
1366 |
&ipc6); |
1da177e4c Linux-2.6.12-rc2 |
1367 1368 1369 1370 |
if (err < 0) { fl6_sock_release(flowlabel); return err; } |
4c9483b2f ipv6: Convert to ... |
1371 1372 |
if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) { flowlabel = fl6_sock_lookup(sk, fl6.flowlabel); |
59c820b23 ipv6: elide flowl... |
1373 |
if (IS_ERR(flowlabel)) |
1da177e4c Linux-2.6.12-rc2 |
1374 1375 1376 1377 |
return -EINVAL; } if (!(opt->opt_nflen|opt->opt_flen)) opt = NULL; |
9f542f616 ipv6: udp: conver... |
1378 |
connected = false; |
1da177e4c Linux-2.6.12-rc2 |
1379 |
} |
45f6fad84 ipv6: add complet... |
1380 1381 1382 1383 |
if (!opt) { opt = txopt_get(np); opt_to_free = opt; } |
df9890c31 [IPV6]: Fix sendi... |
1384 1385 1386 |
if (flowlabel) opt = fl6_merge_options(&opt_space, flowlabel, opt); opt = ipv6_fixup_options(&opt_space, opt); |
26879da58 ipv6: add new str... |
1387 |
ipc6.opt = opt; |
1da177e4c Linux-2.6.12-rc2 |
1388 |
|
4c9483b2f ipv6: Convert to ... |
1389 |
fl6.flowi6_proto = sk->sk_protocol; |
e8e369840 bpf: Fix [::] -> ... |
1390 |
fl6.daddr = *daddr; |
4c9483b2f ipv6: Convert to ... |
1391 |
if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) |
4e3fd7a06 net: remove ipv6_... |
1392 |
fl6.saddr = np->saddr; |
1958b856c net: Put fl6_* ma... |
1393 |
fl6.fl6_sport = inet->inet_sport; |
1ab1457c4 [NET] IPV6: Fix w... |
1394 |
|
1cedee13d bpf: Hooks for sy... |
1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 |
if (cgroup_bpf_enabled && !connected) { err = BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk, (struct sockaddr *)sin6, &fl6.saddr); if (err) goto out_no_dst; if (sin6) { if (ipv6_addr_v4mapped(&sin6->sin6_addr)) { /* BPF program rewrote IPv6-only by IPv4-mapped * IPv6. It's currently unsupported. */ err = -ENOTSUPP; goto out_no_dst; } if (sin6->sin6_port == 0) { /* BPF program set invalid port. Reject it. */ err = -EINVAL; goto out_no_dst; } fl6.fl6_dport = sin6->sin6_port; fl6.daddr = sin6->sin6_addr; } } |
e8e369840 bpf: Fix [::] -> ... |
1417 1418 |
if (ipv6_addr_any(&fl6.daddr)) fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ |
4c9483b2f ipv6: Convert to ... |
1419 |
final_p = fl6_update_dst(&fl6, opt, &final); |
20c59de2e ipv6: Refactor up... |
1420 |
if (final_p) |
9f542f616 ipv6: udp: conver... |
1421 |
connected = false; |
1da177e4c Linux-2.6.12-rc2 |
1422 |
|
4c9483b2f ipv6: Convert to ... |
1423 1424 |
if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) { fl6.flowi6_oif = np->mcast_oif; |
9f542f616 ipv6: udp: conver... |
1425 |
connected = false; |
c4062dfc4 ipv6: Implement I... |
1426 1427 |
} else if (!fl6.flowi6_oif) fl6.flowi6_oif = np->ucast_oif; |
1da177e4c Linux-2.6.12-rc2 |
1428 |
|
4c9483b2f ipv6: Convert to ... |
1429 |
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); |
beb8d13be [MLSXFRM]: Add fl... |
1430 |
|
38b7097b5 ipv6: use TOS mar... |
1431 1432 1433 1434 |
if (ipc6.tclass < 0) ipc6.tclass = np->tclass; fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel); |
4f858c56b ipv6: udp: set ds... |
1435 |
dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, connected); |
68d0c6d34 ipv6: Consolidate... |
1436 1437 1438 |
if (IS_ERR(dst)) { err = PTR_ERR(dst); dst = NULL; |
1da177e4c Linux-2.6.12-rc2 |
1439 |
goto out; |
14e50e57a [XFRM]: Allow pac... |
1440 |
} |
1da177e4c Linux-2.6.12-rc2 |
1441 |
|
26879da58 ipv6: add new str... |
1442 1443 |
if (ipc6.hlimit < 0) ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst); |
1da177e4c Linux-2.6.12-rc2 |
1444 1445 1446 1447 |
if (msg->msg_flags&MSG_CONFIRM) goto do_confirm; back_from_confirm: |
03485f2ad udpv6: Add lockle... |
1448 1449 |
/* Lockless fast path for the non-corking case */ if (!corkreq) { |
1cd7884df udp: expose inet ... |
1450 |
struct inet_cork_full cork; |
03485f2ad udpv6: Add lockle... |
1451 1452 1453 |
struct sk_buff *skb; skb = ip6_make_skb(sk, getfrag, msg, ulen, |
26879da58 ipv6: add new str... |
1454 |
sizeof(struct udphdr), &ipc6, |
03485f2ad udpv6: Add lockle... |
1455 |
&fl6, (struct rt6_info *)dst, |
5fdaa88df ipv6: fold sockcm... |
1456 |
msg->msg_flags, &cork); |
03485f2ad udpv6: Add lockle... |
1457 1458 |
err = PTR_ERR(skb); if (!IS_ERR_OR_NULL(skb)) |
bec1f6f69 udp: generate gso... |
1459 |
err = udp_v6_send_skb(skb, &fl6, &cork.base); |
4f858c56b ipv6: udp: set ds... |
1460 |
goto out; |
03485f2ad udpv6: Add lockle... |
1461 |
} |
1da177e4c Linux-2.6.12-rc2 |
1462 1463 1464 1465 1466 |
lock_sock(sk); if (unlikely(up->pending)) { /* The socket is already corked while preparing it. */ /* ... which is an evident application bug. --ANK */ release_sock(sk); |
ba7a46f16 net: Convert LIMI... |
1467 1468 |
net_dbg_ratelimited("udp cork app bug 2 "); |
1da177e4c Linux-2.6.12-rc2 |
1469 1470 1471 1472 1473 1474 1475 |
err = -EINVAL; goto out; } up->pending = AF_INET6; do_append_data: |
26879da58 ipv6: add new str... |
1476 1477 |
if (ipc6.dontfrag < 0) ipc6.dontfrag = np->dontfrag; |
1da177e4c Linux-2.6.12-rc2 |
1478 |
up->len += ulen; |
26879da58 ipv6: add new str... |
1479 1480 |
err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr), &ipc6, &fl6, (struct rt6_info *)dst, |
5fdaa88df ipv6: fold sockcm... |
1481 |
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
1da177e4c Linux-2.6.12-rc2 |
1482 1483 1484 |
if (err) udp_v6_flush_pending_frames(sk); else if (!corkreq) |
4c0a6cb0d [UDP(-Lite)]: con... |
1485 |
err = udp_v6_push_pending_frames(sk); |
1e0c14f49 [UDP]: Fix MSG_PR... |
1486 1487 |
else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) up->pending = 0; |
1da177e4c Linux-2.6.12-rc2 |
1488 |
|
03485f2ad udpv6: Add lockle... |
1489 1490 1491 |
if (err > 0) err = np->recverr ? net_xmit_errno(err) : 0; release_sock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1492 |
out: |
a3c960899 [IPV6] UDP: Possi... |
1493 |
dst_release(dst); |
1cedee13d bpf: Hooks for sy... |
1494 |
out_no_dst: |
1da177e4c Linux-2.6.12-rc2 |
1495 |
fl6_sock_release(flowlabel); |
45f6fad84 ipv6: add complet... |
1496 |
txopt_put(opt_to_free); |
cd562c985 [IPV6]: Just incr... |
1497 |
if (!err) |
1da177e4c Linux-2.6.12-rc2 |
1498 |
return len; |
a18135eb9 [IPV6]: Add UDP_M... |
1499 1500 1501 1502 1503 1504 1505 1506 |
/* * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting * ENOBUFS might not be good (it's not tunable per se), but otherwise * we don't have a good statistic (IpOutDiscards but it can be too many * things). We could add another new stat but at least for now that * seems like overkill. */ if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { |
6aef70a85 net: snmp: kill v... |
1507 1508 |
UDP6_INC_STATS(sock_net(sk), UDP_MIB_SNDBUFERRORS, is_udplite); |
a18135eb9 [IPV6]: Add UDP_M... |
1509 |
} |
1da177e4c Linux-2.6.12-rc2 |
1510 1511 1512 |
return err; do_confirm: |
0dec879f6 net: use dst_conf... |
1513 1514 |
if (msg->msg_flags & MSG_PROBE) dst_confirm_neigh(dst, &fl6.daddr); |
1da177e4c Linux-2.6.12-rc2 |
1515 1516 1517 1518 1519 |
if (!(msg->msg_flags&MSG_PROBE) || len) goto back_from_confirm; err = 0; goto out; } |
7d06b2e05 net: change proto... |
1520 |
void udpv6_destroy_sock(struct sock *sk) |
1da177e4c Linux-2.6.12-rc2 |
1521 |
{ |
44046a593 udp: add encap_de... |
1522 |
struct udp_sock *up = udp_sk(sk); |
1da177e4c Linux-2.6.12-rc2 |
1523 1524 1525 |
lock_sock(sk); udp_v6_flush_pending_frames(sk); release_sock(sk); |
60fb9567b udp: implement co... |
1526 1527 1528 1529 1530 1531 1532 1533 |
if (static_branch_unlikely(&udpv6_encap_needed_key)) { if (up->encap_type) { void (*encap_destroy)(struct sock *sk); encap_destroy = READ_ONCE(up->encap_destroy); if (encap_destroy) encap_destroy(sk); } if (up->encap_enabled) |
9c4806014 udp: fix jump lab... |
1534 |
static_branch_dec(&udpv6_encap_needed_key); |
44046a593 udp: add encap_de... |
1535 |
} |
1da177e4c Linux-2.6.12-rc2 |
1536 |
inet6_destroy_sock(sk); |
1da177e4c Linux-2.6.12-rc2 |
1537 1538 1539 1540 1541 |
} /* * Socket option code for UDP */ |
a7b75c5a8 net: pass a sockp... |
1542 1543 |
int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen) |
3fdadf7d2 [NET]: {get|set}s... |
1544 |
{ |
db8dac20d [UDP]: Revert udp... |
1545 |
if (level == SOL_UDP || level == SOL_UDPLITE) |
91ac1ccaf net/udp: switch u... |
1546 |
return udp_lib_setsockopt(sk, level, optname, |
a7b75c5a8 net: pass a sockp... |
1547 |
optval, optlen, |
4c0a6cb0d [UDP(-Lite)]: con... |
1548 |
udp_v6_push_pending_frames); |
ba4e58eca [NET]: Supporting... |
1549 |
return ipv6_setsockopt(sk, level, optname, optval, optlen); |
3fdadf7d2 [NET]: {get|set}s... |
1550 |
} |
ba4e58eca [NET]: Supporting... |
1551 1552 |
int udpv6_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen) |
3fdadf7d2 [NET]: {get|set}s... |
1553 |
{ |
db8dac20d [UDP]: Revert udp... |
1554 |
if (level == SOL_UDP || level == SOL_UDPLITE) |
4c0a6cb0d [UDP(-Lite)]: con... |
1555 |
return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
ba4e58eca [NET]: Supporting... |
1556 |
return ipv6_getsockopt(sk, level, optname, optval, optlen); |
3fdadf7d2 [NET]: {get|set}s... |
1557 |
} |
a8e3bb347 net: Add comment ... |
1558 1559 1560 |
/* thinking of making this const? Don't. * early_demux can change based on sysctl. */ |
dddb64bcb net: Add sysctl t... |
1561 |
static struct inet6_protocol udpv6_protocol = { |
5425077d7 net: ipv6: Add ea... |
1562 |
.early_demux = udp_v6_early_demux, |
dddb64bcb net: Add sysctl t... |
1563 |
.early_demux_handler = udp_v6_early_demux, |
1da177e4c Linux-2.6.12-rc2 |
1564 1565 1566 1567 1568 1569 1570 |
.handler = udpv6_rcv, .err_handler = udpv6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; /* ------------------------------------------------------------------------ */ #ifdef CONFIG_PROC_FS |
ba4e58eca [NET]: Supporting... |
1571 |
int udp6_seq_show(struct seq_file *seq, void *v) |
1da177e4c Linux-2.6.12-rc2 |
1572 |
{ |
17ef66afc net: ipv6: Unify ... |
1573 1574 1575 1576 1577 1578 1579 |
if (v == SEQ_START_TOKEN) { seq_puts(seq, IPV6_SEQ_DGRAM_HEADER); } else { int bucket = ((struct udp_iter_state *)seq->private)->bucket; struct inet_sock *inet = inet_sk(v); __u16 srcp = ntohs(inet->inet_sport); __u16 destp = ntohs(inet->inet_dport); |
6c206b200 udp: fix rx queue... |
1580 1581 |
__ip6_dgram_sock_seq_show(seq, v, srcp, destp, udp_rqueue_get(v), bucket); |
17ef66afc net: ipv6: Unify ... |
1582 |
} |
1da177e4c Linux-2.6.12-rc2 |
1583 1584 |
return 0; } |
c35063722 proc: introduce p... |
1585 |
const struct seq_operations udp6_seq_ops = { |
a3d2599b2 ipv{4,6}/udp{,lit... |
1586 1587 1588 1589 1590 |
.start = udp_seq_start, .next = udp_seq_next, .stop = udp_seq_stop, .show = udp6_seq_show, }; |
c35063722 proc: introduce p... |
1591 |
EXPORT_SYMBOL(udp6_seq_ops); |
73cb88ecb net: make the tcp... |
1592 |
|
1da177e4c Linux-2.6.12-rc2 |
1593 |
static struct udp_seq_afinfo udp6_seq_afinfo = { |
1da177e4c Linux-2.6.12-rc2 |
1594 |
.family = AF_INET6, |
645ca708f udp: introduce st... |
1595 |
.udp_table = &udp_table, |
1da177e4c Linux-2.6.12-rc2 |
1596 |
}; |
2c8c1e729 net: spread __net... |
1597 |
int __net_init udp6_proc_init(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
1598 |
{ |
c35063722 proc: introduce p... |
1599 1600 |
if (!proc_create_net_data("udp6", 0444, net->proc_net, &udp6_seq_ops, sizeof(struct udp_iter_state), &udp6_seq_afinfo)) |
a3d2599b2 ipv{4,6}/udp{,lit... |
1601 1602 |
return -ENOMEM; return 0; |
1da177e4c Linux-2.6.12-rc2 |
1603 |
} |
ec120da6f ipv6: trivial whi... |
1604 1605 |
void udp6_proc_exit(struct net *net) { |
a3d2599b2 ipv{4,6}/udp{,lit... |
1606 |
remove_proc_entry("udp6", net->proc_net); |
1da177e4c Linux-2.6.12-rc2 |
1607 1608 1609 1610 1611 1612 |
} #endif /* CONFIG_PROC_FS */ /* ------------------------------------------------------------------------ */ struct proto udpv6_prot = { |
1e8029515 udp: Move the udp... |
1613 1614 1615 |
.name = "UDPv6", .owner = THIS_MODULE, .close = udp_lib_close, |
d74bad4e7 bpf: Hooks for sy... |
1616 |
.pre_connect = udpv6_pre_connect, |
1e8029515 udp: Move the udp... |
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 |
.connect = ip6_datagram_connect, .disconnect = udp_disconnect, .ioctl = udp_ioctl, .init = udp_init_sock, .destroy = udpv6_destroy_sock, .setsockopt = udpv6_setsockopt, .getsockopt = udpv6_getsockopt, .sendmsg = udpv6_sendmsg, .recvmsg = udpv6_recvmsg, .release_cb = ip6_datagram_release_cb, .hash = udp_lib_hash, .unhash = udp_lib_unhash, .rehash = udp_v6_rehash, .get_port = udp_v6_get_port, .memory_allocated = &udp_memory_allocated, .sysctl_mem = sysctl_udp_mem, .sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min), .sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min), .obj_size = sizeof(struct udp6_sock), .h.udp_table = &udp_table, |
1e8029515 udp: Move the udp... |
1637 |
.diag_destroy = udp_abort, |
1da177e4c Linux-2.6.12-rc2 |
1638 |
}; |
1da177e4c Linux-2.6.12-rc2 |
1639 1640 1641 1642 1643 |
static struct inet_protosw udpv6_protosw = { .type = SOCK_DGRAM, .protocol = IPPROTO_UDP, .prot = &udpv6_prot, .ops = &inet6_dgram_ops, |
1da177e4c Linux-2.6.12-rc2 |
1644 1645 |
.flags = INET_PROTOSW_PERMANENT, }; |
7f4e4868f [IPV6]: make the ... |
1646 |
int __init udpv6_init(void) |
1da177e4c Linux-2.6.12-rc2 |
1647 |
{ |
7f4e4868f [IPV6]: make the ... |
1648 |
int ret; |
3336288a9 ipv6: Switch to u... |
1649 1650 |
ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP); if (ret) |
c6b641a4c ipv6: Pull IPv6 G... |
1651 |
goto out; |
3336288a9 ipv6: Switch to u... |
1652 |
|
7f4e4868f [IPV6]: make the ... |
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 |
ret = inet6_register_protosw(&udpv6_protosw); if (ret) goto out_udpv6_protocol; out: return ret; out_udpv6_protocol: inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); goto out; } |
09f7709f4 [IPV6]: fix secti... |
1663 |
void udpv6_exit(void) |
7f4e4868f [IPV6]: make the ... |
1664 1665 1666 |
{ inet6_unregister_protosw(&udpv6_protosw); inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP); |
1da177e4c Linux-2.6.12-rc2 |
1667 |
} |