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