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