Annotation of sys/netinet/udp_usrreq.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: udp_usrreq.c,v 1.114 2007/06/11 11:29:35 henning Exp $ */
2: /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1982, 1986, 1988, 1990, 1993
6: * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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: * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
33: *
34: * NRL grants permission for redistribution and use in source and binary
35: * forms, with or without modification, of the software and documentation
36: * created at NRL provided that the following conditions are met:
37: *
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgements:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * This product includes software developed at the Information
48: * Technology Division, US Naval Research Laboratory.
49: * 4. Neither the name of the NRL nor the names of its contributors
50: * may be used to endorse or promote products derived from this software
51: * without specific prior written permission.
52: *
53: * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
54: * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
57: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64: *
65: * The views and conclusions contained in the software and documentation
66: * are those of the authors and should not be interpreted as representing
67: * official policies, either expressed or implied, of the US Naval
68: * Research Laboratory (NRL).
69: */
70:
71: #include <sys/param.h>
72: #include <sys/systm.h>
73: #include <sys/mbuf.h>
74: #include <sys/protosw.h>
75: #include <sys/socket.h>
76: #include <sys/socketvar.h>
77: #include <sys/sysctl.h>
78:
79: #include <net/if.h>
80: #include <net/route.h>
81:
82: #include <netinet/in.h>
83: #include <netinet/in_systm.h>
84: #include <netinet/in_var.h>
85: #include <netinet/ip.h>
86: #include <netinet/in_pcb.h>
87: #include <netinet/ip_var.h>
88: #include <netinet/ip_icmp.h>
89: #include <netinet/udp.h>
90: #include <netinet/udp_var.h>
91:
92: #ifdef IPSEC
93: #include <netinet/ip_ipsp.h>
94: #include <netinet/ip_esp.h>
95: #endif
96:
97: #ifdef INET6
98: #ifndef INET
99: #include <netinet/in.h>
100: #endif
101: #include <netinet6/ip6protosw.h>
102:
103: extern int ip6_defhlim;
104: #endif /* INET6 */
105:
106: /*
107: * UDP protocol implementation.
108: * Per RFC 768, August, 1980.
109: */
110: int udpcksum = 1;
111:
112: u_int udp_sendspace = 9216; /* really max datagram size */
113: u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
114: /* 40 1K datagrams */
115:
116: int *udpctl_vars[UDPCTL_MAXID] = UDPCTL_VARS;
117:
118: struct inpcbtable udbtable;
119: struct udpstat udpstat;
120:
121: void udp_detach(struct inpcb *);
122: void udp_notify(struct inpcb *, int);
123:
124: #ifndef UDBHASHSIZE
125: #define UDBHASHSIZE 128
126: #endif
127: int udbhashsize = UDBHASHSIZE;
128:
129: /* from in_pcb.c */
130: extern struct baddynamicports baddynamicports;
131:
132: void
133: udp_init()
134: {
135: in_pcbinit(&udbtable, udbhashsize);
136: }
137:
138: #ifdef INET6
139: int
140: udp6_input(mp, offp, proto)
141: struct mbuf **mp;
142: int *offp, proto;
143: {
144: struct mbuf *m = *mp;
145:
146: #if defined(NFAITH) && 0 < NFAITH
147: if (m->m_pkthdr.rcvif) {
148: if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
149: /* XXX send icmp6 host/port unreach? */
150: m_freem(m);
151: return IPPROTO_DONE;
152: }
153: }
154: #endif
155:
156: udp_input(m, *offp, proto);
157: return IPPROTO_DONE;
158: }
159: #endif
160:
161: void
162: udp_input(struct mbuf *m, ...)
163: {
164: struct ip *ip;
165: struct udphdr *uh;
166: struct inpcb *inp;
167: struct mbuf *opts = NULL;
168: struct ip save_ip;
169: int iphlen, len;
170: va_list ap;
171: u_int16_t savesum;
172: union {
173: struct sockaddr sa;
174: struct sockaddr_in sin;
175: #ifdef INET6
176: struct sockaddr_in6 sin6;
177: #endif /* INET6 */
178: } srcsa, dstsa;
179: #ifdef INET6
180: struct ip6_hdr *ip6;
181: #endif /* INET6 */
182: #ifdef IPSEC
183: struct m_tag *mtag;
184: struct tdb_ident *tdbi;
185: struct tdb *tdb;
186: int error, s;
187: #endif /* IPSEC */
188:
189: va_start(ap, m);
190: iphlen = va_arg(ap, int);
191: va_end(ap);
192:
193: udpstat.udps_ipackets++;
194:
195: switch (mtod(m, struct ip *)->ip_v) {
196: case 4:
197: ip = mtod(m, struct ip *);
198: #ifdef INET6
199: ip6 = NULL;
200: #endif /* INET6 */
201: srcsa.sa.sa_family = AF_INET;
202: break;
203: #ifdef INET6
204: case 6:
205: ip = NULL;
206: ip6 = mtod(m, struct ip6_hdr *);
207: srcsa.sa.sa_family = AF_INET6;
208: break;
209: #endif /* INET6 */
210: default:
211: goto bad;
212: }
213:
214: IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
215: if (!uh) {
216: udpstat.udps_hdrops++;
217: return;
218: }
219:
220: /* Check for illegal destination port 0 */
221: if (uh->uh_dport == 0) {
222: udpstat.udps_noport++;
223: goto bad;
224: }
225:
226: /*
227: * Make mbuf data length reflect UDP length.
228: * If not enough data to reflect UDP length, drop.
229: */
230: len = ntohs((u_int16_t)uh->uh_ulen);
231: if (ip) {
232: if (m->m_pkthdr.len - iphlen != len) {
233: if (len > (m->m_pkthdr.len - iphlen) ||
234: len < sizeof(struct udphdr)) {
235: udpstat.udps_badlen++;
236: goto bad;
237: }
238: m_adj(m, len - (m->m_pkthdr.len - iphlen));
239: }
240: }
241: #ifdef INET6
242: else if (ip6) {
243: /* jumbograms */
244: if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)
245: len = m->m_pkthdr.len - iphlen;
246: if (len != m->m_pkthdr.len - iphlen) {
247: udpstat.udps_badlen++;
248: goto bad;
249: }
250: }
251: #endif
252: else /* shouldn't happen */
253: goto bad;
254:
255: /*
256: * Save a copy of the IP header in case we want restore it
257: * for sending an ICMP error message in response.
258: */
259: if (ip)
260: save_ip = *ip;
261:
262: /*
263: * Checksum extended UDP header and data.
264: * from W.R.Stevens: check incoming udp cksums even if
265: * udpcksum is not set.
266: */
267: savesum = uh->uh_sum;
268: #ifdef INET6
269: if (ip6) {
270: /* Be proactive about malicious use of IPv4 mapped address */
271: if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
272: IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
273: /* XXX stat */
274: goto bad;
275: }
276:
277: /*
278: * In IPv6, the UDP checksum is ALWAYS used.
279: */
280: if (uh->uh_sum == 0) {
281: udpstat.udps_nosum++;
282: goto bad;
283: }
284: if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) {
285: udpstat.udps_badsum++;
286: goto bad;
287: }
288: } else
289: #endif /* INET6 */
290: if (uh->uh_sum) {
291: if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) {
292: if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) {
293: udpstat.udps_badsum++;
294: udpstat.udps_inhwcsum++;
295: m_freem(m);
296: return;
297: }
298:
299: if ((uh->uh_sum = in4_cksum(m, IPPROTO_UDP,
300: iphlen, len))) {
301: udpstat.udps_badsum++;
302: m_freem(m);
303: return;
304: }
305: } else {
306: m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_IN_OK;
307: udpstat.udps_inhwcsum++;
308: }
309: } else
310: udpstat.udps_nosum++;
311:
312: #ifdef IPSEC
313: if (udpencap_enable && udpencap_port &&
314: uh->uh_dport == htons(udpencap_port)) {
315: u_int32_t spi;
316: int skip = iphlen + sizeof(struct udphdr);
317:
318: if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {
319: /* packet too short */
320: m_freem(m);
321: return;
322: }
323: m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
324: /*
325: * decapsulate if the SPI is not zero, otherwise pass
326: * to userland
327: */
328: if (spi != 0) {
329: if ((m = m_pullup2(m, skip)) == NULL) {
330: udpstat.udps_hdrops++;
331: return;
332: }
333:
334: /* remove the UDP header */
335: bcopy(mtod(m, u_char *),
336: mtod(m, u_char *) + sizeof(struct udphdr), iphlen);
337: m_adj(m, sizeof(struct udphdr));
338: skip -= sizeof(struct udphdr);
339:
340: espstat.esps_udpencin++;
341: ipsec_common_input(m, skip, offsetof(struct ip, ip_p),
342: srcsa.sa.sa_family, IPPROTO_ESP, 1);
343: return;
344: }
345: }
346: #endif
347:
348: switch (srcsa.sa.sa_family) {
349: case AF_INET:
350: bzero(&srcsa, sizeof(struct sockaddr_in));
351: srcsa.sin.sin_len = sizeof(struct sockaddr_in);
352: srcsa.sin.sin_family = AF_INET;
353: srcsa.sin.sin_port = uh->uh_sport;
354: srcsa.sin.sin_addr = ip->ip_src;
355:
356: bzero(&dstsa, sizeof(struct sockaddr_in));
357: dstsa.sin.sin_len = sizeof(struct sockaddr_in);
358: dstsa.sin.sin_family = AF_INET;
359: dstsa.sin.sin_port = uh->uh_dport;
360: dstsa.sin.sin_addr = ip->ip_dst;
361: break;
362: #ifdef INET6
363: case AF_INET6:
364: bzero(&srcsa, sizeof(struct sockaddr_in6));
365: srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
366: srcsa.sin6.sin6_family = AF_INET6;
367: srcsa.sin6.sin6_port = uh->uh_sport;
368: #if 0 /*XXX inbound flowinfo */
369: srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;
370: #endif
371: /* KAME hack: recover scopeid */
372: (void)in6_recoverscope(&srcsa.sin6, &ip6->ip6_src,
373: m->m_pkthdr.rcvif);
374:
375: bzero(&dstsa, sizeof(struct sockaddr_in6));
376: dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
377: dstsa.sin6.sin6_family = AF_INET6;
378: dstsa.sin6.sin6_port = uh->uh_dport;
379: /* KAME hack: recover scopeid */
380: (void)in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst,
381: m->m_pkthdr.rcvif);
382: break;
383: #endif /* INET6 */
384: }
385:
386: #ifdef INET6
387: if ((ip6 && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) ||
388: (ip && IN_MULTICAST(ip->ip_dst.s_addr)) ||
389: (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {
390: #else /* INET6 */
391: if (IN_MULTICAST(ip->ip_dst.s_addr) ||
392: in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
393: #endif /* INET6 */
394: struct inpcb *last;
395: /*
396: * Deliver a multicast or broadcast datagram to *all* sockets
397: * for which the local and remote addresses and ports match
398: * those of the incoming datagram. This allows more than
399: * one process to receive multi/broadcasts on the same port.
400: * (This really ought to be done for unicast datagrams as
401: * well, but that would cause problems with existing
402: * applications that open both address-specific sockets and
403: * a wildcard socket listening to the same port -- they would
404: * end up receiving duplicates of every unicast datagram.
405: * Those applications open the multiple sockets to overcome an
406: * inadequacy of the UDP socket interface, but for backwards
407: * compatibility we avoid the problem here rather than
408: * fixing the interface. Maybe 4.5BSD will remedy this?)
409: */
410:
411: iphlen += sizeof(struct udphdr);
412:
413: /*
414: * Locate pcb(s) for datagram.
415: * (Algorithm copied from raw_intr().)
416: */
417: last = NULL;
418: CIRCLEQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
419: #ifdef INET6
420: /* don't accept it if AF does not match */
421: if (ip6 && !(inp->inp_flags & INP_IPV6))
422: continue;
423: if (!ip6 && (inp->inp_flags & INP_IPV6))
424: continue;
425: #endif
426: if (inp->inp_lport != uh->uh_dport)
427: continue;
428: #ifdef INET6
429: if (ip6) {
430: if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
431: if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,
432: &ip6->ip6_dst))
433: continue;
434: } else
435: #endif /* INET6 */
436: if (inp->inp_laddr.s_addr != INADDR_ANY) {
437: if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
438: continue;
439: }
440: #ifdef INET6
441: if (ip6) {
442: if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
443: if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
444: &ip6->ip6_src) ||
445: inp->inp_fport != uh->uh_sport)
446: continue;
447: } else
448: #endif /* INET6 */
449: if (inp->inp_faddr.s_addr != INADDR_ANY) {
450: if (inp->inp_faddr.s_addr !=
451: ip->ip_src.s_addr ||
452: inp->inp_fport != uh->uh_sport)
453: continue;
454: }
455:
456: if (last != NULL) {
457: struct mbuf *n;
458:
459: if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
460: #ifdef INET6
461: if (ip6 && (last->inp_flags &
462: IN6P_CONTROLOPTS))
463: ip6_savecontrol(last, n, &opts);
464: #endif /* INET6 */
465: if (ip && (last->inp_flags &
466: INP_CONTROLOPTS))
467: ip_savecontrol(last, &opts,
468: ip, n);
469:
470: m_adj(n, iphlen);
471: if (sbappendaddr(
472: &last->inp_socket->so_rcv,
473: &srcsa.sa, n, opts) == 0) {
474: m_freem(n);
475: if (opts)
476: m_freem(opts);
477: udpstat.udps_fullsock++;
478: } else
479: sorwakeup(last->inp_socket);
480: opts = NULL;
481: }
482: }
483: last = inp;
484: /*
485: * Don't look for additional matches if this one does
486: * not have either the SO_REUSEPORT or SO_REUSEADDR
487: * socket options set. This heuristic avoids searching
488: * through all pcbs in the common case of a non-shared
489: * port. It * assumes that an application will never
490: * clear these options after setting them.
491: */
492: if ((last->inp_socket->so_options & (SO_REUSEPORT |
493: SO_REUSEADDR)) == 0)
494: break;
495: }
496:
497: if (last == NULL) {
498: /*
499: * No matching pcb found; discard datagram.
500: * (No need to send an ICMP Port Unreachable
501: * for a broadcast or multicast datgram.)
502: */
503: udpstat.udps_noportbcast++;
504: goto bad;
505: }
506:
507: #ifdef INET6
508: if (ip6 && (last->inp_flags & IN6P_CONTROLOPTS))
509: ip6_savecontrol(last, m, &opts);
510: #endif /* INET6 */
511: if (ip && (last->inp_flags & INP_CONTROLOPTS))
512: ip_savecontrol(last, &opts, ip, m);
513:
514: m_adj(m, iphlen);
515: if (sbappendaddr(&last->inp_socket->so_rcv,
516: &srcsa.sa, m, opts) == 0) {
517: udpstat.udps_fullsock++;
518: goto bad;
519: }
520: sorwakeup(last->inp_socket);
521: return;
522: }
523: /*
524: * Locate pcb for datagram.
525: */
526: #ifdef INET6
527: if (ip6)
528: inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, uh->uh_sport,
529: &ip6->ip6_dst, uh->uh_dport);
530: else
531: #endif /* INET6 */
532: inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
533: ip->ip_dst, uh->uh_dport);
534: if (inp == 0) {
535: int inpl_reverse = 0;
536: if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST)
537: inpl_reverse = 1;
538: ++udpstat.udps_pcbhashmiss;
539: #ifdef INET6
540: if (ip6) {
541: inp = in6_pcblookup_listen(&udbtable,
542: &ip6->ip6_dst, uh->uh_dport, inpl_reverse);
543: } else
544: #endif /* INET6 */
545: inp = in_pcblookup_listen(&udbtable,
546: ip->ip_dst, uh->uh_dport, inpl_reverse);
547: if (inp == 0) {
548: udpstat.udps_noport++;
549: if (m->m_flags & (M_BCAST | M_MCAST)) {
550: udpstat.udps_noportbcast++;
551: goto bad;
552: }
553: #ifdef INET6
554: if (ip6) {
555: uh->uh_sum = savesum;
556: icmp6_error(m, ICMP6_DST_UNREACH,
557: ICMP6_DST_UNREACH_NOPORT,0);
558: } else
559: #endif /* INET6 */
560: {
561: *ip = save_ip;
562: uh->uh_sum = savesum;
563: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,
564: 0, 0);
565: }
566: return;
567: }
568: }
569:
570: #ifdef IPSEC
571: mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
572: s = splnet();
573: if (mtag != NULL) {
574: tdbi = (struct tdb_ident *)(mtag + 1);
575: tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
576: } else
577: tdb = NULL;
578: ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error,
579: IPSP_DIRECTION_IN, tdb, inp);
580: if (error) {
581: splx(s);
582: goto bad;
583: }
584:
585: /* Latch SA only if the socket is connected */
586: if (inp->inp_tdb_in != tdb &&
587: (inp->inp_socket->so_state & SS_ISCONNECTED)) {
588: if (tdb) {
589: tdb_add_inp(tdb, inp, 1);
590: if (inp->inp_ipo == NULL) {
591: inp->inp_ipo = ipsec_add_policy(inp,
592: srcsa.sa.sa_family, IPSP_DIRECTION_OUT);
593: if (inp->inp_ipo == NULL) {
594: splx(s);
595: goto bad;
596: }
597: }
598: if (inp->inp_ipo->ipo_dstid == NULL &&
599: tdb->tdb_srcid != NULL) {
600: inp->inp_ipo->ipo_dstid = tdb->tdb_srcid;
601: tdb->tdb_srcid->ref_count++;
602: }
603: if (inp->inp_ipsec_remotecred == NULL &&
604: tdb->tdb_remote_cred != NULL) {
605: inp->inp_ipsec_remotecred =
606: tdb->tdb_remote_cred;
607: tdb->tdb_remote_cred->ref_count++;
608: }
609: if (inp->inp_ipsec_remoteauth == NULL &&
610: tdb->tdb_remote_auth != NULL) {
611: inp->inp_ipsec_remoteauth =
612: tdb->tdb_remote_auth;
613: tdb->tdb_remote_auth->ref_count++;
614: }
615: } else { /* Just reset */
616: TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp,
617: inp_tdb_in_next);
618: inp->inp_tdb_in = NULL;
619: }
620: }
621: splx(s);
622: #endif /*IPSEC */
623:
624: opts = NULL;
625: #ifdef INET6
626: if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
627: ip6_savecontrol(inp, m, &opts);
628: #endif /* INET6 */
629: if (ip && (inp->inp_flags & INP_CONTROLOPTS))
630: ip_savecontrol(inp, &opts, ip, m);
631:
632: iphlen += sizeof(struct udphdr);
633: m_adj(m, iphlen);
634: if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) {
635: udpstat.udps_fullsock++;
636: goto bad;
637: }
638: sorwakeup(inp->inp_socket);
639: return;
640: bad:
641: m_freem(m);
642: if (opts)
643: m_freem(opts);
644: }
645:
646: /*
647: * Notify a udp user of an asynchronous error;
648: * just wake up so that he can collect error status.
649: */
650: void
651: udp_notify(inp, errno)
652: struct inpcb *inp;
653: int errno;
654: {
655: inp->inp_socket->so_error = errno;
656: sorwakeup(inp->inp_socket);
657: sowwakeup(inp->inp_socket);
658: }
659:
660: #ifdef INET6
661: void
662: udp6_ctlinput(cmd, sa, d)
663: int cmd;
664: struct sockaddr *sa;
665: void *d;
666: {
667: struct udphdr uh;
668: struct sockaddr_in6 sa6;
669: struct ip6_hdr *ip6;
670: struct mbuf *m;
671: int off;
672: void *cmdarg;
673: struct ip6ctlparam *ip6cp = NULL;
674: struct udp_portonly {
675: u_int16_t uh_sport;
676: u_int16_t uh_dport;
677: } *uhp;
678: void (*notify)(struct inpcb *, int) = udp_notify;
679:
680: if (sa == NULL)
681: return;
682: if (sa->sa_family != AF_INET6 ||
683: sa->sa_len != sizeof(struct sockaddr_in6))
684: return;
685:
686: if ((unsigned)cmd >= PRC_NCMDS)
687: return;
688: if (PRC_IS_REDIRECT(cmd))
689: notify = in_rtchange, d = NULL;
690: else if (cmd == PRC_HOSTDEAD)
691: d = NULL;
692: else if (cmd == PRC_MSGSIZE)
693: ; /* special code is present, see below */
694: else if (inet6ctlerrmap[cmd] == 0)
695: return;
696:
697: /* if the parameter is from icmp6, decode it. */
698: if (d != NULL) {
699: ip6cp = (struct ip6ctlparam *)d;
700: m = ip6cp->ip6c_m;
701: ip6 = ip6cp->ip6c_ip6;
702: off = ip6cp->ip6c_off;
703: cmdarg = ip6cp->ip6c_cmdarg;
704: } else {
705: m = NULL;
706: ip6 = NULL;
707: cmdarg = NULL;
708: /* XXX: translate addresses into internal form */
709: sa6 = *(struct sockaddr_in6 *)sa;
710: #ifndef SCOPEDROUTING
711: if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
712: /* should be impossible */
713: return;
714: }
715: #endif
716: }
717:
718: if (ip6cp && ip6cp->ip6c_finaldst) {
719: bzero(&sa6, sizeof(sa6));
720: sa6.sin6_family = AF_INET6;
721: sa6.sin6_len = sizeof(sa6);
722: sa6.sin6_addr = *ip6cp->ip6c_finaldst;
723: /* XXX: assuming M is valid in this case */
724: sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
725: ip6cp->ip6c_finaldst);
726: #ifndef SCOPEDROUTING
727: if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) {
728: /* should be impossible */
729: return;
730: }
731: #endif
732: } else {
733: /* XXX: translate addresses into internal form */
734: sa6 = *(struct sockaddr_in6 *)sa;
735: #ifndef SCOPEDROUTING
736: if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
737: /* should be impossible */
738: return;
739: }
740: #endif
741: }
742:
743: if (ip6) {
744: /*
745: * XXX: We assume that when IPV6 is non NULL,
746: * M and OFF are valid.
747: */
748: struct sockaddr_in6 sa6_src;
749:
750: /* check if we can safely examine src and dst ports */
751: if (m->m_pkthdr.len < off + sizeof(*uhp))
752: return;
753:
754: bzero(&uh, sizeof(uh));
755: m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
756:
757: bzero(&sa6_src, sizeof(sa6_src));
758: sa6_src.sin6_family = AF_INET6;
759: sa6_src.sin6_len = sizeof(sa6_src);
760: sa6_src.sin6_addr = ip6->ip6_src;
761: sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
762: &ip6->ip6_src);
763: #ifndef SCOPEDROUTING
764: if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) {
765: /* should be impossible */
766: return;
767: }
768: #endif
769:
770: if (cmd == PRC_MSGSIZE) {
771: int valid = 0;
772:
773: /*
774: * Check to see if we have a valid UDP socket
775: * corresponding to the address in the ICMPv6 message
776: * payload.
777: */
778: if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr,
779: uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport))
780: valid = 1;
781: #if 0
782: /*
783: * As the use of sendto(2) is fairly popular,
784: * we may want to allow non-connected pcb too.
785: * But it could be too weak against attacks...
786: * We should at least check if the local address (= s)
787: * is really ours.
788: */
789: else if (in6_pcblookup_listen(&udbtable,
790: &sa6_src.sin6_addr, uh.uh_sport, 0);
791: valid = 1;
792: #endif
793:
794: /*
795: * Depending on the value of "valid" and routing table
796: * size (mtudisc_{hi,lo}wat), we will:
797: * - recalculate the new MTU and create the
798: * corresponding routing entry, or
799: * - ignore the MTU change notification.
800: */
801: icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
802:
803: /*
804: * regardless of if we called icmp6_mtudisc_update(),
805: * we need to call in6_pcbnotify(), to notify path
806: * MTU change to the userland (2292bis-02), because
807: * some unconnected sockets may share the same
808: * destination and want to know the path MTU.
809: */
810: }
811:
812: (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6,
813: uh.uh_dport, (struct sockaddr *)&sa6_src,
814: uh.uh_sport, cmd, cmdarg, notify);
815: } else {
816: (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 0,
817: (struct sockaddr *)&sa6_any, 0, cmd, cmdarg, notify);
818: }
819: }
820: #endif
821:
822: void *
823: udp_ctlinput(cmd, sa, v)
824: int cmd;
825: struct sockaddr *sa;
826: void *v;
827: {
828: struct ip *ip = v;
829: struct udphdr *uhp;
830: struct in_addr faddr;
831: struct inpcb *inp;
832: extern int inetctlerrmap[];
833: void (*notify)(struct inpcb *, int) = udp_notify;
834: int errno;
835:
836: if (sa == NULL)
837: return NULL;
838: if (sa->sa_family != AF_INET ||
839: sa->sa_len != sizeof(struct sockaddr_in))
840: return NULL;
841: faddr = satosin(sa)->sin_addr;
842: if (faddr.s_addr == INADDR_ANY)
843: return NULL;
844:
845: if ((unsigned)cmd >= PRC_NCMDS)
846: return NULL;
847: errno = inetctlerrmap[cmd];
848: if (PRC_IS_REDIRECT(cmd))
849: notify = in_rtchange, ip = 0;
850: else if (cmd == PRC_HOSTDEAD)
851: ip = 0;
852: else if (errno == 0)
853: return NULL;
854: if (ip) {
855: uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
856:
857: #ifdef IPSEC
858: /* PMTU discovery for udpencap */
859: if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable &&
860: udpencap_port && uhp->uh_sport == htons(udpencap_port)) {
861: udpencap_ctlinput(cmd, sa, v);
862: return (NULL);
863: }
864: #endif
865: inp = in_pcbhashlookup(&udbtable,
866: ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport);
867: if (inp && inp->inp_socket != NULL)
868: notify(inp, errno);
869: } else
870: in_pcbnotifyall(&udbtable, sa, errno, notify);
871: return (NULL);
872: }
873:
874: int
875: udp_output(struct mbuf *m, ...)
876: {
877: struct inpcb *inp;
878: struct mbuf *addr, *control;
879: struct udpiphdr *ui;
880: int len = m->m_pkthdr.len;
881: struct in_addr laddr;
882: int s = 0, error = 0;
883: va_list ap;
884:
885: va_start(ap, m);
886: inp = va_arg(ap, struct inpcb *);
887: addr = va_arg(ap, struct mbuf *);
888: control = va_arg(ap, struct mbuf *);
889: va_end(ap);
890:
891: #ifdef DIAGNOSTIC
892: if ((inp->inp_flags & INP_IPV6) != 0)
893: panic("IPv6 inpcb to udp_output");
894: #endif
895:
896: /*
897: * Compute the packet length of the IP header, and
898: * punt if the length looks bogus.
899: */
900: if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
901: error = EMSGSIZE;
902: goto release;
903: }
904:
905: if (addr) {
906: laddr = inp->inp_laddr;
907: if (inp->inp_faddr.s_addr != INADDR_ANY) {
908: error = EISCONN;
909: goto release;
910: }
911: /*
912: * Must block input while temporarily connected.
913: */
914: s = splsoftnet();
915: error = in_pcbconnect(inp, addr);
916: if (error) {
917: splx(s);
918: goto release;
919: }
920: } else {
921: if (inp->inp_faddr.s_addr == INADDR_ANY) {
922: error = ENOTCONN;
923: goto release;
924: }
925: }
926: /*
927: * Calculate data length and get a mbuf
928: * for UDP and IP headers.
929: */
930: M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
931: if (m == 0) {
932: error = ENOBUFS;
933: goto bail;
934: }
935:
936: /*
937: * Fill in mbuf with extended UDP header
938: * and addresses and length put into network format.
939: */
940: ui = mtod(m, struct udpiphdr *);
941: bzero(ui->ui_x1, sizeof ui->ui_x1);
942: ui->ui_pr = IPPROTO_UDP;
943: ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
944: ui->ui_src = inp->inp_laddr;
945: ui->ui_dst = inp->inp_faddr;
946: ui->ui_sport = inp->inp_lport;
947: ui->ui_dport = inp->inp_fport;
948: ui->ui_ulen = ui->ui_len;
949:
950: /*
951: * Compute the pseudo-header checksum; defer further checksumming
952: * until ip_output() or hardware (if it exists).
953: */
954: if (udpcksum) {
955: m->m_pkthdr.csum_flags |= M_UDPV4_CSUM_OUT;
956: ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
957: ui->ui_dst.s_addr, htons((u_int16_t)len +
958: sizeof (struct udphdr) + IPPROTO_UDP));
959: } else
960: ui->ui_sum = 0;
961: ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
962: ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl;
963: ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;
964:
965: udpstat.udps_opackets++;
966: error = ip_output(m, inp->inp_options, &inp->inp_route,
967: inp->inp_socket->so_options &
968: (SO_DONTROUTE | SO_BROADCAST | SO_JUMBO),
969: inp->inp_moptions, inp);
970:
971: bail:
972: if (addr) {
973: inp->inp_laddr = laddr;
974: in_pcbdisconnect(inp);
975: splx(s);
976: }
977: if (control)
978: m_freem(control);
979: return (error);
980:
981: release:
982: m_freem(m);
983: if (control)
984: m_freem(control);
985: return (error);
986: }
987:
988: #ifdef INET6
989: /*ARGSUSED*/
990: int
991: udp6_usrreq(so, req, m, addr, control, p)
992: struct socket *so;
993: int req;
994: struct mbuf *m, *addr, *control;
995: struct proc *p;
996: {
997:
998: return udp_usrreq(so, req, m, addr, control);
999: }
1000: #endif
1001:
1002: /*ARGSUSED*/
1003: int
1004: udp_usrreq(so, req, m, addr, control)
1005: struct socket *so;
1006: int req;
1007: struct mbuf *m, *addr, *control;
1008: {
1009: struct inpcb *inp = sotoinpcb(so);
1010: int error = 0;
1011: int s;
1012:
1013: if (req == PRU_CONTROL) {
1014: #ifdef INET6
1015: if (inp->inp_flags & INP_IPV6)
1016: return (in6_control(so, (u_long)m, (caddr_t)addr,
1017: (struct ifnet *)control, 0));
1018: else
1019: #endif /* INET6 */
1020: return (in_control(so, (u_long)m, (caddr_t)addr,
1021: (struct ifnet *)control));
1022: }
1023: if (inp == NULL && req != PRU_ATTACH) {
1024: error = EINVAL;
1025: goto release;
1026: }
1027: /*
1028: * Note: need to block udp_input while changing
1029: * the udp pcb queue and/or pcb addresses.
1030: */
1031: switch (req) {
1032:
1033: case PRU_ATTACH:
1034: if (inp != NULL) {
1035: error = EINVAL;
1036: break;
1037: }
1038: s = splsoftnet();
1039: error = in_pcballoc(so, &udbtable);
1040: splx(s);
1041: if (error)
1042: break;
1043: error = soreserve(so, udp_sendspace, udp_recvspace);
1044: if (error)
1045: break;
1046: #ifdef INET6
1047: if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6)
1048: ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim =
1049: ip6_defhlim;
1050: else
1051: #endif /* INET6 */
1052: ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl;
1053: break;
1054:
1055: case PRU_DETACH:
1056: udp_detach(inp);
1057: break;
1058:
1059: case PRU_BIND:
1060: s = splsoftnet();
1061: #ifdef INET6
1062: if (inp->inp_flags & INP_IPV6)
1063: error = in6_pcbbind(inp, addr);
1064: else
1065: #endif
1066: error = in_pcbbind(inp, addr);
1067: splx(s);
1068: break;
1069:
1070: case PRU_LISTEN:
1071: error = EOPNOTSUPP;
1072: break;
1073:
1074: case PRU_CONNECT:
1075: #ifdef INET6
1076: if (inp->inp_flags & INP_IPV6) {
1077: if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
1078: error = EISCONN;
1079: break;
1080: }
1081: s = splsoftnet();
1082: error = in6_pcbconnect(inp, addr);
1083: splx(s);
1084: } else
1085: #endif /* INET6 */
1086: {
1087: if (inp->inp_faddr.s_addr != INADDR_ANY) {
1088: error = EISCONN;
1089: break;
1090: }
1091: s = splsoftnet();
1092: error = in_pcbconnect(inp, addr);
1093: splx(s);
1094: }
1095:
1096: if (error == 0)
1097: soisconnected(so);
1098: break;
1099:
1100: case PRU_CONNECT2:
1101: error = EOPNOTSUPP;
1102: break;
1103:
1104: case PRU_ACCEPT:
1105: error = EOPNOTSUPP;
1106: break;
1107:
1108: case PRU_DISCONNECT:
1109: #ifdef INET6
1110: if (inp->inp_flags & INP_IPV6) {
1111: if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
1112: error = ENOTCONN;
1113: break;
1114: }
1115: } else
1116: #endif /* INET6 */
1117: {
1118: if (inp->inp_faddr.s_addr == INADDR_ANY) {
1119: error = ENOTCONN;
1120: break;
1121: }
1122: }
1123:
1124: s = splsoftnet();
1125: #ifdef INET6
1126: if (inp->inp_flags & INP_IPV6)
1127: inp->inp_laddr6 = in6addr_any;
1128: else
1129: #endif /* INET6 */
1130: inp->inp_laddr.s_addr = INADDR_ANY;
1131: in_pcbdisconnect(inp);
1132:
1133: splx(s);
1134: so->so_state &= ~SS_ISCONNECTED; /* XXX */
1135: break;
1136:
1137: case PRU_SHUTDOWN:
1138: socantsendmore(so);
1139: break;
1140:
1141: case PRU_SEND:
1142: #ifdef INET6
1143: if (inp->inp_flags & INP_IPV6)
1144: return (udp6_output(inp, m, addr, control));
1145: else
1146: return (udp_output(m, inp, addr, control));
1147: #else
1148: return (udp_output(m, inp, addr, control));
1149: #endif
1150:
1151: case PRU_ABORT:
1152: soisdisconnected(so);
1153: udp_detach(inp);
1154: break;
1155:
1156: case PRU_SOCKADDR:
1157: #ifdef INET6
1158: if (inp->inp_flags & INP_IPV6)
1159: in6_setsockaddr(inp, addr);
1160: else
1161: #endif /* INET6 */
1162: in_setsockaddr(inp, addr);
1163: break;
1164:
1165: case PRU_PEERADDR:
1166: #ifdef INET6
1167: if (inp->inp_flags & INP_IPV6)
1168: in6_setpeeraddr(inp, addr);
1169: else
1170: #endif /* INET6 */
1171: in_setpeeraddr(inp, addr);
1172: break;
1173:
1174: case PRU_SENSE:
1175: /*
1176: * stat: don't bother with a blocksize.
1177: */
1178: /*
1179: * Perhaps Path MTU might be returned for a connected
1180: * UDP socket in this case.
1181: */
1182: return (0);
1183:
1184: case PRU_SENDOOB:
1185: case PRU_FASTTIMO:
1186: case PRU_SLOWTIMO:
1187: case PRU_PROTORCV:
1188: case PRU_PROTOSEND:
1189: error = EOPNOTSUPP;
1190: break;
1191:
1192: case PRU_RCVD:
1193: case PRU_RCVOOB:
1194: return (EOPNOTSUPP); /* do not free mbuf's */
1195:
1196: default:
1197: panic("udp_usrreq");
1198: }
1199:
1200: release:
1201: if (control) {
1202: m_freem(control);
1203: }
1204: if (m)
1205: m_freem(m);
1206: return (error);
1207: }
1208:
1209: void
1210: udp_detach(inp)
1211: struct inpcb *inp;
1212: {
1213: int s = splsoftnet();
1214:
1215: in_pcbdetach(inp);
1216: splx(s);
1217: }
1218:
1219: /*
1220: * Sysctl for udp variables.
1221: */
1222: int
1223: udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1224: int *name;
1225: u_int namelen;
1226: void *oldp;
1227: size_t *oldlenp;
1228: void *newp;
1229: size_t newlen;
1230: {
1231: /* All sysctl names at this level are terminal. */
1232: if (namelen != 1)
1233: return (ENOTDIR);
1234:
1235: switch (name[0]) {
1236: case UDPCTL_BADDYNAMIC:
1237: return (sysctl_struct(oldp, oldlenp, newp, newlen,
1238: baddynamicports.udp, sizeof(baddynamicports.udp)));
1239: default:
1240: if (name[0] < UDPCTL_MAXID)
1241: return (sysctl_int_arr(udpctl_vars, name, namelen,
1242: oldp, oldlenp, newp, newlen));
1243: return (ENOPROTOOPT);
1244: }
1245: /* NOTREACHED */
1246: }
CVSweb