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