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