1 /* $OpenBSD: uipc_syscalls.c,v 1.55 2003/07/21 22:44:50 tedu 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 /* 58 * System call interface to the socket abstraction. 59 */ 60 extern struct fileops socketops; 61 62 int 63 sys_socket(p, v, retval) 64 struct proc *p; 65 void *v; 66 register_t *retval; 67 { 68 register struct sys_socket_args /* { 69 syscallarg(int) domain; 70 syscallarg(int) type; 71 syscallarg(int) protocol; 72 } */ *uap = v; 73 struct filedesc *fdp = p->p_fd; 74 struct socket *so; 75 struct file *fp; 76 int fd, error; 77 78 if ((error = falloc(p, &fp, &fd)) != 0) 79 return (error); 80 fp->f_flag = FREAD|FWRITE; 81 fp->f_type = DTYPE_SOCKET; 82 fp->f_ops = &socketops; 83 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), 84 SCARG(uap, protocol)); 85 if (error) { 86 fdremove(fdp, fd); 87 closef(fp, p); 88 } else { 89 fp->f_data = so; 90 FILE_SET_MATURE(fp); 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(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, (caddr_t)SCARG(uap, name), SCARG(uap, namelen), 115 MT_SONAME); 116 if (error == 0) { 117 error = sobind((struct socket *)fp->f_data, nam); 118 m_freem(nam); 119 } 120 FRELE(fp); 121 return (error); 122 } 123 124 /* ARGSUSED */ 125 int 126 sys_listen(p, v, retval) 127 struct proc *p; 128 void *v; 129 register_t *retval; 130 { 131 register struct sys_listen_args /* { 132 syscallarg(int) s; 133 syscallarg(int) backlog; 134 } */ *uap = v; 135 struct file *fp; 136 int error; 137 138 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 139 return (error); 140 error = solisten((struct socket *)fp->f_data, SCARG(uap, backlog)); 141 FRELE(fp); 142 return (error); 143 } 144 145 int 146 sys_accept(p, v, retval) 147 struct proc *p; 148 void *v; 149 register_t *retval; 150 { 151 struct sys_accept_args /* { 152 syscallarg(int) s; 153 syscallarg(struct sockaddr *) name; 154 syscallarg(socklen_t *) anamelen; 155 } */ *uap = v; 156 struct file *fp, *headfp; 157 struct mbuf *nam; 158 socklen_t namelen; 159 int error, s, tmpfd; 160 struct socket *head, *so; 161 int nflag; 162 163 if (SCARG(uap, name) && (error = copyin(SCARG(uap, anamelen), 164 &namelen, sizeof (namelen)))) 165 return (error); 166 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 167 return (error); 168 headfp = fp; 169 s = splsoftnet(); 170 head = (struct socket *)fp->f_data; 171 if ((head->so_options & SO_ACCEPTCONN) == 0) { 172 error = EINVAL; 173 goto bad; 174 } 175 if ((head->so_state & SS_NBIO) && head->so_qlen == 0) { 176 error = EWOULDBLOCK; 177 goto bad; 178 } 179 while (head->so_qlen == 0 && head->so_error == 0) { 180 if (head->so_state & SS_CANTRCVMORE) { 181 head->so_error = ECONNABORTED; 182 break; 183 } 184 error = tsleep(&head->so_timeo, PSOCK | PCATCH, netcon, 0); 185 if (error) { 186 goto bad; 187 } 188 } 189 if (head->so_error) { 190 error = head->so_error; 191 head->so_error = 0; 192 goto bad; 193 } 194 195 /* 196 * At this point we know that there is at least one connection 197 * ready to be accepted. Remove it from the queue prior to 198 * allocating the file descriptor for it since falloc() may 199 * block allowing another process to accept the connection 200 * instead. 201 */ 202 so = TAILQ_FIRST(&head->so_q); 203 if (soqremque(so, 1) == 0) 204 panic("accept"); 205 206 /* Take note if socket was non-blocking. */ 207 nflag = (fp->f_flag & FNONBLOCK); 208 209 if ((error = falloc(p, &fp, &tmpfd)) != 0) { 210 /* 211 * Probably ran out of file descriptors. Put the 212 * unaccepted connection back onto the queue and 213 * do another wakeup so some other process might 214 * have a chance at it. 215 */ 216 so->so_head = head; 217 head->so_qlen++; 218 so->so_onq = &head->so_q; 219 TAILQ_INSERT_HEAD(so->so_onq, so, so_qe); 220 wakeup_one(&head->so_timeo); 221 goto bad; 222 } 223 *retval = tmpfd; 224 225 /* connection has been removed from the listen queue */ 226 KNOTE(&head->so_rcv.sb_sel.si_note, 0); 227 228 fp->f_type = DTYPE_SOCKET; 229 fp->f_flag = FREAD | FWRITE | nflag; 230 fp->f_ops = &socketops; 231 fp->f_data = so; 232 nam = m_get(M_WAIT, MT_SONAME); 233 error = soaccept(so, nam); 234 if (!error && SCARG(uap, name)) { 235 if (namelen > nam->m_len) 236 namelen = nam->m_len; 237 /* SHOULD COPY OUT A CHAIN HERE */ 238 if ((error = copyout(mtod(nam, caddr_t), 239 SCARG(uap, name), namelen)) == 0) 240 error = copyout(&namelen, SCARG(uap, anamelen), 241 sizeof (*SCARG(uap, anamelen))); 242 } 243 /* if an error occurred, free the file descriptor */ 244 if (error) { 245 fdremove(p->p_fd, tmpfd); 246 closef(fp, p); 247 } else { 248 FILE_SET_MATURE(fp); 249 } 250 m_freem(nam); 251 bad: 252 splx(s); 253 FRELE(headfp); 254 return (error); 255 } 256 257 /* ARGSUSED */ 258 int 259 sys_connect(p, v, retval) 260 struct proc *p; 261 void *v; 262 register_t *retval; 263 { 264 struct sys_connect_args /* { 265 syscallarg(int) s; 266 syscallarg(struct sockaddr *) name; 267 syscallarg(socklen_t) namelen; 268 } */ *uap = v; 269 struct file *fp; 270 struct socket *so; 271 struct mbuf *nam = NULL; 272 int error, s; 273 274 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 275 return (error); 276 so = (struct socket *)fp->f_data; 277 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 278 FRELE(fp); 279 return (EALREADY); 280 } 281 error = sockargs(&nam, (caddr_t)SCARG(uap, name), SCARG(uap, namelen), 282 MT_SONAME); 283 if (error) 284 goto bad; 285 error = soconnect(so, nam); 286 if (error) 287 goto bad; 288 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 289 FRELE(fp); 290 m_freem(nam); 291 return (EINPROGRESS); 292 } 293 s = splsoftnet(); 294 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 295 error = tsleep(&so->so_timeo, PSOCK | PCATCH, 296 netcon, 0); 297 if (error) 298 break; 299 } 300 if (error == 0) { 301 error = so->so_error; 302 so->so_error = 0; 303 } 304 splx(s); 305 bad: 306 so->so_state &= ~SS_ISCONNECTING; 307 FRELE(fp); 308 if (nam) 309 m_freem(nam); 310 if (error == ERESTART) 311 error = EINTR; 312 return (error); 313 } 314 315 int 316 sys_socketpair(p, v, retval) 317 struct proc *p; 318 void *v; 319 register_t *retval; 320 { 321 register struct sys_socketpair_args /* { 322 syscallarg(int) domain; 323 syscallarg(int) type; 324 syscallarg(int) protocol; 325 syscallarg(int *) rsv; 326 } */ *uap = v; 327 register struct filedesc *fdp = p->p_fd; 328 struct file *fp1, *fp2; 329 struct socket *so1, *so2; 330 int fd, error, sv[2]; 331 332 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 333 SCARG(uap, protocol)); 334 if (error) 335 return (error); 336 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 337 SCARG(uap, protocol)); 338 if (error) 339 goto free1; 340 if ((error = falloc(p, &fp1, &fd)) != 0) 341 goto free2; 342 sv[0] = fd; 343 fp1->f_flag = FREAD|FWRITE; 344 fp1->f_type = DTYPE_SOCKET; 345 fp1->f_ops = &socketops; 346 fp1->f_data = so1; 347 if ((error = falloc(p, &fp2, &fd)) != 0) 348 goto free3; 349 fp2->f_flag = FREAD|FWRITE; 350 fp2->f_type = DTYPE_SOCKET; 351 fp2->f_ops = &socketops; 352 fp2->f_data = so2; 353 sv[1] = fd; 354 if ((error = soconnect2(so1, so2)) != 0) 355 goto free4; 356 if (SCARG(uap, type) == SOCK_DGRAM) { 357 /* 358 * Datagram socket connection is asymmetric. 359 */ 360 if ((error = soconnect2(so2, so1)) != 0) 361 goto free4; 362 } 363 error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int)); 364 if (error == 0) { 365 FILE_SET_MATURE(fp1); 366 FILE_SET_MATURE(fp2); 367 return (error); 368 } 369 free4: 370 fdremove(fdp, sv[1]); 371 closef(fp2, p); 372 so2 = NULL; 373 free3: 374 fdremove(fdp, sv[0]); 375 closef(fp1, p); 376 so1 = NULL; 377 free2: 378 if (so2 != NULL) 379 (void)soclose(so2); 380 free1: 381 if (so1 != NULL) 382 (void)soclose(so1); 383 return (error); 384 } 385 386 int 387 sys_sendto(p, v, retval) 388 struct proc *p; 389 void *v; 390 register_t *retval; 391 { 392 register struct sys_sendto_args /* { 393 syscallarg(int) s; 394 syscallarg(caddr_t) buf; 395 syscallarg(size_t) len; 396 syscallarg(int) flags; 397 syscallarg(struct sockaddr *) to; 398 syscallarg(socklen_t) tolen; 399 } */ *uap = v; 400 struct msghdr msg; 401 struct iovec aiov; 402 403 msg.msg_name = (caddr_t)SCARG(uap, to); 404 msg.msg_namelen = SCARG(uap, tolen); 405 msg.msg_iov = &aiov; 406 msg.msg_iovlen = 1; 407 msg.msg_control = 0; 408 #ifdef COMPAT_OLDSOCK 409 msg.msg_flags = 0; 410 #endif 411 aiov.iov_base = (char *)SCARG(uap, buf); 412 aiov.iov_len = SCARG(uap, len); 413 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 414 } 415 416 int 417 sys_sendmsg(p, v, retval) 418 struct proc *p; 419 void *v; 420 register_t *retval; 421 { 422 register struct sys_sendmsg_args /* { 423 syscallarg(int) s; 424 syscallarg(caddr_t) 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 < 0 || 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 #ifdef COMPAT_OLDSOCK 447 msg.msg_flags = 0; 448 #endif 449 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 450 done: 451 if (iov != aiov) 452 free(iov, M_IOV); 453 return (error); 454 } 455 456 int 457 sendit(p, s, mp, flags, retsize) 458 struct proc *p; 459 int s; 460 struct msghdr *mp; 461 int flags; 462 register_t *retsize; 463 { 464 struct file *fp; 465 struct uio auio; 466 struct iovec *iov; 467 int i; 468 struct mbuf *to, *control; 469 int len, error; 470 #ifdef KTRACE 471 struct iovec *ktriov = NULL; 472 #endif 473 474 to = NULL; 475 476 if ((error = getsock(p->p_fd, s, &fp)) != 0) 477 return (error); 478 auio.uio_iov = mp->msg_iov; 479 auio.uio_iovcnt = mp->msg_iovlen; 480 auio.uio_segflg = UIO_USERSPACE; 481 auio.uio_rw = UIO_WRITE; 482 auio.uio_procp = p; 483 auio.uio_offset = 0; /* XXX */ 484 auio.uio_resid = 0; 485 iov = mp->msg_iov; 486 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 487 /* Don't allow sum > SSIZE_MAX */ 488 if (iov->iov_len > SSIZE_MAX || 489 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 490 error = EINVAL; 491 goto bad; 492 } 493 } 494 if (mp->msg_name) { 495 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 496 MT_SONAME); 497 if (error) 498 goto bad; 499 } 500 if (mp->msg_control) { 501 if (mp->msg_controllen < sizeof(struct cmsghdr) 502 #ifdef COMPAT_OLDSOCK 503 && mp->msg_flags != MSG_COMPAT 504 #endif 505 ) { 506 error = EINVAL; 507 goto bad; 508 } 509 error = sockargs(&control, mp->msg_control, 510 mp->msg_controllen, MT_CONTROL); 511 if (error) 512 goto bad; 513 #ifdef COMPAT_OLDSOCK 514 if (mp->msg_flags == MSG_COMPAT) { 515 register struct cmsghdr *cm; 516 517 M_PREPEND(control, sizeof(*cm), M_WAIT); 518 cm = mtod(control, struct cmsghdr *); 519 cm->cmsg_len = control->m_len; 520 cm->cmsg_level = SOL_SOCKET; 521 cm->cmsg_type = SCM_RIGHTS; 522 } 523 #endif 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 bcopy(auio.uio_iov, ktriov, iovlen); 532 } 533 #endif 534 len = auio.uio_resid; 535 error = sosend((struct socket *)fp->f_data, to, &auio, 536 NULL, control, flags); 537 if (error) { 538 if (auio.uio_resid != len && (error == ERESTART || 539 error == EINTR || error == EWOULDBLOCK)) 540 error = 0; 541 if (error == EPIPE) 542 psignal(p, SIGPIPE); 543 } 544 if (error == 0) 545 *retsize = len - auio.uio_resid; 546 #ifdef KTRACE 547 if (ktriov != NULL) { 548 if (error == 0) 549 ktrgenio(p, s, UIO_WRITE, ktriov, *retsize, error); 550 free(ktriov, M_TEMP); 551 } 552 #endif 553 bad: 554 FRELE(fp); 555 if (to) 556 m_freem(to); 557 return (error); 558 } 559 560 int 561 sys_recvfrom(p, v, retval) 562 struct proc *p; 563 void *v; 564 register_t *retval; 565 { 566 register struct sys_recvfrom_args /* { 567 syscallarg(int) s; 568 syscallarg(caddr_t) buf; 569 syscallarg(size_t) len; 570 syscallarg(int) flags; 571 syscallarg(struct sockaddr *) from; 572 syscallarg(socklen_t *) fromlenaddr; 573 } */ *uap = v; 574 struct msghdr msg; 575 struct iovec aiov; 576 int error; 577 578 if (SCARG(uap, fromlenaddr)) { 579 error = copyin(SCARG(uap, fromlenaddr), 580 &msg.msg_namelen, sizeof (msg.msg_namelen)); 581 if (error) 582 return (error); 583 } else 584 msg.msg_namelen = 0; 585 msg.msg_name = (caddr_t)SCARG(uap, from); 586 msg.msg_iov = &aiov; 587 msg.msg_iovlen = 1; 588 aiov.iov_base = SCARG(uap, buf); 589 aiov.iov_len = SCARG(uap, len); 590 msg.msg_control = 0; 591 msg.msg_flags = SCARG(uap, flags); 592 return (recvit(p, SCARG(uap, s), &msg, 593 (caddr_t)SCARG(uap, fromlenaddr), retval)); 594 } 595 596 int 597 sys_recvmsg(p, v, retval) 598 struct proc *p; 599 void *v; 600 register_t *retval; 601 { 602 register struct sys_recvmsg_args /* { 603 syscallarg(int) s; 604 syscallarg(struct msghdr *) msg; 605 syscallarg(int) flags; 606 } */ *uap = v; 607 struct msghdr msg; 608 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 609 int error; 610 611 error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); 612 if (error) 613 return (error); 614 if (msg.msg_iovlen < 0 || msg.msg_iovlen > IOV_MAX) 615 return (EMSGSIZE); 616 if (msg.msg_iovlen > UIO_SMALLIOV) 617 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen, 618 M_IOV, M_WAITOK); 619 else 620 iov = aiov; 621 #ifdef COMPAT_OLDSOCK 622 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; 623 #else 624 msg.msg_flags = SCARG(uap, flags); 625 #endif 626 if (msg.msg_iovlen > 0) { 627 error = copyin(msg.msg_iov, iov, 628 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 629 if (error) 630 goto done; 631 } 632 uiov = msg.msg_iov; 633 msg.msg_iov = iov; 634 if ((error = recvit(p, SCARG(uap, s), &msg, NULL, retval)) == 0) { 635 msg.msg_iov = uiov; 636 error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); 637 } 638 done: 639 if (iov != aiov) 640 free(iov, M_IOV); 641 return (error); 642 } 643 644 int 645 recvit(p, s, mp, namelenp, retsize) 646 struct proc *p; 647 int s; 648 struct msghdr *mp; 649 caddr_t namelenp; 650 register_t *retsize; 651 { 652 struct file *fp; 653 struct uio auio; 654 register struct iovec *iov; 655 register int i; 656 size_t len; 657 int error; 658 struct mbuf *from = NULL, *control = NULL; 659 #ifdef KTRACE 660 struct iovec *ktriov = NULL; 661 #endif 662 663 if ((error = getsock(p->p_fd, s, &fp)) != 0) 664 return (error); 665 auio.uio_iov = mp->msg_iov; 666 auio.uio_iovcnt = mp->msg_iovlen; 667 auio.uio_segflg = UIO_USERSPACE; 668 auio.uio_rw = UIO_READ; 669 auio.uio_procp = p; 670 auio.uio_offset = 0; /* XXX */ 671 auio.uio_resid = 0; 672 iov = mp->msg_iov; 673 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 674 /* Don't allow sum > SSIZE_MAX */ 675 if (iov->iov_len > SSIZE_MAX || 676 (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { 677 error = EINVAL; 678 goto out; 679 } 680 } 681 #ifdef KTRACE 682 if (KTRPOINT(p, KTR_GENIO)) { 683 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 684 685 ktriov = malloc(iovlen, M_TEMP, M_WAITOK); 686 bcopy(auio.uio_iov, ktriov, iovlen); 687 } 688 #endif 689 len = auio.uio_resid; 690 error = soreceive((struct socket *)fp->f_data, &from, &auio, 691 NULL, mp->msg_control ? &control : NULL, 692 &mp->msg_flags); 693 if (error) { 694 if (auio.uio_resid != len && (error == ERESTART || 695 error == EINTR || error == EWOULDBLOCK)) 696 error = 0; 697 } 698 #ifdef KTRACE 699 if (ktriov != NULL) { 700 if (error == 0) 701 ktrgenio(p, s, UIO_READ, 702 ktriov, len - auio.uio_resid, error); 703 free(ktriov, M_TEMP); 704 } 705 #endif 706 if (error) 707 goto out; 708 *retsize = len - auio.uio_resid; 709 if (mp->msg_name) { 710 socklen_t alen; 711 712 if (from == 0) 713 alen = 0; 714 else { 715 /* save sa_len before it is destroyed by MSG_COMPAT */ 716 alen = mp->msg_namelen; 717 if (alen > from->m_len) 718 alen = from->m_len; 719 /* else if alen < from->m_len ??? */ 720 #ifdef COMPAT_OLDSOCK 721 if (mp->msg_flags & MSG_COMPAT) 722 mtod(from, struct osockaddr *)->sa_family = 723 mtod(from, struct sockaddr *)->sa_family; 724 #endif 725 error = copyout(mtod(from, caddr_t), 726 mp->msg_name, alen); 727 if (error) 728 goto out; 729 } 730 mp->msg_namelen = alen; 731 if (namelenp && 732 (error = copyout(&alen, namelenp, sizeof(alen)))) { 733 #ifdef COMPAT_OLDSOCK 734 if (mp->msg_flags & MSG_COMPAT) 735 error = 0; /* old recvfrom didn't check */ 736 else 737 #endif 738 goto out; 739 } 740 } 741 if (mp->msg_control) { 742 #ifdef COMPAT_OLDSOCK 743 /* 744 * We assume that old recvmsg calls won't receive access 745 * rights and other control info, esp. as control info 746 * is always optional and those options didn't exist in 4.3. 747 * If we receive rights, trim the cmsghdr; anything else 748 * is tossed. 749 */ 750 if (control && mp->msg_flags & MSG_COMPAT) { 751 if (mtod(control, struct cmsghdr *)->cmsg_level != 752 SOL_SOCKET || 753 mtod(control, struct cmsghdr *)->cmsg_type != 754 SCM_RIGHTS) { 755 mp->msg_controllen = 0; 756 goto out; 757 } 758 control->m_len -= sizeof (struct cmsghdr); 759 control->m_data += sizeof (struct cmsghdr); 760 } 761 #endif 762 len = mp->msg_controllen; 763 if (len <= 0 || control == 0) 764 len = 0; 765 else { 766 struct mbuf *m = control; 767 caddr_t p = (caddr_t)mp->msg_control; 768 769 do { 770 i = m->m_len; 771 if (len < i) { 772 mp->msg_flags |= MSG_CTRUNC; 773 i = len; 774 } 775 error = copyout(mtod(m, caddr_t), p, 776 (unsigned)i); 777 if (m->m_next) 778 i = ALIGN(i); 779 p += i; 780 len -= i; 781 if (error != 0 || len <= 0) 782 break; 783 } while ((m = m->m_next) != NULL); 784 len = p - (caddr_t)mp->msg_control; 785 } 786 mp->msg_controllen = len; 787 } 788 out: 789 FRELE(fp); 790 if (from) 791 m_freem(from); 792 if (control) 793 m_freem(control); 794 return (error); 795 } 796 797 /* ARGSUSED */ 798 int 799 sys_shutdown(p, v, retval) 800 struct proc *p; 801 void *v; 802 register_t *retval; 803 { 804 struct sys_shutdown_args /* { 805 syscallarg(int) s; 806 syscallarg(int) how; 807 } */ *uap = v; 808 struct file *fp; 809 int error; 810 811 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 812 return (error); 813 error = soshutdown((struct socket *)fp->f_data, SCARG(uap, how)); 814 FRELE(fp); 815 return (error); 816 } 817 818 /* ARGSUSED */ 819 int 820 sys_setsockopt(p, v, retval) 821 struct proc *p; 822 void *v; 823 register_t *retval; 824 { 825 struct sys_setsockopt_args /* { 826 syscallarg(int) s; 827 syscallarg(int) level; 828 syscallarg(int) name; 829 syscallarg(caddr_t) val; 830 syscallarg(socklen_t) valsize; 831 } */ *uap = v; 832 struct file *fp; 833 struct mbuf *m = NULL; 834 int error; 835 836 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 837 return (error); 838 if (SCARG(uap, valsize) > MCLBYTES) { 839 error = EINVAL; 840 goto bad; 841 } 842 if (SCARG(uap, val)) { 843 m = m_get(M_WAIT, MT_SOOPTS); 844 if (SCARG(uap, valsize) > MLEN) { 845 MCLGET(m, M_DONTWAIT); 846 if ((m->m_flags & M_EXT) == 0) { 847 error = ENOBUFS; 848 goto bad; 849 } 850 } 851 if (m == NULL) { 852 error = ENOBUFS; 853 goto bad; 854 } 855 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 856 SCARG(uap, valsize)); 857 if (error) { 858 goto bad; 859 } 860 m->m_len = SCARG(uap, valsize); 861 } 862 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 863 SCARG(uap, name), m); 864 m = NULL; 865 bad: 866 if (m) 867 m_freem(m); 868 FRELE(fp); 869 return (error); 870 } 871 872 /* ARGSUSED */ 873 int 874 sys_getsockopt(p, v, retval) 875 struct proc *p; 876 void *v; 877 register_t *retval; 878 { 879 struct sys_getsockopt_args /* { 880 syscallarg(int) s; 881 syscallarg(int) level; 882 syscallarg(int) name; 883 syscallarg(caddr_t) val; 884 syscallarg(socklen_t *) avalsize; 885 } */ *uap = v; 886 struct file *fp; 887 struct mbuf *m = NULL; 888 socklen_t valsize; 889 int error; 890 891 if ((error = getsock(p->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 if (valsize > m->m_len) 904 valsize = m->m_len; 905 error = copyout(mtod(m, caddr_t), SCARG(uap, val), valsize); 906 if (error == 0) 907 error = copyout((caddr_t)&valsize, 908 (caddr_t)SCARG(uap, avalsize), sizeof (valsize)); 909 } 910 out: 911 FRELE(fp); 912 if (m != NULL) 913 (void) m_free(m); 914 return (error); 915 } 916 917 int 918 sys_pipe(struct proc *p, void *v, register_t *retval) 919 { 920 register struct sys_pipe_args /* { 921 syscallarg(int *) fdp; 922 } */ *uap = v; 923 int error, fds[2]; 924 register_t rval[2]; 925 926 if ((error = sys_opipe(p, v, rval)) != 0) 927 return (error); 928 929 fds[0] = rval[0]; 930 fds[1] = rval[1]; 931 error = copyout((caddr_t)fds, (caddr_t)SCARG(uap, fdp), 932 2 * sizeof (int)); 933 if (error) { 934 fdrelease(p, fds[0]); 935 fdrelease(p, fds[1]); 936 } 937 return (error); 938 } 939 940 /* 941 * Get socket name. 942 */ 943 /* ARGSUSED */ 944 int 945 sys_getsockname(p, v, retval) 946 struct proc *p; 947 void *v; 948 register_t *retval; 949 { 950 struct sys_getsockname_args /* { 951 syscallarg(int) fdes; 952 syscallarg(caddr_t) asa; 953 syscallarg(socklen_t *) alen; 954 } */ *uap = v; 955 struct file *fp; 956 struct socket *so; 957 struct mbuf *m = NULL; 958 socklen_t len; 959 int error; 960 961 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 962 return (error); 963 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); 964 if (error) 965 goto bad; 966 so = (struct socket *)fp->f_data; 967 m = m_getclr(M_WAIT, MT_SONAME); 968 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); 969 if (error) 970 goto bad; 971 if (len > m->m_len) 972 len = m->m_len; 973 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); 974 if (error == 0) 975 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), 976 sizeof (len)); 977 bad: 978 FRELE(fp); 979 if (m) 980 m_freem(m); 981 return (error); 982 } 983 984 /* 985 * Get name of peer for connected socket. 986 */ 987 /* ARGSUSED */ 988 int 989 sys_getpeername(p, v, retval) 990 struct proc *p; 991 void *v; 992 register_t *retval; 993 { 994 struct sys_getpeername_args /* { 995 syscallarg(int) fdes; 996 syscallarg(caddr_t) asa; 997 syscallarg(socklen_t *) alen; 998 } */ *uap = v; 999 struct file *fp; 1000 register struct socket *so; 1001 struct mbuf *m = NULL; 1002 socklen_t len; 1003 int error; 1004 1005 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 1006 return (error); 1007 so = (struct socket *)fp->f_data; 1008 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) { 1009 FRELE(fp); 1010 return (ENOTCONN); 1011 } 1012 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); 1013 if (error) 1014 goto bad; 1015 m = m_getclr(M_WAIT, MT_SONAME); 1016 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0); 1017 if (error) 1018 goto bad; 1019 if (len > m->m_len) 1020 len = m->m_len; 1021 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), len); 1022 if (error == 0) 1023 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), 1024 sizeof (len)); 1025 bad: 1026 FRELE(fp); 1027 m_freem(m); 1028 return (error); 1029 } 1030 1031 /* 1032 * Get eid of peer for connected socket. 1033 */ 1034 /* ARGSUSED */ 1035 int 1036 sys_getpeereid(p, v, retval) 1037 struct proc *p; 1038 void *v; 1039 register_t *retval; 1040 { 1041 struct sys_getpeereid_args /* { 1042 syscallarg(int) fdes; 1043 syscallarg(uid_t *) euid; 1044 syscallarg(gid_t *) egid; 1045 } */ *uap = v; 1046 struct file *fp; 1047 struct socket *so; 1048 struct mbuf *m = NULL; 1049 struct unpcbid *id; 1050 int error; 1051 1052 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 1053 return (error); 1054 so = (struct socket *)fp->f_data; 1055 if (so->so_proto != pffindtype(AF_LOCAL, SOCK_STREAM)) { 1056 FRELE(fp); 1057 return (EOPNOTSUPP); 1058 } 1059 m = m_getclr(M_WAIT, MT_SONAME); 1060 if (m == NULL) { 1061 error = ENOBUFS; 1062 goto bad; 1063 } 1064 error = (*so->so_proto->pr_usrreq)(so, PRU_PEEREID, 0, m, 0); 1065 if (!error && m->m_len != sizeof(struct unpcbid)) 1066 error = EOPNOTSUPP; 1067 if (error) 1068 goto bad; 1069 id = mtod(m, struct unpcbid *); 1070 error = copyout((caddr_t)&(id->unp_euid), 1071 (caddr_t)SCARG(uap, euid), sizeof(uid_t)); 1072 if (error == 0) 1073 error = copyout((caddr_t)&(id->unp_egid), 1074 (caddr_t)SCARG(uap, egid), sizeof(gid_t)); 1075 bad: 1076 FRELE(fp); 1077 m_freem(m); 1078 return (error); 1079 } 1080 1081 int 1082 sockargs(mp, buf, buflen, type) 1083 struct mbuf **mp; 1084 caddr_t buf; 1085 socklen_t buflen; 1086 int type; 1087 { 1088 struct sockaddr *sa; 1089 struct mbuf *m; 1090 int error; 1091 1092 /* 1093 * We can't allow socket names > UCHAR_MAX in length, since that 1094 * will overflow sa_len. 1095 */ 1096 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX) 1097 return (EINVAL); 1098 if ((u_int)buflen > MCLBYTES) 1099 return (EINVAL); 1100 1101 /* Allocate an mbuf to hold the arguments. */ 1102 m = m_get(M_WAIT, type); 1103 if ((u_int)buflen > MLEN) { 1104 MCLGET(m, M_WAITOK); 1105 if ((m->m_flags & M_EXT) == 0) { 1106 m_free(m); 1107 return ENOBUFS; 1108 } 1109 } 1110 m->m_len = buflen; 1111 error = copyin(buf, mtod(m, caddr_t), buflen); 1112 if (error) { 1113 (void) m_free(m); 1114 return (error); 1115 } 1116 *mp = m; 1117 if (type == MT_SONAME) { 1118 sa = mtod(m, struct sockaddr *); 1119 1120 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1121 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1122 sa->sa_family = sa->sa_len; 1123 #endif 1124 sa->sa_len = buflen; 1125 } 1126 return (0); 1127 } 1128 1129 int 1130 getsock(struct filedesc *fdp, int fdes, struct file **fpp) 1131 { 1132 struct file *fp; 1133 1134 if ((fp = fd_getfile(fdp, fdes)) == NULL) 1135 return (EBADF); 1136 if (fp->f_type != DTYPE_SOCKET) 1137 return (ENOTSOCK); 1138 *fpp = fp; 1139 FREF(fp); 1140 1141 return (0); 1142 } 1143