1 | /* $NetBSD: udp6_usrreq.c,v 1.126 2016/11/18 06:50:04 knakahara Exp $ */ |
2 | /* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
6 | * All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the project nor the names of its contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. |
31 | */ |
32 | |
33 | /* |
34 | * Copyright (c) 1982, 1986, 1989, 1993 |
35 | * The Regents of the University of California. All rights reserved. |
36 | * |
37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions |
39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. Redistributions in binary form must reproduce the above copyright |
43 | * notice, this list of conditions and the following disclaimer in the |
44 | * documentation and/or other materials provided with the distribution. |
45 | * 3. Neither the name of the University nor the names of its contributors |
46 | * may be used to endorse or promote products derived from this software |
47 | * without specific prior written permission. |
48 | * |
49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
59 | * SUCH DAMAGE. |
60 | * |
61 | * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 |
62 | */ |
63 | |
64 | #include <sys/cdefs.h> |
65 | __KERNEL_RCSID(0, "$NetBSD: udp6_usrreq.c,v 1.126 2016/11/18 06:50:04 knakahara Exp $" ); |
66 | |
67 | #ifdef _KERNEL_OPT |
68 | #include "opt_inet.h" |
69 | #include "opt_inet_csum.h" |
70 | #include "opt_ipsec.h" |
71 | #include "opt_net_mpsafe.h" |
72 | #endif |
73 | |
74 | #include <sys/param.h> |
75 | #include <sys/mbuf.h> |
76 | #include <sys/protosw.h> |
77 | #include <sys/socket.h> |
78 | #include <sys/socketvar.h> |
79 | #include <sys/systm.h> |
80 | #include <sys/proc.h> |
81 | #include <sys/syslog.h> |
82 | #include <sys/domain.h> |
83 | #include <sys/sysctl.h> |
84 | |
85 | #include <net/if.h> |
86 | #include <net/if_types.h> |
87 | |
88 | #include <netinet/in.h> |
89 | #include <netinet/in_var.h> |
90 | #include <netinet/in_systm.h> |
91 | #include <netinet/in_offload.h> |
92 | #include <netinet/ip.h> |
93 | #include <netinet/ip_var.h> |
94 | #include <netinet/in_pcb.h> |
95 | #include <netinet/udp.h> |
96 | #include <netinet/udp_var.h> |
97 | #include <netinet/udp_private.h> |
98 | |
99 | #include <netinet/ip6.h> |
100 | #include <netinet/icmp6.h> |
101 | #include <netinet6/ip6_var.h> |
102 | #include <netinet6/ip6_private.h> |
103 | #include <netinet6/in6_pcb.h> |
104 | #include <netinet6/udp6_var.h> |
105 | #include <netinet6/udp6_private.h> |
106 | #include <netinet6/ip6protosw.h> |
107 | #include <netinet6/scope6_var.h> |
108 | |
109 | #ifdef IPSEC |
110 | #include <netipsec/ipsec.h> |
111 | #include <netipsec/ipsec_var.h> |
112 | #include <netipsec/ipsec_private.h> |
113 | #ifdef INET6 |
114 | #include <netipsec/ipsec6.h> |
115 | #endif |
116 | #endif /* IPSEC */ |
117 | |
118 | #include "faith.h" |
119 | #if defined(NFAITH) && NFAITH > 0 |
120 | #include <net/if_faith.h> |
121 | #endif |
122 | |
123 | /* |
124 | * UDP protocol implementation. |
125 | * Per RFC 768, August, 1980. |
126 | */ |
127 | |
128 | extern struct inpcbtable udbtable; |
129 | |
130 | percpu_t *udp6stat_percpu; |
131 | |
132 | /* UDP on IP6 parameters */ |
133 | static int udp6_sendspace = 9216; /* really max datagram size */ |
134 | static int udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6)); |
135 | /* 40 1K datagrams */ |
136 | |
137 | static void udp6_notify(struct in6pcb *, int); |
138 | static void sysctl_net_inet6_udp6_setup(struct sysctllog **); |
139 | |
140 | #ifdef UDP_CSUM_COUNTERS |
141 | #include <sys/device.h> |
142 | struct evcnt udp6_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
143 | NULL, "udp6" , "hwcsum bad" ); |
144 | struct evcnt udp6_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
145 | NULL, "udp6" , "hwcsum ok" ); |
146 | struct evcnt udp6_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
147 | NULL, "udp6" , "hwcsum data" ); |
148 | struct evcnt udp6_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, |
149 | NULL, "udp6" , "swcsum" ); |
150 | |
151 | EVCNT_ATTACH_STATIC(udp6_hwcsum_bad); |
152 | EVCNT_ATTACH_STATIC(udp6_hwcsum_ok); |
153 | EVCNT_ATTACH_STATIC(udp6_hwcsum_data); |
154 | EVCNT_ATTACH_STATIC(udp6_swcsum); |
155 | |
156 | #define UDP_CSUM_COUNTER_INCR(ev) (ev)->ev_count++ |
157 | #else |
158 | #define UDP_CSUM_COUNTER_INCR(ev) /* nothing */ |
159 | #endif |
160 | |
161 | void |
162 | udp6_init(void) |
163 | { |
164 | sysctl_net_inet6_udp6_setup(NULL); |
165 | udp6stat_percpu = percpu_alloc(sizeof(uint64_t) * UDP6_NSTATS); |
166 | |
167 | udp_init_common(); |
168 | } |
169 | |
170 | /* |
171 | * Notify a udp user of an asynchronous error; |
172 | * just wake up so that he can collect error status. |
173 | */ |
174 | static void |
175 | udp6_notify(struct in6pcb *in6p, int errno) |
176 | { |
177 | in6p->in6p_socket->so_error = errno; |
178 | sorwakeup(in6p->in6p_socket); |
179 | sowwakeup(in6p->in6p_socket); |
180 | } |
181 | |
182 | void * |
183 | udp6_ctlinput(int cmd, const struct sockaddr *sa, void *d) |
184 | { |
185 | struct udphdr uh; |
186 | struct ip6_hdr *ip6; |
187 | const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa; |
188 | struct mbuf *m; |
189 | int off; |
190 | void *cmdarg; |
191 | struct ip6ctlparam *ip6cp = NULL; |
192 | const struct sockaddr_in6 *sa6_src = NULL; |
193 | void (*notify)(struct in6pcb *, int) = udp6_notify; |
194 | struct udp_portonly { |
195 | u_int16_t uh_sport; |
196 | u_int16_t uh_dport; |
197 | } *uhp; |
198 | |
199 | if (sa->sa_family != AF_INET6 || |
200 | sa->sa_len != sizeof(struct sockaddr_in6)) |
201 | return NULL; |
202 | |
203 | if ((unsigned)cmd >= PRC_NCMDS) |
204 | return NULL; |
205 | if (PRC_IS_REDIRECT(cmd)) |
206 | notify = in6_rtchange, d = NULL; |
207 | else if (cmd == PRC_HOSTDEAD) |
208 | d = NULL; |
209 | else if (cmd == PRC_MSGSIZE) { |
210 | /* special code is present, see below */ |
211 | notify = in6_rtchange; |
212 | } |
213 | else if (inet6ctlerrmap[cmd] == 0) |
214 | return NULL; |
215 | |
216 | /* if the parameter is from icmp6, decode it. */ |
217 | if (d != NULL) { |
218 | ip6cp = (struct ip6ctlparam *)d; |
219 | m = ip6cp->ip6c_m; |
220 | ip6 = ip6cp->ip6c_ip6; |
221 | off = ip6cp->ip6c_off; |
222 | cmdarg = ip6cp->ip6c_cmdarg; |
223 | sa6_src = ip6cp->ip6c_src; |
224 | } else { |
225 | m = NULL; |
226 | ip6 = NULL; |
227 | cmdarg = NULL; |
228 | sa6_src = &sa6_any; |
229 | off = 0; |
230 | } |
231 | |
232 | if (ip6) { |
233 | /* |
234 | * XXX: We assume that when IPV6 is non NULL, |
235 | * M and OFF are valid. |
236 | */ |
237 | |
238 | /* check if we can safely examine src and dst ports */ |
239 | if (m->m_pkthdr.len < off + sizeof(*uhp)) { |
240 | if (cmd == PRC_MSGSIZE) |
241 | icmp6_mtudisc_update((struct ip6ctlparam *)d, 0); |
242 | return NULL; |
243 | } |
244 | |
245 | memset(&uh, 0, sizeof(uh)); |
246 | m_copydata(m, off, sizeof(*uhp), (void *)&uh); |
247 | |
248 | if (cmd == PRC_MSGSIZE) { |
249 | int valid = 0; |
250 | |
251 | /* |
252 | * Check to see if we have a valid UDP socket |
253 | * corresponding to the address in the ICMPv6 message |
254 | * payload. |
255 | */ |
256 | if (in6_pcblookup_connect(&udbtable, &sa6->sin6_addr, |
257 | uh.uh_dport, (const struct in6_addr *)&sa6_src->sin6_addr, |
258 | uh.uh_sport, 0, 0)) |
259 | valid++; |
260 | #if 0 |
261 | /* |
262 | * As the use of sendto(2) is fairly popular, |
263 | * we may want to allow non-connected pcb too. |
264 | * But it could be too weak against attacks... |
265 | * We should at least check if the local address (= s) |
266 | * is really ours. |
267 | */ |
268 | else if (in6_pcblookup_bind(&udbtable, &sa6->sin6_addr, |
269 | uh.uh_dport, 0)) |
270 | valid++; |
271 | #endif |
272 | |
273 | /* |
274 | * Depending on the value of "valid" and routing table |
275 | * size (mtudisc_{hi,lo}wat), we will: |
276 | * - recalculate the new MTU and create the |
277 | * corresponding routing entry, or |
278 | * - ignore the MTU change notification. |
279 | */ |
280 | icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); |
281 | |
282 | /* |
283 | * regardless of if we called |
284 | * icmp6_mtudisc_update(), we need to call |
285 | * in6_pcbnotify(), to notify path MTU change |
286 | * to the userland (RFC3542), because some |
287 | * unconnected sockets may share the same |
288 | * destination and want to know the path MTU. |
289 | */ |
290 | } |
291 | |
292 | (void) in6_pcbnotify(&udbtable, sa, uh.uh_dport, |
293 | sin6tocsa(sa6_src), uh.uh_sport, cmd, cmdarg, |
294 | notify); |
295 | } else { |
296 | (void) in6_pcbnotify(&udbtable, sa, 0, |
297 | sin6tocsa(sa6_src), 0, cmd, cmdarg, notify); |
298 | } |
299 | return NULL; |
300 | } |
301 | |
302 | int |
303 | udp6_ctloutput(int op, struct socket *so, struct sockopt *sopt) |
304 | { |
305 | int s; |
306 | int error = 0; |
307 | int family; |
308 | |
309 | family = so->so_proto->pr_domain->dom_family; |
310 | |
311 | s = splsoftnet(); |
312 | switch (family) { |
313 | #ifdef INET |
314 | case PF_INET: |
315 | if (sopt->sopt_level != IPPROTO_UDP) { |
316 | error = ip_ctloutput(op, so, sopt); |
317 | goto end; |
318 | } |
319 | break; |
320 | #endif |
321 | #ifdef INET6 |
322 | case PF_INET6: |
323 | if (sopt->sopt_level != IPPROTO_UDP) { |
324 | error = ip6_ctloutput(op, so, sopt); |
325 | goto end; |
326 | } |
327 | break; |
328 | #endif |
329 | default: |
330 | error = EAFNOSUPPORT; |
331 | goto end; |
332 | } |
333 | error = EINVAL; |
334 | |
335 | end: |
336 | splx(s); |
337 | return error; |
338 | } |
339 | |
340 | static void |
341 | udp6_sendup(struct mbuf *m, int off /* offset of data portion */, |
342 | struct sockaddr *src, struct socket *so) |
343 | { |
344 | struct mbuf *opts = NULL; |
345 | struct mbuf *n; |
346 | struct in6pcb *in6p = NULL; |
347 | |
348 | if (!so) |
349 | return; |
350 | if (so->so_proto->pr_domain->dom_family != AF_INET6) |
351 | return; |
352 | in6p = sotoin6pcb(so); |
353 | |
354 | #if defined(IPSEC) |
355 | /* check AH/ESP integrity. */ |
356 | if (ipsec_used && so != NULL && ipsec6_in_reject_so(m, so)) { |
357 | IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); |
358 | if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) |
359 | icmp6_error(n, ICMP6_DST_UNREACH, |
360 | ICMP6_DST_UNREACH_ADMIN, 0); |
361 | return; |
362 | } |
363 | #endif /*IPSEC*/ |
364 | |
365 | if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) { |
366 | if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS |
367 | #ifdef SO_OTIMESTAMP |
368 | || in6p->in6p_socket->so_options & SO_OTIMESTAMP |
369 | #endif |
370 | || in6p->in6p_socket->so_options & SO_TIMESTAMP)) { |
371 | struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *); |
372 | ip6_savecontrol(in6p, &opts, ip6, n); |
373 | } |
374 | |
375 | m_adj(n, off); |
376 | if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) { |
377 | m_freem(n); |
378 | if (opts) |
379 | m_freem(opts); |
380 | so->so_rcv.sb_overflowed++; |
381 | UDP6_STATINC(UDP6_STAT_FULLSOCK); |
382 | } else |
383 | sorwakeup(so); |
384 | } |
385 | } |
386 | |
387 | int |
388 | udp6_realinput(int af, struct sockaddr_in6 *src, struct sockaddr_in6 *dst, |
389 | struct mbuf *m, int off) |
390 | { |
391 | u_int16_t sport, dport; |
392 | int rcvcnt; |
393 | struct in6_addr src6, *dst6; |
394 | const struct in_addr *dst4; |
395 | struct inpcb_hdr *inph; |
396 | struct in6pcb *in6p; |
397 | |
398 | rcvcnt = 0; |
399 | off += sizeof(struct udphdr); /* now, offset of payload */ |
400 | |
401 | if (af != AF_INET && af != AF_INET6) |
402 | goto bad; |
403 | if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) |
404 | goto bad; |
405 | |
406 | src6 = src->sin6_addr; |
407 | if (sa6_recoverscope(src) != 0) { |
408 | /* XXX: should be impossible. */ |
409 | goto bad; |
410 | } |
411 | sport = src->sin6_port; |
412 | |
413 | dport = dst->sin6_port; |
414 | dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr[12]; |
415 | dst6 = &dst->sin6_addr; |
416 | |
417 | if (IN6_IS_ADDR_MULTICAST(dst6) || |
418 | (af == AF_INET && IN_MULTICAST(dst4->s_addr))) { |
419 | /* |
420 | * Deliver a multicast or broadcast datagram to *all* sockets |
421 | * for which the local and remote addresses and ports match |
422 | * those of the incoming datagram. This allows more than |
423 | * one process to receive multi/broadcasts on the same port. |
424 | * (This really ought to be done for unicast datagrams as |
425 | * well, but that would cause problems with existing |
426 | * applications that open both address-specific sockets and |
427 | * a wildcard socket listening to the same port -- they would |
428 | * end up receiving duplicates of every unicast datagram. |
429 | * Those applications open the multiple sockets to overcome an |
430 | * inadequacy of the UDP socket interface, but for backwards |
431 | * compatibility we avoid the problem here rather than |
432 | * fixing the interface. Maybe 4.5BSD will remedy this?) |
433 | */ |
434 | |
435 | /* |
436 | * KAME note: traditionally we dropped udpiphdr from mbuf here. |
437 | * we need udpiphdr for IPsec processing so we do that later. |
438 | */ |
439 | /* |
440 | * Locate pcb(s) for datagram. |
441 | */ |
442 | TAILQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) { |
443 | in6p = (struct in6pcb *)inph; |
444 | if (in6p->in6p_af != AF_INET6) |
445 | continue; |
446 | |
447 | if (in6p->in6p_lport != dport) |
448 | continue; |
449 | if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) { |
450 | if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, |
451 | dst6)) |
452 | continue; |
453 | } else { |
454 | if (IN6_IS_ADDR_V4MAPPED(dst6) && |
455 | (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) |
456 | continue; |
457 | } |
458 | if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { |
459 | if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, |
460 | &src6) || in6p->in6p_fport != sport) |
461 | continue; |
462 | } else { |
463 | if (IN6_IS_ADDR_V4MAPPED(&src6) && |
464 | (in6p->in6p_flags & IN6P_IPV6_V6ONLY)) |
465 | continue; |
466 | } |
467 | |
468 | udp6_sendup(m, off, sin6tosa(src), in6p->in6p_socket); |
469 | rcvcnt++; |
470 | |
471 | /* |
472 | * Don't look for additional matches if this one does |
473 | * not have either the SO_REUSEPORT or SO_REUSEADDR |
474 | * socket options set. This heuristic avoids searching |
475 | * through all pcbs in the common case of a non-shared |
476 | * port. It assumes that an application will never |
477 | * clear these options after setting them. |
478 | */ |
479 | if ((in6p->in6p_socket->so_options & |
480 | (SO_REUSEPORT|SO_REUSEADDR)) == 0) |
481 | break; |
482 | } |
483 | } else { |
484 | /* |
485 | * Locate pcb for datagram. |
486 | */ |
487 | in6p = in6_pcblookup_connect(&udbtable, &src6, sport, dst6, |
488 | dport, 0, 0); |
489 | if (in6p == 0) { |
490 | UDP_STATINC(UDP_STAT_PCBHASHMISS); |
491 | in6p = in6_pcblookup_bind(&udbtable, dst6, dport, 0); |
492 | if (in6p == 0) |
493 | return rcvcnt; |
494 | } |
495 | |
496 | udp6_sendup(m, off, sin6tosa(src), in6p->in6p_socket); |
497 | rcvcnt++; |
498 | } |
499 | |
500 | bad: |
501 | return rcvcnt; |
502 | } |
503 | |
504 | int |
505 | udp6_input_checksum(struct mbuf *m, const struct udphdr *uh, int off, int len) |
506 | { |
507 | |
508 | /* |
509 | * XXX it's better to record and check if this mbuf is |
510 | * already checked. |
511 | */ |
512 | |
513 | if (__predict_false((m->m_flags & M_LOOP) && !udp_do_loopback_cksum)) { |
514 | goto good; |
515 | } |
516 | if (uh->uh_sum == 0) { |
517 | UDP6_STATINC(UDP6_STAT_NOSUM); |
518 | goto bad; |
519 | } |
520 | |
521 | switch (m->m_pkthdr.csum_flags & |
522 | ((m_get_rcvif_NOMPSAFE(m)->if_csum_flags_rx & M_CSUM_UDPv6) | |
523 | M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) { |
524 | case M_CSUM_UDPv6|M_CSUM_TCP_UDP_BAD: |
525 | UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_bad); |
526 | UDP6_STATINC(UDP6_STAT_BADSUM); |
527 | goto bad; |
528 | |
529 | #if 0 /* notyet */ |
530 | case M_CSUM_UDPv6|M_CSUM_DATA: |
531 | #endif |
532 | |
533 | case M_CSUM_UDPv6: |
534 | /* Checksum was okay. */ |
535 | UDP_CSUM_COUNTER_INCR(&udp6_hwcsum_ok); |
536 | break; |
537 | |
538 | default: |
539 | /* |
540 | * Need to compute it ourselves. Maybe skip checksum |
541 | * on loopback interfaces. |
542 | */ |
543 | UDP_CSUM_COUNTER_INCR(&udp6_swcsum); |
544 | if (in6_cksum(m, IPPROTO_UDP, off, len) != 0) { |
545 | UDP6_STATINC(UDP6_STAT_BADSUM); |
546 | goto bad; |
547 | } |
548 | } |
549 | |
550 | good: |
551 | return 0; |
552 | bad: |
553 | return -1; |
554 | } |
555 | |
556 | int |
557 | udp6_input(struct mbuf **mp, int *offp, int proto) |
558 | { |
559 | struct mbuf *m = *mp; |
560 | int off = *offp; |
561 | struct sockaddr_in6 src, dst; |
562 | struct ip6_hdr *ip6; |
563 | struct udphdr *uh; |
564 | u_int32_t plen, ulen; |
565 | |
566 | ip6 = mtod(m, struct ip6_hdr *); |
567 | |
568 | #if defined(NFAITH) && 0 < NFAITH |
569 | if (faithprefix(&ip6->ip6_dst)) { |
570 | /* send icmp6 host unreach? */ |
571 | m_freem(m); |
572 | return IPPROTO_DONE; |
573 | } |
574 | #endif |
575 | |
576 | UDP6_STATINC(UDP6_STAT_IPACKETS); |
577 | |
578 | /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ |
579 | plen = m->m_pkthdr.len - off; |
580 | IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr)); |
581 | if (uh == NULL) { |
582 | IP6_STATINC(IP6_STAT_TOOSHORT); |
583 | return IPPROTO_DONE; |
584 | } |
585 | /* |
586 | * Enforce alignment requirements that are violated in |
587 | * some cases, see kern/50766 for details. |
588 | */ |
589 | if (UDP_HDR_ALIGNED_P(uh) == 0) { |
590 | m = m_copyup(m, off + sizeof(struct udphdr), 0); |
591 | if (m == NULL) { |
592 | IP6_STATINC(IP6_STAT_TOOSHORT); |
593 | return IPPROTO_DONE; |
594 | } |
595 | ip6 = mtod(m, struct ip6_hdr *); |
596 | uh = (struct udphdr *)(mtod(m, char *) + off); |
597 | } |
598 | KASSERT(UDP_HDR_ALIGNED_P(uh)); |
599 | ulen = ntohs((u_short)uh->uh_ulen); |
600 | /* |
601 | * RFC2675 section 4: jumbograms will have 0 in the UDP header field, |
602 | * iff payload length > 0xffff. |
603 | */ |
604 | if (ulen == 0 && plen > 0xffff) |
605 | ulen = plen; |
606 | |
607 | if (plen != ulen) { |
608 | UDP6_STATINC(UDP6_STAT_BADLEN); |
609 | goto bad; |
610 | } |
611 | |
612 | /* destination port of 0 is illegal, based on RFC768. */ |
613 | if (uh->uh_dport == 0) |
614 | goto bad; |
615 | |
616 | /* Be proactive about malicious use of IPv4 mapped address */ |
617 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
618 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
619 | /* XXX stat */ |
620 | goto bad; |
621 | } |
622 | |
623 | /* |
624 | * Checksum extended UDP header and data. Maybe skip checksum |
625 | * on loopback interfaces. |
626 | */ |
627 | if (udp6_input_checksum(m, uh, off, ulen)) |
628 | goto bad; |
629 | |
630 | /* |
631 | * Construct source and dst sockaddrs. |
632 | */ |
633 | memset(&src, 0, sizeof(src)); |
634 | src.sin6_family = AF_INET6; |
635 | src.sin6_len = sizeof(struct sockaddr_in6); |
636 | src.sin6_addr = ip6->ip6_src; |
637 | src.sin6_port = uh->uh_sport; |
638 | memset(&dst, 0, sizeof(dst)); |
639 | dst.sin6_family = AF_INET6; |
640 | dst.sin6_len = sizeof(struct sockaddr_in6); |
641 | dst.sin6_addr = ip6->ip6_dst; |
642 | dst.sin6_port = uh->uh_dport; |
643 | |
644 | if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { |
645 | if (m->m_flags & M_MCAST) { |
646 | UDP6_STATINC(UDP6_STAT_NOPORTMCAST); |
647 | goto bad; |
648 | } |
649 | UDP6_STATINC(UDP6_STAT_NOPORT); |
650 | icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); |
651 | m = NULL; |
652 | } |
653 | |
654 | bad: |
655 | if (m) |
656 | m_freem(m); |
657 | return IPPROTO_DONE; |
658 | } |
659 | |
660 | static int |
661 | udp6_attach(struct socket *so, int proto) |
662 | { |
663 | struct in6pcb *in6p; |
664 | int s, error; |
665 | |
666 | KASSERT(sotoin6pcb(so) == NULL); |
667 | sosetlock(so); |
668 | |
669 | /* |
670 | * MAPPED_ADDR implementation spec: |
671 | * Always attach for IPv6, and only when necessary for IPv4. |
672 | */ |
673 | s = splsoftnet(); |
674 | error = in6_pcballoc(so, &udbtable); |
675 | splx(s); |
676 | if (error) { |
677 | return error; |
678 | } |
679 | error = soreserve(so, udp6_sendspace, udp6_recvspace); |
680 | if (error) { |
681 | return error; |
682 | } |
683 | in6p = sotoin6pcb(so); |
684 | in6p->in6p_cksum = -1; /* just to be sure */ |
685 | |
686 | KASSERT(solocked(so)); |
687 | return 0; |
688 | } |
689 | |
690 | static void |
691 | udp6_detach(struct socket *so) |
692 | { |
693 | struct in6pcb *in6p = sotoin6pcb(so); |
694 | int s; |
695 | |
696 | KASSERT(solocked(so)); |
697 | KASSERT(in6p != NULL); |
698 | |
699 | s = splsoftnet(); |
700 | in6_pcbdetach(in6p); |
701 | splx(s); |
702 | } |
703 | |
704 | static int |
705 | udp6_accept(struct socket *so, struct sockaddr *nam) |
706 | { |
707 | KASSERT(solocked(so)); |
708 | |
709 | return EOPNOTSUPP; |
710 | } |
711 | |
712 | static int |
713 | udp6_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) |
714 | { |
715 | struct in6pcb *in6p = sotoin6pcb(so); |
716 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; |
717 | int error = 0; |
718 | int s; |
719 | |
720 | KASSERT(solocked(so)); |
721 | KASSERT(in6p != NULL); |
722 | |
723 | s = splsoftnet(); |
724 | error = in6_pcbbind(in6p, sin6, l); |
725 | splx(s); |
726 | return error; |
727 | } |
728 | |
729 | static int |
730 | udp6_listen(struct socket *so, struct lwp *l) |
731 | { |
732 | KASSERT(solocked(so)); |
733 | |
734 | return EOPNOTSUPP; |
735 | } |
736 | |
737 | static int |
738 | udp6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) |
739 | { |
740 | struct in6pcb *in6p = sotoin6pcb(so); |
741 | int error = 0; |
742 | int s; |
743 | |
744 | KASSERT(solocked(so)); |
745 | KASSERT(in6p != NULL); |
746 | |
747 | if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) |
748 | return EISCONN; |
749 | s = splsoftnet(); |
750 | error = in6_pcbconnect(in6p, (struct sockaddr_in6 *)nam, l); |
751 | splx(s); |
752 | if (error == 0) |
753 | soisconnected(so); |
754 | |
755 | return error; |
756 | } |
757 | |
758 | static int |
759 | udp6_connect2(struct socket *so, struct socket *so2) |
760 | { |
761 | KASSERT(solocked(so)); |
762 | |
763 | return EOPNOTSUPP; |
764 | } |
765 | |
766 | static int |
767 | udp6_disconnect(struct socket *so) |
768 | { |
769 | struct in6pcb *in6p = sotoin6pcb(so); |
770 | int s; |
771 | |
772 | KASSERT(solocked(so)); |
773 | KASSERT(in6p != NULL); |
774 | |
775 | if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) |
776 | return ENOTCONN; |
777 | |
778 | s = splsoftnet(); |
779 | in6_pcbdisconnect(in6p); |
780 | memset((void *)&in6p->in6p_laddr, 0, sizeof(in6p->in6p_laddr)); |
781 | splx(s); |
782 | |
783 | so->so_state &= ~SS_ISCONNECTED; /* XXX */ |
784 | in6_pcbstate(in6p, IN6P_BOUND); /* XXX */ |
785 | return 0; |
786 | } |
787 | |
788 | static int |
789 | udp6_shutdown(struct socket *so) |
790 | { |
791 | int s; |
792 | |
793 | s = splsoftnet(); |
794 | socantsendmore(so); |
795 | splx(s); |
796 | |
797 | return 0; |
798 | } |
799 | |
800 | static int |
801 | udp6_abort(struct socket *so) |
802 | { |
803 | int s; |
804 | |
805 | KASSERT(solocked(so)); |
806 | KASSERT(sotoin6pcb(so) != NULL); |
807 | |
808 | s = splsoftnet(); |
809 | soisdisconnected(so); |
810 | in6_pcbdetach(sotoin6pcb(so)); |
811 | splx(s); |
812 | |
813 | return 0; |
814 | } |
815 | |
816 | static int |
817 | udp6_ioctl(struct socket *so, u_long cmd, void *addr6, struct ifnet *ifp) |
818 | { |
819 | /* |
820 | * MAPPED_ADDR implementation info: |
821 | * Mapped addr support for PRU_CONTROL is not necessary. |
822 | * Because typical user of PRU_CONTROL is such as ifconfig, |
823 | * and they don't associate any addr to their socket. Then |
824 | * socket family is only hint about the PRU_CONTROL'ed address |
825 | * family, especially when getting addrs from kernel. |
826 | * So AF_INET socket need to be used to control AF_INET addrs, |
827 | * and AF_INET6 socket for AF_INET6 addrs. |
828 | */ |
829 | return in6_control(so, cmd, addr6, ifp); |
830 | } |
831 | |
832 | static int |
833 | udp6_stat(struct socket *so, struct stat *ub) |
834 | { |
835 | KASSERT(solocked(so)); |
836 | |
837 | /* stat: don't bother with a blocksize */ |
838 | return 0; |
839 | } |
840 | |
841 | static int |
842 | udp6_peeraddr(struct socket *so, struct sockaddr *nam) |
843 | { |
844 | KASSERT(solocked(so)); |
845 | KASSERT(sotoin6pcb(so) != NULL); |
846 | KASSERT(nam != NULL); |
847 | |
848 | in6_setpeeraddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam); |
849 | return 0; |
850 | } |
851 | |
852 | static int |
853 | udp6_sockaddr(struct socket *so, struct sockaddr *nam) |
854 | { |
855 | KASSERT(solocked(so)); |
856 | KASSERT(sotoin6pcb(so) != NULL); |
857 | KASSERT(nam != NULL); |
858 | |
859 | in6_setsockaddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam); |
860 | return 0; |
861 | } |
862 | |
863 | static int |
864 | udp6_rcvd(struct socket *so, int flags, struct lwp *l) |
865 | { |
866 | KASSERT(solocked(so)); |
867 | |
868 | return EOPNOTSUPP; |
869 | } |
870 | |
871 | static int |
872 | udp6_recvoob(struct socket *so, struct mbuf *m, int flags) |
873 | { |
874 | KASSERT(solocked(so)); |
875 | |
876 | return EOPNOTSUPP; |
877 | } |
878 | |
879 | static int |
880 | udp6_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, |
881 | struct mbuf *control, struct lwp *l) |
882 | { |
883 | struct in6pcb *in6p = sotoin6pcb(so); |
884 | int error = 0; |
885 | int s; |
886 | |
887 | KASSERT(solocked(so)); |
888 | KASSERT(in6p != NULL); |
889 | KASSERT(m != NULL); |
890 | |
891 | s = splsoftnet(); |
892 | error = udp6_output(in6p, m, (struct sockaddr_in6 *)nam, control, l); |
893 | splx(s); |
894 | |
895 | return error; |
896 | } |
897 | |
898 | static int |
899 | udp6_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) |
900 | { |
901 | KASSERT(solocked(so)); |
902 | |
903 | if (m) |
904 | m_freem(m); |
905 | if (control) |
906 | m_freem(control); |
907 | |
908 | return EOPNOTSUPP; |
909 | } |
910 | |
911 | static int |
912 | udp6_purgeif(struct socket *so, struct ifnet *ifp) |
913 | { |
914 | |
915 | #ifndef NET_MPSAFE |
916 | mutex_enter(softnet_lock); |
917 | #endif |
918 | in6_pcbpurgeif0(&udbtable, ifp); |
919 | in6_purgeif(ifp); |
920 | in6_pcbpurgeif(&udbtable, ifp); |
921 | #ifndef NET_MPSAFE |
922 | mutex_exit(softnet_lock); |
923 | #endif |
924 | |
925 | return 0; |
926 | } |
927 | |
928 | static int |
929 | sysctl_net_inet6_udp6_stats(SYSCTLFN_ARGS) |
930 | { |
931 | |
932 | return (NETSTAT_SYSCTL(udp6stat_percpu, UDP6_NSTATS)); |
933 | } |
934 | |
935 | static void |
936 | sysctl_net_inet6_udp6_setup(struct sysctllog **clog) |
937 | { |
938 | |
939 | sysctl_createv(clog, 0, NULL, NULL, |
940 | CTLFLAG_PERMANENT, |
941 | CTLTYPE_NODE, "inet6" , NULL, |
942 | NULL, 0, NULL, 0, |
943 | CTL_NET, PF_INET6, CTL_EOL); |
944 | sysctl_createv(clog, 0, NULL, NULL, |
945 | CTLFLAG_PERMANENT, |
946 | CTLTYPE_NODE, "udp6" , |
947 | SYSCTL_DESCR("UDPv6 related settings" ), |
948 | NULL, 0, NULL, 0, |
949 | CTL_NET, PF_INET6, IPPROTO_UDP, CTL_EOL); |
950 | |
951 | sysctl_createv(clog, 0, NULL, NULL, |
952 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
953 | CTLTYPE_INT, "sendspace" , |
954 | SYSCTL_DESCR("Default UDP send buffer size" ), |
955 | NULL, 0, &udp6_sendspace, 0, |
956 | CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_SENDSPACE, |
957 | CTL_EOL); |
958 | sysctl_createv(clog, 0, NULL, NULL, |
959 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
960 | CTLTYPE_INT, "recvspace" , |
961 | SYSCTL_DESCR("Default UDP receive buffer size" ), |
962 | NULL, 0, &udp6_recvspace, 0, |
963 | CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_RECVSPACE, |
964 | CTL_EOL); |
965 | sysctl_createv(clog, 0, NULL, NULL, |
966 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
967 | CTLTYPE_INT, "do_loopback_cksum" , |
968 | SYSCTL_DESCR("Perform UDP checksum on loopback" ), |
969 | NULL, 0, &udp_do_loopback_cksum, 0, |
970 | CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_LOOPBACKCKSUM, |
971 | CTL_EOL); |
972 | sysctl_createv(clog, 0, NULL, NULL, |
973 | CTLFLAG_PERMANENT, |
974 | CTLTYPE_STRUCT, "pcblist" , |
975 | SYSCTL_DESCR("UDP protocol control block list" ), |
976 | sysctl_inpcblist, 0, &udbtable, 0, |
977 | CTL_NET, PF_INET6, IPPROTO_UDP, CTL_CREATE, |
978 | CTL_EOL); |
979 | sysctl_createv(clog, 0, NULL, NULL, |
980 | CTLFLAG_PERMANENT, |
981 | CTLTYPE_STRUCT, "stats" , |
982 | SYSCTL_DESCR("UDPv6 statistics" ), |
983 | sysctl_net_inet6_udp6_stats, 0, NULL, 0, |
984 | CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_STATS, |
985 | CTL_EOL); |
986 | } |
987 | |
988 | void |
989 | udp6_statinc(u_int stat) |
990 | { |
991 | |
992 | KASSERT(stat < UDP6_NSTATS); |
993 | UDP6_STATINC(stat); |
994 | } |
995 | |
996 | PR_WRAP_USRREQS(udp6) |
997 | #define udp6_attach udp6_attach_wrapper |
998 | #define udp6_detach udp6_detach_wrapper |
999 | #define udp6_accept udp6_accept_wrapper |
1000 | #define udp6_bind udp6_bind_wrapper |
1001 | #define udp6_listen udp6_listen_wrapper |
1002 | #define udp6_connect udp6_connect_wrapper |
1003 | #define udp6_connect2 udp6_connect2_wrapper |
1004 | #define udp6_disconnect udp6_disconnect_wrapper |
1005 | #define udp6_shutdown udp6_shutdown_wrapper |
1006 | #define udp6_abort udp6_abort_wrapper |
1007 | #define udp6_ioctl udp6_ioctl_wrapper |
1008 | #define udp6_stat udp6_stat_wrapper |
1009 | #define udp6_peeraddr udp6_peeraddr_wrapper |
1010 | #define udp6_sockaddr udp6_sockaddr_wrapper |
1011 | #define udp6_rcvd udp6_rcvd_wrapper |
1012 | #define udp6_recvoob udp6_recvoob_wrapper |
1013 | #define udp6_send udp6_send_wrapper |
1014 | #define udp6_sendoob udp6_sendoob_wrapper |
1015 | #define udp6_purgeif udp6_purgeif_wrapper |
1016 | |
1017 | const struct pr_usrreqs udp6_usrreqs = { |
1018 | .pr_attach = udp6_attach, |
1019 | .pr_detach = udp6_detach, |
1020 | .pr_accept = udp6_accept, |
1021 | .pr_bind = udp6_bind, |
1022 | .pr_listen = udp6_listen, |
1023 | .pr_connect = udp6_connect, |
1024 | .pr_connect2 = udp6_connect2, |
1025 | .pr_disconnect = udp6_disconnect, |
1026 | .pr_shutdown = udp6_shutdown, |
1027 | .pr_abort = udp6_abort, |
1028 | .pr_ioctl = udp6_ioctl, |
1029 | .pr_stat = udp6_stat, |
1030 | .pr_peeraddr = udp6_peeraddr, |
1031 | .pr_sockaddr = udp6_sockaddr, |
1032 | .pr_rcvd = udp6_rcvd, |
1033 | .pr_recvoob = udp6_recvoob, |
1034 | .pr_send = udp6_send, |
1035 | .pr_sendoob = udp6_sendoob, |
1036 | .pr_purgeif = udp6_purgeif, |
1037 | }; |
1038 | |