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