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