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