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