option for receiving OOB data in-line
[unix-history] / usr / src / sys / kern / uipc_socket.c
CommitLineData
da7c5cc6
KM
1/*
2 * Copyright (c) 1982 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
97c8f6a8 6 * @(#)uipc_socket.c 6.26 (Berkeley) %G%
da7c5cc6 7 */
ce9d8eb4 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "dir.h"
12#include "user.h"
13#include "proc.h"
14#include "file.h"
15#include "inode.h"
16#include "buf.h"
17#include "mbuf.h"
18#include "un.h"
19#include "domain.h"
20#include "protosw.h"
21#include "socket.h"
22#include "socketvar.h"
23#include "stat.h"
24#include "ioctl.h"
25#include "uio.h"
3a35e7af 26#include "../net/route.h"
88a7a62a 27#include "../netinet/in.h"
22f36762 28#include "../net/if.h"
ce9d8eb4 29
ce9d8eb4 30/*
cf012934
BJ
31 * Socket operation routines.
32 * These routines are called by the routines in
33 * sys_socket.c or from a system process, and
34 * implement the semantics of socket operations by
35 * switching out to the protocol specific routines.
88a7a62a
SL
36 *
37 * TODO:
88a7a62a 38 * test socketpair
8c0650b0 39 * clean up async
88a7a62a 40 * out-of-band is a kludge
ce9d8eb4 41 */
a8d3bf7f 42/*ARGSUSED*/
98422daa 43socreate(dom, aso, type, proto)
ce9d8eb4 44 struct socket **aso;
88a7a62a
SL
45 register int type;
46 int proto;
ce9d8eb4
BJ
47{
48 register struct protosw *prp;
49 register struct socket *so;
88a7a62a
SL
50 register struct mbuf *m;
51 register int error;
cc15ab5d 52
cc15ab5d 53 if (proto)
8c0650b0 54 prp = pffindproto(dom, proto, type);
cc15ab5d 55 else
4f083fd7 56 prp = pffindtype(dom, type);
cc15ab5d
BJ
57 if (prp == 0)
58 return (EPROTONOSUPPORT);
cf012934
BJ
59 if (prp->pr_type != type)
60 return (EPROTOTYPE);
cce93e4b 61 m = m_getclr(M_WAIT, MT_SOCKET);
ce9d8eb4 62 so = mtod(m, struct socket *);
88a7a62a 63 so->so_options = 0;
62364f0e 64 so->so_state = 0;
4f083fd7 65 so->so_type = type;
62364f0e
BJ
66 if (u.u_uid == 0)
67 so->so_state = SS_PRIV;
ce9d8eb4 68 so->so_proto = prp;
88a7a62a
SL
69 error =
70 (*prp->pr_usrreq)(so, PRU_ATTACH,
8c0650b0 71 (struct mbuf *)0, (struct mbuf *)proto, (struct mbuf *)0);
b91acce4 72 if (error) {
90aaea96 73 so->so_state |= SS_NOFDREF;
de48daf3 74 sofree(so);
cc15ab5d 75 return (error);
ce9d8eb4
BJ
76 }
77 *aso = so;
78 return (0);
79}
80
98422daa 81sobind(so, nam)
cf012934
BJ
82 struct socket *so;
83 struct mbuf *nam;
cf012934
BJ
84{
85 int s = splnet();
86 int error;
87
88 error =
88a7a62a
SL
89 (*so->so_proto->pr_usrreq)(so, PRU_BIND,
90 (struct mbuf *)0, nam, (struct mbuf *)0);
cf012934
BJ
91 splx(s);
92 return (error);
93}
94
95solisten(so, backlog)
88a7a62a 96 register struct socket *so;
cf012934
BJ
97 int backlog;
98{
88a7a62a 99 int s = splnet(), error;
cf012934 100
88a7a62a
SL
101 error =
102 (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
103 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
cf012934
BJ
104 if (error) {
105 splx(s);
106 return (error);
107 }
108 if (so->so_q == 0) {
109 so->so_q = so;
110 so->so_q0 = so;
111 so->so_options |= SO_ACCEPTCONN;
112 }
113 if (backlog < 0)
114 backlog = 0;
5fe6f9d1 115 so->so_qlimit = MIN(backlog, SOMAXCONN);
9e87be97 116 splx(s);
cf012934
BJ
117 return (0);
118}
119
ae921915 120sofree(so)
88a7a62a 121 register struct socket *so;
ae921915
BJ
122{
123
90aaea96
BJ
124 if (so->so_head) {
125 if (!soqremque(so, 0) && !soqremque(so, 1))
126 panic("sofree dq");
127 so->so_head = 0;
128 }
129 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
4ad99bae
BJ
130 return;
131 sbrelease(&so->so_snd);
88a7a62a 132 sorflush(so);
2752c877 133 (void) m_free(dtom(so));
ae921915
BJ
134}
135
92a533e6 136/*
cc15ab5d
BJ
137 * Close a socket on last file table reference removal.
138 * Initiate disconnect if connected.
139 * Free socket when disconnect complete.
92a533e6 140 */
88a7a62a 141soclose(so)
92a533e6 142 register struct socket *so;
92a533e6 143{
cc15ab5d 144 int s = splnet(); /* conservative */
5a1f132a 145 int error;
cc15ab5d 146
90aaea96
BJ
147 if (so->so_options & SO_ACCEPTCONN) {
148 while (so->so_q0 != so)
26225f25 149 (void) soabort(so->so_q0);
90aaea96 150 while (so->so_q != so)
26225f25 151 (void) soabort(so->so_q);
90aaea96 152 }
cc15ab5d
BJ
153 if (so->so_pcb == 0)
154 goto discard;
155 if (so->so_state & SS_ISCONNECTED) {
156 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
dedd6629 157 error = sodisconnect(so);
88a7a62a
SL
158 if (error)
159 goto drop;
cc15ab5d 160 }
98422daa 161 if (so->so_options & SO_LINGER) {
b8acc34d 162 if ((so->so_state & SS_ISDISCONNECTING) &&
88a7a62a
SL
163 (so->so_state & SS_NBIO))
164 goto drop;
b8acc34d
BJ
165 while (so->so_state & SS_ISCONNECTED)
166 sleep((caddr_t)&so->so_timeo, PZERO+1);
72857acf 167 }
cc15ab5d 168 }
89900a09 169drop:
37c0974a 170 if (so->so_pcb) {
88a7a62a
SL
171 int error2 =
172 (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
173 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
174 if (error == 0)
175 error = error2;
37c0974a 176 }
cc15ab5d 177discard:
26225f25
SL
178 if (so->so_state & SS_NOFDREF)
179 panic("soclose: NOFDREF");
90aaea96 180 so->so_state |= SS_NOFDREF;
4ad99bae 181 sofree(so);
cc15ab5d 182 splx(s);
88a7a62a 183 return (error);
92a533e6
BJ
184}
185
26225f25
SL
186/*
187 * Must be called at splnet...
188 */
189soabort(so)
190 struct socket *so;
191{
26225f25 192
88a7a62a
SL
193 return (
194 (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
195 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
92a533e6
BJ
196}
197
98422daa 198soaccept(so, nam)
88a7a62a 199 register struct socket *so;
cf012934 200 struct mbuf *nam;
2b4b57cd
BJ
201{
202 int s = splnet();
203 int error;
204
26225f25
SL
205 if ((so->so_state & SS_NOFDREF) == 0)
206 panic("soaccept: !NOFDREF");
98422daa 207 so->so_state &= ~SS_NOFDREF;
cf012934 208 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
88a7a62a 209 (struct mbuf *)0, nam, (struct mbuf *)0);
2b4b57cd
BJ
210 splx(s);
211 return (error);
212}
213
98422daa 214soconnect(so, nam)
88a7a62a 215 register struct socket *so;
cf012934 216 struct mbuf *nam;
ce9d8eb4 217{
cc15ab5d
BJ
218 int s = splnet();
219 int error;
ce9d8eb4 220
de2c74a5
MK
221 /*
222 * If protocol is connection-based, can only connect once.
223 * Otherwise, if connected, try to disconnect first.
224 * This allows user to disconnect by connecting to, e.g.,
225 * a null address.
226 */
227 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
228 ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
229 (error = sodisconnect(so))))
cc15ab5d 230 error = EISCONN;
de2c74a5
MK
231 else
232 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
233 (struct mbuf *)0, nam, (struct mbuf *)0);
cc15ab5d
BJ
234 splx(s);
235 return (error);
ce9d8eb4
BJ
236}
237
88a7a62a
SL
238soconnect2(so1, so2)
239 register struct socket *so1;
240 struct socket *so2;
241{
242 int s = splnet();
243 int error;
244
5a48956d
SL
245 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
246 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
88a7a62a
SL
247 splx(s);
248 return (error);
249}
88a7a62a 250
dedd6629 251sodisconnect(so)
88a7a62a 252 register struct socket *so;
ce9d8eb4 253{
cc15ab5d
BJ
254 int s = splnet();
255 int error;
ce9d8eb4 256
cc15ab5d
BJ
257 if ((so->so_state & SS_ISCONNECTED) == 0) {
258 error = ENOTCONN;
259 goto bad;
ce9d8eb4 260 }
cc15ab5d
BJ
261 if (so->so_state & SS_ISDISCONNECTING) {
262 error = EALREADY;
263 goto bad;
ce9d8eb4 264 }
cf012934 265 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
dedd6629 266 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
cc15ab5d
BJ
267bad:
268 splx(s);
269 return (error);
ce9d8eb4
BJ
270}
271
cc15ab5d
BJ
272/*
273 * Send on a socket.
274 * If send must go all at once and message is larger than
275 * send buffering, then hard error.
276 * Lock against other senders.
277 * If must go all at once and not enough room now, then
278 * inform user that this would block and do nothing.
8250a099 279 * Otherwise, if nonblocking, send as much as possible.
cc15ab5d 280 */
88a7a62a 281sosend(so, nam, uio, flags, rights)
ce9d8eb4 282 register struct socket *so;
cf012934 283 struct mbuf *nam;
88a7a62a 284 register struct uio *uio;
970108c7 285 int flags;
88a7a62a 286 struct mbuf *rights;
ce9d8eb4 287{
cc15ab5d 288 struct mbuf *top = 0;
8250a099 289 register struct mbuf *m, **mp;
88a7a62a 290 register int space;
c34d38f4 291 int len, rlen = 0, error = 0, s, dontroute, first = 1;
ce9d8eb4 292
5699bf69 293 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
cc15ab5d 294 return (EMSGSIZE);
88a7a62a
SL
295 dontroute =
296 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
297 (so->so_proto->pr_flags & PR_ATOMIC);
8250a099 298 u.u_ru.ru_msgsnd++;
c34d38f4
MK
299 if (rights)
300 rlen = rights->m_len;
cc15ab5d
BJ
301#define snderr(errno) { error = errno; splx(s); goto release; }
302
8250a099
MK
303restart:
304 sblock(&so->so_snd);
305 do {
306 s = splnet();
af9c562f 307 if (so->so_state & SS_CANTSENDMORE)
8250a099 308 snderr(EPIPE);
8250a099
MK
309 if (so->so_error) {
310 error = so->so_error;
311 so->so_error = 0; /* ??? */
312 splx(s);
313 goto release;
314 }
315 if ((so->so_state & SS_ISCONNECTED) == 0) {
316 if (so->so_proto->pr_flags & PR_CONNREQUIRED)
317 snderr(ENOTCONN);
318 if (nam == 0)
319 snderr(EDESTADDRREQ);
320 }
321 if (flags & MSG_OOB)
322 space = 1024;
323 else {
324 space = sbspace(&so->so_snd);
c34d38f4
MK
325 if (space <= rlen ||
326 (sosendallatonce(so) &&
327 space < uio->uio_resid + rlen) ||
09338457
MK
328 (uio->uio_resid >= CLBYTES && space < CLBYTES &&
329 so->so_snd.sb_cc >= CLBYTES &&
330 (so->so_state & SS_NBIO) == 0)) {
8250a099
MK
331 if (so->so_state & SS_NBIO) {
332 if (first)
333 error = EWOULDBLOCK;
334 splx(s);
335 goto release;
336 }
337 sbunlock(&so->so_snd);
338 sbwait(&so->so_snd);
339 splx(s);
340 goto restart;
341 }
342 }
4c078bb2 343 splx(s);
8250a099 344 mp = &top;
c34d38f4 345 space -= rlen;
af9c562f 346 while (space > 0) {
8250a099 347 MGET(m, M_WAIT, MT_DATA);
6ff43975 348 if (uio->uio_resid >= CLBYTES / 2 && space >= CLBYTES) {
658e19b1
MK
349 MCLGET(m);
350 if (m->m_len != CLBYTES)
8250a099 351 goto nopages;
6ff43975 352 len = MIN(CLBYTES, uio->uio_resid);
8c0650b0 353 space -= CLBYTES;
8250a099
MK
354 } else {
355nopages:
6ff43975 356 len = MIN(MIN(MLEN, uio->uio_resid), space);
8c0650b0 357 space -= len;
8250a099
MK
358 }
359 error = uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
360 m->m_len = len;
361 *mp = m;
362 if (error)
363 goto release;
364 mp = &m->m_next;
af9c562f
MK
365 if (uio->uio_resid <= 0)
366 break;
8250a099 367 }
af9c562f
MK
368 if (dontroute)
369 so->so_options |= SO_DONTROUTE;
370 s = splnet(); /* XXX */
371 error = (*so->so_proto->pr_usrreq)(so,
372 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
373 top, (caddr_t)nam, rights);
374 splx(s);
375 if (dontroute)
376 so->so_options &= ~SO_DONTROUTE;
8c0650b0 377 rights = 0;
c34d38f4 378 rlen = 0;
0f90f987 379 top = 0;
8250a099 380 first = 0;
c415b2e3 381 if (error)
8250a099
MK
382 break;
383 } while (uio->uio_resid);
cc15ab5d 384
ce9d8eb4 385release:
cc15ab5d 386 sbunlock(&so->so_snd);
0f90f987
BJ
387 if (top)
388 m_freem(top);
af9c562f
MK
389 if (error == EPIPE)
390 psignal(u.u_procp, SIGPIPE);
ce9d8eb4
BJ
391 return (error);
392}
393
c34d38f4
MK
394/*
395 * Implement receive operations on a socket.
396 * We depend on the way that records are added to the sockbuf
397 * by sbappend*. In particular, each record (mbufs linked through m_next)
398 * must begin with an address if the protocol so specifies,
399 * followed by an optional mbuf containing access rights if supported
400 * by the protocol, and then zero or more mbufs of data.
401 * In order to avoid blocking network interrupts for the entire time here,
402 * we splx() while doing the actual copy to user space.
403 * Although the sockbuf is locked, new data may still be appended,
404 * and thus we must maintain consistency of the sockbuf during that time.
405 */
88a7a62a 406soreceive(so, aname, uio, flags, rightsp)
ce9d8eb4 407 register struct socket *so;
cf012934 408 struct mbuf **aname;
88a7a62a 409 register struct uio *uio;
970108c7 410 int flags;
88a7a62a 411 struct mbuf **rightsp;
ce9d8eb4 412{
6ff43975 413 register struct mbuf *m;
261a8548 414 register int len, error = 0, s, tomark;
88a7a62a 415 struct protosw *pr = so->so_proto;
261a8548 416 struct mbuf *nextrecord;
88a7a62a
SL
417 int moff;
418
419 if (rightsp)
420 *rightsp = 0;
421 if (aname)
422 *aname = 0;
423 if (flags & MSG_OOB) {
cce93e4b 424 m = m_get(M_WAIT, MT_DATA);
88a7a62a 425 error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
de2c74a5 426 m, (struct mbuf *)(flags & MSG_PEEK), (struct mbuf *)0);
a8d3bf7f 427 if (error)
5fe6f9d1 428 goto bad;
970108c7 429 do {
5fe6f9d1 430 len = uio->uio_resid;
970108c7
BJ
431 if (len > m->m_len)
432 len = m->m_len;
a8d3bf7f 433 error =
a29f7995 434 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
970108c7 435 m = m_free(m);
a8d3bf7f 436 } while (uio->uio_resid && error == 0 && m);
5fe6f9d1 437bad:
970108c7 438 if (m)
39d536e6 439 m_freem(m);
a8d3bf7f 440 return (error);
970108c7 441 }
ce9d8eb4 442
cc15ab5d
BJ
443restart:
444 sblock(&so->so_rcv);
445 s = splnet();
446
447#define rcverr(errno) { error = errno; splx(s); goto release; }
ce9d8eb4 448 if (so->so_rcv.sb_cc == 0) {
4c078bb2
BJ
449 if (so->so_error) {
450 error = so->so_error;
451 so->so_error = 0;
452 splx(s);
453 goto release;
454 }
cc15ab5d
BJ
455 if (so->so_state & SS_CANTRCVMORE) {
456 splx(s);
457 goto release;
458 }
196d84fd
BJ
459 if ((so->so_state & SS_ISCONNECTED) == 0 &&
460 (so->so_proto->pr_flags & PR_CONNREQUIRED))
461 rcverr(ENOTCONN);
c34d38f4
MK
462 if (uio->uio_resid == 0)
463 goto release;
62364f0e 464 if (so->so_state & SS_NBIO)
4c078bb2 465 rcverr(EWOULDBLOCK);
cc15ab5d 466 sbunlock(&so->so_rcv);
2752c877 467 sbwait(&so->so_rcv);
a4f6d93d 468 splx(s);
cc15ab5d 469 goto restart;
ce9d8eb4 470 }
c7256358 471 u.u_ru.ru_msgrcv++;
92a533e6 472 m = so->so_rcv.sb_mb;
c34d38f4
MK
473 if (m == 0)
474 panic("receive 1");
475 nextrecord = m->m_act;
88a7a62a 476 if (pr->pr_flags & PR_ADDR) {
c34d38f4 477 if (m->m_type != MT_SONAME)
261a8548
MK
478 panic("receive 1a");
479 if (flags & MSG_PEEK) {
480 if (aname)
970108c7 481 *aname = m_copy(m, 0, m->m_len);
c34d38f4 482 m = m->m_next;
261a8548 483 } else {
c34d38f4 484 sbfree(&so->so_rcv, m);
261a8548
MK
485 if (aname) {
486 *aname = m;
c34d38f4
MK
487 m = m->m_next;
488 (*aname)->m_next = 0;
6ff43975 489 so->so_rcv.sb_mb = m;
c34d38f4 490 } else {
6ff43975
MK
491 MFREE(m, so->so_rcv.sb_mb);
492 m = so->so_rcv.sb_mb;
c34d38f4 493 }
6ff43975
MK
494 if (m)
495 m->m_act = nextrecord;
261a8548
MK
496 }
497 }
498 if (m && m->m_type == MT_RIGHTS) {
499 if ((pr->pr_flags & PR_RIGHTS) == 0)
6ff43975 500 panic("receive 2");
261a8548
MK
501 if (flags & MSG_PEEK) {
502 if (rightsp)
88a7a62a 503 *rightsp = m_copy(m, 0, m->m_len);
c34d38f4 504 m = m->m_next;
261a8548 505 } else {
c34d38f4 506 sbfree(&so->so_rcv, m);
261a8548
MK
507 if (rightsp) {
508 *rightsp = m;
6ff43975 509 so->so_rcv.sb_mb = m->m_next;
c34d38f4 510 m->m_next = 0;
6ff43975 511 m = so->so_rcv.sb_mb;
c34d38f4 512 } else {
6ff43975
MK
513 MFREE(m, so->so_rcv.sb_mb);
514 m = so->so_rcv.sb_mb;
c34d38f4 515 }
6ff43975
MK
516 if (m)
517 m->m_act = nextrecord;
88a7a62a 518 }
cc15ab5d 519 }
970108c7
BJ
520 moff = 0;
521 tomark = so->so_oobmark;
261a8548 522 while (m && uio->uio_resid > 0 && error == 0) {
c34d38f4
MK
523 if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
524 panic("receive 3");
5699bf69 525 len = uio->uio_resid;
32a43ee2 526 so->so_state &= ~SS_RCVATMARK;
970108c7
BJ
527 if (tomark && len > tomark)
528 len = tomark;
8c0650b0 529 if (len > m->m_len - moff)
970108c7 530 len = m->m_len - moff;
ce9d8eb4 531 splx(s);
a8d3bf7f 532 error =
a29f7995 533 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
ce9d8eb4 534 s = splnet();
8c0650b0 535 if (len == m->m_len - moff) {
c34d38f4
MK
536 if (flags & MSG_PEEK) {
537 m = m->m_next;
538 moff = 0;
539 } else {
c34d38f4 540 nextrecord = m->m_act;
6ff43975
MK
541 sbfree(&so->so_rcv, m);
542 MFREE(m, so->so_rcv.sb_mb);
543 m = so->so_rcv.sb_mb;
544 if (m)
545 m->m_act = nextrecord;
c34d38f4 546 }
ce9d8eb4 547 } else {
88a7a62a 548 if (flags & MSG_PEEK)
970108c7
BJ
549 moff += len;
550 else {
551 m->m_off += len;
552 m->m_len -= len;
553 so->so_rcv.sb_cc -= len;
554 }
ce9d8eb4 555 }
88a7a62a 556 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) {
32a43ee2
BJ
557 so->so_oobmark -= len;
558 if (so->so_oobmark == 0) {
559 so->so_state |= SS_RCVATMARK;
560 break;
561 }
562 }
970108c7
BJ
563 if (tomark) {
564 tomark -= len;
565 if (tomark == 0)
566 break;
567 }
261a8548
MK
568 }
569 if ((flags & MSG_PEEK) == 0) {
491e9020 570 if (m == 0)
261a8548 571 so->so_rcv.sb_mb = nextrecord;
6ff43975
MK
572 else if (pr->pr_flags & PR_ATOMIC)
573 (void) sbdroprecord(&so->so_rcv);
261a8548
MK
574 if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
575 (*pr->pr_usrreq)(so, PRU_RCVD, (struct mbuf *)0,
576 (struct mbuf *)0, (struct mbuf *)0);
c34d38f4
MK
577 if (error == 0 && rightsp && *rightsp &&
578 pr->pr_domain->dom_externalize)
579 error = (*pr->pr_domain->dom_externalize)(*rightsp);
261a8548 580 }
cc15ab5d 581release:
ae921915 582 sbunlock(&so->so_rcv);
cc15ab5d 583 splx(s);
ae921915 584 return (error);
92a533e6
BJ
585}
586
98422daa 587soshutdown(so, how)
88a7a62a
SL
588 register struct socket *so;
589 register int how;
98422daa 590{
88a7a62a 591 register struct protosw *pr = so->so_proto;
98422daa
SL
592
593 how++;
88a7a62a
SL
594 if (how & FREAD)
595 sorflush(so);
98422daa 596 if (how & FWRITE)
88a7a62a
SL
597 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
598 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
98422daa
SL
599 return (0);
600}
601
88a7a62a
SL
602sorflush(so)
603 register struct socket *so;
604{
605 register struct sockbuf *sb = &so->so_rcv;
606 register struct protosw *pr = so->so_proto;
607 register int s;
608 struct sockbuf asb;
609
610 sblock(sb);
611 s = splimp();
612 socantrcvmore(so);
613 sbunlock(sb);
614 asb = *sb;
615 bzero((caddr_t)sb, sizeof (*sb));
616 splx(s);
261a8548
MK
617 if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
618 (*pr->pr_domain->dom_dispose)(asb.sb_mb);
88a7a62a
SL
619 sbrelease(&asb);
620}
621
bc2f5859 622sosetopt(so, level, optname, m0)
88a7a62a 623 register struct socket *so;
98422daa 624 int level, optname;
bc2f5859 625 struct mbuf *m0;
98422daa 626{
61ec2127 627 int error = 0;
bc2f5859 628 register struct mbuf *m = m0;
98422daa 629
61ec2127 630 if (level != SOL_SOCKET) {
cbe54390
MK
631 if (so->so_proto && so->so_proto->pr_ctloutput)
632 return ((*so->so_proto->pr_ctloutput)
bc2f5859 633 (PRCO_SETOPT, so, level, optname, &m0));
cbe54390
MK
634 error = ENOPROTOOPT;
635 } else {
636 switch (optname) {
98422daa 637
cbe54390
MK
638 case SO_LINGER:
639 if (m == NULL || m->m_len != sizeof (struct linger)) {
640 error = EINVAL;
641 goto bad;
642 }
643 so->so_linger = mtod(m, struct linger *)->l_linger;
644 /* fall thru... */
645
646 case SO_DEBUG:
647 case SO_KEEPALIVE:
648 case SO_DONTROUTE:
649 case SO_USELOOPBACK:
650 case SO_BROADCAST:
651 case SO_REUSEADDR:
97c8f6a8 652 case SO_OOBINLINE:
cbe54390
MK
653 if (m == NULL || m->m_len < sizeof (int)) {
654 error = EINVAL;
655 goto bad;
656 }
657 if (*mtod(m, int *))
658 so->so_options |= optname;
659 else
660 so->so_options &= ~optname;
661 break;
98422daa 662
cbe54390
MK
663 case SO_SNDBUF:
664 case SO_RCVBUF:
665 case SO_SNDLOWAT:
666 case SO_RCVLOWAT:
667 case SO_SNDTIMEO:
668 case SO_RCVTIMEO:
669 if (m == NULL || m->m_len < sizeof (int)) {
670 error = EINVAL;
671 goto bad;
672 }
673 switch (optname) {
674
675 case SO_SNDBUF:
676 case SO_RCVBUF:
677 if (sbreserve(optname == SO_SNDBUF ? &so->so_snd :
678 &so->so_rcv, *mtod(m, int *)) == 0) {
679 error = ENOBUFS;
680 goto bad;
681 }
682 break;
683
684 case SO_SNDLOWAT:
685 so->so_snd.sb_lowat = *mtod(m, int *);
686 break;
687 case SO_RCVLOWAT:
688 so->so_rcv.sb_lowat = *mtod(m, int *);
689 break;
690 case SO_SNDTIMEO:
691 so->so_snd.sb_timeo = *mtod(m, int *);
692 break;
693 case SO_RCVTIMEO:
694 so->so_rcv.sb_timeo = *mtod(m, int *);
695 break;
696 }
697 break;
698
699 default:
700 error = ENOPROTOOPT;
701 break;
702 }
98422daa 703 }
61ec2127
SL
704bad:
705 if (m)
706 (void) m_free(m);
707 return (error);
98422daa
SL
708}
709
61ec2127 710sogetopt(so, level, optname, mp)
88a7a62a 711 register struct socket *so;
98422daa 712 int level, optname;
61ec2127 713 struct mbuf **mp;
98422daa 714{
61ec2127 715 register struct mbuf *m;
98422daa 716
cbe54390
MK
717 if (level != SOL_SOCKET) {
718 if (so->so_proto && so->so_proto->pr_ctloutput) {
719 return ((*so->so_proto->pr_ctloutput)
720 (PRCO_GETOPT, so, level, optname, mp));
721 } else
722 return (ENOPROTOOPT);
723 } else {
61ec2127 724 m = m_get(M_WAIT, MT_SOOPTS);
d6e6eea8
MK
725 m->m_len = sizeof (int);
726
cbe54390
MK
727 switch (optname) {
728
729 case SO_LINGER:
730 m->m_len = sizeof (struct linger);
731 mtod(m, struct linger *)->l_onoff =
732 so->so_options & SO_LINGER;
733 mtod(m, struct linger *)->l_linger = so->so_linger;
734 break;
735
736 case SO_USELOOPBACK:
737 case SO_DONTROUTE:
738 case SO_DEBUG:
739 case SO_KEEPALIVE:
740 case SO_REUSEADDR:
741 case SO_BROADCAST:
97c8f6a8 742 case SO_OOBINLINE:
cbe54390
MK
743 *mtod(m, int *) = so->so_options & optname;
744 break;
745
d6e6eea8
MK
746 case SO_TYPE:
747 *mtod(m, int *) = so->so_type;
748 break;
749
de2c74a5
MK
750 case SO_ERROR:
751 *mtod(m, int *) = so->so_error;
752 so->so_error = 0;
753 break;
754
cbe54390
MK
755 case SO_SNDBUF:
756 *mtod(m, int *) = so->so_snd.sb_hiwat;
757 break;
98422daa 758
cbe54390
MK
759 case SO_RCVBUF:
760 *mtod(m, int *) = so->so_rcv.sb_hiwat;
761 break;
762
763 case SO_SNDLOWAT:
764 *mtod(m, int *) = so->so_snd.sb_lowat;
765 break;
766
767 case SO_RCVLOWAT:
768 *mtod(m, int *) = so->so_rcv.sb_lowat;
769 break;
770
771 case SO_SNDTIMEO:
772 *mtod(m, int *) = so->so_snd.sb_timeo;
773 break;
774
775 case SO_RCVTIMEO:
776 *mtod(m, int *) = so->so_rcv.sb_timeo;
777 break;
778
779 default:
8011f5df 780 (void)m_free(m);
cbe54390
MK
781 return (ENOPROTOOPT);
782 }
783 *mp = m;
784 return (0);
98422daa 785 }
98422daa
SL
786}
787
edebca28 788sohasoutofband(so)
88a7a62a 789 register struct socket *so;
edebca28 790{
3d190e86 791 struct proc *p;
edebca28 792
3d190e86
MK
793 if (so->so_pgrp < 0)
794 gsignal(-so->so_pgrp, SIGURG);
795 else if (so->so_pgrp > 0 && (p = pfind(so->so_pgrp)) != 0)
796 psignal(p, SIGURG);
de2c74a5
MK
797 if (so->so_rcv.sb_sel) {
798 selwakeup(so->so_rcv.sb_sel, so->so_rcv.sb_flags & SB_COLL);
799 so->so_rcv.sb_sel = 0;
800 so->so_rcv.sb_flags &= ~SB_COLL;
801 }
edebca28 802}