changed \&ps to ps in man page
[unix-history] / sys / kern / uipc_socket.c
CommitLineData
15637ed4
RG
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*/
56socreate(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
92sobind(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
106solisten(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
128sofree(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 */
149soclose(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 }
179drop:
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 }
187discard:
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 */
199soabort(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
208soaccept(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
224soconnect(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
251soconnect2(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
264sodisconnect(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);
280bad:
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 */
302sosend(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
329restart:
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 = &top;
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 {
400nopages:
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 = &top;
437 if (error)
438 goto release;
439 } while (resid && space > 0);
440 } while (resid);
441
442release:
443 sbunlock(&so->so_snd);
444out:
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 */
468soreceive(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;
6e32ab46 482 int orig_resid = uio->uio_resid;
15637ed4
RG
483
484 mp = mp0;
485 if (paddr)
486 *paddr = 0;
487 if (controlp)
488 *controlp = 0;
489 if (flagsp)
490 flags = *flagsp &~ MSG_EOR;
491 else
492 flags = 0;
493 if (flags & MSG_OOB) {
494 m = m_get(M_WAIT, MT_DATA);
495 error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
496 m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
497 if (error)
498 goto bad;
499 do {
500 error = uiomove(mtod(m, caddr_t),
501 (int) min(uio->uio_resid, m->m_len), uio);
502 m = m_free(m);
503 } while (uio->uio_resid && error == 0 && m);
504bad:
505 if (m)
506 m_freem(m);
507 return (error);
508 }
509 if (mp)
510 *mp = (struct mbuf *)0;
511 if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
512 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
513 (struct mbuf *)0, (struct mbuf *)0);
514
515restart:
516 if (error = sblock(&so->so_rcv))
517 return (error);
518 s = splnet();
519
520 m = so->so_rcv.sb_mb;
521 /*
522 * If we have less data than requested, block awaiting more
523 * (subject to any timeout) if:
524 * 1. the current count is less than the low water mark, or
525 * 2. MSG_WAITALL is set, and it is possible to do the entire
526 * receive operation at once if we block (resid <= hiwat).
527 * If MSG_WAITALL is set but resid is larger than the receive buffer,
528 * we have to do the receive in sections, and thus risk returning
529 * a short count if a timeout or signal occurs after we start.
530 */
531 while (m == 0 || so->so_rcv.sb_cc < uio->uio_resid &&
532 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
533 ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
6e32ab46 534 m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0) {
15637ed4
RG
535#ifdef DIAGNOSTIC
536 if (m == 0 && so->so_rcv.sb_cc)
537 panic("receive 1");
538#endif
539 if (so->so_error) {
540 if (m)
541 break;
542 error = so->so_error;
543 if ((flags & MSG_PEEK) == 0)
544 so->so_error = 0;
545 goto release;
546 }
547 if (so->so_state & SS_CANTRCVMORE) {
548 if (m)
549 break;
550 else
551 goto release;
552 }
553 for (; m; m = m->m_next)
554 if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
555 m = so->so_rcv.sb_mb;
556 goto dontblock;
557 }
558 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
559 (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
560 error = ENOTCONN;
561 goto release;
562 }
563 if (uio->uio_resid == 0)
564 goto release;
565 if (so->so_state & SS_NBIO) {
566 error = EWOULDBLOCK;
567 goto release;
568 }
569 sbunlock(&so->so_rcv);
570 error = sbwait(&so->so_rcv);
571 splx(s);
572 if (error)
573 return (error);
574 goto restart;
575 }
576dontblock:
577 p->p_stats->p_ru.ru_msgrcv++;
578 nextrecord = m->m_nextpkt;
579 if (pr->pr_flags & PR_ADDR) {
580#ifdef DIAGNOSTIC
581 if (m->m_type != MT_SONAME)
582 panic("receive 1a");
583#endif
6e32ab46 584 orig_resid = 0;
15637ed4
RG
585 if (flags & MSG_PEEK) {
586 if (paddr)
587 *paddr = m_copy(m, 0, m->m_len);
588 m = m->m_next;
589 } else {
590 sbfree(&so->so_rcv, m);
591 if (paddr) {
592 *paddr = m;
593 so->so_rcv.sb_mb = m->m_next;
594 m->m_next = 0;
595 m = so->so_rcv.sb_mb;
596 } else {
597 MFREE(m, so->so_rcv.sb_mb);
598 m = so->so_rcv.sb_mb;
599 }
600 }
601 }
602 while (m && m->m_type == MT_CONTROL && error == 0) {
603 if (flags & MSG_PEEK) {
604 if (controlp)
605 *controlp = m_copy(m, 0, m->m_len);
606 m = m->m_next;
607 } else {
608 sbfree(&so->so_rcv, m);
609 if (controlp) {
610 if (pr->pr_domain->dom_externalize &&
611 mtod(m, struct cmsghdr *)->cmsg_type ==
612 SCM_RIGHTS)
613 error = (*pr->pr_domain->dom_externalize)(m);
614 *controlp = m;
615 so->so_rcv.sb_mb = m->m_next;
616 m->m_next = 0;
617 m = so->so_rcv.sb_mb;
618 } else {
619 MFREE(m, so->so_rcv.sb_mb);
620 m = so->so_rcv.sb_mb;
621 }
622 }
6e32ab46
DG
623 if (controlp) {
624 orig_resid = 0;
15637ed4 625 controlp = &(*controlp)->m_next;
6e32ab46 626 }
15637ed4
RG
627 }
628 if (m) {
629 if ((flags & MSG_PEEK) == 0)
630 m->m_nextpkt = nextrecord;
631 type = m->m_type;
632 if (type == MT_OOBDATA)
633 flags |= MSG_OOB;
634 }
635 moff = 0;
636 offset = 0;
637 while (m && uio->uio_resid > 0 && error == 0) {
638 if (m->m_type == MT_OOBDATA) {
639 if (type != MT_OOBDATA)
640 break;
641 } else if (type == MT_OOBDATA)
642 break;
643#ifdef DIAGNOSTIC
644 else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
645 panic("receive 3");
646#endif
647 so->so_state &= ~SS_RCVATMARK;
648 len = uio->uio_resid;
649 if (so->so_oobmark && len > so->so_oobmark - offset)
650 len = so->so_oobmark - offset;
651 if (len > m->m_len - moff)
652 len = m->m_len - moff;
653 /*
654 * If mp is set, just pass back the mbufs.
655 * Otherwise copy them out via the uio, then free.
656 * Sockbuf must be consistent here (points to current mbuf,
657 * it points to next record) when we drop priority;
658 * we must note any additions to the sockbuf when we
659 * block interrupts again.
660 */
661 if (mp == 0) {
662 splx(s);
663 error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
664 s = splnet();
665 } else
666 uio->uio_resid -= len;
667 if (len == m->m_len - moff) {
668 if (m->m_flags & M_EOR)
669 flags |= MSG_EOR;
670 if (flags & MSG_PEEK) {
671 m = m->m_next;
672 moff = 0;
673 } else {
674 nextrecord = m->m_nextpkt;
675 sbfree(&so->so_rcv, m);
676 if (mp) {
677 *mp = m;
678 mp = &m->m_next;
679 so->so_rcv.sb_mb = m = m->m_next;
680 *mp = (struct mbuf *)0;
681 } else {
682 MFREE(m, so->so_rcv.sb_mb);
683 m = so->so_rcv.sb_mb;
684 }
685 if (m)
686 m->m_nextpkt = nextrecord;
687 }
688 } else {
689 if (flags & MSG_PEEK)
690 moff += len;
691 else {
692 if (mp)
693 *mp = m_copym(m, 0, len, M_WAIT);
694 m->m_data += len;
695 m->m_len -= len;
696 so->so_rcv.sb_cc -= len;
697 }
698 }
699 if (so->so_oobmark) {
700 if ((flags & MSG_PEEK) == 0) {
701 so->so_oobmark -= len;
702 if (so->so_oobmark == 0) {
703 so->so_state |= SS_RCVATMARK;
704 break;
705 }
706 } else
707 offset += len;
708 }
709 if (flags & MSG_EOR)
710 break;
711 /*
712 * If the MSG_WAITALL flag is set (for non-atomic socket),
713 * we must not quit until "uio->uio_resid == 0" or an error
714 * termination. If a signal/timeout occurs, return
715 * with a short count but without error.
716 * Keep sockbuf locked against other readers.
717 */
718 while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
6e32ab46 719 !sosendallatonce(so) && !nextrecord) {
15637ed4
RG
720 if (so->so_error || so->so_state & SS_CANTRCVMORE)
721 break;
722 error = sbwait(&so->so_rcv);
723 if (error) {
724 sbunlock(&so->so_rcv);
725 splx(s);
726 return (0);
727 }
728 if (m = so->so_rcv.sb_mb)
729 nextrecord = m->m_nextpkt;
730 }
731 }
6e32ab46
DG
732
733 if (m && pr->pr_flags & PR_ATOMIC) {
734 flags |= MSG_TRUNC;
735 if ((flags & MSG_PEEK) == 0)
736 (void) sbdroprecord(&so->so_rcv);
737 }
15637ed4
RG
738 if ((flags & MSG_PEEK) == 0) {
739 if (m == 0)
740 so->so_rcv.sb_mb = nextrecord;
15637ed4
RG
741 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
742 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
743 (struct mbuf *)flags, (struct mbuf *)0,
744 (struct mbuf *)0);
745 }
6e32ab46
DG
746 if (orig_resid == uio->uio_resid && orig_resid &&
747 (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
748 sbunlock(&so->so_rcv);
749 splx(s);
750 goto restart;
751 }
752
15637ed4
RG
753 if (flagsp)
754 *flagsp |= flags;
755release:
756 sbunlock(&so->so_rcv);
757 splx(s);
758 return (error);
759}
760
761soshutdown(so, how)
762 register struct socket *so;
763 register int how;
764{
765 register struct protosw *pr = so->so_proto;
766
767 how++;
768 if (how & FREAD)
769 sorflush(so);
770 if (how & FWRITE)
771 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
772 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
773 return (0);
774}
775
776sorflush(so)
777 register struct socket *so;
778{
779 register struct sockbuf *sb = &so->so_rcv;
780 register struct protosw *pr = so->so_proto;
781 register int s;
782 struct sockbuf asb;
783
784 sb->sb_flags |= SB_NOINTR;
785 (void) sblock(sb);
786 s = splimp();
787 socantrcvmore(so);
788 sbunlock(sb);
789 asb = *sb;
790 bzero((caddr_t)sb, sizeof (*sb));
791 splx(s);
792 if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
793 (*pr->pr_domain->dom_dispose)(asb.sb_mb);
794 sbrelease(&asb);
795}
796
797sosetopt(so, level, optname, m0)
798 register struct socket *so;
799 int level, optname;
800 struct mbuf *m0;
801{
802 int error = 0;
803 register struct mbuf *m = m0;
804
805 if (level != SOL_SOCKET) {
806 if (so->so_proto && so->so_proto->pr_ctloutput)
807 return ((*so->so_proto->pr_ctloutput)
808 (PRCO_SETOPT, so, level, optname, &m0));
809 error = ENOPROTOOPT;
810 } else {
811 switch (optname) {
812
813 case SO_LINGER:
814 if (m == NULL || m->m_len != sizeof (struct linger)) {
815 error = EINVAL;
816 goto bad;
817 }
818 so->so_linger = mtod(m, struct linger *)->l_linger;
819 /* fall thru... */
820
821 case SO_DEBUG:
822 case SO_KEEPALIVE:
823 case SO_DONTROUTE:
824 case SO_USELOOPBACK:
825 case SO_BROADCAST:
826 case SO_REUSEADDR:
827 case SO_OOBINLINE:
828 if (m == NULL || m->m_len < sizeof (int)) {
829 error = EINVAL;
830 goto bad;
831 }
832 if (*mtod(m, int *))
833 so->so_options |= optname;
834 else
835 so->so_options &= ~optname;
836 break;
837
838 case SO_SNDBUF:
839 case SO_RCVBUF:
840 case SO_SNDLOWAT:
841 case SO_RCVLOWAT:
842 if (m == NULL || m->m_len < sizeof (int)) {
843 error = EINVAL;
844 goto bad;
845 }
846 switch (optname) {
847
848 case SO_SNDBUF:
849 case SO_RCVBUF:
850 if (sbreserve(optname == SO_SNDBUF ?
851 &so->so_snd : &so->so_rcv,
852 (u_long) *mtod(m, int *)) == 0) {
853 error = ENOBUFS;
854 goto bad;
855 }
856 break;
857
858 case SO_SNDLOWAT:
859 so->so_snd.sb_lowat = *mtod(m, int *);
860 break;
861 case SO_RCVLOWAT:
862 so->so_rcv.sb_lowat = *mtod(m, int *);
863 break;
864 }
865 break;
866
867 case SO_SNDTIMEO:
868 case SO_RCVTIMEO:
869 {
870 struct timeval *tv;
871 short val;
872
873 if (m == NULL || m->m_len < sizeof (*tv)) {
874 error = EINVAL;
875 goto bad;
876 }
877 tv = mtod(m, struct timeval *);
878 if (tv->tv_sec > SHRT_MAX / hz - hz) {
879 error = EDOM;
880 goto bad;
881 }
882 val = tv->tv_sec * hz + tv->tv_usec / tick;
883
884 switch (optname) {
885
886 case SO_SNDTIMEO:
887 so->so_snd.sb_timeo = val;
888 break;
889 case SO_RCVTIMEO:
890 so->so_rcv.sb_timeo = val;
891 break;
892 }
893 break;
894 }
895
896 default:
897 error = ENOPROTOOPT;
898 break;
899 }
900 }
901bad:
902 if (m)
903 (void) m_free(m);
904 return (error);
905}
906
907sogetopt(so, level, optname, mp)
908 register struct socket *so;
909 int level, optname;
910 struct mbuf **mp;
911{
912 register struct mbuf *m;
913
914 if (level != SOL_SOCKET) {
915 if (so->so_proto && so->so_proto->pr_ctloutput) {
916 return ((*so->so_proto->pr_ctloutput)
917 (PRCO_GETOPT, so, level, optname, mp));
918 } else
919 return (ENOPROTOOPT);
920 } else {
921 m = m_get(M_WAIT, MT_SOOPTS);
922 m->m_len = sizeof (int);
923
924 switch (optname) {
925
926 case SO_LINGER:
927 m->m_len = sizeof (struct linger);
928 mtod(m, struct linger *)->l_onoff =
929 so->so_options & SO_LINGER;
930 mtod(m, struct linger *)->l_linger = so->so_linger;
931 break;
932
933 case SO_USELOOPBACK:
934 case SO_DONTROUTE:
935 case SO_DEBUG:
936 case SO_KEEPALIVE:
937 case SO_REUSEADDR:
938 case SO_BROADCAST:
939 case SO_OOBINLINE:
940 *mtod(m, int *) = so->so_options & optname;
941 break;
942
943 case SO_TYPE:
944 *mtod(m, int *) = so->so_type;
945 break;
946
947 case SO_ERROR:
948 *mtod(m, int *) = so->so_error;
949 so->so_error = 0;
950 break;
951
952 case SO_SNDBUF:
953 *mtod(m, int *) = so->so_snd.sb_hiwat;
954 break;
955
956 case SO_RCVBUF:
957 *mtod(m, int *) = so->so_rcv.sb_hiwat;
958 break;
959
960 case SO_SNDLOWAT:
961 *mtod(m, int *) = so->so_snd.sb_lowat;
962 break;
963
964 case SO_RCVLOWAT:
965 *mtod(m, int *) = so->so_rcv.sb_lowat;
966 break;
967
968 case SO_SNDTIMEO:
969 case SO_RCVTIMEO:
970 {
971 int val = (optname == SO_SNDTIMEO ?
972 so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
973
974 m->m_len = sizeof(struct timeval);
975 mtod(m, struct timeval *)->tv_sec = val / hz;
976 mtod(m, struct timeval *)->tv_usec =
977 (val % hz) / tick;
978 break;
979 }
980
981 default:
982 (void)m_free(m);
983 return (ENOPROTOOPT);
984 }
985 *mp = m;
986 return (0);
987 }
988}
989
990sohasoutofband(so)
991 register struct socket *so;
992{
993 struct proc *p;
994
995 if (so->so_pgid < 0)
996 gsignal(-so->so_pgid, SIGURG);
997 else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
998 psignal(p, SIGURG);
999 if (so->so_rcv.sb_sel) {
1000 selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
1001 so->so_rcv.sb_sel = 0;
1002 so->so_rcv.sb_flags &= ~SB_COLL;
1003 }
1004}