|
|
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: /* Copyright (c) 1998, 1999 Apple Computer, Inc. All Rights Reserved */
23: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24: /*
25: * Copyright (c) 1982, 1986, 1988, 1990, 1993
26: * The Regents of the University of California. All rights reserved.
27: *
28: * Redistribution and use in source and binary forms, with or without
29: * modification, are permitted provided that the following conditions
30: * are met:
31: * 1. Redistributions of source code must retain the above copyright
32: * notice, this list of conditions and the following disclaimer.
33: * 2. Redistributions in binary form must reproduce the above copyright
34: * notice, this list of conditions and the following disclaimer in the
35: * documentation and/or other materials provided with the distribution.
36: * 3. All advertising materials mentioning features or use of this software
37: * must display the following acknowledgement:
38: * This product includes software developed by the University of
39: * California, Berkeley and its contributors.
40: * 4. Neither the name of the University nor the names of its contributors
41: * may be used to endorse or promote products derived from this software
42: * without specific prior written permission.
43: *
44: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54: * SUCH DAMAGE.
55: *
56: * @(#)uipc_socket.c 8.6 (Berkeley) 5/2/95
57: */
58:
59: #include <sys/param.h>
60: #include <sys/systm.h>
61: #include <sys/proc.h>
62: #include <sys/fcntl.h>
63: #include <sys/malloc.h>
64: #include <sys/mbuf.h>
65: #include <sys/domain.h>
66: #include <sys/kernel.h>
67: #include <sys/poll.h>
68: #include <sys/protosw.h>
69: #include <sys/socket.h>
70: #include <sys/socketvar.h>
71: #include <sys/resourcevar.h>
72: #include <sys/signalvar.h>
73: #include <sys/sysctl.h>
74: #include <sys/uio.h>
75: #include <sys/ev.h>
76: #include <sys/kdebug.h>
77:
78: #if ISFB31
79: #include <vm/vm_zone.h>
80: #else
81: #include <kern/zalloc.h>
82: #endif
83:
84: #include <machine/limits.h>
85:
86: int socket_debug = 0;
87: int socket_zone = M_SOCKET;
88: so_gen_t so_gencnt; /* generation count for sockets */
89:
90: MALLOC_DEFINE(M_SONAME, "soname", "socket name");
91: MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
92:
93: #if KDEBUG
94: #define DBG_LAYER_IN_BEG NETDBG_CODE(DBG_NETSOCK, 0)
95: #define DBG_LAYER_IN_END NETDBG_CODE(DBG_NETSOCK, 2)
96: #define DBG_LAYER_OUT_BEG NETDBG_CODE(DBG_NETSOCK, 1)
97: #define DBG_LAYER_OUT_END NETDBG_CODE(DBG_NETSOCK, 3)
98: #define DBG_FNC_SOSEND NETDBG_CODE(DBG_NETSOCK, (4 << 8) | 1)
99: #define DBG_FNC_SORECEIVE NETDBG_CODE(DBG_NETSOCK, (8 << 8))
100: #endif
101:
102: SYSCTL_DECL(_kern_ipc);
103:
104: static int somaxconn = SOMAXCONN;
105: SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW, &somaxconn,
106: 0, "");
107:
108: /*
109: * Socket operation routines.
110: * These routines are called by the routines in
111: * sys_socket.c or from a system process, and
112: * implement the semantics of socket operations by
113: * switching out to the protocol specific routines.
114: */
115:
116: void socketinit()
117: {
118: }
119:
120:
121: /*
122: * Get a socket structure from our zone, and initialize it.
123: * We don't implement `waitok' yet (see comments in uipc_domain.c).
124: * Note that it would probably be better to allocate socket
125: * and PCB at the same time, but I'm not convinced that all
126: * the protocols can be easily modified to do this.
127: */
128: struct socket *
129: soalloc(waitok)
130: int waitok;
131: {
132: struct socket *so;
133:
134: so = _MALLOC_ZONE(sizeof(*so), socket_zone, M_WAITOK);
135: if (so) {
136: /* XXX race condition for reentrant kernel */
137: bzero(so, sizeof *so);
138: so->so_gencnt = ++so_gencnt;
139: so->so_zone = socket_zone;
140: }
141: return so;
142: }
143:
144: int
145: socreate(dom, aso, type, proto)
146: int dom;
147: struct socket **aso;
148: register int type;
149: int proto;
150:
151: {
152: struct proc *p = current_proc();
153: register struct protosw *prp;
154: struct socket *so;
155: register int error = 0;
156:
157: if (proto)
158: prp = pffindproto(dom, proto, type);
159: else
160: prp = pffindtype(dom, type);
161: if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
162: return (EPROTONOSUPPORT);
163: if (prp->pr_type != type)
164: return (EPROTOTYPE);
165: so = soalloc(p != 0);
166: if (so == 0)
167: return (ENOBUFS);
168:
169: TAILQ_INIT(&so->so_incomp);
170: TAILQ_INIT(&so->so_comp);
171: so->so_type = type;
172:
173: if (p != 0) {
174: if (p->p_ucred->cr_uid == 0)
175: so->so_state = SS_PRIV;
176:
177: so->so_uid = p->p_ucred->cr_uid;
178: }
179:
180: so->so_proto = prp;
181: so->so_rcv.sb_flags |= SB_RECV; /* XXX */
182: if (prp->pr_sfilter.tqh_first)
183: error = sfilter_init(so);
184: if (error == 0)
185: error = (*prp->pr_usrreqs->pru_attach)(so, proto, p);
186:
187: if (error) {
188: so->so_state |= SS_NOFDREF;
189: sofree(so);
190: return (error);
191: }
192: prp->pr_domain->dom_refs++;
193: so->so_rcv.sb_so = so->so_snd.sb_so = so;
194: TAILQ_INIT(&so->so_evlist);
195: *aso = so;
196: return (0);
197: }
198:
199: int
200: sobind(so, nam)
201: struct socket *so;
202: struct sockaddr *nam;
203:
204: {
205: struct proc *p = current_proc();
206: int error;
207: struct kextcb *kp;
208: int s = splnet();
209:
210: error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam, p);
211: if (error == 0) /* ??? */
212: { kp = sotokextcb(so);
213: while (kp)
214: { if (kp->e_soif && kp->e_soif->sf_sobind)
215: { error = (*kp->e_soif->sf_sobind)(so, nam, kp);
216: if (error)
217: { if (error == EJUSTRETURN)
218: break;
219: splx(s);
220: return(error);
221: }
222: }
223: kp = kp->e_next;
224: }
225: }
226: splx(s);
227: return (error);
228: }
229:
230: void
231: sodealloc(so)
232: struct socket *so;
233: {
234: so->so_gencnt = ++so_gencnt;
235: _FREE_ZONE(so, sizeof(*so), so->so_zone);
236: }
237:
238: int
239: solisten(so, backlog)
240: register struct socket *so;
241: int backlog;
242:
243: {
244: struct kextcb *kp;
245: struct proc *p = current_proc();
246: int s, error;
247:
248: s = splnet();
249: error = (*so->so_proto->pr_usrreqs->pru_listen)(so, p);
250: if (error) {
251: splx(s);
252: return (error);
253: }
254: if (so->so_comp.tqh_first == NULL)
255: so->so_options |= SO_ACCEPTCONN;
256: if (backlog < 0 || backlog > somaxconn)
257: backlog = somaxconn;
258: so->so_qlimit = backlog;
259: kp = sotokextcb(so);
260: while (kp)
261: {
262: if (kp->e_soif && kp->e_soif->sf_solisten)
263: { error = (*kp->e_soif->sf_solisten)(so, kp);
264: if (error)
265: { if (error == EJUSTRETURN)
266: break;
267: splx(s);
268: return(error);
269: }
270: }
271: kp = kp->e_next;
272: }
273:
274: splx(s);
275: return (0);
276: }
277:
278:
279: void
280: sofree(so)
281: register struct socket *so;
282: { int error;
283: struct kextcb *kp;
284: struct socket *head = so->so_head;
285:
286: kp = sotokextcb(so);
287: while (kp)
288: { if (kp->e_soif && kp->e_soif->sf_sofree)
289: { error = (*kp->e_soif->sf_sofree)(so, kp);
290: if (error)
291: return; /* void fn */
292: }
293: kp = kp->e_next;
294: }
295:
296: if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
297: return;
298: if (head != NULL) {
299: if (so->so_state & SS_INCOMP) {
300: TAILQ_REMOVE(&head->so_incomp, so, so_list);
301: head->so_incqlen--;
302: } else if (so->so_state & SS_COMP) {
303: TAILQ_REMOVE(&head->so_comp, so, so_list);
304: } else {
305: panic("sofree: not queued");
306: }
307: head->so_qlen--;
308: so->so_state &= ~(SS_INCOMP|SS_COMP);
309: so->so_head = NULL;
310: }
311:
312: sbrelease(&so->so_snd);
313: sorflush(so);
314: sfilter_term(so);
315: sodealloc(so);
316: }
317:
318: /*
319: * Close a socket on last file table reference removal.
320: * Initiate disconnect if connected.
321: * Free socket when disconnect complete.
322: */
323: int
324: soclose(so)
325: register struct socket *so;
326: {
327: int s = splnet(); /* conservative */
328: int error = 0;
329: struct kextcb *kp;
330:
331: #if FB31SIG
332: funsetown(so->so_pgid);
333: #endif
334: kp = sotokextcb(so);
335: while (kp)
336: { if (kp->e_soif && kp->e_soif->sf_soclose)
337: { error = (*kp->e_soif->sf_soclose)(so, kp);
338: if (error)
339: { splx(s);
340: return((error == EJUSTRETURN) ? 0 : error);
341: }
342: }
343: kp = kp->e_next;
344: }
345:
346: if (so->so_options & SO_ACCEPTCONN) {
347: struct socket *sp, *sonext;
348:
349: for (sp = so->so_incomp.tqh_first; sp != NULL; sp = sonext) {
350: sonext = sp->so_list.tqe_next;
351: (void) soabort(sp);
352: }
353: for (sp = so->so_comp.tqh_first; sp != NULL; sp = sonext) {
354: sonext = sp->so_list.tqe_next;
355: (void) soabort(sp);
356: }
357: }
358: if (so->so_pcb == 0)
359: goto discard;
360: if (so->so_state & SS_ISCONNECTED) {
361: if ((so->so_state & SS_ISDISCONNECTING) == 0) {
362: error = sodisconnect(so);
363: if (error)
364: goto drop;
365: }
366: if (so->so_options & SO_LINGER) {
367: if ((so->so_state & SS_ISDISCONNECTING) &&
368: (so->so_state & SS_NBIO))
369: goto drop;
370: while (so->so_state & SS_ISCONNECTED) {
371: error = tsleep((caddr_t)&so->so_timeo,
372: PSOCK | PCATCH, "soclos", so->so_linger);
373: if (error)
374: break;
375: }
376: }
377: }
378: drop:
379: if (so->so_pcb) {
380: int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
381: if (error == 0)
382: error = error2;
383: }
384: discard:
385: if (so->so_state & SS_NOFDREF)
386: panic("soclose: NOFDREF");
387: so->so_state |= SS_NOFDREF;
388: so->so_proto->pr_domain->dom_refs--;
389: evsofree(so);
390: sofree(so);
391: splx(s);
392: return (error);
393: }
394:
395: /*
396: * Must be called at splnet...
397: */
398: int
399: soabort(so)
400: struct socket *so;
401: {
402:
403: return (*so->so_proto->pr_usrreqs->pru_abort)(so);
404: }
405:
406: int
407: soaccept(so, nam)
408: register struct socket *so;
409: struct sockaddr **nam;
410: { int s = splnet();
411: int error;
412: struct kextcb *kp;
413:
414: if ((so->so_state & SS_NOFDREF) == 0)
415: panic("soaccept: !NOFDREF");
416: so->so_state &= ~SS_NOFDREF;
417: error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
418: if (error == 0)
419: { kp = sotokextcb(so);
420: while (kp) {
421: if (kp->e_soif && kp->e_soif->sf_soaccept)
422: { error = (*kp->e_soif->sf_soaccept)(so, nam, kp);
423: if (error)
424: { if (error == EJUSTRETURN)
425: break;
426: splx(s);
427: return(error);
428: }
429: }
430: kp = kp->e_next;
431: }
432: }
433:
434:
435: splx(s);
436: return (error);
437: }
438:
439: int
440: soconnect(so, nam)
441: register struct socket *so;
442: struct sockaddr *nam;
443:
444: {
445: int s;
446: int error;
447: struct proc *p = current_proc();
448: struct kextcb *kp;
449:
450: if (so->so_options & SO_ACCEPTCONN)
451: return (EOPNOTSUPP);
452: s = splnet();
453: /*
454: * If protocol is connection-based, can only connect once.
455: * Otherwise, if connected, try to disconnect first.
456: * This allows user to disconnect by connecting to, e.g.,
457: * a null address.
458: */
459: if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
460: ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
461: (error = sodisconnect(so))))
462: error = EISCONN;
463: else {
464: error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam, p);
465: if (error == 0)
466: {
467: kp = sotokextcb(so);
468: while (kp)
469: {
470: if (kp->e_soif && kp->e_soif->sf_soconnect)
471: { error = (*kp->e_soif->sf_soconnect)(so, nam, kp);
472: if (error)
473: { if (error == EJUSTRETURN)
474: break;
475: splx(s);
476: return(error);
477: }
478: }
479: kp = kp->e_next;
480: }
481: }
482: }
483:
484: splx(s);
485: return (error);
486: }
487:
488: int
489: soconnect2(so1, so2)
490: register struct socket *so1;
491: struct socket *so2;
492: {
493: int s = splnet();
494: int error;
495: struct kextcb *kp;
496:
497: error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
498: if (error == 0)
499: { kp = sotokextcb(so1);
500: while (kp)
501: { if (kp->e_soif && kp->e_soif->sf_soconnect2)
502: { error = (*kp->e_soif->sf_soconnect2)(so1, so2, kp);
503: if (error)
504: { if (error == EJUSTRETURN)
505: break;
506: splx(s);
507: return(error);
508: }
509: }
510: kp = kp->e_next;
511: }
512: }
513: splx(s);
514: return (error);
515: }
516:
517: int
518: sodisconnect(so)
519: register struct socket *so;
520: {
521: int s = splnet();
522: int error;
523: struct kextcb *kp;
524:
525: if ((so->so_state & SS_ISCONNECTED) == 0) {
526: error = ENOTCONN;
527: goto bad;
528: }
529: if (so->so_state & SS_ISDISCONNECTING) {
530: error = EALREADY;
531: goto bad;
532: }
533: error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
534:
535: if (error == 0)
536: { kp = sotokextcb(so);
537: while (kp)
538: { if (kp->e_soif && kp->e_soif->sf_sodisconnect)
539: { error = (*kp->e_soif->sf_sodisconnect)(so, kp);
540: if (error)
541: { if (error == EJUSTRETURN)
542: break;
543: splx(s);
544: return(error);
545: }
546: }
547: kp = kp->e_next;
548: }
549: }
550:
551: bad:
552: splx(s);
553: return (error);
554: }
555:
556: #define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_DONTWAIT : M_WAIT)
557: /*
558: * Send on a socket.
559: * If send must go all at once and message is larger than
560: * send buffering, then hard error.
561: * Lock against other senders.
562: * If must go all at once and not enough room now, then
563: * inform user that this would block and do nothing.
564: * Otherwise, if nonblocking, send as much as possible.
565: * The data to be sent is described by "uio" if nonzero,
566: * otherwise by the mbuf chain "top" (which must be null
567: * if uio is not). Data provided in mbuf chain must be small
568: * enough to send all at once.
569: *
570: * Returns nonzero on error, timeout or signal; callers
571: * must check for short counts if EINTR/ERESTART are returned.
572: * Data and control buffers are freed on return.
573: * Experiment:
574: * MSG_HOLD: go thru most of sosend(), but just enqueue the mbuf
575: * MSG_SEND: go thru as for MSG_HOLD on current fragment, then
576: * point at the mbuf chain being constructed and go from there.
577: */
578: int
579: sosend(so, addr, uio, top, control, flags)
580: register struct socket *so;
581: struct sockaddr *addr;
582: struct uio *uio;
583: struct mbuf *top;
584: struct mbuf *control;
585: int flags;
586:
587: {
588: struct mbuf **mp;
589: register struct mbuf *m;
590: register long space, len, resid;
591: int clen = 0, error, s, dontroute, mlen, sendflags;
592: int atomic = sosendallatonce(so) || top;
593: struct proc *p = current_proc();
594: struct kextcb *kp;
595:
596: if (uio)
597: resid = uio->uio_resid;
598: else
599: resid = top->m_pkthdr.len;
600:
601: KERNEL_DEBUG((DBG_FNC_SOSEND | DBG_FUNC_START),
602: so,
603: resid,
604: so->so_snd.sb_cc,
605: so->so_snd.sb_lowat,
606: so->so_snd.sb_hiwat);
607:
608: /*
609: * In theory resid should be unsigned.
610: * However, space must be signed, as it might be less than 0
611: * if we over-committed, and we must use a signed comparison
612: * of space and resid. On the other hand, a negative resid
613: * causes us to loop sending 0-length segments to the protocol.
614: *
615: * Also check to make sure that MSG_EOR isn't used on SOCK_STREAM
616: * type sockets since that's an error.
617: */
618: if (resid < 0 || so->so_type == SOCK_STREAM && (flags & MSG_EOR)) {
619: error = EINVAL;
620: goto out;
621: }
622:
623: dontroute =
624: (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
625: (so->so_proto->pr_flags & PR_ATOMIC);
626: if (p)
627: p->p_stats->p_ru.ru_msgsnd++;
628: if (control)
629: clen = control->m_len;
630: #define snderr(errno) { error = errno; splx(s); goto release; }
631:
632: restart:
633: error = sblock(&so->so_snd, SBLOCKWAIT(flags));
634: if (error)
635: goto out;
636: do {
637: s = splnet();
638: if (so->so_state & SS_CANTSENDMORE)
639: snderr(EPIPE);
640: if (so->so_error) {
641: error = so->so_error;
642: so->so_error = 0;
643: splx(s);
644: goto release;
645: }
646: if ((so->so_state & SS_ISCONNECTED) == 0) {
647: /*
648: * `sendto' and `sendmsg' is allowed on a connection-
649: * based socket if it supports implied connect.
650: * Return ENOTCONN if not connected and no address is
651: * supplied.
652: */
653: if ((so->so_proto->pr_flags & PR_CONNREQUIRED) &&
654: (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) {
655: if ((so->so_state & SS_ISCONFIRMING) == 0 &&
656: !(resid == 0 && clen != 0))
657: snderr(ENOTCONN);
658: } else if (addr == 0 && !(flags&MSG_HOLD))
659: snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
660: ENOTCONN : EDESTADDRREQ);
661: }
662: space = sbspace(&so->so_snd);
663: if (flags & MSG_OOB)
664: space += 1024;
665: if ((atomic && resid > so->so_snd.sb_hiwat) ||
666: clen > so->so_snd.sb_hiwat)
667: snderr(EMSGSIZE);
668: if (space < resid + clen && uio &&
669: (atomic || space < so->so_snd.sb_lowat || space < clen)) {
670: if (so->so_state & SS_NBIO)
671: snderr(EWOULDBLOCK);
672: sbunlock(&so->so_snd);
673: error = sbwait(&so->so_snd);
674: splx(s);
675: if (error)
676: goto out;
677: goto restart;
678: }
679: splx(s);
680: mp = ⊤
681: space -= clen;
682: do {
683: if (uio == NULL) {
684: /*
685: * Data is prepackaged in "top".
686: */
687: resid = 0;
688: if (flags & MSG_EOR)
689: top->m_flags |= M_EOR;
690: } else do {
691: KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_NONE, -1, 0, 0, 0, 0);
692: if (top == 0) {
693: MGETHDR(m, M_WAIT, MT_DATA);
694: mlen = MHLEN;
695: m->m_pkthdr.len = 0;
696: m->m_pkthdr.rcvif = (struct ifnet *)0;
697: } else {
698: MGET(m, M_WAIT, MT_DATA);
699: mlen = MLEN;
700: }
701: if (resid >= MINCLSIZE) {
702: MCLGET(m, M_WAIT);
703: if ((m->m_flags & M_EXT) == 0)
704: goto nopages;
705: mlen = MCLBYTES;
706: len = min(min(mlen, resid), space);
707: } else {
708: nopages:
709: len = min(min(mlen, resid), space);
710: /*
711: * For datagram protocols, leave room
712: * for protocol headers in first mbuf.
713: */
714: if (atomic && top == 0 && len < mlen)
715: MH_ALIGN(m, len);
716: }
717: KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_NONE, -1, 0, 0, 0, 0);
718: space -= len;
719: error = uiomove(mtod(m, caddr_t), (int)len, uio);
720: resid = uio->uio_resid;
721:
722: m->m_len = len;
723: *mp = m;
724: top->m_pkthdr.len += len;
725: if (error)
726: goto release;
727: mp = &m->m_next;
728: if (resid <= 0) {
729: if (flags & MSG_EOR)
730: top->m_flags |= M_EOR;
731: break;
732: }
733: } while (space > 0 && (atomic || resid < MINCLSIZE));
734:
735: if (flags & (MSG_HOLD|MSG_SEND))
736: { /* Enqueue for later, go away if HOLD */
737: register struct mbuf *mb1;
738: if (so->so_temp && (flags & MSG_FLUSH))
739: { m_freem(so->so_temp);
740: so->so_temp = NULL;
741: }
742: if (so->so_temp)
743: so->so_tail->m_next = top;
744: else
745: so->so_temp = top;
746: mb1 = top;
747: while (mb1->m_next)
748: mb1 = mb1->m_next;
749: so->so_tail = mb1;
750: if (flags&MSG_HOLD)
751: { top = NULL;
752: goto release;
753: }
754: top = so->so_temp;
755: }
756: if (dontroute)
757: so->so_options |= SO_DONTROUTE;
758: s = splnet(); /* XXX */
759: kp = sotokextcb(so);
760: /* Compute flags here, for pru_send and NKEs */
761: sendflags = (flags & MSG_OOB) ? PRUS_OOB :
762: /*
763: * If the user set MSG_EOF, the protocol
764: * understands this flag and nothing left to
765: * send then use PRU_SEND_EOF instead of PRU_SEND.
766: */
767: ((flags & MSG_EOF) &&
768: (so->so_proto->pr_flags & PR_IMPLOPCL) &&
769: (resid <= 0)) ?
770: PRUS_EOF :
771: /* If there is more to send set PRUS_MORETOCOME */
772: (resid > 0 && space > 0) ? PRUS_MORETOCOME : 0;
773: while (kp)
774: { if (kp->e_soif && kp->e_soif->sf_sosend)
775: { error = (*kp->e_soif->sf_sosend)(so, &addr,
776: &uio, &top,
777: &control,
778: &sendflags,
779: kp);
780: if (error)
781: { if (error == EJUSTRETURN)
782: { sbunlock(&so->so_snd);
783: return(0);
784: }
785: goto release;
786: }
787: }
788: kp = kp->e_next;
789: }
790:
791: error = (*so->so_proto->pr_usrreqs->pru_send)(so,
792: sendflags, top, addr, control, p);
793: splx(s);
794: if (flags & MSG_SEND)
795: so->so_temp = NULL;
796:
797: if (dontroute)
798: so->so_options &= ~SO_DONTROUTE;
799: clen = 0;
800: control = 0;
801: top = 0;
802: mp = ⊤
803: if (error)
804: goto release;
805: } while (resid && space > 0);
806: } while (resid);
807:
808: release:
809: sbunlock(&so->so_snd);
810: out:
811: if (top)
812: m_freem(top);
813: if (control)
814: m_freem(control);
815:
816: KERNEL_DEBUG(DBG_FNC_SOSEND | DBG_FUNC_END,
817: so,
818: resid,
819: so->so_snd.sb_cc,
820: space,
821: error);
822:
823: return (error);
824: }
825:
826: /*
827: * Implement receive operations on a socket.
828: * We depend on the way that records are added to the sockbuf
829: * by sbappend*. In particular, each record (mbufs linked through m_next)
830: * must begin with an address if the protocol so specifies,
831: * followed by an optional mbuf or mbufs containing ancillary data,
832: * and then zero or more mbufs of data.
833: * In order to avoid blocking network interrupts for the entire time here,
834: * we splx() while doing the actual copy to user space.
835: * Although the sockbuf is locked, new data may still be appended,
836: * and thus we must maintain consistency of the sockbuf during that time.
837: *
838: * The caller may receive the data as a single mbuf chain by supplying
839: * an mbuf **mp0 for use in returning the chain. The uio is then used
840: * only for the count in uio_resid.
841: */
842: int
843: soreceive(so, psa, uio, mp0, controlp, flagsp)
844: register struct socket *so;
845: struct sockaddr **psa;
846: struct uio *uio;
847: struct mbuf **mp0;
848: struct mbuf **controlp;
849: int *flagsp;
850: {
851: register struct mbuf *m, **mp;
852: register int flags, len, error, s, offset;
853: struct protosw *pr = so->so_proto;
854: struct mbuf *nextrecord;
855: int moff, type = 0;
856: int orig_resid = uio->uio_resid;
857: struct kextcb *kp;
858:
859: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_START,
860: so,
861: uio->uio_resid,
862: so->so_rcv.sb_cc,
863: so->so_rcv.sb_lowat,
864: so->so_rcv.sb_hiwat);
865:
866: kp = sotokextcb(so);
867: while (kp)
868: { if (kp->e_soif && kp->e_soif->sf_soreceive)
869: { error = (*kp->e_soif->sf_soreceive)(so, psa, &uio,
870: mp0, controlp,
871: flagsp, kp);
872: if (error)
873: return((error == EJUSTRETURN) ? 0 : error);
874: }
875: kp = kp->e_next;
876: }
877:
878: mp = mp0;
879: if (psa)
880: *psa = 0;
881: if (controlp)
882: *controlp = 0;
883: if (flagsp)
884: flags = *flagsp &~ MSG_EOR;
885: else
886: flags = 0;
887: if (flags & MSG_OOB) {
888: m = m_get(M_WAIT, MT_DATA);
889: error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
890: if (error)
891: goto bad;
892: do {
893: error = uiomove(mtod(m, caddr_t),
894: (int) min(uio->uio_resid, m->m_len), uio);
895: m = m_free(m);
896: } while (uio->uio_resid && error == 0 && m);
897: bad:
898: if (m)
899: m_freem(m);
900:
901: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
902: return (error);
903: }
904: if (mp)
905: *mp = (struct mbuf *)0;
906: if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
907: (*pr->pr_usrreqs->pru_rcvd)(so, 0);
908:
909: restart:
910: if (error = sblock(&so->so_rcv, SBLOCKWAIT(flags)))
911: {
912: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
913: return (error);
914: }
915: s = splnet();
916:
917: m = so->so_rcv.sb_mb;
918: /*
919: * If we have less data than requested, block awaiting more
920: * (subject to any timeout) if:
921: * 1. the current count is less than the low water mark, or
922: * 2. MSG_WAITALL is set, and it is possible to do the entire
923: * receive operation at once if we block (resid <= hiwat).
924: * 3. MSG_DONTWAIT is not set
925: * If MSG_WAITALL is set but resid is larger than the receive buffer,
926: * we have to do the receive in sections, and thus risk returning
927: * a short count if a timeout or signal occurs after we start.
928: */
929: if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
930: so->so_rcv.sb_cc < uio->uio_resid) &&
931: (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
932: ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
933: m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
934: KASSERT(m != 0 || !so->so_rcv.sb_cc, ("receive 1"));
935: if (so->so_error) {
936: if (m)
937: goto dontblock;
938: error = so->so_error;
939: if ((flags & MSG_PEEK) == 0)
940: so->so_error = 0;
941: goto release;
942: }
943: if (so->so_state & SS_CANTRCVMORE) {
944: if (m)
945: goto dontblock;
946: else
947: goto release;
948: }
949: for (; m; m = m->m_next)
950: if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
951: m = so->so_rcv.sb_mb;
952: goto dontblock;
953: }
954: if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
955: (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
956: error = ENOTCONN;
957: goto release;
958: }
959: if (uio->uio_resid == 0)
960: goto release;
961: if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
962: error = EWOULDBLOCK;
963: goto release;
964: }
965: sbunlock(&so->so_rcv);
966: if (socket_debug)
967: printf("Waiting for socket data\n");
968: error = sbwait(&so->so_rcv);
969: if (socket_debug)
970: printf("SORECEIVE - sbwait returned %d\n", error);
971: splx(s);
972: if (error)
973: {
974: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, error,0,0,0,0);
975: return (error);
976: }
977: goto restart;
978: }
979: dontblock:
980: #ifdef notyet /* XXXX */
981: if (uio->uio_procp)
982: uio->uio_procp->p_stats->p_ru.ru_msgrcv++;
983: #endif
984: nextrecord = m->m_nextpkt;
985: if ((pr->pr_flags & PR_ADDR) && m->m_type == MT_SONAME) {
986: KASSERT(m->m_type == MT_SONAME, ("receive 1a"));
987: orig_resid = 0;
988: if (psa)
989: *psa = dup_sockaddr(mtod(m, struct sockaddr *),
990: mp0 == 0);
991: if (flags & MSG_PEEK) {
992: m = m->m_next;
993: } else {
994: sbfree(&so->so_rcv, m);
995: MFREE(m, so->so_rcv.sb_mb);
996: m = so->so_rcv.sb_mb;
997: }
998: }
999: while (m && m->m_type == MT_CONTROL && error == 0) {
1000: if (flags & MSG_PEEK) {
1001: if (controlp)
1002: *controlp = m_copy(m, 0, m->m_len);
1003: m = m->m_next;
1004: } else {
1005: sbfree(&so->so_rcv, m);
1006: if (controlp) {
1007: if (pr->pr_domain->dom_externalize &&
1008: mtod(m, struct cmsghdr *)->cmsg_type ==
1009: SCM_RIGHTS)
1010: error = (*pr->pr_domain->dom_externalize)(m);
1011: *controlp = m;
1012: so->so_rcv.sb_mb = m->m_next;
1013: m->m_next = 0;
1014: m = so->so_rcv.sb_mb;
1015: } else {
1016: MFREE(m, so->so_rcv.sb_mb);
1017: m = so->so_rcv.sb_mb;
1018: }
1019: }
1020: if (controlp) {
1021: orig_resid = 0;
1022: controlp = &(*controlp)->m_next;
1023: }
1024: }
1025: if (m) {
1026: if ((flags & MSG_PEEK) == 0)
1027: m->m_nextpkt = nextrecord;
1028: type = m->m_type;
1029: if (type == MT_OOBDATA)
1030: flags |= MSG_OOB;
1031: }
1032: moff = 0;
1033: offset = 0;
1034: while (m && uio->uio_resid > 0 && error == 0) {
1035: if (m->m_type == MT_OOBDATA) {
1036: if (type != MT_OOBDATA)
1037: break;
1038: } else if (type == MT_OOBDATA)
1039: break;
1040: #if 0
1041: /*
1042: * This assertion needs rework. The trouble is Appletalk is uses many
1043: * mbuf types (NOT listed in mbuf.h!) which will trigger this panic.
1044: * For now just remove the assertion... CSM 9/98
1045: */
1046: else
1047: KASSERT(m->m_type == MT_DATA || m->m_type == MT_HEADER,
1048: ("receive 3"));
1049: #endif
1050: so->so_state &= ~SS_RCVATMARK;
1051: len = uio->uio_resid;
1052: if (so->so_oobmark && len > so->so_oobmark - offset)
1053: len = so->so_oobmark - offset;
1054: if (len > m->m_len - moff)
1055: len = m->m_len - moff;
1056: /*
1057: * If mp is set, just pass back the mbufs.
1058: * Otherwise copy them out via the uio, then free.
1059: * Sockbuf must be consistent here (points to current mbuf,
1060: * it points to next record) when we drop priority;
1061: * we must note any additions to the sockbuf when we
1062: * block interrupts again.
1063: */
1064: if (mp == 0) {
1065: splx(s);
1066: error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
1067: s = splnet();
1068: if (error)
1069: goto release;
1070: } else
1071: uio->uio_resid -= len;
1072: if (len == m->m_len - moff) {
1073: if (m->m_flags & M_EOR)
1074: flags |= MSG_EOR;
1075: if (flags & MSG_PEEK) {
1076: m = m->m_next;
1077: moff = 0;
1078: } else {
1079: nextrecord = m->m_nextpkt;
1080: sbfree(&so->so_rcv, m);
1081: if (mp) {
1082: *mp = m;
1083: mp = &m->m_next;
1084: so->so_rcv.sb_mb = m = m->m_next;
1085: *mp = (struct mbuf *)0;
1086: } else {
1087: MFREE(m, so->so_rcv.sb_mb);
1088: m = so->so_rcv.sb_mb;
1089: }
1090: if (m)
1091: m->m_nextpkt = nextrecord;
1092: }
1093: } else {
1094: if (flags & MSG_PEEK)
1095: moff += len;
1096: else {
1097: if (mp)
1098: *mp = m_copym(m, 0, len, M_WAIT);
1099: m->m_data += len;
1100: m->m_len -= len;
1101: so->so_rcv.sb_cc -= len;
1102: }
1103: }
1104: if (so->so_oobmark) {
1105: if ((flags & MSG_PEEK) == 0) {
1106: so->so_oobmark -= len;
1107: if (so->so_oobmark == 0) {
1108: so->so_state |= SS_RCVATMARK;
1109: postevent(so, 0, EV_OOB);
1110: break;
1111: }
1112: } else {
1113: offset += len;
1114: if (offset == so->so_oobmark)
1115: break;
1116: }
1117: }
1118: if (flags & MSG_EOR)
1119: break;
1120: /*
1121: * If the MSG_WAITALL flag is set (for non-atomic socket),
1122: * we must not quit until "uio->uio_resid == 0" or an error
1123: * termination. If a signal/timeout occurs, return
1124: * with a short count but without error.
1125: * Keep sockbuf locked against other readers.
1126: */
1127: while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
1128: !sosendallatonce(so) && !nextrecord) {
1129: if (so->so_error || so->so_state & SS_CANTRCVMORE)
1130: break;
1131: error = sbwait(&so->so_rcv);
1132: if (error) {
1133: sbunlock(&so->so_rcv);
1134: splx(s);
1135: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END, 0,0,0,0,0);
1136: return (0);
1137: }
1138: m = so->so_rcv.sb_mb;
1139: if (m)
1140: nextrecord = m->m_nextpkt;
1141: }
1142: }
1143:
1144: if (m && pr->pr_flags & PR_ATOMIC) {
1145: if (so->so_options & SO_DONTTRUNC)
1146: flags |= MSG_RCVMORE;
1147: else
1148: { flags |= MSG_TRUNC;
1149: if ((flags & MSG_PEEK) == 0)
1150: (void) sbdroprecord(&so->so_rcv);
1151: }
1152: }
1153: if ((flags & MSG_PEEK) == 0) {
1154: if (m == 0)
1155: so->so_rcv.sb_mb = nextrecord;
1156: if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
1157: (*pr->pr_usrreqs->pru_rcvd)(so, flags);
1158: }
1159: if ((so->so_options & SO_WANTMORE) && so->so_rcv.sb_cc > 0)
1160: flags |= MSG_HAVEMORE;
1161: if (orig_resid == uio->uio_resid && orig_resid &&
1162: (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
1163: sbunlock(&so->so_rcv);
1164: splx(s);
1165: goto restart;
1166: }
1167:
1168: if (flagsp)
1169: *flagsp |= flags;
1170: release:
1171: sbunlock(&so->so_rcv);
1172: splx(s);
1173:
1174: KERNEL_DEBUG(DBG_FNC_SORECEIVE | DBG_FUNC_END,
1175: so,
1176: uio->uio_resid,
1177: so->so_rcv.sb_cc,
1178: 0,
1179: error);
1180:
1181: return (error);
1182: }
1183:
1184: int
1185: soshutdown(so, how)
1186: register struct socket *so;
1187: register int how;
1188: {
1189: register struct protosw *pr = so->so_proto;
1190: struct kextcb *kp;
1191: int ret;
1192:
1193: kp = sotokextcb(so);
1194: while (kp)
1195: { if (kp->e_soif && kp->e_soif->sf_soshutdown)
1196: { ret = (*kp->e_soif->sf_soshutdown)(so, how, kp);
1197: if (ret)
1198: return((ret == EJUSTRETURN) ? 0 : ret);
1199: }
1200: kp = kp->e_next;
1201: }
1202:
1203: how++;
1204: if (how & FREAD) {
1205: sorflush(so);
1206: postevent(so, 0, EV_RCLOSED);
1207: }
1208: if (how & FWRITE) {
1209: ret = ((*pr->pr_usrreqs->pru_shutdown)(so));
1210: postevent(so, 0, EV_WCLOSED);
1211: return(ret);
1212: }
1213: return (0);
1214: }
1215:
1216: void
1217: sorflush(so)
1218: register struct socket *so;
1219: {
1220: register struct sockbuf *sb = &so->so_rcv;
1221: register struct protosw *pr = so->so_proto;
1222: register int s, error;
1223: struct sockbuf asb;
1224: struct kextcb *kp;
1225:
1226: kp = sotokextcb(so);
1227: while (kp)
1228: { if (kp->e_soif && kp->e_soif->sf_sorflush)
1229: { if ((*kp->e_soif->sf_sorflush)(so, kp))
1230: return;
1231: }
1232: kp = kp->e_next;
1233: }
1234:
1235: sb->sb_flags |= SB_NOINTR;
1236: (void) sblock(sb, M_WAIT);
1237: s = splimp();
1238: socantrcvmore(so);
1239: sbunlock(sb);
1240: asb = *sb;
1241: bzero((caddr_t)sb, sizeof (*sb));
1242: splx(s);
1243: if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
1244: (*pr->pr_domain->dom_dispose)(asb.sb_mb);
1245: sbrelease(&asb);
1246: }
1247:
1248: /*
1249: * Perhaps this routine, and sooptcopyout(), below, ought to come in
1250: * an additional variant to handle the case where the option value needs
1251: * to be some kind of integer, but not a specific size.
1252: * In addition to their use here, these functions are also called by the
1253: * protocol-level pr_ctloutput() routines.
1254: */
1255: int
1256: sooptcopyin(sopt, buf, len, minlen)
1257: struct sockopt *sopt;
1258: void *buf;
1259: size_t len;
1260: size_t minlen;
1261: {
1262: size_t valsize;
1263:
1264: /*
1265: * If the user gives us more than we wanted, we ignore it,
1266: * but if we don't get the minimum length the caller
1267: * wants, we return EINVAL. On success, sopt->sopt_valsize
1268: * is set to however much we actually retrieved.
1269: */
1270: if ((valsize = sopt->sopt_valsize) < minlen)
1271: return EINVAL;
1272: if (valsize > len)
1273: sopt->sopt_valsize = valsize = len;
1274:
1275: if (sopt->sopt_p != 0)
1276: return (copyin(sopt->sopt_val, buf, valsize));
1277:
1278: bcopy(sopt->sopt_val, buf, valsize);
1279: return 0;
1280: }
1281:
1282: int
1283: sosetopt(so, sopt)
1284: struct socket *so;
1285: struct sockopt *sopt;
1286: {
1287: int error, optval;
1288: struct linger l;
1289: struct timeval tv;
1290: short val;
1291: struct kextcb *kp;
1292:
1293: kp = sotokextcb(so);
1294: while (kp)
1295: { if (kp->e_soif && kp->e_soif->sf_socontrol)
1296: { error = (*kp->e_soif->sf_socontrol)(so, sopt, kp);
1297: if (error)
1298: return((error == EJUSTRETURN) ? 0 : error);
1299: }
1300: kp = kp->e_next;
1301: }
1302:
1303: error = 0;
1304: if (sopt->sopt_level != SOL_SOCKET) {
1305: if (so->so_proto && so->so_proto->pr_ctloutput)
1306: return ((*so->so_proto->pr_ctloutput)
1307: (so, sopt));
1308: error = ENOPROTOOPT;
1309: } else {
1310: switch (sopt->sopt_name) {
1311: case SO_LINGER:
1312: error = sooptcopyin(sopt, &l, sizeof l, sizeof l);
1313: if (error)
1314: goto bad;
1315:
1316: so->so_linger = l.l_linger;
1317: if (l.l_onoff)
1318: so->so_options |= SO_LINGER;
1319: else
1320: so->so_options &= ~SO_LINGER;
1321: break;
1322:
1323: case SO_DEBUG:
1324: case SO_KEEPALIVE:
1325: case SO_DONTROUTE:
1326: case SO_USELOOPBACK:
1327: case SO_BROADCAST:
1328: case SO_REUSEADDR:
1329: case SO_REUSEPORT:
1330: case SO_OOBINLINE:
1331: case SO_TIMESTAMP:
1332: case SO_DONTTRUNC:
1333: case SO_WANTMORE:
1334: error = sooptcopyin(sopt, &optval, sizeof optval,
1335: sizeof optval);
1336: if (error)
1337: goto bad;
1338: if (optval)
1339: so->so_options |= sopt->sopt_name;
1340: else
1341: so->so_options &= ~sopt->sopt_name;
1342: break;
1343:
1344: case SO_SNDBUF:
1345: case SO_RCVBUF:
1346: case SO_SNDLOWAT:
1347: case SO_RCVLOWAT:
1348: error = sooptcopyin(sopt, &optval, sizeof optval,
1349: sizeof optval);
1350: if (error)
1351: goto bad;
1352:
1353: /*
1354: * Values < 1 make no sense for any of these
1355: * options, so disallow them.
1356: */
1357: if (optval < 1) {
1358: error = EINVAL;
1359: goto bad;
1360: }
1361:
1362: switch (sopt->sopt_name) {
1363: case SO_SNDBUF:
1364: case SO_RCVBUF:
1365: if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
1366: &so->so_snd : &so->so_rcv,
1367: (u_long) optval) == 0) {
1368: error = ENOBUFS;
1369: goto bad;
1370: }
1371: break;
1372:
1373: /*
1374: * Make sure the low-water is never greater than
1375: * the high-water.
1376: */
1377: case SO_SNDLOWAT:
1378: so->so_snd.sb_lowat =
1379: (optval > so->so_snd.sb_hiwat) ?
1380: so->so_snd.sb_hiwat : optval;
1381: break;
1382: case SO_RCVLOWAT:
1383: so->so_rcv.sb_lowat =
1384: (optval > so->so_rcv.sb_hiwat) ?
1385: so->so_rcv.sb_hiwat : optval;
1386: break;
1387: }
1388: break;
1389:
1390: case SO_SNDTIMEO:
1391: case SO_RCVTIMEO:
1392: error = sooptcopyin(sopt, &tv, sizeof tv,
1393: sizeof tv);
1394: if (error)
1395: goto bad;
1396:
1397: if (tv.tv_sec > SHRT_MAX / hz - hz) {
1398: error = EDOM;
1399: goto bad;
1400: }
1401: val = tv.tv_sec * hz + tv.tv_usec / tick;
1402:
1403: switch (sopt->sopt_name) {
1404: case SO_SNDTIMEO:
1405: so->so_snd.sb_timeo = val;
1406: break;
1407: case SO_RCVTIMEO:
1408: so->so_rcv.sb_timeo = val;
1409: break;
1410: }
1411: break;
1412:
1413: case SO_NKE:
1414: { struct so_nke nke;
1415: struct NFDescriptor *nf1, *nf2 = NULL;
1416:
1417: error = sooptcopyin(sopt, &nke,
1418: sizeof nke, sizeof nke);
1419: if (error)
1420: goto bad;
1421:
1422: error = nke_insert(so, &nke);
1423: break;
1424: }
1425:
1426: default:
1427: error = ENOPROTOOPT;
1428: break;
1429: }
1430: if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
1431: (void) ((*so->so_proto->pr_ctloutput)
1432: (so, sopt));
1433: }
1434: }
1435: bad:
1436: return (error);
1437: }
1438:
1439: /* Helper routine for getsockopt */
1440: int
1441: sooptcopyout(sopt, buf, len)
1442: struct sockopt *sopt;
1443: void *buf;
1444: size_t len;
1445: {
1446: int error;
1447: size_t valsize;
1448:
1449: error = 0;
1450:
1451: /*
1452: * Documented get behavior is that we always return a value,
1453: * possibly truncated to fit in the user's buffer.
1454: * Traditional behavior is that we always tell the user
1455: * precisely how much we copied, rather than something useful
1456: * like the total amount we had available for her.
1457: * Note that this interface is not idempotent; the entire answer must
1458: * generated ahead of time.
1459: */
1460: valsize = min(len, sopt->sopt_valsize);
1461: sopt->sopt_valsize = valsize;
1462: if (sopt->sopt_val != 0) {
1463: if (sopt->sopt_p != 0)
1464: error = copyout(buf, sopt->sopt_val, valsize);
1465: else
1466: bcopy(buf, sopt->sopt_val, valsize);
1467: }
1468: return error;
1469: }
1470:
1471: int
1472: sogetopt(so, sopt)
1473: struct socket *so;
1474: struct sockopt *sopt;
1475: {
1476: int error, optval;
1477: struct linger l;
1478: struct timeval tv;
1479: struct mbuf *m;
1480: struct kextcb *kp;
1481:
1482: kp = sotokextcb(so);
1483: while (kp)
1484: { if (kp->e_soif && kp->e_soif->sf_socontrol)
1485: { error = (*kp->e_soif->sf_socontrol)(so, sopt, kp);
1486: if (error)
1487: return((error == EJUSTRETURN) ? 0 : error);
1488: }
1489: kp = kp->e_next;
1490: }
1491:
1492: error = 0;
1493: if (sopt->sopt_level != SOL_SOCKET) {
1494: if (so->so_proto && so->so_proto->pr_ctloutput) {
1495: return ((*so->so_proto->pr_ctloutput)
1496: (so, sopt));
1497: } else
1498: return (ENOPROTOOPT);
1499: } else {
1500: switch (sopt->sopt_name) {
1501: case SO_LINGER:
1502: l.l_onoff = so->so_options & SO_LINGER;
1503: l.l_linger = so->so_linger;
1504: error = sooptcopyout(sopt, &l, sizeof l);
1505: break;
1506:
1507: case SO_USELOOPBACK:
1508: case SO_DONTROUTE:
1509: case SO_DEBUG:
1510: case SO_KEEPALIVE:
1511: case SO_REUSEADDR:
1512: case SO_REUSEPORT:
1513: case SO_BROADCAST:
1514: case SO_OOBINLINE:
1515: case SO_TIMESTAMP:
1516: case SO_DONTTRUNC:
1517: case SO_WANTMORE:
1518: optval = so->so_options & sopt->sopt_name;
1519: integer:
1520: error = sooptcopyout(sopt, &optval, sizeof optval);
1521: break;
1522:
1523: case SO_TYPE:
1524: optval = so->so_type;
1525: goto integer;
1526:
1527: case SO_NREAD:
1528: { int pkt_total;
1529: struct mbuf *m1;
1530:
1531: pkt_total = 0;
1532: m1 = so->so_rcv.sb_mb;
1533: if (so->so_proto->pr_flags & PR_ATOMIC)
1534: {
1535: #if 0
1536: kprintf("SKT CC: %d\n", so->so_rcv.sb_cc);
1537: #endif
1538: while (m1)
1539: { if (m1->m_type == MT_DATA)
1540: pkt_total += m1->m_len;
1541: #if 0
1542: kprintf("CNT: %d/%d\n", m1->m_len, pkt_total);
1543: #endif
1544: m1 = m1->m_next;
1545: }
1546: optval = pkt_total;
1547: } else
1548: optval = so->so_rcv.sb_cc;
1549: #if 0
1550: kprintf("RTN: %d\n", optval);
1551: #endif
1552: goto integer;
1553: }
1554: case SO_ERROR:
1555: optval = so->so_error;
1556: so->so_error = 0;
1557: goto integer;
1558:
1559: case SO_SNDBUF:
1560: optval = so->so_snd.sb_hiwat;
1561: goto integer;
1562:
1563: case SO_RCVBUF:
1564: optval = so->so_rcv.sb_hiwat;
1565: goto integer;
1566:
1567: case SO_SNDLOWAT:
1568: optval = so->so_snd.sb_lowat;
1569: goto integer;
1570:
1571: case SO_RCVLOWAT:
1572: optval = so->so_rcv.sb_lowat;
1573: goto integer;
1574:
1575: case SO_SNDTIMEO:
1576: case SO_RCVTIMEO:
1577: optval = (sopt->sopt_name == SO_SNDTIMEO ?
1578: so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
1579:
1580: tv.tv_sec = optval / hz;
1581: tv.tv_usec = (optval % hz) * tick;
1582: error = sooptcopyout(sopt, &tv, sizeof tv);
1583: break;
1584:
1585: default:
1586: error = ENOPROTOOPT;
1587: break;
1588: }
1589: return (error);
1590: }
1591: }
1592:
1593: void
1594: sohasoutofband(so)
1595: register struct socket *so;
1596: {
1597: struct proc *p;
1598:
1599: struct kextcb *kp;
1600:
1601: kp = sotokextcb(so);
1602: while (kp)
1603: { if (kp->e_soif && kp->e_soif->sf_sohasoutofband)
1604: { if ((*kp->e_soif->sf_sohasoutofband)(so, kp))
1605: return;
1606: }
1607: kp = kp->e_next;
1608: }
1609: if (so->so_pgid < 0)
1610: gsignal(-so->so_pgid, SIGURG);
1611: else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
1612: psignal(p, SIGURG);
1613: selwakeup(&so->so_rcv.sb_sel);
1614: }
1615:
1616: /*
1617: * Network filter support
1618: */
1619: /* Run the list of filters, creating extension control blocks */
1620: sfilter_init(register struct socket *so)
1621: { struct kextcb *kp, **kpp;
1622: struct protosw *prp;
1623: struct NFDescriptor *nfp;
1624:
1625: prp = so->so_proto;
1626: nfp = prp->pr_sfilter.tqh_first; /* non-null */
1627: kpp = &so->so_ext;
1628: kp = NULL;
1629: while (nfp)
1630: { MALLOC(kp, struct kextcb *, sizeof(*kp),
1631: M_TEMP, M_WAITOK);
1632: if (kp == NULL)
1633: return(ENOBUFS); /* so_free will clean up */
1634: *kpp = kp;
1635: kpp = &kp->e_next;
1636: kp->e_next = NULL;
1637: kp->e_fcb = NULL;
1638: kp->e_nfd = nfp;
1639: kp->e_soif = nfp->nf_soif;
1640: kp->e_sout = nfp->nf_soutil;
1641: /*
1642: * Ignore return value for create
1643: * Everyone gets a chance at startup
1644: */
1645: if (kp->e_soif && kp->e_soif->sf_socreate)
1646: (*kp->e_soif->sf_socreate)(so, prp, kp);
1647: nfp = nfp->nf_next.tqe_next;
1648: }
1649: return(0);
1650: }
1651:
1652:
1653: /*
1654: * Run the list of filters, freeing extension control blocks
1655: * Assumes the soif/soutil blocks have been handled.
1656: */
1657: sfilter_term(struct socket *so)
1658: { struct kextcb *kp, *kp1;
1659:
1660: kp = so->so_ext;
1661: while (kp)
1662: { kp1 = kp->e_next;
1663: /*
1664: * Ignore return code on termination; everyone must
1665: * get terminated.
1666: */
1667: if (kp->e_soif && kp->e_soif->sf_sofree)
1668: kp->e_soif->sf_sofree(so, kp);
1669: FREE(kp, M_TEMP);
1670: kp = kp1;
1671: }
1672: return(0);
1673: }
1674:
1675:
1676: int
1677: sopoll(struct socket *so, int events, struct ucred *cred)
1678: {
1679: struct proc *p = current_proc();
1680: int revents = 0;
1681: int s = splnet();
1682:
1683: if (events & (POLLIN | POLLRDNORM))
1684: if (soreadable(so))
1685: revents |= events & (POLLIN | POLLRDNORM);
1686:
1687: if (events & (POLLOUT | POLLWRNORM))
1688: if (sowriteable(so))
1689: revents |= events & (POLLOUT | POLLWRNORM);
1690:
1691: if (events & (POLLPRI | POLLRDBAND))
1692: if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
1693: revents |= events & (POLLPRI | POLLRDBAND);
1694:
1695: if (revents == 0) {
1696: if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) {
1697: selrecord(p, &so->so_rcv.sb_sel);
1698: so->so_rcv.sb_flags |= SB_SEL;
1699: }
1700:
1701: if (events & (POLLOUT | POLLWRNORM)) {
1702: selrecord(p, &so->so_snd.sb_sel);
1703: so->so_snd.sb_flags |= SB_SEL;
1704: }
1705: }
1706:
1707: splx(s);
1708: return (revents);
1709: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.