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