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