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