do it "right"?
[unix-history] / usr / src / sys / kern / uipc_socket.c
CommitLineData
5a48956d 1/* uipc_socket.c 4.76 83/06/14 */
ce9d8eb4
BJ
2
3#include "../h/param.h"
92a533e6 4#include "../h/systm.h"
ce9d8eb4
BJ
5#include "../h/dir.h"
6#include "../h/user.h"
92a533e6
BJ
7#include "../h/proc.h"
8#include "../h/file.h"
ce9d8eb4 9#include "../h/inode.h"
92a533e6 10#include "../h/buf.h"
ce9d8eb4 11#include "../h/mbuf.h"
88a7a62a 12#include "../h/un.h"
92a533e6
BJ
13#include "../h/protosw.h"
14#include "../h/socket.h"
15#include "../h/socketvar.h"
ae921915 16#include "../h/stat.h"
b8acc34d 17#include "../h/ioctl.h"
32a43ee2 18#include "../h/uio.h"
3a35e7af 19#include "../net/route.h"
88a7a62a 20#include "../netinet/in.h"
22f36762 21#include "../net/if.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:
31 * sostat
32 * test socketpair
33 * PR_RIGHTS
34 * clean up select, async
35 * out-of-band is a kludge
ce9d8eb4 36 */
a8d3bf7f 37/*ARGSUSED*/
98422daa 38socreate(dom, aso, type, proto)
ce9d8eb4 39 struct socket **aso;
88a7a62a
SL
40 register int type;
41 int proto;
ce9d8eb4
BJ
42{
43 register struct protosw *prp;
44 register struct socket *so;
88a7a62a
SL
45 register struct mbuf *m;
46 register int error;
cc15ab5d 47
cc15ab5d 48 if (proto)
4f083fd7 49 prp = pffindproto(dom, proto);
cc15ab5d 50 else
4f083fd7 51 prp = pffindtype(dom, type);
cc15ab5d
BJ
52 if (prp == 0)
53 return (EPROTONOSUPPORT);
cf012934
BJ
54 if (prp->pr_type != type)
55 return (EPROTOTYPE);
cce93e4b 56 m = m_getclr(M_WAIT, MT_SOCKET);
ce9d8eb4
BJ
57 if (m == 0)
58 return (ENOBUFS);
ce9d8eb4 59 so = mtod(m, struct socket *);
88a7a62a 60 so->so_options = 0;
62364f0e 61 so->so_state = 0;
4f083fd7 62 so->so_type = type;
62364f0e
BJ
63 if (u.u_uid == 0)
64 so->so_state = SS_PRIV;
ce9d8eb4 65 so->so_proto = prp;
88a7a62a
SL
66 error =
67 (*prp->pr_usrreq)(so, PRU_ATTACH,
68 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
b91acce4 69 if (error) {
90aaea96 70 so->so_state |= SS_NOFDREF;
de48daf3 71 sofree(so);
cc15ab5d 72 return (error);
ce9d8eb4
BJ
73 }
74 *aso = so;
75 return (0);
76}
77
98422daa 78sobind(so, nam)
cf012934
BJ
79 struct socket *so;
80 struct mbuf *nam;
cf012934
BJ
81{
82 int s = splnet();
83 int error;
84
85 error =
88a7a62a
SL
86 (*so->so_proto->pr_usrreq)(so, PRU_BIND,
87 (struct mbuf *)0, nam, (struct mbuf *)0);
cf012934
BJ
88 splx(s);
89 return (error);
90}
91
92solisten(so, backlog)
88a7a62a 93 register struct socket *so;
cf012934
BJ
94 int backlog;
95{
88a7a62a 96 int s = splnet(), error;
cf012934 97
88a7a62a
SL
98 error =
99 (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
100 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
cf012934
BJ
101 if (error) {
102 splx(s);
103 return (error);
104 }
105 if (so->so_q == 0) {
106 so->so_q = so;
107 so->so_q0 = so;
108 so->so_options |= SO_ACCEPTCONN;
109 }
110 if (backlog < 0)
111 backlog = 0;
5fe6f9d1 112 so->so_qlimit = MIN(backlog, SOMAXCONN);
9e87be97 113 splx(s);
cf012934
BJ
114 return (0);
115}
116
ae921915 117sofree(so)
88a7a62a 118 register struct socket *so;
ae921915
BJ
119{
120
90aaea96
BJ
121 if (so->so_head) {
122 if (!soqremque(so, 0) && !soqremque(so, 1))
123 panic("sofree dq");
124 so->so_head = 0;
125 }
126 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
4ad99bae
BJ
127 return;
128 sbrelease(&so->so_snd);
88a7a62a 129 sorflush(so);
2752c877 130 (void) m_free(dtom(so));
ae921915
BJ
131}
132
92a533e6 133/*
cc15ab5d
BJ
134 * Close a socket on last file table reference removal.
135 * Initiate disconnect if connected.
136 * Free socket when disconnect complete.
92a533e6 137 */
88a7a62a 138soclose(so)
92a533e6 139 register struct socket *so;
92a533e6 140{
cc15ab5d 141 int s = splnet(); /* conservative */
5a1f132a 142 int error;
cc15ab5d 143
90aaea96
BJ
144 if (so->so_options & SO_ACCEPTCONN) {
145 while (so->so_q0 != so)
26225f25 146 (void) soabort(so->so_q0);
90aaea96 147 while (so->so_q != so)
26225f25 148 (void) soabort(so->so_q);
90aaea96 149 }
cc15ab5d
BJ
150 if (so->so_pcb == 0)
151 goto discard;
152 if (so->so_state & SS_ISCONNECTED) {
153 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
ac76a23d 154 error = sodisconnect(so, (struct mbuf *)0);
88a7a62a
SL
155 if (error)
156 goto drop;
cc15ab5d 157 }
98422daa 158 if (so->so_options & SO_LINGER) {
b8acc34d 159 if ((so->so_state & SS_ISDISCONNECTING) &&
88a7a62a
SL
160 (so->so_state & SS_NBIO))
161 goto drop;
b8acc34d
BJ
162 while (so->so_state & SS_ISCONNECTED)
163 sleep((caddr_t)&so->so_timeo, PZERO+1);
72857acf 164 }
cc15ab5d 165 }
89900a09 166drop:
37c0974a 167 if (so->so_pcb) {
88a7a62a
SL
168 int error2 =
169 (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
170 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
171 if (error == 0)
172 error = error2;
37c0974a 173 }
cc15ab5d 174discard:
26225f25
SL
175 if (so->so_state & SS_NOFDREF)
176 panic("soclose: NOFDREF");
90aaea96 177 so->so_state |= SS_NOFDREF;
4ad99bae 178 sofree(so);
cc15ab5d 179 splx(s);
88a7a62a 180 return (error);
92a533e6
BJ
181}
182
26225f25
SL
183/*
184 * Must be called at splnet...
185 */
186soabort(so)
187 struct socket *so;
188{
26225f25 189
88a7a62a
SL
190 return (
191 (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
192 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
92a533e6
BJ
193}
194
98422daa 195soaccept(so, nam)
88a7a62a 196 register struct socket *so;
cf012934 197 struct mbuf *nam;
2b4b57cd
BJ
198{
199 int s = splnet();
200 int error;
201
26225f25
SL
202 if ((so->so_state & SS_NOFDREF) == 0)
203 panic("soaccept: !NOFDREF");
98422daa 204 so->so_state &= ~SS_NOFDREF;
cf012934 205 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
88a7a62a 206 (struct mbuf *)0, nam, (struct mbuf *)0);
2b4b57cd
BJ
207 splx(s);
208 return (error);
209}
210
98422daa 211soconnect(so, nam)
88a7a62a 212 register struct socket *so;
cf012934 213 struct mbuf *nam;
ce9d8eb4 214{
cc15ab5d
BJ
215 int s = splnet();
216 int error;
ce9d8eb4 217
cc15ab5d
BJ
218 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
219 error = EISCONN;
220 goto bad;
221 }
cf012934 222 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
88a7a62a 223 (struct mbuf *)0, nam, (struct mbuf *)0);
cc15ab5d
BJ
224bad:
225 splx(s);
226 return (error);
ce9d8eb4
BJ
227}
228
88a7a62a
SL
229soconnect2(so1, so2)
230 register struct socket *so1;
231 struct socket *so2;
232{
233 int s = splnet();
234 int error;
235
5a48956d
SL
236 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
237 (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0);
88a7a62a
SL
238 splx(s);
239 return (error);
240}
88a7a62a 241
cf012934 242sodisconnect(so, nam)
88a7a62a 243 register struct socket *so;
cf012934 244 struct mbuf *nam;
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,
88a7a62a 258 (struct mbuf *)0, nam, (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.
271 */
88a7a62a 272sosend(so, nam, uio, flags, rights)
ce9d8eb4 273 register struct socket *so;
cf012934 274 struct mbuf *nam;
88a7a62a 275 register struct uio *uio;
970108c7 276 int flags;
88a7a62a 277 struct mbuf *rights;
ce9d8eb4 278{
cc15ab5d
BJ
279 struct mbuf *top = 0;
280 register struct mbuf *m, **mp = &top;
88a7a62a
SL
281 register int space;
282 int len, error = 0, s, dontroute;
ce9d8eb4 283
5699bf69 284 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
cc15ab5d 285 return (EMSGSIZE);
88a7a62a
SL
286 dontroute =
287 (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
288 (so->so_proto->pr_flags & PR_ATOMIC);
0f90f987 289restart:
cc15ab5d
BJ
290 sblock(&so->so_snd);
291#define snderr(errno) { error = errno; splx(s); goto release; }
292
c7256358 293 u.u_ru.ru_msgsnd++;
cc15ab5d 294again:
0f90f987
BJ
295 s = splnet();
296 if (so->so_state & SS_CANTSENDMORE) {
297 psignal(u.u_procp, SIGPIPE);
298 snderr(EPIPE);
299 }
4c078bb2
BJ
300 if (so->so_error) {
301 error = so->so_error;
0f90f987 302 so->so_error = 0; /* ??? */
4c078bb2
BJ
303 splx(s);
304 goto release;
305 }
cc15ab5d
BJ
306 if ((so->so_state & SS_ISCONNECTED) == 0) {
307 if (so->so_proto->pr_flags & PR_CONNREQUIRED)
308 snderr(ENOTCONN);
cf012934 309 if (nam == 0)
cc15ab5d
BJ
310 snderr(EDESTADDRREQ);
311 }
cc15ab5d 312 if (top) {
98422daa
SL
313 if (dontroute)
314 so->so_options |= SO_DONTROUTE;
970108c7 315 error = (*so->so_proto->pr_usrreq)(so,
88a7a62a
SL
316 (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
317 top, (caddr_t)nam, rights);
98422daa
SL
318 if (dontroute)
319 so->so_options &= ~SO_DONTROUTE;
0f90f987 320 top = 0;
cc15ab5d
BJ
321 if (error) {
322 splx(s);
ce9d8eb4
BJ
323 goto release;
324 }
cc15ab5d 325 mp = &top;
ce9d8eb4 326 }
5699bf69 327 if (uio->uio_resid == 0) {
b91acce4
BJ
328 splx(s);
329 goto release;
330 }
88a7a62a 331 if (flags & MSG_OOB)
970108c7
BJ
332 space = 1024;
333 else {
334 space = sbspace(&so->so_snd);
335 if (space <= 0 ||
336 sosendallatonce(so) && space < uio->uio_resid) {
337 if (so->so_state & SS_NBIO)
338 snderr(EWOULDBLOCK);
339 sbunlock(&so->so_snd);
340 sbwait(&so->so_snd);
341 splx(s);
342 goto restart;
343 }
ce9d8eb4 344 }
cc15ab5d 345 splx(s);
5699bf69
BJ
346 while (uio->uio_resid > 0 && space > 0) {
347 register struct iovec *iov = uio->uio_iov;
348
349 if (iov->iov_len == 0) {
350 uio->uio_iov++;
351 uio->uio_iovcnt--;
352 if (uio->uio_iovcnt < 0)
353 panic("sosend");
354 continue;
355 }
cce93e4b 356 MGET(m, M_WAIT, MT_DATA);
cc15ab5d 357 if (m == NULL) {
0f90f987 358 error = ENOBUFS; /* SIGPIPE? */
cc15ab5d 359 goto release;
ce9d8eb4 360 }
5699bf69 361 if (iov->iov_len >= CLBYTES && space >= CLBYTES) {
cc15ab5d 362 register struct mbuf *p;
c5ff2e32 363 MCLGET(p, 1);
cc15ab5d
BJ
364 if (p == 0)
365 goto nopages;
366 m->m_off = (int)p - (int)m;
c5ff2e32 367 len = CLBYTES;
cc15ab5d 368 } else {
ce9d8eb4 369nopages:
5699bf69 370 len = MIN(MLEN, iov->iov_len);
ce9d8eb4 371 }
39d536e6 372 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
cc15ab5d
BJ
373 m->m_len = len;
374 *mp = m;
375 mp = &m->m_next;
88a7a62a 376 if (flags & MSG_OOB)
970108c7
BJ
377 space -= len;
378 else
379 space = sbspace(&so->so_snd);
ce9d8eb4 380 }
cc15ab5d
BJ
381 goto again;
382
ce9d8eb4 383release:
cc15ab5d 384 sbunlock(&so->so_snd);
0f90f987
BJ
385 if (top)
386 m_freem(top);
ce9d8eb4
BJ
387 return (error);
388}
389
88a7a62a 390soreceive(so, aname, uio, flags, rightsp)
ce9d8eb4 391 register struct socket *so;
cf012934 392 struct mbuf **aname;
88a7a62a 393 register struct uio *uio;
970108c7 394 int flags;
88a7a62a 395 struct mbuf **rightsp;
ce9d8eb4
BJ
396{
397 register struct mbuf *m, *n;
88a7a62a
SL
398 register int len, error = 0, s, eor, tomark;
399 struct protosw *pr = so->so_proto;
400 int moff;
401
402 if (rightsp)
403 *rightsp = 0;
404 if (aname)
405 *aname = 0;
406 if (flags & MSG_OOB) {
cce93e4b 407 m = m_get(M_WAIT, MT_DATA);
88a7a62a 408 if (m == 0)
5fe6f9d1 409 return (ENOBUFS);
88a7a62a
SL
410 error = (*pr->pr_usrreq)(so, PRU_RCVOOB,
411 m, (struct mbuf *)0, (struct mbuf *)0);
a8d3bf7f 412 if (error)
5fe6f9d1 413 goto bad;
970108c7 414 do {
5fe6f9d1 415 len = uio->uio_resid;
970108c7
BJ
416 if (len > m->m_len)
417 len = m->m_len;
a8d3bf7f 418 error =
a29f7995 419 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
970108c7 420 m = m_free(m);
a8d3bf7f 421 } while (uio->uio_resid && error == 0 && m);
5fe6f9d1 422bad:
970108c7 423 if (m)
39d536e6 424 m_freem(m);
a8d3bf7f 425 return (error);
970108c7 426 }
ce9d8eb4 427
cc15ab5d
BJ
428restart:
429 sblock(&so->so_rcv);
430 s = splnet();
431
432#define rcverr(errno) { error = errno; splx(s); goto release; }
ce9d8eb4 433 if (so->so_rcv.sb_cc == 0) {
4c078bb2
BJ
434 if (so->so_error) {
435 error = so->so_error;
436 so->so_error = 0;
437 splx(s);
438 goto release;
439 }
cc15ab5d
BJ
440 if (so->so_state & SS_CANTRCVMORE) {
441 splx(s);
442 goto release;
443 }
196d84fd
BJ
444 if ((so->so_state & SS_ISCONNECTED) == 0 &&
445 (so->so_proto->pr_flags & PR_CONNREQUIRED))
446 rcverr(ENOTCONN);
62364f0e 447 if (so->so_state & SS_NBIO)
4c078bb2 448 rcverr(EWOULDBLOCK);
cc15ab5d 449 sbunlock(&so->so_rcv);
2752c877 450 sbwait(&so->so_rcv);
a4f6d93d 451 splx(s);
cc15ab5d 452 goto restart;
ce9d8eb4 453 }
c7256358 454 u.u_ru.ru_msgrcv++;
92a533e6 455 m = so->so_rcv.sb_mb;
ce9d8eb4
BJ
456 if (m == 0)
457 panic("receive");
88a7a62a
SL
458 if (pr->pr_flags & PR_ADDR) {
459 if ((flags & MSG_PEEK) == 0) {
970108c7
BJ
460 so->so_rcv.sb_cc -= m->m_len;
461 so->so_rcv.sb_mbcnt -= MSIZE;
462 }
cf012934 463 if (aname) {
88a7a62a 464 if (flags & MSG_PEEK) {
970108c7 465 *aname = m_copy(m, 0, m->m_len);
5fe6f9d1
SL
466 if (*aname == NULL)
467 panic("receive 2");
468 } else
970108c7 469 *aname = m;
cf012934
BJ
470 m = m->m_next;
471 (*aname)->m_next = 0;
472 } else
88a7a62a 473 if (flags & MSG_PEEK)
970108c7
BJ
474 m = m->m_next;
475 else
476 m = m_free(m);
88a7a62a
SL
477 if (m == 0)
478 panic("receive 2a");
479 if (rightsp) {
480 if (m->m_len)
481 *rightsp = m_copy(m, 0, m->m_len);
482 else {
483 *rightsp = m_get(M_DONTWAIT, MT_SONAME);
484 if (*rightsp)
485 (*rightsp)->m_len = 0;
486 }
487 if (*rightsp == NULL)
488 panic("receive 2b");
489 }
490 if (flags & MSG_PEEK)
491 m = m->m_next;
492 else {
493 so->so_rcv.sb_cc -= m->m_len;
494 so->so_rcv.sb_mbcnt -= MSIZE;
495 m = m_free(m);
496 }
cc15ab5d 497 if (m == 0)
5fe6f9d1 498 panic("receive 3");
88a7a62a 499 if ((flags & MSG_PEEK) == 0)
e435773e 500 so->so_rcv.sb_mb = m;
cc15ab5d 501 }
ce9d8eb4 502 eor = 0;
970108c7
BJ
503 moff = 0;
504 tomark = so->so_oobmark;
ce9d8eb4 505 do {
5699bf69 506 if (uio->uio_resid <= 0)
32a43ee2 507 break;
5699bf69 508 len = uio->uio_resid;
32a43ee2 509 so->so_state &= ~SS_RCVATMARK;
970108c7
BJ
510 if (tomark && len > tomark)
511 len = tomark;
e435773e 512 if (moff+len > m->m_len - moff)
970108c7 513 len = m->m_len - moff;
ce9d8eb4 514 splx(s);
a8d3bf7f 515 error =
a29f7995 516 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
ce9d8eb4
BJ
517 s = splnet();
518 if (len == m->m_len) {
e495e1cc 519 eor = (int)m->m_act;
88a7a62a 520 if (flags & MSG_PEEK)
970108c7
BJ
521 m = m->m_next;
522 else {
523 sbfree(&so->so_rcv, m);
524 MFREE(m, n);
525 m = n;
e435773e 526 so->so_rcv.sb_mb = m;
970108c7
BJ
527 }
528 moff = 0;
ce9d8eb4 529 } else {
88a7a62a 530 if (flags & MSG_PEEK)
970108c7
BJ
531 moff += len;
532 else {
533 m->m_off += len;
534 m->m_len -= len;
535 so->so_rcv.sb_cc -= len;
536 }
ce9d8eb4 537 }
88a7a62a 538 if ((flags & MSG_PEEK) == 0 && so->so_oobmark) {
32a43ee2
BJ
539 so->so_oobmark -= len;
540 if (so->so_oobmark == 0) {
541 so->so_state |= SS_RCVATMARK;
542 break;
543 }
544 }
970108c7
BJ
545 if (tomark) {
546 tomark -= len;
547 if (tomark == 0)
548 break;
549 }
a8d3bf7f 550 } while (m && error == 0 && !eor);
88a7a62a 551 if (flags & MSG_PEEK)
970108c7 552 goto release;
ce9d8eb4
BJ
553 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
554 do {
ce9d8eb4 555 if (m == 0)
5fe6f9d1 556 panic("receive 4");
cc15ab5d 557 sbfree(&so->so_rcv, m);
ce9d8eb4
BJ
558 eor = (int)m->m_act;
559 so->so_rcv.sb_mb = m->m_next;
560 MFREE(m, n);
cc15ab5d 561 m = n;
ce9d8eb4 562 } while (eor == 0);
cc15ab5d 563 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
cf012934 564 (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
88a7a62a 565 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0);
cc15ab5d 566release:
ae921915 567 sbunlock(&so->so_rcv);
88a7a62a
SL
568 if (error == 0 && rightsp &&
569 *rightsp && so->so_proto->pr_family == AF_UNIX)
570 error = unp_externalize(*rightsp);
cc15ab5d 571 splx(s);
ae921915 572 return (error);
92a533e6
BJ
573}
574
98422daa 575soshutdown(so, how)
88a7a62a
SL
576 register struct socket *so;
577 register int how;
98422daa 578{
88a7a62a 579 register struct protosw *pr = so->so_proto;
98422daa
SL
580
581 how++;
88a7a62a
SL
582 if (how & FREAD)
583 sorflush(so);
98422daa 584 if (how & FWRITE)
88a7a62a
SL
585 return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN,
586 (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0));
98422daa
SL
587 return (0);
588}
589
88a7a62a
SL
590sorflush(so)
591 register struct socket *so;
592{
593 register struct sockbuf *sb = &so->so_rcv;
594 register struct protosw *pr = so->so_proto;
595 register int s;
596 struct sockbuf asb;
597
598 sblock(sb);
599 s = splimp();
600 socantrcvmore(so);
601 sbunlock(sb);
602 asb = *sb;
603 bzero((caddr_t)sb, sizeof (*sb));
604 splx(s);
605 if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS))
606 unp_scan(asb.sb_mb, unp_discard);
607 sbrelease(&asb);
608}
609
98422daa 610sosetopt(so, level, optname, m)
88a7a62a 611 register struct socket *so;
98422daa 612 int level, optname;
88a7a62a 613 register struct mbuf *m;
98422daa 614{
98422daa
SL
615
616 if (level != SOL_SOCKET)
617 return (EINVAL); /* XXX */
98422daa
SL
618 switch (optname) {
619
620 case SO_DEBUG:
d2cba8de 621 case SO_KEEPALIVE:
b4a3d4a7
SL
622 case SO_DONTROUTE:
623 case SO_USELOOPBACK:
624 case SO_REUSEADDR:
625 so->so_options |= optname;
d2cba8de
SL
626 break;
627
98422daa 628 case SO_LINGER:
d2cba8de
SL
629 if (m == NULL || m->m_len != sizeof (int))
630 return (EINVAL);
98422daa 631 so->so_options |= SO_LINGER;
d2cba8de 632 so->so_linger = *mtod(m, int *);
98422daa
SL
633 break;
634
635 case SO_DONTLINGER:
636 so->so_options &= ~SO_LINGER;
637 so->so_linger = 0;
638 break;
639
98422daa
SL
640 default:
641 return (EINVAL);
642 }
643 return (0);
644}
645
646sogetopt(so, level, optname, m)
88a7a62a 647 register struct socket *so;
98422daa 648 int level, optname;
88a7a62a 649 register struct mbuf *m;
98422daa 650{
98422daa
SL
651
652 if (level != SOL_SOCKET)
653 return (EINVAL); /* XXX */
654 switch (optname) {
655
656 case SO_USELOOPBACK:
657 case SO_DONTROUTE:
658 case SO_DEBUG:
659 case SO_KEEPALIVE:
660 case SO_LINGER:
b4a3d4a7 661 case SO_REUSEADDR:
98422daa
SL
662 if ((so->so_options & optname) == 0)
663 return (ENOPROTOOPT);
d2cba8de 664 if (optname == SO_LINGER && m != NULL) {
98422daa
SL
665 *mtod(m, int *) = so->so_linger;
666 m->m_len = sizeof (so->so_linger);
667 }
668 break;
669
670 default:
671 return (EINVAL);
672 }
673 return (0);
674}
675
edebca28 676sohasoutofband(so)
88a7a62a 677 register struct socket *so;
edebca28
BJ
678{
679
680 if (so->so_pgrp == 0)
681 return;
682 if (so->so_pgrp > 0)
683 gsignal(so->so_pgrp, SIGURG);
0a0f7cbb
BJ
684 else {
685 struct proc *p = pfind(-so->so_pgrp);
686
687 if (p)
688 psignal(p, SIGURG);
689 }
edebca28 690}