Commit | Line | Data |
---|---|---|
d2cba8de | 1 | /* uipc_syscalls.c 4.42 83/01/13 */ |
c8c7dd0e BJ |
2 | |
3 | #include "../h/param.h" | |
4 | #include "../h/systm.h" | |
5 | #include "../h/dir.h" | |
6 | #include "../h/user.h" | |
7 | #include "../h/proc.h" | |
8 | #include "../h/file.h" | |
9 | #include "../h/inode.h" | |
10 | #include "../h/buf.h" | |
11 | #include "../h/mbuf.h" | |
c8c7dd0e BJ |
12 | #include "../h/protosw.h" |
13 | #include "../h/socket.h" | |
14 | #include "../h/socketvar.h" | |
4147b3f6 | 15 | #include "../h/descrip.h" |
a6b6f679 | 16 | #include "../h/uio.h" |
4147b3f6 | 17 | |
c8c7dd0e | 18 | /* |
cf012934 | 19 | * System call interface to the socket abstraction. |
c8c7dd0e BJ |
20 | */ |
21 | ||
cf012934 | 22 | socket() |
c8c7dd0e | 23 | { |
cc15ab5d | 24 | register struct a { |
cf012934 | 25 | int domain; |
cc15ab5d | 26 | int type; |
cf012934 | 27 | int protocol; |
cc15ab5d | 28 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 29 | struct socket *so; |
cc15ab5d | 30 | register struct file *fp; |
c8c7dd0e | 31 | |
dfb67abe | 32 | if ((fp = falloc()) == NULL) |
66f52238 | 33 | return; |
4147b3f6 BJ |
34 | fp->f_flag = FREAD|FWRITE; |
35 | fp->f_type = DTYPE_SOCKET; | |
66f52238 | 36 | u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol); |
cc15ab5d BJ |
37 | if (u.u_error) |
38 | goto bad; | |
2b4b57cd | 39 | fp->f_socket = so; |
cc15ab5d BJ |
40 | return; |
41 | bad: | |
42 | u.u_ofile[u.u_r.r_val1] = 0; | |
43 | fp->f_count = 0; | |
c8c7dd0e | 44 | } |
ae921915 | 45 | |
cf012934 | 46 | bind() |
ae921915 | 47 | { |
2b4b57cd | 48 | register struct a { |
cf012934 BJ |
49 | int s; |
50 | caddr_t name; | |
51 | int namelen; | |
2b4b57cd | 52 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 53 | register struct file *fp; |
cf012934 | 54 | struct mbuf *nam; |
ae921915 | 55 | |
cf012934 BJ |
56 | fp = getf(uap->s); |
57 | if (fp == 0) | |
58 | return; | |
59 | if (fp->f_type != DTYPE_SOCKET) { | |
60 | u.u_error = ENOTSOCK; | |
2b4b57cd BJ |
61 | return; |
62 | } | |
cf012934 BJ |
63 | u.u_error = sockname(&nam, uap->name, uap->namelen); |
64 | if (u.u_error) | |
65 | return; | |
66f52238 | 66 | u.u_error = sobind(fp->f_socket, nam); |
cf012934 | 67 | m_freem(nam); |
cf012934 BJ |
68 | } |
69 | ||
70 | listen() | |
71 | { | |
72 | register struct a { | |
73 | int s; | |
74 | int backlog; | |
75 | } *uap = (struct a *)u.u_ap; | |
76 | register struct file *fp; | |
77 | ||
78 | fp = getf(uap->s); | |
2b4b57cd BJ |
79 | if (fp == 0) |
80 | return; | |
4147b3f6 | 81 | if (fp->f_type != DTYPE_SOCKET) { |
2b4b57cd BJ |
82 | u.u_error = ENOTSOCK; |
83 | return; | |
84 | } | |
cf012934 BJ |
85 | u.u_error = solisten(fp->f_socket, uap->backlog); |
86 | } | |
87 | ||
88 | accept() | |
89 | { | |
90 | register struct a { | |
91 | int s; | |
92 | caddr_t name; | |
93 | int *anamelen; | |
cf012934 BJ |
94 | } *uap = (struct a *)u.u_ap; |
95 | register struct file *fp; | |
96 | struct mbuf *nam; | |
cf012934 BJ |
97 | int namelen; |
98 | int s; | |
99 | register struct socket *so; | |
100 | ||
101 | if (uap->name == 0) | |
102 | goto noname; | |
127f7d76 SL |
103 | u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, |
104 | sizeof (namelen)); | |
105 | if (u.u_error) | |
cf012934 | 106 | return; |
b32450f4 | 107 | if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { |
cf012934 BJ |
108 | u.u_error = EFAULT; |
109 | return; | |
110 | } | |
111 | noname: | |
cf012934 BJ |
112 | fp = getf(uap->s); |
113 | if (fp == 0) | |
66f52238 | 114 | return; |
cf012934 BJ |
115 | if (fp->f_type != DTYPE_SOCKET) { |
116 | u.u_error = ENOTSOCK; | |
66f52238 | 117 | return; |
cf012934 | 118 | } |
2b4b57cd BJ |
119 | s = splnet(); |
120 | so = fp->f_socket; | |
4147b3f6 BJ |
121 | if ((so->so_options & SO_ACCEPTCONN) == 0) { |
122 | u.u_error = EINVAL; | |
123 | splx(s); | |
66f52238 | 124 | return; |
4147b3f6 BJ |
125 | } |
126 | if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { | |
2b4b57cd BJ |
127 | u.u_error = EWOULDBLOCK; |
128 | splx(s); | |
66f52238 | 129 | return; |
2b4b57cd | 130 | } |
4147b3f6 | 131 | while (so->so_qlen == 0 && so->so_error == 0) { |
62229532 BJ |
132 | if (so->so_state & SS_CANTRCVMORE) { |
133 | so->so_error = ECONNABORTED; | |
134 | break; | |
135 | } | |
d08c5322 | 136 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
62229532 | 137 | } |
f269ef23 BJ |
138 | if (so->so_error) { |
139 | u.u_error = so->so_error; | |
140 | splx(s); | |
66f52238 | 141 | return; |
f269ef23 | 142 | } |
4147b3f6 BJ |
143 | if ((so->so_options & SO_NEWFDONCONN) == 0) { |
144 | struct socket *nso = so->so_q; | |
145 | (void) soqremque(nso, 1); | |
6e7edb25 | 146 | u.u_error = soclose(so, 1); |
4147b3f6 BJ |
147 | fp->f_socket = nso; |
148 | nso->so_q = 0; | |
149 | so = nso; | |
150 | goto ret; | |
151 | } | |
152 | if (ufalloc() < 0) { | |
153 | splx(s); | |
66f52238 | 154 | return; |
4147b3f6 BJ |
155 | } |
156 | fp = falloc(); | |
157 | if (fp == 0) { | |
158 | u.u_ofile[u.u_r.r_val1] = 0; | |
2b4b57cd | 159 | splx(s); |
66f52238 | 160 | return; |
cf012934 BJ |
161 | } |
162 | { struct socket *aso = so->so_q; | |
163 | if (soqremque(aso, 1) == 0) | |
164 | panic("accept"); | |
165 | so = aso; | |
2b4b57cd | 166 | } |
4147b3f6 BJ |
167 | fp->f_type = DTYPE_SOCKET; |
168 | fp->f_flag = FREAD|FWRITE; | |
cf012934 | 169 | fp->f_socket = so; |
4147b3f6 | 170 | ret: |
cce93e4b | 171 | nam = m_get(M_WAIT, MT_SONAME); |
66f52238 | 172 | (void) soaccept(so, nam); |
cf012934 BJ |
173 | if (uap->name) { |
174 | if (namelen > nam->m_len) | |
175 | namelen = nam->m_len; | |
176 | /* SHOULD COPY OUT A CHAIN HERE */ | |
b32450f4 BJ |
177 | (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, |
178 | (u_int)namelen); | |
179 | (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, | |
cf012934 BJ |
180 | sizeof (*uap->anamelen)); |
181 | } | |
182 | m_freem(nam); | |
2b4b57cd | 183 | splx(s); |
ae921915 BJ |
184 | } |
185 | ||
cf012934 | 186 | connect() |
c8c7dd0e BJ |
187 | { |
188 | register struct a { | |
cf012934 BJ |
189 | int s; |
190 | caddr_t name; | |
191 | int namelen; | |
c8c7dd0e | 192 | } *uap = (struct a *)u.u_ap; |
c8c7dd0e BJ |
193 | register struct file *fp; |
194 | register struct socket *so; | |
cf012934 | 195 | struct mbuf *nam; |
c8c7dd0e BJ |
196 | int s; |
197 | ||
cf012934 | 198 | fp = getf(uap->s); |
c8c7dd0e BJ |
199 | if (fp == 0) |
200 | return; | |
4147b3f6 | 201 | if (fp->f_type != DTYPE_SOCKET) { |
c8c7dd0e BJ |
202 | u.u_error = ENOTSOCK; |
203 | return; | |
204 | } | |
205 | so = fp->f_socket; | |
cf012934 | 206 | u.u_error = sockname(&nam, uap->name, uap->namelen); |
c8c7dd0e BJ |
207 | if (u.u_error) |
208 | return; | |
66f52238 | 209 | u.u_error = soconnect(so, nam); |
cf012934 BJ |
210 | if (u.u_error) |
211 | goto bad; | |
c8c7dd0e | 212 | s = splnet(); |
62364f0e | 213 | if ((so->so_state & SS_NBIO) && |
cc15ab5d | 214 | (so->so_state & SS_ISCONNECTING)) { |
c8c7dd0e | 215 | u.u_error = EINPROGRESS; |
cc15ab5d | 216 | splx(s); |
cf012934 | 217 | goto bad; |
c8c7dd0e | 218 | } |
cc15ab5d | 219 | while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) |
c8c7dd0e BJ |
220 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
221 | u.u_error = so->so_error; | |
cc15ab5d BJ |
222 | so->so_error = 0; |
223 | splx(s); | |
cf012934 BJ |
224 | bad: |
225 | m_freem(nam); | |
c8c7dd0e BJ |
226 | } |
227 | ||
cf012934 BJ |
228 | socketpair() |
229 | { | |
230 | ||
231 | u.u_error = ENOENT; | |
232 | } | |
233 | ||
234 | sendto() | |
c8c7dd0e BJ |
235 | { |
236 | register struct a { | |
cf012934 BJ |
237 | int s; |
238 | caddr_t buf; | |
239 | int len; | |
240 | int flags; | |
241 | caddr_t to; | |
242 | int tolen; | |
c8c7dd0e BJ |
243 | } *uap = (struct a *)u.u_ap; |
244 | register struct file *fp; | |
d3d550b5 BJ |
245 | struct uio auio; |
246 | struct iovec aiov; | |
cf012934 | 247 | struct mbuf *to; |
c8c7dd0e | 248 | |
cf012934 | 249 | fp = getf(uap->s); |
c8c7dd0e BJ |
250 | if (fp == 0) |
251 | return; | |
4147b3f6 | 252 | if (fp->f_type != DTYPE_SOCKET) { |
c8c7dd0e BJ |
253 | u.u_error = ENOTSOCK; |
254 | return; | |
255 | } | |
d3d550b5 BJ |
256 | auio.uio_iov = &aiov; |
257 | auio.uio_iovcnt = 1; | |
cf012934 BJ |
258 | aiov.iov_base = uap->buf; |
259 | aiov.iov_len = uap->len; | |
260 | auio.uio_resid = uap->len; | |
d3d550b5 BJ |
261 | auio.uio_segflg = 0; |
262 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 263 | if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { |
c8c7dd0e BJ |
264 | u.u_error = EFAULT; |
265 | return; | |
266 | } | |
cf012934 BJ |
267 | u.u_error = sockname(&to, uap->to, uap->tolen); |
268 | if (u.u_error) | |
269 | goto bad; | |
970108c7 | 270 | u.u_error = sosend(fp->f_socket, to, &auio, uap->flags); |
76d78581 | 271 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
cf012934 BJ |
272 | bad: |
273 | m_freem(to); | |
c8c7dd0e BJ |
274 | } |
275 | ||
cf012934 | 276 | send() |
cc15ab5d BJ |
277 | { |
278 | register struct a { | |
cf012934 BJ |
279 | int s; |
280 | caddr_t buf; | |
281 | int len; | |
282 | int flags; | |
cc15ab5d BJ |
283 | } *uap = (struct a *)u.u_ap; |
284 | register struct file *fp; | |
a6b6f679 BJ |
285 | struct uio auio; |
286 | struct iovec aiov; | |
cc15ab5d | 287 | |
cf012934 BJ |
288 | fp = getf(uap->s); |
289 | if (fp == 0) | |
290 | return; | |
291 | if (fp->f_type != DTYPE_SOCKET) { | |
292 | u.u_error = ENOTSOCK; | |
293 | return; | |
294 | } | |
295 | auio.uio_iov = &aiov; | |
296 | auio.uio_iovcnt = 1; | |
297 | aiov.iov_base = uap->buf; | |
298 | aiov.iov_len = uap->len; | |
299 | auio.uio_resid = uap->len; | |
300 | auio.uio_segflg = 0; | |
301 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 302 | if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { |
cf012934 BJ |
303 | u.u_error = EFAULT; |
304 | return; | |
305 | } | |
306 | if (u.u_error) | |
307 | return; | |
970108c7 | 308 | u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags); |
76d78581 | 309 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
cf012934 BJ |
310 | } |
311 | ||
312 | recvfrom() | |
313 | { | |
314 | register struct a { | |
315 | int s; | |
316 | caddr_t buf; | |
317 | int len; | |
318 | int flags; | |
319 | caddr_t from; | |
320 | int *fromlenaddr; | |
321 | } *uap = (struct a *)u.u_ap; | |
322 | register struct file *fp; | |
323 | struct uio auio; | |
324 | struct iovec aiov; | |
325 | struct mbuf *from; | |
326 | int fromlen; | |
327 | ||
127f7d76 SL |
328 | u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, |
329 | sizeof (fromlen)); | |
330 | if (u.u_error) | |
cf012934 | 331 | return; |
cf012934 BJ |
332 | fp = getf(uap->s); |
333 | if (fp == 0) | |
334 | return; | |
335 | if (fp->f_type != DTYPE_SOCKET) { | |
336 | u.u_error = ENOTSOCK; | |
337 | return; | |
338 | } | |
339 | auio.uio_iov = &aiov; | |
340 | auio.uio_iovcnt = 1; | |
341 | aiov.iov_base = uap->buf; | |
342 | aiov.iov_len = uap->len; | |
343 | auio.uio_resid = uap->len; | |
344 | auio.uio_segflg = 0; | |
345 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 346 | if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { |
cf012934 BJ |
347 | u.u_error = EFAULT; |
348 | return; | |
349 | } | |
350 | from = 0; | |
970108c7 | 351 | u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags); |
cf012934 BJ |
352 | if (u.u_error) |
353 | goto bad; | |
354 | if (from == 0) | |
355 | fromlen = 0; | |
356 | else { | |
357 | if (fromlen > from->m_len) | |
358 | fromlen = from->m_len; | |
127f7d76 SL |
359 | u.u_error = copyout(mtod(from, caddr_t), uap->from, |
360 | (u_int)fromlen); | |
361 | if (u.u_error) | |
cf012934 | 362 | goto bad; |
cf012934 | 363 | } |
127f7d76 SL |
364 | u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, |
365 | sizeof (fromlen)); | |
366 | if (u.u_error) | |
cf012934 | 367 | goto bad; |
cf012934 BJ |
368 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
369 | bad: | |
370 | if (from) | |
371 | m_freem(from); | |
cf012934 BJ |
372 | } |
373 | ||
374 | recv() | |
375 | { | |
376 | register struct a { | |
377 | int s; | |
378 | caddr_t buf; | |
379 | int len; | |
380 | int flags; | |
381 | } *uap = (struct a *)u.u_ap; | |
382 | register struct file *fp; | |
383 | struct uio auio; | |
384 | struct iovec aiov; | |
385 | ||
386 | fp = getf(uap->s); | |
cc15ab5d BJ |
387 | if (fp == 0) |
388 | return; | |
4147b3f6 | 389 | if (fp->f_type != DTYPE_SOCKET) { |
cc15ab5d BJ |
390 | u.u_error = ENOTSOCK; |
391 | return; | |
392 | } | |
a6b6f679 BJ |
393 | auio.uio_iov = &aiov; |
394 | auio.uio_iovcnt = 1; | |
cf012934 BJ |
395 | aiov.iov_base = uap->buf; |
396 | aiov.iov_len = uap->len; | |
397 | auio.uio_resid = uap->len; | |
a6b6f679 BJ |
398 | auio.uio_segflg = 0; |
399 | auio.uio_offset = 0; /* XXX */ | |
b32450f4 | 400 | if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { |
cc15ab5d BJ |
401 | u.u_error = EFAULT; |
402 | return; | |
403 | } | |
b32450f4 BJ |
404 | u.u_error = |
405 | soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); | |
cf012934 BJ |
406 | u.u_r.r_val1 = uap->len - auio.uio_resid; |
407 | } | |
408 | ||
409 | sendmsg() | |
410 | { | |
411 | ||
412 | u.u_error = EINVAL; | |
413 | } | |
414 | ||
415 | recvmsg() | |
416 | { | |
417 | ||
418 | u.u_error = EINVAL; | |
419 | } | |
420 | ||
421 | shutdown() | |
422 | { | |
6ef233bf SL |
423 | struct a { |
424 | int s; | |
425 | int how; | |
426 | } *uap = (struct a *)u.u_ap; | |
427 | struct file *fp; | |
cf012934 | 428 | |
6ef233bf SL |
429 | fp = getf(uap->s); |
430 | if (fp == 0) | |
431 | return; | |
432 | if (fp->f_type != DTYPE_SOCKET) { | |
433 | u.u_error = ENOTSOCK; | |
434 | return; | |
435 | } | |
436 | u.u_error = soshutdown(fp->f_socket, uap->how); | |
cf012934 BJ |
437 | } |
438 | ||
66f52238 SL |
439 | setsockopt() |
440 | { | |
441 | struct a { | |
442 | int s; | |
443 | int level; | |
444 | int name; | |
445 | caddr_t val; | |
446 | int valsize; | |
447 | } *uap = (struct a *)u.u_ap; | |
448 | struct file *fp; | |
d2cba8de | 449 | struct mbuf *m = NULL; |
66f52238 SL |
450 | |
451 | fp = getf(uap->s); | |
452 | if (fp == 0) | |
453 | return; | |
454 | if (fp->f_type != DTYPE_SOCKET) { | |
455 | u.u_error = ENOTSOCK; | |
456 | return; | |
457 | } | |
458 | if (uap->valsize > MLEN) { | |
459 | u.u_error = EINVAL; | |
460 | return; | |
461 | } | |
d2cba8de SL |
462 | if (uap->val) { |
463 | m = m_get(M_WAIT, MT_SOOPTS); | |
464 | if (m == 0) { | |
465 | u.u_error = ENOBUFS; | |
466 | return; | |
467 | } | |
468 | u.u_error = copyin(uap->val, mtod(m, caddr_t), | |
469 | (u_int)uap->valsize); | |
470 | if (u.u_error) | |
471 | goto bad; | |
472 | m->m_len = uap->valsize; | |
66f52238 | 473 | } |
66f52238 SL |
474 | u.u_error = sosetopt(fp->f_socket, uap->level, uap->name, m); |
475 | bad: | |
d2cba8de SL |
476 | if (m != NULL) |
477 | (void) m_free(m); | |
66f52238 SL |
478 | } |
479 | ||
480 | getsockopt() | |
481 | { | |
482 | struct a { | |
483 | int s; | |
484 | int level; | |
485 | int name; | |
486 | caddr_t val; | |
487 | int *avalsize; | |
488 | } *uap = (struct a *)u.u_ap; | |
489 | struct file *fp; | |
d2cba8de | 490 | struct mbuf *m = NULL; |
66f52238 SL |
491 | int valsize; |
492 | ||
493 | fp = getf(uap->s); | |
494 | if (fp == 0) | |
495 | return; | |
496 | if (fp->f_type != DTYPE_SOCKET) { | |
497 | u.u_error = ENOTSOCK; | |
498 | return; | |
499 | } | |
d2cba8de SL |
500 | if (uap->val) { |
501 | u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, | |
502 | sizeof (valsize)); | |
503 | if (u.u_error) | |
504 | return; | |
505 | m = m_get(M_WAIT, MT_SOOPTS); | |
506 | if (m == NULL) { | |
507 | u.u_error = ENOBUFS; | |
508 | return; | |
509 | } | |
66f52238 SL |
510 | } |
511 | u.u_error = sogetopt(fp->f_socket, uap->level, uap->name, m); | |
512 | if (u.u_error) | |
513 | goto bad; | |
d2cba8de SL |
514 | if (uap->val) { |
515 | if (valsize > m->m_len) | |
516 | valsize = m->m_len; | |
517 | u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); | |
518 | if (u.u_error) | |
519 | goto bad; | |
520 | u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, | |
521 | sizeof (valsize)); | |
522 | } | |
66f52238 | 523 | bad: |
d2cba8de SL |
524 | if (m != NULL) |
525 | (void) m_free(m); | |
66f52238 SL |
526 | } |
527 | ||
cf012934 BJ |
528 | pipe() |
529 | { | |
530 | register struct file *rf, *wf; | |
531 | struct socket *rso, *wso; | |
532 | int r; | |
533 | ||
4f083fd7 SL |
534 | u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, |
535 | (struct socketopt *)0); | |
2b4b57cd BJ |
536 | if (u.u_error) |
537 | return; | |
4f083fd7 SL |
538 | u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, |
539 | (struct socketopt *)0); | |
cf012934 BJ |
540 | if (u.u_error) |
541 | goto free; | |
542 | rf = falloc(); | |
543 | if (rf == NULL) | |
544 | goto free2; | |
545 | r = u.u_r.r_val1; | |
546 | rf->f_flag = FREAD; | |
547 | rf->f_type = DTYPE_SOCKET; | |
548 | rf->f_socket = rso; | |
549 | wf = falloc(); | |
550 | if (wf == NULL) | |
551 | goto free3; | |
552 | wf->f_flag = FWRITE; | |
553 | wf->f_type = DTYPE_SOCKET; | |
554 | wf->f_socket = wso; | |
555 | u.u_r.r_val2 = u.u_r.r_val1; | |
556 | u.u_r.r_val1 = r; | |
557 | if (piconnect(wso, rso) == 0) | |
558 | goto free4; | |
559 | return; | |
560 | free4: | |
561 | wf->f_count = 0; | |
562 | u.u_ofile[u.u_r.r_val2] = 0; | |
563 | free3: | |
564 | rf->f_count = 0; | |
565 | u.u_ofile[r] = 0; | |
566 | free2: | |
567 | wso->so_state |= SS_NOFDREF; | |
568 | sofree(wso); | |
569 | free: | |
570 | rso->so_state |= SS_NOFDREF; | |
571 | sofree(rso); | |
cc15ab5d | 572 | } |
a3076b07 BJ |
573 | |
574 | /* | |
575 | * Get socket address. | |
576 | */ | |
577 | ssocketaddr() | |
578 | { | |
579 | register struct a { | |
580 | int fdes; | |
581 | struct sockaddr *asa; | |
582 | } *uap = (struct a *)u.u_ap; | |
583 | register struct file *fp; | |
05d69517 | 584 | register struct socket *so; |
cf012934 | 585 | struct mbuf *m; |
a3076b07 BJ |
586 | |
587 | fp = getf(uap->fdes); | |
588 | if (fp == 0) | |
589 | return; | |
4147b3f6 | 590 | if (fp->f_type != DTYPE_SOCKET) { |
a3076b07 BJ |
591 | u.u_error = ENOTSOCK; |
592 | return; | |
593 | } | |
05d69517 | 594 | so = fp->f_socket; |
cce93e4b | 595 | m = m_getclr(M_WAIT, MT_SONAME); |
05d69517 | 596 | u.u_error = |
cf012934 | 597 | (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); |
05d69517 | 598 | if (u.u_error) |
cf012934 | 599 | goto bad; |
127f7d76 SL |
600 | u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, |
601 | sizeof (struct sockaddr)); | |
cf012934 BJ |
602 | bad: |
603 | m_freem(m); | |
604 | } | |
605 | ||
606 | sockname(aname, name, namelen) | |
607 | struct mbuf **aname; | |
608 | caddr_t name; | |
609 | int namelen; | |
610 | { | |
611 | register struct mbuf *m; | |
127f7d76 | 612 | int error; |
cf012934 BJ |
613 | |
614 | if (namelen > MLEN) | |
615 | return (EINVAL); | |
cce93e4b | 616 | m = m_get(M_WAIT, MT_SONAME); |
cf012934 | 617 | m->m_len = namelen; |
127f7d76 SL |
618 | error = copyin(name, mtod(m, caddr_t), (u_int)namelen); |
619 | if (error) | |
cf012934 | 620 | (void) m_free(m); |
127f7d76 SL |
621 | else |
622 | *aname = m; | |
623 | return (error); | |
cf012934 | 624 | } |