Annotation of src/sys/netinet/udp_usrreq.c, Revision 1.225
1.225 ! ozaki-r 1: /* $NetBSD: udp_usrreq.c,v 1.224 2016/02/15 14:59:03 rtr Exp $ */
1.48 itojun 2:
3: /*
4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5: * All rights reserved.
1.94 itojun 6: *
1.48 itojun 7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. Neither the name of the project nor the names of its contributors
16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
1.94 itojun 18: *
1.48 itojun 19: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
1.14 cgd 31:
1.1 cgd 32: /*
1.44 thorpej 33: * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
1.13 mycroft 34: * The Regents of the University of California. All rights reserved.
1.1 cgd 35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
1.104 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 45: * may be used to endorse or promote products derived from this software
46: * without specific prior written permission.
47: *
48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58: * SUCH DAMAGE.
59: *
1.44 thorpej 60: * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
1.1 cgd 61: */
1.91 lukem 62:
1.198 rmind 63: /*
64: * UDP protocol implementation.
65: * Per RFC 768, August, 1980.
66: */
67:
1.91 lukem 68: #include <sys/cdefs.h>
1.225 ! ozaki-r 69: __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.224 2016/02/15 14:59:03 rtr Exp $");
1.50 thorpej 70:
1.222 pooka 71: #ifdef _KERNEL_OPT
1.77 soda 72: #include "opt_inet.h"
1.174 christos 73: #include "opt_compat_netbsd.h"
1.50 thorpej 74: #include "opt_ipsec.h"
1.78 thorpej 75: #include "opt_inet_csum.h"
1.64 ws 76: #include "opt_ipkdb.h"
1.101 martin 77: #include "opt_mbuftrace.h"
1.222 pooka 78: #endif
1.1 cgd 79:
1.5 mycroft 80: #include <sys/param.h>
81: #include <sys/mbuf.h>
1.192 pooka 82: #include <sys/once.h>
1.5 mycroft 83: #include <sys/protosw.h>
84: #include <sys/socket.h>
85: #include <sys/socketvar.h>
1.27 christos 86: #include <sys/systm.h>
87: #include <sys/proc.h>
1.53 itojun 88: #include <sys/domain.h>
1.27 christos 89: #include <sys/sysctl.h>
1.1 cgd 90:
1.5 mycroft 91: #include <net/if.h>
1.1 cgd 92:
1.5 mycroft 93: #include <netinet/in.h>
94: #include <netinet/in_systm.h>
1.15 cgd 95: #include <netinet/in_var.h>
1.5 mycroft 96: #include <netinet/ip.h>
97: #include <netinet/in_pcb.h>
98: #include <netinet/ip_var.h>
99: #include <netinet/ip_icmp.h>
100: #include <netinet/udp.h>
101: #include <netinet/udp_var.h>
1.166 thorpej 102: #include <netinet/udp_private.h>
1.1 cgd 103:
1.53 itojun 104: #ifdef INET6
105: #include <netinet/ip6.h>
106: #include <netinet/icmp6.h>
107: #include <netinet6/ip6_var.h>
1.167 thorpej 108: #include <netinet6/ip6_private.h>
1.53 itojun 109: #include <netinet6/in6_pcb.h>
110: #include <netinet6/udp6_var.h>
1.168 thorpej 111: #include <netinet6/udp6_private.h>
1.53 itojun 112: #endif
113:
114: #ifndef INET6
115: /* always need ip6.h for IP6_EXTHDR_GET */
116: #include <netinet/ip6.h>
117: #endif
118:
1.190 christos 119: #ifdef IPSEC
1.105 jonathan 120: #include <netipsec/ipsec.h>
1.169 thorpej 121: #include <netipsec/ipsec_var.h>
122: #include <netipsec/ipsec_private.h>
1.147 christos 123: #include <netipsec/esp.h>
1.105 jonathan 124: #ifdef INET6
125: #include <netipsec/ipsec6.h>
126: #endif
1.190 christos 127: #endif /* IPSEC */
1.105 jonathan 128:
1.174 christos 129: #ifdef COMPAT_50
130: #include <compat/sys/socket.h>
131: #endif
132:
1.64 ws 133: #ifdef IPKDB
134: #include <ipkdb/ipkdb.h>
135: #endif
136:
1.8 mycroft 137: int udpcksum = 1;
1.141 yamt 138: int udp_do_loopback_cksum = 0;
1.93 matt 139:
140: struct inpcbtable udbtable;
1.164 thorpej 141:
1.166 thorpej 142: percpu_t *udpstat_percpu;
1.8 mycroft 143:
1.72 itojun 144: #ifdef INET
1.190 christos 145: #ifdef IPSEC
1.144 manu 146: static int udp4_espinudp (struct mbuf **, int, struct sockaddr *,
1.130 manu 147: struct socket *);
1.189 christos 148: #endif
1.119 matt 149: static void udp4_sendup (struct mbuf *, int, struct sockaddr *,
150: struct socket *);
151: static int udp4_realinput (struct sockaddr_in *, struct sockaddr_in *,
1.144 manu 152: struct mbuf **, int);
1.129 yamt 153: static int udp4_input_checksum(struct mbuf *, const struct udphdr *, int, int);
1.72 itojun 154: #endif
155: #ifdef INET
1.119 matt 156: static void udp_notify (struct inpcb *, int);
1.72 itojun 157: #endif
1.7 mycroft 158:
1.26 mycroft 159: #ifndef UDBHASHSIZE
160: #define UDBHASHSIZE 128
161: #endif
162: int udbhashsize = UDBHASHSIZE;
163:
1.196 rmind 164: /*
165: * For send - really max datagram size; for receive - 40 1K datagrams.
166: */
167: static int udp_sendspace = 9216;
168: static int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
169:
1.98 matt 170: #ifdef MBUFTRACE
1.150 dogcow 171: struct mowner udp_mowner = MOWNER_INIT("udp", "");
172: struct mowner udp_rx_mowner = MOWNER_INIT("udp", "rx");
173: struct mowner udp_tx_mowner = MOWNER_INIT("udp", "tx");
1.98 matt 174: #endif
175:
1.78 thorpej 176: #ifdef UDP_CSUM_COUNTERS
177: #include <sys/device.h>
178:
1.140 yamt 179: #if defined(INET)
1.78 thorpej 180: struct evcnt udp_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
181: NULL, "udp", "hwcsum bad");
182: struct evcnt udp_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
183: NULL, "udp", "hwcsum ok");
184: struct evcnt udp_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
185: NULL, "udp", "hwcsum data");
186: struct evcnt udp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
187: NULL, "udp", "swcsum");
188:
1.120 matt 189: EVCNT_ATTACH_STATIC(udp_hwcsum_bad);
190: EVCNT_ATTACH_STATIC(udp_hwcsum_ok);
191: EVCNT_ATTACH_STATIC(udp_hwcsum_data);
192: EVCNT_ATTACH_STATIC(udp_swcsum);
1.140 yamt 193: #endif /* defined(INET) */
194:
195: #define UDP_CSUM_COUNTER_INCR(ev) (ev)->ev_count++
1.78 thorpej 196: #else
197: #define UDP_CSUM_COUNTER_INCR(ev) /* nothing */
198: #endif /* UDP_CSUM_COUNTERS */
199:
1.179 pooka 200: static void sysctl_net_inet_udp_setup(struct sysctllog **);
201:
1.192 pooka 202: static int
203: do_udpinit(void)
1.1 cgd 204: {
1.18 mycroft 205:
1.35 mycroft 206: in_pcbinit(&udbtable, udbhashsize, udbhashsize);
1.193 pooka 207: udpstat_percpu = percpu_alloc(sizeof(uint64_t) * UDP_NSTATS);
1.78 thorpej 208:
1.98 matt 209: MOWNER_ATTACH(&udp_tx_mowner);
210: MOWNER_ATTACH(&udp_rx_mowner);
211: MOWNER_ATTACH(&udp_mowner);
1.166 thorpej 212:
1.192 pooka 213: return 0;
214: }
215:
216: void
217: udp_init_common(void)
218: {
219: static ONCE_DECL(doudpinit);
220:
221: RUN_ONCE(&doudpinit, do_udpinit);
222: }
223:
224: void
225: udp_init(void)
226: {
227:
228: sysctl_net_inet_udp_setup(NULL);
229:
230: udp_init_common();
1.1 cgd 231: }
232:
1.129 yamt 233: /*
234: * Checksum extended UDP header and data.
235: */
236:
237: int
238: udp_input_checksum(int af, struct mbuf *m, const struct udphdr *uh,
239: int iphlen, int len)
240: {
241:
242: switch (af) {
1.72 itojun 243: #ifdef INET
1.129 yamt 244: case AF_INET:
245: return udp4_input_checksum(m, uh, iphlen, len);
246: #endif
247: #ifdef INET6
248: case AF_INET6:
249: return udp6_input_checksum(m, uh, iphlen, len);
250: #endif
251: }
252: #ifdef DIAGNOSTIC
253: panic("udp_input_checksum: unknown af %d", af);
254: #endif
255: /* NOTREACHED */
256: return -1;
257: }
258:
259: #ifdef INET
260:
261: /*
262: * Checksum extended UDP header and data.
263: */
264:
265: static int
266: udp4_input_checksum(struct mbuf *m, const struct udphdr *uh,
267: int iphlen, int len)
268: {
269:
270: /*
271: * XXX it's better to record and check if this mbuf is
272: * already checked.
273: */
274:
275: if (uh->uh_sum == 0)
276: return 0;
277:
278: switch (m->m_pkthdr.csum_flags &
279: ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv4) |
280: M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
281: case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
282: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
283: goto badcsum;
284:
285: case M_CSUM_UDPv4|M_CSUM_DATA: {
286: u_int32_t hw_csum = m->m_pkthdr.csum_data;
287:
288: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data);
289: if (m->m_pkthdr.csum_flags & M_CSUM_NO_PSEUDOHDR) {
290: const struct ip *ip =
291: mtod(m, const struct ip *);
292:
293: hw_csum = in_cksum_phdr(ip->ip_src.s_addr,
294: ip->ip_dst.s_addr,
295: htons(hw_csum + len + IPPROTO_UDP));
296: }
297: if ((hw_csum ^ 0xffff) != 0)
298: goto badcsum;
299: break;
300: }
301:
302: case M_CSUM_UDPv4:
303: /* Checksum was okay. */
304: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok);
305: break;
306:
307: default:
308: /*
309: * Need to compute it ourselves. Maybe skip checksum
310: * on loopback interfaces.
311: */
312: if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
313: IFF_LOOPBACK) ||
314: udp_do_loopback_cksum)) {
315: UDP_CSUM_COUNTER_INCR(&udp_swcsum);
316: if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
317: goto badcsum;
318: }
319: break;
320: }
321:
322: return 0;
323:
324: badcsum:
1.166 thorpej 325: UDP_STATINC(UDP_STAT_BADSUM);
1.129 yamt 326: return -1;
327: }
328:
1.7 mycroft 329: void
1.27 christos 330: udp_input(struct mbuf *m, ...)
1.1 cgd 331: {
1.53 itojun 332: va_list ap;
333: struct sockaddr_in src, dst;
334: struct ip *ip;
335: struct udphdr *uh;
1.97 simonb 336: int iphlen;
1.53 itojun 337: int len;
338: int n;
1.96 itojun 339: u_int16_t ip_len;
1.53 itojun 340:
341: va_start(ap, m);
342: iphlen = va_arg(ap, int);
1.97 simonb 343: (void)va_arg(ap, int); /* ignore value, advance ap */
1.53 itojun 344: va_end(ap);
345:
1.98 matt 346: MCLAIM(m, &udp_rx_mowner);
1.166 thorpej 347: UDP_STATINC(UDP_STAT_IPACKETS);
1.53 itojun 348:
349: /*
350: * Get IP and UDP header together in first mbuf.
351: */
352: ip = mtod(m, struct ip *);
353: IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
354: if (uh == NULL) {
1.166 thorpej 355: UDP_STATINC(UDP_STAT_HDROPS);
1.53 itojun 356: return;
357: }
1.95 thorpej 358: KASSERT(UDP_HDR_ALIGNED_P(uh));
1.53 itojun 359:
1.57 itojun 360: /* destination port of 0 is illegal, based on RFC768. */
361: if (uh->uh_dport == 0)
362: goto bad;
363:
1.53 itojun 364: /*
365: * Make mbuf data length reflect UDP length.
366: * If not enough data to reflect UDP length, drop.
367: */
1.96 itojun 368: ip_len = ntohs(ip->ip_len);
1.53 itojun 369: len = ntohs((u_int16_t)uh->uh_ulen);
1.96 itojun 370: if (ip_len != iphlen + len) {
371: if (ip_len < iphlen + len || len < sizeof(struct udphdr)) {
1.166 thorpej 372: UDP_STATINC(UDP_STAT_BADLEN);
1.53 itojun 373: goto bad;
374: }
1.96 itojun 375: m_adj(m, iphlen + len - ip_len);
1.53 itojun 376: }
377:
378: /*
379: * Checksum extended UDP header and data.
380: */
1.129 yamt 381: if (udp4_input_checksum(m, uh, iphlen, len))
382: goto badcsum;
1.53 itojun 383:
384: /* construct source and dst sockaddrs. */
1.159 dyoung 385: sockaddr_in_init(&src, &ip->ip_src, uh->uh_sport);
386: sockaddr_in_init(&dst, &ip->ip_dst, uh->uh_dport);
1.53 itojun 387:
1.144 manu 388: if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
1.166 thorpej 389: UDP_STATINC(UDP_STAT_HDROPS);
1.144 manu 390: return;
391: }
1.188 christos 392: if (m == NULL) {
393: /*
394: * packet has been processed by ESP stuff -
395: * e.g. dropped NAT-T-keep-alive-packet ...
396: */
397: return;
398: }
399: ip = mtod(m, struct ip *);
1.53 itojun 400: #ifdef INET6
401: if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
402: struct sockaddr_in6 src6, dst6;
403:
1.175 cegger 404: memset(&src6, 0, sizeof(src6));
1.53 itojun 405: src6.sin6_family = AF_INET6;
406: src6.sin6_len = sizeof(struct sockaddr_in6);
1.224 rtr 407: in6_in_2_v4mapin6(&ip->ip_src, &src6.sin6_addr);
1.53 itojun 408: src6.sin6_port = uh->uh_sport;
1.175 cegger 409: memset(&dst6, 0, sizeof(dst6));
1.53 itojun 410: dst6.sin6_family = AF_INET6;
411: dst6.sin6_len = sizeof(struct sockaddr_in6);
1.224 rtr 412: in6_in_2_v4mapin6(&ip->ip_dst, &dst6.sin6_addr);
1.53 itojun 413: dst6.sin6_port = uh->uh_dport;
414:
415: n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen);
416: }
417: #endif
418:
419: if (n == 0) {
420: if (m->m_flags & (M_BCAST | M_MCAST)) {
1.166 thorpej 421: UDP_STATINC(UDP_STAT_NOPORTBCAST);
1.53 itojun 422: goto bad;
423: }
1.166 thorpej 424: UDP_STATINC(UDP_STAT_NOPORT);
1.64 ws 425: #ifdef IPKDB
1.53 itojun 426: if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
427: m, iphlen + sizeof(struct udphdr),
428: m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) {
429: /*
430: * It was a debugger connect packet,
431: * just drop it now
432: */
433: goto bad;
434: }
435: #endif
436: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
437: m = NULL;
438: }
439:
440: bad:
441: if (m)
442: m_freem(m);
1.78 thorpej 443: return;
444:
445: badcsum:
446: m_freem(m);
1.53 itojun 447: }
1.72 itojun 448: #endif
1.53 itojun 449:
1.72 itojun 450: #ifdef INET
1.53 itojun 451: static void
1.119 matt 452: udp4_sendup(struct mbuf *m, int off /* offset of data portion */,
453: struct sockaddr *src, struct socket *so)
1.53 itojun 454: {
455: struct mbuf *opts = NULL;
456: struct mbuf *n;
457: struct inpcb *inp = NULL;
458:
459: if (!so)
460: return;
461: switch (so->so_proto->pr_domain->dom_family) {
462: case AF_INET:
463: inp = sotoinpcb(so);
464: break;
465: #ifdef INET6
466: case AF_INET6:
467: break;
468: #endif
469: default:
470: return;
471: }
472:
1.190 christos 473: #if defined(IPSEC)
1.53 itojun 474: /* check AH/ESP integrity. */
1.199 christos 475: if (ipsec_used && so != NULL && ipsec4_in_reject_so(m, so)) {
1.169 thorpej 476: IPSEC_STATINC(IPSEC_STAT_IN_POLVIO);
1.162 dyoung 477: if ((n = m_copypacket(m, M_DONTWAIT)) != NULL)
1.110 itojun 478: icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT,
479: 0, 0);
1.53 itojun 480: return;
481: }
482: #endif /*IPSEC*/
483:
1.162 dyoung 484: if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
1.53 itojun 485: if (inp && (inp->inp_flags & INP_CONTROLOPTS
1.174 christos 486: #ifdef SO_OTIMESTAMP
487: || so->so_options & SO_OTIMESTAMP
488: #endif
1.53 itojun 489: || so->so_options & SO_TIMESTAMP)) {
490: struct ip *ip = mtod(n, struct ip *);
491: ip_savecontrol(inp, &opts, ip, n);
492: }
493:
494: m_adj(n, off);
495: if (sbappendaddr(&so->so_rcv, src, n,
496: opts) == 0) {
497: m_freem(n);
498: if (opts)
499: m_freem(opts);
1.124 darrenr 500: so->so_rcv.sb_overflowed++;
1.166 thorpej 501: UDP_STATINC(UDP_STAT_FULLSOCK);
1.53 itojun 502: } else
503: sorwakeup(so);
504: }
505: }
1.72 itojun 506: #endif
1.53 itojun 507:
1.72 itojun 508: #ifdef INET
1.53 itojun 509: static int
1.119 matt 510: udp4_realinput(struct sockaddr_in *src, struct sockaddr_in *dst,
1.144 manu 511: struct mbuf **mp, int off /* offset of udphdr */)
1.53 itojun 512: {
513: u_int16_t *sport, *dport;
514: int rcvcnt;
515: struct in_addr *src4, *dst4;
1.109 itojun 516: struct inpcb_hdr *inph;
1.53 itojun 517: struct inpcb *inp;
1.144 manu 518: struct mbuf *m = *mp;
1.53 itojun 519:
520: rcvcnt = 0;
521: off += sizeof(struct udphdr); /* now, offset of payload */
522:
523: if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
524: goto bad;
525:
526: src4 = &src->sin_addr;
527: sport = &src->sin_port;
528: dst4 = &dst->sin_addr;
529: dport = &dst->sin_port;
530:
1.73 itojun 531: if (IN_MULTICAST(dst4->s_addr) ||
1.53 itojun 532: in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
533: /*
534: * Deliver a multicast or broadcast datagram to *all* sockets
535: * for which the local and remote addresses and ports match
536: * those of the incoming datagram. This allows more than
537: * one process to receive multi/broadcasts on the same port.
538: * (This really ought to be done for unicast datagrams as
539: * well, but that would cause problems with existing
540: * applications that open both address-specific sockets and
541: * a wildcard socket listening to the same port -- they would
542: * end up receiving duplicates of every unicast datagram.
543: * Those applications open the multiple sockets to overcome an
544: * inadequacy of the UDP socket interface, but for backwards
545: * compatibility we avoid the problem here rather than
546: * fixing the interface. Maybe 4.5BSD will remedy this?)
547: */
548:
549: /*
1.92 itojun 550: * KAME note: traditionally we dropped udpiphdr from mbuf here.
1.71 itojun 551: * we need udpiphdr for IPsec processing so we do that later.
1.53 itojun 552: */
553: /*
554: * Locate pcb(s) for datagram.
555: */
1.191 christos 556: TAILQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
1.109 itojun 557: inp = (struct inpcb *)inph;
558: if (inp->inp_af != AF_INET)
559: continue;
560:
1.53 itojun 561: if (inp->inp_lport != *dport)
562: continue;
563: if (!in_nullhost(inp->inp_laddr)) {
564: if (!in_hosteq(inp->inp_laddr, *dst4))
565: continue;
566: }
567: if (!in_nullhost(inp->inp_faddr)) {
568: if (!in_hosteq(inp->inp_faddr, *src4) ||
569: inp->inp_fport != *sport)
570: continue;
571: }
572:
573: udp4_sendup(m, off, (struct sockaddr *)src,
574: inp->inp_socket);
575: rcvcnt++;
576:
577: /*
578: * Don't look for additional matches if this one does
579: * not have either the SO_REUSEPORT or SO_REUSEADDR
580: * socket options set. This heuristic avoids searching
581: * through all pcbs in the common case of a non-shared
582: * port. It assumes that an application will never
583: * clear these options after setting them.
584: */
585: if ((inp->inp_socket->so_options &
586: (SO_REUSEPORT|SO_REUSEADDR)) == 0)
587: break;
588: }
589: } else {
590: /*
591: * Locate pcb for datagram.
592: */
1.180 dyoung 593: inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4,
594: *dport, 0);
1.53 itojun 595: if (inp == 0) {
1.166 thorpej 596: UDP_STATINC(UDP_STAT_PCBHASHMISS);
1.53 itojun 597: inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
1.82 itojun 598: if (inp == 0)
1.53 itojun 599: return rcvcnt;
600: }
601:
1.190 christos 602: #ifdef IPSEC
1.130 manu 603: /* Handle ESP over UDP */
604: if (inp->inp_flags & INP_ESPINUDP_ALL) {
605: struct sockaddr *sa = (struct sockaddr *)src;
606:
1.144 manu 607: switch(udp4_espinudp(mp, off, sa, inp->inp_socket)) {
608: case -1: /* Error, m was freeed */
609: rcvcnt = -1;
610: goto bad;
611: break;
612:
613: case 1: /* ESP over UDP */
1.130 manu 614: rcvcnt++;
615: goto bad;
1.144 manu 616: break;
617:
618: case 0: /* plain UDP */
619: default: /* Unexpected */
620: /*
621: * Normal UDP processing will take place
622: * m may have changed.
623: */
624: m = *mp;
625: break;
1.130 manu 626: }
627: }
1.189 christos 628: #endif
1.130 manu 629:
1.178 minskim 630: /*
631: * Check the minimum TTL for socket.
632: */
633: if (mtod(m, struct ip *)->ip_ttl < inp->inp_ip_minttl)
634: goto bad;
635:
1.53 itojun 636: udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
637: rcvcnt++;
638: }
639:
640: bad:
641: return rcvcnt;
642: }
1.72 itojun 643: #endif
1.53 itojun 644:
1.72 itojun 645: #ifdef INET
1.1 cgd 646: /*
647: * Notify a udp user of an asynchronous error;
648: * just wake up so that he can collect error status.
649: */
1.7 mycroft 650: static void
1.119 matt 651: udp_notify(struct inpcb *inp, int errno)
1.1 cgd 652: {
653: inp->inp_socket->so_error = errno;
654: sorwakeup(inp->inp_socket);
655: sowwakeup(inp->inp_socket);
656: }
657:
1.27 christos 658: void *
1.157 dyoung 659: udp_ctlinput(int cmd, const struct sockaddr *sa, void *v)
1.1 cgd 660: {
1.66 augustss 661: struct ip *ip = v;
662: struct udphdr *uh;
1.119 matt 663: void (*notify)(struct inpcb *, int) = udp_notify;
1.21 mycroft 664: int errno;
1.1 cgd 665:
1.53 itojun 666: if (sa->sa_family != AF_INET
667: || sa->sa_len != sizeof(struct sockaddr_in))
1.51 itojun 668: return NULL;
1.20 mycroft 669: if ((unsigned)cmd >= PRC_NCMDS)
1.27 christos 670: return NULL;
1.20 mycroft 671: errno = inetctlerrmap[cmd];
1.18 mycroft 672: if (PRC_IS_REDIRECT(cmd))
1.19 mycroft 673: notify = in_rtchange, ip = 0;
1.18 mycroft 674: else if (cmd == PRC_HOSTDEAD)
1.19 mycroft 675: ip = 0;
1.23 cgd 676: else if (errno == 0)
1.27 christos 677: return NULL;
1.19 mycroft 678: if (ip) {
1.158 christos 679: uh = (struct udphdr *)((char *)ip + (ip->ip_hl << 2));
1.157 dyoung 680: in_pcbnotify(&udbtable, satocsin(sa)->sin_addr, uh->uh_dport,
1.34 mycroft 681: ip->ip_src, uh->uh_sport, errno, notify);
1.53 itojun 682:
683: /* XXX mapped address case */
1.19 mycroft 684: } else
1.157 dyoung 685: in_pcbnotifyall(&udbtable, satocsin(sa)->sin_addr, errno,
1.34 mycroft 686: notify);
1.27 christos 687: return NULL;
1.1 cgd 688: }
689:
1.7 mycroft 690: int
1.173 plunky 691: udp_ctloutput(int op, struct socket *so, struct sockopt *sopt)
1.130 manu 692: {
693: int s;
694: int error = 0;
695: struct inpcb *inp;
696: int family;
1.173 plunky 697: int optval;
1.130 manu 698:
699: family = so->so_proto->pr_domain->dom_family;
700:
701: s = splsoftnet();
702: switch (family) {
703: #ifdef INET
704: case PF_INET:
1.173 plunky 705: if (sopt->sopt_level != IPPROTO_UDP) {
706: error = ip_ctloutput(op, so, sopt);
1.130 manu 707: goto end;
708: }
709: break;
710: #endif
711: #ifdef INET6
712: case PF_INET6:
1.173 plunky 713: if (sopt->sopt_level != IPPROTO_UDP) {
714: error = ip6_ctloutput(op, so, sopt);
1.130 manu 715: goto end;
716: }
717: break;
718: #endif
719: default:
720: error = EAFNOSUPPORT;
721: goto end;
722: }
723:
724:
725: switch (op) {
726: case PRCO_SETOPT:
727: inp = sotoinpcb(so);
728:
1.173 plunky 729: switch (sopt->sopt_name) {
1.130 manu 730: case UDP_ENCAP:
1.173 plunky 731: error = sockopt_getint(sopt, &optval);
732: if (error)
1.153 yamt 733: break;
1.131 perry 734:
1.173 plunky 735: switch(optval) {
1.130 manu 736: case 0:
737: inp->inp_flags &= ~INP_ESPINUDP_ALL;
738: break;
739:
740: case UDP_ENCAP_ESPINUDP:
741: inp->inp_flags &= ~INP_ESPINUDP_ALL;
742: inp->inp_flags |= INP_ESPINUDP;
743: break;
1.131 perry 744:
1.130 manu 745: case UDP_ENCAP_ESPINUDP_NON_IKE:
746: inp->inp_flags &= ~INP_ESPINUDP_ALL;
747: inp->inp_flags |= INP_ESPINUDP_NON_IKE;
748: break;
749: default:
750: error = EINVAL;
751: break;
752: }
753: break;
1.183 christos 754:
1.130 manu 755: default:
756: error = ENOPROTOOPT;
757: break;
758: }
759: break;
760:
761: default:
762: error = EINVAL;
763: break;
1.131 perry 764: }
765:
1.130 manu 766: end:
767: splx(s);
768: return error;
769: }
1.131 perry 770:
1.130 manu 771:
772: int
1.223 riastrad 773: udp_output(struct mbuf *m, struct inpcb *inp)
1.27 christos 774: {
1.66 augustss 775: struct udpiphdr *ui;
1.125 thorpej 776: struct route *ro;
1.66 augustss 777: int len = m->m_pkthdr.len;
1.31 mycroft 778: int error = 0;
1.27 christos 779:
1.98 matt 780: MCLAIM(m, &udp_tx_mowner);
1.1 cgd 781:
782: /*
783: * Calculate data length and get a mbuf
784: * for UDP and IP headers.
785: */
1.13 mycroft 786: M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
787: if (m == 0) {
788: error = ENOBUFS;
1.39 thorpej 789: goto release;
790: }
791:
792: /*
793: * Compute the packet length of the IP header, and
794: * punt if the length looks bogus.
795: */
1.96 itojun 796: if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
1.39 thorpej 797: error = EMSGSIZE;
1.13 mycroft 798: goto release;
799: }
1.1 cgd 800:
801: /*
802: * Fill in mbuf with extended UDP header
803: * and addresses and length put into network format.
804: */
805: ui = mtod(m, struct udpiphdr *);
806: ui->ui_pr = IPPROTO_UDP;
807: ui->ui_src = inp->inp_laddr;
808: ui->ui_dst = inp->inp_faddr;
809: ui->ui_sport = inp->inp_lport;
810: ui->ui_dport = inp->inp_fport;
1.78 thorpej 811: ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr));
1.1 cgd 812:
1.125 thorpej 813: ro = &inp->inp_route;
814:
1.1 cgd 815: /*
1.78 thorpej 816: * Set up checksum and output datagram.
1.1 cgd 817: */
818: if (udpcksum) {
1.78 thorpej 819: /*
820: * XXX Cache pseudo-header checksum part for
821: * XXX "connected" UDP sockets.
822: */
823: ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
824: ui->ui_dst.s_addr, htons((u_int16_t)len +
825: sizeof(struct udphdr) + IPPROTO_UDP));
1.135 yamt 826: m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
1.78 thorpej 827: m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
828: } else
829: ui->ui_sum = 0;
1.96 itojun 830: ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
1.1 cgd 831: ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
832: ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
1.166 thorpej 833: UDP_STATINC(UDP_STAT_OPACKETS);
1.48 itojun 834:
1.125 thorpej 835: return (ip_output(m, inp->inp_options, ro,
1.12 mycroft 836: inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
1.107 itojun 837: inp->inp_moptions, inp->inp_socket));
1.1 cgd 838:
839: release:
840: m_freem(m);
841: return (error);
842: }
843:
1.196 rmind 844: static int
845: udp_attach(struct socket *so, int proto)
846: {
847: struct inpcb *inp;
848: int error;
849:
850: KASSERT(sotoinpcb(so) == NULL);
851:
852: /* Assign the lock (must happen even if we will error out). */
853: sosetlock(so);
854:
855: #ifdef MBUFTRACE
856: so->so_mowner = &udp_mowner;
857: so->so_rcv.sb_mowner = &udp_rx_mowner;
858: so->so_snd.sb_mowner = &udp_tx_mowner;
859: #endif
860: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
861: error = soreserve(so, udp_sendspace, udp_recvspace);
862: if (error) {
863: return error;
864: }
865: }
866:
867: error = in_pcballoc(so, &udbtable);
868: if (error) {
869: return error;
870: }
871: inp = sotoinpcb(so);
872: inp->inp_ip.ip_ttl = ip_defttl;
873: KASSERT(solocked(so));
874:
875: return error;
876: }
877:
878: static void
879: udp_detach(struct socket *so)
880: {
881: struct inpcb *inp;
882:
883: KASSERT(solocked(so));
884: inp = sotoinpcb(so);
885: KASSERT(inp != NULL);
886: in_pcbdetach(inp);
887: }
1.1 cgd 888:
1.195 rmind 889: static int
1.219 rtr 890: udp_accept(struct socket *so, struct sockaddr *nam)
1.208 rtr 891: {
892: KASSERT(solocked(so));
893:
894: panic("udp_accept");
1.210 rtr 895:
1.208 rtr 896: return EOPNOTSUPP;
897: }
898:
899: static int
1.218 rtr 900: udp_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
1.210 rtr 901: {
902: struct inpcb *inp = sotoinpcb(so);
1.218 rtr 903: struct sockaddr_in *sin = (struct sockaddr_in *)nam;
1.210 rtr 904: int error = 0;
905: int s;
906:
907: KASSERT(solocked(so));
908: KASSERT(inp != NULL);
909: KASSERT(nam != NULL);
910:
911: s = splsoftnet();
1.218 rtr 912: error = in_pcbbind(inp, sin, l);
1.210 rtr 913: splx(s);
914:
915: return error;
916: }
917:
918: static int
1.214 rtr 919: udp_listen(struct socket *so, struct lwp *l)
1.210 rtr 920: {
921: KASSERT(solocked(so));
922:
923: return EOPNOTSUPP;
924: }
925:
1.211 rtr 926: static int
1.221 rtr 927: udp_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
1.211 rtr 928: {
929: struct inpcb *inp = sotoinpcb(so);
930: int error = 0;
931: int s;
932:
933: KASSERT(solocked(so));
934: KASSERT(inp != NULL);
935: KASSERT(nam != NULL);
936:
937: s = splsoftnet();
1.221 rtr 938: error = in_pcbconnect(inp, (struct sockaddr_in *)nam, l);
1.211 rtr 939: if (! error)
940: soisconnected(so);
941: splx(s);
942: return error;
943: }
1.210 rtr 944:
945: static int
1.217 rtr 946: udp_connect2(struct socket *so, struct socket *so2)
947: {
948: KASSERT(solocked(so));
949:
950: return EOPNOTSUPP;
951: }
952:
953: static int
1.212 rtr 954: udp_disconnect(struct socket *so)
955: {
956: struct inpcb *inp = sotoinpcb(so);
957: int s;
958:
959: KASSERT(solocked(so));
960: KASSERT(inp != NULL);
961:
962: s = splsoftnet();
963: /*soisdisconnected(so);*/
964: so->so_state &= ~SS_ISCONNECTED; /* XXX */
965: in_pcbdisconnect(inp);
966: inp->inp_laddr = zeroin_addr; /* XXX */
967: in_pcbstate(inp, INP_BOUND); /* XXX */
968: splx(s);
969:
970: return 0;
971: }
972:
973: static int
974: udp_shutdown(struct socket *so)
975: {
976: int s;
977:
978: KASSERT(solocked(so));
979:
980: s = splsoftnet();
981: socantsendmore(so);
982: splx(s);
983:
984: return 0;
985: }
986:
987: static int
988: udp_abort(struct socket *so)
989: {
990: KASSERT(solocked(so));
991:
992: panic("udp_abort");
993:
994: return EOPNOTSUPP;
995: }
996:
997: static int
1.202 rtr 998: udp_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
1.200 rtr 999: {
1.202 rtr 1000: return in_control(so, cmd, nam, ifp);
1.200 rtr 1001: }
1002:
1003: static int
1.203 rtr 1004: udp_stat(struct socket *so, struct stat *ub)
1005: {
1.206 rtr 1006: KASSERT(solocked(so));
1007:
1.205 rtr 1008: /* stat: don't bother with a blocksize. */
1009: return 0;
1.203 rtr 1010: }
1011:
1012: static int
1.219 rtr 1013: udp_peeraddr(struct socket *so, struct sockaddr *nam)
1.207 rtr 1014: {
1.213 rtr 1015: int s;
1016:
1.207 rtr 1017: KASSERT(solocked(so));
1018: KASSERT(sotoinpcb(so) != NULL);
1019: KASSERT(nam != NULL);
1020:
1.213 rtr 1021: s = splsoftnet();
1.219 rtr 1022: in_setpeeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
1.213 rtr 1023: splx(s);
1024:
1.207 rtr 1025: return 0;
1026: }
1027:
1028: static int
1.219 rtr 1029: udp_sockaddr(struct socket *so, struct sockaddr *nam)
1.207 rtr 1030: {
1.213 rtr 1031: int s;
1032:
1.207 rtr 1033: KASSERT(solocked(so));
1034: KASSERT(sotoinpcb(so) != NULL);
1035: KASSERT(nam != NULL);
1036:
1.213 rtr 1037: s = splsoftnet();
1.219 rtr 1038: in_setsockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
1.213 rtr 1039: splx(s);
1040:
1.207 rtr 1041: return 0;
1042: }
1043:
1044: static int
1.216 rtr 1045: udp_rcvd(struct socket *so, int flags, struct lwp *l)
1046: {
1047: KASSERT(solocked(so));
1048:
1049: return EOPNOTSUPP;
1050: }
1051:
1052: static int
1.209 rtr 1053: udp_recvoob(struct socket *so, struct mbuf *m, int flags)
1054: {
1055: KASSERT(solocked(so));
1056:
1057: return EOPNOTSUPP;
1058: }
1059:
1060: static int
1.221 rtr 1061: udp_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
1.215 rtr 1062: struct mbuf *control, struct lwp *l)
1063: {
1064: struct inpcb *inp = sotoinpcb(so);
1065: int error = 0;
1066: struct in_addr laddr; /* XXX */
1067: int s;
1068:
1069: KASSERT(solocked(so));
1070: KASSERT(inp != NULL);
1071: KASSERT(m != NULL);
1072:
1073: if (control && control->m_len) {
1074: m_freem(control);
1075: m_freem(m);
1076: return EINVAL;
1077: }
1078:
1079: memset(&laddr, 0, sizeof laddr);
1080:
1081: s = splsoftnet();
1082: if (nam) {
1083: laddr = inp->inp_laddr; /* XXX */
1084: if ((so->so_state & SS_ISCONNECTED) != 0) {
1085: error = EISCONN;
1086: goto die;
1087: }
1.221 rtr 1088: error = in_pcbconnect(inp, (struct sockaddr_in *)nam, l);
1.215 rtr 1089: if (error)
1090: goto die;
1091: } else {
1092: if ((so->so_state & SS_ISCONNECTED) == 0) {
1093: error = ENOTCONN;
1094: goto die;
1095: }
1096: }
1097: error = udp_output(m, inp);
1098: m = NULL;
1099: if (nam) {
1100: in_pcbdisconnect(inp);
1101: inp->inp_laddr = laddr; /* XXX */
1102: in_pcbstate(inp, INP_BOUND); /* XXX */
1103: }
1104: die:
1105: if (m)
1106: m_freem(m);
1107:
1108: splx(s);
1109: return error;
1110: }
1111:
1112: static int
1.209 rtr 1113: udp_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
1114: {
1115: KASSERT(solocked(so));
1116:
1117: m_freem(m);
1118: m_freem(control);
1119:
1120: return EOPNOTSUPP;
1121: }
1122:
1123: static int
1.217 rtr 1124: udp_purgeif(struct socket *so, struct ifnet *ifp)
1125: {
1126: int s;
1127:
1128: s = splsoftnet();
1129: mutex_enter(softnet_lock);
1130: in_pcbpurgeif0(&udbtable, ifp);
1131: in_purgeif(ifp);
1132: in_pcbpurgeif(&udbtable, ifp);
1133: mutex_exit(softnet_lock);
1134: splx(s);
1135:
1136: return 0;
1137: }
1138:
1139: static int
1.166 thorpej 1140: sysctl_net_inet_udp_stats(SYSCTLFN_ARGS)
1141: {
1142:
1.172 thorpej 1143: return (NETSTAT_SYSCTL(udpstat_percpu, UDP_NSTATS));
1.166 thorpej 1144: }
1145:
1.13 mycroft 1146: /*
1147: * Sysctl for udp variables.
1148: */
1.179 pooka 1149: static void
1150: sysctl_net_inet_udp_setup(struct sysctllog **clog)
1.13 mycroft 1151: {
1.194 pooka 1152:
1.116 atatat 1153: sysctl_createv(clog, 0, NULL, NULL,
1154: CTLFLAG_PERMANENT,
1.114 atatat 1155: CTLTYPE_NODE, "inet", NULL,
1156: NULL, 0, NULL, 0,
1157: CTL_NET, PF_INET, CTL_EOL);
1.116 atatat 1158: sysctl_createv(clog, 0, NULL, NULL,
1159: CTLFLAG_PERMANENT,
1.122 atatat 1160: CTLTYPE_NODE, "udp",
1161: SYSCTL_DESCR("UDPv4 related settings"),
1.114 atatat 1162: NULL, 0, NULL, 0,
1163: CTL_NET, PF_INET, IPPROTO_UDP, CTL_EOL);
1164:
1.116 atatat 1165: sysctl_createv(clog, 0, NULL, NULL,
1166: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1167: CTLTYPE_INT, "checksum",
1.123 heas 1168: SYSCTL_DESCR("Compute UDP checksums"),
1.114 atatat 1169: NULL, 0, &udpcksum, 0,
1170: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_CHECKSUM,
1171: CTL_EOL);
1.116 atatat 1172: sysctl_createv(clog, 0, NULL, NULL,
1173: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1174: CTLTYPE_INT, "sendspace",
1175: SYSCTL_DESCR("Default UDP send buffer size"),
1.114 atatat 1176: NULL, 0, &udp_sendspace, 0,
1177: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_SENDSPACE,
1178: CTL_EOL);
1.116 atatat 1179: sysctl_createv(clog, 0, NULL, NULL,
1180: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1181: CTLTYPE_INT, "recvspace",
1182: SYSCTL_DESCR("Default UDP receive buffer size"),
1.114 atatat 1183: NULL, 0, &udp_recvspace, 0,
1184: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_RECVSPACE,
1185: CTL_EOL);
1.125 thorpej 1186: sysctl_createv(clog, 0, NULL, NULL,
1187: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1188: CTLTYPE_INT, "do_loopback_cksum",
1189: SYSCTL_DESCR("Perform UDP checksum on loopback"),
1190: NULL, 0, &udp_do_loopback_cksum, 0,
1191: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_LOOPBACKCKSUM,
1192: CTL_EOL);
1.132 atatat 1193: sysctl_createv(clog, 0, NULL, NULL,
1194: CTLFLAG_PERMANENT,
1.134 atatat 1195: CTLTYPE_STRUCT, "pcblist",
1.132 atatat 1196: SYSCTL_DESCR("UDP protocol control block list"),
1197: sysctl_inpcblist, 0, &udbtable, 0,
1198: CTL_NET, PF_INET, IPPROTO_UDP, CTL_CREATE,
1199: CTL_EOL);
1.139 elad 1200: sysctl_createv(clog, 0, NULL, NULL,
1201: CTLFLAG_PERMANENT,
1202: CTLTYPE_STRUCT, "stats",
1203: SYSCTL_DESCR("UDP statistics"),
1.166 thorpej 1204: sysctl_net_inet_udp_stats, 0, NULL, 0,
1.139 elad 1205: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS,
1206: CTL_EOL);
1.1 cgd 1207: }
1.72 itojun 1208: #endif
1.130 manu 1209:
1.166 thorpej 1210: void
1211: udp_statinc(u_int stat)
1212: {
1213:
1214: KASSERT(stat < UDP_NSTATS);
1215: UDP_STATINC(stat);
1216: }
1217:
1.190 christos 1218: #if defined(INET) && defined(IPSEC)
1.130 manu 1219: /*
1220: * Returns:
1221: * 1 if the packet was processed
1222: * 0 if normal UDP processing should take place
1.144 manu 1223: * -1 if an error occurent and m was freed
1.130 manu 1224: */
1225: static int
1.154 yamt 1226: udp4_espinudp(struct mbuf **mp, int off, struct sockaddr *src,
1.151 christos 1227: struct socket *so)
1.130 manu 1228: {
1229: size_t len;
1.158 christos 1230: void *data;
1.130 manu 1231: struct inpcb *inp;
1232: size_t skip = 0;
1233: size_t minlen;
1234: size_t iphdrlen;
1235: struct ip *ip;
1.136 manu 1236: struct m_tag *tag;
1237: struct udphdr *udphdr;
1238: u_int16_t sport, dport;
1.144 manu 1239: struct mbuf *m = *mp;
1.130 manu 1240:
1.131 perry 1241: /*
1.130 manu 1242: * Collapse the mbuf chain if the first mbuf is too short
1243: * The longest case is: UDP + non ESP marker + ESP
1244: */
1245: minlen = off + sizeof(u_int64_t) + sizeof(struct esp);
1246: if (minlen > m->m_pkthdr.len)
1247: minlen = m->m_pkthdr.len;
1248:
1249: if (m->m_len < minlen) {
1.144 manu 1250: if ((*mp = m_pullup(m, minlen)) == NULL) {
1.130 manu 1251: printf("udp4_espinudp: m_pullup failed\n");
1.144 manu 1252: return -1;
1.130 manu 1253: }
1.144 manu 1254: m = *mp;
1.130 manu 1255: }
1256:
1.131 perry 1257: len = m->m_len - off;
1.158 christos 1258: data = mtod(m, char *) + off;
1.130 manu 1259: inp = sotoinpcb(so);
1260:
1261: /* Ignore keepalive packets */
1.158 christos 1262: if ((len == 1) && (*(unsigned char *)data == 0xff)) {
1.188 christos 1263: m_free(m);
1264: *mp = NULL; /* avoid any further processiong by caller ... */
1.130 manu 1265: return 1;
1266: }
1267:
1.131 perry 1268: /*
1269: * Check that the payload is long enough to hold
1.130 manu 1270: * an ESP header and compute the length of encapsulation
1.131 perry 1271: * header to remove
1.130 manu 1272: */
1273: if (inp->inp_flags & INP_ESPINUDP) {
1274: u_int32_t *st = (u_int32_t *)data;
1275:
1276: if ((len <= sizeof(struct esp)) || (*st == 0))
1277: return 0; /* Normal UDP processing */
1278:
1279: skip = sizeof(struct udphdr);
1280: }
1281:
1282: if (inp->inp_flags & INP_ESPINUDP_NON_IKE) {
1.142 kleink 1283: u_int32_t *st = (u_int32_t *)data;
1.130 manu 1284:
1285: if ((len <= sizeof(u_int64_t) + sizeof(struct esp))
1.142 kleink 1286: || ((st[0] | st[1]) != 0))
1.130 manu 1287: return 0; /* Normal UDP processing */
1.131 perry 1288:
1.130 manu 1289: skip = sizeof(struct udphdr) + sizeof(u_int64_t);
1290: }
1291:
1292: /*
1.136 manu 1293: * Get the UDP ports. They are handled in network
1294: * order everywhere in IPSEC_NAT_T code.
1295: */
1.158 christos 1296: udphdr = (struct udphdr *)((char *)data - skip);
1.136 manu 1297: sport = udphdr->uh_sport;
1298: dport = udphdr->uh_dport;
1299:
1300: /*
1.130 manu 1301: * Remove the UDP header (and possibly the non ESP marker)
1302: * IP header lendth is iphdrlen
1.131 perry 1303: * Before:
1.130 manu 1304: * <--- off --->
1305: * +----+------+-----+
1306: * | IP | UDP | ESP |
1307: * +----+------+-----+
1308: * <-skip->
1309: * After:
1310: * +----+-----+
1311: * | IP | ESP |
1312: * +----+-----+
1313: * <-skip->
1314: */
1315: iphdrlen = off - sizeof(struct udphdr);
1.158 christos 1316: memmove(mtod(m, char *) + skip, mtod(m, void *), iphdrlen);
1.130 manu 1317: m_adj(m, skip);
1318:
1319: ip = mtod(m, struct ip *);
1320: ip->ip_len = htons(ntohs(ip->ip_len) - skip);
1321: ip->ip_p = IPPROTO_ESP;
1322:
1323: /*
1.188 christos 1324: * We have modified the packet - it is now ESP, so we should not
1325: * return to UDP processing ...
1326: *
1.136 manu 1327: * Add a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember
1328: * the source UDP port. This is required if we want
1329: * to select the right SPD for multiple hosts behind
1330: * same NAT
1331: */
1.137 manu 1332: if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
1333: sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {
1334: printf("udp4_espinudp: m_tag_get failed\n");
1.188 christos 1335: m_freem(m);
1336: return -1;
1.137 manu 1337: }
1.136 manu 1338: ((u_int16_t *)(tag + 1))[0] = sport;
1339: ((u_int16_t *)(tag + 1))[1] = dport;
1.188 christos 1340: m_tag_prepend(m, tag);
1.136 manu 1341:
1.190 christos 1342: #ifdef IPSEC
1.199 christos 1343: if (ipsec_used)
1344: ipsec4_common_input(m, iphdrlen, IPPROTO_ESP);
1345: /* XXX: else */
1.147 christos 1346: #else
1.188 christos 1347: esp4_input(m, iphdrlen);
1.147 christos 1348: #endif
1.130 manu 1349:
1.185 liamjfoy 1350: /* We handled it, it shouldn't be handled by UDP */
1.188 christos 1351: *mp = NULL; /* avoid free by caller ... */
1.130 manu 1352: return 1;
1353: }
1354: #endif
1.195 rmind 1355:
1.197 rmind 1356: PR_WRAP_USRREQS(udp)
1357: #define udp_attach udp_attach_wrapper
1358: #define udp_detach udp_detach_wrapper
1.208 rtr 1359: #define udp_accept udp_accept_wrapper
1.210 rtr 1360: #define udp_bind udp_bind_wrapper
1361: #define udp_listen udp_listen_wrapper
1.211 rtr 1362: #define udp_connect udp_connect_wrapper
1.217 rtr 1363: #define udp_connect2 udp_connect2_wrapper
1.212 rtr 1364: #define udp_disconnect udp_disconnect_wrapper
1365: #define udp_shutdown udp_shutdown_wrapper
1366: #define udp_abort udp_abort_wrapper
1.200 rtr 1367: #define udp_ioctl udp_ioctl_wrapper
1.203 rtr 1368: #define udp_stat udp_stat_wrapper
1.207 rtr 1369: #define udp_peeraddr udp_peeraddr_wrapper
1370: #define udp_sockaddr udp_sockaddr_wrapper
1.216 rtr 1371: #define udp_rcvd udp_rcvd_wrapper
1.209 rtr 1372: #define udp_recvoob udp_recvoob_wrapper
1.215 rtr 1373: #define udp_send udp_send_wrapper
1.209 rtr 1374: #define udp_sendoob udp_sendoob_wrapper
1.217 rtr 1375: #define udp_purgeif udp_purgeif_wrapper
1.195 rmind 1376:
1377: const struct pr_usrreqs udp_usrreqs = {
1.196 rmind 1378: .pr_attach = udp_attach,
1379: .pr_detach = udp_detach,
1.208 rtr 1380: .pr_accept = udp_accept,
1.210 rtr 1381: .pr_bind = udp_bind,
1382: .pr_listen = udp_listen,
1.211 rtr 1383: .pr_connect = udp_connect,
1.217 rtr 1384: .pr_connect2 = udp_connect2,
1.212 rtr 1385: .pr_disconnect = udp_disconnect,
1386: .pr_shutdown = udp_shutdown,
1387: .pr_abort = udp_abort,
1.200 rtr 1388: .pr_ioctl = udp_ioctl,
1.203 rtr 1389: .pr_stat = udp_stat,
1.207 rtr 1390: .pr_peeraddr = udp_peeraddr,
1391: .pr_sockaddr = udp_sockaddr,
1.216 rtr 1392: .pr_rcvd = udp_rcvd,
1.209 rtr 1393: .pr_recvoob = udp_recvoob,
1.215 rtr 1394: .pr_send = udp_send,
1.209 rtr 1395: .pr_sendoob = udp_sendoob,
1.217 rtr 1396: .pr_purgeif = udp_purgeif,
1.195 rmind 1397: };
CVSweb <webmaster@jp.NetBSD.org>