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