Commit | Line | Data |
---|---|---|
e435773e | 1 | /* uipc_socket.c 4.53 82/10/16 */ |
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 | |
cf012934 | 28 | socreate(dom, aso, type, proto, opt) |
ce9d8eb4 | 29 | struct socket **aso; |
cf012934 BJ |
30 | int type, proto; |
31 | struct socketopt *opt; | |
ce9d8eb4 BJ |
32 | { |
33 | register struct protosw *prp; | |
34 | register struct socket *so; | |
35 | struct mbuf *m; | |
cf012934 | 36 | int pf, error; |
cc15ab5d | 37 | |
cf012934 | 38 | pf = dom ? PF_UNIX : PF_INET; /* should be u.u_protof */ |
cc15ab5d BJ |
39 | if (proto) |
40 | prp = pffindproto(pf, proto); | |
41 | else | |
42 | prp = pffindtype(pf, type); | |
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 BJ |
52 | so->so_state = 0; |
53 | if (u.u_uid == 0) | |
54 | so->so_state = SS_PRIV; | |
ce9d8eb4 | 55 | so->so_proto = prp; |
cf012934 BJ |
56 | error = (*prp->pr_usrreq)(so, PRU_ATTACH, |
57 | (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)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 | ||
cf012934 BJ |
67 | sobind(so, nam, opt) |
68 | struct socket *so; | |
69 | struct mbuf *nam; | |
70 | struct socketopt *opt; | |
71 | { | |
72 | int s = splnet(); | |
73 | int error; | |
74 | ||
75 | error = | |
76 | (*so->so_proto->pr_usrreq)(so, PRU_BIND, | |
77 | (struct mbuf *)0, nam, opt); | |
78 | splx(s); | |
79 | return (error); | |
80 | } | |
81 | ||
82 | solisten(so, backlog) | |
83 | struct socket *so; | |
84 | int backlog; | |
85 | { | |
86 | int s = splnet(); | |
87 | int error; | |
88 | ||
89 | error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, | |
90 | (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); | |
91 | if (error) { | |
92 | splx(s); | |
93 | return (error); | |
94 | } | |
95 | if (so->so_q == 0) { | |
96 | so->so_q = so; | |
97 | so->so_q0 = so; | |
98 | so->so_options |= SO_ACCEPTCONN; | |
99 | } | |
100 | if (backlog < 0) | |
101 | backlog = 0; | |
102 | so->so_qlimit = backlog < 5 ? backlog : 5; | |
103 | so->so_options |= SO_NEWFDONCONN; | |
104 | return (0); | |
105 | } | |
106 | ||
ae921915 BJ |
107 | sofree(so) |
108 | struct socket *so; | |
109 | { | |
110 | ||
90aaea96 BJ |
111 | if (so->so_head) { |
112 | if (!soqremque(so, 0) && !soqremque(so, 1)) | |
113 | panic("sofree dq"); | |
114 | so->so_head = 0; | |
115 | } | |
116 | if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) | |
4ad99bae BJ |
117 | return; |
118 | sbrelease(&so->so_snd); | |
119 | sbrelease(&so->so_rcv); | |
2752c877 | 120 | (void) m_free(dtom(so)); |
ae921915 BJ |
121 | } |
122 | ||
92a533e6 | 123 | /* |
cc15ab5d BJ |
124 | * Close a socket on last file table reference removal. |
125 | * Initiate disconnect if connected. | |
126 | * Free socket when disconnect complete. | |
92a533e6 | 127 | */ |
89900a09 | 128 | soclose(so, exiting) |
92a533e6 | 129 | register struct socket *so; |
89900a09 | 130 | int exiting; |
92a533e6 | 131 | { |
cc15ab5d BJ |
132 | int s = splnet(); /* conservative */ |
133 | ||
90aaea96 BJ |
134 | if (so->so_options & SO_ACCEPTCONN) { |
135 | while (so->so_q0 != so) | |
136 | soclose(so->so_q0, 1); | |
137 | while (so->so_q != so) | |
138 | soclose(so->so_q, 1); | |
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) { | |
2b4b57cd | 146 | u.u_error = sodisconnect(so, (struct sockaddr *)0); |
cc15ab5d | 147 | if (u.u_error) { |
89900a09 BJ |
148 | if (exiting) |
149 | goto drop; | |
cc15ab5d BJ |
150 | splx(s); |
151 | return; | |
152 | } | |
153 | } | |
30b84e26 | 154 | if ((so->so_options & SO_DONTLINGER) == 0) { |
b8acc34d | 155 | if ((so->so_state & SS_ISDISCONNECTING) && |
62364f0e | 156 | (so->so_state & SS_NBIO) && |
89900a09 | 157 | exiting == 0) { |
b8acc34d BJ |
158 | u.u_error = EINPROGRESS; |
159 | splx(s); | |
160 | return; | |
161 | } | |
89900a09 | 162 | /* should use tsleep here, for at most linger */ |
b8acc34d BJ |
163 | while (so->so_state & SS_ISCONNECTED) |
164 | sleep((caddr_t)&so->so_timeo, PZERO+1); | |
72857acf | 165 | } |
cc15ab5d | 166 | } |
89900a09 | 167 | drop: |
37c0974a | 168 | if (so->so_pcb) { |
cf012934 BJ |
169 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, |
170 | (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); | |
37c0974a SL |
171 | if (exiting == 0 && u.u_error) { |
172 | splx(s); | |
173 | return; | |
174 | } | |
175 | } | |
cc15ab5d | 176 | discard: |
90aaea96 | 177 | so->so_state |= SS_NOFDREF; |
4ad99bae | 178 | sofree(so); |
cc15ab5d | 179 | splx(s); |
92a533e6 BJ |
180 | } |
181 | ||
ae921915 | 182 | /*ARGSUSED*/ |
cc15ab5d | 183 | sostat(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 | 192 | soaccept(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 | 206 | soconnect(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 |
220 | bad: |
221 | splx(s); | |
222 | return (error); | |
ce9d8eb4 BJ |
223 | } |
224 | ||
cf012934 | 225 | sodisconnect(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 |
242 | bad: |
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 | 255 | sosend(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 = ⊤ | |
ae921915 BJ |
263 | register u_int len; |
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 | 268 | restart: |
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 | 273 | again: |
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 = ⊤ |
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 | 344 | nopages: |
5699bf69 | 345 | len = MIN(MLEN, iov->iov_len); |
ce9d8eb4 | 346 | } |
5699bf69 | 347 | 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 | 358 | release: |
cc15ab5d | 359 | sbunlock(&so->so_snd); |
0f90f987 BJ |
360 | if (top) |
361 | m_freem(top); | |
ce9d8eb4 BJ |
362 | return (error); |
363 | } | |
364 | ||
970108c7 | 365 | soreceive(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 | 370 | { |
32a43ee2 | 371 | register struct iovec *iov; |
ce9d8eb4 | 372 | register struct mbuf *m, *n; |
ae921915 | 373 | u_int len; |
970108c7 BJ |
374 | int eor, s, error = 0, moff, tomark; |
375 | ||
376 | if (flags & SOF_OOB) { | |
377 | struct mbuf *m = m_get(M_WAIT); | |
378 | ||
379 | (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, | |
380 | m, (struct mbuf *)0, (struct socketopt *)0); | |
381 | len = uio->uio_resid; | |
382 | do { | |
383 | if (len > m->m_len) | |
384 | len = m->m_len; | |
385 | uiomove(mtod(m, caddr_t), (int)len, UIO_READ, uio); | |
386 | m = m_free(m); | |
387 | } while (uio->uio_resid && u.u_error == 0 && m); | |
388 | if (m) | |
389 | (void) m_freem(m); | |
390 | return; | |
391 | } | |
ce9d8eb4 | 392 | |
cc15ab5d BJ |
393 | restart: |
394 | sblock(&so->so_rcv); | |
e435773e | 395 | SBCHECK(&so->so_snd, "soreceive restart"); |
cc15ab5d BJ |
396 | s = splnet(); |
397 | ||
398 | #define rcverr(errno) { error = errno; splx(s); goto release; } | |
ce9d8eb4 | 399 | if (so->so_rcv.sb_cc == 0) { |
4c078bb2 BJ |
400 | if (so->so_error) { |
401 | error = so->so_error; | |
402 | so->so_error = 0; | |
403 | splx(s); | |
404 | goto release; | |
405 | } | |
cc15ab5d BJ |
406 | if (so->so_state & SS_CANTRCVMORE) { |
407 | splx(s); | |
408 | goto release; | |
409 | } | |
196d84fd BJ |
410 | if ((so->so_state & SS_ISCONNECTED) == 0 && |
411 | (so->so_proto->pr_flags & PR_CONNREQUIRED)) | |
412 | rcverr(ENOTCONN); | |
62364f0e | 413 | if (so->so_state & SS_NBIO) |
4c078bb2 | 414 | rcverr(EWOULDBLOCK); |
cc15ab5d | 415 | sbunlock(&so->so_rcv); |
2752c877 | 416 | sbwait(&so->so_rcv); |
a4f6d93d | 417 | splx(s); |
cc15ab5d | 418 | goto restart; |
ce9d8eb4 | 419 | } |
c7256358 | 420 | u.u_ru.ru_msgrcv++; |
92a533e6 | 421 | m = so->so_rcv.sb_mb; |
ce9d8eb4 BJ |
422 | if (m == 0) |
423 | panic("receive"); | |
e435773e | 424 | SBCHECK(&so->so_snd, "soreceive havecc"); |
b031e888 | 425 | if (so->so_proto->pr_flags & PR_ADDR) { |
970108c7 BJ |
426 | if ((flags & SOF_PREVIEW) == 0) { |
427 | so->so_rcv.sb_cc -= m->m_len; | |
428 | so->so_rcv.sb_mbcnt -= MSIZE; | |
429 | } | |
cf012934 | 430 | if (aname) { |
970108c7 BJ |
431 | if (flags & SOF_PREVIEW) |
432 | *aname = m_copy(m, 0, m->m_len); | |
433 | else | |
434 | *aname = m; | |
cf012934 BJ |
435 | m = m->m_next; |
436 | (*aname)->m_next = 0; | |
437 | } else | |
970108c7 BJ |
438 | if (flags & SOF_PREVIEW) |
439 | m = m->m_next; | |
440 | else | |
441 | m = m_free(m); | |
cc15ab5d BJ |
442 | if (m == 0) |
443 | panic("receive 2"); | |
e435773e BJ |
444 | if ((flags & SOF_PREVIEW) == 0) |
445 | so->so_rcv.sb_mb = m; | |
446 | SBCHECK(&so->so_snd, "soreceive afteraddr"); | |
cc15ab5d | 447 | } |
ce9d8eb4 | 448 | eor = 0; |
970108c7 BJ |
449 | moff = 0; |
450 | tomark = so->so_oobmark; | |
ce9d8eb4 | 451 | do { |
5699bf69 | 452 | if (uio->uio_resid <= 0) |
32a43ee2 | 453 | break; |
5699bf69 | 454 | len = uio->uio_resid; |
32a43ee2 | 455 | so->so_state &= ~SS_RCVATMARK; |
970108c7 BJ |
456 | if (tomark && len > tomark) |
457 | len = tomark; | |
e435773e | 458 | if (moff+len > m->m_len - moff) |
970108c7 | 459 | len = m->m_len - moff; |
ce9d8eb4 | 460 | splx(s); |
970108c7 | 461 | uiomove(mtod(m, caddr_t) + moff, (int)len, UIO_READ, uio); |
ce9d8eb4 BJ |
462 | s = splnet(); |
463 | if (len == m->m_len) { | |
e495e1cc | 464 | eor = (int)m->m_act; |
970108c7 BJ |
465 | if (flags & SOF_PREVIEW) |
466 | m = m->m_next; | |
467 | else { | |
468 | sbfree(&so->so_rcv, m); | |
469 | MFREE(m, n); | |
470 | m = n; | |
e435773e | 471 | so->so_rcv.sb_mb = m; |
970108c7 BJ |
472 | } |
473 | moff = 0; | |
ce9d8eb4 | 474 | } else { |
970108c7 BJ |
475 | if (flags & SOF_PREVIEW) |
476 | moff += len; | |
477 | else { | |
478 | m->m_off += len; | |
479 | m->m_len -= len; | |
480 | so->so_rcv.sb_cc -= len; | |
481 | } | |
ce9d8eb4 | 482 | } |
970108c7 | 483 | if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { |
32a43ee2 BJ |
484 | so->so_oobmark -= len; |
485 | if (so->so_oobmark == 0) { | |
486 | so->so_state |= SS_RCVATMARK; | |
487 | break; | |
488 | } | |
489 | } | |
970108c7 BJ |
490 | if (tomark) { |
491 | tomark -= len; | |
492 | if (tomark == 0) | |
493 | break; | |
494 | } | |
e435773e | 495 | SBCHECK(&so->so_snd, "soreceive rcvloop"); |
970108c7 BJ |
496 | } while (m && !eor); |
497 | if (flags & SOF_PREVIEW) | |
498 | goto release; | |
ce9d8eb4 BJ |
499 | if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) |
500 | do { | |
ce9d8eb4 | 501 | if (m == 0) |
cc15ab5d BJ |
502 | panic("receive 3"); |
503 | sbfree(&so->so_rcv, m); | |
ce9d8eb4 BJ |
504 | eor = (int)m->m_act; |
505 | so->so_rcv.sb_mb = m->m_next; | |
506 | MFREE(m, n); | |
cc15ab5d | 507 | m = n; |
e435773e | 508 | SBCHECK(&so->so_snd, "soreceive atomicloop"); |
ce9d8eb4 | 509 | } while (eor == 0); |
cc15ab5d | 510 | if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) |
cf012934 BJ |
511 | (*so->so_proto->pr_usrreq)(so, PRU_RCVD, |
512 | (struct mbuf *)0, (struct mbuf *)0, (struct socketopt *)0); | |
cc15ab5d | 513 | release: |
ae921915 | 514 | sbunlock(&so->so_rcv); |
cc15ab5d | 515 | splx(s); |
ae921915 | 516 | return (error); |
92a533e6 BJ |
517 | } |
518 | ||
edebca28 BJ |
519 | sohasoutofband(so) |
520 | struct socket *so; | |
521 | { | |
522 | ||
523 | if (so->so_pgrp == 0) | |
524 | return; | |
525 | if (so->so_pgrp > 0) | |
526 | gsignal(so->so_pgrp, SIGURG); | |
0a0f7cbb BJ |
527 | else { |
528 | struct proc *p = pfind(-so->so_pgrp); | |
529 | ||
530 | if (p) | |
531 | psignal(p, SIGURG); | |
532 | } | |
edebca28 BJ |
533 | } |
534 | ||
ae921915 | 535 | /*ARGSUSED*/ |
4b72e2f9 | 536 | soioctl(so, cmd, data) |
92a533e6 BJ |
537 | register struct socket *so; |
538 | int cmd; | |
4b72e2f9 | 539 | register char *data; |
92a533e6 BJ |
540 | { |
541 | ||
2156d53c | 542 | switch (cmd) { |
92a533e6 | 543 | |
4b72e2f9 SL |
544 | case FIONBIO: |
545 | if (*(int *)data) | |
62364f0e | 546 | so->so_state |= SS_NBIO; |
30b84e26 | 547 | else |
62364f0e | 548 | so->so_state &= ~SS_NBIO; |
30b84e26 | 549 | return; |
30b84e26 | 550 | |
4b72e2f9 SL |
551 | case FIOASYNC: |
552 | if (*(int *)data) | |
62364f0e | 553 | so->so_state |= SS_ASYNC; |
30b84e26 | 554 | else |
62364f0e | 555 | so->so_state &= ~SS_ASYNC; |
30b84e26 | 556 | return; |
30b84e26 | 557 | |
4b72e2f9 SL |
558 | case SIOCSKEEP: |
559 | if (*(int *)data) | |
9d2f171f | 560 | so->so_options &= ~SO_KEEPALIVE; |
90aaea96 BJ |
561 | else |
562 | so->so_options |= SO_KEEPALIVE; | |
30b84e26 | 563 | return; |
30b84e26 | 564 | |
4b72e2f9 SL |
565 | case SIOCGKEEP: |
566 | *(int *)data = (so->so_options & SO_KEEPALIVE) != 0; | |
30b84e26 | 567 | return; |
30b84e26 | 568 | |
4b72e2f9 SL |
569 | case SIOCSLINGER: |
570 | so->so_linger = *(int *)data; | |
30b84e26 BJ |
571 | if (so->so_linger) |
572 | so->so_options &= ~SO_DONTLINGER; | |
573 | else | |
574 | so->so_options |= SO_DONTLINGER; | |
575 | return; | |
30b84e26 | 576 | |
4b72e2f9 SL |
577 | case SIOCGLINGER: |
578 | *(int *)data = so->so_linger; | |
edebca28 | 579 | return; |
edebca28 | 580 | |
4b72e2f9 SL |
581 | case SIOCSPGRP: |
582 | so->so_pgrp = *(int *)data; | |
583 | return; | |
584 | ||
585 | case SIOCGPGRP: | |
586 | *(int *)data = so->so_pgrp; | |
587 | return; | |
30b84e26 | 588 | |
b8acc34d | 589 | case SIOCDONE: { |
4b72e2f9 SL |
590 | int flags = *(int *)data; |
591 | ||
30b84e26 | 592 | flags++; |
b8acc34d BJ |
593 | if (flags & FREAD) { |
594 | int s = splimp(); | |
595 | socantrcvmore(so); | |
596 | sbflush(&so->so_rcv); | |
785e10b7 | 597 | splx(s); |
b8acc34d BJ |
598 | } |
599 | if (flags & FWRITE) | |
cf012934 BJ |
600 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, |
601 | (struct mbuf *)0, (struct mbuf *)0, | |
602 | (struct socketopt *)0); | |
b8acc34d BJ |
603 | return; |
604 | } | |
605 | ||
edebca28 | 606 | case SIOCSENDOOB: { |
4b72e2f9 | 607 | char oob = *(char *)data; |
970108c7 | 608 | struct mbuf *m = m_get(M_DONTWAIT); |
4b72e2f9 | 609 | |
edebca28 BJ |
610 | if (m == 0) { |
611 | u.u_error = ENOBUFS; | |
612 | return; | |
613 | } | |
970108c7 | 614 | m->m_len = 1; |
4b72e2f9 | 615 | *mtod(m, char *) = oob; |
cf012934 BJ |
616 | (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, |
617 | m, (struct mbuf *)0, (struct socketopt *)0); | |
edebca28 BJ |
618 | return; |
619 | } | |
620 | ||
621 | case SIOCRCVOOB: { | |
970108c7 | 622 | struct mbuf *m = m_get(M_WAIT); |
4b72e2f9 | 623 | |
edebca28 BJ |
624 | if (m == 0) { |
625 | u.u_error = ENOBUFS; | |
626 | return; | |
627 | } | |
970108c7 | 628 | *mtod(m, caddr_t) = 0; |
cf012934 BJ |
629 | (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, |
630 | m, (struct mbuf *)0, (struct socketopt *)0); | |
4b72e2f9 SL |
631 | *(char *)data = *mtod(m, char *); |
632 | (void) m_free(m); | |
edebca28 BJ |
633 | return; |
634 | } | |
635 | ||
4b72e2f9 SL |
636 | case SIOCATMARK: |
637 | *(int *)data = (so->so_state&SS_RCVATMARK) != 0; | |
edebca28 | 638 | return; |
2a4251c4 SL |
639 | |
640 | /* routing table update calls */ | |
641 | case SIOCADDRT: | |
642 | case SIOCDELRT: | |
2a4251c4 SL |
643 | if (!suser()) |
644 | return; | |
4b72e2f9 | 645 | u.u_error = rtrequest(cmd, (struct rtentry *)data); |
2a4251c4 | 646 | return; |
2a4251c4 | 647 | |
5e1eeba0 | 648 | /* type/protocol specific ioctls */ |
92a533e6 | 649 | } |
5e1eeba0 | 650 | u.u_error = EOPNOTSUPP; |
ce9d8eb4 | 651 | } |