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