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