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