uipc_syscalls.c revision 1.45.2.1 1 /* $NetBSD: uipc_syscalls.c,v 1.45.2.1 2000/11/20 18:09:14 bouyer 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 "opt_ktrace.h"
39 #include "opt_compat_freebsd.h"
40 #include "opt_compat_linux.h"
41 #include "opt_compat_sunos.h"
42 #include "opt_compat_hpux.h"
43 #include "opt_compat_ultrix.h"
44 #include "opt_compat_43.h"
45 #include "opt_compat_osf1.h"
46 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \
47 defined(COMPAT_HPUX) || defined(COMPAT_FREEBSD) || \
48 defined(COMPAT_ULTRIX) || defined(COMPAT_OSF1)
49 #define COMPAT_OLDSOCK /* used by <sys/socket.h> */
50 #endif
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/filedesc.h>
55 #include <sys/proc.h>
56 #include <sys/file.h>
57 #include <sys/buf.h>
58 #include <sys/malloc.h>
59 #include <sys/mbuf.h>
60 #include <sys/protosw.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/signalvar.h>
64 #include <sys/un.h>
65 #ifdef KTRACE
66 #include <sys/ktrace.h>
67 #endif
68
69 #include <sys/mount.h>
70 #include <sys/syscallargs.h>
71
72 #include <uvm/uvm_extern.h>
73
74 /*
75 * System call interface to the socket abstraction.
76 */
77 extern struct fileops socketops;
78
79 int
80 sys_socket(p, v, retval)
81 struct proc *p;
82 void *v;
83 register_t *retval;
84 {
85 struct sys_socket_args /* {
86 syscallarg(int) domain;
87 syscallarg(int) type;
88 syscallarg(int) protocol;
89 } */ *uap = v;
90 struct filedesc *fdp = p->p_fd;
91 struct socket *so;
92 struct file *fp;
93 int fd, error;
94
95 /* falloc() will use the desciptor for us */
96 if ((error = falloc(p, &fp, &fd)) != 0)
97 return (error);
98 fp->f_flag = FREAD|FWRITE;
99 fp->f_type = DTYPE_SOCKET;
100 fp->f_ops = &socketops;
101 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
102 SCARG(uap, protocol));
103 if (error) {
104 FILE_UNUSE(fp, p);
105 fdremove(fdp, fd);
106 ffree(fp);
107 } else {
108 fp->f_data = (caddr_t)so;
109 FILE_UNUSE(fp, p);
110 *retval = fd;
111 }
112 return (error);
113 }
114
115 /* ARGSUSED */
116 int
117 sys_bind(p, v, retval)
118 struct proc *p;
119 void *v;
120 register_t *retval;
121 {
122 struct sys_bind_args /* {
123 syscallarg(int) s;
124 syscallarg(const struct sockaddr *) name;
125 syscallarg(unsigned int) namelen;
126 } */ *uap = v;
127 struct file *fp;
128 struct mbuf *nam;
129 int error;
130
131 /* getsock() will use the descriptor for us */
132 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
133 return (error);
134 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
135 MT_SONAME);
136 if (error) {
137 FILE_UNUSE(fp, p);
138 return (error);
139 }
140 error = sobind((struct socket *)fp->f_data, nam);
141 m_freem(nam);
142 FILE_UNUSE(fp, p);
143 return (error);
144 }
145
146 /* ARGSUSED */
147 int
148 sys_listen(p, v, retval)
149 struct proc *p;
150 void *v;
151 register_t *retval;
152 {
153 struct sys_listen_args /* {
154 syscallarg(int) s;
155 syscallarg(int) backlog;
156 } */ *uap = v;
157 struct file *fp;
158 int error;
159
160 /* getsock() will use the descriptor for us */
161 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
162 return (error);
163 error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog));
164 FILE_UNUSE(fp, p);
165 return (error);
166 }
167
168 int
169 sys_accept(p, v, retval)
170 struct proc *p;
171 void *v;
172 register_t *retval;
173 {
174 struct sys_accept_args /* {
175 syscallarg(int) s;
176 syscallarg(struct sockaddr *) name;
177 syscallarg(unsigned int *) anamelen;
178 } */ *uap = v;
179 struct filedesc *fdp = p->p_fd;
180 struct file *fp;
181 struct mbuf *nam;
182 unsigned int namelen;
183 int error, s, fd;
184 struct socket *so;
185
186 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
187 (caddr_t)&namelen, sizeof(namelen))))
188 return (error);
189 if (SCARG(uap, name) != NULL &&
190 uvm_useracc((caddr_t)SCARG(uap, name), sizeof(struct sockaddr),
191 B_WRITE) == FALSE)
192 return (EFAULT);
193
194 /* getsock() will use the descriptor for us */
195 if ((error = getsock(fdp, SCARG(uap, s), &fp)) != 0)
196 return (error);
197 s = splsoftnet();
198 so = (struct socket *)fp->f_data;
199 FILE_UNUSE(fp, p);
200 if (!(so->so_proto->pr_flags & PR_LISTEN)) {
201 splx(s);
202 return (EOPNOTSUPP);
203 }
204 if ((so->so_options & SO_ACCEPTCONN) == 0) {
205 splx(s);
206 return (EINVAL);
207 }
208 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
209 splx(s);
210 return (EWOULDBLOCK);
211 }
212 while (so->so_qlen == 0 && so->so_error == 0) {
213 if (so->so_state & SS_CANTRCVMORE) {
214 so->so_error = ECONNABORTED;
215 break;
216 }
217 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
218 netcon, 0);
219 if (error) {
220 splx(s);
221 return (error);
222 }
223 }
224 if (so->so_error) {
225 error = so->so_error;
226 so->so_error = 0;
227 splx(s);
228 return (error);
229 }
230 /* falloc() will use the descriptor for us */
231 if ((error = falloc(p, &fp, &fd)) != 0) {
232 splx(s);
233 return (error);
234 }
235 *retval = fd;
236 { struct socket *aso = so->so_q.tqh_first;
237 if (soqremque(aso, 1) == 0)
238 panic("accept");
239 so = aso;
240 }
241 fp->f_type = DTYPE_SOCKET;
242 fp->f_flag = FREAD|FWRITE;
243 fp->f_ops = &socketops;
244 fp->f_data = (caddr_t)so;
245 FILE_UNUSE(fp, p);
246 nam = m_get(M_WAIT, MT_SONAME);
247 if ((error = soaccept(so, nam)) == 0 && SCARG(uap, name)) {
248 if (namelen > nam->m_len)
249 namelen = nam->m_len;
250 /* SHOULD COPY OUT A CHAIN HERE */
251 if ((error = copyout(mtod(nam, caddr_t),
252 (caddr_t)SCARG(uap, name), namelen)) == 0)
253 error = copyout((caddr_t)&namelen,
254 (caddr_t)SCARG(uap, anamelen),
255 sizeof(*SCARG(uap, anamelen)));
256 }
257 /* if an error occured, free the file descriptor */
258 if (error) {
259 fdremove(fdp, fd);
260 ffree(fp);
261 }
262 m_freem(nam);
263 splx(s);
264 return (error);
265 }
266
267 /* ARGSUSED */
268 int
269 sys_connect(p, v, retval)
270 struct proc *p;
271 void *v;
272 register_t *retval;
273 {
274 struct sys_connect_args /* {
275 syscallarg(int) s;
276 syscallarg(const struct sockaddr *) name;
277 syscallarg(unsigned int) namelen;
278 } */ *uap = v;
279 struct file *fp;
280 struct socket *so;
281 struct mbuf *nam;
282 int error, s;
283
284 /* getsock() will use the descriptor for us */
285 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
286 return (error);
287 so = (struct socket *)fp->f_data;
288 FILE_UNUSE(fp, p);
289 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
290 return (EALREADY);
291 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
292 MT_SONAME);
293 if (error)
294 return (error);
295 error = soconnect(so, nam);
296 if (error)
297 goto bad;
298 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
299 m_freem(nam);
300 return (EINPROGRESS);
301 }
302 s = splsoftnet();
303 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
304 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
305 netcon, 0);
306 if (error)
307 break;
308 }
309 if (error == 0) {
310 error = so->so_error;
311 so->so_error = 0;
312 }
313 splx(s);
314 bad:
315 so->so_state &= ~SS_ISCONNECTING;
316 m_freem(nam);
317 if (error == ERESTART)
318 error = EINTR;
319 return (error);
320 }
321
322 int
323 sys_socketpair(p, v, retval)
324 struct proc *p;
325 void *v;
326 register_t *retval;
327 {
328 struct sys_socketpair_args /* {
329 syscallarg(int) domain;
330 syscallarg(int) type;
331 syscallarg(int) protocol;
332 syscallarg(int *) rsv;
333 } */ *uap = v;
334 struct filedesc *fdp = p->p_fd;
335 struct file *fp1, *fp2;
336 struct socket *so1, *so2;
337 int fd, error, sv[2];
338
339 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
340 SCARG(uap, protocol));
341 if (error)
342 return (error);
343 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
344 SCARG(uap, protocol));
345 if (error)
346 goto free1;
347 /* falloc() will use the descriptor for us */
348 if ((error = falloc(p, &fp1, &fd)) != 0)
349 goto free2;
350 sv[0] = fd;
351 fp1->f_flag = FREAD|FWRITE;
352 fp1->f_type = DTYPE_SOCKET;
353 fp1->f_ops = &socketops;
354 fp1->f_data = (caddr_t)so1;
355 if ((error = falloc(p, &fp2, &fd)) != 0)
356 goto free3;
357 fp2->f_flag = FREAD|FWRITE;
358 fp2->f_type = DTYPE_SOCKET;
359 fp2->f_ops = &socketops;
360 fp2->f_data = (caddr_t)so2;
361 sv[1] = fd;
362 if ((error = soconnect2(so1, so2)) != 0)
363 goto free4;
364 if (SCARG(uap, type) == SOCK_DGRAM) {
365 /*
366 * Datagram socket connection is asymmetric.
367 */
368 if ((error = soconnect2(so2, so1)) != 0)
369 goto free4;
370 }
371 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
372 2 * sizeof(int));
373 FILE_UNUSE(fp1, p);
374 FILE_UNUSE(fp2, p);
375 return (error);
376 free4:
377 FILE_UNUSE(fp2, p);
378 ffree(fp2);
379 fdremove(fdp, sv[1]);
380 free3:
381 FILE_UNUSE(fp1, p);
382 ffree(fp1);
383 fdremove(fdp, sv[0]);
384 free2:
385 (void)soclose(so2);
386 free1:
387 (void)soclose(so1);
388 return (error);
389 }
390
391 int
392 sys_sendto(p, v, retval)
393 struct proc *p;
394 void *v;
395 register_t *retval;
396 {
397 struct sys_sendto_args /* {
398 syscallarg(int) s;
399 syscallarg(const void *) buf;
400 syscallarg(size_t) len;
401 syscallarg(int) flags;
402 syscallarg(const struct sockaddr *) to;
403 syscallarg(unsigned int) tolen;
404 } */ *uap = v;
405 struct msghdr msg;
406 struct iovec aiov;
407
408 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */
409 msg.msg_namelen = SCARG(uap, tolen);
410 msg.msg_iov = &aiov;
411 msg.msg_iovlen = 1;
412 msg.msg_control = 0;
413 #ifdef COMPAT_OLDSOCK
414 msg.msg_flags = 0;
415 #endif
416 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */
417 aiov.iov_len = SCARG(uap, len);
418 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
419 }
420
421 int
422 sys_sendmsg(p, v, retval)
423 struct proc *p;
424 void *v;
425 register_t *retval;
426 {
427 struct sys_sendmsg_args /* {
428 syscallarg(int) s;
429 syscallarg(const struct msghdr *) msg;
430 syscallarg(int) flags;
431 } */ *uap = v;
432 struct msghdr msg;
433 struct iovec aiov[UIO_SMALLIOV], *iov;
434 int error;
435
436 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
437 if (error)
438 return (error);
439 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
440 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
441 return (EMSGSIZE);
442 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
443 M_IOV, M_WAITOK);
444 } else
445 iov = aiov;
446 if ((unsigned int)msg.msg_iovlen > 0) {
447 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
448 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
449 if (error)
450 goto done;
451 }
452 msg.msg_iov = iov;
453 #ifdef COMPAT_OLDSOCK
454 msg.msg_flags = 0;
455 #endif
456 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
457 done:
458 if (iov != aiov)
459 free(iov, M_IOV);
460 return (error);
461 }
462
463 int
464 sendit(p, s, mp, flags, retsize)
465 struct proc *p;
466 int s;
467 struct msghdr *mp;
468 int flags;
469 register_t *retsize;
470 {
471 struct file *fp;
472 struct uio auio;
473 struct iovec *iov;
474 int i;
475 struct mbuf *to, *control;
476 int len, error;
477 struct socket *so;
478 #ifdef KTRACE
479 struct iovec *ktriov = NULL;
480 #endif
481
482 /* getsock() will use the descriptor for us */
483 if ((error = getsock(p->p_fd, s, &fp)) != 0)
484 return (error);
485 auio.uio_iov = mp->msg_iov;
486 auio.uio_iovcnt = mp->msg_iovlen;
487 auio.uio_segflg = UIO_USERSPACE;
488 auio.uio_rw = UIO_WRITE;
489 auio.uio_procp = p;
490 auio.uio_offset = 0; /* XXX */
491 auio.uio_resid = 0;
492 iov = mp->msg_iov;
493 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
494 #if 0
495 /* cannot happen; iov_len is unsigned */
496 if (iov->iov_len < 0) {
497 error = EINVAL;
498 goto out;
499 }
500 #endif
501 /*
502 * Writes return ssize_t because -1 is returned on error.
503 * Therefore, we must restrict the length to SSIZE_MAX to
504 * avoid garbage return values.
505 */
506 auio.uio_resid += iov->iov_len;
507 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
508 error = EINVAL;
509 goto out;
510 }
511 }
512 if (mp->msg_name) {
513 error = sockargs(&to, mp->msg_name, mp->msg_namelen,
514 MT_SONAME);
515 if (error)
516 goto out;
517 } else
518 to = 0;
519 if (mp->msg_control) {
520 if (mp->msg_controllen < sizeof(struct cmsghdr)
521 #ifdef COMPAT_OLDSOCK
522 && mp->msg_flags != MSG_COMPAT
523 #endif
524 ) {
525 error = EINVAL;
526 goto bad;
527 }
528 error = sockargs(&control, mp->msg_control,
529 mp->msg_controllen, MT_CONTROL);
530 if (error)
531 goto bad;
532 #ifdef COMPAT_OLDSOCK
533 if (mp->msg_flags == MSG_COMPAT) {
534 struct cmsghdr *cm;
535
536 M_PREPEND(control, sizeof(*cm), M_WAIT);
537 if (control == 0) {
538 error = ENOBUFS;
539 goto bad;
540 } else {
541 cm = mtod(control, struct cmsghdr *);
542 cm->cmsg_len = control->m_len;
543 cm->cmsg_level = SOL_SOCKET;
544 cm->cmsg_type = SCM_RIGHTS;
545 }
546 }
547 #endif
548 } else
549 control = 0;
550 #ifdef KTRACE
551 if (KTRPOINT(p, KTR_GENIO)) {
552 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
553
554 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
555 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
556 }
557 #endif
558 len = auio.uio_resid;
559 so = (struct socket *)fp->f_data;
560 error = (*so->so_send)(so, to, &auio, NULL, control, flags);
561 if (error) {
562 if (auio.uio_resid != len && (error == ERESTART ||
563 error == EINTR || error == EWOULDBLOCK))
564 error = 0;
565 if (error == EPIPE)
566 psignal(p, SIGPIPE);
567 }
568 if (error == 0)
569 *retsize = len - auio.uio_resid;
570 #ifdef KTRACE
571 if (ktriov != NULL) {
572 if (error == 0)
573 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error);
574 free(ktriov, M_TEMP);
575 }
576 #endif
577 bad:
578 if (to)
579 m_freem(to);
580 out:
581 FILE_UNUSE(fp, p);
582 return (error);
583 }
584
585 int
586 sys_recvfrom(p, v, retval)
587 struct proc *p;
588 void *v;
589 register_t *retval;
590 {
591 struct sys_recvfrom_args /* {
592 syscallarg(int) s;
593 syscallarg(void *) buf;
594 syscallarg(size_t) len;
595 syscallarg(int) flags;
596 syscallarg(struct sockaddr *) from;
597 syscallarg(unsigned int *) fromlenaddr;
598 } */ *uap = v;
599 struct msghdr msg;
600 struct iovec aiov;
601 int error;
602
603 if (SCARG(uap, fromlenaddr)) {
604 error = copyin((caddr_t)SCARG(uap, fromlenaddr),
605 (caddr_t)&msg.msg_namelen,
606 sizeof(msg.msg_namelen));
607 if (error)
608 return (error);
609 } else
610 msg.msg_namelen = 0;
611 msg.msg_name = (caddr_t)SCARG(uap, from);
612 msg.msg_iov = &aiov;
613 msg.msg_iovlen = 1;
614 aiov.iov_base = SCARG(uap, buf);
615 aiov.iov_len = SCARG(uap, len);
616 msg.msg_control = 0;
617 msg.msg_flags = SCARG(uap, flags);
618 return (recvit(p, SCARG(uap, s), &msg,
619 (caddr_t)SCARG(uap, fromlenaddr), retval));
620 }
621
622 int
623 sys_recvmsg(p, v, retval)
624 struct proc *p;
625 void *v;
626 register_t *retval;
627 {
628 struct sys_recvmsg_args /* {
629 syscallarg(int) s;
630 syscallarg(struct msghdr *) msg;
631 syscallarg(int) flags;
632 } */ *uap = v;
633 struct msghdr msg;
634 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
635 int error;
636
637 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
638 sizeof(msg));
639 if (error)
640 return (error);
641 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
642 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
643 return (EMSGSIZE);
644 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
645 M_IOV, M_WAITOK);
646 } else
647 iov = aiov;
648 if ((unsigned int)msg.msg_iovlen > 0) {
649 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
650 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
651 if (error)
652 goto done;
653 }
654 uiov = msg.msg_iov;
655 msg.msg_iov = iov;
656 #ifdef COMPAT_OLDSOCK
657 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
658 #else
659 msg.msg_flags = SCARG(uap, flags);
660 #endif
661 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
662 msg.msg_iov = uiov;
663 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
664 sizeof(msg));
665 }
666 done:
667 if (iov != aiov)
668 free(iov, M_IOV);
669 return (error);
670 }
671
672 int
673 recvit(p, s, mp, namelenp, retsize)
674 struct proc *p;
675 int s;
676 struct msghdr *mp;
677 caddr_t namelenp;
678 register_t *retsize;
679 {
680 struct file *fp;
681 struct uio auio;
682 struct iovec *iov;
683 int i;
684 int len, error;
685 struct mbuf *from = 0, *control = 0;
686 struct socket *so;
687 #ifdef KTRACE
688 struct iovec *ktriov = NULL;
689 #endif
690
691 /* getsock() will use the descriptor for us */
692 if ((error = getsock(p->p_fd, s, &fp)) != 0)
693 return (error);
694 auio.uio_iov = mp->msg_iov;
695 auio.uio_iovcnt = mp->msg_iovlen;
696 auio.uio_segflg = UIO_USERSPACE;
697 auio.uio_rw = UIO_READ;
698 auio.uio_procp = p;
699 auio.uio_offset = 0; /* XXX */
700 auio.uio_resid = 0;
701 iov = mp->msg_iov;
702 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
703 #if 0
704 /* cannot happen iov_len is unsigned */
705 if (iov->iov_len < 0) {
706 error = EINVAL;
707 goto out1;
708 }
709 #endif
710 /*
711 * Reads return ssize_t because -1 is returned on error.
712 * Therefore we must restrict the length to SSIZE_MAX to
713 * avoid garbage return values.
714 */
715 auio.uio_resid += iov->iov_len;
716 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
717 error = EINVAL;
718 goto out1;
719 }
720 }
721 #ifdef KTRACE
722 if (KTRPOINT(p, KTR_GENIO)) {
723 int iovlen = auio.uio_iovcnt * sizeof(struct iovec);
724
725 ktriov = malloc(iovlen, M_TEMP, M_WAITOK);
726 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
727 }
728 #endif
729 len = auio.uio_resid;
730 so = (struct socket *)fp->f_data;
731 error = (*so->so_receive)(so, &from, &auio, NULL,
732 mp->msg_control ? &control : NULL, &mp->msg_flags);
733 if (error) {
734 if (auio.uio_resid != len && (error == ERESTART ||
735 error == EINTR || error == EWOULDBLOCK))
736 error = 0;
737 }
738 #ifdef KTRACE
739 if (ktriov != NULL) {
740 if (error == 0)
741 ktrgenio(p, s, UIO_READ, ktriov,
742 len - auio.uio_resid, error);
743 free(ktriov, M_TEMP);
744 }
745 #endif
746 if (error)
747 goto out;
748 *retsize = len - auio.uio_resid;
749 if (mp->msg_name) {
750 len = mp->msg_namelen;
751 if (len <= 0 || from == 0)
752 len = 0;
753 else {
754 #ifdef COMPAT_OLDSOCK
755 if (mp->msg_flags & MSG_COMPAT)
756 mtod(from, struct osockaddr *)->sa_family =
757 mtod(from, struct sockaddr *)->sa_family;
758 #endif
759 if (len > from->m_len)
760 len = from->m_len;
761 /* else if len < from->m_len ??? */
762 error = copyout(mtod(from, caddr_t),
763 (caddr_t)mp->msg_name, (unsigned)len);
764 if (error)
765 goto out;
766 }
767 mp->msg_namelen = len;
768 if (namelenp &&
769 (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) {
770 #ifdef COMPAT_OLDSOCK
771 if (mp->msg_flags & MSG_COMPAT)
772 error = 0; /* old recvfrom didn't check */
773 else
774 #endif
775 goto out;
776 }
777 }
778 if (mp->msg_control) {
779 #ifdef COMPAT_OLDSOCK
780 /*
781 * We assume that old recvmsg calls won't receive access
782 * rights and other control info, esp. as control info
783 * is always optional and those options didn't exist in 4.3.
784 * If we receive rights, trim the cmsghdr; anything else
785 * is tossed.
786 */
787 if (control && mp->msg_flags & MSG_COMPAT) {
788 if (mtod(control, struct cmsghdr *)->cmsg_level !=
789 SOL_SOCKET ||
790 mtod(control, struct cmsghdr *)->cmsg_type !=
791 SCM_RIGHTS) {
792 mp->msg_controllen = 0;
793 goto out;
794 }
795 control->m_len -= sizeof(struct cmsghdr);
796 control->m_data += sizeof(struct cmsghdr);
797 }
798 #endif
799 len = mp->msg_controllen;
800 if (len <= 0 || control == 0)
801 len = 0;
802 else {
803 struct mbuf *m = control;
804 caddr_t p = (caddr_t)mp->msg_control;
805
806 do {
807 i = m->m_len;
808 if (len < i) {
809 mp->msg_flags |= MSG_CTRUNC;
810 i = len;
811 }
812 error = copyout(mtod(m, caddr_t), p,
813 (unsigned)i);
814 if (m->m_next)
815 i = ALIGN(i);
816 p += i;
817 len -= i;
818 if (error != 0 || len <= 0)
819 break;
820 } while ((m = m->m_next) != NULL);
821 len = p - (caddr_t)mp->msg_control;
822 }
823 mp->msg_controllen = len;
824 }
825 out:
826 if (from)
827 m_freem(from);
828 if (control)
829 m_freem(control);
830 out1:
831 FILE_UNUSE(fp, p);
832 return (error);
833 }
834
835 /* ARGSUSED */
836 int
837 sys_shutdown(p, v, retval)
838 struct proc *p;
839 void *v;
840 register_t *retval;
841 {
842 struct sys_shutdown_args /* {
843 syscallarg(int) s;
844 syscallarg(int) how;
845 } */ *uap = v;
846 struct file *fp;
847 int error;
848
849 /* getsock() will use the descriptor for us */
850 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
851 return (error);
852 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how));
853 FILE_UNUSE(fp, p);
854 return (error);
855 }
856
857 /* ARGSUSED */
858 int
859 sys_setsockopt(p, v, retval)
860 struct proc *p;
861 void *v;
862 register_t *retval;
863 {
864 struct sys_setsockopt_args /* {
865 syscallarg(int) s;
866 syscallarg(int) level;
867 syscallarg(int) name;
868 syscallarg(const void *) val;
869 syscallarg(unsigned int) valsize;
870 } */ *uap = v;
871 struct file *fp;
872 struct mbuf *m = NULL;
873 int error;
874
875 /* getsock() will use the descriptor for us */
876 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
877 return (error);
878 if (SCARG(uap, valsize) > MLEN) {
879 error = EINVAL;
880 goto out;
881 }
882 if (SCARG(uap, val)) {
883 m = m_get(M_WAIT, MT_SOOPTS);
884 error = copyin(SCARG(uap, val), mtod(m, caddr_t),
885 SCARG(uap, valsize));
886 if (error) {
887 (void) m_free(m);
888 goto out;
889 }
890 m->m_len = SCARG(uap, valsize);
891 }
892 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
893 SCARG(uap, name), m);
894 out:
895 FILE_UNUSE(fp, p);
896 return (error);
897 }
898
899 /* ARGSUSED */
900 int
901 sys_getsockopt(p, v, retval)
902 struct proc *p;
903 void *v;
904 register_t *retval;
905 {
906 struct sys_getsockopt_args /* {
907 syscallarg(int) s;
908 syscallarg(int) level;
909 syscallarg(int) name;
910 syscallarg(void *) val;
911 syscallarg(unsigned int *) avalsize;
912 } */ *uap = v;
913 struct file *fp;
914 struct mbuf *m = NULL, *m0;
915 unsigned int op, i, valsize;
916 int error;
917
918 /* getsock() will use the descriptor for us */
919 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
920 return (error);
921 if (SCARG(uap, val)) {
922 error = copyin((caddr_t)SCARG(uap, avalsize),
923 (caddr_t)&valsize, sizeof(valsize));
924 if (error)
925 goto out;
926 } else
927 valsize = 0;
928 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
929 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
930 m != NULL) {
931 op = 0;
932 while (m && !error && op < valsize) {
933 i = min(m->m_len, (valsize - op));
934 error = copyout(mtod(m, caddr_t), SCARG(uap, val), i);
935 op += i;
936 SCARG(uap, val) = ((u_int8_t *)SCARG(uap, val)) + i;
937 m0 = m;
938 MFREE(m0, m);
939 }
940 valsize = op;
941 if (error == 0)
942 error = copyout(&valsize,
943 SCARG(uap, avalsize), sizeof(valsize));
944 }
945 if (m != NULL)
946 (void) m_free(m);
947 out:
948 FILE_UNUSE(fp, p);
949 return (error);
950 }
951
952 /* ARGSUSED */
953 int
954 sys_pipe(p, v, retval)
955 struct proc *p;
956 void *v;
957 register_t *retval;
958 {
959 struct filedesc *fdp = p->p_fd;
960 struct file *rf, *wf;
961 struct socket *rso, *wso;
962 int fd, error;
963
964 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0)
965 return (error);
966 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0)
967 goto free1;
968 /* falloc() will use the descriptor for us */
969 if ((error = falloc(p, &rf, &fd)) != 0)
970 goto free2;
971 retval[0] = fd;
972 rf->f_flag = FREAD;
973 rf->f_type = DTYPE_SOCKET;
974 rf->f_ops = &socketops;
975 rf->f_data = (caddr_t)rso;
976 if ((error = falloc(p, &wf, &fd)) != 0)
977 goto free3;
978 wf->f_flag = FWRITE;
979 wf->f_type = DTYPE_SOCKET;
980 wf->f_ops = &socketops;
981 wf->f_data = (caddr_t)wso;
982 retval[1] = fd;
983 if ((error = unp_connect2(wso, rso)) != 0)
984 goto free4;
985 FILE_UNUSE(rf, p);
986 FILE_UNUSE(wf, p);
987 return (0);
988 free4:
989 FILE_UNUSE(wf, p);
990 ffree(wf);
991 fdremove(fdp, retval[1]);
992 free3:
993 FILE_UNUSE(rf, p);
994 ffree(rf);
995 fdremove(fdp, retval[0]);
996 free2:
997 (void)soclose(wso);
998 free1:
999 (void)soclose(rso);
1000 return (error);
1001 }
1002
1003 /*
1004 * Get socket name.
1005 */
1006 /* ARGSUSED */
1007 int
1008 sys_getsockname(p, v, retval)
1009 struct proc *p;
1010 void *v;
1011 register_t *retval;
1012 {
1013 struct sys_getsockname_args /* {
1014 syscallarg(int) fdes;
1015 syscallarg(struct sockaddr *) asa;
1016 syscallarg(unsigned int *) alen;
1017 } */ *uap = v;
1018 struct file *fp;
1019 struct socket *so;
1020 struct mbuf *m;
1021 unsigned int len;
1022 int error;
1023
1024 /* getsock() will use the descriptor for us */
1025 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1026 return (error);
1027 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1028 if (error)
1029 goto out;
1030 so = (struct socket *)fp->f_data;
1031 m = m_getclr(M_WAIT, MT_SONAME);
1032 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0,
1033 m, (struct mbuf *)0, (struct proc *)0);
1034 if (error)
1035 goto bad;
1036 if (len > m->m_len)
1037 len = m->m_len;
1038 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1039 if (error == 0)
1040 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
1041 sizeof(len));
1042 bad:
1043 m_freem(m);
1044 out:
1045 FILE_UNUSE(fp, p);
1046 return (error);
1047 }
1048
1049 /*
1050 * Get name of peer for connected socket.
1051 */
1052 /* ARGSUSED */
1053 int
1054 sys_getpeername(p, v, retval)
1055 struct proc *p;
1056 void *v;
1057 register_t *retval;
1058 {
1059 struct sys_getpeername_args /* {
1060 syscallarg(int) fdes;
1061 syscallarg(struct sockaddr *) asa;
1062 syscallarg(unsigned int *) alen;
1063 } */ *uap = v;
1064 struct file *fp;
1065 struct socket *so;
1066 struct mbuf *m;
1067 unsigned int len;
1068 int error;
1069
1070 /* getsock() will use the descriptor for us */
1071 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0)
1072 return (error);
1073 so = (struct socket *)fp->f_data;
1074 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1075 error = ENOTCONN;
1076 goto out;
1077 }
1078 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len));
1079 if (error)
1080 goto out;
1081 m = m_getclr(M_WAIT, MT_SONAME);
1082 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0,
1083 m, (struct mbuf *)0, (struct proc *)0);
1084 if (error)
1085 goto bad;
1086 if (len > m->m_len)
1087 len = m->m_len;
1088 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len);
1089 if (error)
1090 goto bad;
1091 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len));
1092 bad:
1093 m_freem(m);
1094 out:
1095 FILE_UNUSE(fp, p);
1096 return (error);
1097 }
1098
1099 /*
1100 * XXX In a perfect world, we wouldn't pass around socket control
1101 * XXX arguments in mbufs, and this could go away.
1102 */
1103 int
1104 sockargs(mp, buf, buflen, type)
1105 struct mbuf **mp;
1106 const void *buf;
1107 int buflen, type;
1108 {
1109 struct sockaddr *sa;
1110 struct mbuf *m;
1111 int error;
1112
1113 /*
1114 * We can't allow socket names > UCHAR_MAX in length, since that
1115 * will overflow sa_len.
1116 */
1117 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
1118 return (EINVAL);
1119
1120 /* Allocate an mbuf to hold the arguments. */
1121 m = m_get(M_WAIT, type);
1122 if ((u_int)buflen > MLEN) {
1123 /*
1124 * Won't fit into a regular mbuf, so we allocate just
1125 * enough external storage to hold the argument.
1126 */
1127 MEXTMALLOC(m, buflen, M_WAITOK);
1128 }
1129 m->m_len = buflen;
1130 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1131 if (error) {
1132 (void) m_free(m);
1133 return (error);
1134 }
1135 *mp = m;
1136 if (type == MT_SONAME) {
1137 sa = mtod(m, struct sockaddr *);
1138
1139 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1140 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1141 sa->sa_family = sa->sa_len;
1142 #endif
1143 sa->sa_len = buflen;
1144 }
1145 return (0);
1146 }
1147
1148 int
1149 getsock(fdp, fdes, fpp)
1150 struct filedesc *fdp;
1151 int fdes;
1152 struct file **fpp;
1153 {
1154 struct file *fp;
1155
1156 if ((unsigned)fdes >= fdp->fd_nfiles ||
1157 (fp = fdp->fd_ofiles[fdes]) == NULL ||
1158 (fp->f_iflags & FIF_WANTCLOSE) != 0)
1159 return (EBADF);
1160
1161 FILE_USE(fp);
1162
1163 if (fp->f_type != DTYPE_SOCKET) {
1164 FILE_UNUSE(fp, NULL);
1165 return (ENOTSOCK);
1166 }
1167 *fpp = fp;
1168 return (0);
1169 }
1170