Commit | Line | Data |
---|---|---|
0a0f7cbb | 1 | /* uipc_socket.c 4.26 82/01/17 */ |
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" |
c5ff2e32 BJ |
17 | #include "../net/in.h" |
18 | #include "../net/in_systm.h" | |
ce9d8eb4 | 19 | |
ce9d8eb4 | 20 | /* |
cc15ab5d BJ |
21 | * Socket support routines. |
22 | * | |
23 | * DEAL WITH INTERRUPT NOTIFICATION. | |
ce9d8eb4 | 24 | */ |
ce9d8eb4 BJ |
25 | |
26 | /* | |
27 | * Create a socket. | |
28 | */ | |
2b4b57cd | 29 | socreate(aso, type, asp, asa, options) |
ce9d8eb4 BJ |
30 | struct socket **aso; |
31 | int type; | |
2b4b57cd BJ |
32 | struct sockproto *asp; |
33 | struct sockaddr *asa; | |
92a533e6 | 34 | int options; |
ce9d8eb4 BJ |
35 | { |
36 | register struct protosw *prp; | |
37 | register struct socket *so; | |
38 | struct mbuf *m; | |
cc15ab5d | 39 | int pf, proto, error; |
2b4b57cd | 40 | COUNT(SOCREATE); |
ce9d8eb4 BJ |
41 | |
42 | /* | |
cc15ab5d BJ |
43 | * Use process standard protocol/protocol family if none |
44 | * specified by address argument. | |
ce9d8eb4 | 45 | */ |
2b4b57cd | 46 | if (asp == 0) { |
cc15ab5d | 47 | pf = PF_INET; /* should be u.u_protof */ |
ce9d8eb4 BJ |
48 | proto = 0; |
49 | } else { | |
2b4b57cd BJ |
50 | pf = asp->sp_family; |
51 | proto = asp->sp_protocol; | |
ce9d8eb4 | 52 | } |
cc15ab5d BJ |
53 | |
54 | /* | |
55 | * If protocol specified, look for it, otherwise | |
56 | * for a protocol of the correct type in the right family. | |
57 | */ | |
58 | if (proto) | |
59 | prp = pffindproto(pf, proto); | |
60 | else | |
61 | prp = pffindtype(pf, type); | |
62 | if (prp == 0) | |
63 | return (EPROTONOSUPPORT); | |
ce9d8eb4 BJ |
64 | |
65 | /* | |
66 | * Get a socket structure. | |
67 | */ | |
cc15ab5d | 68 | m = m_getclr(M_WAIT); |
ce9d8eb4 BJ |
69 | if (m == 0) |
70 | return (ENOBUFS); | |
ce9d8eb4 | 71 | so = mtod(m, struct socket *); |
92a533e6 | 72 | so->so_options = options; |
ce9d8eb4 BJ |
73 | |
74 | /* | |
cc15ab5d BJ |
75 | * Attach protocol to socket, initializing |
76 | * and reserving resources. | |
ce9d8eb4 BJ |
77 | */ |
78 | so->so_proto = prp; | |
b91acce4 BJ |
79 | error = (*prp->pr_usrreq)(so, PRU_ATTACH, 0, asa); |
80 | if (error) { | |
2752c877 | 81 | (void) m_free(dtom(so)); |
cc15ab5d | 82 | return (error); |
ce9d8eb4 BJ |
83 | } |
84 | *aso = so; | |
85 | return (0); | |
86 | } | |
87 | ||
ae921915 BJ |
88 | sofree(so) |
89 | struct socket *so; | |
90 | { | |
91 | ||
2b4b57cd | 92 | COUNT(SOFREE); |
4ad99bae BJ |
93 | if (so->so_pcb || (so->so_state & SS_USERGONE) == 0) |
94 | return; | |
95 | sbrelease(&so->so_snd); | |
96 | sbrelease(&so->so_rcv); | |
2752c877 | 97 | (void) m_free(dtom(so)); |
ae921915 BJ |
98 | } |
99 | ||
92a533e6 | 100 | /* |
cc15ab5d BJ |
101 | * Close a socket on last file table reference removal. |
102 | * Initiate disconnect if connected. | |
103 | * Free socket when disconnect complete. | |
92a533e6 | 104 | */ |
cc15ab5d | 105 | soclose(so) |
92a533e6 | 106 | register struct socket *so; |
92a533e6 | 107 | { |
cc15ab5d BJ |
108 | int s = splnet(); /* conservative */ |
109 | ||
2b4b57cd | 110 | COUNT(SOCLOSE); |
cc15ab5d BJ |
111 | if (so->so_pcb == 0) |
112 | goto discard; | |
113 | if (so->so_state & SS_ISCONNECTED) { | |
114 | if ((so->so_state & SS_ISDISCONNECTING) == 0) { | |
2b4b57cd | 115 | u.u_error = sodisconnect(so, (struct sockaddr *)0); |
cc15ab5d BJ |
116 | if (u.u_error) { |
117 | splx(s); | |
118 | return; | |
119 | } | |
120 | } | |
30b84e26 | 121 | if ((so->so_options & SO_DONTLINGER) == 0) { |
b8acc34d | 122 | if ((so->so_state & SS_ISDISCONNECTING) && |
30b84e26 | 123 | (so->so_options & SO_NONBLOCKING)) { |
b8acc34d BJ |
124 | u.u_error = EINPROGRESS; |
125 | splx(s); | |
126 | return; | |
127 | } | |
30b84e26 | 128 | /* should use tsleep here */ |
b8acc34d BJ |
129 | while (so->so_state & SS_ISCONNECTED) |
130 | sleep((caddr_t)&so->so_timeo, PZERO+1); | |
72857acf | 131 | } |
cc15ab5d BJ |
132 | } |
133 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, 0, 0); | |
134 | discard: | |
4ad99bae BJ |
135 | so->so_state |= SS_USERGONE; |
136 | sofree(so); | |
cc15ab5d | 137 | splx(s); |
92a533e6 BJ |
138 | } |
139 | ||
2b4b57cd BJ |
140 | sosplice(pso, so) |
141 | struct socket *pso, *so; | |
142 | { | |
143 | ||
144 | COUNT(SOSPLICE); | |
4c078bb2 | 145 | if (pso->so_proto->pr_family != PF_UNIX) { |
2b4b57cd BJ |
146 | struct socket *tso; |
147 | tso = pso; pso = so; so = tso; | |
148 | } | |
4c078bb2 | 149 | if (pso->so_proto->pr_family != PF_UNIX) |
2b4b57cd BJ |
150 | return (EOPNOTSUPP); |
151 | /* check types and buffer space */ | |
152 | /* merge buffers */ | |
153 | return (0); | |
154 | } | |
155 | ||
ae921915 | 156 | /*ARGSUSED*/ |
cc15ab5d | 157 | sostat(so, sb) |
92a533e6 | 158 | struct socket *so; |
cc15ab5d | 159 | struct stat *sb; |
92a533e6 BJ |
160 | { |
161 | ||
2b4b57cd | 162 | COUNT(SOSTAT); |
5e35cca3 BJ |
163 | bzero((caddr_t)sb, sizeof (*sb)); /* XXX */ |
164 | return (0); /* XXX */ | |
92a533e6 BJ |
165 | } |
166 | ||
2b4b57cd BJ |
167 | /* |
168 | * Accept connection on a socket. | |
169 | */ | |
170 | soaccept(so, asa) | |
171 | struct socket *so; | |
172 | struct sockaddr *asa; | |
173 | { | |
174 | int s = splnet(); | |
175 | int error; | |
176 | ||
177 | COUNT(SOACCEPT); | |
2b4b57cd BJ |
178 | if ((so->so_options & SO_ACCEPTCONN) == 0) { |
179 | error = EINVAL; /* XXX */ | |
180 | goto bad; | |
181 | } | |
92d06f69 BJ |
182 | if ((so->so_state & SS_CONNAWAITING) == 0) { |
183 | error = ENOTCONN; | |
184 | goto bad; | |
185 | } | |
186 | so->so_state &= ~SS_CONNAWAITING; | |
2b4b57cd BJ |
187 | error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, 0, (caddr_t)asa); |
188 | bad: | |
189 | splx(s); | |
190 | return (error); | |
191 | } | |
192 | ||
ce9d8eb4 | 193 | /* |
cc15ab5d BJ |
194 | * Connect socket to a specified address. |
195 | * If already connected or connecting, then avoid | |
196 | * the protocol entry, to keep its job simpler. | |
ce9d8eb4 | 197 | */ |
2b4b57cd | 198 | soconnect(so, asa) |
ce9d8eb4 | 199 | struct socket *so; |
2b4b57cd | 200 | struct sockaddr *asa; |
ce9d8eb4 | 201 | { |
cc15ab5d BJ |
202 | int s = splnet(); |
203 | int error; | |
ce9d8eb4 | 204 | |
2b4b57cd | 205 | COUNT(SOCONNECT); |
cc15ab5d BJ |
206 | if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) { |
207 | error = EISCONN; | |
208 | goto bad; | |
209 | } | |
2b4b57cd | 210 | error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, 0, (caddr_t)asa); |
cc15ab5d BJ |
211 | bad: |
212 | splx(s); | |
213 | return (error); | |
ce9d8eb4 BJ |
214 | } |
215 | ||
216 | /* | |
cc15ab5d BJ |
217 | * Disconnect from a socket. |
218 | * Address parameter is from system call for later multicast | |
219 | * protocols. Check to make sure that connected and no disconnect | |
220 | * in progress (for protocol's sake), and then invoke protocol. | |
ce9d8eb4 | 221 | */ |
2b4b57cd | 222 | sodisconnect(so, asa) |
ce9d8eb4 | 223 | struct socket *so; |
2b4b57cd | 224 | struct sockaddr *asa; |
ce9d8eb4 | 225 | { |
cc15ab5d BJ |
226 | int s = splnet(); |
227 | int error; | |
ce9d8eb4 | 228 | |
2b4b57cd | 229 | COUNT(SODISCONNECT); |
cc15ab5d BJ |
230 | if ((so->so_state & SS_ISCONNECTED) == 0) { |
231 | error = ENOTCONN; | |
232 | goto bad; | |
ce9d8eb4 | 233 | } |
cc15ab5d BJ |
234 | if (so->so_state & SS_ISDISCONNECTING) { |
235 | error = EALREADY; | |
236 | goto bad; | |
ce9d8eb4 | 237 | } |
2b4b57cd | 238 | error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, 0, asa); |
cc15ab5d BJ |
239 | bad: |
240 | splx(s); | |
241 | return (error); | |
ce9d8eb4 BJ |
242 | } |
243 | ||
cc15ab5d BJ |
244 | /* |
245 | * Send on a socket. | |
246 | * If send must go all at once and message is larger than | |
247 | * send buffering, then hard error. | |
248 | * Lock against other senders. | |
249 | * If must go all at once and not enough room now, then | |
250 | * inform user that this would block and do nothing. | |
251 | */ | |
2b4b57cd | 252 | sosend(so, asa) |
ce9d8eb4 | 253 | register struct socket *so; |
2b4b57cd | 254 | struct sockaddr *asa; |
ce9d8eb4 | 255 | { |
cc15ab5d BJ |
256 | struct mbuf *top = 0; |
257 | register struct mbuf *m, **mp = ⊤ | |
ae921915 BJ |
258 | register u_int len; |
259 | int error = 0, space, s; | |
ce9d8eb4 | 260 | |
2b4b57cd | 261 | COUNT(SOSEND); |
cc15ab5d BJ |
262 | if (so->so_state & SS_CANTSENDMORE) |
263 | return (EPIPE); | |
264 | if (sosendallatonce(so) && u.u_count > so->so_snd.sb_hiwat) | |
265 | return (EMSGSIZE); | |
30b84e26 | 266 | if ((so->so_snd.sb_flags & SB_LOCK) && (so->so_options & SO_NONBLOCKING)) |
cc15ab5d BJ |
267 | return (EWOULDBLOCK); |
268 | sblock(&so->so_snd); | |
269 | #define snderr(errno) { error = errno; splx(s); goto release; } | |
270 | ||
271 | s = splnet(); | |
272 | again: | |
4c078bb2 BJ |
273 | if (so->so_error) { |
274 | error = so->so_error; | |
275 | so->so_error = 0; | |
276 | splx(s); | |
277 | goto release; | |
278 | } | |
cc15ab5d BJ |
279 | if ((so->so_state & SS_ISCONNECTED) == 0) { |
280 | if (so->so_proto->pr_flags & PR_CONNREQUIRED) | |
281 | snderr(ENOTCONN); | |
2b4b57cd | 282 | if (asa == 0) |
cc15ab5d BJ |
283 | snderr(EDESTADDRREQ); |
284 | } | |
cc15ab5d | 285 | if (top) { |
2b4b57cd | 286 | error = (*so->so_proto->pr_usrreq)(so, PRU_SEND, top, asa); |
cc15ab5d BJ |
287 | if (error) { |
288 | splx(s); | |
ce9d8eb4 BJ |
289 | goto release; |
290 | } | |
cc15ab5d BJ |
291 | top = 0; |
292 | mp = ⊤ | |
ce9d8eb4 | 293 | } |
b91acce4 BJ |
294 | if (u.u_count == 0) { |
295 | splx(s); | |
296 | goto release; | |
297 | } | |
50fc8df6 BJ |
298 | space = sbspace(&so->so_snd); |
299 | if (space == 0 || sosendallatonce(so) && space < u.u_count) { | |
30b84e26 | 300 | if (so->so_options & SO_NONBLOCKING) |
cc15ab5d BJ |
301 | snderr(EWOULDBLOCK); |
302 | sbunlock(&so->so_snd); | |
303 | sbwait(&so->so_snd); | |
304 | splx(s); | |
ce9d8eb4 BJ |
305 | goto again; |
306 | } | |
cc15ab5d | 307 | splx(s); |
50fc8df6 | 308 | while (u.u_count && space > 0) { |
cc15ab5d BJ |
309 | MGET(m, 1); |
310 | if (m == NULL) { | |
311 | error = ENOBUFS; | |
312 | m_freem(top); | |
313 | goto release; | |
ce9d8eb4 | 314 | } |
c5ff2e32 | 315 | if (u.u_count >= CLBYTES && space >= CLBYTES) { |
cc15ab5d | 316 | register struct mbuf *p; |
c5ff2e32 | 317 | MCLGET(p, 1); |
cc15ab5d BJ |
318 | if (p == 0) |
319 | goto nopages; | |
320 | m->m_off = (int)p - (int)m; | |
c5ff2e32 | 321 | len = CLBYTES; |
cc15ab5d | 322 | } else { |
ce9d8eb4 | 323 | nopages: |
cc15ab5d BJ |
324 | m->m_off = MMINOFF; |
325 | len = MIN(MLEN, u.u_count); | |
ce9d8eb4 | 326 | } |
cc15ab5d BJ |
327 | iomove(mtod(m, caddr_t), len, B_WRITE); |
328 | m->m_len = len; | |
329 | *mp = m; | |
330 | mp = &m->m_next; | |
50fc8df6 | 331 | space = sbspace(&so->so_snd); |
ce9d8eb4 | 332 | } |
cc15ab5d BJ |
333 | s = splnet(); |
334 | goto again; | |
335 | ||
ce9d8eb4 | 336 | release: |
cc15ab5d | 337 | sbunlock(&so->so_snd); |
ce9d8eb4 BJ |
338 | return (error); |
339 | } | |
340 | ||
2b4b57cd | 341 | soreceive(so, asa) |
ce9d8eb4 | 342 | register struct socket *so; |
2b4b57cd | 343 | struct sockaddr *asa; |
ce9d8eb4 BJ |
344 | { |
345 | register struct mbuf *m, *n; | |
ae921915 | 346 | u_int len; |
edebca28 BJ |
347 | int eor, s, error = 0, cnt = u.u_count; |
348 | caddr_t base = u.u_base; | |
ce9d8eb4 | 349 | |
2b4b57cd | 350 | COUNT(SORECEIVE); |
cc15ab5d BJ |
351 | restart: |
352 | sblock(&so->so_rcv); | |
353 | s = splnet(); | |
354 | ||
355 | #define rcverr(errno) { error = errno; splx(s); goto release; } | |
ce9d8eb4 | 356 | if (so->so_rcv.sb_cc == 0) { |
4c078bb2 BJ |
357 | if (so->so_error) { |
358 | error = so->so_error; | |
359 | so->so_error = 0; | |
360 | splx(s); | |
361 | goto release; | |
362 | } | |
cc15ab5d BJ |
363 | if (so->so_state & SS_CANTRCVMORE) { |
364 | splx(s); | |
365 | goto release; | |
366 | } | |
196d84fd BJ |
367 | if ((so->so_state & SS_ISCONNECTED) == 0 && |
368 | (so->so_proto->pr_flags & PR_CONNREQUIRED)) | |
369 | rcverr(ENOTCONN); | |
30b84e26 | 370 | if (so->so_options & SO_NONBLOCKING) |
4c078bb2 | 371 | rcverr(EWOULDBLOCK); |
cc15ab5d | 372 | sbunlock(&so->so_rcv); |
2752c877 | 373 | sbwait(&so->so_rcv); |
a4f6d93d | 374 | splx(s); |
cc15ab5d | 375 | goto restart; |
ce9d8eb4 | 376 | } |
92a533e6 | 377 | m = so->so_rcv.sb_mb; |
ce9d8eb4 BJ |
378 | if (m == 0) |
379 | panic("receive"); | |
b031e888 | 380 | if (so->so_proto->pr_flags & PR_ADDR) { |
b031e888 BJ |
381 | if (m->m_len != sizeof (struct sockaddr)) |
382 | panic("soreceive addr"); | |
383 | if (asa) | |
384 | bcopy(mtod(m, caddr_t), (caddr_t)asa, sizeof (*asa)); | |
b031e888 BJ |
385 | so->so_rcv.sb_cc -= m->m_len; |
386 | so->so_rcv.sb_mbcnt -= MSIZE; | |
50fc8df6 | 387 | m = m_free(m); |
cc15ab5d BJ |
388 | if (m == 0) |
389 | panic("receive 2"); | |
50fc8df6 | 390 | so->so_rcv.sb_mb = m; |
cc15ab5d | 391 | } |
edebca28 BJ |
392 | so->so_state &= ~SS_RCVATMARK; |
393 | if (so->so_oobmark && cnt > so->so_oobmark) | |
394 | cnt = so->so_oobmark; | |
ce9d8eb4 BJ |
395 | eor = 0; |
396 | do { | |
edebca28 | 397 | len = MIN(m->m_len, cnt); |
ce9d8eb4 BJ |
398 | if (len == m->m_len) { |
399 | eor = (int)m->m_act; | |
cc15ab5d | 400 | sbfree(&so->so_rcv, m); |
2156d53c | 401 | so->so_rcv.sb_mb = m->m_next; |
ce9d8eb4 BJ |
402 | } |
403 | splx(s); | |
404 | iomove(mtod(m, caddr_t), len, B_READ); | |
edebca28 | 405 | cnt -= len; |
ce9d8eb4 BJ |
406 | s = splnet(); |
407 | if (len == m->m_len) { | |
408 | MFREE(m, n); | |
409 | } else { | |
410 | m->m_off += len; | |
411 | m->m_len -= len; | |
92a533e6 | 412 | so->so_rcv.sb_cc -= len; |
ce9d8eb4 | 413 | } |
edebca28 | 414 | } while ((m = so->so_rcv.sb_mb) && cnt && !eor); |
ce9d8eb4 BJ |
415 | if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) |
416 | do { | |
ce9d8eb4 | 417 | if (m == 0) |
cc15ab5d BJ |
418 | panic("receive 3"); |
419 | sbfree(&so->so_rcv, m); | |
ce9d8eb4 BJ |
420 | eor = (int)m->m_act; |
421 | so->so_rcv.sb_mb = m->m_next; | |
422 | MFREE(m, n); | |
cc15ab5d | 423 | m = n; |
ce9d8eb4 | 424 | } while (eor == 0); |
cc15ab5d BJ |
425 | if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) |
426 | (*so->so_proto->pr_usrreq)(so, PRU_RCVD, 0, 0); | |
edebca28 BJ |
427 | if (so->so_oobmark) { |
428 | so->so_oobmark -= u.u_base - base; | |
429 | if (so->so_oobmark == 0) | |
430 | so->so_state |= SS_RCVATMARK; | |
431 | } | |
cc15ab5d | 432 | release: |
ae921915 | 433 | sbunlock(&so->so_rcv); |
cc15ab5d | 434 | splx(s); |
ae921915 | 435 | return (error); |
92a533e6 BJ |
436 | } |
437 | ||
edebca28 BJ |
438 | sohasoutofband(so) |
439 | struct socket *so; | |
440 | { | |
441 | ||
442 | if (so->so_pgrp == 0) | |
443 | return; | |
444 | if (so->so_pgrp > 0) | |
445 | gsignal(so->so_pgrp, SIGURG); | |
0a0f7cbb BJ |
446 | else { |
447 | struct proc *p = pfind(-so->so_pgrp); | |
448 | ||
449 | if (p) | |
450 | psignal(p, SIGURG); | |
451 | } | |
edebca28 BJ |
452 | } |
453 | ||
ae921915 BJ |
454 | /*ARGSUSED*/ |
455 | soioctl(so, cmd, cmdp) | |
92a533e6 BJ |
456 | register struct socket *so; |
457 | int cmd; | |
458 | register caddr_t cmdp; | |
459 | { | |
460 | ||
2b4b57cd | 461 | COUNT(SOIOCTL); |
2156d53c | 462 | switch (cmd) { |
92a533e6 | 463 | |
30b84e26 BJ |
464 | case FIONBIO: { |
465 | int nbio; | |
466 | if (copyin(cmdp, (caddr_t)&nbio, sizeof (nbio))) { | |
467 | u.u_error = EFAULT; | |
468 | return; | |
469 | } | |
470 | if (nbio) | |
471 | so->so_options |= SO_NONBLOCKING; | |
472 | else | |
473 | so->so_options &= ~SO_NONBLOCKING; | |
474 | return; | |
475 | } | |
476 | ||
477 | case FIOASYNC: { | |
478 | int async; | |
479 | if (copyin(cmdp, (caddr_t)&async, sizeof (async))) { | |
480 | u.u_error = EFAULT; | |
481 | return; | |
482 | } | |
483 | if (async) | |
484 | ; | |
485 | else | |
486 | ; | |
487 | return; | |
488 | } | |
489 | ||
490 | case SIOCSKEEP: { | |
491 | int keep; | |
492 | if (copyin(cmdp, (caddr_t)&keep, sizeof (keep))) { | |
493 | u.u_error = EFAULT; | |
494 | return; | |
495 | } | |
496 | if (keep) | |
497 | so->so_options &= ~SO_NOKEEPALIVE; | |
498 | else | |
499 | so->so_options |= SO_NOKEEPALIVE; | |
500 | return; | |
501 | } | |
502 | ||
503 | case SIOCGKEEP: { | |
504 | int keep = (so->so_options & SO_NOKEEPALIVE) == 0; | |
505 | if (copyout((caddr_t)&keep, cmdp, sizeof (keep))) | |
506 | u.u_error = EFAULT; | |
507 | return; | |
508 | } | |
509 | ||
510 | case SIOCSLINGER: { | |
511 | int linger; | |
512 | if (copyin(cmdp, (caddr_t)&linger, sizeof (linger))) { | |
513 | u.u_error = EFAULT; | |
514 | return; | |
515 | } | |
516 | so->so_linger = linger; | |
517 | if (so->so_linger) | |
518 | so->so_options &= ~SO_DONTLINGER; | |
519 | else | |
520 | so->so_options |= SO_DONTLINGER; | |
521 | return; | |
522 | } | |
523 | ||
524 | case SIOCGLINGER: { | |
525 | int linger = so->so_linger; | |
526 | if (copyout((caddr_t)&linger, cmdp, sizeof (linger))) { | |
527 | u.u_error = EFAULT; | |
528 | return; | |
529 | } | |
530 | } | |
edebca28 BJ |
531 | case SIOCSPGRP: { |
532 | int pgrp; | |
533 | if (copyin(cmdp, (caddr_t)&pgrp, sizeof (pgrp))) { | |
534 | u.u_error = EFAULT; | |
535 | return; | |
536 | } | |
537 | so->so_pgrp = pgrp; | |
538 | return; | |
539 | } | |
540 | ||
541 | case SIOCGPGRP: { | |
542 | int pgrp = so->so_pgrp; | |
543 | if (copyout((caddr_t)&pgrp, cmdp, sizeof (pgrp))) { | |
544 | u.u_error = EFAULT; | |
545 | return; | |
546 | } | |
547 | } | |
30b84e26 | 548 | |
b8acc34d BJ |
549 | case SIOCDONE: { |
550 | int flags; | |
551 | if (copyin(cmdp, (caddr_t)&flags, sizeof (flags))) { | |
552 | u.u_error = EFAULT; | |
553 | return; | |
554 | } | |
30b84e26 | 555 | flags++; |
b8acc34d BJ |
556 | if (flags & FREAD) { |
557 | int s = splimp(); | |
558 | socantrcvmore(so); | |
559 | sbflush(&so->so_rcv); | |
560 | } | |
561 | if (flags & FWRITE) | |
c30cd845 | 562 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, (struct mbuf *)0, 0); |
b8acc34d BJ |
563 | return; |
564 | } | |
565 | ||
edebca28 BJ |
566 | case SIOCSENDOOB: { |
567 | char oob; | |
568 | struct mbuf *m; | |
569 | if (copyin(cmdp, (caddr_t)&oob, sizeof (oob))) { | |
570 | u.u_error = EFAULT; | |
571 | return; | |
572 | } | |
573 | m = m_get(M_DONTWAIT); | |
574 | if (m == 0) { | |
575 | u.u_error = ENOBUFS; | |
576 | return; | |
577 | } | |
578 | m->m_off = MMINOFF; | |
579 | m->m_len = 1; | |
580 | *mtod(m, caddr_t) = oob; | |
581 | (*so->so_proto->pr_usrreq)(so, PRU_SENDOOB, m, 0); | |
582 | return; | |
583 | } | |
584 | ||
585 | case SIOCRCVOOB: { | |
586 | struct mbuf *m = m_get(M_DONTWAIT); | |
587 | if (m == 0) { | |
588 | u.u_error = ENOBUFS; | |
589 | return; | |
590 | } | |
591 | m->m_off = MMINOFF; *mtod(m, caddr_t) = 0; | |
592 | (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, m, 0); | |
593 | if (copyout(mtod(m, caddr_t), cmdp, sizeof (char))) { | |
594 | u.u_error = EFAULT; | |
595 | return; | |
596 | } | |
597 | m_free(m); | |
598 | return; | |
599 | } | |
600 | ||
601 | case SIOCATMARK: { | |
602 | int atmark = (so->so_state&SS_RCVATMARK) != 0; | |
603 | if (copyout((caddr_t)&atmark, cmdp, sizeof (atmark))) { | |
604 | u.u_error = EFAULT; | |
605 | return; | |
606 | } | |
607 | return; | |
608 | } | |
92a533e6 BJ |
609 | } |
610 | switch (so->so_type) { | |
611 | ||
612 | case SOCK_STREAM: | |
613 | break; | |
614 | ||
615 | case SOCK_DGRAM: | |
616 | break; | |
617 | ||
618 | case SOCK_RDM: | |
619 | break; | |
620 | ||
621 | case SOCK_RAW: | |
622 | break; | |
92a533e6 | 623 | } |
ce9d8eb4 | 624 | } |