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