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