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