1 /* $OpenBSD: uipc_syscalls.c,v 1.82 2011/07/08 20:54:03 deraadt Exp $ */ 2 /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/filedesc.h> 38 #include <sys/proc.h> 39 #include <sys/file.h> 40 #include <sys/buf.h> 41 #include <sys/malloc.h> 42 #include <sys/event.h> 43 #include <sys/mbuf.h> 44 #include <sys/protosw.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/signalvar.h> 48 #include <sys/unpcb.h> 49 #include <sys/un.h> 50 #ifdef KTRACE 51 #include <sys/ktrace.h> 52 #endif 53 54 #include <sys/mount.h> 55 #include <sys/syscallargs.h> 56 57 #include <net/route.h> 58 59 /* 60 * System call interface to the socket abstraction. 61 */ 62 extern struct fileops socketops; 63 64 int 65 sys_socket(struct proc *p, void *v, register_t *retval) 66 { 67 struct sys_socket_args /* { 68 syscallarg(int) domain; 69 syscallarg(int) type; 70 syscallarg(int) protocol; 71 } */ *uap = v; 72 struct filedesc *fdp = p->p_fd; 73 struct socket *so; 74 struct file *fp; 75 int fd, error; 76 77 fdplock(fdp); 78 79 if ((error = falloc(p, &fp, &fd)) != 0) 80 goto out; 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 fdremove(fdp, fd); 88 closef(fp, p); 89 } else { 90 fp->f_data = so; 91 FILE_SET_MATURE(fp); 92 *retval = fd; 93 } 94 out: 95 fdpunlock(fdp); 96 return (error); 97 } 98 99 /* ARGSUSED */ 100 int 101 sys_bind(struct proc *p, void *v, register_t *retval) 102 { 103 struct sys_bind_args /* { 104 syscallarg(int) s; 105 syscallarg(const struct sockaddr *) name; 106 syscallarg(socklen_t) 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 == 0) { 117 #ifdef KTRACE 118 if (KTRPOINT(p, KTR_STRUCT)) 119 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 120 #endif 121 error = sobind(fp->f_data, nam, p); 122 m_freem(nam); 123 } 124 FRELE(fp); 125 return (error); 126 } 127 128 /* ARGSUSED */ 129 int 130 sys_listen(struct proc *p, void *v, register_t *retval) 131 { 132 struct sys_listen_args /* { 133 syscallarg(int) s; 134 syscallarg(int) backlog; 135 } */ *uap = v; 136 struct file *fp; 137 int error; 138 139 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 140 return (error); 141 error = solisten(fp->f_data, SCARG(uap, backlog)); 142 FRELE(fp); 143 return (error); 144 } 145 146 int 147 sys_accept(struct proc *p, void *v, register_t *retval) 148 { 149 struct sys_accept_args /* { 150 syscallarg(int) s; 151 syscallarg(struct sockaddr *) name; 152 syscallarg(socklen_t *) anamelen; 153 } */ *uap = v; 154 struct file *fp, *headfp; 155 struct mbuf *nam; 156 socklen_t namelen; 157 int error, s, tmpfd; 158 struct socket *head, *so; 159 int nflag; 160 161 if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen), 162 &namelen, sizeof (namelen)))) 163 return (error); 164 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 165 return (error); 166 headfp = fp; 167 s = splsoftnet(); 168 head = fp->f_data; 169 if ((head->so_options & SO_ACCEPTCONN) == 0) { 170 error = EINVAL; 171 goto bad; 172 } 173 if ((head->so_state & SS_NBIO) && head->so_qlen == 0) { 174 if (head->so_state & SS_CANTRCVMORE) 175 error = ECONNABORTED; 176 else 177 error = EWOULDBLOCK; 178 goto bad; 179 } 180 while (head->so_qlen == 0 && head->so_error == 0) { 181 if (head->so_state & SS_CANTRCVMORE) { 182 head->so_error = ECONNABORTED; 183 break; 184 } 185 error = tsleep(&head->so_timeo, PSOCK | PCATCH, "netcon", 0); 186 if (error) { 187 goto bad; 188 } 189 } 190 if (head->so_error) { 191 error = head->so_error; 192 head->so_error = 0; 193 goto bad; 194 } 195 196 /* 197 * At this point we know that there is at least one connection 198 * ready to be accepted. Remove it from the queue prior to 199 * allocating the file descriptor for it since falloc() may 200 * block allowing another process to accept the connection 201 * instead. 202 */ 203 so = TAILQ_FIRST(&head->so_q); 204 if (soqremque(so, 1) == 0) 205 panic("accept"); 206 207 /* Take note if socket was non-blocking. */ 208 nflag = (fp->f_flag & FNONBLOCK); 209 210 fdplock(p->p_fd); 211 if ((error = falloc(p, &fp, &tmpfd)) != 0) { 212 /* 213 * Probably ran out of file descriptors. Put the 214 * unaccepted connection back onto the queue and 215 * do another wakeup so some other process might 216 * have a chance at it. 217 */ 218 soqinsque(head, so, 1); 219 wakeup_one(&head->so_timeo); 220 goto unlock; 221 } 222 *retval = tmpfd; 223 224 /* connection has been removed from the listen queue */ 225 KNOTE(&head->so_rcv.sb_sel.si_note, 0); 226 227 fp->f_type = DTYPE_SOCKET; 228 fp->f_flag = FREAD | FWRITE | nflag; 229 fp->f_ops = &socketops; 230 fp->f_data = so; 231 nam = m_get(M_WAIT, MT_SONAME); 232 error = soaccept(so, nam); 233 if (!error && SCARG(uap, name)) { 234 if (namelen > nam->m_len) 235 namelen = nam->m_len; 236 /* SHOULD COPY OUT A CHAIN HERE */ 237 if ((error = copyout(mtod(nam, caddr_t), 238 SCARG(uap, name), namelen)) == 0) { 239 #ifdef KTRACE 240 if (KTRPOINT(p, KTR_STRUCT)) 241 ktrsockaddr(p, mtod(nam, caddr_t), namelen); 242 #endif 243 error = copyout(&namelen, SCARG(uap, anamelen), 244 sizeof (*SCARG(uap, anamelen))); 245 } 246 } 247 /* if an error occurred, free the file descriptor */ 248 if (error) { 249 fdremove(p->p_fd, tmpfd); 250 closef(fp, p); 251 } else { 252 FILE_SET_MATURE(fp); 253 } 254 m_freem(nam); 255 unlock: 256 fdpunlock(p->p_fd); 257 bad: 258 splx(s); 259 FRELE(headfp); 260 return (error); 261 } 262 263 /* ARGSUSED */ 264 int 265 sys_connect(struct proc *p, void *v, register_t *retval) 266 { 267 struct sys_connect_args /* { 268 syscallarg(int) s; 269 syscallarg(const struct sockaddr *) name; 270 syscallarg(socklen_t) namelen; 271 } */ *uap = v; 272 struct file *fp; 273 struct socket *so; 274 struct mbuf *nam = NULL; 275 int error, s; 276 277 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 278 return (error); 279 so = fp->f_data; 280 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 281 FRELE(fp); 282 return (EALREADY); 283 } 284 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 285 MT_SONAME); 286 if (error) 287 goto bad; 288 #ifdef KTRACE 289 if (KTRPOINT(p, KTR_STRUCT)) 290 ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); 291 #endif 292 error = soconnect(so, nam); 293 if (error) 294 goto bad; 295 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 296 FRELE(fp); 297 m_freem(nam); 298 return (EINPROGRESS); 299 } 300 s = splsoftnet(); 301 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 302 error = tsleep(&so->so_timeo, PSOCK | PCATCH, 303 "netcon2", 0); 304 if (error) 305 break; 306 } 307 if (error == 0) { 308 error = so->so_error; 309 so->so_error = 0; 310 } 311 splx(s); 312 bad: 313 so->so_state &= ~SS_ISCONNECTING; 314 FRELE(fp); 315 if (nam) 316 m_freem(nam); 317 if (error == ERESTART) 318 error = EINTR; 319 return (error); 320 } 321 322 int 323 sys_socketpair(struct proc *p, void *v, register_t *retval) 324 { 325 struct sys_socketpair_args /* { 326 syscallarg(int) domain; 327 syscallarg(int) type; 328 syscallarg(int) protocol; 329 syscallarg(int *) rsv; 330 } */ *uap = v; 331 struct filedesc *fdp = p->p_fd; 332 struct file *fp1, *fp2; 333 struct socket *so1, *so2; 334 int fd, error, sv[2]; 335 336 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 337 SCARG(uap, protocol)); 338 if (error) 339 return (error); 340 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 341 SCARG(uap, protocol)); 342 if (error) 343 goto free1; 344 345 fdplock(fdp); 346 if ((error = falloc(p, &fp1, &fd)) != 0) 347 goto free2; 348 sv[0] = fd; 349 fp1->f_flag = FREAD|FWRITE; 350 fp1->f_type = DTYPE_SOCKET; 351 fp1->f_ops = &socketops; 352 fp1->f_data = so1; 353 if ((error = falloc(p, &fp2, &fd)) != 0) 354 goto free3; 355 fp2->f_flag = FREAD|FWRITE; 356 fp2->f_type = DTYPE_SOCKET; 357 fp2->f_ops = &socketops; 358 fp2->f_data = so2; 359 sv[1] = fd; 360 if ((error = soconnect2(so1, so2)) != 0) 361 goto free4; 362 if (SCARG(uap, type) == SOCK_DGRAM) { 363 /* 364 * Datagram socket connection is asymmetric. 365 */ 366 if ((error = soconnect2(so2, so1)) != 0) 367 goto free4; 368 } 369 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); 370 if (error == 0) { 371 FILE_SET_MATURE(fp1); 372 FILE_SET_MATURE(fp2); 373 fdpunlock(fdp); 374 return (0); 375 } 376 free4: 377 fdremove(fdp, sv[1]); 378 closef(fp2, p); 379 so2 = NULL; 380 free3: 381 fdremove(fdp, sv[0]); 382 closef(fp1, p); 383 so1 = NULL; 384 free2: 385 if (so2 != NULL) 386 (void)soclose(so2); 387 fdpunlock(fdp); 388 free1: 389 if (so1 != NULL) 390 (void)soclose(so1); 391 return (error); 392 } 393 394 int 395 sys_sendto(struct proc *p, void *v, register_t *retval) 396 { 397 struct sys_sendto_args /* { 398 syscallarg(int) s; 399 syscallarg(const void *) buf; 400 syscallarg(size_t) len; 401 syscallarg(int) flags; 402 syscallarg(const struct sockaddr *) to; 403 syscallarg(socklen_t) tolen; 404 } */ *uap = v; 405 struct msghdr msg; 406 struct iovec aiov; 407 408 msg.msg_name = (caddr_t)SCARG(uap, to); 409 msg.msg_namelen = SCARG(uap, tolen); 410 msg.msg_iov = &aiov; 411 msg.msg_iovlen = 1; 412 msg.msg_control = 0; 413 msg.msg_flags = 0; 414 aiov.iov_base = (char *)SCARG(uap, buf); 415 aiov.iov_len = SCARG(uap, len); 416 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 417 } 418 419 int 420 sys_sendmsg(struct proc *p, void *v, register_t *retval) 421 { 422 struct sys_sendmsg_args /* { 423 syscallarg(int) s; 424 syscallarg(const struct msghdr *) msg; 425 syscallarg(int) flags; 426 } */ *uap = v; 427 struct msghdr msg; 428 struct iovec aiov[UIO_SMALLIOV], *iov; 429 int error; 430 431 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 432 if (error) 433 return (error); 434 if (msg.msg_iovlen > IOV_MAX) 435 return (EMSGSIZE); 436 if (msg.msg_iovlen > UIO_SMALLIOV) 437 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen, 438 M_IOV, M_WAITOK); 439 else 440 iov = aiov; 441 if (msg.msg_iovlen && 442 (error = copyin(msg.msg_iov, iov, 443 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 444 goto done; 445 msg.msg_iov = iov; 446 msg.msg_flags = 0; 447 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 448 done: 449 if (iov != aiov) 450 free(iov, M_IOV); 451 return (error); 452 } 453 454 int 455 sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) 456 { 457 struct file *fp; 458 struct uio auio; 459 struct iovec *iov; 460 int i; 461 struct mbuf *to, *control; 462 size_t len; 463 int error; 464 #ifdef KTRACE 465 struct iovec *ktriov = NULL; 466 #endif 467 468 to = NULL; 469 470 if ((error = getsock(p->p_fd, s, &fp)) != 0) 471 return (error); 472 auio.uio_iov = mp->msg_iov; 473 auio.uio_iovcnt = mp->msg_iovlen; 474 auio.uio_segflg = UIO_USERSPACE; 475 auio.uio_rw = UIO_WRITE; 476 auio.uio_procp = p; 477 auio.uio_offset = 0; /* XXX */ 478 auio.uio_resid = 0; 479 iov = mp->msg_iov; 480 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 481 /* Don't allow sum > SSIZE_MAX */ 482 if (iov->iov_len > SSIZE_MAX || 483 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 484 error = EINVAL; 485 goto bad; 486 } 487 } 488 if (mp->msg_name) { 489 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 490 MT_SONAME); 491 if (error) 492 goto bad; 493 #ifdef KTRACE 494 if (KTRPOINT(p, KTR_STRUCT)) 495 ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); 496 #endif 497 } 498 if (mp->msg_control) { 499 if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { 500 error = EINVAL; 501 goto bad; 502 } 503 error = sockargs(&control, mp->msg_control, 504 mp->msg_controllen, MT_CONTROL); 505 if (error) 506 goto bad; 507 } else 508 control = 0; 509 #ifdef KTRACE 510 if (KTRPOINT(p, KTR_GENIO)) { 511 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 512 513 ktriov = malloc(iovlen, M_TEMP, M_WAITOK); 514 bcopy(auio.uio_iov, ktriov, iovlen); 515 } 516 #endif 517 len = auio.uio_resid; 518 error = sosend(fp->f_data, to, &auio, NULL, control, flags); 519 if (error) { 520 if (auio.uio_resid != len && (error == ERESTART || 521 error == EINTR || error == EWOULDBLOCK)) 522 error = 0; 523 if (error == EPIPE) 524 ptsignal(p, SIGPIPE, STHREAD); 525 } 526 if (error == 0) { 527 *retsize = len - auio.uio_resid; 528 fp->f_wxfer++; 529 fp->f_wbytes += *retsize; 530 } 531 #ifdef KTRACE 532 if (ktriov != NULL) { 533 if (error == 0) 534 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error); 535 free(ktriov, M_TEMP); 536 } 537 #endif 538 bad: 539 FRELE(fp); 540 if (to) 541 m_freem(to); 542 return (error); 543 } 544 545 int 546 sys_recvfrom(struct proc *p, void *v, register_t *retval) 547 { 548 struct sys_recvfrom_args /* { 549 syscallarg(int) s; 550 syscallarg(void *) buf; 551 syscallarg(size_t) len; 552 syscallarg(int) flags; 553 syscallarg(struct sockaddr *) from; 554 syscallarg(socklen_t *) fromlenaddr; 555 } */ *uap = v; 556 struct msghdr msg; 557 struct iovec aiov; 558 int error; 559 560 if (SCARG(uap, fromlenaddr)) { 561 error = copyin(SCARG(uap, fromlenaddr), 562 &msg.msg_namelen, sizeof (msg.msg_namelen)); 563 if (error) 564 return (error); 565 } else 566 msg.msg_namelen = 0; 567 msg.msg_name = (caddr_t)SCARG(uap, from); 568 msg.msg_iov = &aiov; 569 msg.msg_iovlen = 1; 570 aiov.iov_base = SCARG(uap, buf); 571 aiov.iov_len = SCARG(uap, len); 572 msg.msg_control = 0; 573 msg.msg_flags = SCARG(uap, flags); 574 return (recvit(p, SCARG(uap, s), &msg, 575 (caddr_t)SCARG(uap, fromlenaddr), retval)); 576 } 577 578 int 579 sys_recvmsg(struct proc *p, void *v, register_t *retval) 580 { 581 struct sys_recvmsg_args /* { 582 syscallarg(int) s; 583 syscallarg(struct msghdr *) msg; 584 syscallarg(int) flags; 585 } */ *uap = v; 586 struct msghdr msg; 587 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 588 int error; 589 590 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 591 if (error) 592 return (error); 593 if (msg.msg_iovlen > IOV_MAX) 594 return (EMSGSIZE); 595 if (msg.msg_iovlen > UIO_SMALLIOV) 596 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen, 597 M_IOV, M_WAITOK); 598 else 599 iov = aiov; 600 msg.msg_flags = SCARG(uap, flags); 601 if (msg.msg_iovlen > 0) { 602 error = copyin(msg.msg_iov, iov, 603 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 604 if (error) 605 goto done; 606 } 607 uiov = msg.msg_iov; 608 msg.msg_iov = iov; 609 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { 610 msg.msg_iov = uiov; 611 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 612 } 613 done: 614 if (iov != aiov) 615 free(iov, M_IOV); 616 return (error); 617 } 618 619 int 620 recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, 621 register_t *retsize) 622 { 623 struct file *fp; 624 struct uio auio; 625 struct iovec *iov; 626 int i; 627 size_t len; 628 int error; 629 struct mbuf *from = NULL, *control = NULL; 630 #ifdef KTRACE 631 struct iovec *ktriov = NULL; 632 #endif 633 634 if ((error = getsock(p->p_fd, s, &fp)) != 0) 635 return (error); 636 auio.uio_iov = mp->msg_iov; 637 auio.uio_iovcnt = mp->msg_iovlen; 638 auio.uio_segflg = UIO_USERSPACE; 639 auio.uio_rw = UIO_READ; 640 auio.uio_procp = p; 641 auio.uio_offset = 0; /* XXX */ 642 auio.uio_resid = 0; 643 iov = mp->msg_iov; 644 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 645 /* Don't allow sum > SSIZE_MAX */ 646 if (iov->iov_len > SSIZE_MAX || 647 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 648 error = EINVAL; 649 goto out; 650 } 651 } 652 #ifdef KTRACE 653 if (KTRPOINT(p, KTR_GENIO)) { 654 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 655 656 ktriov = malloc(iovlen, M_TEMP, M_WAITOK); 657 bcopy(auio.uio_iov, ktriov, iovlen); 658 } 659 #endif 660 len = auio.uio_resid; 661 error = soreceive(fp->f_data, &from, &auio, NULL, 662 mp->msg_control ? &control : NULL, 663 &mp->msg_flags, 664 mp->msg_control ? mp->msg_controllen : 0); 665 if (error) { 666 if (auio.uio_resid != len && (error == ERESTART || 667 error == EINTR || error == EWOULDBLOCK)) 668 error = 0; 669 } 670 #ifdef KTRACE 671 if (ktriov != NULL) { 672 if (error == 0) 673 ktrgenio(p, s, UIO_READ, 674 ktriov, len - auio.uio_resid, error); 675 free(ktriov, M_TEMP); 676 } 677 #endif 678 if (error) 679 goto out; 680 *retsize = len - auio.uio_resid; 681 if (mp->msg_name) { 682 socklen_t alen; 683 684 if (from == NULL) 685 alen = 0; 686 else { 687 alen = MIN(from->m_len, mp->msg_namelen); 688 error = copyout(mtod(from, caddr_t), mp->msg_name, 689 alen); 690 if (error) 691 goto out; 692 #ifdef KTRACE 693 if (KTRPOINT(p, KTR_STRUCT)) 694 ktrsockaddr(p, mtod(from, caddr_t), alen); 695 #endif 696 697 } 698 mp->msg_namelen = alen; 699 if (namelenp && 700 (error = copyout(&alen, namelenp, sizeof(alen)))) { 701 goto out; 702 } 703 } 704 if (mp->msg_control) { 705 len = mp->msg_controllen; 706 if (len <= 0 || control == NULL) 707 len = 0; 708 else { 709 struct mbuf *m = control; 710 caddr_t p = mp->msg_control; 711 712 do { 713 i = m->m_len; 714 if (len < i) { 715 mp->msg_flags |= MSG_CTRUNC; 716 i = len; 717 } 718 error = copyout(mtod(m, caddr_t), p, 719 (unsigned)i); 720 if (m->m_next) 721 i = ALIGN(i); 722 p += i; 723 len -= i; 724 if (error != 0 || len <= 0) 725 break; 726 } while ((m = m->m_next) != NULL); 727 len = p - (caddr_t)mp->msg_control; 728 } 729 mp->msg_controllen = len; 730 } 731 if (!error) { 732 fp->f_rxfer++; 733 fp->f_rbytes += *retsize; 734 } 735 out: 736 FRELE(fp); 737 if (from) 738 m_freem(from); 739 if (control) 740 m_freem(control); 741 return (error); 742 } 743 744 /* ARGSUSED */ 745 int 746 sys_shutdown(struct proc *p, void *v, register_t *retval) 747 { 748 struct sys_shutdown_args /* { 749 syscallarg(int) s; 750 syscallarg(int) how; 751 } */ *uap = v; 752 struct file *fp; 753 int error; 754 755 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 756 return (error); 757 error = soshutdown(fp->f_data, SCARG(uap, how)); 758 FRELE(fp); 759 return (error); 760 } 761 762 /* ARGSUSED */ 763 int 764 sys_setsockopt(struct proc *p, void *v, register_t *retval) 765 { 766 struct sys_setsockopt_args /* { 767 syscallarg(int) s; 768 syscallarg(int) level; 769 syscallarg(int) name; 770 syscallarg(const void *) val; 771 syscallarg(socklen_t) valsize; 772 } */ *uap = v; 773 struct file *fp; 774 struct mbuf *m = NULL; 775 int error; 776 777 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 778 return (error); 779 if (SCARG(uap, valsize) > MCLBYTES) { 780 error = EINVAL; 781 goto bad; 782 } 783 if (SCARG(uap, val)) { 784 m = m_get(M_WAIT, MT_SOOPTS); 785 if (SCARG(uap, valsize) > MLEN) { 786 MCLGET(m, M_DONTWAIT); 787 if ((m->m_flags & M_EXT) == 0) { 788 error = ENOBUFS; 789 goto bad; 790 } 791 } 792 if (m == NULL) { 793 error = ENOBUFS; 794 goto bad; 795 } 796 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 797 SCARG(uap, valsize)); 798 if (error) { 799 goto bad; 800 } 801 m->m_len = SCARG(uap, valsize); 802 } 803 error = sosetopt(fp->f_data, SCARG(uap, level), 804 SCARG(uap, name), m); 805 m = NULL; 806 bad: 807 if (m) 808 m_freem(m); 809 FRELE(fp); 810 return (error); 811 } 812 813 /* ARGSUSED */ 814 int 815 sys_getsockopt(struct proc *p, void *v, register_t *retval) 816 { 817 struct sys_getsockopt_args /* { 818 syscallarg(int) s; 819 syscallarg(int) level; 820 syscallarg(int) name; 821 syscallarg(void *) val; 822 syscallarg(socklen_t *) avalsize; 823 } */ *uap = v; 824 struct file *fp; 825 struct mbuf *m = NULL; 826 socklen_t valsize; 827 int error; 828 829 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 830 return (error); 831 if (SCARG(uap, val)) { 832 error = copyin(SCARG(uap, avalsize), 833 &valsize, sizeof (valsize)); 834 if (error) 835 goto out; 836 } else 837 valsize = 0; 838 if ((error = sogetopt(fp->f_data, SCARG(uap, level), 839 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && 840 m != NULL) { 841 if (valsize > m->m_len) 842 valsize = m->m_len; 843 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 844 if (error == 0) 845 error = copyout(&valsize, 846 SCARG(uap, avalsize), sizeof (valsize)); 847 } 848 out: 849 FRELE(fp); 850 if (m != NULL) 851 (void)m_free(m); 852 return (error); 853 } 854 855 /* 856 * Get socket name. 857 */ 858 /* ARGSUSED */ 859 int 860 sys_getsockname(struct proc *p, void *v, register_t *retval) 861 { 862 struct sys_getsockname_args /* { 863 syscallarg(int) fdes; 864 syscallarg(struct sockaddr *) asa; 865 syscallarg(socklen_t *) alen; 866 } */ *uap = v; 867 struct file *fp; 868 struct socket *so; 869 struct mbuf *m = NULL; 870 socklen_t len; 871 int error; 872 873 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 874 return (error); 875 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 876 if (error) 877 goto bad; 878 so = fp->f_data; 879 m = m_getclr(M_WAIT, MT_SONAME); 880 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p); 881 if (error) 882 goto bad; 883 if (len > m->m_len) 884 len = m->m_len; 885 error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len); 886 if (error == 0) { 887 #ifdef KTRACE 888 if (KTRPOINT(p, KTR_STRUCT)) 889 ktrsockaddr(p, mtod(m, caddr_t), len); 890 #endif 891 error = copyout(&len, SCARG(uap, alen), sizeof (len)); 892 } 893 bad: 894 FRELE(fp); 895 if (m) 896 m_freem(m); 897 return (error); 898 } 899 900 /* 901 * Get name of peer for connected socket. 902 */ 903 /* ARGSUSED */ 904 int 905 sys_getpeername(struct proc *p, void *v, register_t *retval) 906 { 907 struct sys_getpeername_args /* { 908 syscallarg(int) fdes; 909 syscallarg(struct sockaddr *) asa; 910 syscallarg(socklen_t *) alen; 911 } */ *uap = v; 912 struct file *fp; 913 struct socket *so; 914 struct mbuf *m = NULL; 915 socklen_t len; 916 int error; 917 918 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 919 return (error); 920 so = fp->f_data; 921 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { 922 FRELE(fp); 923 return (ENOTCONN); 924 } 925 error = copyin(SCARG(uap, alen), &len, sizeof (len)); 926 if (error) 927 goto bad; 928 m = m_getclr(M_WAIT, MT_SONAME); 929 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p); 930 if (error) 931 goto bad; 932 if (len > m->m_len) 933 len = m->m_len; 934 error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len); 935 if (error == 0) { 936 #ifdef KTRACE 937 if (KTRPOINT(p, KTR_STRUCT)) 938 ktrsockaddr(p, mtod(m, caddr_t), len); 939 #endif 940 error = copyout(&len, SCARG(uap, alen), sizeof (len)); 941 } 942 bad: 943 FRELE(fp); 944 m_freem(m); 945 return (error); 946 } 947 948 int 949 sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type) 950 { 951 struct sockaddr *sa; 952 struct mbuf *m; 953 int error; 954 955 /* 956 * We can't allow socket names > UCHAR_MAX in length, since that 957 * will overflow sa_len. Also, control data more than MCLBYTES in 958 * length is just too much. 959 */ 960 if (buflen > (type == MT_SONAME ? UCHAR_MAX : MCLBYTES)) 961 return (EINVAL); 962 963 /* Allocate an mbuf to hold the arguments. */ 964 m = m_get(M_WAIT, type); 965 if ((u_int)buflen > MLEN) { 966 MCLGET(m, M_WAITOK); 967 if ((m->m_flags & M_EXT) == 0) { 968 m_free(m); 969 return ENOBUFS; 970 } 971 } 972 m->m_len = buflen; 973 error = copyin(buf, mtod(m, caddr_t), buflen); 974 if (error) { 975 (void) m_free(m); 976 return (error); 977 } 978 *mp = m; 979 if (type == MT_SONAME) { 980 sa = mtod(m, struct sockaddr *); 981 #if BYTE_ORDER != BIG_ENDIAN 982 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 983 sa->sa_family = sa->sa_len; 984 #endif 985 sa->sa_len = buflen; 986 } 987 return (0); 988 } 989 990 int 991 getsock(struct filedesc *fdp, int fdes, struct file **fpp) 992 { 993 struct file *fp; 994 995 if ((fp = fd_getfile(fdp, fdes)) == NULL) 996 return (EBADF); 997 if (fp->f_type != DTYPE_SOCKET) 998 return (ENOTSOCK); 999 *fpp = fp; 1000 FREF(fp); 1001 1002 return (0); 1003 } 1004 1005 /* ARGSUSED */ 1006 int 1007 sys_setrtable(struct proc *p, void *v, register_t *retval) 1008 { 1009 struct sys_setrtable_args /* { 1010 syscallarg(int) rtableid; 1011 } */ *uap = v; 1012 int rtableid, error; 1013 1014 rtableid = SCARG(uap, rtableid); 1015 1016 if (p->p_p->ps_rtableid == (u_int)rtableid) 1017 return (0); 1018 if (p->p_p->ps_rtableid != 0 && (error = suser(p, 0)) != 0) 1019 return (error); 1020 if (rtableid < 0 || !rtable_exists((u_int)rtableid)) 1021 return (EINVAL); 1022 1023 p->p_p->ps_rtableid = (u_int)rtableid; 1024 return (0); 1025 } 1026 1027 /* ARGSUSED */ 1028 int 1029 sys_getrtable(struct proc *p, void *v, register_t *retval) 1030 { 1031 *retval = (int)p->p_p->ps_rtableid; 1032 return (0); 1033 } 1034