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