|
|
1.1 cgd 1: /*
2: * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)uipc_socket.c 7.28 (Berkeley) 5/4/91
34: */
35:
36: #include "param.h"
37: #include "proc.h"
38: #include "file.h"
39: #include "malloc.h"
40: #include "mbuf.h"
41: #include "domain.h"
42: #include "kernel.h"
43: #include "protosw.h"
44: #include "socket.h"
45: #include "socketvar.h"
46: #include "resourcevar.h"
47:
48: /*
49: * Socket operation routines.
50: * These routines are called by the routines in
51: * sys_socket.c or from a system process, and
52: * implement the semantics of socket operations by
53: * switching out to the protocol specific routines.
54: */
55: /*ARGSUSED*/
56: socreate(dom, aso, type, proto)
57: struct socket **aso;
58: register int type;
59: int proto;
60: {
61: struct proc *p = curproc; /* XXX */
62: register struct protosw *prp;
63: register struct socket *so;
64: register int error;
65:
66: if (proto)
67: prp = pffindproto(dom, proto, type);
68: else
69: prp = pffindtype(dom, type);
70: if (prp == 0)
71: return (EPROTONOSUPPORT);
72: if (prp->pr_type != type)
73: return (EPROTOTYPE);
74: MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT);
75: bzero((caddr_t)so, sizeof(*so));
76: so->so_type = type;
77: if (p->p_ucred->cr_uid == 0)
78: so->so_state = SS_PRIV;
79: so->so_proto = prp;
80: error =
81: (*prp->pr_usrreq)(so, PRU_ATTACH,
82: (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
83: if (error) {
84: so->so_state |= SS_NOFDREF;
85: sofree(so);
86: return (error);
87: }
88: *aso = so;
89: return (0);
90: }
91:
92: sobind(so, nam)
93: struct socket *so;
94: struct mbuf *nam;
95: {
96: int s = splnet();
97: int error;
98:
99: error =
100: (*so->so_proto->pr_usrreq)(so, PRU_BIND,
101: (struct mbuf *)0, nam, (struct mbuf *)0);
102: splx(s);
103: return (error);
104: }
105:
106: solisten(so, backlog)
107: register struct socket *so;
108: int backlog;
109: {
110: int s = splnet(), error;
111:
112: error =
113: (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
114: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
115: if (error) {
116: splx(s);
117: return (error);
118: }
119: if (so->so_q == 0)
120: so->so_options |= SO_ACCEPTCONN;
121: if (backlog < 0)
122: backlog = 0;
123: so->so_qlimit = min(backlog, SOMAXCONN);
124: splx(s);
125: return (0);
126: }
127:
128: sofree(so)
129: register struct socket *so;
130: {
131:
132: if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
133: return;
134: if (so->so_head) {
135: if (!soqremque(so, 0) && !soqremque(so, 1))
136: panic("sofree dq");
137: so->so_head = 0;
138: }
139: sbrelease(&so->so_snd);
140: sorflush(so);
141: FREE(so, M_SOCKET);
142: }
143:
144: /*
145: * Close a socket on last file table reference removal.
146: * Initiate disconnect if connected.
147: * Free socket when disconnect complete.
148: */
149: soclose(so)
150: register struct socket *so;
151: {
152: int s = splnet(); /* conservative */
153: int error = 0;
154:
155: if (so->so_options & SO_ACCEPTCONN) {
156: while (so->so_q0)
157: (void) soabort(so->so_q0);
158: while (so->so_q)
159: (void) soabort(so->so_q);
160: }
161: if (so->so_pcb == 0)
162: goto discard;
163: if (so->so_state & SS_ISCONNECTED) {
164: if ((so->so_state & SS_ISDISCONNECTING) == 0) {
165: error = sodisconnect(so);
166: if (error)
167: goto drop;
168: }
169: if (so->so_options & SO_LINGER) {
170: if ((so->so_state & SS_ISDISCONNECTING) &&
171: (so->so_state & SS_NBIO))
172: goto drop;
173: while (so->so_state & SS_ISCONNECTED)
174: if (error = tsleep((caddr_t)&so->so_timeo,
175: PSOCK | PCATCH, netcls, so->so_linger))
176: break;
177: }
178: }
179: drop:
180: if (so->so_pcb) {
181: int error2 =
182: (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
183: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
184: if (error == 0)
185: error = error2;
186: }
187: discard:
188: if (so->so_state & SS_NOFDREF)
189: panic("soclose: NOFDREF");
190: so->so_state |= SS_NOFDREF;
191: sofree(so);
192: splx(s);
193: return (error);
194: }
195:
196: /*
197: * Must be called at splnet...
198: */
199: soabort(so)
200: struct socket *so;
201: {
202:
203: return (
204: (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
205: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
206: }
207:
208: soaccept(so, nam)
209: register struct socket *so;
210: struct mbuf *nam;
211: {
212: int s = splnet();
213: int error;
214:
215: if ((so->so_state & SS_NOFDREF) == 0)
216: panic("soaccept: !NOFDREF");
217: so->so_state &= ~SS_NOFDREF;
218: error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
219: (struct mbuf *)0, nam, (struct mbuf *)0);
220: splx(s);
221: return (error);
222: }
223:
224: soconnect(so, nam)
225: register struct socket *so;
226: struct mbuf *nam;
227: {
228: int s;
229: int error;
230:
231: if (so->so_options & SO_ACCEPTCONN)
232: return (EOPNOTSUPP);
233: s = splnet();
234: /*
235: * If protocol is connection-based, can only connect once.
236: * Otherwise, if connected, try to disconnect first.
237: * This allows user to disconnect by connecting to, e.g.,
238: * a null address.
239: */
240: if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
241: ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
242: (error = sodisconnect(so))))
243: error = EISCONN;
244: else
245: error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
246: (struct mbuf *)0, nam, (struct mbuf *)0);
247: splx(s);
248: return (error);
249: }
250:
251: soconnect2(so1, so2)
252: register struct socket *so1;
253: struct socket *so2;
254: {
255: int s = splnet();
256: int error;
257:
258: error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
259: (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
260: splx(s);
261: return (error);
262: }
263:
264: sodisconnect(so)
265: register struct socket *so;
266: {
267: int s = splnet();
268: int error;
269:
270: if ((so->so_state & SS_ISCONNECTED) == 0) {
271: error = ENOTCONN;
272: goto bad;
273: }
274: if (so->so_state & SS_ISDISCONNECTING) {
275: error = EALREADY;
276: goto bad;
277: }
278: error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
279: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
280: bad:
281: splx(s);
282: return (error);
283: }
284:
285: /*
286: * Send on a socket.
287: * If send must go all at once and message is larger than
288: * send buffering, then hard error.
289: * Lock against other senders.
290: * If must go all at once and not enough room now, then
291: * inform user that this would block and do nothing.
292: * Otherwise, if nonblocking, send as much as possible.
293: * The data to be sent is described by "uio" if nonzero,
294: * otherwise by the mbuf chain "top" (which must be null
295: * if uio is not). Data provided in mbuf chain must be small
296: * enough to send all at once.
297: *
298: * Returns nonzero on error, timeout or signal; callers
299: * must check for short counts if EINTR/ERESTART are returned.
300: * Data and control buffers are freed on return.
301: */
302: sosend(so, addr, uio, top, control, flags)
303: register struct socket *so;
304: struct mbuf *addr;
305: struct uio *uio;
306: struct mbuf *top;
307: struct mbuf *control;
308: int flags;
309: {
310: struct proc *p = curproc; /* XXX */
311: struct mbuf **mp;
312: register struct mbuf *m;
313: register long space, len, resid;
314: int clen = 0, error, s, dontroute, mlen;
315: int atomic = sosendallatonce(so) || top;
316:
317: if (uio)
318: resid = uio->uio_resid;
319: else
320: resid = top->m_pkthdr.len;
321: dontroute =
322: (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
323: (so->so_proto->pr_flags & PR_ATOMIC);
324: p->p_stats->p_ru.ru_msgsnd++;
325: if (control)
326: clen = control->m_len;
327: #define snderr(errno) { error = errno; splx(s); goto release; }
328:
329: restart:
330: if (error = sblock(&so->so_snd))
331: goto out;
332: do {
333: s = splnet();
334: if (so->so_state & SS_CANTSENDMORE)
335: snderr(EPIPE);
336: if (so->so_error)
337: snderr(so->so_error);
338: if ((so->so_state & SS_ISCONNECTED) == 0) {
339: if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
340: if ((so->so_state & SS_ISCONFIRMING) == 0 &&
341: !(resid == 0 && clen != 0))
342: snderr(ENOTCONN);
343: } else if (addr == 0)
344: snderr(EDESTADDRREQ);
345: }
346: space = sbspace(&so->so_snd);
347: if (flags & MSG_OOB)
348: space += 1024;
349: if (space < resid + clen &&
350: (atomic || space < so->so_snd.sb_lowat || space < clen)) {
351: if (atomic && resid > so->so_snd.sb_hiwat ||
352: clen > so->so_snd.sb_hiwat)
353: snderr(EMSGSIZE);
354: if (so->so_state & SS_NBIO)
355: snderr(EWOULDBLOCK);
356: sbunlock(&so->so_snd);
357: error = sbwait(&so->so_snd);
358: splx(s);
359: if (error)
360: goto out;
361: goto restart;
362: }
363: splx(s);
364: mp = ⊤
365: space -= clen;
366: do {
367: if (uio == NULL) {
368: /*
369: * Data is prepackaged in "top".
370: */
371: resid = 0;
372: if (flags & MSG_EOR)
373: top->m_flags |= M_EOR;
374: } else do {
375: if (top == 0) {
376: MGETHDR(m, M_WAIT, MT_DATA);
377: mlen = MHLEN;
378: m->m_pkthdr.len = 0;
379: m->m_pkthdr.rcvif = (struct ifnet *)0;
380: } else {
381: MGET(m, M_WAIT, MT_DATA);
382: mlen = MLEN;
383: }
384: if (resid >= MINCLSIZE && space >= MCLBYTES) {
385: MCLGET(m, M_WAIT);
386: if ((m->m_flags & M_EXT) == 0)
387: goto nopages;
388: mlen = MCLBYTES;
389: #ifdef MAPPED_MBUFS
390: len = min(MCLBYTES, resid);
391: #else
392: if (top == 0) {
393: len = min(MCLBYTES - max_hdr, resid);
394: m->m_data += max_hdr;
395: } else
396: len = min(MCLBYTES, resid);
397: #endif
398: space -= MCLBYTES;
399: } else {
400: nopages:
401: len = min(min(mlen, resid), space);
402: space -= len;
403: /*
404: * For datagram protocols, leave room
405: * for protocol headers in first mbuf.
406: */
407: if (atomic && top == 0 && len < mlen)
408: MH_ALIGN(m, len);
409: }
410: error = uiomove(mtod(m, caddr_t), (int)len, uio);
411: resid = uio->uio_resid;
412: m->m_len = len;
413: *mp = m;
414: top->m_pkthdr.len += len;
415: if (error)
416: goto release;
417: mp = &m->m_next;
418: if (resid <= 0) {
419: if (flags & MSG_EOR)
420: top->m_flags |= M_EOR;
421: break;
422: }
423: } while (space > 0 && atomic);
424: if (dontroute)
425: so->so_options |= SO_DONTROUTE;
426: s = splnet(); /* XXX */
427: error = (*so->so_proto->pr_usrreq)(so,
428: (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
429: top, addr, control);
430: splx(s);
431: if (dontroute)
432: so->so_options &= ~SO_DONTROUTE;
433: clen = 0;
434: control = 0;
435: top = 0;
436: mp = ⊤
437: if (error)
438: goto release;
439: } while (resid && space > 0);
440: } while (resid);
441:
442: release:
443: sbunlock(&so->so_snd);
444: out:
445: if (top)
446: m_freem(top);
447: if (control)
448: m_freem(control);
449: return (error);
450: }
451:
452: /*
453: * Implement receive operations on a socket.
454: * We depend on the way that records are added to the sockbuf
455: * by sbappend*. In particular, each record (mbufs linked through m_next)
456: * must begin with an address if the protocol so specifies,
457: * followed by an optional mbuf or mbufs containing ancillary data,
458: * and then zero or more mbufs of data.
459: * In order to avoid blocking network interrupts for the entire time here,
460: * we splx() while doing the actual copy to user space.
461: * Although the sockbuf is locked, new data may still be appended,
462: * and thus we must maintain consistency of the sockbuf during that time.
463: *
464: * The caller may receive the data as a single mbuf chain by supplying
465: * an mbuf **mp0 for use in returning the chain. The uio is then used
466: * only for the count in uio_resid.
467: */
468: soreceive(so, paddr, uio, mp0, controlp, flagsp)
469: register struct socket *so;
470: struct mbuf **paddr;
471: struct uio *uio;
472: struct mbuf **mp0;
473: struct mbuf **controlp;
474: int *flagsp;
475: {
476: struct proc *p = curproc; /* XXX */
477: register struct mbuf *m, **mp;
478: register int flags, len, error, s, offset;
479: struct protosw *pr = so->so_proto;
480: struct mbuf *nextrecord;
481: int moff, type;
482:
483: mp = mp0;
484: if (paddr)
485: *paddr = 0;
486: if (controlp)
487: *controlp = 0;
488: if (flagsp)
489: flags = *flagsp &~ MSG_EOR;
490: else
491: flags = 0;
492: if (flags & MSG_OOB) {
493: m = m_get(M_WAIT, MT_DATA);
494: error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
495: m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
496: if (error)
497: goto bad;
498: do {
499: error = uiomove(mtod(m, caddr_t),
500: (int) min(uio->uio_resid, m->m_len), uio);
501: m = m_free(m);
502: } while (uio->uio_resid && error == 0 && m);
503: bad:
504: if (m)
505: m_freem(m);
506: return (error);
507: }
508: if (mp)
509: *mp = (struct mbuf *)0;
510: if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
511: (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
512: (struct mbuf *)0, (struct mbuf *)0);
513:
514: restart:
515: if (error = sblock(&so->so_rcv))
516: return (error);
517: s = splnet();
518:
519: m = so->so_rcv.sb_mb;
520: /*
521: * If we have less data than requested, block awaiting more
522: * (subject to any timeout) if:
523: * 1. the current count is less than the low water mark, or
524: * 2. MSG_WAITALL is set, and it is possible to do the entire
525: * receive operation at once if we block (resid <= hiwat).
526: * If MSG_WAITALL is set but resid is larger than the receive buffer,
527: * we have to do the receive in sections, and thus risk returning
528: * a short count if a timeout or signal occurs after we start.
529: */
530: while (m == 0 || so->so_rcv.sb_cc < uio->uio_resid &&
531: (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
532: ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
533: m->m_nextpkt == 0) {
534: #ifdef DIAGNOSTIC
535: if (m == 0 && so->so_rcv.sb_cc)
536: panic("receive 1");
537: #endif
538: if (so->so_error) {
539: if (m)
540: break;
541: error = so->so_error;
542: if ((flags & MSG_PEEK) == 0)
543: so->so_error = 0;
544: goto release;
545: }
546: if (so->so_state & SS_CANTRCVMORE) {
547: if (m)
548: break;
549: else
550: goto release;
551: }
552: for (; m; m = m->m_next)
553: if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
554: m = so->so_rcv.sb_mb;
555: goto dontblock;
556: }
557: if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
558: (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
559: error = ENOTCONN;
560: goto release;
561: }
562: if (uio->uio_resid == 0)
563: goto release;
564: if (so->so_state & SS_NBIO) {
565: error = EWOULDBLOCK;
566: goto release;
567: }
568: sbunlock(&so->so_rcv);
569: error = sbwait(&so->so_rcv);
570: splx(s);
571: if (error)
572: return (error);
573: goto restart;
574: }
575: dontblock:
576: p->p_stats->p_ru.ru_msgrcv++;
577: nextrecord = m->m_nextpkt;
578: if (pr->pr_flags & PR_ADDR) {
579: #ifdef DIAGNOSTIC
580: if (m->m_type != MT_SONAME)
581: panic("receive 1a");
582: #endif
583: if (flags & MSG_PEEK) {
584: if (paddr)
585: *paddr = m_copy(m, 0, m->m_len);
586: m = m->m_next;
587: } else {
588: sbfree(&so->so_rcv, m);
589: if (paddr) {
590: *paddr = m;
591: so->so_rcv.sb_mb = m->m_next;
592: m->m_next = 0;
593: m = so->so_rcv.sb_mb;
594: } else {
595: MFREE(m, so->so_rcv.sb_mb);
596: m = so->so_rcv.sb_mb;
597: }
598: }
599: }
600: while (m && m->m_type == MT_CONTROL && error == 0) {
601: if (flags & MSG_PEEK) {
602: if (controlp)
603: *controlp = m_copy(m, 0, m->m_len);
604: m = m->m_next;
605: } else {
606: sbfree(&so->so_rcv, m);
607: if (controlp) {
608: if (pr->pr_domain->dom_externalize &&
609: mtod(m, struct cmsghdr *)->cmsg_type ==
610: SCM_RIGHTS)
611: error = (*pr->pr_domain->dom_externalize)(m);
612: *controlp = m;
613: so->so_rcv.sb_mb = m->m_next;
614: m->m_next = 0;
615: m = so->so_rcv.sb_mb;
616: } else {
617: MFREE(m, so->so_rcv.sb_mb);
618: m = so->so_rcv.sb_mb;
619: }
620: }
621: if (controlp)
622: controlp = &(*controlp)->m_next;
623: }
624: if (m) {
625: if ((flags & MSG_PEEK) == 0)
626: m->m_nextpkt = nextrecord;
627: type = m->m_type;
628: if (type == MT_OOBDATA)
629: flags |= MSG_OOB;
630: }
631: moff = 0;
632: offset = 0;
633: while (m && uio->uio_resid > 0 && error == 0) {
634: if (m->m_type == MT_OOBDATA) {
635: if (type != MT_OOBDATA)
636: break;
637: } else if (type == MT_OOBDATA)
638: break;
639: #ifdef DIAGNOSTIC
640: else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
641: panic("receive 3");
642: #endif
643: so->so_state &= ~SS_RCVATMARK;
644: len = uio->uio_resid;
645: if (so->so_oobmark && len > so->so_oobmark - offset)
646: len = so->so_oobmark - offset;
647: if (len > m->m_len - moff)
648: len = m->m_len - moff;
649: /*
650: * If mp is set, just pass back the mbufs.
651: * Otherwise copy them out via the uio, then free.
652: * Sockbuf must be consistent here (points to current mbuf,
653: * it points to next record) when we drop priority;
654: * we must note any additions to the sockbuf when we
655: * block interrupts again.
656: */
657: if (mp == 0) {
658: splx(s);
659: error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
660: s = splnet();
661: } else
662: uio->uio_resid -= len;
663: if (len == m->m_len - moff) {
664: if (m->m_flags & M_EOR)
665: flags |= MSG_EOR;
666: if (flags & MSG_PEEK) {
667: m = m->m_next;
668: moff = 0;
669: } else {
670: nextrecord = m->m_nextpkt;
671: sbfree(&so->so_rcv, m);
672: if (mp) {
673: *mp = m;
674: mp = &m->m_next;
675: so->so_rcv.sb_mb = m = m->m_next;
676: *mp = (struct mbuf *)0;
677: } else {
678: MFREE(m, so->so_rcv.sb_mb);
679: m = so->so_rcv.sb_mb;
680: }
681: if (m)
682: m->m_nextpkt = nextrecord;
683: }
684: } else {
685: if (flags & MSG_PEEK)
686: moff += len;
687: else {
688: if (mp)
689: *mp = m_copym(m, 0, len, M_WAIT);
690: m->m_data += len;
691: m->m_len -= len;
692: so->so_rcv.sb_cc -= len;
693: }
694: }
695: if (so->so_oobmark) {
696: if ((flags & MSG_PEEK) == 0) {
697: so->so_oobmark -= len;
698: if (so->so_oobmark == 0) {
699: so->so_state |= SS_RCVATMARK;
700: break;
701: }
702: } else
703: offset += len;
704: }
705: if (flags & MSG_EOR)
706: break;
707: /*
708: * If the MSG_WAITALL flag is set (for non-atomic socket),
709: * we must not quit until "uio->uio_resid == 0" or an error
710: * termination. If a signal/timeout occurs, return
711: * with a short count but without error.
712: * Keep sockbuf locked against other readers.
713: */
714: while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
715: !sosendallatonce(so)) {
716: if (so->so_error || so->so_state & SS_CANTRCVMORE)
717: break;
718: error = sbwait(&so->so_rcv);
719: if (error) {
720: sbunlock(&so->so_rcv);
721: splx(s);
722: return (0);
723: }
724: if (m = so->so_rcv.sb_mb)
725: nextrecord = m->m_nextpkt;
726: }
727: }
728: if ((flags & MSG_PEEK) == 0) {
729: if (m == 0)
730: so->so_rcv.sb_mb = nextrecord;
731: else if (pr->pr_flags & PR_ATOMIC) {
732: flags |= MSG_TRUNC;
733: (void) sbdroprecord(&so->so_rcv);
734: }
735: if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
736: (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
737: (struct mbuf *)flags, (struct mbuf *)0,
738: (struct mbuf *)0);
739: }
740: if (flagsp)
741: *flagsp |= flags;
742: release:
743: sbunlock(&so->so_rcv);
744: splx(s);
745: return (error);
746: }
747:
748: soshutdown(so, how)
749: register struct socket *so;
750: register int how;
751: {
752: register struct protosw *pr = so->so_proto;
753:
754: how++;
755: if (how & FREAD)
756: sorflush(so);
757: if (how & FWRITE)
758: return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
759: (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
760: return (0);
761: }
762:
763: sorflush(so)
764: register struct socket *so;
765: {
766: register struct sockbuf *sb = &so->so_rcv;
767: register struct protosw *pr = so->so_proto;
768: register int s;
769: struct sockbuf asb;
770:
771: sb->sb_flags |= SB_NOINTR;
772: (void) sblock(sb);
773: s = splimp();
774: socantrcvmore(so);
775: sbunlock(sb);
776: asb = *sb;
777: bzero((caddr_t)sb, sizeof (*sb));
778: splx(s);
779: if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
780: (*pr->pr_domain->dom_dispose)(asb.sb_mb);
781: sbrelease(&asb);
782: }
783:
784: sosetopt(so, level, optname, m0)
785: register struct socket *so;
786: int level, optname;
787: struct mbuf *m0;
788: {
789: int error = 0;
790: register struct mbuf *m = m0;
791:
792: if (level != SOL_SOCKET) {
793: if (so->so_proto && so->so_proto->pr_ctloutput)
794: return ((*so->so_proto->pr_ctloutput)
795: (PRCO_SETOPT, so, level, optname, &m0));
796: error = ENOPROTOOPT;
797: } else {
798: switch (optname) {
799:
800: case SO_LINGER:
801: if (m == NULL || m->m_len != sizeof (struct linger)) {
802: error = EINVAL;
803: goto bad;
804: }
805: so->so_linger = mtod(m, struct linger *)->l_linger;
806: /* fall thru... */
807:
808: case SO_DEBUG:
809: case SO_KEEPALIVE:
810: case SO_DONTROUTE:
811: case SO_USELOOPBACK:
812: case SO_BROADCAST:
813: case SO_REUSEADDR:
814: case SO_OOBINLINE:
815: if (m == NULL || m->m_len < sizeof (int)) {
816: error = EINVAL;
817: goto bad;
818: }
819: if (*mtod(m, int *))
820: so->so_options |= optname;
821: else
822: so->so_options &= ~optname;
823: break;
824:
825: case SO_SNDBUF:
826: case SO_RCVBUF:
827: case SO_SNDLOWAT:
828: case SO_RCVLOWAT:
829: if (m == NULL || m->m_len < sizeof (int)) {
830: error = EINVAL;
831: goto bad;
832: }
833: switch (optname) {
834:
835: case SO_SNDBUF:
836: case SO_RCVBUF:
837: if (sbreserve(optname == SO_SNDBUF ?
838: &so->so_snd : &so->so_rcv,
839: (u_long) *mtod(m, int *)) == 0) {
840: error = ENOBUFS;
841: goto bad;
842: }
843: break;
844:
845: case SO_SNDLOWAT:
846: so->so_snd.sb_lowat = *mtod(m, int *);
847: break;
848: case SO_RCVLOWAT:
849: so->so_rcv.sb_lowat = *mtod(m, int *);
850: break;
851: }
852: break;
853:
854: case SO_SNDTIMEO:
855: case SO_RCVTIMEO:
856: {
857: struct timeval *tv;
858: short val;
859:
860: if (m == NULL || m->m_len < sizeof (*tv)) {
861: error = EINVAL;
862: goto bad;
863: }
864: tv = mtod(m, struct timeval *);
865: if (tv->tv_sec > SHRT_MAX / hz - hz) {
866: error = EDOM;
867: goto bad;
868: }
869: val = tv->tv_sec * hz + tv->tv_usec / tick;
870:
871: switch (optname) {
872:
873: case SO_SNDTIMEO:
874: so->so_snd.sb_timeo = val;
875: break;
876: case SO_RCVTIMEO:
877: so->so_rcv.sb_timeo = val;
878: break;
879: }
880: break;
881: }
882:
883: default:
884: error = ENOPROTOOPT;
885: break;
886: }
887: }
888: bad:
889: if (m)
890: (void) m_free(m);
891: return (error);
892: }
893:
894: sogetopt(so, level, optname, mp)
895: register struct socket *so;
896: int level, optname;
897: struct mbuf **mp;
898: {
899: register struct mbuf *m;
900:
901: if (level != SOL_SOCKET) {
902: if (so->so_proto && so->so_proto->pr_ctloutput) {
903: return ((*so->so_proto->pr_ctloutput)
904: (PRCO_GETOPT, so, level, optname, mp));
905: } else
906: return (ENOPROTOOPT);
907: } else {
908: m = m_get(M_WAIT, MT_SOOPTS);
909: m->m_len = sizeof (int);
910:
911: switch (optname) {
912:
913: case SO_LINGER:
914: m->m_len = sizeof (struct linger);
915: mtod(m, struct linger *)->l_onoff =
916: so->so_options & SO_LINGER;
917: mtod(m, struct linger *)->l_linger = so->so_linger;
918: break;
919:
920: case SO_USELOOPBACK:
921: case SO_DONTROUTE:
922: case SO_DEBUG:
923: case SO_KEEPALIVE:
924: case SO_REUSEADDR:
925: case SO_BROADCAST:
926: case SO_OOBINLINE:
927: *mtod(m, int *) = so->so_options & optname;
928: break;
929:
930: case SO_TYPE:
931: *mtod(m, int *) = so->so_type;
932: break;
933:
934: case SO_ERROR:
935: *mtod(m, int *) = so->so_error;
936: so->so_error = 0;
937: break;
938:
939: case SO_SNDBUF:
940: *mtod(m, int *) = so->so_snd.sb_hiwat;
941: break;
942:
943: case SO_RCVBUF:
944: *mtod(m, int *) = so->so_rcv.sb_hiwat;
945: break;
946:
947: case SO_SNDLOWAT:
948: *mtod(m, int *) = so->so_snd.sb_lowat;
949: break;
950:
951: case SO_RCVLOWAT:
952: *mtod(m, int *) = so->so_rcv.sb_lowat;
953: break;
954:
955: case SO_SNDTIMEO:
956: case SO_RCVTIMEO:
957: {
958: int val = (optname == SO_SNDTIMEO ?
959: so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
960:
961: m->m_len = sizeof(struct timeval);
962: mtod(m, struct timeval *)->tv_sec = val / hz;
963: mtod(m, struct timeval *)->tv_usec =
964: (val % hz) / tick;
965: break;
966: }
967:
968: default:
969: (void)m_free(m);
970: return (ENOPROTOOPT);
971: }
972: *mp = m;
973: return (0);
974: }
975: }
976:
977: sohasoutofband(so)
978: register struct socket *so;
979: {
980: struct proc *p;
981:
982: if (so->so_pgid < 0)
983: gsignal(-so->so_pgid, SIGURG);
984: else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
985: psignal(p, SIGURG);
986: if (so->so_rcv.sb_sel) {
987: selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
988: so->so_rcv.sb_sel = 0;
989: so->so_rcv.sb_flags &= ~SB_COLL;
990: }
991: }