purge mush; stuff for i_blocks
[unix-history] / usr / src / sys / kern / uipc_socket.c
CommitLineData
9e87be97 1/* uipc_socket.c 4.74 83/05/18 */
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"
22f36762 19#include "../net/if.h"
ce9d8eb4 20
ce9d8eb4 21/*
cf012934
BJ
22 * Socket operation routines.
23 * These routines are called by the routines in
24 * sys_socket.c or from a system process, and
25 * implement the semantics of socket operations by
26 * switching out to the protocol specific routines.
ce9d8eb4 27 */
ce9d8eb4 28
a8d3bf7f 29/*ARGSUSED*/
98422daa 30socreate(dom, aso, type, proto)
ce9d8eb4 31 struct socket **aso;
cf012934 32 int type, proto;
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);
cce93e4b 47 m = m_getclr(M_WAIT, MT_SOCKET);
ce9d8eb4
BJ
48 if (m == 0)
49 return (ENOBUFS);
ce9d8eb4 50 so = mtod(m, struct socket *);
98422daa 51 so->so_options = SO_LINGER;
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 57 error = (*prp->pr_usrreq)(so, PRU_ATTACH,
98422daa 58 (struct mbuf *)0, (struct mbuf *)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
98422daa 68sobind(so, nam)
cf012934
BJ
69 struct socket *so;
70 struct mbuf *nam;
cf012934
BJ
71{
72 int s = splnet();
73 int error;
74
75 error =
98422daa 76 (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam);
cf012934
BJ
77 splx(s);
78 return (error);
79}
80
81solisten(so, backlog)
82 struct socket *so;
83 int backlog;
84{
85 int s = splnet();
86 int error;
87
88 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN,
98422daa 89 (struct mbuf *)0, (struct mbuf *)0);
cf012934
BJ
90 if (error) {
91 splx(s);
92 return (error);
93 }
94 if (so->so_q == 0) {
95 so->so_q = so;
96 so->so_q0 = so;
97 so->so_options |= SO_ACCEPTCONN;
98 }
99 if (backlog < 0)
100 backlog = 0;
5fe6f9d1
SL
101#define SOMAXCONN 5
102 so->so_qlimit = MIN(backlog, SOMAXCONN);
cf012934 103 so->so_options |= SO_NEWFDONCONN;
9e87be97 104 splx(s);
cf012934
BJ
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)
26225f25 138 (void) soabort(so->so_q0);
90aaea96 139 while (so->so_q != so)
26225f25 140 (void) soabort(so->so_q);
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 }
98422daa 156 if (so->so_options & SO_LINGER) {
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,
98422daa 169 (struct mbuf *)0, (struct mbuf *)0);
5a1f132a 170 if (exiting == 0 && error) {
37c0974a 171 splx(s);
5a1f132a 172 return (error);
37c0974a
SL
173 }
174 }
cc15ab5d 175discard:
26225f25
SL
176 if (so->so_state & SS_NOFDREF)
177 panic("soclose: NOFDREF");
90aaea96 178 so->so_state |= SS_NOFDREF;
4ad99bae 179 sofree(so);
cc15ab5d 180 splx(s);
5a1f132a 181 return (0);
92a533e6
BJ
182}
183
26225f25
SL
184/*
185 * Must be called at splnet...
186 */
187soabort(so)
188 struct socket *so;
189{
190 int error;
191
192 error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT,
193 (struct mbuf *)0, (struct mbuf *)0);
194 return (error);
195}
196
ae921915 197/*ARGSUSED*/
0cc4f3e6 198sostat(so, ub)
92a533e6 199 struct socket *so;
0cc4f3e6 200 struct stat *ub;
92a533e6 201{
0cc4f3e6 202 struct stat sb;
92a533e6 203
0cc4f3e6 204 bzero((caddr_t)&sb, sizeof (sb)); /* XXX */
4f083fd7 205 (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */
5e35cca3 206 return (0); /* XXX */
92a533e6
BJ
207}
208
98422daa 209soaccept(so, nam)
2b4b57cd 210 struct socket *so;
cf012934 211 struct mbuf *nam;
2b4b57cd
BJ
212{
213 int s = splnet();
214 int error;
215
26225f25
SL
216 if ((so->so_state & SS_NOFDREF) == 0)
217 panic("soaccept: !NOFDREF");
98422daa 218 so->so_state &= ~SS_NOFDREF;
cf012934 219 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT,
98422daa 220 (struct mbuf *)0, nam);
2b4b57cd
BJ
221 splx(s);
222 return (error);
223}
224
98422daa 225soconnect(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|SS_ISCONNECTING)) {
233 error = EISCONN;
234 goto bad;
235 }
cf012934 236 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
98422daa 237 (struct mbuf *)0, nam);
cc15ab5d
BJ
238bad:
239 splx(s);
240 return (error);
ce9d8eb4
BJ
241}
242
cf012934 243sodisconnect(so, nam)
ce9d8eb4 244 struct socket *so;
cf012934 245 struct mbuf *nam;
ce9d8eb4 246{
cc15ab5d
BJ
247 int s = splnet();
248 int error;
ce9d8eb4 249
cc15ab5d
BJ
250 if ((so->so_state & SS_ISCONNECTED) == 0) {
251 error = ENOTCONN;
252 goto bad;
ce9d8eb4 253 }
cc15ab5d
BJ
254 if (so->so_state & SS_ISDISCONNECTING) {
255 error = EALREADY;
256 goto bad;
ce9d8eb4 257 }
cf012934 258 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT,
98422daa 259 (struct mbuf *)0, nam);
cc15ab5d
BJ
260bad:
261 splx(s);
262 return (error);
ce9d8eb4
BJ
263}
264
cc15ab5d
BJ
265/*
266 * Send on a socket.
267 * If send must go all at once and message is larger than
268 * send buffering, then hard error.
269 * Lock against other senders.
270 * If must go all at once and not enough room now, then
271 * inform user that this would block and do nothing.
272 */
970108c7 273sosend(so, nam, uio, flags)
ce9d8eb4 274 register struct socket *so;
cf012934 275 struct mbuf *nam;
5699bf69 276 struct uio *uio;
970108c7 277 int flags;
ce9d8eb4 278{
cc15ab5d
BJ
279 struct mbuf *top = 0;
280 register struct mbuf *m, **mp = &top;
5a1f132a 281 register int len;
98422daa 282 int error = 0, space, s, dontroute;
ce9d8eb4 283
5699bf69 284 if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat)
cc15ab5d 285 return (EMSGSIZE);
98422daa
SL
286 dontroute = (flags & SOF_DONTROUTE) &&
287 (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
BJ
315 error = (*so->so_proto->pr_usrreq)(so,
316 (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND,
98422daa
SL
317 top, (caddr_t)nam);
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 }
970108c7
BJ
331 if (flags & SOF_OOB)
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;
970108c7
BJ
376 if (flags & SOF_OOB)
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
970108c7 390soreceive(so, aname, uio, flags)
ce9d8eb4 391 register struct socket *so;
cf012934 392 struct mbuf **aname;
32a43ee2 393 struct uio *uio;
970108c7 394 int flags;
ce9d8eb4
BJ
395{
396 register struct mbuf *m, *n;
5a1f132a 397 int len;
970108c7
BJ
398 int eor, s, error = 0, moff, tomark;
399
400 if (flags & SOF_OOB) {
cce93e4b 401 m = m_get(M_WAIT, MT_DATA);
5fe6f9d1
SL
402 if (m == NULL)
403 return (ENOBUFS);
a8d3bf7f 404 error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB,
98422daa 405 m, (struct mbuf *)0);
a8d3bf7f 406 if (error)
5fe6f9d1 407 goto bad;
970108c7 408 do {
5fe6f9d1 409 len = uio->uio_resid;
970108c7
BJ
410 if (len > m->m_len)
411 len = m->m_len;
a8d3bf7f 412 error =
a29f7995 413 uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio);
970108c7 414 m = m_free(m);
a8d3bf7f 415 } while (uio->uio_resid && error == 0 && m);
5fe6f9d1 416bad:
970108c7 417 if (m)
39d536e6 418 m_freem(m);
a8d3bf7f 419 return (error);
970108c7 420 }
ce9d8eb4 421
cc15ab5d
BJ
422restart:
423 sblock(&so->so_rcv);
424 s = splnet();
425
426#define rcverr(errno) { error = errno; splx(s); goto release; }
ce9d8eb4 427 if (so->so_rcv.sb_cc == 0) {
4c078bb2
BJ
428 if (so->so_error) {
429 error = so->so_error;
430 so->so_error = 0;
431 splx(s);
432 goto release;
433 }
cc15ab5d
BJ
434 if (so->so_state & SS_CANTRCVMORE) {
435 splx(s);
436 goto release;
437 }
196d84fd
BJ
438 if ((so->so_state & SS_ISCONNECTED) == 0 &&
439 (so->so_proto->pr_flags & PR_CONNREQUIRED))
440 rcverr(ENOTCONN);
62364f0e 441 if (so->so_state & SS_NBIO)
4c078bb2 442 rcverr(EWOULDBLOCK);
cc15ab5d 443 sbunlock(&so->so_rcv);
2752c877 444 sbwait(&so->so_rcv);
a4f6d93d 445 splx(s);
cc15ab5d 446 goto restart;
ce9d8eb4 447 }
c7256358 448 u.u_ru.ru_msgrcv++;
92a533e6 449 m = so->so_rcv.sb_mb;
ce9d8eb4
BJ
450 if (m == 0)
451 panic("receive");
b031e888 452 if (so->so_proto->pr_flags & PR_ADDR) {
970108c7
BJ
453 if ((flags & SOF_PREVIEW) == 0) {
454 so->so_rcv.sb_cc -= m->m_len;
455 so->so_rcv.sb_mbcnt -= MSIZE;
456 }
cf012934 457 if (aname) {
5fe6f9d1 458 if (flags & SOF_PREVIEW) {
970108c7 459 *aname = m_copy(m, 0, m->m_len);
5fe6f9d1
SL
460 if (*aname == NULL)
461 panic("receive 2");
462 } else
970108c7 463 *aname = m;
cf012934
BJ
464 m = m->m_next;
465 (*aname)->m_next = 0;
466 } else
970108c7
BJ
467 if (flags & SOF_PREVIEW)
468 m = m->m_next;
469 else
470 m = m_free(m);
cc15ab5d 471 if (m == 0)
5fe6f9d1 472 panic("receive 3");
e435773e
BJ
473 if ((flags & SOF_PREVIEW) == 0)
474 so->so_rcv.sb_mb = m;
cc15ab5d 475 }
ce9d8eb4 476 eor = 0;
970108c7
BJ
477 moff = 0;
478 tomark = so->so_oobmark;
ce9d8eb4 479 do {
5699bf69 480 if (uio->uio_resid <= 0)
32a43ee2 481 break;
5699bf69 482 len = uio->uio_resid;
32a43ee2 483 so->so_state &= ~SS_RCVATMARK;
970108c7
BJ
484 if (tomark && len > tomark)
485 len = tomark;
e435773e 486 if (moff+len > m->m_len - moff)
970108c7 487 len = m->m_len - moff;
ce9d8eb4 488 splx(s);
a8d3bf7f 489 error =
a29f7995 490 uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio);
ce9d8eb4
BJ
491 s = splnet();
492 if (len == m->m_len) {
e495e1cc 493 eor = (int)m->m_act;
970108c7
BJ
494 if (flags & SOF_PREVIEW)
495 m = m->m_next;
496 else {
497 sbfree(&so->so_rcv, m);
498 MFREE(m, n);
499 m = n;
e435773e 500 so->so_rcv.sb_mb = m;
970108c7
BJ
501 }
502 moff = 0;
ce9d8eb4 503 } else {
970108c7
BJ
504 if (flags & SOF_PREVIEW)
505 moff += len;
506 else {
507 m->m_off += len;
508 m->m_len -= len;
509 so->so_rcv.sb_cc -= len;
510 }
ce9d8eb4 511 }
970108c7 512 if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) {
32a43ee2
BJ
513 so->so_oobmark -= len;
514 if (so->so_oobmark == 0) {
515 so->so_state |= SS_RCVATMARK;
516 break;
517 }
518 }
970108c7
BJ
519 if (tomark) {
520 tomark -= len;
521 if (tomark == 0)
522 break;
523 }
a8d3bf7f 524 } while (m && error == 0 && !eor);
970108c7
BJ
525 if (flags & SOF_PREVIEW)
526 goto release;
ce9d8eb4
BJ
527 if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0)
528 do {
ce9d8eb4 529 if (m == 0)
5fe6f9d1 530 panic("receive 4");
cc15ab5d 531 sbfree(&so->so_rcv, m);
ce9d8eb4
BJ
532 eor = (int)m->m_act;
533 so->so_rcv.sb_mb = m->m_next;
534 MFREE(m, n);
cc15ab5d 535 m = n;
ce9d8eb4 536 } while (eor == 0);
cc15ab5d 537 if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb)
cf012934 538 (*so->so_proto->pr_usrreq)(so, PRU_RCVD,
98422daa 539 (struct mbuf *)0, (struct mbuf *)0);
cc15ab5d 540release:
ae921915 541 sbunlock(&so->so_rcv);
cc15ab5d 542 splx(s);
ae921915 543 return (error);
92a533e6
BJ
544}
545
98422daa
SL
546soshutdown(so, how)
547 struct socket *so;
548 int how;
549{
550
551 how++;
552 if (how & FREAD) {
553 int s = splimp();
554 socantrcvmore(so);
555 sbflush(&so->so_rcv);
556 splx(s);
557 }
558 if (how & FWRITE)
559 return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN,
560 (struct mbuf *)0, (struct mbuf *)0));
561 return (0);
562}
563
564sosetopt(so, level, optname, m)
565 struct socket *so;
566 int level, optname;
567 struct mbuf *m;
568{
98422daa
SL
569
570 if (level != SOL_SOCKET)
571 return (EINVAL); /* XXX */
98422daa
SL
572 switch (optname) {
573
574 case SO_DEBUG:
d2cba8de 575 case SO_KEEPALIVE:
b4a3d4a7
SL
576 case SO_DONTROUTE:
577 case SO_USELOOPBACK:
578 case SO_REUSEADDR:
579 so->so_options |= optname;
d2cba8de
SL
580 break;
581
98422daa 582 case SO_LINGER:
d2cba8de
SL
583 if (m == NULL || m->m_len != sizeof (int))
584 return (EINVAL);
98422daa 585 so->so_options |= SO_LINGER;
d2cba8de 586 so->so_linger = *mtod(m, int *);
98422daa
SL
587 break;
588
589 case SO_DONTLINGER:
590 so->so_options &= ~SO_LINGER;
591 so->so_linger = 0;
592 break;
593
98422daa
SL
594 default:
595 return (EINVAL);
596 }
597 return (0);
598}
599
600sogetopt(so, level, optname, m)
601 struct socket *so;
602 int level, optname;
603 struct mbuf *m;
604{
98422daa
SL
605
606 if (level != SOL_SOCKET)
607 return (EINVAL); /* XXX */
608 switch (optname) {
609
610 case SO_USELOOPBACK:
611 case SO_DONTROUTE:
612 case SO_DEBUG:
613 case SO_KEEPALIVE:
614 case SO_LINGER:
b4a3d4a7 615 case SO_REUSEADDR:
98422daa
SL
616 if ((so->so_options & optname) == 0)
617 return (ENOPROTOOPT);
d2cba8de 618 if (optname == SO_LINGER && m != NULL) {
98422daa
SL
619 *mtod(m, int *) = so->so_linger;
620 m->m_len = sizeof (so->so_linger);
621 }
622 break;
623
624 default:
625 return (EINVAL);
626 }
627 return (0);
628}
629
edebca28
BJ
630sohasoutofband(so)
631 struct socket *so;
632{
633
634 if (so->so_pgrp == 0)
635 return;
636 if (so->so_pgrp > 0)
637 gsignal(so->so_pgrp, SIGURG);
0a0f7cbb
BJ
638 else {
639 struct proc *p = pfind(-so->so_pgrp);
640
641 if (p)
642 psignal(p, SIGURG);
643 }
edebca28
BJ
644}
645
ae921915 646/*ARGSUSED*/
4b72e2f9 647soioctl(so, cmd, data)
92a533e6
BJ
648 register struct socket *so;
649 int cmd;
4b72e2f9 650 register char *data;
92a533e6
BJ
651{
652
2156d53c 653 switch (cmd) {
92a533e6 654
4b72e2f9
SL
655 case FIONBIO:
656 if (*(int *)data)
62364f0e 657 so->so_state |= SS_NBIO;
30b84e26 658 else
62364f0e 659 so->so_state &= ~SS_NBIO;
a8d3bf7f 660 break;
30b84e26 661
4b72e2f9
SL
662 case FIOASYNC:
663 if (*(int *)data)
62364f0e 664 so->so_state |= SS_ASYNC;
30b84e26 665 else
62364f0e 666 so->so_state &= ~SS_ASYNC;
a8d3bf7f 667 break;
30b84e26 668
4b72e2f9
SL
669 case SIOCSPGRP:
670 so->so_pgrp = *(int *)data;
a8d3bf7f 671 break;
4b72e2f9
SL
672
673 case SIOCGPGRP:
674 *(int *)data = so->so_pgrp;
a8d3bf7f 675 break;
30b84e26 676
4b72e2f9
SL
677 case SIOCATMARK:
678 *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
a8d3bf7f 679 break;
2a4251c4
SL
680
681 /* routing table update calls */
682 case SIOCADDRT:
683 case SIOCDELRT:
2a4251c4 684 if (!suser())
5fe6f9d1 685 return (u.u_error);
47b7bdd9 686 return (rtrequest(cmd, (struct rtentry *)data));
2a4251c4 687
22f36762
SL
688 /* interface parameter requests */
689 case SIOCSIFADDR:
690 case SIOCSIFFLAGS:
9841d167 691 case SIOCSIFDSTADDR:
22f36762
SL
692 if (!suser())
693 return (u.u_error);
694 return (ifrequest(cmd, data));
695
696 case SIOCGIFADDR:
697 case SIOCGIFFLAGS:
9841d167 698 case SIOCGIFDSTADDR:
22f36762
SL
699 return (ifrequest(cmd, data));
700
701 case SIOCGIFCONF:
702 return (ifconf(cmd, data));
703
5e1eeba0 704 /* type/protocol specific ioctls */
a8d3bf7f 705 default:
5fe6f9d1 706 return (ENOTTY); /* XXX */
92a533e6 707 }
a8d3bf7f 708 return (0);
ce9d8eb4 709}