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