Annotation of src/sys/netinet/udp_usrreq.c, Revision 1.134.2.6
1.134.2.6! riz 1: /* $NetBSD: udp_usrreq.c,v 1.134.2.5 2005/09/08 21:10:24 tron 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:
63: #include <sys/cdefs.h>
1.134.2.6! riz 64: __KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.134.2.5 2005/09/08 21:10:24 tron Exp $");
1.50 thorpej 65:
1.77 soda 66: #include "opt_inet.h"
1.50 thorpej 67: #include "opt_ipsec.h"
1.78 thorpej 68: #include "opt_inet_csum.h"
1.64 ws 69: #include "opt_ipkdb.h"
1.101 martin 70: #include "opt_mbuftrace.h"
1.1 cgd 71:
1.5 mycroft 72: #include <sys/param.h>
73: #include <sys/malloc.h>
74: #include <sys/mbuf.h>
75: #include <sys/protosw.h>
76: #include <sys/socket.h>
77: #include <sys/socketvar.h>
1.13 mycroft 78: #include <sys/errno.h>
1.5 mycroft 79: #include <sys/stat.h>
1.27 christos 80: #include <sys/systm.h>
81: #include <sys/proc.h>
1.53 itojun 82: #include <sys/domain.h>
1.27 christos 83: #include <sys/sysctl.h>
1.1 cgd 84:
1.5 mycroft 85: #include <net/if.h>
86: #include <net/route.h>
1.1 cgd 87:
1.5 mycroft 88: #include <netinet/in.h>
89: #include <netinet/in_systm.h>
1.15 cgd 90: #include <netinet/in_var.h>
1.5 mycroft 91: #include <netinet/ip.h>
92: #include <netinet/in_pcb.h>
93: #include <netinet/ip_var.h>
94: #include <netinet/ip_icmp.h>
95: #include <netinet/udp.h>
96: #include <netinet/udp_var.h>
1.1 cgd 97:
1.130 manu 98: #ifdef IPSEC_NAT_T
99: #include <netinet6/ipsec.h>
100: #include <netinet6/esp.h>
101: #endif
102:
1.53 itojun 103: #ifdef INET6
104: #include <netinet/ip6.h>
105: #include <netinet/icmp6.h>
106: #include <netinet6/ip6_var.h>
107: #include <netinet6/in6_pcb.h>
108: #include <netinet6/udp6_var.h>
109: #endif
110:
111: #ifndef INET6
112: /* always need ip6.h for IP6_EXTHDR_GET */
113: #include <netinet/ip6.h>
114: #endif
115:
1.76 itojun 116: #include "faith.h"
117: #if defined(NFAITH) && NFAITH > 0
118: #include <net/if_faith.h>
119: #endif
120:
1.27 christos 121: #include <machine/stdarg.h>
122:
1.105 jonathan 123: #ifdef FAST_IPSEC
124: #include <netipsec/ipsec.h>
1.121 jonathan 125: #include <netipsec/ipsec_var.h> /* XXX ipsecstat namespace */
1.105 jonathan 126: #ifdef INET6
127: #include <netipsec/ipsec6.h>
128: #endif
129: #endif /* FAST_IPSEC*/
130:
1.48 itojun 131: #ifdef IPSEC
132: #include <netinet6/ipsec.h>
133: #include <netkey/key.h>
134: #endif /*IPSEC*/
135:
1.64 ws 136: #ifdef IPKDB
137: #include <ipkdb/ipkdb.h>
138: #endif
139:
1.8 mycroft 140: /*
141: * UDP protocol implementation.
142: * Per RFC 768, August, 1980.
143: */
144: #ifndef COMPAT_42
145: int udpcksum = 1;
146: #else
147: int udpcksum = 0; /* XXX */
148: #endif
1.93 matt 149:
150: struct inpcbtable udbtable;
151: struct udpstat udpstat;
1.8 mycroft 152:
1.72 itojun 153: #ifdef INET
1.130 manu 154: #ifdef IPSEC_NAT_T
1.134.2.6! riz 155: static int udp4_espinudp (struct mbuf **, int, struct sockaddr *,
1.130 manu 156: struct socket *);
157: #endif
1.119 matt 158: static void udp4_sendup (struct mbuf *, int, struct sockaddr *,
159: struct socket *);
160: static int udp4_realinput (struct sockaddr_in *, struct sockaddr_in *,
1.134.2.6! riz 161: struct mbuf **, int);
1.129 yamt 162: static int udp4_input_checksum(struct mbuf *, const struct udphdr *, int, int);
1.72 itojun 163: #endif
1.53 itojun 164: #ifdef INET6
1.119 matt 165: static void udp6_sendup (struct mbuf *, int, struct sockaddr *,
166: struct socket *);
167: static int udp6_realinput (int, struct sockaddr_in6 *,
168: struct sockaddr_in6 *, struct mbuf *, int);
1.129 yamt 169: static int udp6_input_checksum(struct mbuf *, const struct udphdr *, int, int);
1.53 itojun 170: #endif
1.72 itojun 171: #ifdef INET
1.119 matt 172: static void udp_notify (struct inpcb *, int);
1.72 itojun 173: #endif
1.7 mycroft 174:
1.26 mycroft 175: #ifndef UDBHASHSIZE
176: #define UDBHASHSIZE 128
177: #endif
178: int udbhashsize = UDBHASHSIZE;
179:
1.98 matt 180: #ifdef MBUFTRACE
181: struct mowner udp_mowner = { "udp" };
182: struct mowner udp_rx_mowner = { "udp", "rx" };
183: struct mowner udp_tx_mowner = { "udp", "tx" };
184: #endif
185:
1.78 thorpej 186: #ifdef UDP_CSUM_COUNTERS
187: #include <sys/device.h>
188:
189: struct evcnt udp_hwcsum_bad = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
190: NULL, "udp", "hwcsum bad");
191: struct evcnt udp_hwcsum_ok = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
192: NULL, "udp", "hwcsum ok");
193: struct evcnt udp_hwcsum_data = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
194: NULL, "udp", "hwcsum data");
195: struct evcnt udp_swcsum = EVCNT_INITIALIZER(EVCNT_TYPE_MISC,
196: NULL, "udp", "swcsum");
197:
198: #define UDP_CSUM_COUNTER_INCR(ev) (ev)->ev_count++
199:
1.120 matt 200: EVCNT_ATTACH_STATIC(udp_hwcsum_bad);
201: EVCNT_ATTACH_STATIC(udp_hwcsum_ok);
202: EVCNT_ATTACH_STATIC(udp_hwcsum_data);
203: EVCNT_ATTACH_STATIC(udp_swcsum);
204:
1.78 thorpej 205: #else
206:
207: #define UDP_CSUM_COUNTER_INCR(ev) /* nothing */
208:
209: #endif /* UDP_CSUM_COUNTERS */
210:
1.7 mycroft 211: void
1.119 matt 212: udp_init(void)
1.1 cgd 213: {
1.18 mycroft 214:
1.35 mycroft 215: in_pcbinit(&udbtable, udbhashsize, udbhashsize);
1.78 thorpej 216:
1.98 matt 217: MOWNER_ATTACH(&udp_tx_mowner);
218: MOWNER_ATTACH(&udp_rx_mowner);
219: MOWNER_ATTACH(&udp_mowner);
1.1 cgd 220: }
221:
1.129 yamt 222: /*
223: * Checksum extended UDP header and data.
224: */
225:
226: int
227: udp_input_checksum(int af, struct mbuf *m, const struct udphdr *uh,
228: int iphlen, int len)
229: {
230:
231: switch (af) {
1.72 itojun 232: #ifdef INET
1.129 yamt 233: case AF_INET:
234: return udp4_input_checksum(m, uh, iphlen, len);
235: #endif
236: #ifdef INET6
237: case AF_INET6:
238: return udp6_input_checksum(m, uh, iphlen, len);
239: #endif
240: }
241: #ifdef DIAGNOSTIC
242: panic("udp_input_checksum: unknown af %d", af);
243: #endif
244: /* NOTREACHED */
245: return -1;
246: }
247:
248: #ifdef INET
249:
250: /*
251: * Checksum extended UDP header and data.
252: */
253:
254: static int
255: udp4_input_checksum(struct mbuf *m, const struct udphdr *uh,
256: int iphlen, int len)
257: {
258:
259: /*
260: * XXX it's better to record and check if this mbuf is
261: * already checked.
262: */
263:
264: if (uh->uh_sum == 0)
265: return 0;
266:
267: switch (m->m_pkthdr.csum_flags &
268: ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_UDPv4) |
269: M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
270: case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
271: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
272: goto badcsum;
273:
274: case M_CSUM_UDPv4|M_CSUM_DATA: {
275: u_int32_t hw_csum = m->m_pkthdr.csum_data;
276:
277: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data);
278: if (m->m_pkthdr.csum_flags & M_CSUM_NO_PSEUDOHDR) {
279: const struct ip *ip =
280: mtod(m, const struct ip *);
281:
282: hw_csum = in_cksum_phdr(ip->ip_src.s_addr,
283: ip->ip_dst.s_addr,
284: htons(hw_csum + len + IPPROTO_UDP));
285: }
286: if ((hw_csum ^ 0xffff) != 0)
287: goto badcsum;
288: break;
289: }
290:
291: case M_CSUM_UDPv4:
292: /* Checksum was okay. */
293: UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok);
294: break;
295:
296: default:
297: /*
298: * Need to compute it ourselves. Maybe skip checksum
299: * on loopback interfaces.
300: */
301: if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
302: IFF_LOOPBACK) ||
303: udp_do_loopback_cksum)) {
304: UDP_CSUM_COUNTER_INCR(&udp_swcsum);
305: if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
306: goto badcsum;
307: }
308: break;
309: }
310:
311: return 0;
312:
313: badcsum:
314: udpstat.udps_badsum++;
315: return -1;
316: }
317:
1.7 mycroft 318: void
1.27 christos 319: udp_input(struct mbuf *m, ...)
1.1 cgd 320: {
1.53 itojun 321: va_list ap;
322: struct sockaddr_in src, dst;
323: struct ip *ip;
324: struct udphdr *uh;
1.97 simonb 325: int iphlen;
1.53 itojun 326: int len;
327: int n;
1.96 itojun 328: u_int16_t ip_len;
1.53 itojun 329:
330: va_start(ap, m);
331: iphlen = va_arg(ap, int);
1.97 simonb 332: (void)va_arg(ap, int); /* ignore value, advance ap */
1.53 itojun 333: va_end(ap);
334:
1.98 matt 335: MCLAIM(m, &udp_rx_mowner);
1.53 itojun 336: udpstat.udps_ipackets++;
337:
338: /*
339: * Get IP and UDP header together in first mbuf.
340: */
341: ip = mtod(m, struct ip *);
342: IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
343: if (uh == NULL) {
344: udpstat.udps_hdrops++;
345: return;
346: }
1.95 thorpej 347: KASSERT(UDP_HDR_ALIGNED_P(uh));
1.53 itojun 348:
1.57 itojun 349: /* destination port of 0 is illegal, based on RFC768. */
350: if (uh->uh_dport == 0)
351: goto bad;
352:
1.53 itojun 353: /*
354: * Make mbuf data length reflect UDP length.
355: * If not enough data to reflect UDP length, drop.
356: */
1.96 itojun 357: ip_len = ntohs(ip->ip_len);
1.53 itojun 358: len = ntohs((u_int16_t)uh->uh_ulen);
1.96 itojun 359: if (ip_len != iphlen + len) {
360: if (ip_len < iphlen + len || len < sizeof(struct udphdr)) {
1.53 itojun 361: udpstat.udps_badlen++;
362: goto bad;
363: }
1.96 itojun 364: m_adj(m, iphlen + len - ip_len);
1.53 itojun 365: }
366:
367: /*
368: * Checksum extended UDP header and data.
369: */
1.129 yamt 370: if (udp4_input_checksum(m, uh, iphlen, len))
371: goto badcsum;
1.53 itojun 372:
373: /* construct source and dst sockaddrs. */
374: bzero(&src, sizeof(src));
375: src.sin_family = AF_INET;
376: src.sin_len = sizeof(struct sockaddr_in);
377: bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr));
378: src.sin_port = uh->uh_sport;
379: bzero(&dst, sizeof(dst));
380: dst.sin_family = AF_INET;
381: dst.sin_len = sizeof(struct sockaddr_in);
382: bcopy(&ip->ip_dst, &dst.sin_addr, sizeof(dst.sin_addr));
383: dst.sin_port = uh->uh_dport;
384:
1.134.2.6! riz 385: if ((n = udp4_realinput(&src, &dst, &m, iphlen)) == -1) {
! 386: udpstat.udps_hdrops++;
! 387: return;
! 388: }
1.53 itojun 389: #ifdef INET6
390: if (IN_MULTICAST(ip->ip_dst.s_addr) || n == 0) {
391: struct sockaddr_in6 src6, dst6;
392:
393: bzero(&src6, sizeof(src6));
394: src6.sin6_family = AF_INET6;
395: src6.sin6_len = sizeof(struct sockaddr_in6);
396: src6.sin6_addr.s6_addr[10] = src6.sin6_addr.s6_addr[11] = 0xff;
397: bcopy(&ip->ip_src, &src6.sin6_addr.s6_addr[12],
398: sizeof(ip->ip_src));
399: src6.sin6_port = uh->uh_sport;
400: bzero(&dst6, sizeof(dst6));
401: dst6.sin6_family = AF_INET6;
402: dst6.sin6_len = sizeof(struct sockaddr_in6);
403: dst6.sin6_addr.s6_addr[10] = dst6.sin6_addr.s6_addr[11] = 0xff;
404: bcopy(&ip->ip_dst, &dst6.sin6_addr.s6_addr[12],
405: sizeof(ip->ip_dst));
406: dst6.sin6_port = uh->uh_dport;
407:
408: n += udp6_realinput(AF_INET, &src6, &dst6, m, iphlen);
409: }
410: #endif
411:
412: if (n == 0) {
413: if (m->m_flags & (M_BCAST | M_MCAST)) {
414: udpstat.udps_noportbcast++;
415: goto bad;
416: }
1.61 itojun 417: udpstat.udps_noport++;
1.64 ws 418: #ifdef IPKDB
1.53 itojun 419: if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport,
420: m, iphlen + sizeof(struct udphdr),
421: m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) {
422: /*
423: * It was a debugger connect packet,
424: * just drop it now
425: */
426: goto bad;
427: }
428: #endif
429: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
430: m = NULL;
431: }
432:
433: bad:
434: if (m)
435: m_freem(m);
1.78 thorpej 436: return;
437:
438: badcsum:
439: m_freem(m);
1.53 itojun 440: }
1.72 itojun 441: #endif
1.53 itojun 442:
443: #ifdef INET6
1.129 yamt 444: static int
445: udp6_input_checksum(struct mbuf *m, const struct udphdr *uh, int off, int len)
446: {
447:
448: if (__predict_false((m->m_flags & M_LOOP) && !udp_do_loopback_cksum)) {
449: goto good;
450: }
451: if (uh->uh_sum == 0) {
452: udp6stat.udp6s_nosum++;
453: goto bad;
454: }
455: if (in6_cksum(m, IPPROTO_UDP, off, len) != 0) {
456: udp6stat.udp6s_badsum++;
457: goto bad;
458: }
459:
460: good:
461: return 0;
462: bad:
463: return -1;
464: }
465:
1.53 itojun 466: int
1.119 matt 467: udp6_input(struct mbuf **mp, int *offp, int proto)
1.53 itojun 468: {
469: struct mbuf *m = *mp;
470: int off = *offp;
471: struct sockaddr_in6 src, dst;
472: struct ip6_hdr *ip6;
473: struct udphdr *uh;
474: u_int32_t plen, ulen;
475:
1.76 itojun 476: ip6 = mtod(m, struct ip6_hdr *);
477:
1.53 itojun 478: #if defined(NFAITH) && 0 < NFAITH
1.76 itojun 479: if (faithprefix(&ip6->ip6_dst)) {
480: /* send icmp6 host unreach? */
481: m_freem(m);
482: return IPPROTO_DONE;
1.53 itojun 483: }
484: #endif
485:
486: udp6stat.udp6s_ipackets++;
487:
488: /* check for jumbogram is done in ip6_input. we can trust pkthdr.len */
489: plen = m->m_pkthdr.len - off;
490: IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
491: if (uh == NULL) {
492: ip6stat.ip6s_tooshort++;
493: return IPPROTO_DONE;
494: }
1.95 thorpej 495: KASSERT(UDP_HDR_ALIGNED_P(uh));
1.53 itojun 496: ulen = ntohs((u_short)uh->uh_ulen);
1.69 itojun 497: /*
498: * RFC2675 section 4: jumbograms will have 0 in the UDP header field,
499: * iff payload length > 0xffff.
500: */
1.53 itojun 501: if (ulen == 0 && plen > 0xffff)
502: ulen = plen;
503:
504: if (plen != ulen) {
505: udp6stat.udp6s_badlen++;
1.54 itojun 506: goto bad;
507: }
508:
1.57 itojun 509: /* destination port of 0 is illegal, based on RFC768. */
510: if (uh->uh_dport == 0)
511: goto bad;
512:
1.54 itojun 513: /* Be proactive about malicious use of IPv4 mapped address */
514: if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
515: IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
516: /* XXX stat */
1.53 itojun 517: goto bad;
518: }
519:
520: /*
1.125 thorpej 521: * Checksum extended UDP header and data. Maybe skip checksum
522: * on loopback interfaces.
1.53 itojun 523: */
1.129 yamt 524: if (udp6_input_checksum(m, uh, off, ulen))
525: goto bad;
1.53 itojun 526:
527: /*
528: * Construct source and dst sockaddrs.
529: * Note that ifindex (s6_addr16[1]) is already filled.
530: */
531: bzero(&src, sizeof(src));
532: src.sin6_family = AF_INET6;
533: src.sin6_len = sizeof(struct sockaddr_in6);
1.69 itojun 534: /* KAME hack: recover scopeid */
535: (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif);
1.53 itojun 536: src.sin6_port = uh->uh_sport;
537: bzero(&dst, sizeof(dst));
538: dst.sin6_family = AF_INET6;
539: dst.sin6_len = sizeof(struct sockaddr_in6);
1.69 itojun 540: /* KAME hack: recover scopeid */
541: (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif);
1.53 itojun 542: dst.sin6_port = uh->uh_dport;
543:
544: if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) {
545: if (m->m_flags & M_MCAST) {
546: udp6stat.udp6s_noportmcast++;
547: goto bad;
548: }
1.61 itojun 549: udp6stat.udp6s_noport++;
1.53 itojun 550: icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
551: m = NULL;
552: }
553:
554: bad:
555: if (m)
556: m_freem(m);
557: return IPPROTO_DONE;
558: }
559: #endif
560:
1.72 itojun 561: #ifdef INET
1.53 itojun 562: static void
1.119 matt 563: udp4_sendup(struct mbuf *m, int off /* offset of data portion */,
564: struct sockaddr *src, struct socket *so)
1.53 itojun 565: {
566: struct mbuf *opts = NULL;
567: struct mbuf *n;
568: struct inpcb *inp = NULL;
569:
570: if (!so)
571: return;
572: switch (so->so_proto->pr_domain->dom_family) {
573: case AF_INET:
574: inp = sotoinpcb(so);
575: break;
576: #ifdef INET6
577: case AF_INET6:
578: break;
579: #endif
580: default:
581: return;
582: }
583:
1.105 jonathan 584: #if defined(IPSEC) || defined(FAST_IPSEC)
1.53 itojun 585: /* check AH/ESP integrity. */
586: if (so != NULL && ipsec4_in_reject_so(m, so)) {
587: ipsecstat.in_polvio++;
1.110 itojun 588: if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
589: icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_ADMIN_PROHIBIT,
590: 0, 0);
1.53 itojun 591: return;
592: }
593: #endif /*IPSEC*/
594:
595: if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
596: if (inp && (inp->inp_flags & INP_CONTROLOPTS
597: || so->so_options & SO_TIMESTAMP)) {
598: struct ip *ip = mtod(n, struct ip *);
599: ip_savecontrol(inp, &opts, ip, n);
600: }
601:
602: m_adj(n, off);
603: if (sbappendaddr(&so->so_rcv, src, n,
604: opts) == 0) {
605: m_freem(n);
606: if (opts)
607: m_freem(opts);
1.124 darrenr 608: so->so_rcv.sb_overflowed++;
1.81 enami 609: udpstat.udps_fullsock++;
1.53 itojun 610: } else
611: sorwakeup(so);
612: }
613: }
1.72 itojun 614: #endif
1.53 itojun 615:
616: #ifdef INET6
617: static void
1.119 matt 618: udp6_sendup(struct mbuf *m, int off /* offset of data portion */,
619: struct sockaddr *src, struct socket *so)
1.53 itojun 620: {
621: struct mbuf *opts = NULL;
622: struct mbuf *n;
623: struct in6pcb *in6p = NULL;
624:
625: if (!so)
626: return;
627: if (so->so_proto->pr_domain->dom_family != AF_INET6)
628: return;
629: in6p = sotoin6pcb(so);
630:
1.105 jonathan 631: #if defined(IPSEC) || defined(FAST_IPSEC)
1.53 itojun 632: /* check AH/ESP integrity. */
633: if (so != NULL && ipsec6_in_reject_so(m, so)) {
634: ipsec6stat.in_polvio++;
1.111 mycroft 635: if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
1.110 itojun 636: icmp6_error(n, ICMP6_DST_UNREACH,
637: ICMP6_DST_UNREACH_ADMIN, 0);
1.53 itojun 638: return;
639: }
640: #endif /*IPSEC*/
641:
642: if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
643: if (in6p && (in6p->in6p_flags & IN6P_CONTROLOPTS
644: || in6p->in6p_socket->so_options & SO_TIMESTAMP)) {
645: struct ip6_hdr *ip6 = mtod(n, struct ip6_hdr *);
646: ip6_savecontrol(in6p, &opts, ip6, n);
647: }
648:
649: m_adj(n, off);
650: if (sbappendaddr(&so->so_rcv, src, n, opts) == 0) {
651: m_freem(n);
652: if (opts)
653: m_freem(opts);
1.124 darrenr 654: so->so_rcv.sb_overflowed++;
1.53 itojun 655: udp6stat.udp6s_fullsock++;
656: } else
657: sorwakeup(so);
658: }
659: }
660: #endif
661:
1.72 itojun 662: #ifdef INET
1.53 itojun 663: static int
1.119 matt 664: udp4_realinput(struct sockaddr_in *src, struct sockaddr_in *dst,
1.134.2.6! riz 665: struct mbuf **mp, int off /* offset of udphdr */)
1.53 itojun 666: {
667: u_int16_t *sport, *dport;
668: int rcvcnt;
669: struct in_addr *src4, *dst4;
1.109 itojun 670: struct inpcb_hdr *inph;
1.53 itojun 671: struct inpcb *inp;
1.134.2.6! riz 672: struct mbuf *m = *mp;
1.53 itojun 673:
674: rcvcnt = 0;
675: off += sizeof(struct udphdr); /* now, offset of payload */
676:
677: if (src->sin_family != AF_INET || dst->sin_family != AF_INET)
678: goto bad;
679:
680: src4 = &src->sin_addr;
681: sport = &src->sin_port;
682: dst4 = &dst->sin_addr;
683: dport = &dst->sin_port;
684:
1.73 itojun 685: if (IN_MULTICAST(dst4->s_addr) ||
1.53 itojun 686: in_broadcast(*dst4, m->m_pkthdr.rcvif)) {
687: /*
688: * Deliver a multicast or broadcast datagram to *all* sockets
689: * for which the local and remote addresses and ports match
690: * those of the incoming datagram. This allows more than
691: * one process to receive multi/broadcasts on the same port.
692: * (This really ought to be done for unicast datagrams as
693: * well, but that would cause problems with existing
694: * applications that open both address-specific sockets and
695: * a wildcard socket listening to the same port -- they would
696: * end up receiving duplicates of every unicast datagram.
697: * Those applications open the multiple sockets to overcome an
698: * inadequacy of the UDP socket interface, but for backwards
699: * compatibility we avoid the problem here rather than
700: * fixing the interface. Maybe 4.5BSD will remedy this?)
701: */
702:
703: /*
1.92 itojun 704: * KAME note: traditionally we dropped udpiphdr from mbuf here.
1.71 itojun 705: * we need udpiphdr for IPsec processing so we do that later.
1.53 itojun 706: */
707: /*
708: * Locate pcb(s) for datagram.
709: */
1.109 itojun 710: CIRCLEQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
711: inp = (struct inpcb *)inph;
712: if (inp->inp_af != AF_INET)
713: continue;
714:
1.53 itojun 715: if (inp->inp_lport != *dport)
716: continue;
717: if (!in_nullhost(inp->inp_laddr)) {
718: if (!in_hosteq(inp->inp_laddr, *dst4))
719: continue;
720: }
721: if (!in_nullhost(inp->inp_faddr)) {
722: if (!in_hosteq(inp->inp_faddr, *src4) ||
723: inp->inp_fport != *sport)
724: continue;
725: }
726:
727: udp4_sendup(m, off, (struct sockaddr *)src,
728: inp->inp_socket);
729: rcvcnt++;
730:
731: /*
732: * Don't look for additional matches if this one does
733: * not have either the SO_REUSEPORT or SO_REUSEADDR
734: * socket options set. This heuristic avoids searching
735: * through all pcbs in the common case of a non-shared
736: * port. It assumes that an application will never
737: * clear these options after setting them.
738: */
739: if ((inp->inp_socket->so_options &
740: (SO_REUSEPORT|SO_REUSEADDR)) == 0)
741: break;
742: }
743: } else {
744: /*
745: * Locate pcb for datagram.
746: */
747: inp = in_pcblookup_connect(&udbtable, *src4, *sport, *dst4, *dport);
748: if (inp == 0) {
749: ++udpstat.udps_pcbhashmiss;
750: inp = in_pcblookup_bind(&udbtable, *dst4, *dport);
1.82 itojun 751: if (inp == 0)
1.53 itojun 752: return rcvcnt;
753: }
754:
1.130 manu 755: #ifdef IPSEC_NAT_T
756: /* Handle ESP over UDP */
757: if (inp->inp_flags & INP_ESPINUDP_ALL) {
758: struct sockaddr *sa = (struct sockaddr *)src;
759:
1.134.2.6! riz 760: switch(udp4_espinudp(mp, off, sa, inp->inp_socket)) {
! 761: case -1: /* Error, m was freeed */
! 762: rcvcnt = -1;
! 763: goto bad;
! 764: break;
! 765:
! 766: case 1: /* ESP over UDP */
1.130 manu 767: rcvcnt++;
768: goto bad;
1.134.2.6! riz 769: break;
1.130 manu 770:
1.134.2.6! riz 771: case 0: /* plain UDP */
! 772: default: /* Unexpected */
! 773: /*
! 774: * Normal UDP processing will take place
! 775: * m may have changed.
! 776: */
! 777: m = *mp;
! 778: break;
! 779: }
1.130 manu 780: }
781: #endif
782:
1.53 itojun 783: udp4_sendup(m, off, (struct sockaddr *)src, inp->inp_socket);
784: rcvcnt++;
785: }
786:
787: bad:
788: return rcvcnt;
789: }
1.72 itojun 790: #endif
1.53 itojun 791:
792: #ifdef INET6
793: static int
1.119 matt 794: udp6_realinput(int af, struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
795: struct mbuf *m, int off)
1.53 itojun 796: {
1.79 itojun 797: u_int16_t sport, dport;
1.53 itojun 798: int rcvcnt;
1.79 itojun 799: struct in6_addr src6, dst6;
800: const struct in_addr *dst4;
1.109 itojun 801: struct inpcb_hdr *inph;
1.53 itojun 802: struct in6pcb *in6p;
803:
804: rcvcnt = 0;
805: off += sizeof(struct udphdr); /* now, offset of payload */
806:
807: if (af != AF_INET && af != AF_INET6)
808: goto bad;
809: if (src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6)
810: goto bad;
811:
1.79 itojun 812: in6_embedscope(&src6, src, NULL, NULL);
813: sport = src->sin6_port;
814: in6_embedscope(&dst6, dst, NULL, NULL);
815: dport = dst->sin6_port;
1.88 itojun 816: dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr[12];
1.53 itojun 817:
1.79 itojun 818: if (IN6_IS_ADDR_MULTICAST(&dst6) ||
819: (af == AF_INET && IN_MULTICAST(dst4->s_addr))) {
1.53 itojun 820: /*
821: * Deliver a multicast or broadcast datagram to *all* sockets
822: * for which the local and remote addresses and ports match
823: * those of the incoming datagram. This allows more than
824: * one process to receive multi/broadcasts on the same port.
825: * (This really ought to be done for unicast datagrams as
826: * well, but that would cause problems with existing
827: * applications that open both address-specific sockets and
828: * a wildcard socket listening to the same port -- they would
829: * end up receiving duplicates of every unicast datagram.
830: * Those applications open the multiple sockets to overcome an
831: * inadequacy of the UDP socket interface, but for backwards
832: * compatibility we avoid the problem here rather than
833: * fixing the interface. Maybe 4.5BSD will remedy this?)
834: */
835:
836: /*
1.92 itojun 837: * KAME note: traditionally we dropped udpiphdr from mbuf here.
1.71 itojun 838: * we need udpiphdr for IPsec processing so we do that later.
1.53 itojun 839: */
840: /*
841: * Locate pcb(s) for datagram.
842: */
1.109 itojun 843: CIRCLEQ_FOREACH(inph, &udbtable.inpt_queue, inph_queue) {
844: in6p = (struct in6pcb *)inph;
845: if (in6p->in6p_af != AF_INET6)
846: continue;
847:
1.79 itojun 848: if (in6p->in6p_lport != dport)
1.53 itojun 849: continue;
850: if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
1.90 itojun 851: if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &dst6))
1.53 itojun 852: continue;
1.92 itojun 853: } else {
1.79 itojun 854: if (IN6_IS_ADDR_V4MAPPED(&dst6) &&
1.85 itojun 855: (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
1.55 itojun 856: continue;
857: }
1.53 itojun 858: if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
1.79 itojun 859: if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
860: &src6) || in6p->in6p_fport != sport)
1.53 itojun 861: continue;
1.92 itojun 862: } else {
1.79 itojun 863: if (IN6_IS_ADDR_V4MAPPED(&src6) &&
1.85 itojun 864: (in6p->in6p_flags & IN6P_IPV6_V6ONLY))
1.55 itojun 865: continue;
866: }
1.53 itojun 867:
868: udp6_sendup(m, off, (struct sockaddr *)src,
869: in6p->in6p_socket);
870: rcvcnt++;
871:
872: /*
873: * Don't look for additional matches if this one does
874: * not have either the SO_REUSEPORT or SO_REUSEADDR
875: * socket options set. This heuristic avoids searching
876: * through all pcbs in the common case of a non-shared
877: * port. It assumes that an application will never
878: * clear these options after setting them.
879: */
880: if ((in6p->in6p_socket->so_options &
881: (SO_REUSEPORT|SO_REUSEADDR)) == 0)
882: break;
883: }
884: } else {
885: /*
886: * Locate pcb for datagram.
887: */
1.109 itojun 888: in6p = in6_pcblookup_connect(&udbtable, &src6, sport,
1.79 itojun 889: &dst6, dport, 0);
1.53 itojun 890: if (in6p == 0) {
891: ++udpstat.udps_pcbhashmiss;
1.109 itojun 892: in6p = in6_pcblookup_bind(&udbtable, &dst6, dport, 0);
1.82 itojun 893: if (in6p == 0)
1.53 itojun 894: return rcvcnt;
895: }
896:
897: udp6_sendup(m, off, (struct sockaddr *)src, in6p->in6p_socket);
898: rcvcnt++;
899: }
900:
901: bad:
902: return rcvcnt;
903: }
904: #endif
1.1 cgd 905:
1.72 itojun 906: #ifdef INET
1.1 cgd 907: /*
908: * Notify a udp user of an asynchronous error;
909: * just wake up so that he can collect error status.
910: */
1.7 mycroft 911: static void
1.119 matt 912: udp_notify(struct inpcb *inp, int errno)
1.1 cgd 913: {
914: inp->inp_socket->so_error = errno;
915: sorwakeup(inp->inp_socket);
916: sowwakeup(inp->inp_socket);
917: }
918:
1.27 christos 919: void *
1.119 matt 920: udp_ctlinput(int cmd, struct sockaddr *sa, void *v)
1.1 cgd 921: {
1.66 augustss 922: struct ip *ip = v;
923: struct udphdr *uh;
1.119 matt 924: void (*notify)(struct inpcb *, int) = udp_notify;
1.21 mycroft 925: int errno;
1.1 cgd 926:
1.53 itojun 927: if (sa->sa_family != AF_INET
928: || sa->sa_len != sizeof(struct sockaddr_in))
1.51 itojun 929: return NULL;
1.20 mycroft 930: if ((unsigned)cmd >= PRC_NCMDS)
1.27 christos 931: return NULL;
1.20 mycroft 932: errno = inetctlerrmap[cmd];
1.18 mycroft 933: if (PRC_IS_REDIRECT(cmd))
1.19 mycroft 934: notify = in_rtchange, ip = 0;
1.18 mycroft 935: else if (cmd == PRC_HOSTDEAD)
1.19 mycroft 936: ip = 0;
1.23 cgd 937: else if (errno == 0)
1.27 christos 938: return NULL;
1.19 mycroft 939: if (ip) {
1.1 cgd 940: uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
1.34 mycroft 941: in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
942: ip->ip_src, uh->uh_sport, errno, notify);
1.53 itojun 943:
944: /* XXX mapped address case */
1.19 mycroft 945: } else
1.34 mycroft 946: in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno,
947: notify);
1.27 christos 948: return NULL;
1.1 cgd 949: }
950:
1.7 mycroft 951: int
1.131 perry 952: udp_ctloutput(op, so, level, optname, mp)
1.130 manu 953: int op;
954: struct socket *so;
955: int level, optname;
956: struct mbuf **mp;
957: {
958: int s;
959: int error = 0;
960: struct mbuf *m;
961: struct inpcb *inp;
962: int family;
963:
964: family = so->so_proto->pr_domain->dom_family;
965:
966: s = splsoftnet();
967: switch (family) {
968: #ifdef INET
969: case PF_INET:
970: if (level != IPPROTO_UDP) {
971: error = ip_ctloutput(op, so, level, optname, mp);
972: goto end;
973: }
974: break;
975: #endif
976: #ifdef INET6
977: case PF_INET6:
978: if (level != IPPROTO_UDP) {
979: error = ip6_ctloutput(op, so, level, optname, mp);
980: goto end;
981: }
982: break;
983: #endif
984: default:
985: error = EAFNOSUPPORT;
986: goto end;
987: break;
988: }
989:
990:
991: switch (op) {
992: case PRCO_SETOPT:
993: m = *mp;
994: inp = sotoinpcb(so);
995:
996: switch (optname) {
997: case UDP_ENCAP:
998: if (m == NULL || m->m_len < sizeof (int)) {
999: error = EINVAL;
1000: goto end;
1001: }
1.131 perry 1002:
1.130 manu 1003: switch(*mtod(m, int *)) {
1004: #ifdef IPSEC_NAT_T
1005: case 0:
1006: inp->inp_flags &= ~INP_ESPINUDP_ALL;
1007: break;
1008:
1009: case UDP_ENCAP_ESPINUDP:
1010: inp->inp_flags &= ~INP_ESPINUDP_ALL;
1011: inp->inp_flags |= INP_ESPINUDP;
1012: break;
1.131 perry 1013:
1.130 manu 1014: case UDP_ENCAP_ESPINUDP_NON_IKE:
1015: inp->inp_flags &= ~INP_ESPINUDP_ALL;
1016: inp->inp_flags |= INP_ESPINUDP_NON_IKE;
1017: break;
1018: #endif
1019: default:
1020: error = EINVAL;
1021: goto end;
1022: break;
1023: }
1024: break;
1025:
1026: default:
1027: error = ENOPROTOOPT;
1028: goto end;
1029: break;
1030: }
1031: break;
1032:
1033: default:
1034: error = EINVAL;
1035: goto end;
1036: break;
1.131 perry 1037: }
1038:
1.130 manu 1039: end:
1040: splx(s);
1041: return error;
1042: }
1.131 perry 1043:
1.130 manu 1044:
1045: int
1.27 christos 1046: udp_output(struct mbuf *m, ...)
1047: {
1.66 augustss 1048: struct inpcb *inp;
1049: struct udpiphdr *ui;
1.125 thorpej 1050: struct route *ro;
1.66 augustss 1051: int len = m->m_pkthdr.len;
1.31 mycroft 1052: int error = 0;
1.27 christos 1053: va_list ap;
1054:
1.98 matt 1055: MCLAIM(m, &udp_tx_mowner);
1.27 christos 1056: va_start(ap, m);
1057: inp = va_arg(ap, struct inpcb *);
1058: va_end(ap);
1.1 cgd 1059:
1060: /*
1061: * Calculate data length and get a mbuf
1062: * for UDP and IP headers.
1063: */
1.13 mycroft 1064: M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
1065: if (m == 0) {
1066: error = ENOBUFS;
1.39 thorpej 1067: goto release;
1068: }
1069:
1070: /*
1071: * Compute the packet length of the IP header, and
1072: * punt if the length looks bogus.
1073: */
1.96 itojun 1074: if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
1.39 thorpej 1075: error = EMSGSIZE;
1.13 mycroft 1076: goto release;
1077: }
1.1 cgd 1078:
1079: /*
1080: * Fill in mbuf with extended UDP header
1081: * and addresses and length put into network format.
1082: */
1083: ui = mtod(m, struct udpiphdr *);
1084: ui->ui_pr = IPPROTO_UDP;
1085: ui->ui_src = inp->inp_laddr;
1086: ui->ui_dst = inp->inp_faddr;
1087: ui->ui_sport = inp->inp_lport;
1088: ui->ui_dport = inp->inp_fport;
1.78 thorpej 1089: ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr));
1.1 cgd 1090:
1.125 thorpej 1091: ro = &inp->inp_route;
1092:
1.1 cgd 1093: /*
1.78 thorpej 1094: * Set up checksum and output datagram.
1.1 cgd 1095: */
1096: if (udpcksum) {
1.78 thorpej 1097: /*
1098: * XXX Cache pseudo-header checksum part for
1099: * XXX "connected" UDP sockets.
1100: */
1101: ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
1102: ui->ui_dst.s_addr, htons((u_int16_t)len +
1103: sizeof(struct udphdr) + IPPROTO_UDP));
1.134.2.4 tron 1104: m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
1.78 thorpej 1105: m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
1106: } else
1107: ui->ui_sum = 0;
1.96 itojun 1108: ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
1.1 cgd 1109: ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
1110: ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
1111: udpstat.udps_opackets++;
1.48 itojun 1112:
1.125 thorpej 1113: return (ip_output(m, inp->inp_options, ro,
1.12 mycroft 1114: inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
1.107 itojun 1115: inp->inp_moptions, inp->inp_socket));
1.1 cgd 1116:
1117: release:
1118: m_freem(m);
1119: return (error);
1120: }
1121:
1.42 thorpej 1122: int udp_sendspace = 9216; /* really max datagram size */
1123: int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
1.1 cgd 1124: /* 40 1K datagrams */
1125:
1126: /*ARGSUSED*/
1.7 mycroft 1127: int
1.119 matt 1128: udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
1129: struct mbuf *control, struct proc *p)
1.1 cgd 1130: {
1.66 augustss 1131: struct inpcb *inp;
1.1 cgd 1132: int s;
1.66 augustss 1133: int error = 0;
1.1 cgd 1134:
1135: if (req == PRU_CONTROL)
1.31 mycroft 1136: return (in_control(so, (long)m, (caddr_t)nam,
1.30 mycroft 1137: (struct ifnet *)control, p));
1.59 thorpej 1138:
1.60 thorpej 1139: if (req == PRU_PURGEIF) {
1.80 itojun 1140: in_pcbpurgeif0(&udbtable, (struct ifnet *)control);
1.60 thorpej 1141: in_purgeif((struct ifnet *)control);
1142: in_pcbpurgeif(&udbtable, (struct ifnet *)control);
1.59 thorpej 1143: return (0);
1144: }
1.31 mycroft 1145:
1146: s = splsoftnet();
1147: inp = sotoinpcb(so);
1.32 mycroft 1148: #ifdef DIAGNOSTIC
1149: if (req != PRU_SEND && req != PRU_SENDOOB && control)
1150: panic("udp_usrreq: unexpected control mbuf");
1151: #endif
1.31 mycroft 1152: if (inp == 0 && req != PRU_ATTACH) {
1153: error = EINVAL;
1154: goto release;
1155: }
1156:
1.1 cgd 1157: /*
1158: * Note: need to block udp_input while changing
1159: * the udp pcb queue and/or pcb addresses.
1160: */
1161: switch (req) {
1162:
1163: case PRU_ATTACH:
1.31 mycroft 1164: if (inp != 0) {
1165: error = EISCONN;
1.1 cgd 1166: break;
1167: }
1.98 matt 1168: #ifdef MBUFTRACE
1169: so->so_mowner = &udp_mowner;
1170: so->so_rcv.sb_mowner = &udp_rx_mowner;
1171: so->so_snd.sb_mowner = &udp_tx_mowner;
1172: #endif
1.31 mycroft 1173: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
1174: error = soreserve(so, udp_sendspace, udp_recvspace);
1175: if (error)
1176: break;
1177: }
1.18 mycroft 1178: error = in_pcballoc(so, &udbtable);
1.1 cgd 1179: if (error)
1180: break;
1.31 mycroft 1181: inp = sotoinpcb(so);
1182: inp->inp_ip.ip_ttl = ip_defttl;
1.1 cgd 1183: break;
1184:
1185: case PRU_DETACH:
1.31 mycroft 1186: in_pcbdetach(inp);
1.1 cgd 1187: break;
1188:
1189: case PRU_BIND:
1.31 mycroft 1190: error = in_pcbbind(inp, nam, p);
1.1 cgd 1191: break;
1192:
1193: case PRU_LISTEN:
1194: error = EOPNOTSUPP;
1195: break;
1196:
1197: case PRU_CONNECT:
1.31 mycroft 1198: error = in_pcbconnect(inp, nam);
1199: if (error)
1.1 cgd 1200: break;
1.31 mycroft 1201: soisconnected(so);
1.1 cgd 1202: break;
1203:
1204: case PRU_CONNECT2:
1205: error = EOPNOTSUPP;
1206: break;
1207:
1208: case PRU_DISCONNECT:
1.31 mycroft 1209: /*soisdisconnected(so);*/
1210: so->so_state &= ~SS_ISCONNECTED; /* XXX */
1.1 cgd 1211: in_pcbdisconnect(inp);
1.34 mycroft 1212: inp->inp_laddr = zeroin_addr; /* XXX */
1.35 mycroft 1213: in_pcbstate(inp, INP_BOUND); /* XXX */
1.1 cgd 1214: break;
1215:
1216: case PRU_SHUTDOWN:
1217: socantsendmore(so);
1218: break;
1219:
1.31 mycroft 1220: case PRU_RCVD:
1221: error = EOPNOTSUPP;
1.1 cgd 1222: break;
1223:
1.31 mycroft 1224: case PRU_SEND:
1.32 mycroft 1225: if (control && control->m_len) {
1226: m_freem(control);
1227: m_freem(m);
1228: error = EINVAL;
1229: break;
1230: }
1.31 mycroft 1231: {
1.35 mycroft 1232: struct in_addr laddr; /* XXX */
1.1 cgd 1233:
1.31 mycroft 1234: if (nam) {
1.35 mycroft 1235: laddr = inp->inp_laddr; /* XXX */
1.31 mycroft 1236: if ((so->so_state & SS_ISCONNECTED) != 0) {
1237: error = EISCONN;
1.32 mycroft 1238: goto die;
1.31 mycroft 1239: }
1240: error = in_pcbconnect(inp, nam);
1.100 matt 1241: if (error)
1242: goto die;
1.31 mycroft 1243: } else {
1244: if ((so->so_state & SS_ISCONNECTED) == 0) {
1245: error = ENOTCONN;
1.32 mycroft 1246: goto die;
1.31 mycroft 1247: }
1248: }
1.33 mycroft 1249: error = udp_output(m, inp);
1.100 matt 1250: m = NULL;
1.31 mycroft 1251: if (nam) {
1252: in_pcbdisconnect(inp);
1.35 mycroft 1253: inp->inp_laddr = laddr; /* XXX */
1254: in_pcbstate(inp, INP_BOUND); /* XXX */
1.31 mycroft 1255: }
1.100 matt 1256: die:
1257: if (m)
1258: m_freem(m);
1.31 mycroft 1259: }
1.1 cgd 1260: break;
1261:
1262: case PRU_SENSE:
1263: /*
1264: * stat: don't bother with a blocksize.
1265: */
1.31 mycroft 1266: splx(s);
1.1 cgd 1267: return (0);
1268:
1.31 mycroft 1269: case PRU_RCVOOB:
1270: error = EOPNOTSUPP;
1271: break;
1272:
1.1 cgd 1273: case PRU_SENDOOB:
1.32 mycroft 1274: m_freem(control);
1.31 mycroft 1275: m_freem(m);
1.1 cgd 1276: error = EOPNOTSUPP;
1277: break;
1278:
1.31 mycroft 1279: case PRU_SOCKADDR:
1280: in_setsockaddr(inp, nam);
1281: break;
1282:
1283: case PRU_PEERADDR:
1284: in_setpeeraddr(inp, nam);
1285: break;
1.1 cgd 1286:
1287: default:
1288: panic("udp_usrreq");
1289: }
1290:
1291: release:
1.31 mycroft 1292: splx(s);
1.1 cgd 1293: return (error);
1.13 mycroft 1294: }
1295:
1296: /*
1297: * Sysctl for udp variables.
1298: */
1.114 atatat 1299: SYSCTL_SETUP(sysctl_net_inet_udp_setup, "sysctl net.inet.udp subtree setup")
1.13 mycroft 1300: {
1.114 atatat 1301:
1.116 atatat 1302: sysctl_createv(clog, 0, NULL, NULL,
1303: CTLFLAG_PERMANENT,
1.114 atatat 1304: CTLTYPE_NODE, "net", NULL,
1305: NULL, 0, NULL, 0,
1306: CTL_NET, CTL_EOL);
1.116 atatat 1307: sysctl_createv(clog, 0, NULL, NULL,
1308: CTLFLAG_PERMANENT,
1.114 atatat 1309: CTLTYPE_NODE, "inet", NULL,
1310: NULL, 0, NULL, 0,
1311: CTL_NET, PF_INET, CTL_EOL);
1.116 atatat 1312: sysctl_createv(clog, 0, NULL, NULL,
1313: CTLFLAG_PERMANENT,
1.122 atatat 1314: CTLTYPE_NODE, "udp",
1315: SYSCTL_DESCR("UDPv4 related settings"),
1.114 atatat 1316: NULL, 0, NULL, 0,
1317: CTL_NET, PF_INET, IPPROTO_UDP, CTL_EOL);
1318:
1.116 atatat 1319: sysctl_createv(clog, 0, NULL, NULL,
1320: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1321: CTLTYPE_INT, "checksum",
1.123 heas 1322: SYSCTL_DESCR("Compute UDP checksums"),
1.114 atatat 1323: NULL, 0, &udpcksum, 0,
1324: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_CHECKSUM,
1325: CTL_EOL);
1.116 atatat 1326: sysctl_createv(clog, 0, NULL, NULL,
1327: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1328: CTLTYPE_INT, "sendspace",
1329: SYSCTL_DESCR("Default UDP send buffer size"),
1.114 atatat 1330: NULL, 0, &udp_sendspace, 0,
1331: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_SENDSPACE,
1332: CTL_EOL);
1.116 atatat 1333: sysctl_createv(clog, 0, NULL, NULL,
1334: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1.122 atatat 1335: CTLTYPE_INT, "recvspace",
1336: SYSCTL_DESCR("Default UDP receive buffer size"),
1.114 atatat 1337: NULL, 0, &udp_recvspace, 0,
1338: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_RECVSPACE,
1339: CTL_EOL);
1.125 thorpej 1340: sysctl_createv(clog, 0, NULL, NULL,
1341: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1342: CTLTYPE_INT, "do_loopback_cksum",
1343: SYSCTL_DESCR("Perform UDP checksum on loopback"),
1344: NULL, 0, &udp_do_loopback_cksum, 0,
1345: CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_LOOPBACKCKSUM,
1346: CTL_EOL);
1.132 atatat 1347: sysctl_createv(clog, 0, NULL, NULL,
1348: CTLFLAG_PERMANENT,
1.134 atatat 1349: CTLTYPE_STRUCT, "pcblist",
1.132 atatat 1350: SYSCTL_DESCR("UDP protocol control block list"),
1351: sysctl_inpcblist, 0, &udbtable, 0,
1352: CTL_NET, PF_INET, IPPROTO_UDP, CTL_CREATE,
1353: CTL_EOL);
1.1 cgd 1354: }
1.72 itojun 1355: #endif
1.130 manu 1356:
1357: #if (defined INET && defined IPSEC_NAT_T)
1358: /*
1359: * Returns:
1360: * 1 if the packet was processed
1361: * 0 if normal UDP processing should take place
1.134.2.6! riz 1362: * -1 if an error occurent and m was freed
1.130 manu 1363: */
1364: static int
1.134.2.6! riz 1365: udp4_espinudp(mp, off, src, so)
! 1366: struct mbuf **mp;
1.130 manu 1367: int off;
1368: struct sockaddr *src;
1369: struct socket *so;
1370: {
1371: size_t len;
1372: caddr_t data;
1373: struct inpcb *inp;
1374: size_t skip = 0;
1375: size_t minlen;
1376: size_t iphdrlen;
1377: struct ip *ip;
1378: struct mbuf *n;
1.134.2.1 tron 1379: struct m_tag *tag;
1380: struct udphdr *udphdr;
1381: u_int16_t sport, dport;
1.134.2.6! riz 1382: struct mbuf *m = *mp;
1.130 manu 1383:
1.131 perry 1384: /*
1.130 manu 1385: * Collapse the mbuf chain if the first mbuf is too short
1386: * The longest case is: UDP + non ESP marker + ESP
1387: */
1388: minlen = off + sizeof(u_int64_t) + sizeof(struct esp);
1389: if (minlen > m->m_pkthdr.len)
1390: minlen = m->m_pkthdr.len;
1391:
1392: if (m->m_len < minlen) {
1.134.2.6! riz 1393: if ((*mp = m_pullup(m, minlen)) == NULL) {
1.130 manu 1394: printf("udp4_espinudp: m_pullup failed\n");
1.134.2.6! riz 1395: return -1;
1.130 manu 1396: }
1.134.2.6! riz 1397: m = *mp;
1.130 manu 1398: }
1399:
1.131 perry 1400: len = m->m_len - off;
1.130 manu 1401: data = mtod(m, caddr_t) + off;
1402: inp = sotoinpcb(so);
1403:
1404: /* Ignore keepalive packets */
1405: if ((len == 1) && (data[0] == '\xff')) {
1406: return 1;
1407: }
1408:
1.131 perry 1409: /*
1410: * Check that the payload is long enough to hold
1.130 manu 1411: * an ESP header and compute the length of encapsulation
1.131 perry 1412: * header to remove
1.130 manu 1413: */
1414: if (inp->inp_flags & INP_ESPINUDP) {
1415: u_int32_t *st = (u_int32_t *)data;
1416:
1417: if ((len <= sizeof(struct esp)) || (*st == 0))
1418: return 0; /* Normal UDP processing */
1419:
1420: skip = sizeof(struct udphdr);
1421: }
1422:
1423: if (inp->inp_flags & INP_ESPINUDP_NON_IKE) {
1.134.2.5 tron 1424: u_int32_t *st = (u_int32_t *)data;
1.130 manu 1425:
1426: if ((len <= sizeof(u_int64_t) + sizeof(struct esp))
1.134.2.5 tron 1427: || ((st[0] | st[1]) != 0))
1.130 manu 1428: return 0; /* Normal UDP processing */
1.131 perry 1429:
1.130 manu 1430: skip = sizeof(struct udphdr) + sizeof(u_int64_t);
1431: }
1432:
1433: /*
1.134.2.1 tron 1434: * Get the UDP ports. They are handled in network
1435: * order everywhere in IPSEC_NAT_T code.
1436: */
1437: udphdr = (struct udphdr *)(data - skip);
1438: sport = udphdr->uh_sport;
1439: dport = udphdr->uh_dport;
1440:
1441: /*
1.130 manu 1442: * Remove the UDP header (and possibly the non ESP marker)
1443: * IP header lendth is iphdrlen
1.131 perry 1444: * Before:
1.130 manu 1445: * <--- off --->
1446: * +----+------+-----+
1447: * | IP | UDP | ESP |
1448: * +----+------+-----+
1449: * <-skip->
1450: * After:
1451: * +----+-----+
1452: * | IP | ESP |
1453: * +----+-----+
1454: * <-skip->
1455: */
1456: iphdrlen = off - sizeof(struct udphdr);
1457: memmove(mtod(m, caddr_t) + skip, mtod(m, caddr_t), iphdrlen);
1458: m_adj(m, skip);
1459:
1460: ip = mtod(m, struct ip *);
1461: ip->ip_len = htons(ntohs(ip->ip_len) - skip);
1462: ip->ip_p = IPPROTO_ESP;
1463:
1464: /*
1.131 perry 1465: * Copy the mbuf to avoid multiple free, as both
1466: * esp4_input (which we call) and udp_input (which
1.130 manu 1467: * called us) free the mbuf.
1468: */
1469: if ((n = m_dup(m, 0, M_COPYALL, M_DONTWAIT)) == NULL) {
1470: printf("udp4_espinudp: m_dup failed\n");
1471: return 0;
1472: }
1473:
1.134.2.1 tron 1474: /*
1475: * Add a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember
1476: * the source UDP port. This is required if we want
1477: * to select the right SPD for multiple hosts behind
1478: * same NAT
1479: */
1.134.2.2 tron 1480: if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
1481: sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {
1482: printf("udp4_espinudp: m_tag_get failed\n");
1.134.2.3 tron 1483: m_freem(n);
1.134.2.2 tron 1484: return 0;
1485: }
1.134.2.1 tron 1486: ((u_int16_t *)(tag + 1))[0] = sport;
1487: ((u_int16_t *)(tag + 1))[1] = dport;
1488: m_tag_prepend(n, tag);
1489:
1.130 manu 1490: esp4_input(n, iphdrlen);
1491:
1492: /* We handled it, it shoudln't be handled by UDP */
1493: return 1;
1494: }
1495: #endif
CVSweb <webmaster@jp.NetBSD.org>