uipc_syscalls.c revision 1.71 1 /* $NetBSD: uipc_syscalls.c,v 1.71 2002/10/23 09:14:29 jdolecek Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)uipc_syscalls.c 8.6 (Berkeley) 2/14/95
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.71 2002/10/23 09:14:29 jdolecek Exp $");
40
41 #include "opt_ktrace.h"
42 #include "opt_pipe.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/filedesc.h>
47 #include <sys/proc.h>
48 #include <sys/file.h>
49 #include <sys/buf.h>
50 #include <sys/malloc.h>
51 #include <sys/mbuf.h>
52 #include <sys/protosw.h>
53 #include <sys/socket.h>
54 #include <sys/socketvar.h>
55 #include <sys/signalvar.h>
56 #include <sys/un.h>
57 #ifdef KTRACE
58 #include <sys/ktrace.h>
59 #endif
60 #include <sys/event.h>
61
62 #include <sys/mount.h>
63 #include <sys/syscallargs.h>
64
65 #include <uvm/uvm_extern.h>
66
67 /*
68 * System call interface to the socket abstraction.
69 */
70 extern struct fileops socketops;
71
72 int
73 sys_socket(struct proc *p, void *v, register_t *retval)
74 {
75 struct sys_socket_args /* {
76 syscallarg(int) domain;
77 syscallarg(int) type;
78 syscallarg(int) protocol;
79 } */ *uap = v;
80 struct filedesc *fdp;
81 struct socket *so;
82 struct file *fp;
83 int fd, error;
84
85 fdp = p->p_fd;
86 /* falloc() will use the desciptor for us */
87 if ((error = falloc(p, &fp, &fd)) != 0)
88 return (error);
89 fp->f_flag = FREAD|FWRITE;
90 fp->f_type = DTYPE_SOCKET;
91 fp->f_ops = &socketops;
92 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
93 SCARG(uap, protocol));
94 if (error) {
95 FILE_UNUSE(fp, p);
96 fdremove(fdp, fd);
97 ffree(fp);
98 } else {
99 fp->f_data = (caddr_t)so;
100 FILE_SET_MATURE(fp);
101 FILE_UNUSE(fp, p);
102 *retval = fd;
103 }
104 return (error);
105 }
106
107 /* ARGSUSED */
108 int
109 sys_bind(struct proc *p, void *v, register_t *retval)
110 {
111 struct sys_bind_args /* {
112 syscallarg(int) s;
113 syscallarg(const struct sockaddr *) name;
114 syscallarg(unsigned int) namelen;
115 } */ *uap = v;
116 struct file *fp;
117 struct mbuf *nam;
118 int error;
119
120 /* getsock() will use the descriptor for us */
121 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
122 return (error);
123 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
124 MT_SONAME);
125 if (error) {
126 FILE_UNUSE(fp, p);
127 return (error);
128 }
129 error = sobind((struct socket *)fp->f_data, nam, p);
130 m_freem(nam);
131 FILE_UNUSE(fp, p);
132 return (error);
133 }
134
135 /* ARGSUSED */
136 int
137 sys_listen(struct proc *p, void *v, register_t *retval)
138 {
139 struct sys_listen_args /* {
140 syscallarg(int) s;
141 syscallarg(int) backlog;
142 } */ *uap = v;
143 struct file *fp;
144 int error;
145
146 /* getsock() will use the descriptor for us */
147 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
148 return (error);
149 error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog));
150 FILE_UNUSE(fp, p);
151 return (error);
152 }
153
154 int
155 sys_accept(struct proc *p, void *v, register_t *retval)
156 {
157 struct sys_accept_args /* {
158 syscallarg(int) s;
159 syscallarg(struct sockaddr *) name;
160 syscallarg(unsigned int *) anamelen;
161 } */ *uap = v;
162 struct filedesc *fdp;
163 struct file *fp;
164 struct mbuf *nam;
165 unsigned int namelen;
166 int error, s, fd;
167 struct socket *so;
168
169 fdp = p->p_fd;
170 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
171 (caddr_t)&namelen, sizeof(namelen))))
172 return (error);
173 if (SCARG(uap, name) != NULL &&
174 uvm_useracc((caddr_t)SCARG(uap, name), sizeof(struct sockaddr),
175 B_WRITE) == FALSE)
176 return (EFAULT);
177
178 /* getsock() will use the descriptor for us */
179 if ((error = getsock(fdp, SCARG(uap, s), &fp)) != 0)
180 return (error);
181 s = splsoftnet();
182 so = (struct socket *)fp->f_data;
183 FILE_UNUSE(fp, p);
184 if (!(so->so_proto->pr_flags & PR_LISTEN)) {
185 splx(s);
186 return (EOPNOTSUPP);
187 }
188 if ((so->so_options & SO_ACCEPTCONN) == 0) {
189 splx(s);
190 return (EINVAL);
191 }
192 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
193 splx(s);
194 return (EWOULDBLOCK);
195 }
196 while (so->so_qlen == 0 && so->so_error == 0) {
197 if (so->so_state & SS_CANTRCVMORE) {
198 so->so_error = ECONNABORTED;
199 break;
200 }
201 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
202 netcon, 0);
203 if (error) {
204 splx(s);
205 return (error);
206 }
207 }
208 if (so->so_error) {
209 error = so->so_error;
210 so->so_error = 0;
211 splx(s);
212 return (error);
213 }
214 /* falloc() will use the descriptor for us */
215 if ((error = falloc(p, &fp, &fd)) != 0) {
216 splx(s);
217 return (error);
218 }
219 *retval = fd;
220
221 /* connection has been removed from the listen queue */
222 KNOTE(&so->so_rcv.sb_sel.si_klist, 0);
223
224 { struct socket *aso = TAILQ_FIRST(&so->so_q);
225 if (soqremque(aso, 1) == 0)
226 panic("accept");
227 so = aso;
228 }
229 fp->f_type = DTYPE_SOCKET;
230 fp->f_flag = FREAD|FWRITE;
231 fp->f_ops = &socketops;
232 fp->f_data = (caddr_t)so;
233 FILE_UNUSE(fp, p);
234 nam = m_get(M_WAIT, MT_SONAME);
235 if ((error = soaccept(so, nam)) == 0 && SCARG(uap, name)) {
236 if (namelen > nam->m_len)
237 namelen = nam->m_len;
238 /* SHOULD COPY OUT A CHAIN HERE */
239 if ((error = copyout(mtod(nam, caddr_t),
240 (caddr_t)SCARG(uap, name), namelen)) == 0)
241 error = copyout((caddr_t)&namelen,
242 (caddr_t)SCARG(uap, anamelen),
243 sizeof(*SCARG(uap, anamelen)));
244 }
245 /* if an error occurred, free the file descriptor */
246 if (error) {
247 fdremove(fdp, fd);
248 ffree(fp);
249 }
250 m_freem(nam);
251 splx(s);
252 FILE_SET_MATURE(fp);
253 return (error);
254 }
255
256 /* ARGSUSED */
257 int
258 sys_connect(struct proc *p, void *v, register_t *retval)
259 {
260 struct sys_connect_args /* {
261 syscallarg(int) s;
262 syscallarg(const struct sockaddr *) name;
263 syscallarg(unsigned int) namelen;
264 } */ *uap = v;
265 struct file *fp;
266 struct socket *so;
267 struct mbuf *nam;
268 int error, s;
269
270 /* getsock() will use the descriptor for us */
271 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
272 return (error);
273 so = (struct socket *)fp->f_data;
274 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
275 error = EALREADY;
276 goto out;
277 }
278 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
279 MT_SONAME);
280 if (error)
281 goto out;
282 error = soconnect(so, nam);
283 if (error)
284 goto bad;
285 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
286 m_freem(nam);
287 error = EINPROGRESS;
288 goto out;
289 }
290 s = splsoftnet();
291 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
292 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
293 netcon, 0);
294 if (error)
295 break;
296 }
297 if (error == 0) {
298 error = so->so_error;
299 so->so_error = 0;
300 }
301 splx(s);
302 bad:
303 so->so_state &= ~SS_ISCONNECTING;
304 m_freem(nam);
305 if (error == ERESTART)
306 error = EINTR;
307 out:
308 FILE_UNUSE(fp, p);
309 return (error);
310 }
311
312 int
313 sys_socketpair(struct proc *p, void *v, register_t *retval)
314 {
315 struct sys_socketpair_args /* {
316 syscallarg(int) domain;
317 syscallarg(int) type;
318 syscallarg(int) protocol;
319 syscallarg(int *) rsv;
320 } */ *uap = v;
321 struct filedesc *fdp;
322 struct file *fp1, *fp2;
323 struct socket *so1, *so2;
324 int fd, error, sv[2];
325
326 fdp = p->p_fd;
327 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
328 SCARG(uap, protocol));
329 if (error)
330 return (error);
331 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
332 SCARG(uap, protocol));
333 if (error)
334 goto free1;
335 /* falloc() will use the descriptor for us */
336 if ((error = falloc(p, &fp1, &fd)) != 0)
337 goto free2;
338 sv[0] = fd;
339 fp1->f_flag = FREAD|FWRITE;
340 fp1->f_type = DTYPE_SOCKET;
341 fp1->f_ops = &socketops;
342 fp1->f_data = (caddr_t)so1;
343 if ((error = falloc(p, &fp2, &fd)) != 0)
344 goto free3;
345 fp2->f_flag = FREAD|FWRITE;
346 fp2->f_type = DTYPE_SOCKET;
347 fp2->f_ops = &socketops;
348 fp2->f_data = (caddr_t)so2;
349 sv[1] = fd;
350 if ((error = soconnect2(so1, so2)) != 0)
351 goto free4;
352 if (SCARG(uap, type) == SOCK_DGRAM) {
353 /*
354 * Datagram socket connection is asymmetric.
355 */
356 if ((error = soconnect2(so2, so1)) != 0)
357 goto free4;
358 }
359 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
360 2 * sizeof(int));
361 FILE_SET_MATURE(fp1);
362 FILE_SET_MATURE(fp2);
363 FILE_UNUSE(fp1, p);
364 FILE_UNUSE(fp2, p);
365 return (error);
366 free4:
367 FILE_UNUSE(fp2, p);
368 ffree(fp2);
369 fdremove(fdp, sv[1]);
370 free3:
371 FILE_UNUSE(fp1, p);
372 ffree(fp1);
373 fdremove(fdp, sv[0]);
374 free2:
375 (void)soclose(so2);
376 free1:
377 (void)soclose(so1);
378 return (error);
379 }
380
381 int
382 sys_sendto(struct proc *p, void *v, register_t *retval)
383 {
384 struct sys_sendto_args /* {
385 syscallarg(int) s;
386 syscallarg(const void *) buf;
387 syscallarg(size_t) len;
388 syscallarg(int) flags;
389 syscallarg(const struct sockaddr *) to;
390 syscallarg(unsigned int) tolen;
391 } */ *uap = v;
392 struct msghdr msg;
393 struct iovec aiov;
394
395 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
396 msg.msg_namelen = SCARG(uap, tolen);
397 msg.msg_iov = &aiov;
398 msg.msg_iovlen = 1;
399 msg.msg_control = 0;
400 msg.msg_flags = 0;
401 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
402 aiov.iov_len = SCARG(uap, len);
403 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
404 }
405
406 int
407 sys_sendmsg(struct proc *p, void *v, register_t *retval)
408 {
409 struct sys_sendmsg_args /* {
410 syscallarg(int) s;
411 syscallarg(const struct msghdr *) msg;
412 syscallarg(int) flags;
413 } */ *uap = v;
414 struct msghdr msg;
415 struct iovec aiov[UIO_SMALLIOV], *iov;
416 int error;
417
418 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
419 if (error)
420 return (error);
421 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
422 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
423 return (EMSGSIZE);
424 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
425 M_IOV, M_WAITOK);
426 } else
427 iov = aiov;
428 if ((unsigned int)msg.msg_iovlen > 0) {
429 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
430 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
431 if (error)
432 goto done;
433 }
434 msg.msg_iov = iov;
435 msg.msg_flags = 0;
436 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
437 done:
438 if (iov != aiov)
439 free(iov, M_IOV);
440 return (error);
441 }
442
443 int
444 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
445 {
446 struct file *fp;
447 struct uio auio;
448 struct iovec *iov;
449 int i, len, error;
450 struct mbuf *to, *control;
451 struct socket *so;
452 #ifdef KTRACE
453 struct iovec *ktriov;
454 #endif
455
456 #ifdef KTRACE
457 ktriov = NULL;
458 #endif
459 /* getsock() will use the descriptor for us */
460 if ((error = getsock(p->p_fd, s, &fp)) != 0)
461 return (error);
462 auio.uio_iov = mp->msg_iov;
463 auio.uio_iovcnt = mp->msg_iovlen;
464 auio.uio_segflg = UIO_USERSPACE;
465 auio.uio_rw = UIO_WRITE;
466 auio.uio_procp = p;
467 auio.uio_offset = 0; /* XXX */
468 auio.uio_resid = 0;
469 iov = mp->msg_iov;
470 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
471 #if 0
472 /* cannot happen; iov_len is unsigned */
473 if (iov->iov_len < 0) {
474 error = EINVAL;
475 goto out;
476 }
477 #endif
478 /*
479 * Writes return ssize_t because -1 is returned on error.
480 * Therefore, we must restrict the length to SSIZE_MAX to
481 * avoid garbage return values.
482 */
483 auio.uio_resid += iov->iov_len;
484 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
485 error = EINVAL;
486 goto out;
487 }
488 }
489 if (mp->msg_name) {
490 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
491 MT_SONAME);
492 if (error)
493 goto out;
494 } else
495 to = 0;
496 if (mp->msg_control) {
497 if (mp->msg_controllen < sizeof(struct cmsghdr)) {
498 error = EINVAL;
499 goto bad;
500 }
501 error = sockargs(&control, mp->msg_control,
502 mp->msg_controllen, MT_CONTROL);
503 if (error)
504 goto bad;
505 } else
506 control = 0;
507 #ifdef KTRACE
508 if (KTRPOINT(p, KTR_GENIO)) {
509 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
510
511 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
512 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
513 }
514 #endif
515 len = auio.uio_resid;
516 so = (struct socket *)fp->f_data;
517 error = (*so->so_send)(so, to, &auio, NULL, control, flags);
518 if (error) {
519 if (auio.uio_resid != len && (error == ERESTART ||
520 error == EINTR || error == EWOULDBLOCK))
521 error = 0;
522 if (error == EPIPE)
523 psignal(p, SIGPIPE);
524 }
525 if (error == 0)
526 *retsize = len - auio.uio_resid;
527 #ifdef KTRACE
528 if (ktriov != NULL) {
529 if (error == 0)
530 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error);
531 free(ktriov, M_TEMP);
532 }
533 #endif
534 bad:
535 if (to)
536 m_freem(to);
537 out:
538 FILE_UNUSE(fp, p);
539 return (error);
540 }
541
542 int
543 sys_recvfrom(struct proc *p, void *v, register_t *retval)
544 {
545 struct sys_recvfrom_args /* {
546 syscallarg(int) s;
547 syscallarg(void *) buf;
548 syscallarg(size_t) len;
549 syscallarg(int) flags;
550 syscallarg(struct sockaddr *) from;
551 syscallarg(unsigned int *) fromlenaddr;
552 } */ *uap = v;
553 struct msghdr msg;
554 struct iovec aiov;
555 int error;
556
557 if (SCARG(uap, fromlenaddr)) {
558 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
559 (caddr_t)&msg.msg_namelen,
560 sizeof(msg.msg_namelen));
561 if (error)
562 return (error);
563 } else
564 msg.msg_namelen = 0;
565 msg.msg_name = (caddr_t)SCARG(uap, from);
566 msg.msg_iov = &aiov;
567 msg.msg_iovlen = 1;
568 aiov.iov_base = SCARG(uap, buf);
569 aiov.iov_len = SCARG(uap, len);
570 msg.msg_control = 0;
571 msg.msg_flags = SCARG(uap, flags);
572 return (recvit(p, SCARG(uap, s), &msg,
573 (caddr_t)SCARG(uap, fromlenaddr), retval));
574 }
575
576 int
577 sys_recvmsg(struct proc *p, void *v, register_t *retval)
578 {
579 struct sys_recvmsg_args /* {
580 syscallarg(int) s;
581 syscallarg(struct msghdr *) msg;
582 syscallarg(int) flags;
583 } */ *uap = v;
584 struct msghdr msg;
585 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
586 int error;
587
588 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
589 sizeof(msg));
590 if (error)
591 return (error);
592 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
593 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
594 return (EMSGSIZE);
595 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
596 M_IOV, M_WAITOK);
597 } else
598 iov = aiov;
599 if ((unsigned int)msg.msg_iovlen > 0) {
600 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
601 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
602 if (error)
603 goto done;
604 }
605 uiov = msg.msg_iov;
606 msg.msg_iov = iov;
607 msg.msg_flags = SCARG(uap, flags);
608 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
609 msg.msg_iov = uiov;
610 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
611 sizeof(msg));
612 }
613 done:
614 if (iov != aiov)
615 free(iov, M_IOV);
616 return (error);
617 }
618
619 int
620 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp,
621 register_t *retsize)
622 {
623 struct file *fp;
624 struct uio auio;
625 struct iovec *iov;
626 int i, len, error;
627 struct mbuf *from, *control;
628 struct socket *so;
629 #ifdef KTRACE
630 struct iovec *ktriov;
631 #endif
632
633 from = 0;
634 control = 0;
635 #ifdef KTRACE
636 ktriov = NULL;
637 #endif
638
639 /* getsock() will use the descriptor for us */
640 if ((error = getsock(p->p_fd, s, &fp)) != 0)
641 return (error);
642 auio.uio_iov = mp->msg_iov;
643 auio.uio_iovcnt = mp->msg_iovlen;
644 auio.uio_segflg = UIO_USERSPACE;
645 auio.uio_rw = UIO_READ;
646 auio.uio_procp = p;
647 auio.uio_offset = 0; /* XXX */
648 auio.uio_resid = 0;
649 iov = mp->msg_iov;
650 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
651 #if 0
652 /* cannot happen iov_len is unsigned */
653 if (iov->iov_len < 0) {
654 error = EINVAL;
655 goto out1;
656 }
657 #endif
658 /*
659 * Reads return ssize_t because -1 is returned on error.
660 * Therefore we must restrict the length to SSIZE_MAX to
661 * avoid garbage return values.
662 */
663 auio.uio_resid += iov->iov_len;
664 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
665 error = EINVAL;
666 goto out1;
667 }
668 }
669 #ifdef KTRACE
670 if (KTRPOINT(p, KTR_GENIO)) {
671 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
672
673 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
674 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
675 }
676 #endif
677 len = auio.uio_resid;
678 so = (struct socket *)fp->f_data;
679 error = (*so->so_receive)(so, &from, &auio, NULL,
680 mp->msg_control ? &control : NULL, &mp->msg_flags);
681 if (error) {
682 if (auio.uio_resid != len && (error == ERESTART ||
683 error == EINTR || error == EWOULDBLOCK))
684 error = 0;
685 }
686 #ifdef KTRACE
687 if (ktriov != NULL) {
688 if (error == 0)
689 ktrgenio(p, s, UIO_READ, ktriov,
690 len - auio.uio_resid, error);
691 free(ktriov, M_TEMP);
692 }
693 #endif
694 if (error)
695 goto out;
696 *retsize = len - auio.uio_resid;
697 if (mp->msg_name) {
698 len = mp->msg_namelen;
699 if (len <= 0 || from == 0)
700 len = 0;
701 else {
702 if (len > from->m_len)
703 len = from->m_len;
704 /* else if len < from->m_len ??? */
705 error = copyout(mtod(from, caddr_t),
706 (caddr_t)mp->msg_name, (unsigned)len);
707 if (error)
708 goto out;
709 }
710 mp->msg_namelen = len;
711 if (namelenp &&
712 (error = copyout((caddr_t)&len, namelenp, sizeof(int))))
713 goto out;
714 }
715 if (mp->msg_control) {
716 len = mp->msg_controllen;
717 if (len <= 0 || control == 0)
718 len = 0;
719 else {
720 struct mbuf *m = control;
721 caddr_t p = (caddr_t)mp->msg_control;
722
723 do {
724 i = m->m_len;
725 if (len < i) {
726 mp->msg_flags |= MSG_CTRUNC;
727 i = len;
728 }
729 error = copyout(mtod(m, caddr_t), p,
730 (unsigned)i);
731 if (m->m_next)
732 i = ALIGN(i);
733 p += i;
734 len -= i;
735 if (error != 0 || len <= 0)
736 break;
737 } while ((m = m->m_next) != NULL);
738 len = p - (caddr_t)mp->msg_control;
739 }
740 mp->msg_controllen = len;
741 }
742 out:
743 if (from)
744 m_freem(from);
745 if (control)
746 m_freem(control);
747 out1:
748 FILE_UNUSE(fp, p);
749 return (error);
750 }
751
752 /* ARGSUSED */
753 int
754 sys_shutdown(struct proc *p, void *v, register_t *retval)
755 {
756 struct sys_shutdown_args /* {
757 syscallarg(int) s;
758 syscallarg(int) how;
759 } */ *uap = v;
760 struct file *fp;
761 int error;
762
763 /* getsock() will use the descriptor for us */
764 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
765 return (error);
766 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how));
767 FILE_UNUSE(fp, p);
768 return (error);
769 }
770
771 /* ARGSUSED */
772 int
773 sys_setsockopt(struct proc *p, void *v, register_t *retval)
774 {
775 struct sys_setsockopt_args /* {
776 syscallarg(int) s;
777 syscallarg(int) level;
778 syscallarg(int) name;
779 syscallarg(const void *) val;
780 syscallarg(unsigned int) valsize;
781 } */ *uap = v;
782 struct file *fp;
783 struct mbuf *m;
784 int error;
785 unsigned int l;
786
787 m = NULL;
788 /* getsock() will use the descriptor for us */
789 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
790 return (error);
791 l = SCARG(uap, valsize);
792 if (l > MCLBYTES) {
793 error = EINVAL;
794 goto out;
795 }
796 if (SCARG(uap, val)) {
797 m = m_get(M_WAIT, MT_SOOPTS);
798 if (l > MLEN)
799 MCLGET(m, M_WAIT);
800 error = copyin(SCARG(uap, val), mtod(m, caddr_t), l);
801 if (error) {
802 (void) m_free(m);
803 goto out;
804 }
805 m->m_len = SCARG(uap, valsize);
806 }
807 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
808 SCARG(uap, name), m);
809 out:
810 FILE_UNUSE(fp, p);
811 return (error);
812 }
813
814 /* ARGSUSED */
815 int
816 sys_getsockopt(struct proc *p, void *v, register_t *retval)
817 {
818 struct sys_getsockopt_args /* {
819 syscallarg(int) s;
820 syscallarg(int) level;
821 syscallarg(int) name;
822 syscallarg(void *) val;
823 syscallarg(unsigned int *) avalsize;
824 } */ *uap = v;
825 struct file *fp;
826 struct mbuf *m, *m0;
827 unsigned int op, i, valsize;
828 int error;
829
830 m = NULL;
831 /* getsock() will use the descriptor for us */
832 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
833 return (error);
834 if (SCARG(uap, val)) {
835 error = copyin((caddr_t)SCARG(uap, avalsize),
836 (caddr_t)&valsize, sizeof(valsize));
837 if (error)
838 goto out;
839 } else
840 valsize = 0;
841 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
842 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
843 m != NULL) {
844 op = 0;
845 while (m && !error && op < valsize) {
846 i = min(m->m_len, (valsize - op));
847 error = copyout(mtod(m, caddr_t), SCARG(uap, val), i);
848 op += i;
849 SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i;
850 m0 = m;
851 MFREE(m0, m);
852 }
853 valsize = op;
854 if (error == 0)
855 error = copyout(&valsize,
856 SCARG(uap, avalsize), sizeof(valsize));
857 }
858 if (m != NULL)
859 (void) m_free(m);
860 out:
861 FILE_UNUSE(fp, p);
862 return (error);
863 }
864
865 #ifdef PIPE_SOCKETPAIR
866 /* ARGSUSED */
867 int
868 sys_pipe(struct proc *p, void *v, register_t *retval)
869 {
870 struct filedesc *fdp;
871 struct file *rf, *wf;
872 struct socket *rso, *wso;
873 int fd, error;
874
875 fdp = p->p_fd;
876 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
877 return (error);
878 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
879 goto free1;
880 /* remember this socket pair implements a pipe */
881 wso->so_state |= SS_ISAPIPE;
882 rso->so_state |= SS_ISAPIPE;
883 /* falloc() will use the descriptor for us */
884 if ((error = falloc(p, &rf, &fd)) != 0)
885 goto free2;
886 retval[0] = fd;
887 rf->f_flag = FREAD;
888 rf->f_type = DTYPE_SOCKET;
889 rf->f_ops = &socketops;
890 rf->f_data = (caddr_t)rso;
891 if ((error = falloc(p, &wf, &fd)) != 0)
892 goto free3;
893 wf->f_flag = FWRITE;
894 wf->f_type = DTYPE_SOCKET;
895 wf->f_ops = &socketops;
896 wf->f_data = (caddr_t)wso;
897 retval[1] = fd;
898 if ((error = unp_connect2(wso, rso)) != 0)
899 goto free4;
900 FILE_SET_MATURE(rf);
901 FILE_SET_MATURE(wf);
902 FILE_UNUSE(rf, p);
903 FILE_UNUSE(wf, p);
904 return (0);
905 free4:
906 FILE_UNUSE(wf, p);
907 ffree(wf);
908 fdremove(fdp, retval[1]);
909 free3:
910 FILE_UNUSE(rf, p);
911 ffree(rf);
912 fdremove(fdp, retval[0]);
913 free2:
914 (void)soclose(wso);
915 free1:
916 (void)soclose(rso);
917 return (error);
918 }
919 #endif /* PIPE_SOCKETPAIR */
920
921 /*
922 * Get socket name.
923 */
924 /* ARGSUSED */
925 int
926 sys_getsockname(struct proc *p, void *v, register_t *retval)
927 {
928 struct sys_getsockname_args /* {
929 syscallarg(int) fdes;
930 syscallarg(struct sockaddr *) asa;
931 syscallarg(unsigned int *) alen;
932 } */ *uap = v;
933 struct file *fp;
934 struct socket *so;
935 struct mbuf *m;
936 unsigned int len;
937 int error;
938
939 /* getsock() will use the descriptor for us */
940 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
941 return (error);
942 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
943 if (error)
944 goto out;
945 so = (struct socket *)fp->f_data;
946 m = m_getclr(M_WAIT, MT_SONAME);
947 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
948 m, (struct mbuf *)0, (struct proc *)0);
949 if (error)
950 goto bad;
951 if (len > m->m_len)
952 len = m->m_len;
953 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
954 if (error == 0)
955 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
956 sizeof(len));
957 bad:
958 m_freem(m);
959 out:
960 FILE_UNUSE(fp, p);
961 return (error);
962 }
963
964 /*
965 * Get name of peer for connected socket.
966 */
967 /* ARGSUSED */
968 int
969 sys_getpeername(struct proc *p, void *v, register_t *retval)
970 {
971 struct sys_getpeername_args /* {
972 syscallarg(int) fdes;
973 syscallarg(struct sockaddr *) asa;
974 syscallarg(unsigned int *) alen;
975 } */ *uap = v;
976 struct file *fp;
977 struct socket *so;
978 struct mbuf *m;
979 unsigned int len;
980 int error;
981
982 /* getsock() will use the descriptor for us */
983 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
984 return (error);
985 so = (struct socket *)fp->f_data;
986 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
987 error = ENOTCONN;
988 goto out;
989 }
990 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
991 if (error)
992 goto out;
993 m = m_getclr(M_WAIT, MT_SONAME);
994 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
995 m, (struct mbuf *)0, (struct proc *)0);
996 if (error)
997 goto bad;
998 if (len > m->m_len)
999 len = m->m_len;
1000 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1001 if (error)
1002 goto bad;
1003 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1004 bad:
1005 m_freem(m);
1006 out:
1007 FILE_UNUSE(fp, p);
1008 return (error);
1009 }
1010
1011 /*
1012 * XXX In a perfect world, we wouldn't pass around socket control
1013 * XXX arguments in mbufs, and this could go away.
1014 */
1015 int
1016 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
1017 {
1018 struct sockaddr *sa;
1019 struct mbuf *m;
1020 int error;
1021
1022 /*
1023 * We can't allow socket names > UCHAR_MAX in length, since that
1024 * will overflow sa_len. Control data more than a page size in
1025 * length is just too much.
1026 */
1027 if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
1028 return (EINVAL);
1029
1030 /* Allocate an mbuf to hold the arguments. */
1031 m = m_get(M_WAIT, type);
1032 if (buflen > MLEN) {
1033 /*
1034 * Won't fit into a regular mbuf, so we allocate just
1035 * enough external storage to hold the argument.
1036 */
1037 MEXTMALLOC(m, buflen, M_WAITOK);
1038 }
1039 m->m_len = buflen;
1040 error = copyin(buf, mtod(m, caddr_t), buflen);
1041 if (error) {
1042 (void) m_free(m);
1043 return (error);
1044 }
1045 *mp = m;
1046 if (type == MT_SONAME) {
1047 sa = mtod(m, struct sockaddr *);
1048 #if BYTE_ORDER != BIG_ENDIAN
1049 /*
1050 * 4.3BSD compat thing - need to stay, since bind(2),
1051 * connect(2), sendto(2) were not versioned for COMPAT_43.
1052 */
1053 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1054 sa->sa_family = sa->sa_len;
1055 #endif
1056 sa->sa_len = buflen;
1057 }
1058 return (0);
1059 }
1060
1061 int
1062 getsock(struct filedesc *fdp, int fdes, struct file **fpp)
1063 {
1064 struct file *fp;
1065
1066 if ((fp = fd_getfile(fdp, fdes)) == NULL)
1067 return (EBADF);
1068
1069 FILE_USE(fp);
1070
1071 if (fp->f_type != DTYPE_SOCKET) {
1072 FILE_UNUSE(fp, NULL);
1073 return (ENOTSOCK);
1074 }
1075 *fpp = fp;
1076 return (0);
1077 }
1078