Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)uipc_syscalls.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
c8c7dd0e | 8 | |
94368568 JB |
9 | #include "param.h" |
10 | #include "systm.h" | |
11 | #include "dir.h" | |
12 | #include "user.h" | |
13 | #include "proc.h" | |
14 | #include "file.h" | |
15 | #include "inode.h" | |
16 | #include "buf.h" | |
17 | #include "mbuf.h" | |
18 | #include "protosw.h" | |
19 | #include "socket.h" | |
20 | #include "socketvar.h" | |
21 | #include "uio.h" | |
4147b3f6 | 22 | |
c8c7dd0e | 23 | /* |
cf012934 | 24 | * System call interface to the socket abstraction. |
c8c7dd0e BJ |
25 | */ |
26 | ||
88a7a62a SL |
27 | struct file *getsock(); |
28 | extern struct fileops socketops; | |
29 | ||
cf012934 | 30 | socket() |
c8c7dd0e | 31 | { |
cc15ab5d | 32 | register struct a { |
cf012934 | 33 | int domain; |
cc15ab5d | 34 | int type; |
cf012934 | 35 | int protocol; |
cc15ab5d | 36 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 37 | struct socket *so; |
cc15ab5d | 38 | register struct file *fp; |
c8c7dd0e | 39 | |
dfb67abe | 40 | if ((fp = falloc()) == NULL) |
66f52238 | 41 | return; |
4147b3f6 BJ |
42 | fp->f_flag = FREAD|FWRITE; |
43 | fp->f_type = DTYPE_SOCKET; | |
88a7a62a | 44 | fp->f_ops = &socketops; |
66f52238 | 45 | u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol); |
cc15ab5d BJ |
46 | if (u.u_error) |
47 | goto bad; | |
88a7a62a | 48 | fp->f_data = (caddr_t)so; |
cc15ab5d BJ |
49 | return; |
50 | bad: | |
51 | u.u_ofile[u.u_r.r_val1] = 0; | |
52 | fp->f_count = 0; | |
c8c7dd0e | 53 | } |
ae921915 | 54 | |
cf012934 | 55 | bind() |
ae921915 | 56 | { |
2b4b57cd | 57 | register struct a { |
cf012934 BJ |
58 | int s; |
59 | caddr_t name; | |
60 | int namelen; | |
2b4b57cd | 61 | } *uap = (struct a *)u.u_ap; |
2b4b57cd | 62 | register struct file *fp; |
cf012934 | 63 | struct mbuf *nam; |
ae921915 | 64 | |
88a7a62a | 65 | fp = getsock(uap->s); |
cf012934 BJ |
66 | if (fp == 0) |
67 | return; | |
98447d3f | 68 | u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); |
cf012934 BJ |
69 | if (u.u_error) |
70 | return; | |
88a7a62a | 71 | u.u_error = sobind((struct socket *)fp->f_data, nam); |
cf012934 | 72 | m_freem(nam); |
cf012934 BJ |
73 | } |
74 | ||
75 | listen() | |
76 | { | |
77 | register struct a { | |
78 | int s; | |
79 | int backlog; | |
80 | } *uap = (struct a *)u.u_ap; | |
81 | register struct file *fp; | |
82 | ||
88a7a62a | 83 | fp = getsock(uap->s); |
2b4b57cd BJ |
84 | if (fp == 0) |
85 | return; | |
88a7a62a | 86 | u.u_error = solisten((struct socket *)fp->f_data, uap->backlog); |
cf012934 BJ |
87 | } |
88 | ||
89 | accept() | |
90 | { | |
91 | register struct a { | |
92 | int s; | |
93 | caddr_t name; | |
94 | int *anamelen; | |
cf012934 BJ |
95 | } *uap = (struct a *)u.u_ap; |
96 | register struct file *fp; | |
97 | struct mbuf *nam; | |
cf012934 BJ |
98 | int namelen; |
99 | int s; | |
100 | register struct socket *so; | |
101 | ||
102 | if (uap->name == 0) | |
103 | goto noname; | |
127f7d76 SL |
104 | u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, |
105 | sizeof (namelen)); | |
106 | if (u.u_error) | |
cf012934 | 107 | return; |
b32450f4 | 108 | if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { |
cf012934 BJ |
109 | u.u_error = EFAULT; |
110 | return; | |
111 | } | |
112 | noname: | |
88a7a62a | 113 | fp = getsock(uap->s); |
cf012934 | 114 | if (fp == 0) |
66f52238 | 115 | return; |
2b4b57cd | 116 | s = splnet(); |
88a7a62a | 117 | so = (struct socket *)fp->f_data; |
4147b3f6 BJ |
118 | if ((so->so_options & SO_ACCEPTCONN) == 0) { |
119 | u.u_error = EINVAL; | |
120 | splx(s); | |
66f52238 | 121 | return; |
4147b3f6 BJ |
122 | } |
123 | if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { | |
2b4b57cd BJ |
124 | u.u_error = EWOULDBLOCK; |
125 | splx(s); | |
66f52238 | 126 | return; |
2b4b57cd | 127 | } |
4147b3f6 | 128 | while (so->so_qlen == 0 && so->so_error == 0) { |
62229532 BJ |
129 | if (so->so_state & SS_CANTRCVMORE) { |
130 | so->so_error = ECONNABORTED; | |
131 | break; | |
132 | } | |
d08c5322 | 133 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
62229532 | 134 | } |
f269ef23 BJ |
135 | if (so->so_error) { |
136 | u.u_error = so->so_error; | |
f4ed5810 | 137 | so->so_error = 0; |
f269ef23 | 138 | splx(s); |
66f52238 | 139 | return; |
f269ef23 | 140 | } |
88a7a62a | 141 | if (ufalloc(0) < 0) { |
4147b3f6 | 142 | splx(s); |
66f52238 | 143 | return; |
4147b3f6 BJ |
144 | } |
145 | fp = falloc(); | |
146 | if (fp == 0) { | |
147 | u.u_ofile[u.u_r.r_val1] = 0; | |
2b4b57cd | 148 | splx(s); |
66f52238 | 149 | return; |
cf012934 BJ |
150 | } |
151 | { struct socket *aso = so->so_q; | |
152 | if (soqremque(aso, 1) == 0) | |
153 | panic("accept"); | |
154 | so = aso; | |
2b4b57cd | 155 | } |
4147b3f6 BJ |
156 | fp->f_type = DTYPE_SOCKET; |
157 | fp->f_flag = FREAD|FWRITE; | |
88a7a62a SL |
158 | fp->f_ops = &socketops; |
159 | fp->f_data = (caddr_t)so; | |
cce93e4b | 160 | nam = m_get(M_WAIT, MT_SONAME); |
66f52238 | 161 | (void) soaccept(so, nam); |
cf012934 BJ |
162 | if (uap->name) { |
163 | if (namelen > nam->m_len) | |
164 | namelen = nam->m_len; | |
165 | /* SHOULD COPY OUT A CHAIN HERE */ | |
b32450f4 BJ |
166 | (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, |
167 | (u_int)namelen); | |
168 | (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, | |
cf012934 BJ |
169 | sizeof (*uap->anamelen)); |
170 | } | |
171 | m_freem(nam); | |
2b4b57cd | 172 | splx(s); |
ae921915 BJ |
173 | } |
174 | ||
cf012934 | 175 | connect() |
c8c7dd0e BJ |
176 | { |
177 | register struct a { | |
cf012934 BJ |
178 | int s; |
179 | caddr_t name; | |
180 | int namelen; | |
c8c7dd0e | 181 | } *uap = (struct a *)u.u_ap; |
c8c7dd0e BJ |
182 | register struct file *fp; |
183 | register struct socket *so; | |
cf012934 | 184 | struct mbuf *nam; |
c8c7dd0e BJ |
185 | int s; |
186 | ||
88a7a62a | 187 | fp = getsock(uap->s); |
c8c7dd0e BJ |
188 | if (fp == 0) |
189 | return; | |
88a7a62a | 190 | so = (struct socket *)fp->f_data; |
a7a77c02 MK |
191 | if ((so->so_state & SS_NBIO) && |
192 | (so->so_state & SS_ISCONNECTING)) { | |
6222acc3 | 193 | u.u_error = EALREADY; |
a7a77c02 MK |
194 | return; |
195 | } | |
98447d3f | 196 | u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME); |
c8c7dd0e BJ |
197 | if (u.u_error) |
198 | return; | |
66f52238 | 199 | u.u_error = soconnect(so, nam); |
cf012934 BJ |
200 | if (u.u_error) |
201 | goto bad; | |
6222acc3 MK |
202 | if ((so->so_state & SS_NBIO) && |
203 | (so->so_state & SS_ISCONNECTING)) { | |
204 | u.u_error = EINPROGRESS; | |
205 | m_freem(nam); | |
206 | return; | |
207 | } | |
c8c7dd0e | 208 | s = splnet(); |
88a7a62a SL |
209 | if (setjmp(&u.u_qsave)) { |
210 | if (u.u_error == 0) | |
211 | u.u_error = EINTR; | |
212 | goto bad2; | |
c8c7dd0e | 213 | } |
cc15ab5d | 214 | while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) |
c8c7dd0e BJ |
215 | sleep((caddr_t)&so->so_timeo, PZERO+1); |
216 | u.u_error = so->so_error; | |
cc15ab5d | 217 | so->so_error = 0; |
88a7a62a | 218 | bad2: |
cc15ab5d | 219 | splx(s); |
cf012934 | 220 | bad: |
6750daae | 221 | so->so_state &= ~SS_ISCONNECTING; |
cf012934 | 222 | m_freem(nam); |
c8c7dd0e BJ |
223 | } |
224 | ||
cf012934 BJ |
225 | socketpair() |
226 | { | |
5a48956d SL |
227 | register struct a { |
228 | int domain; | |
229 | int type; | |
230 | int protocol; | |
231 | int *rsv; | |
232 | } *uap = (struct a *)u.u_ap; | |
233 | register struct file *fp1, *fp2; | |
234 | struct socket *so1, *so2; | |
235 | int sv[2]; | |
cf012934 | 236 | |
5a48956d SL |
237 | if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) { |
238 | u.u_error = EFAULT; | |
239 | return; | |
240 | } | |
241 | u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol); | |
242 | if (u.u_error) | |
243 | return; | |
244 | u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol); | |
245 | if (u.u_error) | |
246 | goto free; | |
247 | fp1 = falloc(); | |
248 | if (fp1 == NULL) | |
249 | goto free2; | |
250 | sv[0] = u.u_r.r_val1; | |
251 | fp1->f_flag = FREAD|FWRITE; | |
252 | fp1->f_type = DTYPE_SOCKET; | |
253 | fp1->f_ops = &socketops; | |
254 | fp1->f_data = (caddr_t)so1; | |
255 | fp2 = falloc(); | |
256 | if (fp2 == NULL) | |
257 | goto free3; | |
258 | fp2->f_flag = FREAD|FWRITE; | |
259 | fp2->f_type = DTYPE_SOCKET; | |
260 | fp2->f_ops = &socketops; | |
261 | fp2->f_data = (caddr_t)so2; | |
262 | sv[1] = u.u_r.r_val1; | |
263 | u.u_error = soconnect2(so1, so2); | |
264 | if (u.u_error) | |
265 | goto free4; | |
33446404 MK |
266 | if (uap->type == SOCK_DGRAM) { |
267 | /* | |
268 | * Datagram socket connection is asymmetric. | |
269 | */ | |
270 | u.u_error = soconnect2(so2, so1); | |
271 | if (u.u_error) | |
272 | goto free4; | |
273 | } | |
274 | u.u_r.r_val1 = 0; | |
5a48956d SL |
275 | (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); |
276 | return; | |
277 | free4: | |
278 | fp2->f_count = 0; | |
279 | u.u_ofile[sv[1]] = 0; | |
280 | free3: | |
281 | fp1->f_count = 0; | |
282 | u.u_ofile[sv[0]] = 0; | |
283 | free2: | |
8011f5df | 284 | (void)soclose(so2); |
5a48956d | 285 | free: |
8011f5df | 286 | (void)soclose(so1); |
cf012934 BJ |
287 | } |
288 | ||
289 | sendto() | |
c8c7dd0e BJ |
290 | { |
291 | register struct a { | |
cf012934 BJ |
292 | int s; |
293 | caddr_t buf; | |
294 | int len; | |
295 | int flags; | |
296 | caddr_t to; | |
297 | int tolen; | |
c8c7dd0e | 298 | } *uap = (struct a *)u.u_ap; |
88a7a62a | 299 | struct msghdr msg; |
d3d550b5 | 300 | struct iovec aiov; |
c8c7dd0e | 301 | |
88a7a62a SL |
302 | msg.msg_name = uap->to; |
303 | msg.msg_namelen = uap->tolen; | |
304 | msg.msg_iov = &aiov; | |
305 | msg.msg_iovlen = 1; | |
cf012934 BJ |
306 | aiov.iov_base = uap->buf; |
307 | aiov.iov_len = uap->len; | |
88a7a62a SL |
308 | msg.msg_accrights = 0; |
309 | msg.msg_accrightslen = 0; | |
310 | sendit(uap->s, &msg, uap->flags); | |
c8c7dd0e BJ |
311 | } |
312 | ||
cf012934 | 313 | send() |
cc15ab5d BJ |
314 | { |
315 | register struct a { | |
cf012934 BJ |
316 | int s; |
317 | caddr_t buf; | |
318 | int len; | |
319 | int flags; | |
cc15ab5d | 320 | } *uap = (struct a *)u.u_ap; |
88a7a62a | 321 | struct msghdr msg; |
a6b6f679 | 322 | struct iovec aiov; |
cc15ab5d | 323 | |
88a7a62a SL |
324 | msg.msg_name = 0; |
325 | msg.msg_namelen = 0; | |
326 | msg.msg_iov = &aiov; | |
327 | msg.msg_iovlen = 1; | |
cf012934 BJ |
328 | aiov.iov_base = uap->buf; |
329 | aiov.iov_len = uap->len; | |
88a7a62a SL |
330 | msg.msg_accrights = 0; |
331 | msg.msg_accrightslen = 0; | |
332 | sendit(uap->s, &msg, uap->flags); | |
333 | } | |
334 | ||
335 | sendmsg() | |
336 | { | |
337 | register struct a { | |
338 | int s; | |
339 | caddr_t msg; | |
340 | int flags; | |
341 | } *uap = (struct a *)u.u_ap; | |
342 | struct msghdr msg; | |
343 | struct iovec aiov[MSG_MAXIOVLEN]; | |
344 | ||
345 | u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); | |
346 | if (u.u_error) | |
347 | return; | |
348 | if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { | |
349 | u.u_error = EMSGSIZE; | |
cf012934 BJ |
350 | return; |
351 | } | |
88a7a62a SL |
352 | u.u_error = |
353 | copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, | |
354 | (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); | |
cf012934 BJ |
355 | if (u.u_error) |
356 | return; | |
88a7a62a | 357 | msg.msg_iov = aiov; |
88a7a62a SL |
358 | sendit(uap->s, &msg, uap->flags); |
359 | } | |
360 | ||
361 | sendit(s, mp, flags) | |
362 | int s; | |
363 | register struct msghdr *mp; | |
364 | int flags; | |
365 | { | |
366 | register struct file *fp; | |
367 | struct uio auio; | |
368 | register struct iovec *iov; | |
369 | register int i; | |
370 | struct mbuf *to, *rights; | |
371 | int len; | |
372 | ||
373 | fp = getsock(s); | |
374 | if (fp == 0) | |
375 | return; | |
376 | auio.uio_iov = mp->msg_iov; | |
377 | auio.uio_iovcnt = mp->msg_iovlen; | |
c41770c0 | 378 | auio.uio_segflg = UIO_USERSPACE; |
88a7a62a SL |
379 | auio.uio_offset = 0; /* XXX */ |
380 | auio.uio_resid = 0; | |
381 | iov = mp->msg_iov; | |
125c8f95 | 382 | for (i = 0; i < mp->msg_iovlen; i++, iov++) { |
88a7a62a SL |
383 | if (iov->iov_len < 0) { |
384 | u.u_error = EINVAL; | |
385 | return; | |
386 | } | |
0f6422b0 MK |
387 | if (iov->iov_len == 0) |
388 | continue; | |
88a7a62a SL |
389 | if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { |
390 | u.u_error = EFAULT; | |
391 | return; | |
392 | } | |
393 | auio.uio_resid += iov->iov_len; | |
88a7a62a SL |
394 | } |
395 | if (mp->msg_name) { | |
396 | u.u_error = | |
98447d3f | 397 | sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); |
88a7a62a SL |
398 | if (u.u_error) |
399 | return; | |
400 | } else | |
401 | to = 0; | |
402 | if (mp->msg_accrights) { | |
403 | u.u_error = | |
98447d3f MK |
404 | sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen, |
405 | MT_RIGHTS); | |
88a7a62a SL |
406 | if (u.u_error) |
407 | goto bad; | |
408 | } else | |
409 | rights = 0; | |
410 | len = auio.uio_resid; | |
411 | u.u_error = | |
412 | sosend((struct socket *)fp->f_data, to, &auio, flags, rights); | |
413 | u.u_r.r_val1 = len - auio.uio_resid; | |
414 | if (rights) | |
415 | m_freem(rights); | |
416 | bad: | |
417 | if (to) | |
418 | m_freem(to); | |
cf012934 BJ |
419 | } |
420 | ||
421 | recvfrom() | |
422 | { | |
423 | register struct a { | |
424 | int s; | |
425 | caddr_t buf; | |
426 | int len; | |
427 | int flags; | |
428 | caddr_t from; | |
429 | int *fromlenaddr; | |
430 | } *uap = (struct a *)u.u_ap; | |
88a7a62a | 431 | struct msghdr msg; |
cf012934 | 432 | struct iovec aiov; |
88a7a62a | 433 | int len; |
cf012934 | 434 | |
88a7a62a SL |
435 | u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, |
436 | sizeof (len)); | |
127f7d76 | 437 | if (u.u_error) |
cf012934 | 438 | return; |
88a7a62a SL |
439 | msg.msg_name = uap->from; |
440 | msg.msg_namelen = len; | |
441 | msg.msg_iov = &aiov; | |
442 | msg.msg_iovlen = 1; | |
cf012934 BJ |
443 | aiov.iov_base = uap->buf; |
444 | aiov.iov_len = uap->len; | |
88a7a62a SL |
445 | msg.msg_accrights = 0; |
446 | msg.msg_accrightslen = 0; | |
447 | recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0); | |
cf012934 BJ |
448 | } |
449 | ||
450 | recv() | |
451 | { | |
452 | register struct a { | |
453 | int s; | |
454 | caddr_t buf; | |
455 | int len; | |
456 | int flags; | |
457 | } *uap = (struct a *)u.u_ap; | |
88a7a62a | 458 | struct msghdr msg; |
cf012934 BJ |
459 | struct iovec aiov; |
460 | ||
88a7a62a SL |
461 | msg.msg_name = 0; |
462 | msg.msg_namelen = 0; | |
463 | msg.msg_iov = &aiov; | |
464 | msg.msg_iovlen = 1; | |
cf012934 BJ |
465 | aiov.iov_base = uap->buf; |
466 | aiov.iov_len = uap->len; | |
88a7a62a SL |
467 | msg.msg_accrights = 0; |
468 | msg.msg_accrightslen = 0; | |
469 | recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0); | |
cf012934 BJ |
470 | } |
471 | ||
88a7a62a | 472 | recvmsg() |
cf012934 | 473 | { |
88a7a62a SL |
474 | register struct a { |
475 | int s; | |
476 | struct msghdr *msg; | |
477 | int flags; | |
478 | } *uap = (struct a *)u.u_ap; | |
479 | struct msghdr msg; | |
480 | struct iovec aiov[MSG_MAXIOVLEN]; | |
cf012934 | 481 | |
88a7a62a SL |
482 | u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); |
483 | if (u.u_error) | |
484 | return; | |
485 | if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { | |
486 | u.u_error = EMSGSIZE; | |
487 | return; | |
488 | } | |
489 | u.u_error = | |
490 | copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, | |
491 | (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); | |
492 | if (u.u_error) | |
493 | return; | |
494 | msg.msg_iov = aiov; | |
495 | if (msg.msg_accrights) | |
496 | if (useracc((caddr_t)msg.msg_accrights, | |
497 | (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { | |
498 | u.u_error = EFAULT; | |
499 | return; | |
500 | } | |
501 | recvit(uap->s, &msg, uap->flags, | |
502 | (caddr_t)&uap->msg->msg_namelen, | |
503 | (caddr_t)&uap->msg->msg_accrightslen); | |
cf012934 BJ |
504 | } |
505 | ||
88a7a62a SL |
506 | recvit(s, mp, flags, namelenp, rightslenp) |
507 | int s; | |
508 | register struct msghdr *mp; | |
509 | int flags; | |
510 | caddr_t namelenp, rightslenp; | |
cf012934 | 511 | { |
88a7a62a SL |
512 | register struct file *fp; |
513 | struct uio auio; | |
514 | register struct iovec *iov; | |
515 | register int i; | |
516 | struct mbuf *from, *rights; | |
517 | int len; | |
518 | ||
519 | fp = getsock(s); | |
520 | if (fp == 0) | |
521 | return; | |
522 | auio.uio_iov = mp->msg_iov; | |
523 | auio.uio_iovcnt = mp->msg_iovlen; | |
c41770c0 | 524 | auio.uio_segflg = UIO_USERSPACE; |
88a7a62a SL |
525 | auio.uio_offset = 0; /* XXX */ |
526 | auio.uio_resid = 0; | |
527 | iov = mp->msg_iov; | |
125c8f95 | 528 | for (i = 0; i < mp->msg_iovlen; i++, iov++) { |
88a7a62a SL |
529 | if (iov->iov_len < 0) { |
530 | u.u_error = EINVAL; | |
531 | return; | |
532 | } | |
0f6422b0 MK |
533 | if (iov->iov_len == 0) |
534 | continue; | |
88a7a62a SL |
535 | if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) { |
536 | u.u_error = EFAULT; | |
537 | return; | |
538 | } | |
539 | auio.uio_resid += iov->iov_len; | |
88a7a62a SL |
540 | } |
541 | len = auio.uio_resid; | |
542 | u.u_error = | |
543 | soreceive((struct socket *)fp->f_data, &from, &auio, | |
544 | flags, &rights); | |
545 | u.u_r.r_val1 = len - auio.uio_resid; | |
546 | if (mp->msg_name) { | |
547 | len = mp->msg_namelen; | |
548 | if (len <= 0 || from == 0) | |
549 | len = 0; | |
550 | else { | |
551 | if (len > from->m_len) | |
552 | len = from->m_len; | |
553 | (void) copyout((caddr_t)mtod(from, caddr_t), | |
554 | (caddr_t)mp->msg_name, (unsigned)len); | |
555 | } | |
556 | (void) copyout((caddr_t)&len, namelenp, sizeof (int)); | |
557 | } | |
558 | if (mp->msg_accrights) { | |
559 | len = mp->msg_accrightslen; | |
560 | if (len <= 0 || rights == 0) | |
561 | len = 0; | |
562 | else { | |
563 | if (len > rights->m_len) | |
564 | len = rights->m_len; | |
565 | (void) copyout((caddr_t)mtod(rights, caddr_t), | |
566 | (caddr_t)mp->msg_accrights, (unsigned)len); | |
567 | } | |
568 | (void) copyout((caddr_t)&len, rightslenp, sizeof (int)); | |
569 | } | |
570 | if (rights) | |
571 | m_freem(rights); | |
572 | if (from) | |
573 | m_freem(from); | |
cf012934 BJ |
574 | } |
575 | ||
576 | shutdown() | |
577 | { | |
6ef233bf SL |
578 | struct a { |
579 | int s; | |
580 | int how; | |
581 | } *uap = (struct a *)u.u_ap; | |
582 | struct file *fp; | |
cf012934 | 583 | |
88a7a62a | 584 | fp = getsock(uap->s); |
6ef233bf SL |
585 | if (fp == 0) |
586 | return; | |
88a7a62a | 587 | u.u_error = soshutdown((struct socket *)fp->f_data, uap->how); |
cf012934 BJ |
588 | } |
589 | ||
66f52238 SL |
590 | setsockopt() |
591 | { | |
592 | struct a { | |
593 | int s; | |
594 | int level; | |
595 | int name; | |
596 | caddr_t val; | |
597 | int valsize; | |
598 | } *uap = (struct a *)u.u_ap; | |
599 | struct file *fp; | |
d2cba8de | 600 | struct mbuf *m = NULL; |
66f52238 | 601 | |
88a7a62a | 602 | fp = getsock(uap->s); |
66f52238 SL |
603 | if (fp == 0) |
604 | return; | |
66f52238 SL |
605 | if (uap->valsize > MLEN) { |
606 | u.u_error = EINVAL; | |
607 | return; | |
608 | } | |
d2cba8de SL |
609 | if (uap->val) { |
610 | m = m_get(M_WAIT, MT_SOOPTS); | |
7c52d753 | 611 | if (m == NULL) { |
d2cba8de SL |
612 | u.u_error = ENOBUFS; |
613 | return; | |
614 | } | |
88a7a62a SL |
615 | u.u_error = |
616 | copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); | |
61ec2127 SL |
617 | if (u.u_error) { |
618 | (void) m_free(m); | |
619 | return; | |
620 | } | |
d2cba8de | 621 | m->m_len = uap->valsize; |
66f52238 | 622 | } |
88a7a62a SL |
623 | u.u_error = |
624 | sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m); | |
66f52238 SL |
625 | } |
626 | ||
627 | getsockopt() | |
628 | { | |
629 | struct a { | |
630 | int s; | |
631 | int level; | |
632 | int name; | |
633 | caddr_t val; | |
634 | int *avalsize; | |
635 | } *uap = (struct a *)u.u_ap; | |
636 | struct file *fp; | |
d2cba8de | 637 | struct mbuf *m = NULL; |
66f52238 SL |
638 | int valsize; |
639 | ||
88a7a62a | 640 | fp = getsock(uap->s); |
66f52238 SL |
641 | if (fp == 0) |
642 | return; | |
d2cba8de SL |
643 | if (uap->val) { |
644 | u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, | |
645 | sizeof (valsize)); | |
646 | if (u.u_error) | |
647 | return; | |
61ec2127 SL |
648 | } else |
649 | valsize = 0; | |
88a7a62a | 650 | u.u_error = |
61ec2127 | 651 | sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m); |
66f52238 SL |
652 | if (u.u_error) |
653 | goto bad; | |
61ec2127 | 654 | if (uap->val && valsize && m != NULL) { |
d2cba8de SL |
655 | if (valsize > m->m_len) |
656 | valsize = m->m_len; | |
657 | u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); | |
658 | if (u.u_error) | |
659 | goto bad; | |
660 | u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, | |
661 | sizeof (valsize)); | |
662 | } | |
66f52238 | 663 | bad: |
d2cba8de SL |
664 | if (m != NULL) |
665 | (void) m_free(m); | |
66f52238 SL |
666 | } |
667 | ||
cf012934 BJ |
668 | pipe() |
669 | { | |
670 | register struct file *rf, *wf; | |
671 | struct socket *rso, *wso; | |
672 | int r; | |
673 | ||
88a7a62a | 674 | u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0); |
2b4b57cd BJ |
675 | if (u.u_error) |
676 | return; | |
88a7a62a | 677 | u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0); |
cf012934 BJ |
678 | if (u.u_error) |
679 | goto free; | |
680 | rf = falloc(); | |
681 | if (rf == NULL) | |
682 | goto free2; | |
683 | r = u.u_r.r_val1; | |
684 | rf->f_flag = FREAD; | |
685 | rf->f_type = DTYPE_SOCKET; | |
88a7a62a SL |
686 | rf->f_ops = &socketops; |
687 | rf->f_data = (caddr_t)rso; | |
cf012934 BJ |
688 | wf = falloc(); |
689 | if (wf == NULL) | |
690 | goto free3; | |
691 | wf->f_flag = FWRITE; | |
692 | wf->f_type = DTYPE_SOCKET; | |
88a7a62a SL |
693 | wf->f_ops = &socketops; |
694 | wf->f_data = (caddr_t)wso; | |
cf012934 BJ |
695 | u.u_r.r_val2 = u.u_r.r_val1; |
696 | u.u_r.r_val1 = r; | |
d97afdcc | 697 | if (u.u_error = unp_connect2(wso, rso)) |
cf012934 | 698 | goto free4; |
9c58d471 MK |
699 | wso->so_state |= SS_CANTRCVMORE; |
700 | rso->so_state |= SS_CANTSENDMORE; | |
cf012934 BJ |
701 | return; |
702 | free4: | |
703 | wf->f_count = 0; | |
704 | u.u_ofile[u.u_r.r_val2] = 0; | |
705 | free3: | |
706 | rf->f_count = 0; | |
707 | u.u_ofile[r] = 0; | |
708 | free2: | |
8011f5df | 709 | (void)soclose(wso); |
cf012934 | 710 | free: |
8011f5df | 711 | (void)soclose(rso); |
cc15ab5d | 712 | } |
a3076b07 BJ |
713 | |
714 | /* | |
70f2eac5 | 715 | * Get socket name. |
a3076b07 | 716 | */ |
70f2eac5 | 717 | getsockname() |
a3076b07 BJ |
718 | { |
719 | register struct a { | |
720 | int fdes; | |
70f2eac5 SL |
721 | caddr_t asa; |
722 | int *alen; | |
a3076b07 BJ |
723 | } *uap = (struct a *)u.u_ap; |
724 | register struct file *fp; | |
05d69517 | 725 | register struct socket *so; |
cf012934 | 726 | struct mbuf *m; |
70f2eac5 | 727 | int len; |
a3076b07 | 728 | |
88a7a62a | 729 | fp = getsock(uap->fdes); |
a3076b07 BJ |
730 | if (fp == 0) |
731 | return; | |
70f2eac5 SL |
732 | u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); |
733 | if (u.u_error) | |
734 | return; | |
88a7a62a | 735 | so = (struct socket *)fp->f_data; |
cce93e4b | 736 | m = m_getclr(M_WAIT, MT_SONAME); |
7c52d753 SL |
737 | if (m == NULL) { |
738 | u.u_error = ENOBUFS; | |
739 | return; | |
740 | } | |
70f2eac5 SL |
741 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); |
742 | if (u.u_error) | |
743 | goto bad; | |
744 | if (len > m->m_len) | |
745 | len = m->m_len; | |
746 | u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); | |
05d69517 | 747 | if (u.u_error) |
cf012934 | 748 | goto bad; |
70f2eac5 | 749 | u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); |
cf012934 BJ |
750 | bad: |
751 | m_freem(m); | |
752 | } | |
753 | ||
a7343092 SL |
754 | /* |
755 | * Get name of peer for connected socket. | |
756 | */ | |
757 | getpeername() | |
758 | { | |
759 | register struct a { | |
760 | int fdes; | |
761 | caddr_t asa; | |
762 | int *alen; | |
763 | } *uap = (struct a *)u.u_ap; | |
764 | register struct file *fp; | |
765 | register struct socket *so; | |
766 | struct mbuf *m; | |
767 | int len; | |
768 | ||
769 | fp = getsock(uap->fdes); | |
770 | if (fp == 0) | |
771 | return; | |
772 | so = (struct socket *)fp->f_data; | |
773 | if ((so->so_state & SS_ISCONNECTED) == 0) { | |
774 | u.u_error = ENOTCONN; | |
775 | return; | |
776 | } | |
777 | m = m_getclr(M_WAIT, MT_SONAME); | |
778 | if (m == NULL) { | |
779 | u.u_error = ENOBUFS; | |
780 | return; | |
781 | } | |
782 | u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); | |
783 | if (u.u_error) | |
784 | return; | |
785 | u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); | |
786 | if (u.u_error) | |
787 | goto bad; | |
788 | if (len > m->m_len) | |
789 | len = m->m_len; | |
790 | u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); | |
791 | if (u.u_error) | |
792 | goto bad; | |
793 | u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); | |
794 | bad: | |
795 | m_freem(m); | |
796 | } | |
797 | ||
98447d3f | 798 | sockargs(aname, name, namelen, type) |
cf012934 BJ |
799 | struct mbuf **aname; |
800 | caddr_t name; | |
98447d3f | 801 | int namelen, type; |
cf012934 BJ |
802 | { |
803 | register struct mbuf *m; | |
127f7d76 | 804 | int error; |
cf012934 BJ |
805 | |
806 | if (namelen > MLEN) | |
807 | return (EINVAL); | |
98447d3f | 808 | m = m_get(M_WAIT, type); |
7c52d753 SL |
809 | if (m == NULL) |
810 | return (ENOBUFS); | |
cf012934 | 811 | m->m_len = namelen; |
127f7d76 SL |
812 | error = copyin(name, mtod(m, caddr_t), (u_int)namelen); |
813 | if (error) | |
cf012934 | 814 | (void) m_free(m); |
127f7d76 SL |
815 | else |
816 | *aname = m; | |
817 | return (error); | |
cf012934 | 818 | } |
88a7a62a SL |
819 | |
820 | struct file * | |
821 | getsock(fdes) | |
822 | int fdes; | |
823 | { | |
824 | register struct file *fp; | |
825 | ||
826 | fp = getf(fdes); | |
827 | if (fp == NULL) | |
828 | return (0); | |
829 | if (fp->f_type != DTYPE_SOCKET) { | |
830 | u.u_error = ENOTSOCK; | |
831 | return (0); | |
832 | } | |
833 | return (fp); | |
834 | } |