|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
55: */
56:
57: #include <sys/param.h>
58: #include <sys/systm.h>
59: #include <sys/kernel.h>
60: #include <sys/malloc.h>
61: #include <sys/mbuf.h>
62: #include <sys/protosw.h>
63: #include <sys/socket.h>
64: #include <sys/socketvar.h>
65: #include <sys/sysctl.h>
66: #include <sys/syslog.h>
67:
68: #if ISFB31
69: #include <vm/vm_zone.h>
70: #endif
71:
72:
73: #include <net/if.h>
74: #include <net/route.h>
75:
76: #include <netinet/in.h>
77: #include <netinet/in_systm.h>
78: #include <netinet/ip.h>
79: #include <netinet/in_pcb.h>
80: #include <netinet/in_var.h>
81: #include <netinet/ip_var.h>
82: #include <netinet/ip_icmp.h>
83: #include <netinet/icmp_var.h>
84: #include <netinet/udp.h>
85: #include <netinet/udp_var.h>
86:
87: #define __STDC__ 1
88: /*
89: * UDP protocol implementation.
90: * Per RFC 768, August, 1980.
91: */
92: #ifndef COMPAT_42
93: static int udpcksum = 1;
94: #else
95: static int udpcksum = 0; /* XXX */
96: #endif
97: SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
98: &udpcksum, 0, "");
99:
100: static int log_in_vain = 0;
101: SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
102: &log_in_vain, 0, "");
103:
104: static struct inpcbhead udb; /* from udp_var.h */
105: struct inpcbinfo udbinfo;
106:
107: #ifndef UDBHASHSIZE
108: #define UDBHASHSIZE 16
109: #endif
110:
111: static struct udpstat udpstat; /* from udp_var.h */
112: SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
113: &udpstat, udpstat, "");
114:
115: static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
116:
117: static int udp_output __P((struct inpcb *, struct mbuf *, struct sockaddr *,
118: struct mbuf *, struct proc *));
119: static void udp_notify __P((struct inpcb *, int));
120:
121: void
122: udp_init()
123: {
124: vm_size_t str_size;
125: int stat;
126: u_char fake_owner;
127: struct in_addr laddr;
128: struct in_addr faddr;
129: u_short lport;
130:
131: LIST_INIT(&udb);
132: udbinfo.listhead = &udb;
133: udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
134: udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
135: &udbinfo.porthashmask);
136: #if ISFB31
137: udbinfo.ipi_zone = zinit("udpcb", sizeof(struct inpcb), maxsockets,
138: ZONE_INTERRUPT, 0);
139: #else
140: str_size = (vm_size_t) sizeof(struct inpcb);
141: udbinfo.ipi_zone = (void *) zinit(str_size, 80000*str_size, 8192, "inpcb_zone");
142: #endif
143:
144: udbinfo.last_pcb = 0;
145: in_pcb_nat_init(&udbinfo, AF_INET, IPPROTO_UDP, SOCK_DGRAM);
146:
147: #if 0
148: stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
149: kprintf("udp_init in_pcb_new_share_client - stat = %d\n", stat);
150:
151: laddr.s_addr = 0x11646464;
152: faddr.s_addr = 0x11646465;
153:
154: lport = 1500;
155: in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner);
156: kprintf("udp_init in_pcb_grab_port - stat = %d\n", stat);
157:
158: stat = in_pcb_rem_share_client(&udbinfo, fake_owner);
159: kprintf("udp_init in_pcb_rem_share_client - stat = %d\n", stat);
160:
161: stat = in_pcb_new_share_client(&udbinfo, &fake_owner);
162: kprintf("udp_init in_pcb_new_share_client(2) - stat = %d\n", stat);
163:
164: laddr.s_addr = 0x11646464;
165: faddr.s_addr = 0x11646465;
166:
167: lport = 1500;
168: stat = in_pcb_grab_port(&udbinfo, 0, laddr, &lport, faddr, 1600, 0, fake_owner);
169: kprintf("udp_init in_pcb_grab_port(2) - stat = %d\n", stat);
170: #endif
171: }
172:
173: void
174: udp_input(m, iphlen)
175: register struct mbuf *m;
176: int iphlen;
177: {
178: register struct ip *ip;
179: register struct udphdr *uh;
180: register struct inpcb *inp;
181: struct mbuf *opts = 0;
182: int len;
183: struct ip save_ip;
184:
185: udpstat.udps_ipackets++;
186:
187: /*
188: * Strip IP options, if any; should skip this,
189: * make available to user, and use on returned packets,
190: * but we don't yet have a way to check the checksum
191: * with options still present.
192: */
193: if (iphlen > sizeof (struct ip)) {
194: ip_stripoptions(m, (struct mbuf *)0);
195: iphlen = sizeof(struct ip);
196: }
197:
198: /*
199: * Get IP and UDP header together in first mbuf.
200: */
201: ip = mtod(m, struct ip *);
202: if (m->m_len < iphlen + sizeof(struct udphdr)) {
203: if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
204: udpstat.udps_hdrops++;
205: return;
206: }
207: ip = mtod(m, struct ip *);
208: }
209: uh = (struct udphdr *)((caddr_t)ip + iphlen);
210:
211: /*
212: * Make mbuf data length reflect UDP length.
213: * If not enough data to reflect UDP length, drop.
214: */
215: len = ntohs((u_short)uh->uh_ulen);
216: if (ip->ip_len != len) {
217: if (len > ip->ip_len || len < sizeof(struct udphdr)) {
218: udpstat.udps_badlen++;
219: goto bad;
220: }
221: m_adj(m, len - ip->ip_len);
222: /* ip->ip_len = len; */
223: }
224: /*
225: * Save a copy of the IP header in case we want restore it
226: * for sending an ICMP error message in response.
227: */
228: save_ip = *ip;
229:
230: /*
231: * Checksum extended UDP header and data.
232: */
233: if (uh->uh_sum) {
234: bzero(((struct ipovly *)ip)->ih_x1, 9);
235: ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
236: uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
237: if (uh->uh_sum) {
238: udpstat.udps_badsum++;
239: m_freem(m);
240: return;
241: }
242: }
243:
244: if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
245: in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
246: struct inpcb *last;
247: /*
248: * Deliver a multicast or broadcast datagram to *all* sockets
249: * for which the local and remote addresses and ports match
250: * those of the incoming datagram. This allows more than
251: * one process to receive multi/broadcasts on the same port.
252: * (This really ought to be done for unicast datagrams as
253: * well, but that would cause problems with existing
254: * applications that open both address-specific sockets and
255: * a wildcard socket listening to the same port -- they would
256: * end up receiving duplicates of every unicast datagram.
257: * Those applications open the multiple sockets to overcome an
258: * inadequacy of the UDP socket interface, but for backwards
259: * compatibility we avoid the problem here rather than
260: * fixing the interface. Maybe 4.5BSD will remedy this?)
261: */
262:
263: /*
264: * Construct sockaddr format source address.
265: */
266: udp_in.sin_port = uh->uh_sport;
267: udp_in.sin_addr = ip->ip_src;
268: m->m_len -= sizeof (struct udpiphdr);
269: m->m_data += sizeof (struct udpiphdr);
270: /*
271: * Locate pcb(s) for datagram.
272: * (Algorithm copied from raw_intr().)
273: */
274: last = NULL;
275: for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
276: if (inp->inp_lport != uh->uh_dport)
277: continue;
278: if (inp->inp_laddr.s_addr != INADDR_ANY) {
279: if (inp->inp_laddr.s_addr !=
280: ip->ip_dst.s_addr)
281: continue;
282: }
283: if (inp->inp_faddr.s_addr != INADDR_ANY) {
284: if (inp->inp_faddr.s_addr !=
285: ip->ip_src.s_addr ||
286: inp->inp_fport != uh->uh_sport)
287: continue;
288: }
289:
290: if (last != NULL) {
291: struct mbuf *n;
292:
293: if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
294: if (last->inp_flags & INP_CONTROLOPTS
295: || last->inp_socket->so_options & SO_TIMESTAMP)
296: ip_savecontrol(last, &opts, ip, n);
297: if (sbappendaddr(&last->inp_socket->so_rcv,
298: (struct sockaddr *)&udp_in,
299: n, opts) == 0) {
300: m_freem(n);
301: if (opts)
302: m_freem(opts);
303: udpstat.udps_fullsock++;
304: } else
305: sorwakeup(last->inp_socket);
306: opts = 0;
307: }
308: }
309: last = inp;
310: /*
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.
317: */
318: if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
319: break;
320: }
321:
322: if (last == NULL) {
323: /*
324: * No matching pcb found; discard datagram.
325: * (No need to send an ICMP Port Unreachable
326: * for a broadcast or multicast datgram.)
327: */
328: udpstat.udps_noportbcast++;
329: goto bad;
330: }
331: if (last->inp_flags & INP_CONTROLOPTS
332: || last->inp_socket->so_options & SO_TIMESTAMP)
333: ip_savecontrol(last, &opts, ip, m);
334: if (sbappendaddr(&last->inp_socket->so_rcv,
335: (struct sockaddr *)&udp_in,
336: m, opts) == 0) {
337: udpstat.udps_fullsock++;
338: goto bad;
339: }
340: sorwakeup(last->inp_socket);
341: return;
342: }
343: /*
344: * Locate pcb for datagram.
345: */
346: inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
347: ip->ip_dst, uh->uh_dport, 1);
348: if (inp == NULL) {
349: if (log_in_vain) {
350: char buf[4*sizeof "123"];
351:
352: strcpy(buf, inet_ntoa(ip->ip_dst));
353: log(LOG_INFO,
354: "Connection attempt to UDP %s:%d from %s:%d\n",
355: buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
356: ntohs(uh->uh_sport));
357: }
358: udpstat.udps_noport++;
359: if (m->m_flags & (M_BCAST | M_MCAST)) {
360: udpstat.udps_noportbcast++;
361: goto bad;
362: }
363: *ip = save_ip;
364: #if ICMP_BANDLIM
365: if (badport_bandlim(0) < 0)
366: goto bad;
367: #endif
368: icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
369: return;
370: }
371:
372: /*
373: * Construct sockaddr format source address.
374: * Stuff source address and datagram in user buffer.
375: */
376: udp_in.sin_port = uh->uh_sport;
377: udp_in.sin_addr = ip->ip_src;
378: if (inp->inp_flags & INP_CONTROLOPTS
379: || inp->inp_socket->so_options & SO_TIMESTAMP)
380: ip_savecontrol(inp, &opts, ip, m);
381: iphlen += sizeof(struct udphdr);
382: m->m_len -= iphlen;
383: m->m_pkthdr.len -= iphlen;
384: m->m_data += iphlen;
385: if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
386: m, opts) == 0) {
387: udpstat.udps_fullsock++;
388: goto bad;
389: }
390: sorwakeup(inp->inp_socket);
391: return;
392: bad:
393: m_freem(m);
394: if (opts)
395: m_freem(opts);
396: }
397:
398: /*
399: * Notify a udp user of an asynchronous error;
400: * just wake up so that he can collect error status.
401: */
402: static void
403: udp_notify(inp, errno)
404: register struct inpcb *inp;
405: int errno;
406: {
407: inp->inp_socket->so_error = errno;
408: sorwakeup(inp->inp_socket);
409: sowwakeup(inp->inp_socket);
410: }
411:
412: void
413: udp_ctlinput(cmd, sa, vip)
414: int cmd;
415: struct sockaddr *sa;
416: void *vip;
417: {
418: register struct ip *ip = vip;
419: register struct udphdr *uh;
420:
421: if (!PRC_IS_REDIRECT(cmd) &&
422: ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0))
423: return;
424: if (ip) {
425: uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
426: in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
427: cmd, udp_notify);
428: } else
429: in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
430: }
431:
432:
433: static int
434: udp_pcblist SYSCTL_HANDLER_ARGS
435: {
436: int error, i, n, s;
437: struct inpcb *inp, **inp_list;
438: inp_gen_t gencnt;
439: struct xinpgen xig;
440:
441: /*
442: * The process of preparing the TCB list is too time-consuming and
443: * resource-intensive to repeat twice on every request.
444: */
445: if (req->oldptr == 0) {
446: n = udbinfo.ipi_count;
447: req->oldidx = 2 * (sizeof xig)
448: + (n + n/8) * sizeof(struct xinpcb);
449: return 0;
450: }
451:
452: if (req->newptr != 0)
453: return EPERM;
454:
455: /*
456: * OK, now we're committed to doing something.
457: */
458: s = splnet();
459: gencnt = udbinfo.ipi_gencnt;
460: n = udbinfo.ipi_count;
461: splx(s);
462:
463: xig.xig_len = sizeof xig;
464: xig.xig_count = n;
465: xig.xig_gen = gencnt;
466: xig.xig_sogen = so_gencnt;
467: error = SYSCTL_OUT(req, &xig, sizeof xig);
468: if (error)
469: return error;
470:
471: inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
472: if (inp_list == 0) {
473: return ENOMEM;
474: }
475: s = splnet();
476: for (inp = udbinfo.listhead->lh_first, i = 0; inp && i < n;
477: inp = inp->inp_list.le_next) {
478: if (inp->inp_gencnt <= gencnt)
479: inp_list[i++] = inp;
480: }
481: splx(s);
482: n = i;
483:
484: error = 0;
485: for (i = 0; i < n; i++) {
486: inp = inp_list[i];
487: if (inp->inp_gencnt <= gencnt) {
488: struct xinpcb xi;
489: xi.xi_len = sizeof xi;
490: /* XXX should avoid extra copy */
491: bcopy(inp, &xi.xi_inp, sizeof *inp);
492: if (inp->inp_socket)
493: sotoxsocket(inp->inp_socket, &xi.xi_socket);
494: error = SYSCTL_OUT(req, &xi, sizeof xi);
495: }
496: }
497: if (!error) {
498: /*
499: * Give the user an updated idea of our state.
500: * If the generation differs from what we told
501: * her before, she knows that something happened
502: * while we were processing this request, and it
503: * might be necessary to retry.
504: */
505: s = splnet();
506: xig.xig_gen = udbinfo.ipi_gencnt;
507: xig.xig_sogen = so_gencnt;
508: xig.xig_count = udbinfo.ipi_count;
509: splx(s);
510: error = SYSCTL_OUT(req, &xig, sizeof xig);
511: }
512: FREE(inp_list, M_TEMP);
513: return error;
514: }
515:
516: SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
517: udp_pcblist, "S,xinpcb", "List of active UDP sockets");
518:
519:
520:
521: static int
522: udp_output(inp, m, addr, control, p)
523: register struct inpcb *inp;
524: register struct mbuf *m;
525: struct sockaddr *addr;
526: struct mbuf *control;
527: struct proc *p;
528: {
529: register struct udpiphdr *ui;
530: register int len = m->m_pkthdr.len;
531: struct in_addr laddr;
532: int s = 0, error = 0;
533:
534: if (control)
535: m_freem(control); /* XXX */
536:
537: if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
538: error = EMSGSIZE;
539: goto release;
540: }
541:
542: if (addr) {
543: laddr = inp->inp_laddr;
544: if (inp->inp_faddr.s_addr != INADDR_ANY) {
545: error = EISCONN;
546: goto release;
547: }
548: /*
549: * Must block input while temporarily connected.
550: */
551: s = splnet();
552: error = in_pcbconnect(inp, addr, p);
553: if (error) {
554: splx(s);
555: goto release;
556: }
557: } else {
558: if (inp->inp_faddr.s_addr == INADDR_ANY) {
559: error = ENOTCONN;
560: goto release;
561: }
562: }
563: /*
564: * Calculate data length and get a mbuf
565: * for UDP and IP headers.
566: */
567: M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
568: if (m == 0) {
569: error = ENOBUFS;
570: if (addr)
571: splx(s);
572: goto release;
573: }
574:
575: /*
576: * Fill in mbuf with extended UDP header
577: * and addresses and length put into network format.
578: */
579: ui = mtod(m, struct udpiphdr *);
580: bzero(ui->ui_x1, sizeof(ui->ui_x1));
581: ui->ui_pr = IPPROTO_UDP;
582: ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
583: ui->ui_src = inp->inp_laddr;
584: ui->ui_dst = inp->inp_faddr;
585: ui->ui_sport = inp->inp_lport;
586: ui->ui_dport = inp->inp_fport;
587: ui->ui_ulen = ui->ui_len;
588:
589: /*
590: * Stuff checksum and output datagram.
591: */
592: ui->ui_sum = 0;
593: if (udpcksum) {
594: if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
595: ui->ui_sum = 0xffff;
596: }
597: ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
598: ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
599: ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
600: udpstat.udps_opackets++;
601: error = ip_output(m, inp->inp_options, &inp->inp_route,
602: inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
603: inp->inp_moptions);
604:
605: if (addr) {
606: in_pcbdisconnect(inp);
607: inp->inp_laddr = laddr; /* XXX rehash? */
608: splx(s);
609: }
610: return (error);
611:
612: release:
613: m_freem(m);
614: return (error);
615: }
616:
617: static u_long udp_sendspace = 9216; /* really max datagram size */
618: /* 40 1K datagrams */
619: SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
620: &udp_sendspace, 0, "");
621:
622: static u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
623: SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
624: &udp_recvspace, 0, "");
625:
626: static int
627: udp_abort(struct socket *so)
628: {
629: struct inpcb *inp;
630: int s;
631:
632: inp = sotoinpcb(so);
633: if (inp == 0)
634: return EINVAL; /* ??? possible? panic instead? */
635: soisdisconnected(so);
636: s = splnet();
637: in_pcbdetach(inp);
638: splx(s);
639: return 0;
640: }
641:
642: static int
643: udp_attach(struct socket *so, int proto, struct proc *p)
644: {
645: struct inpcb *inp;
646: int s, error;
647:
648: inp = sotoinpcb(so);
649: if (inp != 0)
650: return EINVAL;
651:
652: s = splnet();
653: error = in_pcballoc(so, &udbinfo, p);
654: splx(s);
655: if (error)
656: return error;
657: error = soreserve(so, udp_sendspace, udp_recvspace);
658: if (error)
659: return error;
660: ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
661: return 0;
662: }
663:
664: static int
665: udp_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
666: {
667: struct inpcb *inp;
668: int s, error;
669:
670: inp = sotoinpcb(so);
671: if (inp == 0)
672: return EINVAL;
673: s = splnet();
674: error = in_pcbbind(inp, nam, p);
675: splx(s);
676: return error;
677: }
678:
679: static int
680: udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
681: {
682: struct inpcb *inp;
683: int s, error;
684:
685: inp = sotoinpcb(so);
686: if (inp == 0)
687: return EINVAL;
688: if (inp->inp_faddr.s_addr != INADDR_ANY)
689: return EISCONN;
690: s = splnet();
691: error = in_pcbconnect(inp, nam, p);
692: splx(s);
693: if (error == 0)
694: soisconnected(so);
695: return error;
696: }
697:
698: static int
699: udp_detach(struct socket *so)
700: {
701: struct inpcb *inp;
702: int s;
703:
704: inp = sotoinpcb(so);
705: if (inp == 0)
706: return EINVAL;
707: s = splnet();
708: in_pcbdetach(inp);
709: splx(s);
710: return 0;
711: }
712:
713: static int
714: udp_disconnect(struct socket *so)
715: {
716: struct inpcb *inp;
717: int s;
718:
719: inp = sotoinpcb(so);
720: if (inp == 0)
721: return EINVAL;
722: if (inp->inp_faddr.s_addr == INADDR_ANY)
723: return ENOTCONN;
724:
725: s = splnet();
726: in_pcbdisconnect(inp);
727: inp->inp_laddr.s_addr = INADDR_ANY;
728: splx(s);
729: so->so_state &= ~SS_ISCONNECTED; /* XXX */
730: return 0;
731: }
732:
733: static int
734: udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
735: struct mbuf *control, struct proc *p)
736: {
737: struct inpcb *inp;
738:
739: inp = sotoinpcb(so);
740: if (inp == 0) {
741: m_freem(m);
742: return EINVAL;
743: }
744: return udp_output(inp, m, addr, control, p);
745: }
746:
747: static int
748: udp_shutdown(struct socket *so)
749: {
750: struct inpcb *inp;
751:
752: inp = sotoinpcb(so);
753: if (inp == 0)
754: return EINVAL;
755: socantsendmore(so);
756: return 0;
757: }
758:
759: struct pr_usrreqs udp_usrreqs = {
760: udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect,
761: pru_connect2_notsupp, in_control, udp_detach, udp_disconnect,
762: pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
763: pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown,
764: in_setsockaddr, sosend, soreceive, sopoll
765: };
766:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.