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