merge of 4.1b and 4.1c
[unix-history] / usr / src / sys / kern / uipc_socket.c
CommitLineData
4f083fd7 1/* uipc_socket.c 4.64 82/11/13 */
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;
4f083fd7 37 int error;
cc15ab5d 38
cc15ab5d 39 if (proto)
4f083fd7 40 prp = pffindproto(dom, proto);
cc15ab5d 41 else
4f083fd7 42 prp = pffindtype(dom, type);
cc15ab5d
BJ
43 if (prp == 0)
44 return (EPROTONOSUPPORT);
cf012934
BJ
45 if (prp->pr_type != type)
46 return (EPROTOTYPE);
cc15ab5d 47 m = m_getclr(M_WAIT);
ce9d8eb4
BJ
48 if (m == 0)
49 return (ENOBUFS);
ce9d8eb4 50 so = mtod(m, struct socket *);
cf012934 51 so->so_options = 0;
62364f0e 52 so->so_state = 0;
4f083fd7 53 so->so_type = type;
62364f0e
BJ
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*/
0cc4f3e6 183sostat(so, ub)
92a533e6 184 struct socket *so;
0cc4f3e6 185 struct stat *ub;
92a533e6 186{
0cc4f3e6 187 struct stat sb;
92a533e6 188
0cc4f3e6 189 bzero((caddr_t)&sb, sizeof (sb)); /* XXX */
4f083fd7 190 (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */
5e35cca3 191 return (0); /* XXX */
92a533e6
BJ
192}
193
cf012934 194soaccept(so, nam, opt)
2b4b57cd 195 struct socket *so;
cf012934
BJ
196 struct mbuf *nam;
197 struct socketopt *opt;
2b4b57cd
BJ
198{
199 int s = splnet();
200 int error;
201
cf012934
BJ
202 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
203 (struct mbuf *)0, nam, opt);
2b4b57cd
BJ
204 splx(s);
205 return (error);
206}
207
cf012934 208soconnect(so, nam, opt)
ce9d8eb4 209 struct socket *so;
cf012934
BJ
210 struct mbuf *nam;
211 struct socketopt *opt;
ce9d8eb4 212{
cc15ab5d
BJ
213 int s = splnet();
214 int error;
ce9d8eb4 215
cc15ab5d
BJ
216 if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) {
217 error = EISCONN;
218 goto bad;
219 }
cf012934
BJ
220 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
221 (struct mbuf *)0, nam, opt);
cc15ab5d
BJ
222bad:
223 splx(s);
224 return (error);
ce9d8eb4
BJ
225}
226
cf012934 227sodisconnect(so, nam)
ce9d8eb4 228 struct socket *so;
cf012934 229 struct mbuf *nam;
ce9d8eb4 230{
cc15ab5d
BJ
231 int s = splnet();
232 int error;
ce9d8eb4 233
cc15ab5d
BJ
234 if ((so->so_state & SS_ISCONNECTED) == 0) {
235 error = ENOTCONN;
236 goto bad;
ce9d8eb4 237 }
cc15ab5d
BJ
238 if (so->so_state & SS_ISDISCONNECTING) {
239 error = EALREADY;
240 goto bad;
ce9d8eb4 241 }
cf012934
BJ
242 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
243 (struct mbuf *)0, nam, (struct socketopt *)0);
cc15ab5d
BJ
244bad:
245 splx(s);
246 return (error);
ce9d8eb4
BJ
247}
248
cc15ab5d
BJ
249/*
250 * Send on a socket.
251 * If send must go all at once and message is larger than
252 * send buffering, then hard error.
253 * Lock against other senders.
254 * If must go all at once and not enough room now, then
255 * inform user that this would block and do nothing.
256 */
970108c7 257sosend(so, nam, uio, flags)
ce9d8eb4 258 register struct socket *so;
cf012934 259 struct mbuf *nam;
5699bf69 260 struct uio *uio;
970108c7 261 int flags;
ce9d8eb4 262{
cc15ab5d
BJ
263 struct mbuf *top = 0;
264 register struct mbuf *m, **mp = &top;
5a1f132a 265 register int len;
ae921915 266 int error = 0, space, s;
ce9d8eb4 267
5699bf69 268 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
cc15ab5d 269 return (EMSGSIZE);
0f90f987 270restart:
cc15ab5d
BJ
271 sblock(&so->so_snd);
272#define snderr(errno) { error = errno; splx(s); goto release; }
273
c7256358 274 u.u_ru.ru_msgsnd++;
cc15ab5d 275again:
0f90f987
BJ
276 s = splnet();
277 if (so->so_state & SS_CANTSENDMORE) {
278 psignal(u.u_procp, SIGPIPE);
279 snderr(EPIPE);
280 }
4c078bb2
BJ
281 if (so->so_error) {
282 error = so->so_error;
0f90f987 283 so->so_error = 0; /* ??? */
4c078bb2
BJ
284 splx(s);
285 goto release;
286 }
cc15ab5d
BJ
287 if ((so->so_state & SS_ISCONNECTED) == 0) {
288 if (so->so_proto->pr_flags & PR_CONNREQUIRED)
289 snderr(ENOTCONN);
cf012934 290 if (nam == 0)
cc15ab5d
BJ
291 snderr(EDESTADDRREQ);
292 }
cc15ab5d 293 if (top) {
970108c7
BJ
294 error = (*so->so_proto->pr_usrreq)(so,
295 (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
cf012934 296 top, (caddr_t)nam, (struct socketopt *)0);
0f90f987 297 top = 0;
cc15ab5d
BJ
298 if (error) {
299 splx(s);
ce9d8eb4
BJ
300 goto release;
301 }
cc15ab5d 302 mp = &top;
ce9d8eb4 303 }
5699bf69 304 if (uio->uio_resid == 0) {
b91acce4
BJ
305 splx(s);
306 goto release;
307 }
970108c7
BJ
308 if (flags & SOF_OOB)
309 space = 1024;
310 else {
311 space = sbspace(&so->so_snd);
312 if (space <= 0 ||
313 sosendallatonce(so) && space < uio->uio_resid) {
314 if (so->so_state & SS_NBIO)
315 snderr(EWOULDBLOCK);
316 sbunlock(&so->so_snd);
317 sbwait(&so->so_snd);
318 splx(s);
319 goto restart;
320 }
ce9d8eb4 321 }
cc15ab5d 322 splx(s);
5699bf69
BJ
323 while (uio->uio_resid > 0 && space > 0) {
324 register struct iovec *iov = uio->uio_iov;
325
326 if (iov->iov_len == 0) {
327 uio->uio_iov++;
328 uio->uio_iovcnt--;
329 if (uio->uio_iovcnt < 0)
330 panic("sosend");
331 continue;
332 }
cc15ab5d
BJ
333 MGET(m, 1);
334 if (m == NULL) {
0f90f987 335 error = ENOBUFS; /* SIGPIPE? */
cc15ab5d 336 goto release;
ce9d8eb4 337 }
5699bf69 338 if (iov->iov_len >= CLBYTES && space >= CLBYTES) {
cc15ab5d 339 register struct mbuf *p;
c5ff2e32 340 MCLGET(p, 1);
cc15ab5d
BJ
341 if (p == 0)
342 goto nopages;
343 m->m_off = (int)p - (int)m;
c5ff2e32 344 len = CLBYTES;
cc15ab5d 345 } else {
ce9d8eb4 346nopages:
5699bf69 347 len = MIN(MLEN, iov->iov_len);
ce9d8eb4 348 }
39d536e6 349 (void) uiomove(mtod(m, caddr_t), len, UIO_WRITE, uio);
cc15ab5d
BJ
350 m->m_len = len;
351 *mp = m;
352 mp = &m->m_next;
970108c7
BJ
353 if (flags & SOF_OOB)
354 space -= len;
355 else
356 space = sbspace(&so->so_snd);
ce9d8eb4 357 }
cc15ab5d
BJ
358 goto again;
359
ce9d8eb4 360release:
cc15ab5d 361 sbunlock(&so->so_snd);
0f90f987
BJ
362 if (top)
363 m_freem(top);
ce9d8eb4
BJ
364 return (error);
365}
366
970108c7 367soreceive(so, aname, uio, flags)
ce9d8eb4 368 register struct socket *so;
cf012934 369 struct mbuf **aname;
32a43ee2 370 struct uio *uio;
970108c7 371 int flags;
ce9d8eb4
BJ
372{
373 register struct mbuf *m, *n;
5a1f132a 374 int len;
970108c7
BJ
375 int eor, s, error = 0, moff, tomark;
376
377 if (flags & SOF_OOB) {
a8d3bf7f
BJ
378 m = m_get(M_WAIT);
379 error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
970108c7 380 m, (struct mbuf *)0, (struct socketopt *)0);
a8d3bf7f 381 if (error)
5a1f132a 382 return (error);
970108c7
BJ
383 len = uio->uio_resid;
384 do {
385 if (len > m->m_len)
386 len = m->m_len;
a8d3bf7f 387 error =
a29f7995 388 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
970108c7 389 m = m_free(m);
a8d3bf7f 390 } while (uio->uio_resid && error == 0 && m);
970108c7 391 if (m)
39d536e6 392 m_freem(m);
a8d3bf7f 393 return (error);
970108c7 394 }
ce9d8eb4 395
cc15ab5d
BJ
396restart:
397 sblock(&so->so_rcv);
398 s = splnet();
37d8f813 399SBCHECK(&so->so_rcv, "soreceive restart");
cc15ab5d
BJ
400
401#define rcverr(errno) { error = errno; splx(s); goto release; }
ce9d8eb4 402 if (so->so_rcv.sb_cc == 0) {
4c078bb2
BJ
403 if (so->so_error) {
404 error = so->so_error;
405 so->so_error = 0;
406 splx(s);
407 goto release;
408 }
cc15ab5d
BJ
409 if (so->so_state & SS_CANTRCVMORE) {
410 splx(s);
411 goto release;
412 }
196d84fd
BJ
413 if ((so->so_state & SS_ISCONNECTED) == 0 &&
414 (so->so_proto->pr_flags & PR_CONNREQUIRED))
415 rcverr(ENOTCONN);
62364f0e 416 if (so->so_state & SS_NBIO)
4c078bb2 417 rcverr(EWOULDBLOCK);
cc15ab5d 418 sbunlock(&so->so_rcv);
2752c877 419 sbwait(&so->so_rcv);
a4f6d93d 420 splx(s);
cc15ab5d 421 goto restart;
ce9d8eb4 422 }
c7256358 423 u.u_ru.ru_msgrcv++;
92a533e6 424 m = so->so_rcv.sb_mb;
ce9d8eb4
BJ
425 if (m == 0)
426 panic("receive");
e435773e 427SBCHECK(&so->so_snd, "soreceive havecc");
b031e888 428 if (so->so_proto->pr_flags & PR_ADDR) {
970108c7
BJ
429 if ((flags & SOF_PREVIEW) == 0) {
430 so->so_rcv.sb_cc -= m->m_len;
431 so->so_rcv.sb_mbcnt -= MSIZE;
432 }
cf012934 433 if (aname) {
970108c7
BJ
434 if (flags & SOF_PREVIEW)
435 *aname = m_copy(m, 0, m->m_len);
436 else
437 *aname = m;
cf012934
BJ
438 m = m->m_next;
439 (*aname)->m_next = 0;
440 } else
970108c7
BJ
441 if (flags & SOF_PREVIEW)
442 m = m->m_next;
443 else
444 m = m_free(m);
cc15ab5d
BJ
445 if (m == 0)
446 panic("receive 2");
e435773e
BJ
447 if ((flags & SOF_PREVIEW) == 0)
448 so->so_rcv.sb_mb = m;
449SBCHECK(&so->so_snd, "soreceive afteraddr");
cc15ab5d 450 }
ce9d8eb4 451 eor = 0;
970108c7
BJ
452 moff = 0;
453 tomark = so->so_oobmark;
ce9d8eb4 454 do {
5699bf69 455 if (uio->uio_resid <= 0)
32a43ee2 456 break;
5699bf69 457 len = uio->uio_resid;
32a43ee2 458 so->so_state &= ~SS_RCVATMARK;
970108c7
BJ
459 if (tomark && len > tomark)
460 len = tomark;
e435773e 461 if (moff+len > m->m_len - moff)
970108c7 462 len = m->m_len - moff;
ce9d8eb4 463 splx(s);
a8d3bf7f 464 error =
a29f7995 465 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
ce9d8eb4
BJ
466 s = splnet();
467 if (len == m->m_len) {
e495e1cc 468 eor = (int)m->m_act;
970108c7
BJ
469 if (flags & SOF_PREVIEW)
470 m = m->m_next;
471 else {
472 sbfree(&so->so_rcv, m);
473 MFREE(m, n);
474 m = n;
e435773e 475 so->so_rcv.sb_mb = m;
970108c7
BJ
476 }
477 moff = 0;
ce9d8eb4 478 } else {
970108c7
BJ
479 if (flags & SOF_PREVIEW)
480 moff += len;
481 else {
482 m->m_off += len;
483 m->m_len -= len;
484 so->so_rcv.sb_cc -= len;
485 }
ce9d8eb4 486 }
970108c7 487 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) {
32a43ee2
BJ
488 so->so_oobmark -= len;
489 if (so->so_oobmark == 0) {
490 so->so_state |= SS_RCVATMARK;
491 break;
492 }
493 }
970108c7
BJ
494 if (tomark) {
495 tomark -= len;
496 if (tomark == 0)
497 break;
498 }
e435773e 499SBCHECK(&so->so_snd, "soreceive rcvloop");
a8d3bf7f 500 } while (m && error == 0 && !eor);
970108c7
BJ
501 if (flags & SOF_PREVIEW)
502 goto release;
ce9d8eb4
BJ
503 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
504 do {
ce9d8eb4 505 if (m == 0)
cc15ab5d
BJ
506 panic("receive 3");
507 sbfree(&so->so_rcv, m);
ce9d8eb4
BJ
508 eor = (int)m->m_act;
509 so->so_rcv.sb_mb = m->m_next;
510 MFREE(m, n);
cc15ab5d 511 m = n;
e435773e 512SBCHECK(&so->so_snd, "soreceive atomicloop");
ce9d8eb4 513 } while (eor == 0);
cc15ab5d 514 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
cf012934
BJ
515 (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
516 (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0);
cc15ab5d 517release:
ae921915 518 sbunlock(&so->so_rcv);
cc15ab5d 519 splx(s);
ae921915 520 return (error);
92a533e6
BJ
521}
522
edebca28
BJ
523sohasoutofband(so)
524 struct socket *so;
525{
526
527 if (so->so_pgrp == 0)
528 return;
529 if (so->so_pgrp > 0)
530 gsignal(so->so_pgrp, SIGURG);
0a0f7cbb
BJ
531 else {
532 struct proc *p = pfind(-so->so_pgrp);
533
534 if (p)
535 psignal(p, SIGURG);
536 }
edebca28
BJ
537}
538
ae921915 539/*ARGSUSED*/
4b72e2f9 540soioctl(so, cmd, data)
92a533e6
BJ
541 register struct socket *so;
542 int cmd;
4b72e2f9 543 register char *data;
92a533e6
BJ
544{
545
2156d53c 546 switch (cmd) {
92a533e6 547
4b72e2f9
SL
548 case FIONBIO:
549 if (*(int *)data)
62364f0e 550 so->so_state |= SS_NBIO;
30b84e26 551 else
62364f0e 552 so->so_state &= ~SS_NBIO;
a8d3bf7f 553 break;
30b84e26 554
4b72e2f9
SL
555 case FIOASYNC:
556 if (*(int *)data)
62364f0e 557 so->so_state |= SS_ASYNC;
30b84e26 558 else
62364f0e 559 so->so_state &= ~SS_ASYNC;
a8d3bf7f 560 break;
30b84e26 561
4b72e2f9
SL
562 case SIOCSKEEP:
563 if (*(int *)data)
9d2f171f 564 so->so_options &= ~SO_KEEPALIVE;
90aaea96
BJ
565 else
566 so->so_options |= SO_KEEPALIVE;
a8d3bf7f 567 break;
30b84e26 568
4b72e2f9
SL
569 case SIOCGKEEP:
570 *(int *)data = (so->so_options & SO_KEEPALIVE) != 0;
a8d3bf7f 571 break;
30b84e26 572
4b72e2f9
SL
573 case SIOCSLINGER:
574 so->so_linger = *(int *)data;
30b84e26
BJ
575 if (so->so_linger)
576 so->so_options &= ~SO_DONTLINGER;
577 else
578 so->so_options |= SO_DONTLINGER;
a8d3bf7f 579 break;
30b84e26 580
4b72e2f9
SL
581 case SIOCGLINGER:
582 *(int *)data = so->so_linger;
a8d3bf7f 583 break;
edebca28 584
4b72e2f9
SL
585 case SIOCSPGRP:
586 so->so_pgrp = *(int *)data;
a8d3bf7f 587 break;
4b72e2f9
SL
588
589 case SIOCGPGRP:
590 *(int *)data = so->so_pgrp;
a8d3bf7f 591 break;
30b84e26 592
b8acc34d 593 case SIOCDONE: {
4b72e2f9
SL
594 int flags = *(int *)data;
595
30b84e26 596 flags++;
b8acc34d
BJ
597 if (flags & FREAD) {
598 int s = splimp();
599 socantrcvmore(so);
600 sbflush(&so->so_rcv);
785e10b7 601 splx(s);
b8acc34d
BJ
602 }
603 if (flags & FWRITE)
47b7bdd9 604 return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN,
cf012934 605 (struct mbuf *)0, (struct mbuf *)0,
47b7bdd9 606 (struct socketopt *)0));
a8d3bf7f 607 break;
b8acc34d
BJ
608 }
609
edebca28 610 case SIOCSENDOOB: {
4b72e2f9 611 char oob = *(char *)data;
970108c7 612 struct mbuf *m = m_get(M_DONTWAIT);
4b72e2f9 613
a8d3bf7f
BJ
614 if (m == 0)
615 return (ENOBUFS);
970108c7 616 m->m_len = 1;
4b72e2f9 617 *mtod(m, char *) = oob;
47b7bdd9
BJ
618 return ((*so->so_proto->pr_usrreq)(so, PRU_SENDOOB,
619 m, (struct mbuf *)0, (struct socketopt *)0));
edebca28
BJ
620 }
621
622 case SIOCRCVOOB: {
970108c7 623 struct mbuf *m = m_get(M_WAIT);
4b72e2f9 624
a8d3bf7f
BJ
625 if (m == 0)
626 return (ENOBUFS);
970108c7 627 *mtod(m, caddr_t) = 0;
cf012934
BJ
628 (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
629 m, (struct mbuf *)0, (struct socketopt *)0);
4b72e2f9
SL
630 *(char *)data = *mtod(m, char *);
631 (void) m_free(m);
a8d3bf7f 632 break;
edebca28
BJ
633 }
634
4b72e2f9
SL
635 case SIOCATMARK:
636 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
a8d3bf7f 637 break;
2a4251c4
SL
638
639 /* routing table update calls */
640 case SIOCADDRT:
641 case SIOCDELRT:
2a4251c4 642 if (!suser())
47b7bdd9
BJ
643 return (u.u_error); /* XXX */
644 return (rtrequest(cmd, (struct rtentry *)data));
2a4251c4 645
5e1eeba0 646 /* type/protocol specific ioctls */
a8d3bf7f
BJ
647 default:
648 return (ENOTTY);
92a533e6 649 }
a8d3bf7f 650 return (0);
ce9d8eb4 651}