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