1 /* $NetBSD: uipc_syscalls.c,v 1.11 1995/03/05 08:52:21 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/filedesc.h> 41 #include <sys/proc.h> 42 #include <sys/file.h> 43 #include <sys/buf.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #ifdef KTRACE 50 #include <sys/ktrace.h> 51 #endif 52 53 #include <sys/mount.h> 54 #include <sys/syscallargs.h> 55 56 /* 57 * System call interface to the socket abstraction. 58 */ 59 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) 60 #define COMPAT_OLDSOCK 61 #endif 62 63 extern struct fileops socketops; 64 65 int 66 socket(p, uap, retval) 67 struct proc *p; 68 register struct socket_args /* { 69 syscallarg(int) domain; 70 syscallarg(int) type; 71 syscallarg(int) protocol; 72 } */ *uap; 73 register_t *retval; 74 { 75 struct filedesc *fdp = p->p_fd; 76 struct socket *so; 77 struct file *fp; 78 int fd, error; 79 80 if (error = falloc(p, &fp, &fd)) 81 return (error); 82 fp->f_flag = FREAD|FWRITE; 83 fp->f_type = DTYPE_SOCKET; 84 fp->f_ops = &socketops; 85 if (error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), 86 SCARG(uap, protocol))) { 87 fdp->fd_ofiles[fd] = 0; 88 ffree(fp); 89 } else { 90 fp->f_data = (caddr_t)so; 91 *retval = fd; 92 } 93 return (error); 94 } 95 96 /* ARGSUSED */ 97 int 98 bind(p, uap, retval) 99 struct proc *p; 100 register struct bind_args /* { 101 syscallarg(int) s; 102 syscallarg(caddr_t) name; 103 syscallarg(int) namelen; 104 } */ *uap; 105 register_t *retval; 106 { 107 struct file *fp; 108 struct mbuf *nam; 109 int error; 110 111 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 112 return (error); 113 if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 114 MT_SONAME)) 115 return (error); 116 error = sobind((struct socket *)fp->f_data, nam); 117 m_freem(nam); 118 return (error); 119 } 120 121 /* ARGSUSED */ 122 int 123 listen(p, uap, retval) 124 struct proc *p; 125 register struct listen_args /* { 126 syscallarg(int) s; 127 syscallarg(int) backlog; 128 } */ *uap; 129 register_t *retval; 130 { 131 struct file *fp; 132 int error; 133 134 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 135 return (error); 136 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog))); 137 } 138 139 #ifdef COMPAT_OLDSOCK 140 int 141 accept(p, uap, retval) 142 struct proc *p; 143 struct accept_args /* { 144 syscallarg(int) s; 145 syscallarg(caddr_t) name; 146 syscallarg(int *) anamelen; 147 } */ *uap; 148 register_t *retval; 149 { 150 151 return (accept1(p, uap, retval, 0)); 152 } 153 154 int 155 compat_43_accept(p, uap, retval) 156 struct proc *p; 157 struct accept_args /* { 158 syscallarg(int) s; 159 syscallarg(caddr_t) name; 160 syscallarg(int *) anamelen; 161 } */ *uap; 162 register_t *retval; 163 { 164 165 return (accept1(p, uap, retval, 1)); 166 } 167 #else /* COMPAT_OLDSOCK */ 168 169 #define accept1 accept 170 #endif 171 172 int 173 accept1(p, uap, retval, compat_43) 174 struct proc *p; 175 register struct accept_args /* { 176 syscallarg(int) s; 177 syscallarg(caddr_t) name; 178 syscallarg(int *) anamelen; 179 } */ *uap; 180 register_t *retval; 181 int compat_43; 182 { 183 struct file *fp; 184 struct mbuf *nam; 185 int namelen, error, s, tmpfd; 186 register struct socket *so; 187 188 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen), 189 (caddr_t)&namelen, sizeof (namelen)))) 190 return (error); 191 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 192 return (error); 193 s = splnet(); 194 so = (struct socket *)fp->f_data; 195 if ((so->so_options & SO_ACCEPTCONN) == 0) { 196 splx(s); 197 return (EINVAL); 198 } 199 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 200 splx(s); 201 return (EWOULDBLOCK); 202 } 203 while (so->so_qlen == 0 && so->so_error == 0) { 204 if (so->so_state & SS_CANTRCVMORE) { 205 so->so_error = ECONNABORTED; 206 break; 207 } 208 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 209 netcon, 0)) { 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 if (error = falloc(p, &fp, &tmpfd)) { 221 splx(s); 222 return (error); 223 } 224 *retval = tmpfd; 225 { struct socket *aso = so->so_q; 226 if (soqremque(aso, 1) == 0) 227 panic("accept"); 228 so = aso; 229 } 230 fp->f_type = DTYPE_SOCKET; 231 fp->f_flag = FREAD|FWRITE; 232 fp->f_ops = &socketops; 233 fp->f_data = (caddr_t)so; 234 nam = m_get(M_WAIT, MT_SONAME); 235 (void) soaccept(so, nam); 236 if (SCARG(uap, name)) { 237 #ifdef COMPAT_OLDSOCK 238 if (compat_43) 239 mtod(nam, struct osockaddr *)->sa_family = 240 mtod(nam, struct sockaddr *)->sa_family; 241 #endif 242 if (namelen > nam->m_len) 243 namelen = nam->m_len; 244 /* SHOULD COPY OUT A CHAIN HERE */ 245 if ((error = copyout(mtod(nam, caddr_t), 246 (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0) 247 error = copyout((caddr_t)&namelen, 248 (caddr_t)SCARG(uap, anamelen), 249 sizeof (*SCARG(uap, anamelen))); 250 } 251 m_freem(nam); 252 splx(s); 253 return (error); 254 } 255 256 /* ARGSUSED */ 257 int 258 connect(p, uap, retval) 259 struct proc *p; 260 register struct connect_args /* { 261 syscallarg(int) s; 262 syscallarg(caddr_t) name; 263 syscallarg(int) namelen; 264 } */ *uap; 265 register_t *retval; 266 { 267 struct file *fp; 268 register struct socket *so; 269 struct mbuf *nam; 270 int error, s; 271 272 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 273 return (error); 274 so = (struct socket *)fp->f_data; 275 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 276 return (EALREADY); 277 if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 278 MT_SONAME)) 279 return (error); 280 error = soconnect(so, nam); 281 if (error) 282 goto bad; 283 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 284 m_freem(nam); 285 return (EINPROGRESS); 286 } 287 s = splnet(); 288 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) 289 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 290 netcon, 0)) 291 break; 292 if (error == 0) { 293 error = so->so_error; 294 so->so_error = 0; 295 } 296 splx(s); 297 bad: 298 so->so_state &= ~SS_ISCONNECTING; 299 m_freem(nam); 300 if (error == ERESTART) 301 error = EINTR; 302 return (error); 303 } 304 305 int 306 socketpair(p, uap, retval) 307 struct proc *p; 308 register struct socketpair_args /* { 309 syscallarg(int) domain; 310 syscallarg(int) type; 311 syscallarg(int) protocol; 312 syscallarg(int *) rsv; 313 } */ *uap; 314 register_t *retval; 315 { 316 register struct filedesc *fdp = p->p_fd; 317 struct file *fp1, *fp2; 318 struct socket *so1, *so2; 319 int fd, error, sv[2]; 320 321 if (error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 322 SCARG(uap, protocol))) 323 return (error); 324 if (error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 325 SCARG(uap, protocol))) 326 goto free1; 327 if (error = falloc(p, &fp1, &fd)) 328 goto free2; 329 sv[0] = fd; 330 fp1->f_flag = FREAD|FWRITE; 331 fp1->f_type = DTYPE_SOCKET; 332 fp1->f_ops = &socketops; 333 fp1->f_data = (caddr_t)so1; 334 if (error = falloc(p, &fp2, &fd)) 335 goto free3; 336 fp2->f_flag = FREAD|FWRITE; 337 fp2->f_type = DTYPE_SOCKET; 338 fp2->f_ops = &socketops; 339 fp2->f_data = (caddr_t)so2; 340 sv[1] = fd; 341 if (error = soconnect2(so1, so2)) 342 goto free4; 343 if (SCARG(uap, type) == SOCK_DGRAM) { 344 /* 345 * Datagram socket connection is asymmetric. 346 */ 347 if (error = soconnect2(so2, so1)) 348 goto free4; 349 } 350 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), 351 2 * sizeof (int)); 352 retval[0] = sv[0]; /* XXX ??? */ 353 retval[1] = sv[1]; /* XXX ??? */ 354 return (error); 355 free4: 356 ffree(fp2); 357 fdp->fd_ofiles[sv[1]] = 0; 358 free3: 359 ffree(fp1); 360 fdp->fd_ofiles[sv[0]] = 0; 361 free2: 362 (void)soclose(so2); 363 free1: 364 (void)soclose(so1); 365 return (error); 366 } 367 368 int 369 sendto(p, uap, retval) 370 struct proc *p; 371 register struct sendto_args /* { 372 syscallarg(int) s; 373 syscallarg(caddr_t) buf; 374 syscallarg(size_t) len; 375 syscallarg(int) flags; 376 syscallarg(caddr_t) to; 377 syscallarg(int) tolen; 378 } */ *uap; 379 register_t *retval; 380 { 381 struct msghdr msg; 382 struct iovec aiov; 383 384 msg.msg_name = SCARG(uap, to); 385 msg.msg_namelen = SCARG(uap, tolen); 386 msg.msg_iov = &aiov; 387 msg.msg_iovlen = 1; 388 msg.msg_control = 0; 389 #ifdef COMPAT_OLDSOCK 390 msg.msg_flags = 0; 391 #endif 392 aiov.iov_base = SCARG(uap, buf); 393 aiov.iov_len = SCARG(uap, len); 394 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 395 } 396 397 #ifdef COMPAT_OLDSOCK 398 int 399 compat_43_send(p, uap, retval) 400 struct proc *p; 401 register struct compat_43_send_args /* { 402 syscallarg(int) s; 403 syscallarg(caddr_t) buf; 404 syscallarg(int) len; 405 syscallarg(int) flags; 406 } */ *uap; 407 register_t *retval; 408 { 409 struct msghdr msg; 410 struct iovec aiov; 411 412 msg.msg_name = 0; 413 msg.msg_namelen = 0; 414 msg.msg_iov = &aiov; 415 msg.msg_iovlen = 1; 416 aiov.iov_base = SCARG(uap, buf); 417 aiov.iov_len = SCARG(uap, len); 418 msg.msg_control = 0; 419 msg.msg_flags = 0; 420 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 421 } 422 423 #define MSG_COMPAT 0x8000 424 int 425 compat_43_sendmsg(p, uap, retval) 426 struct proc *p; 427 register struct compat_43_sendmsg_args /* { 428 syscallarg(int) s; 429 syscallarg(caddr_t) msg; 430 syscallarg(int) flags; 431 } */ *uap; 432 register_t *retval; 433 { 434 struct msghdr msg; 435 struct iovec aiov[UIO_SMALLIOV], *iov; 436 int error; 437 438 if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, 439 sizeof (struct omsghdr))) 440 return (error); 441 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 442 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 443 return (EMSGSIZE); 444 MALLOC(iov, struct iovec *, 445 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 446 M_WAITOK); 447 } else 448 iov = aiov; 449 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 450 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 451 goto done; 452 msg.msg_flags = MSG_COMPAT; 453 msg.msg_iov = iov; 454 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 455 done: 456 if (iov != aiov) 457 FREE(iov, M_IOV); 458 return (error); 459 } 460 #endif 461 462 int 463 sendmsg(p, uap, retval) 464 struct proc *p; 465 register struct sendmsg_args /* { 466 syscallarg(int) s; 467 syscallarg(caddr_t) msg; 468 syscallarg(int) flags; 469 } */ *uap; 470 register_t *retval; 471 { 472 struct msghdr msg; 473 struct iovec aiov[UIO_SMALLIOV], *iov; 474 int error; 475 476 if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg))) 477 return (error); 478 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 479 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 480 return (EMSGSIZE); 481 MALLOC(iov, struct iovec *, 482 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 483 M_WAITOK); 484 } else 485 iov = aiov; 486 if (msg.msg_iovlen && 487 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 488 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 489 goto done; 490 msg.msg_iov = iov; 491 #ifdef COMPAT_OLDSOCK 492 msg.msg_flags = 0; 493 #endif 494 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 495 done: 496 if (iov != aiov) 497 FREE(iov, M_IOV); 498 return (error); 499 } 500 501 int 502 sendit(p, s, mp, flags, retsize) 503 register struct proc *p; 504 int s; 505 register struct msghdr *mp; 506 int flags; 507 register_t *retsize; 508 { 509 struct file *fp; 510 struct uio auio; 511 register struct iovec *iov; 512 register int i; 513 struct mbuf *to, *control; 514 int len, error; 515 #ifdef KTRACE 516 struct iovec *ktriov = NULL; 517 #endif 518 519 if (error = getsock(p->p_fd, s, &fp)) 520 return (error); 521 auio.uio_iov = mp->msg_iov; 522 auio.uio_iovcnt = mp->msg_iovlen; 523 auio.uio_segflg = UIO_USERSPACE; 524 auio.uio_rw = UIO_WRITE; 525 auio.uio_procp = p; 526 auio.uio_offset = 0; /* XXX */ 527 auio.uio_resid = 0; 528 iov = mp->msg_iov; 529 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 530 if (iov->iov_len < 0) 531 return (EINVAL); 532 if ((auio.uio_resid += iov->iov_len) < 0) 533 return (EINVAL); 534 } 535 if (mp->msg_name) { 536 if (error = sockargs(&to, mp->msg_name, mp->msg_namelen, 537 MT_SONAME)) 538 return (error); 539 } else 540 to = 0; 541 if (mp->msg_control) { 542 if (mp->msg_controllen < sizeof(struct cmsghdr) 543 #ifdef COMPAT_OLDSOCK 544 && mp->msg_flags != MSG_COMPAT 545 #endif 546 ) { 547 error = EINVAL; 548 goto bad; 549 } 550 if (error = sockargs(&control, mp->msg_control, 551 mp->msg_controllen, MT_CONTROL)) 552 goto bad; 553 #ifdef COMPAT_OLDSOCK 554 if (mp->msg_flags == MSG_COMPAT) { 555 register struct cmsghdr *cm; 556 557 M_PREPEND(control, sizeof(*cm), M_WAIT); 558 if (control == 0) { 559 error = ENOBUFS; 560 goto bad; 561 } else { 562 cm = mtod(control, struct cmsghdr *); 563 cm->cmsg_len = control->m_len; 564 cm->cmsg_level = SOL_SOCKET; 565 cm->cmsg_type = SCM_RIGHTS; 566 } 567 } 568 #endif 569 } else 570 control = 0; 571 #ifdef KTRACE 572 if (KTRPOINT(p, KTR_GENIO)) { 573 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 574 575 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 576 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 577 } 578 #endif 579 len = auio.uio_resid; 580 if (error = sosend((struct socket *)fp->f_data, to, &auio, 581 (struct mbuf *)0, control, flags)) { 582 if (auio.uio_resid != len && (error == ERESTART || 583 error == EINTR || error == EWOULDBLOCK)) 584 error = 0; 585 if (error == EPIPE) 586 psignal(p, SIGPIPE); 587 } 588 if (error == 0) 589 *retsize = len - auio.uio_resid; 590 #ifdef KTRACE 591 if (ktriov != NULL) { 592 if (error == 0) 593 ktrgenio(p->p_tracep, s, UIO_WRITE, 594 ktriov, *retsize, error); 595 FREE(ktriov, M_TEMP); 596 } 597 #endif 598 bad: 599 if (to) 600 m_freem(to); 601 return (error); 602 } 603 604 #ifdef COMPAT_OLDSOCK 605 int 606 compat_43_recvfrom(p, uap, retval) 607 struct proc *p; 608 struct recvfrom_args /* { 609 syscallarg(int) s; 610 syscallarg(caddr_t) buf; 611 syscallarg(size_t) len; 612 syscallarg(int) flags; 613 syscallarg(caddr_t) from; 614 syscallarg(int *) fromlenaddr; 615 } */ *uap; 616 register_t *retval; 617 { 618 619 SCARG(uap, flags) |= MSG_COMPAT; 620 return (recvfrom(p, uap, retval)); 621 } 622 #endif 623 624 int 625 recvfrom(p, uap, retval) 626 struct proc *p; 627 register struct recvfrom_args /* { 628 syscallarg(int) s; 629 syscallarg(caddr_t) buf; 630 syscallarg(size_t) len; 631 syscallarg(int) flags; 632 syscallarg(caddr_t) from; 633 syscallarg(int *) fromlenaddr; 634 } */ *uap; 635 register_t *retval; 636 { 637 struct msghdr msg; 638 struct iovec aiov; 639 int error; 640 641 if (SCARG(uap, fromlenaddr)) { 642 if (error = copyin((caddr_t)SCARG(uap, fromlenaddr), 643 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen))) 644 return (error); 645 } else 646 msg.msg_namelen = 0; 647 msg.msg_name = SCARG(uap, from); 648 msg.msg_iov = &aiov; 649 msg.msg_iovlen = 1; 650 aiov.iov_base = SCARG(uap, buf); 651 aiov.iov_len = SCARG(uap, len); 652 msg.msg_control = 0; 653 msg.msg_flags = SCARG(uap, flags); 654 return (recvit(p, SCARG(uap, s), &msg, 655 (caddr_t)SCARG(uap, fromlenaddr), retval)); 656 } 657 658 #ifdef COMPAT_OLDSOCK 659 int 660 compat_43_recv(p, uap, retval) 661 struct proc *p; 662 register struct compat_43_recv_args /* { 663 syscallarg(int) s; 664 syscallarg(caddr_t) buf; 665 syscallarg(int) len; 666 syscallarg(int) flags; 667 } */ *uap; 668 register_t *retval; 669 { 670 struct msghdr msg; 671 struct iovec aiov; 672 673 msg.msg_name = 0; 674 msg.msg_namelen = 0; 675 msg.msg_iov = &aiov; 676 msg.msg_iovlen = 1; 677 aiov.iov_base = SCARG(uap, buf); 678 aiov.iov_len = SCARG(uap, len); 679 msg.msg_control = 0; 680 msg.msg_flags = SCARG(uap, flags); 681 return (recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)); 682 } 683 684 /* 685 * Old recvmsg. This code takes advantage of the fact that the old msghdr 686 * overlays the new one, missing only the flags, and with the (old) access 687 * rights where the control fields are now. 688 */ 689 int 690 compat_43_recvmsg(p, uap, retval) 691 struct proc *p; 692 register struct compat_43_recvmsg_args /* { 693 syscallarg(int) s; 694 syscallarg(struct omsghdr *) msg; 695 syscallarg(int) flags; 696 } */ *uap; 697 register_t *retval; 698 { 699 struct msghdr msg; 700 struct iovec aiov[UIO_SMALLIOV], *iov; 701 int error; 702 703 if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, 704 sizeof (struct omsghdr))) 705 return (error); 706 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 707 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 708 return (EMSGSIZE); 709 MALLOC(iov, struct iovec *, 710 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 711 M_WAITOK); 712 } else 713 iov = aiov; 714 msg.msg_flags = SCARG(uap, flags) | MSG_COMPAT; 715 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 716 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 717 goto done; 718 msg.msg_iov = iov; 719 error = recvit(p, SCARG(uap, s), &msg, 720 (caddr_t)&SCARG(uap, msg)->msg_namelen, retval); 721 722 if (msg.msg_controllen && error == 0) 723 error = copyout((caddr_t)&msg.msg_controllen, 724 (caddr_t)&SCARG(uap, msg)->msg_accrightslen, sizeof (int)); 725 done: 726 if (iov != aiov) 727 FREE(iov, M_IOV); 728 return (error); 729 } 730 #endif 731 732 int 733 recvmsg(p, uap, retval) 734 struct proc *p; 735 register struct recvmsg_args /* { 736 syscallarg(int) s; 737 syscallarg(struct msghdr *) msg; 738 syscallarg(int) flags; 739 } */ *uap; 740 register_t *retval; 741 { 742 struct msghdr msg; 743 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 744 register int error; 745 746 if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, 747 sizeof (msg))) 748 return (error); 749 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 750 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 751 return (EMSGSIZE); 752 MALLOC(iov, struct iovec *, 753 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 754 M_WAITOK); 755 } else 756 iov = aiov; 757 #ifdef COMPAT_OLDSOCK 758 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; 759 #else 760 msg.msg_flags = SCARG(uap, flags); 761 #endif 762 uiov = msg.msg_iov; 763 msg.msg_iov = iov; 764 if (error = copyin((caddr_t)uiov, (caddr_t)iov, 765 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))) 766 goto done; 767 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { 768 msg.msg_iov = uiov; 769 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), 770 sizeof(msg)); 771 } 772 done: 773 if (iov != aiov) 774 FREE(iov, M_IOV); 775 return (error); 776 } 777 778 int 779 recvit(p, s, mp, namelenp, retsize) 780 register struct proc *p; 781 int s; 782 register struct msghdr *mp; 783 caddr_t namelenp; 784 register_t *retsize; 785 { 786 struct file *fp; 787 struct uio auio; 788 register struct iovec *iov; 789 register int i; 790 int len, error; 791 struct mbuf *from = 0, *control = 0; 792 #ifdef KTRACE 793 struct iovec *ktriov = NULL; 794 #endif 795 796 if (error = getsock(p->p_fd, s, &fp)) 797 return (error); 798 auio.uio_iov = mp->msg_iov; 799 auio.uio_iovcnt = mp->msg_iovlen; 800 auio.uio_segflg = UIO_USERSPACE; 801 auio.uio_rw = UIO_READ; 802 auio.uio_procp = p; 803 auio.uio_offset = 0; /* XXX */ 804 auio.uio_resid = 0; 805 iov = mp->msg_iov; 806 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 807 if (iov->iov_len < 0) 808 return (EINVAL); 809 if ((auio.uio_resid += iov->iov_len) < 0) 810 return (EINVAL); 811 } 812 #ifdef KTRACE 813 if (KTRPOINT(p, KTR_GENIO)) { 814 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 815 816 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 817 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 818 } 819 #endif 820 len = auio.uio_resid; 821 if (error = soreceive((struct socket *)fp->f_data, &from, &auio, 822 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 823 &mp->msg_flags)) { 824 if (auio.uio_resid != len && (error == ERESTART || 825 error == EINTR || error == EWOULDBLOCK)) 826 error = 0; 827 } 828 #ifdef KTRACE 829 if (ktriov != NULL) { 830 if (error == 0) 831 ktrgenio(p->p_tracep, s, UIO_READ, 832 ktriov, len - auio.uio_resid, error); 833 FREE(ktriov, M_TEMP); 834 } 835 #endif 836 if (error) 837 goto out; 838 *retsize = len - auio.uio_resid; 839 if (mp->msg_name) { 840 len = mp->msg_namelen; 841 if (len <= 0 || from == 0) 842 len = 0; 843 else { 844 #ifdef COMPAT_OLDSOCK 845 if (mp->msg_flags & MSG_COMPAT) 846 mtod(from, struct osockaddr *)->sa_family = 847 mtod(from, struct sockaddr *)->sa_family; 848 #endif 849 if (len > from->m_len) 850 len = from->m_len; 851 /* else if len < from->m_len ??? */ 852 if (error = copyout(mtod(from, caddr_t), 853 (caddr_t)mp->msg_name, (unsigned)len)) 854 goto out; 855 } 856 mp->msg_namelen = len; 857 if (namelenp && 858 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 859 #ifdef COMPAT_OLDSOCK 860 if (mp->msg_flags & MSG_COMPAT) 861 error = 0; /* old recvfrom didn't check */ 862 else 863 #endif 864 goto out; 865 } 866 } 867 if (mp->msg_control) { 868 #ifdef COMPAT_OLDSOCK 869 /* 870 * We assume that old recvmsg calls won't receive access 871 * rights and other control info, esp. as control info 872 * is always optional and those options didn't exist in 4.3. 873 * If we receive rights, trim the cmsghdr; anything else 874 * is tossed. 875 */ 876 if (control && mp->msg_flags & MSG_COMPAT) { 877 if (mtod(control, struct cmsghdr *)->cmsg_level != 878 SOL_SOCKET || 879 mtod(control, struct cmsghdr *)->cmsg_type != 880 SCM_RIGHTS) { 881 mp->msg_controllen = 0; 882 goto out; 883 } 884 control->m_len -= sizeof (struct cmsghdr); 885 control->m_data += sizeof (struct cmsghdr); 886 } 887 #endif 888 len = mp->msg_controllen; 889 if (len <= 0 || control == 0) 890 len = 0; 891 else { 892 if (len >= control->m_len) 893 len = control->m_len; 894 else 895 mp->msg_flags |= MSG_CTRUNC; 896 error = copyout((caddr_t)mtod(control, caddr_t), 897 (caddr_t)mp->msg_control, (unsigned)len); 898 } 899 mp->msg_controllen = len; 900 } 901 out: 902 if (from) 903 m_freem(from); 904 if (control) 905 m_freem(control); 906 return (error); 907 } 908 909 /* ARGSUSED */ 910 int 911 shutdown(p, uap, retval) 912 struct proc *p; 913 register struct shutdown_args /* { 914 syscallarg(int) s; 915 syscallarg(int) how; 916 } */ *uap; 917 register_t *retval; 918 { 919 struct file *fp; 920 int error; 921 922 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 923 return (error); 924 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how))); 925 } 926 927 /* ARGSUSED */ 928 int 929 setsockopt(p, uap, retval) 930 struct proc *p; 931 register struct setsockopt_args /* { 932 syscallarg(int) s; 933 syscallarg(int) level; 934 syscallarg(int) name; 935 syscallarg(caddr_t) val; 936 syscallarg(int) valsize; 937 } */ *uap; 938 register_t *retval; 939 { 940 struct file *fp; 941 struct mbuf *m = NULL; 942 int error; 943 944 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 945 return (error); 946 if (SCARG(uap, valsize) > MLEN) 947 return (EINVAL); 948 if (SCARG(uap, val)) { 949 m = m_get(M_WAIT, MT_SOOPTS); 950 if (m == NULL) 951 return (ENOBUFS); 952 if (error = copyin(SCARG(uap, val), mtod(m, caddr_t), 953 (u_int)SCARG(uap, valsize))) { 954 (void) m_free(m); 955 return (error); 956 } 957 m->m_len = SCARG(uap, valsize); 958 } 959 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 960 SCARG(uap, name), m)); 961 } 962 963 /* ARGSUSED */ 964 int 965 getsockopt(p, uap, retval) 966 struct proc *p; 967 register struct getsockopt_args /* { 968 syscallarg(int) s; 969 syscallarg(int) level; 970 syscallarg(int) name; 971 syscallarg(caddr_t) val; 972 syscallarg(int *) avalsize; 973 } */ *uap; 974 register_t *retval; 975 { 976 struct file *fp; 977 struct mbuf *m = NULL; 978 int valsize, error; 979 980 if (error = getsock(p->p_fd, SCARG(uap, s), &fp)) 981 return (error); 982 if (SCARG(uap, val)) { 983 if (error = copyin((caddr_t)SCARG(uap, avalsize), 984 (caddr_t)&valsize, sizeof (valsize))) 985 return (error); 986 } else 987 valsize = 0; 988 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), 989 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && 990 m != NULL) { 991 if (valsize > m->m_len) 992 valsize = m->m_len; 993 error = copyout(mtod(m, caddr_t), SCARG(uap, val), 994 (u_int)valsize); 995 if (error == 0) 996 error = copyout((caddr_t)&valsize, 997 (caddr_t)SCARG(uap, avalsize), sizeof (valsize)); 998 } 999 if (m != NULL) 1000 (void) m_free(m); 1001 return (error); 1002 } 1003 1004 /* ARGSUSED */ 1005 int 1006 pipe(p, uap, retval) 1007 struct proc *p; 1008 void *uap; 1009 register_t *retval; 1010 { 1011 register struct filedesc *fdp = p->p_fd; 1012 struct file *rf, *wf; 1013 struct socket *rso, *wso; 1014 int fd, error; 1015 1016 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) 1017 return (error); 1018 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) 1019 goto free1; 1020 if (error = falloc(p, &rf, &fd)) 1021 goto free2; 1022 retval[0] = fd; 1023 rf->f_flag = FREAD; 1024 rf->f_type = DTYPE_SOCKET; 1025 rf->f_ops = &socketops; 1026 rf->f_data = (caddr_t)rso; 1027 if (error = falloc(p, &wf, &fd)) 1028 goto free3; 1029 wf->f_flag = FWRITE; 1030 wf->f_type = DTYPE_SOCKET; 1031 wf->f_ops = &socketops; 1032 wf->f_data = (caddr_t)wso; 1033 retval[1] = fd; 1034 if (error = unp_connect2(wso, rso)) 1035 goto free4; 1036 return (0); 1037 free4: 1038 ffree(wf); 1039 fdp->fd_ofiles[retval[1]] = 0; 1040 free3: 1041 ffree(rf); 1042 fdp->fd_ofiles[retval[0]] = 0; 1043 free2: 1044 (void)soclose(wso); 1045 free1: 1046 (void)soclose(rso); 1047 return (error); 1048 } 1049 1050 /* 1051 * Get socket name. 1052 */ 1053 #ifdef COMPAT_OLDSOCK 1054 int 1055 getsockname(p, uap, retval) 1056 struct proc *p; 1057 struct getsockname_args /* { 1058 syscallarg(int) fdes; 1059 syscallarg(caddr_t) asa; 1060 syscallarg(int *) alen; 1061 } */ *uap; 1062 register_t *retval; 1063 { 1064 1065 return (getsockname1(p, uap, retval, 0)); 1066 } 1067 1068 int 1069 compat_43_getsockname(p, uap, retval) 1070 struct proc *p; 1071 struct getsockname_args /* { 1072 syscallarg(int) fdes; 1073 syscallarg(caddr_t) asa; 1074 syscallarg(int *) alen; 1075 } */ *uap; 1076 register_t *retval; 1077 { 1078 1079 return (getsockname1(p, uap, retval, 1)); 1080 } 1081 #else /* COMPAT_OLDSOCK */ 1082 1083 #define getsockname1 getsockname 1084 #endif 1085 1086 /* ARGSUSED */ 1087 int 1088 getsockname1(p, uap, retval, compat_43) 1089 struct proc *p; 1090 register struct getsockname_args /* { 1091 syscallarg(int) fdes; 1092 syscallarg(caddr_t) asa; 1093 syscallarg(int *) alen; 1094 } */ *uap; 1095 register_t *retval; 1096 int compat_43; 1097 { 1098 struct file *fp; 1099 register struct socket *so; 1100 struct mbuf *m; 1101 int len, error; 1102 1103 if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) 1104 return (error); 1105 if (error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, 1106 sizeof (len))) 1107 return (error); 1108 so = (struct socket *)fp->f_data; 1109 m = m_getclr(M_WAIT, MT_SONAME); 1110 if (m == NULL) 1111 return (ENOBUFS); 1112 if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0)) 1113 goto bad; 1114 if (len > m->m_len) 1115 len = m->m_len; 1116 #ifdef COMPAT_OLDSOCK 1117 if (compat_43) 1118 mtod(m, struct osockaddr *)->sa_family = 1119 mtod(m, struct sockaddr *)->sa_family; 1120 #endif 1121 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); 1122 if (error == 0) 1123 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), 1124 sizeof (len)); 1125 bad: 1126 m_freem(m); 1127 return (error); 1128 } 1129 1130 /* 1131 * Get name of peer for connected socket. 1132 */ 1133 #ifdef COMPAT_OLDSOCK 1134 int 1135 getpeername(p, uap, retval) 1136 struct proc *p; 1137 struct getpeername_args /* { 1138 syscallarg(int) fdes; 1139 syscallarg(caddr_t) asa; 1140 syscallarg(int *) alen; 1141 } */ *uap; 1142 register_t *retval; 1143 { 1144 1145 return (getpeername1(p, uap, retval, 0)); 1146 } 1147 1148 int 1149 compat_43_getpeername(p, uap, retval) 1150 struct proc *p; 1151 struct getpeername_args /* { 1152 syscallarg(int) fdes; 1153 syscallarg(caddr_t) asa; 1154 syscallarg(int *) alen; 1155 } */ *uap; 1156 register_t *retval; 1157 { 1158 1159 return (getpeername1(p, uap, retval, 1)); 1160 } 1161 #else /* COMPAT_OLDSOCK */ 1162 1163 #define getpeername1 getpeername 1164 #endif 1165 1166 /* ARGSUSED */ 1167 int 1168 getpeername1(p, uap, retval, compat_43) 1169 struct proc *p; 1170 register struct getpeername_args /* { 1171 syscallarg(int) fdes; 1172 syscallarg(caddr_t) asa; 1173 syscallarg(int *) alen; 1174 } */ *uap; 1175 register_t *retval; 1176 int compat_43; 1177 { 1178 struct file *fp; 1179 register struct socket *so; 1180 struct mbuf *m; 1181 int len, error; 1182 1183 if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) 1184 return (error); 1185 so = (struct socket *)fp->f_data; 1186 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1187 return (ENOTCONN); 1188 if (error = 1189 copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len))) 1190 return (error); 1191 m = m_getclr(M_WAIT, MT_SONAME); 1192 if (m == NULL) 1193 return (ENOBUFS); 1194 if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0)) 1195 goto bad; 1196 if (len > m->m_len) 1197 len = m->m_len; 1198 #ifdef COMPAT_OLDSOCK 1199 if (compat_43) 1200 mtod(m, struct osockaddr *)->sa_family = 1201 mtod(m, struct sockaddr *)->sa_family; 1202 #endif 1203 if (error = 1204 copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len)) 1205 goto bad; 1206 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len)); 1207 bad: 1208 m_freem(m); 1209 return (error); 1210 } 1211 1212 int 1213 sockargs(mp, buf, buflen, type) 1214 struct mbuf **mp; 1215 caddr_t buf; 1216 int buflen, type; 1217 { 1218 register struct sockaddr *sa; 1219 register struct mbuf *m; 1220 int error; 1221 1222 if ((u_int)buflen > MLEN) { 1223 #ifdef COMPAT_OLDSOCK 1224 if (type == MT_SONAME && (u_int)buflen <= 112) 1225 buflen = MLEN; /* unix domain compat. hack */ 1226 else 1227 #endif 1228 return (EINVAL); 1229 } 1230 m = m_get(M_WAIT, type); 1231 if (m == NULL) 1232 return (ENOBUFS); 1233 m->m_len = buflen; 1234 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1235 if (error) { 1236 (void) m_free(m); 1237 return (error); 1238 } 1239 *mp = m; 1240 if (type == MT_SONAME) { 1241 sa = mtod(m, struct sockaddr *); 1242 1243 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1244 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1245 sa->sa_family = sa->sa_len; 1246 #endif 1247 sa->sa_len = buflen; 1248 } 1249 return (0); 1250 } 1251 1252 int 1253 getsock(fdp, fdes, fpp) 1254 struct filedesc *fdp; 1255 int fdes; 1256 struct file **fpp; 1257 { 1258 register struct file *fp; 1259 1260 if ((unsigned)fdes >= fdp->fd_nfiles || 1261 (fp = fdp->fd_ofiles[fdes]) == NULL) 1262 return (EBADF); 1263 if (fp->f_type != DTYPE_SOCKET) 1264 return (ENOTSOCK); 1265 *fpp = fp; 1266 return (0); 1267 } 1268