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