1 /* $NetBSD: uipc_syscalls.c,v 1.22 1996/06/14 22:21:44 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/filedesc.h> 41 #include <sys/proc.h> 42 #include <sys/file.h> 43 #include <sys/buf.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/signalvar.h> 50 #include <sys/un.h> 51 #ifdef KTRACE 52 #include <sys/ktrace.h> 53 #endif 54 55 #include <sys/mount.h> 56 #include <sys/syscallargs.h> 57 58 /* 59 * System call interface to the socket abstraction. 60 */ 61 extern struct fileops socketops; 62 63 int 64 sys_socket(p, v, retval) 65 struct proc *p; 66 void *v; 67 register_t *retval; 68 { 69 register struct sys_socket_args /* { 70 syscallarg(int) domain; 71 syscallarg(int) type; 72 syscallarg(int) protocol; 73 } */ *uap = v; 74 struct filedesc *fdp = p->p_fd; 75 struct socket *so; 76 struct file *fp; 77 int fd, error; 78 79 if ((error = falloc(p, &fp, &fd)) != 0) 80 return (error); 81 fp->f_flag = FREAD|FWRITE; 82 fp->f_type = DTYPE_SOCKET; 83 fp->f_ops = &socketops; 84 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), 85 SCARG(uap, protocol)); 86 if (error) { 87 fdp->fd_ofiles[fd] = 0; 88 ffree(fp); 89 } else { 90 fp->f_data = (caddr_t)so; 91 *retval = fd; 92 } 93 return (error); 94 } 95 96 /* ARGSUSED */ 97 int 98 sys_bind(p, v, retval) 99 struct proc *p; 100 void *v; 101 register_t *retval; 102 { 103 register struct sys_bind_args /* { 104 syscallarg(int) s; 105 syscallarg(caddr_t) name; 106 syscallarg(int) namelen; 107 } */ *uap = v; 108 struct file *fp; 109 struct mbuf *nam; 110 int error; 111 112 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 113 return (error); 114 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 115 MT_SONAME); 116 if (error) 117 return (error); 118 error = sobind((struct socket *)fp->f_data, nam); 119 m_freem(nam); 120 return (error); 121 } 122 123 /* ARGSUSED */ 124 int 125 sys_listen(p, v, retval) 126 struct proc *p; 127 void *v; 128 register_t *retval; 129 { 130 register struct sys_listen_args /* { 131 syscallarg(int) s; 132 syscallarg(int) backlog; 133 } */ *uap = v; 134 struct file *fp; 135 int error; 136 137 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 138 return (error); 139 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog))); 140 } 141 142 int 143 sys_accept(p, v, retval) 144 struct proc *p; 145 void *v; 146 register_t *retval; 147 { 148 register struct sys_accept_args /* { 149 syscallarg(int) s; 150 syscallarg(caddr_t) name; 151 syscallarg(int *) anamelen; 152 } */ *uap = v; 153 struct file *fp; 154 struct mbuf *nam; 155 int namelen, error, s, tmpfd; 156 register struct socket *so; 157 158 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen), 159 (caddr_t)&namelen, sizeof (namelen)))) 160 return (error); 161 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 162 return (error); 163 s = splsoftnet(); 164 so = (struct socket *)fp->f_data; 165 if ((so->so_options & SO_ACCEPTCONN) == 0) { 166 splx(s); 167 return (EINVAL); 168 } 169 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { 170 splx(s); 171 return (EWOULDBLOCK); 172 } 173 while (so->so_qlen == 0 && so->so_error == 0) { 174 if (so->so_state & SS_CANTRCVMORE) { 175 so->so_error = ECONNABORTED; 176 break; 177 } 178 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 179 netcon, 0); 180 if (error) { 181 splx(s); 182 return (error); 183 } 184 } 185 if (so->so_error) { 186 error = so->so_error; 187 so->so_error = 0; 188 splx(s); 189 return (error); 190 } 191 if ((error = falloc(p, &fp, &tmpfd)) != 0) { 192 splx(s); 193 return (error); 194 } 195 *retval = tmpfd; 196 { struct socket *aso = so->so_q; 197 if (soqremque(aso, 1) == 0) 198 panic("accept"); 199 so = aso; 200 } 201 fp->f_type = DTYPE_SOCKET; 202 fp->f_flag = FREAD|FWRITE; 203 fp->f_ops = &socketops; 204 fp->f_data = (caddr_t)so; 205 nam = m_get(M_WAIT, MT_SONAME); 206 (void) soaccept(so, nam); 207 if (SCARG(uap, name)) { 208 if (namelen > nam->m_len) 209 namelen = nam->m_len; 210 /* SHOULD COPY OUT A CHAIN HERE */ 211 if ((error = copyout(mtod(nam, caddr_t), 212 (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0) 213 error = copyout((caddr_t)&namelen, 214 (caddr_t)SCARG(uap, anamelen), 215 sizeof (*SCARG(uap, anamelen))); 216 } 217 m_freem(nam); 218 splx(s); 219 return (error); 220 } 221 222 /* ARGSUSED */ 223 int 224 sys_connect(p, v, retval) 225 struct proc *p; 226 void *v; 227 register_t *retval; 228 { 229 register struct sys_connect_args /* { 230 syscallarg(int) s; 231 syscallarg(caddr_t) name; 232 syscallarg(int) namelen; 233 } */ *uap = v; 234 struct file *fp; 235 register struct socket *so; 236 struct mbuf *nam; 237 int error, s; 238 239 if ((error = getsock(p->p_fd, SCARG(uap, s), &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 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 245 MT_SONAME); 246 if (error) 247 return (error); 248 error = soconnect(so, nam); 249 if (error) 250 goto bad; 251 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 252 m_freem(nam); 253 return (EINPROGRESS); 254 } 255 s = splsoftnet(); 256 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 257 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 258 netcon, 0); 259 if (error) 260 break; 261 } 262 if (error == 0) { 263 error = so->so_error; 264 so->so_error = 0; 265 } 266 splx(s); 267 bad: 268 so->so_state &= ~SS_ISCONNECTING; 269 m_freem(nam); 270 if (error == ERESTART) 271 error = EINTR; 272 return (error); 273 } 274 275 int 276 sys_socketpair(p, v, retval) 277 struct proc *p; 278 void *v; 279 register_t *retval; 280 { 281 register struct sys_socketpair_args /* { 282 syscallarg(int) domain; 283 syscallarg(int) type; 284 syscallarg(int) protocol; 285 syscallarg(int *) rsv; 286 } */ *uap = v; 287 register struct filedesc *fdp = p->p_fd; 288 struct file *fp1, *fp2; 289 struct socket *so1, *so2; 290 int fd, error, sv[2]; 291 292 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 293 SCARG(uap, protocol)); 294 if (error) 295 return (error); 296 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 297 SCARG(uap, protocol)); 298 if (error) 299 goto free1; 300 if ((error = falloc(p, &fp1, &fd)) != 0) 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(p, &fp2, &fd)) != 0) 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)) != 0) 315 goto free4; 316 if (SCARG(uap, type) == SOCK_DGRAM) { 317 /* 318 * Datagram socket connection is asymmetric. 319 */ 320 if ((error = soconnect2(so2, so1)) != 0) 321 goto free4; 322 } 323 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), 324 2 * sizeof (int)); 325 return (error); 326 free4: 327 ffree(fp2); 328 fdp->fd_ofiles[sv[1]] = 0; 329 free3: 330 ffree(fp1); 331 fdp->fd_ofiles[sv[0]] = 0; 332 free2: 333 (void)soclose(so2); 334 free1: 335 (void)soclose(so1); 336 return (error); 337 } 338 339 int 340 sys_sendto(p, v, retval) 341 struct proc *p; 342 void *v; 343 register_t *retval; 344 { 345 register struct sys_sendto_args /* { 346 syscallarg(int) s; 347 syscallarg(caddr_t) buf; 348 syscallarg(size_t) len; 349 syscallarg(int) flags; 350 syscallarg(caddr_t) to; 351 syscallarg(int) tolen; 352 } */ *uap = v; 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 int 370 sys_sendmsg(p, v, retval) 371 struct proc *p; 372 void *v; 373 register_t *retval; 374 { 375 register struct sys_sendmsg_args /* { 376 syscallarg(int) s; 377 syscallarg(caddr_t) msg; 378 syscallarg(int) flags; 379 } */ *uap = v; 380 struct msghdr msg; 381 struct iovec aiov[UIO_SMALLIOV], *iov; 382 int error; 383 384 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg)); 385 if (error) 386 return (error); 387 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 388 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 389 return (EMSGSIZE); 390 MALLOC(iov, struct iovec *, 391 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 392 M_WAITOK); 393 } else 394 iov = aiov; 395 if (msg.msg_iovlen && 396 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 397 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 398 goto done; 399 msg.msg_iov = iov; 400 #ifdef COMPAT_OLDSOCK 401 msg.msg_flags = 0; 402 #endif 403 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 404 done: 405 if (iov != aiov) 406 FREE(iov, M_IOV); 407 return (error); 408 } 409 410 int 411 sendit(p, s, mp, flags, retsize) 412 register struct proc *p; 413 int s; 414 register struct msghdr *mp; 415 int flags; 416 register_t *retsize; 417 { 418 struct file *fp; 419 struct uio auio; 420 register struct iovec *iov; 421 register int i; 422 struct mbuf *to, *control; 423 int len, error; 424 #ifdef KTRACE 425 struct iovec *ktriov = NULL; 426 #endif 427 428 if ((error = getsock(p->p_fd, s, &fp)) != 0) 429 return (error); 430 auio.uio_iov = mp->msg_iov; 431 auio.uio_iovcnt = mp->msg_iovlen; 432 auio.uio_segflg = UIO_USERSPACE; 433 auio.uio_rw = UIO_WRITE; 434 auio.uio_procp = p; 435 auio.uio_offset = 0; /* XXX */ 436 auio.uio_resid = 0; 437 iov = mp->msg_iov; 438 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 439 #if 0 440 /* cannot happen; iov_len is unsigned */ 441 if (iov->iov_len < 0) 442 return (EINVAL); 443 #endif 444 if ((auio.uio_resid += iov->iov_len) < 0) 445 return (EINVAL); 446 } 447 if (mp->msg_name) { 448 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 449 MT_SONAME); 450 if (error) 451 return (error); 452 } else 453 to = 0; 454 if (mp->msg_control) { 455 if (mp->msg_controllen < sizeof(struct cmsghdr) 456 #ifdef COMPAT_OLDSOCK 457 && mp->msg_flags != MSG_COMPAT 458 #endif 459 ) { 460 error = EINVAL; 461 goto bad; 462 } 463 error = sockargs(&control, mp->msg_control, 464 mp->msg_controllen, MT_CONTROL); 465 if (error) 466 goto bad; 467 #ifdef COMPAT_OLDSOCK 468 if (mp->msg_flags == MSG_COMPAT) { 469 register struct cmsghdr *cm; 470 471 M_PREPEND(control, sizeof(*cm), M_WAIT); 472 if (control == 0) { 473 error = ENOBUFS; 474 goto bad; 475 } else { 476 cm = mtod(control, struct cmsghdr *); 477 cm->cmsg_len = control->m_len; 478 cm->cmsg_level = SOL_SOCKET; 479 cm->cmsg_type = SCM_RIGHTS; 480 } 481 } 482 #endif 483 } else 484 control = 0; 485 #ifdef KTRACE 486 if (KTRPOINT(p, KTR_GENIO)) { 487 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 488 489 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 490 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 491 } 492 #endif 493 len = auio.uio_resid; 494 error = sosend((struct socket *)fp->f_data, to, &auio, 495 NULL, control, flags); 496 if (error) { 497 if (auio.uio_resid != len && (error == ERESTART || 498 error == EINTR || error == EWOULDBLOCK)) 499 error = 0; 500 if (error == EPIPE) 501 psignal(p, SIGPIPE); 502 } 503 if (error == 0) 504 *retsize = len - auio.uio_resid; 505 #ifdef KTRACE 506 if (ktriov != NULL) { 507 if (error == 0) 508 ktrgenio(p->p_tracep, s, UIO_WRITE, 509 ktriov, *retsize, error); 510 FREE(ktriov, M_TEMP); 511 } 512 #endif 513 bad: 514 if (to) 515 m_freem(to); 516 return (error); 517 } 518 519 int 520 sys_recvfrom(p, v, retval) 521 struct proc *p; 522 void *v; 523 register_t *retval; 524 { 525 register struct sys_recvfrom_args /* { 526 syscallarg(int) s; 527 syscallarg(caddr_t) buf; 528 syscallarg(size_t) len; 529 syscallarg(int) flags; 530 syscallarg(caddr_t) from; 531 syscallarg(int *) fromlenaddr; 532 } */ *uap = v; 533 struct msghdr msg; 534 struct iovec aiov; 535 int error; 536 537 if (SCARG(uap, fromlenaddr)) { 538 error = copyin((caddr_t)SCARG(uap, fromlenaddr), 539 (caddr_t)&msg.msg_namelen, 540 sizeof (msg.msg_namelen)); 541 if (error) 542 return (error); 543 } else 544 msg.msg_namelen = 0; 545 msg.msg_name = SCARG(uap, from); 546 msg.msg_iov = &aiov; 547 msg.msg_iovlen = 1; 548 aiov.iov_base = SCARG(uap, buf); 549 aiov.iov_len = SCARG(uap, len); 550 msg.msg_control = 0; 551 msg.msg_flags = SCARG(uap, flags); 552 return (recvit(p, SCARG(uap, s), &msg, 553 (caddr_t)SCARG(uap, fromlenaddr), retval)); 554 } 555 556 int 557 sys_recvmsg(p, v, retval) 558 struct proc *p; 559 void *v; 560 register_t *retval; 561 { 562 register struct sys_recvmsg_args /* { 563 syscallarg(int) s; 564 syscallarg(struct msghdr *) msg; 565 syscallarg(int) flags; 566 } */ *uap = v; 567 struct msghdr msg; 568 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 569 register int error; 570 571 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, 572 sizeof (msg)); 573 if (error) 574 return (error); 575 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 576 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 577 return (EMSGSIZE); 578 MALLOC(iov, struct iovec *, 579 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 580 M_WAITOK); 581 } else 582 iov = aiov; 583 #ifdef COMPAT_OLDSOCK 584 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; 585 #else 586 msg.msg_flags = SCARG(uap, flags); 587 #endif 588 uiov = msg.msg_iov; 589 msg.msg_iov = iov; 590 error = copyin((caddr_t)uiov, (caddr_t)iov, 591 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 592 if (error) 593 goto done; 594 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { 595 msg.msg_iov = uiov; 596 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), 597 sizeof(msg)); 598 } 599 done: 600 if (iov != aiov) 601 FREE(iov, M_IOV); 602 return (error); 603 } 604 605 int 606 recvit(p, s, mp, namelenp, retsize) 607 register struct proc *p; 608 int s; 609 register struct msghdr *mp; 610 caddr_t namelenp; 611 register_t *retsize; 612 { 613 struct file *fp; 614 struct uio auio; 615 register struct iovec *iov; 616 register int i; 617 int len, error; 618 struct mbuf *from = 0, *control = 0; 619 #ifdef KTRACE 620 struct iovec *ktriov = NULL; 621 #endif 622 623 if ((error = getsock(p->p_fd, s, &fp)) != 0) 624 return (error); 625 auio.uio_iov = mp->msg_iov; 626 auio.uio_iovcnt = mp->msg_iovlen; 627 auio.uio_segflg = UIO_USERSPACE; 628 auio.uio_rw = UIO_READ; 629 auio.uio_procp = p; 630 auio.uio_offset = 0; /* XXX */ 631 auio.uio_resid = 0; 632 iov = mp->msg_iov; 633 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 634 #if 0 635 /* cannot happen iov_len is unsigned */ 636 if (iov->iov_len < 0) 637 return (EINVAL); 638 #endif 639 if ((auio.uio_resid += iov->iov_len) < 0) 640 return (EINVAL); 641 } 642 #ifdef KTRACE 643 if (KTRPOINT(p, KTR_GENIO)) { 644 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 645 646 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 647 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 648 } 649 #endif 650 len = auio.uio_resid; 651 error = soreceive((struct socket *)fp->f_data, &from, &auio, 652 NULL, mp->msg_control ? &control : NULL, 653 &mp->msg_flags); 654 if (error) { 655 if (auio.uio_resid != len && (error == ERESTART || 656 error == EINTR || error == EWOULDBLOCK)) 657 error = 0; 658 } 659 #ifdef KTRACE 660 if (ktriov != NULL) { 661 if (error == 0) 662 ktrgenio(p->p_tracep, s, UIO_READ, 663 ktriov, len - auio.uio_resid, error); 664 FREE(ktriov, M_TEMP); 665 } 666 #endif 667 if (error) 668 goto out; 669 *retsize = len - auio.uio_resid; 670 if (mp->msg_name) { 671 len = mp->msg_namelen; 672 if (len <= 0 || from == 0) 673 len = 0; 674 else { 675 #ifdef COMPAT_OLDSOCK 676 if (mp->msg_flags & MSG_COMPAT) 677 mtod(from, struct osockaddr *)->sa_family = 678 mtod(from, struct sockaddr *)->sa_family; 679 #endif 680 if (len > from->m_len) 681 len = from->m_len; 682 /* else if len < from->m_len ??? */ 683 error = copyout(mtod(from, caddr_t), 684 (caddr_t)mp->msg_name, (unsigned)len); 685 if (error) 686 goto out; 687 } 688 mp->msg_namelen = len; 689 if (namelenp && 690 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 691 #ifdef COMPAT_OLDSOCK 692 if (mp->msg_flags & MSG_COMPAT) 693 error = 0; /* old recvfrom didn't check */ 694 else 695 #endif 696 goto out; 697 } 698 } 699 if (mp->msg_control) { 700 #ifdef COMPAT_OLDSOCK 701 /* 702 * We assume that old recvmsg calls won't receive access 703 * rights and other control info, esp. as control info 704 * is always optional and those options didn't exist in 4.3. 705 * If we receive rights, trim the cmsghdr; anything else 706 * is tossed. 707 */ 708 if (control && mp->msg_flags & MSG_COMPAT) { 709 if (mtod(control, struct cmsghdr *)->cmsg_level != 710 SOL_SOCKET || 711 mtod(control, struct cmsghdr *)->cmsg_type != 712 SCM_RIGHTS) { 713 mp->msg_controllen = 0; 714 goto out; 715 } 716 control->m_len -= sizeof (struct cmsghdr); 717 control->m_data += sizeof (struct cmsghdr); 718 } 719 #endif 720 len = mp->msg_controllen; 721 if (len <= 0 || control == 0) 722 len = 0; 723 else { 724 if (len >= control->m_len) 725 len = control->m_len; 726 else 727 mp->msg_flags |= MSG_CTRUNC; 728 error = copyout((caddr_t)mtod(control, caddr_t), 729 (caddr_t)mp->msg_control, (unsigned)len); 730 } 731 mp->msg_controllen = len; 732 } 733 out: 734 if (from) 735 m_freem(from); 736 if (control) 737 m_freem(control); 738 return (error); 739 } 740 741 /* ARGSUSED */ 742 int 743 sys_shutdown(p, v, retval) 744 struct proc *p; 745 void *v; 746 register_t *retval; 747 { 748 register struct sys_shutdown_args /* { 749 syscallarg(int) s; 750 syscallarg(int) how; 751 } */ *uap = v; 752 struct file *fp; 753 int error; 754 755 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 756 return (error); 757 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how))); 758 } 759 760 /* ARGSUSED */ 761 int 762 sys_setsockopt(p, v, retval) 763 struct proc *p; 764 void *v; 765 register_t *retval; 766 { 767 register struct sys_setsockopt_args /* { 768 syscallarg(int) s; 769 syscallarg(int) level; 770 syscallarg(int) name; 771 syscallarg(caddr_t) val; 772 syscallarg(int) valsize; 773 } */ *uap = v; 774 struct file *fp; 775 struct mbuf *m = NULL; 776 int error; 777 778 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 779 return (error); 780 if (SCARG(uap, valsize) > MLEN) 781 return (EINVAL); 782 if (SCARG(uap, val)) { 783 m = m_get(M_WAIT, MT_SOOPTS); 784 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 785 (u_int)SCARG(uap, valsize)); 786 if (error) { 787 (void) m_free(m); 788 return (error); 789 } 790 m->m_len = SCARG(uap, valsize); 791 } 792 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 793 SCARG(uap, name), m)); 794 } 795 796 /* ARGSUSED */ 797 int 798 sys_getsockopt(p, v, retval) 799 struct proc *p; 800 void *v; 801 register_t *retval; 802 { 803 register struct sys_getsockopt_args /* { 804 syscallarg(int) s; 805 syscallarg(int) level; 806 syscallarg(int) name; 807 syscallarg(caddr_t) val; 808 syscallarg(int *) avalsize; 809 } */ *uap = v; 810 struct file *fp; 811 struct mbuf *m = NULL; 812 int valsize, error; 813 814 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 815 return (error); 816 if (SCARG(uap, val)) { 817 error = copyin((caddr_t)SCARG(uap, avalsize), 818 (caddr_t)&valsize, sizeof (valsize)); 819 if (error) 820 return (error); 821 } else 822 valsize = 0; 823 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), 824 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && 825 m != NULL) { 826 if (valsize > m->m_len) 827 valsize = m->m_len; 828 error = copyout(mtod(m, caddr_t), SCARG(uap, val), 829 (u_int)valsize); 830 if (error == 0) 831 error = copyout((caddr_t)&valsize, 832 (caddr_t)SCARG(uap, avalsize), sizeof (valsize)); 833 } 834 if (m != NULL) 835 (void) m_free(m); 836 return (error); 837 } 838 839 /* ARGSUSED */ 840 int 841 sys_pipe(p, v, retval) 842 struct proc *p; 843 void *v; 844 register_t *retval; 845 { 846 register struct filedesc *fdp = p->p_fd; 847 struct file *rf, *wf; 848 struct socket *rso, *wso; 849 int fd, error; 850 851 if ((error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0)) != 0) 852 return (error); 853 if ((error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0)) != 0) 854 goto free1; 855 if ((error = falloc(p, &rf, &fd)) != 0) 856 goto free2; 857 retval[0] = fd; 858 rf->f_flag = FREAD; 859 rf->f_type = DTYPE_SOCKET; 860 rf->f_ops = &socketops; 861 rf->f_data = (caddr_t)rso; 862 if ((error = falloc(p, &wf, &fd)) != 0) 863 goto free3; 864 wf->f_flag = FWRITE; 865 wf->f_type = DTYPE_SOCKET; 866 wf->f_ops = &socketops; 867 wf->f_data = (caddr_t)wso; 868 retval[1] = fd; 869 if ((error = unp_connect2(wso, rso)) != 0) 870 goto free4; 871 return (0); 872 free4: 873 ffree(wf); 874 fdp->fd_ofiles[retval[1]] = 0; 875 free3: 876 ffree(rf); 877 fdp->fd_ofiles[retval[0]] = 0; 878 free2: 879 (void)soclose(wso); 880 free1: 881 (void)soclose(rso); 882 return (error); 883 } 884 885 /* 886 * Get socket name. 887 */ 888 /* ARGSUSED */ 889 int 890 sys_getsockname(p, v, retval) 891 struct proc *p; 892 void *v; 893 register_t *retval; 894 { 895 register struct sys_getsockname_args /* { 896 syscallarg(int) fdes; 897 syscallarg(caddr_t) asa; 898 syscallarg(int *) alen; 899 } */ *uap = v; 900 struct file *fp; 901 register struct socket *so; 902 struct mbuf *m; 903 int len, error; 904 905 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 906 return (error); 907 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); 908 if (error) 909 return (error); 910 so = (struct socket *)fp->f_data; 911 m = m_getclr(M_WAIT, MT_SONAME); 912 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0, 913 m, (struct mbuf *)0, (struct proc *)0); 914 if (error) 915 goto bad; 916 if (len > m->m_len) 917 len = m->m_len; 918 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); 919 if (error == 0) 920 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), 921 sizeof (len)); 922 bad: 923 m_freem(m); 924 return (error); 925 } 926 927 /* 928 * Get name of peer for connected socket. 929 */ 930 /* ARGSUSED */ 931 int 932 sys_getpeername(p, v, retval) 933 struct proc *p; 934 void *v; 935 register_t *retval; 936 { 937 register struct sys_getpeername_args /* { 938 syscallarg(int) fdes; 939 syscallarg(caddr_t) asa; 940 syscallarg(int *) alen; 941 } */ *uap = v; 942 struct file *fp; 943 register struct socket *so; 944 struct mbuf *m; 945 int len, error; 946 947 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 948 return (error); 949 so = (struct socket *)fp->f_data; 950 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 951 return (ENOTCONN); 952 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)); 953 if (error) 954 return (error); 955 m = m_getclr(M_WAIT, MT_SONAME); 956 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0, 957 m, (struct mbuf *)0, (struct proc *)0); 958 if (error) 959 goto bad; 960 if (len > m->m_len) 961 len = m->m_len; 962 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); 963 if (error) 964 goto bad; 965 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len)); 966 bad: 967 m_freem(m); 968 return (error); 969 } 970 971 int 972 sockargs(mp, buf, buflen, type) 973 struct mbuf **mp; 974 caddr_t buf; 975 int buflen, type; 976 { 977 register struct sockaddr *sa; 978 register struct mbuf *m; 979 int error; 980 981 if ((u_int)buflen > MLEN) { 982 #ifdef COMPAT_OLDSOCK 983 if (type == MT_SONAME && (u_int)buflen <= 112) 984 buflen = MLEN; /* unix domain compat. hack */ 985 else 986 #endif 987 return (EINVAL); 988 } 989 m = m_get(M_WAIT, type); 990 m->m_len = buflen; 991 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 992 if (error) { 993 (void) m_free(m); 994 return (error); 995 } 996 *mp = m; 997 if (type == MT_SONAME) { 998 sa = mtod(m, struct sockaddr *); 999 1000 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1001 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1002 sa->sa_family = sa->sa_len; 1003 #endif 1004 sa->sa_len = buflen; 1005 } 1006 return (0); 1007 } 1008 1009 int 1010 getsock(fdp, fdes, fpp) 1011 struct filedesc *fdp; 1012 int fdes; 1013 struct file **fpp; 1014 { 1015 register struct file *fp; 1016 1017 if ((unsigned)fdes >= fdp->fd_nfiles || 1018 (fp = fdp->fd_ofiles[fdes]) == NULL) 1019 return (EBADF); 1020 if (fp->f_type != DTYPE_SOCKET) 1021 return (ENOTSOCK); 1022 *fpp = fp; 1023 return (0); 1024 } 1025