Annotation of src/sys/netinet/udp_usrreq.c, Revision 1.47.4.1
1.47.4.1! thorpej 1: /* $NetBSD: udp_usrreq.c,v 1.48 1999/07/01 08:12:52 itojun Exp $ */
! 2:
! 3: /*
! 4: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
! 5: * All rights reserved.
! 6: *
! 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.
! 18: *
! 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.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the University of
47: * California, Berkeley and its contributors.
48: * 4. Neither the name of the University nor the names of its contributors
49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: *
1.44 thorpej 64: * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
1.1 cgd 65: */
1.38 ws 66: #include "ipkdb.h"
1.1 cgd 67:
1.47.4.1! thorpej 68: /* XXX MAPPED_ADDR_ENABLED should be revisited */
! 69:
1.5 mycroft 70: #include <sys/param.h>
71: #include <sys/malloc.h>
72: #include <sys/mbuf.h>
1.47.4.1! thorpej 73: #ifdef MAPPED_ADDR_ENABLED
! 74: #include <sys/domain.h>
! 75: #endif /* MAPPED_ADDR_ENABLED */
1.5 mycroft 76: #include <sys/protosw.h>
77: #include <sys/socket.h>
78: #include <sys/socketvar.h>
1.13 mycroft 79: #include <sys/errno.h>
1.5 mycroft 80: #include <sys/stat.h>
1.27 christos 81: #include <sys/systm.h>
82: #include <sys/proc.h>
83:
84: #include <vm/vm.h>
85: #include <sys/sysctl.h>
1.1 cgd 86:
1.5 mycroft 87: #include <net/if.h>
88: #include <net/route.h>
1.1 cgd 89:
1.5 mycroft 90: #include <netinet/in.h>
91: #include <netinet/in_systm.h>
1.15 cgd 92: #include <netinet/in_var.h>
1.5 mycroft 93: #include <netinet/ip.h>
94: #include <netinet/in_pcb.h>
95: #include <netinet/ip_var.h>
96: #include <netinet/ip_icmp.h>
97: #include <netinet/udp.h>
98: #include <netinet/udp_var.h>
1.1 cgd 99:
1.27 christos 100: #include <machine/stdarg.h>
101:
1.47.4.1! thorpej 102: #ifdef IPSEC
! 103: #include <netinet6/ipsec.h>
! 104: #include <netkey/key.h>
! 105: #include <netkey/key_debug.h>
! 106: #endif /*IPSEC*/
! 107:
1.8 mycroft 108: /*
109: * UDP protocol implementation.
110: * Per RFC 768, August, 1980.
111: */
112: #ifndef COMPAT_42
113: int udpcksum = 1;
114: #else
115: int udpcksum = 0; /* XXX */
116: #endif
117:
1.13 mycroft 118: static void udp_notify __P((struct inpcb *, int));
1.7 mycroft 119:
1.26 mycroft 120: #ifndef UDBHASHSIZE
121: #define UDBHASHSIZE 128
122: #endif
123: int udbhashsize = UDBHASHSIZE;
124:
1.7 mycroft 125: void
1.1 cgd 126: udp_init()
127: {
1.18 mycroft 128:
1.35 mycroft 129: in_pcbinit(&udbtable, udbhashsize, udbhashsize);
1.1 cgd 130: }
131:
1.7 mycroft 132: void
1.27 christos 133: #if __STDC__
134: udp_input(struct mbuf *m, ...)
135: #else
136: udp_input(m, va_alist)
137: struct mbuf *m;
138: va_dcl
139: #endif
1.1 cgd 140: {
1.47.4.1! thorpej 141: int proto;
1.1 cgd 142: register struct ip *ip;
143: register struct udphdr *uh;
144: register struct inpcb *inp;
145: struct mbuf *opts = 0;
146: int len;
147: struct ip save_ip;
1.27 christos 148: int iphlen;
149: va_list ap;
1.34 mycroft 150: struct sockaddr_in udpsrc;
1.47.4.1! thorpej 151: #ifdef MAPPED_ADDR_ENABLED
! 152: struct sockaddr_in6 mapped;
! 153: #endif
! 154: struct sockaddr *sa;
1.27 christos 155:
156: va_start(ap, m);
157: iphlen = va_arg(ap, int);
1.47.4.1! thorpej 158: proto = va_arg(ap, int);
1.27 christos 159: va_end(ap);
1.1 cgd 160:
161: udpstat.udps_ipackets++;
162:
163: /*
164: * Strip IP options, if any; should skip this,
165: * make available to user, and use on returned packets,
166: * but we don't yet have a way to check the checksum
167: * with options still present.
168: */
169: if (iphlen > sizeof (struct ip)) {
170: ip_stripoptions(m, (struct mbuf *)0);
171: iphlen = sizeof(struct ip);
172: }
173:
174: /*
175: * Get IP and UDP header together in first mbuf.
176: */
177: ip = mtod(m, struct ip *);
178: if (m->m_len < iphlen + sizeof(struct udphdr)) {
179: if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
180: udpstat.udps_hdrops++;
181: return;
182: }
183: ip = mtod(m, struct ip *);
184: }
185: uh = (struct udphdr *)((caddr_t)ip + iphlen);
186:
187: /*
188: * Make mbuf data length reflect UDP length.
189: * If not enough data to reflect UDP length, drop.
190: */
1.15 cgd 191: len = ntohs((u_int16_t)uh->uh_ulen);
1.47 mycroft 192: if (ip->ip_len != iphlen + len) {
193: if (ip->ip_len < iphlen + len) {
1.1 cgd 194: udpstat.udps_badlen++;
195: goto bad;
196: }
1.47 mycroft 197: m_adj(m, iphlen + len - ip->ip_len);
1.1 cgd 198: }
199: /*
200: * Save a copy of the IP header in case we want restore it
201: * for sending an ICMP error message in response.
202: */
203: save_ip = *ip;
204:
205: /*
206: * Checksum extended UDP header and data.
207: */
1.29 mrg 208: if (uh->uh_sum) {
1.25 cgd 209: bzero(((struct ipovly *)ip)->ih_x1,
210: sizeof ((struct ipovly *)ip)->ih_x1);
1.1 cgd 211: ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
1.46 mycroft 212: if (in_cksum(m, len + sizeof (struct ip)) != 0) {
1.1 cgd 213: udpstat.udps_badsum++;
214: m_freem(m);
215: return;
216: }
217: }
1.13 mycroft 218:
1.47.4.1! thorpej 219: /*
! 220: * Construct sockaddr format source address.
! 221: */
! 222: udpsrc.sin_family = AF_INET;
! 223: udpsrc.sin_len = sizeof(struct sockaddr_in);
! 224: udpsrc.sin_addr = ip->ip_src;
! 225: udpsrc.sin_port = uh->uh_sport;
! 226: bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero));
! 227:
1.16 mycroft 228: if (IN_MULTICAST(ip->ip_dst.s_addr) ||
1.13 mycroft 229: in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
1.40 thorpej 230: struct inpcb *last;
1.4 hpeyerl 231: /*
232: * Deliver a multicast or broadcast datagram to *all* sockets
233: * for which the local and remote addresses and ports match
234: * those of the incoming datagram. This allows more than
235: * one process to receive multi/broadcasts on the same port.
236: * (This really ought to be done for unicast datagrams as
237: * well, but that would cause problems with existing
238: * applications that open both address-specific sockets and
239: * a wildcard socket listening to the same port -- they would
240: * end up receiving duplicates of every unicast datagram.
241: * Those applications open the multiple sockets to overcome an
242: * inadequacy of the UDP socket interface, but for backwards
243: * compatibility we avoid the problem here rather than
1.13 mycroft 244: * fixing the interface. Maybe 4.5BSD will remedy this?)
1.4 hpeyerl 245: */
1.13 mycroft 246:
1.47.4.1! thorpej 247: iphlen += sizeof(struct udphdr);
1.4 hpeyerl 248: /*
1.47.4.1! thorpej 249: * KAME note: usually we drop udpiphdr from mbuf here.
! 250: * we need udpiphdr for iPsec processing so we do that later.
1.4 hpeyerl 251: */
252: /*
253: * Locate pcb(s) for datagram.
254: * (Algorithm copied from raw_intr().)
255: */
256: last = NULL;
1.22 cgd 257: for (inp = udbtable.inpt_queue.cqh_first;
258: inp != (struct inpcb *)&udbtable.inpt_queue;
259: inp = inp->inp_queue.cqe_next) {
1.4 hpeyerl 260: if (inp->inp_lport != uh->uh_dport)
261: continue;
1.34 mycroft 262: if (!in_nullhost(inp->inp_laddr)) {
263: if (!in_hosteq(inp->inp_laddr, ip->ip_dst))
1.4 hpeyerl 264: continue;
265: }
1.34 mycroft 266: if (!in_nullhost(inp->inp_faddr)) {
267: if (!in_hosteq(inp->inp_faddr, ip->ip_src) ||
1.4 hpeyerl 268: inp->inp_fport != uh->uh_sport)
269: continue;
270: }
271:
272: if (last != NULL) {
273: struct mbuf *n;
274:
1.47.4.1! thorpej 275: #ifdef IPSEC
! 276: /* check AH/ESP integrity. */
! 277: if (last != NULL && ipsec4_in_reject(m, last)) {
! 278: ipsecstat.in_polvio++;
! 279: /* do not inject data to pcb */
! 280: } else
! 281: #endif /*IPSEC*/
1.4 hpeyerl 282: if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
1.47.4.1! thorpej 283: m_adj(m, iphlen);
1.40 thorpej 284: if (last->inp_flags & INP_CONTROLOPTS
285: || last->inp_socket->so_options &
286: SO_TIMESTAMP) {
287: ip_savecontrol(last, &opts,
288: ip, n);
289: }
1.47.4.1! thorpej 290: sa = (struct sockaddr *)&udpsrc;
! 291: #ifdef MAPPED_ADDR_ENABLED
! 292: if (last->inp_socket->so_proto->pr_domain->dom_family == AF_INET6) {
! 293: in6_sin_2_v4mapsin6(&udpsrc,
! 294: &mapped);
! 295: sa = (struct sockaddr *)&mapped;
! 296: }
! 297: #endif /* MAPPED_ADDR_ENABLED */
1.40 thorpej 298: if (sbappendaddr(
299: &last->inp_socket->so_rcv,
1.47.4.1! thorpej 300: sa, n, opts) == 0) {
1.4 hpeyerl 301: m_freem(n);
1.40 thorpej 302: if (opts)
303: m_freem(opts);
1.13 mycroft 304: } else
1.40 thorpej 305: sorwakeup(last->inp_socket);
306: opts = 0;
1.4 hpeyerl 307: }
308: }
1.40 thorpej 309: last = inp;
1.4 hpeyerl 310: /*
1.13 mycroft 311: * Don't look for additional matches if this one does
312: * not have either the SO_REUSEPORT or SO_REUSEADDR
313: * socket options set. This heuristic avoids searching
314: * through all pcbs in the common case of a non-shared
315: * port. It * assumes that an application will never
316: * clear these options after setting them.
1.4 hpeyerl 317: */
1.40 thorpej 318: if ((last->inp_socket->so_options &
319: (SO_REUSEPORT|SO_REUSEADDR)) == 0)
1.4 hpeyerl 320: break;
321: }
1.6 mycroft 322:
1.4 hpeyerl 323: if (last == NULL) {
324: /*
325: * No matching pcb found; discard datagram.
326: * (No need to send an ICMP Port Unreachable
327: * for a broadcast or multicast datgram.)
328: */
1.47.4.1! thorpej 329: udpstat.udps_noport++;
1.13 mycroft 330: udpstat.udps_noportbcast++;
1.4 hpeyerl 331: goto bad;
332: }
1.47.4.1! thorpej 333: #ifdef IPSEC
! 334: /* check AH/ESP integrity. */
! 335: if (last != NULL && ipsec4_in_reject(m, last)) {
! 336: ipsecstat.in_polvio++;
! 337: goto bad;
! 338: }
! 339: #endif /*IPSEC*/
1.40 thorpej 340: if (last->inp_flags & INP_CONTROLOPTS ||
341: last->inp_socket->so_options & SO_TIMESTAMP)
342: ip_savecontrol(last, &opts, ip, m);
1.47.4.1! thorpej 343: sa = (struct sockaddr *)&udpsrc;
! 344: #ifdef MAPPED_ADDR_ENABLED
! 345: if (last->inp_socket->so_proto->pr_domain->dom_family ==
! 346: AF_INET6) {
! 347: in6_sin_2_v4mapsin6(&udpsrc, &mapped);
! 348: sa = (struct sockaddr *)&mapped;
! 349: }
! 350: #endif /* MAPPED_ADDR_ENABLED */
! 351: if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) {
1.13 mycroft 352: udpstat.udps_fullsock++;
1.4 hpeyerl 353: goto bad;
1.13 mycroft 354: }
1.40 thorpej 355: sorwakeup(last->inp_socket);
1.4 hpeyerl 356: return;
357: }
1.1 cgd 358: /*
359: * Locate pcb for datagram.
360: */
1.35 mycroft 361: inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport,
1.26 mycroft 362: ip->ip_dst, uh->uh_dport);
363: if (inp == 0) {
364: ++udpstat.udps_pcbhashmiss;
1.35 mycroft 365: inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);
1.18 mycroft 366: if (inp == 0) {
367: udpstat.udps_noport++;
368: if (m->m_flags & (M_BCAST | M_MCAST)) {
369: udpstat.udps_noportbcast++;
370: goto bad;
371: }
372: *ip = save_ip;
1.38 ws 373: #if NIPKDB > 0
374: if (checkipkdb(&ip->ip_src,
375: uh->uh_sport,
376: uh->uh_dport,
377: m,
378: iphlen + sizeof(struct udphdr),
379: len - sizeof(struct udphdr)))
1.37 ws 380: /* It was a debugger connect packet, just drop it now */
381: goto bad;
382: #endif
1.18 mycroft 383: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
384: return;
1.13 mycroft 385: }
1.1 cgd 386: }
1.47.4.1! thorpej 387: #ifdef IPSEC
! 388: if (inp != NULL && ipsec4_in_reject(m, inp)) {
! 389: ipsecstat.in_polvio++;
! 390: goto bad;
! 391: }
! 392: #endif /*IPSEC*/
1.1 cgd 393:
394: /*
395: * Stuff source address and datagram in user buffer.
396: */
1.40 thorpej 397: if (inp->inp_flags & INP_CONTROLOPTS ||
398: inp->inp_socket->so_options & SO_TIMESTAMP)
399: ip_savecontrol(inp, &opts, ip, m);
1.1 cgd 400: iphlen += sizeof(struct udphdr);
401: m->m_len -= iphlen;
402: m->m_pkthdr.len -= iphlen;
403: m->m_data += iphlen;
1.47.4.1! thorpej 404: sa = (struct sockaddr *)&udpsrc;
! 405: #ifdef MAPPED_ADDR_ENABLED
! 406: if (inp->inp_socket->so_proto->pr_domain->dom_family == AF_INET6) {
! 407: in6_sin_2_v4mapsin6(&udpsrc, &mapped);
! 408: sa = (struct sockaddr *)&mapped;
! 409: }
! 410: #endif /* MAPPED_ADDR_ENABLED */
! 411: if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) {
1.1 cgd 412: udpstat.udps_fullsock++;
413: goto bad;
414: }
415: sorwakeup(inp->inp_socket);
416: return;
417: bad:
418: m_freem(m);
419: if (opts)
420: m_freem(opts);
421: }
422:
423: /*
424: * Notify a udp user of an asynchronous error;
425: * just wake up so that he can collect error status.
426: */
1.7 mycroft 427: static void
1.1 cgd 428: udp_notify(inp, errno)
429: register struct inpcb *inp;
1.7 mycroft 430: int errno;
1.1 cgd 431: {
1.34 mycroft 432:
1.1 cgd 433: inp->inp_socket->so_error = errno;
434: sorwakeup(inp->inp_socket);
435: sowwakeup(inp->inp_socket);
436: }
437:
1.27 christos 438: void *
439: udp_ctlinput(cmd, sa, v)
1.1 cgd 440: int cmd;
441: struct sockaddr *sa;
1.27 christos 442: void *v;
1.1 cgd 443: {
1.27 christos 444: register struct ip *ip = v;
1.1 cgd 445: register struct udphdr *uh;
1.21 mycroft 446: extern int inetctlerrmap[];
1.18 mycroft 447: void (*notify) __P((struct inpcb *, int)) = udp_notify;
1.21 mycroft 448: int errno;
1.1 cgd 449:
1.20 mycroft 450: if ((unsigned)cmd >= PRC_NCMDS)
1.27 christos 451: return NULL;
1.20 mycroft 452: errno = inetctlerrmap[cmd];
1.18 mycroft 453: if (PRC_IS_REDIRECT(cmd))
1.19 mycroft 454: notify = in_rtchange, ip = 0;
1.18 mycroft 455: else if (cmd == PRC_HOSTDEAD)
1.19 mycroft 456: ip = 0;
1.23 cgd 457: else if (errno == 0)
1.27 christos 458: return NULL;
1.19 mycroft 459: if (ip) {
1.1 cgd 460: uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
1.34 mycroft 461: in_pcbnotify(&udbtable, satosin(sa)->sin_addr, uh->uh_dport,
462: ip->ip_src, uh->uh_sport, errno, notify);
1.19 mycroft 463: } else
1.34 mycroft 464: in_pcbnotifyall(&udbtable, satosin(sa)->sin_addr, errno,
465: notify);
1.27 christos 466: return NULL;
1.1 cgd 467: }
468:
1.7 mycroft 469: int
1.27 christos 470: #if __STDC__
471: udp_output(struct mbuf *m, ...)
472: #else
473: udp_output(m, va_alist)
474: struct mbuf *m;
475: va_dcl
476: #endif
477: {
1.1 cgd 478: register struct inpcb *inp;
479: register struct udpiphdr *ui;
480: register int len = m->m_pkthdr.len;
1.31 mycroft 481: int error = 0;
1.27 christos 482: va_list ap;
483:
484: va_start(ap, m);
485: inp = va_arg(ap, struct inpcb *);
486: va_end(ap);
1.1 cgd 487:
488: /*
489: * Calculate data length and get a mbuf
490: * for UDP and IP headers.
491: */
1.13 mycroft 492: M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
493: if (m == 0) {
494: error = ENOBUFS;
1.39 thorpej 495: goto release;
496: }
497:
498: /*
499: * Compute the packet length of the IP header, and
500: * punt if the length looks bogus.
501: */
502: if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
503: error = EMSGSIZE;
1.13 mycroft 504: goto release;
505: }
1.1 cgd 506:
507: /*
508: * Fill in mbuf with extended UDP header
509: * and addresses and length put into network format.
510: */
511: ui = mtod(m, struct udpiphdr *);
1.25 cgd 512: bzero(ui->ui_x1, sizeof ui->ui_x1);
1.1 cgd 513: ui->ui_pr = IPPROTO_UDP;
1.15 cgd 514: ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
1.1 cgd 515: ui->ui_src = inp->inp_laddr;
516: ui->ui_dst = inp->inp_faddr;
517: ui->ui_sport = inp->inp_lport;
518: ui->ui_dport = inp->inp_fport;
519: ui->ui_ulen = ui->ui_len;
520:
521: /*
522: * Stuff checksum and output datagram.
523: */
524: ui->ui_sum = 0;
525: if (udpcksum) {
526: if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
527: ui->ui_sum = 0xffff;
528: }
529: ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
530: ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
531: ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
532: udpstat.udps_opackets++;
1.47.4.1! thorpej 533:
! 534: #ifdef IPSEC
! 535: m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket;
! 536: #endif /*IPSEC*/
! 537:
1.31 mycroft 538: return (ip_output(m, inp->inp_options, &inp->inp_route,
1.12 mycroft 539: inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
1.31 mycroft 540: inp->inp_moptions));
1.1 cgd 541:
542: release:
543: m_freem(m);
544: return (error);
545: }
546:
1.42 thorpej 547: int udp_sendspace = 9216; /* really max datagram size */
548: int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
1.1 cgd 549: /* 40 1K datagrams */
550:
551: /*ARGSUSED*/
1.7 mycroft 552: int
1.31 mycroft 553: udp_usrreq(so, req, m, nam, control, p)
1.1 cgd 554: struct socket *so;
555: int req;
1.31 mycroft 556: struct mbuf *m, *nam, *control;
1.30 mycroft 557: struct proc *p;
1.1 cgd 558: {
1.31 mycroft 559: register struct inpcb *inp;
1.1 cgd 560: int s;
1.31 mycroft 561: register int error = 0;
1.1 cgd 562:
563: if (req == PRU_CONTROL)
1.31 mycroft 564: return (in_control(so, (long)m, (caddr_t)nam,
1.30 mycroft 565: (struct ifnet *)control, p));
1.31 mycroft 566:
567: s = splsoftnet();
568: inp = sotoinpcb(so);
1.32 mycroft 569: #ifdef DIAGNOSTIC
570: if (req != PRU_SEND && req != PRU_SENDOOB && control)
571: panic("udp_usrreq: unexpected control mbuf");
572: #endif
1.31 mycroft 573: if (inp == 0 && req != PRU_ATTACH) {
574: error = EINVAL;
575: goto release;
576: }
577:
1.1 cgd 578: /*
579: * Note: need to block udp_input while changing
580: * the udp pcb queue and/or pcb addresses.
581: */
582: switch (req) {
583:
584: case PRU_ATTACH:
1.31 mycroft 585: if (inp != 0) {
586: error = EISCONN;
1.1 cgd 587: break;
588: }
1.31 mycroft 589: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
590: error = soreserve(so, udp_sendspace, udp_recvspace);
591: if (error)
592: break;
593: }
1.18 mycroft 594: error = in_pcballoc(so, &udbtable);
1.1 cgd 595: if (error)
596: break;
1.31 mycroft 597: inp = sotoinpcb(so);
598: inp->inp_ip.ip_ttl = ip_defttl;
1.47.4.1! thorpej 599: #ifdef IPSEC
! 600: inp = (struct inpcb *)so->so_pcb;
! 601: error = ipsec_init_policy(&inp->inp_sp);
! 602: #endif /*IPSEC*/
1.1 cgd 603: break;
604:
605: case PRU_DETACH:
1.31 mycroft 606: in_pcbdetach(inp);
1.1 cgd 607: break;
608:
609: case PRU_BIND:
1.31 mycroft 610: error = in_pcbbind(inp, nam, p);
1.1 cgd 611: break;
612:
613: case PRU_LISTEN:
614: error = EOPNOTSUPP;
615: break;
616:
617: case PRU_CONNECT:
1.31 mycroft 618: error = in_pcbconnect(inp, nam);
619: if (error)
1.1 cgd 620: break;
1.31 mycroft 621: soisconnected(so);
1.1 cgd 622: break;
623:
624: case PRU_CONNECT2:
625: error = EOPNOTSUPP;
626: break;
627:
628: case PRU_DISCONNECT:
1.31 mycroft 629: /*soisdisconnected(so);*/
630: so->so_state &= ~SS_ISCONNECTED; /* XXX */
1.1 cgd 631: in_pcbdisconnect(inp);
1.34 mycroft 632: inp->inp_laddr = zeroin_addr; /* XXX */
1.35 mycroft 633: in_pcbstate(inp, INP_BOUND); /* XXX */
1.1 cgd 634: break;
635:
636: case PRU_SHUTDOWN:
637: socantsendmore(so);
638: break;
639:
1.31 mycroft 640: case PRU_RCVD:
641: error = EOPNOTSUPP;
1.1 cgd 642: break;
643:
1.31 mycroft 644: case PRU_SEND:
1.32 mycroft 645: if (control && control->m_len) {
646: m_freem(control);
647: m_freem(m);
648: error = EINVAL;
649: break;
650: }
1.31 mycroft 651: {
1.35 mycroft 652: struct in_addr laddr; /* XXX */
1.1 cgd 653:
1.31 mycroft 654: if (nam) {
1.35 mycroft 655: laddr = inp->inp_laddr; /* XXX */
1.31 mycroft 656: if ((so->so_state & SS_ISCONNECTED) != 0) {
657: error = EISCONN;
1.32 mycroft 658: goto die;
1.31 mycroft 659: }
660: error = in_pcbconnect(inp, nam);
1.32 mycroft 661: if (error) {
662: die:
663: m_freem(m);
1.31 mycroft 664: break;
1.32 mycroft 665: }
1.31 mycroft 666: } else {
667: if ((so->so_state & SS_ISCONNECTED) == 0) {
668: error = ENOTCONN;
1.32 mycroft 669: goto die;
1.31 mycroft 670: }
671: }
1.33 mycroft 672: error = udp_output(m, inp);
1.31 mycroft 673: if (nam) {
674: in_pcbdisconnect(inp);
1.35 mycroft 675: inp->inp_laddr = laddr; /* XXX */
676: in_pcbstate(inp, INP_BOUND); /* XXX */
1.31 mycroft 677: }
678: }
1.1 cgd 679: break;
680:
681: case PRU_SENSE:
682: /*
683: * stat: don't bother with a blocksize.
684: */
1.31 mycroft 685: splx(s);
1.1 cgd 686: return (0);
687:
1.31 mycroft 688: case PRU_RCVOOB:
689: error = EOPNOTSUPP;
690: break;
691:
1.1 cgd 692: case PRU_SENDOOB:
1.32 mycroft 693: m_freem(control);
1.31 mycroft 694: m_freem(m);
1.1 cgd 695: error = EOPNOTSUPP;
696: break;
697:
1.31 mycroft 698: case PRU_SOCKADDR:
699: in_setsockaddr(inp, nam);
700: break;
701:
702: case PRU_PEERADDR:
703: in_setpeeraddr(inp, nam);
704: break;
1.1 cgd 705:
706: default:
707: panic("udp_usrreq");
708: }
709:
710: release:
1.31 mycroft 711: splx(s);
1.1 cgd 712: return (error);
1.13 mycroft 713: }
714:
715: /*
716: * Sysctl for udp variables.
717: */
1.27 christos 718: int
1.13 mycroft 719: udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
720: int *name;
721: u_int namelen;
722: void *oldp;
723: size_t *oldlenp;
724: void *newp;
725: size_t newlen;
726: {
727: /* All sysctl names at this level are terminal. */
728: if (namelen != 1)
729: return (ENOTDIR);
730:
731: switch (name[0]) {
732: case UDPCTL_CHECKSUM:
733: return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));
1.42 thorpej 734: case UDPCTL_SENDSPACE:
735: return (sysctl_int(oldp, oldlenp, newp, newlen,
736: &udp_sendspace));
737: case UDPCTL_RECVSPACE:
738: return (sysctl_int(oldp, oldlenp, newp, newlen,
739: &udp_recvspace));
1.13 mycroft 740: default:
741: return (ENOPROTOOPT);
742: }
743: /* NOTREACHED */
1.1 cgd 744: }
CVSweb <webmaster@jp.NetBSD.org>