remove crud
[unix-history] / usr / src / sys / kern / uipc_socket.c
CommitLineData
2b77b553 1/* uipc_socket.c 4.62 82/10/31 */
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"
92a533e6
BJ
12#include "../h/protosw.h"
13#include "../h/socket.h"
14#include "../h/socketvar.h"
ae921915 15#include "../h/stat.h"
b8acc34d 16#include "../h/ioctl.h"
32a43ee2 17#include "../h/uio.h"
3a35e7af 18#include "../net/route.h"
ce9d8eb4 19
ce9d8eb4 20/*
cf012934
BJ
21 * Socket operation routines.
22 * These routines are called by the routines in
23 * sys_socket.c or from a system process, and
24 * implement the semantics of socket operations by
25 * switching out to the protocol specific routines.
ce9d8eb4 26 */
ce9d8eb4 27
a8d3bf7f 28/*ARGSUSED*/
cf012934 29socreate(dom, aso, type, proto, opt)
ce9d8eb4 30 struct socket **aso;
cf012934
BJ
31 int type, proto;
32 struct socketopt *opt;
ce9d8eb4
BJ
33{
34 register struct protosw *prp;
35 register struct socket *so;
36 struct mbuf *m;
cf012934 37 int pf, error;
cc15ab5d 38
cf012934 39 pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */
cc15ab5d
BJ
40 if (proto)
41 prp = pffindproto(pf, proto);
42 else
43 prp = pffindtype(pf, type);
44 if (prp == 0)
45 return (EPROTONOSUPPORT);
cf012934
BJ
46 if (prp->pr_type != type)
47 return (EPROTOTYPE);
cc15ab5d 48 m = m_getclr(M_WAIT);
ce9d8eb4
BJ
49 if (m == 0)
50 return (ENOBUFS);
ce9d8eb4 51 so = mtod(m, struct socket *);
cf012934 52 so->so_options = 0;
62364f0e
BJ
53 so->so_state = 0;
54 if (u.u_uid == 0)
55 so->so_state = SS_PRIV;
ce9d8eb4 56 so->so_proto = prp;
cf012934
BJ
57 error = (*prp->pr_usrreq)(so, PRU_ATTACH,
58 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
b91acce4 59 if (error) {
90aaea96 60 so->so_state |= SS_NOFDREF;
de48daf3 61 sofree(so);
cc15ab5d 62 return (error);
ce9d8eb4
BJ
63 }
64 *aso = so;
65 return (0);
66}
67
cf012934
BJ
68sobind(so, nam, opt)
69 struct socket *so;
70 struct mbuf *nam;
71 struct socketopt *opt;
72{
73 int s = splnet();
74 int error;
75
76 error =
77 (*so->so_proto->pr_usrreq)(so, PRU_BIND,
78 (struct mbuf *)0, nam, opt);
79 splx(s);
80 return (error);
81}
82
83solisten(so, backlog)
84 struct socket *so;
85 int backlog;
86{
87 int s = splnet();
88 int error;
89
90 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
91 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
92 if (error) {
93 splx(s);
94 return (error);
95 }
96 if (so->so_q == 0) {
97 so->so_q = so;
98 so->so_q0 = so;
99 so->so_options |= SO_ACCEPTCONN;
100 }
101 if (backlog < 0)
102 backlog = 0;
103 so->so_qlimit = backlog < 5 ? backlog : 5;
104 so->so_options |= SO_NEWFDONCONN;
105 return (0);
106}
107
ae921915
BJ
108sofree(so)
109 struct socket *so;
110{
111
90aaea96
BJ
112 if (so->so_head) {
113 if (!soqremque(so, 0) && !soqremque(so, 1))
114 panic("sofree dq");
115 so->so_head = 0;
116 }
117 if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
4ad99bae
BJ
118 return;
119 sbrelease(&so->so_snd);
120 sbrelease(&so->so_rcv);
2752c877 121 (void) m_free(dtom(so));
ae921915
BJ
122}
123
92a533e6 124/*
cc15ab5d
BJ
125 * Close a socket on last file table reference removal.
126 * Initiate disconnect if connected.
127 * Free socket when disconnect complete.
92a533e6 128 */
89900a09 129soclose(so, exiting)
92a533e6 130 register struct socket *so;
89900a09 131 int exiting;
92a533e6 132{
cc15ab5d 133 int s = splnet(); /* conservative */
5a1f132a 134 int error;
cc15ab5d 135
90aaea96
BJ
136 if (so->so_options & SO_ACCEPTCONN) {
137 while (so->so_q0 != so)
5a1f132a 138 (void) soclose(so->so_q0, 1);
90aaea96 139 while (so->so_q != so)
5a1f132a 140 (void) soclose(so->so_q, 1);
90aaea96 141 }
cc15ab5d
BJ
142 if (so->so_pcb == 0)
143 goto discard;
1ee9e088
BJ
144 if (exiting)
145 so->so_options |= SO_KEEPALIVE;
cc15ab5d
BJ
146 if (so->so_state & SS_ISCONNECTED) {
147 if ((so->so_state & SS_ISDISCONNECTING) == 0) {
ac76a23d 148 error = sodisconnect(so, (struct mbuf *)0);
5a1f132a 149 if (error) {
89900a09
BJ
150 if (exiting)
151 goto drop;
cc15ab5d 152 splx(s);
5a1f132a 153 return (error);
cc15ab5d
BJ
154 }
155 }
30b84e26 156 if ((so->so_options & SO_DONTLINGER) == 0) {
b8acc34d 157 if ((so->so_state & SS_ISDISCONNECTING) &&
62364f0e 158 (so->so_state & SS_NBIO) &&
5a1f132a
BJ
159 exiting == 0)
160 return (EINPROGRESS);
89900a09 161 /* should use tsleep here, for at most linger */
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) {
5a1f132a 168 error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
cf012934 169 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
5a1f132a 170 if (exiting == 0 && error) {
37c0974a 171 splx(s);
5a1f132a 172 return (error);
37c0974a
SL
173 }
174 }
cc15ab5d 175discard:
90aaea96 176 so->so_state |= SS_NOFDREF;
4ad99bae 177 sofree(so);
cc15ab5d 178 splx(s);
5a1f132a 179 return (0);
92a533e6
BJ
180}
181
ae921915 182/*ARGSUSED*/
cc15ab5d 183sostat(so, sb)
92a533e6 184 struct socket *so;
cc15ab5d 185 struct stat *sb;
92a533e6
BJ
186{
187
5e35cca3 188 bzero((caddr_t)sb, sizeof (*sb)); /* XXX */
2b77b553 189 copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */
5e35cca3 190 return (0); /* XXX */
92a533e6
BJ
191}
192
cf012934 193soaccept(so, nam, opt)
2b4b57cd 194 struct socket *so;
cf012934
BJ
195 struct mbuf *nam;
196 struct socketopt *opt;
2b4b57cd
BJ
197{
198 int s = splnet();
199 int error;
200
cf012934
BJ
201 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
202 (struct mbuf *)0, nam, opt);
2b4b57cd
BJ
203 splx(s);
204 return (error);
205}
206
cf012934 207soconnect(so, nam, opt)
ce9d8eb4 208 struct socket *so;
cf012934
BJ
209 struct mbuf *nam;
210 struct socketopt *opt;
ce9d8eb4 211{
cc15ab5d
BJ
212 int s = splnet();
213 int error;
ce9d8eb4 214
cc15ab5d
BJ
215 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
216 error = EISCONN;
217 goto bad;
218 }
cf012934
BJ
219 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
220 (struct mbuf *)0, nam, opt);
cc15ab5d
BJ
221bad:
222 splx(s);
223 return (error);
ce9d8eb4
BJ
224}
225
cf012934 226sodisconnect(so, nam)
ce9d8eb4 227 struct socket *so;
cf012934 228 struct mbuf *nam;
ce9d8eb4 229{
cc15ab5d
BJ
230 int s = splnet();
231 int error;
ce9d8eb4 232
cc15ab5d
BJ
233 if ((so->so_state & SS_ISCONNECTED) == 0) {
234 error = ENOTCONN;
235 goto bad;
ce9d8eb4 236 }
cc15ab5d
BJ
237 if (so->so_state & SS_ISDISCONNECTING) {
238 error = EALREADY;
239 goto bad;
ce9d8eb4 240 }
cf012934
BJ
241 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
242 (struct mbuf *)0, nam, (struct socketopt *)0);
cc15ab5d
BJ
243bad:
244 splx(s);
245 return (error);
ce9d8eb4
BJ
246}
247
cc15ab5d
BJ
248/*
249 * Send on a socket.
250 * If send must go all at once and message is larger than
251 * send buffering, then hard error.
252 * Lock against other senders.
253 * If must go all at once and not enough room now, then
254 * inform user that this would block and do nothing.
255 */
970108c7 256sosend(so, nam, uio, flags)
ce9d8eb4 257 register struct socket *so;
cf012934 258 struct mbuf *nam;
5699bf69 259 struct uio *uio;
970108c7 260 int flags;
ce9d8eb4 261{
cc15ab5d
BJ
262 struct mbuf *top = 0;
263 register struct mbuf *m, **mp = &top;
5a1f132a 264 register int len;
ae921915 265 int error = 0, space, s;
ce9d8eb4 266
5699bf69 267 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
cc15ab5d 268 return (EMSGSIZE);
0f90f987 269restart:
cc15ab5d
BJ
270 sblock(&so->so_snd);
271#define snderr(errno) { error = errno; splx(s); goto release; }
272
c7256358 273 u.u_ru.ru_msgsnd++;
cc15ab5d 274again:
0f90f987
BJ
275 s = splnet();
276 if (so->so_state & SS_CANTSENDMORE) {
277 psignal(u.u_procp, SIGPIPE);
278 snderr(EPIPE);
279 }
4c078bb2
BJ
280 if (so->so_error) {
281 error = so->so_error;
0f90f987 282 so->so_error = 0; /* ??? */
4c078bb2
BJ
283 splx(s);
284 goto release;
285 }
cc15ab5d
BJ
286 if ((so->so_state & SS_ISCONNECTED) == 0) {
287 if (so->so_proto->pr_flags & PR_CONNREQUIRED)
288 snderr(ENOTCONN);
cf012934 289 if (nam == 0)
cc15ab5d
BJ
290 snderr(EDESTADDRREQ);
291 }
cc15ab5d 292 if (top) {
970108c7
BJ
293 error = (*so->so_proto->pr_usrreq)(so,
294 (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
cf012934 295 top, (caddr_t)nam, (struct socketopt *)0);
0f90f987 296 top = 0;
cc15ab5d
BJ
297 if (error) {
298 splx(s);
ce9d8eb4
BJ
299 goto release;
300 }
cc15ab5d 301 mp = &top;
ce9d8eb4 302 }
5699bf69 303 if (uio->uio_resid == 0) {
b91acce4
BJ
304 splx(s);
305 goto release;
306 }
970108c7
BJ
307 if (flags & SOF_OOB)
308 space = 1024;
309 else {
310 space = sbspace(&so->so_snd);
311 if (space <= 0 ||
312 sosendallatonce(so) && space < uio->uio_resid) {
313 if (so->so_state & SS_NBIO)
314 snderr(EWOULDBLOCK);
315 sbunlock(&so->so_snd);
316 sbwait(&so->so_snd);
317 splx(s);
318 goto restart;
319 }
ce9d8eb4 320 }
cc15ab5d 321 splx(s);
5699bf69
BJ
322 while (uio->uio_resid > 0 && space > 0) {
323 register struct iovec *iov = uio->uio_iov;
324
325 if (iov->iov_len == 0) {
326 uio->uio_iov++;
327 uio->uio_iovcnt--;
328 if (uio->uio_iovcnt < 0)
329 panic("sosend");
330 continue;
331 }
cc15ab5d
BJ
332 MGET(m, 1);
333 if (m == NULL) {
0f90f987 334 error = ENOBUFS; /* SIGPIPE? */
cc15ab5d 335 goto release;
ce9d8eb4 336 }
5699bf69 337 if (iov->iov_len >= CLBYTES && space >= CLBYTES) {
cc15ab5d 338 register struct mbuf *p;
c5ff2e32 339 MCLGET(p, 1);
cc15ab5d
BJ
340 if (p == 0)
341 goto nopages;
342 m->m_off = (int)p - (int)m;
c5ff2e32 343 len = CLBYTES;
cc15ab5d 344 } else {
ce9d8eb4 345nopages:
5699bf69 346 len = MIN(MLEN, iov->iov_len);
ce9d8eb4 347 }
39d536e6 348 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
cc15ab5d
BJ
349 m->m_len = len;
350 *mp = m;
351 mp = &m->m_next;
970108c7
BJ
352 if (flags & SOF_OOB)
353 space -= len;
354 else
355 space = sbspace(&so->so_snd);
ce9d8eb4 356 }
cc15ab5d
BJ
357 goto again;
358
ce9d8eb4 359release:
cc15ab5d 360 sbunlock(&so->so_snd);
0f90f987
BJ
361 if (top)
362 m_freem(top);
ce9d8eb4
BJ
363 return (error);
364}
365
970108c7 366soreceive(so, aname, uio, flags)
ce9d8eb4 367 register struct socket *so;
cf012934 368 struct mbuf **aname;
32a43ee2 369 struct uio *uio;
970108c7 370 int flags;
ce9d8eb4
BJ
371{
372 register struct mbuf *m, *n;
5a1f132a 373 int len;
970108c7
BJ
374 int eor, s, error = 0, moff, tomark;
375
376 if (flags & SOF_OOB) {
a8d3bf7f
BJ
377 m = m_get(M_WAIT);
378 error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
970108c7 379 m, (struct mbuf *)0, (struct socketopt *)0);
a8d3bf7f 380 if (error)
5a1f132a 381 return (error);
970108c7
BJ
382 len = uio->uio_resid;
383 do {
384 if (len > m->m_len)
385 len = m->m_len;
a8d3bf7f 386 error =
a29f7995 387 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
970108c7 388 m = m_free(m);
a8d3bf7f 389 } while (uio->uio_resid && error == 0 && m);
970108c7 390 if (m)
39d536e6 391 m_freem(m);
a8d3bf7f 392 return (error);
970108c7 393 }
ce9d8eb4 394
cc15ab5d
BJ
395restart:
396 sblock(&so->so_rcv);
397 s = splnet();
37d8f813 398SBCHECK(&so->so_rcv, "soreceive restart");
cc15ab5d
BJ
399
400#define rcverr(errno) { error = errno; splx(s); goto release; }
ce9d8eb4 401 if (so->so_rcv.sb_cc == 0) {
4c078bb2
BJ
402 if (so->so_error) {
403 error = so->so_error;
404 so->so_error = 0;
405 splx(s);
406 goto release;
407 }
cc15ab5d
BJ
408 if (so->so_state & SS_CANTRCVMORE) {
409 splx(s);
410 goto release;
411 }
196d84fd
BJ
412 if ((so->so_state & SS_ISCONNECTED) == 0 &&
413 (so->so_proto->pr_flags & PR_CONNREQUIRED))
414 rcverr(ENOTCONN);
62364f0e 415 if (so->so_state & SS_NBIO)
4c078bb2 416 rcverr(EWOULDBLOCK);
cc15ab5d 417 sbunlock(&so->so_rcv);
2752c877 418 sbwait(&so->so_rcv);
a4f6d93d 419 splx(s);
cc15ab5d 420 goto restart;
ce9d8eb4 421 }
c7256358 422 u.u_ru.ru_msgrcv++;
92a533e6 423 m = so->so_rcv.sb_mb;
ce9d8eb4
BJ
424 if (m == 0)
425 panic("receive");
e435773e 426SBCHECK(&so->so_snd, "soreceive havecc");
b031e888 427 if (so->so_proto->pr_flags & PR_ADDR) {
970108c7
BJ
428 if ((flags & SOF_PREVIEW) == 0) {
429 so->so_rcv.sb_cc -= m->m_len;
430 so->so_rcv.sb_mbcnt -= MSIZE;
431 }
cf012934 432 if (aname) {
970108c7
BJ
433 if (flags & SOF_PREVIEW)
434 *aname = m_copy(m, 0, m->m_len);
435 else
436 *aname = m;
cf012934
BJ
437 m = m->m_next;
438 (*aname)->m_next = 0;
439 } else
970108c7
BJ
440 if (flags & SOF_PREVIEW)
441 m = m->m_next;
442 else
443 m = m_free(m);
cc15ab5d
BJ
444 if (m == 0)
445 panic("receive 2");
e435773e
BJ
446 if ((flags & SOF_PREVIEW) == 0)
447 so->so_rcv.sb_mb = m;
448SBCHECK(&so->so_snd, "soreceive afteraddr");
cc15ab5d 449 }
ce9d8eb4 450 eor = 0;
970108c7
BJ
451 moff = 0;
452 tomark = so->so_oobmark;
ce9d8eb4 453 do {
5699bf69 454 if (uio->uio_resid <= 0)
32a43ee2 455 break;
5699bf69 456 len = uio->uio_resid;
32a43ee2 457 so->so_state &= ~SS_RCVATMARK;
970108c7
BJ
458 if (tomark && len > tomark)
459 len = tomark;
e435773e 460 if (moff+len > m->m_len - moff)
970108c7 461 len = m->m_len - moff;
ce9d8eb4 462 splx(s);
a8d3bf7f 463 error =
a29f7995 464 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
ce9d8eb4
BJ
465 s = splnet();
466 if (len == m->m_len) {
e495e1cc 467 eor = (int)m->m_act;
970108c7
BJ
468 if (flags & SOF_PREVIEW)
469 m = m->m_next;
470 else {
471 sbfree(&so->so_rcv, m);
472 MFREE(m, n);
473 m = n;
e435773e 474 so->so_rcv.sb_mb = m;
970108c7
BJ
475 }
476 moff = 0;
ce9d8eb4 477 } else {
970108c7
BJ
478 if (flags & SOF_PREVIEW)
479 moff += len;
480 else {
481 m->m_off += len;
482 m->m_len -= len;
483 so->so_rcv.sb_cc -= len;
484 }
ce9d8eb4 485 }
970108c7 486 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) {
32a43ee2
BJ
487 so->so_oobmark -= len;
488 if (so->so_oobmark == 0) {
489 so->so_state |= SS_RCVATMARK;
490 break;
491 }
492 }
970108c7
BJ
493 if (tomark) {
494 tomark -= len;
495 if (tomark == 0)
496 break;
497 }
e435773e 498SBCHECK(&so->so_snd, "soreceive rcvloop");
a8d3bf7f 499 } while (m && error == 0 && !eor);
970108c7
BJ
500 if (flags & SOF_PREVIEW)
501 goto release;
ce9d8eb4
BJ
502 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
503 do {
ce9d8eb4 504 if (m == 0)
cc15ab5d
BJ
505 panic("receive 3");
506 sbfree(&so->so_rcv, m);
ce9d8eb4
BJ
507 eor = (int)m->m_act;
508 so->so_rcv.sb_mb = m->m_next;
509 MFREE(m, n);
cc15ab5d 510 m = n;
e435773e 511SBCHECK(&so->so_snd, "soreceive atomicloop");
ce9d8eb4 512 } while (eor == 0);
cc15ab5d 513 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
cf012934
BJ
514 (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
515 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
cc15ab5d 516release:
ae921915 517 sbunlock(&so->so_rcv);
cc15ab5d 518 splx(s);
ae921915 519 return (error);
92a533e6
BJ
520}
521
edebca28
BJ
522sohasoutofband(so)
523 struct socket *so;
524{
525
526 if (so->so_pgrp == 0)
527 return;
528 if (so->so_pgrp > 0)
529 gsignal(so->so_pgrp, SIGURG);
0a0f7cbb
BJ
530 else {
531 struct proc *p = pfind(-so->so_pgrp);
532
533 if (p)
534 psignal(p, SIGURG);
535 }
edebca28
BJ
536}
537
ae921915 538/*ARGSUSED*/
4b72e2f9 539soioctl(so, cmd, data)
92a533e6
BJ
540 register struct socket *so;
541 int cmd;
4b72e2f9 542 register char *data;
92a533e6
BJ
543{
544
2156d53c 545 switch (cmd) {
92a533e6 546
4b72e2f9
SL
547 case FIONBIO:
548 if (*(int *)data)
62364f0e 549 so->so_state |= SS_NBIO;
30b84e26 550 else
62364f0e 551 so->so_state &= ~SS_NBIO;
a8d3bf7f 552 break;
30b84e26 553
4b72e2f9
SL
554 case FIOASYNC:
555 if (*(int *)data)
62364f0e 556 so->so_state |= SS_ASYNC;
30b84e26 557 else
62364f0e 558 so->so_state &= ~SS_ASYNC;
a8d3bf7f 559 break;
30b84e26 560
4b72e2f9
SL
561 case SIOCSKEEP:
562 if (*(int *)data)
9d2f171f 563 so->so_options &= ~SO_KEEPALIVE;
90aaea96
BJ
564 else
565 so->so_options |= SO_KEEPALIVE;
a8d3bf7f 566 break;
30b84e26 567
4b72e2f9
SL
568 case SIOCGKEEP:
569 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0;
a8d3bf7f 570 break;
30b84e26 571
4b72e2f9
SL
572 case SIOCSLINGER:
573 so->so_linger = *(int *)data;
30b84e26
BJ
574 if (so->so_linger)
575 so->so_options &= ~SO_DONTLINGER;
576 else
577 so->so_options |= SO_DONTLINGER;
a8d3bf7f 578 break;
30b84e26 579
4b72e2f9
SL
580 case SIOCGLINGER:
581 *(int *)data = so->so_linger;
a8d3bf7f 582 break;
edebca28 583
4b72e2f9
SL
584 case SIOCSPGRP:
585 so->so_pgrp = *(int *)data;
a8d3bf7f 586 break;
4b72e2f9
SL
587
588 case SIOCGPGRP:
589 *(int *)data = so->so_pgrp;
a8d3bf7f 590 break;
30b84e26 591
b8acc34d 592 case SIOCDONE: {
4b72e2f9
SL
593 int flags = *(int *)data;
594
30b84e26 595 flags++;
b8acc34d
BJ
596 if (flags & FREAD) {
597 int s = splimp();
598 socantrcvmore(so);
599 sbflush(&so->so_rcv);
785e10b7 600 splx(s);
b8acc34d
BJ
601 }
602 if (flags & FWRITE)
47b7bdd9 603 return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN,
cf012934 604 (struct mbuf *)0, (struct mbuf *)0,
47b7bdd9 605 (struct socketopt *)0));
a8d3bf7f 606 break;
b8acc34d
BJ
607 }
608
edebca28 609 case SIOCSENDOOB: {
4b72e2f9 610 char oob = *(char *)data;
970108c7 611 struct mbuf *m = m_get(M_DONTWAIT);
4b72e2f9 612
a8d3bf7f
BJ
613 if (m == 0)
614 return (ENOBUFS);
970108c7 615 m->m_len = 1;
4b72e2f9 616 *mtod(m, char *) = oob;
47b7bdd9
BJ
617 return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB,
618 m, (struct mbuf *)0, (struct socketopt *)0));
edebca28
BJ
619 }
620
621 case SIOCRCVOOB: {
970108c7 622 struct mbuf *m = m_get(M_WAIT);
4b72e2f9 623
a8d3bf7f
BJ
624 if (m == 0)
625 return (ENOBUFS);
970108c7 626 *mtod(m, caddr_t) = 0;
cf012934
BJ
627 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
628 m, (struct mbuf *)0, (struct socketopt *)0);
4b72e2f9
SL
629 *(char *)data = *mtod(m, char *);
630 (void) m_free(m);
a8d3bf7f 631 break;
edebca28
BJ
632 }
633
4b72e2f9
SL
634 case SIOCATMARK:
635 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
a8d3bf7f 636 break;
2a4251c4
SL
637
638 /* routing table update calls */
639 case SIOCADDRT:
640 case SIOCDELRT:
2a4251c4 641 if (!suser())
47b7bdd9
BJ
642 return (u.u_error); /* XXX */
643 return (rtrequest(cmd, (struct rtentry *)data));
2a4251c4 644
5e1eeba0 645 /* type/protocol specific ioctls */
a8d3bf7f
BJ
646 default:
647 return (ENOTTY);
92a533e6 648 }
a8d3bf7f 649 return (0);
ce9d8eb4 650}