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