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