1 /* $NetBSD: uipc_syscalls.c,v 1.38 1998/08/04 19:48:35 kleink 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.6 (Berkeley) 2/14/95 36 */ 37 38 #include "opt_ktrace.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/filedesc.h> 43 #include <sys/proc.h> 44 #include <sys/file.h> 45 #include <sys/buf.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.h> 48 #include <sys/protosw.h> 49 #include <sys/socket.h> 50 #include <sys/socketvar.h> 51 #include <sys/signalvar.h> 52 #include <sys/un.h> 53 #ifdef KTRACE 54 #include <sys/ktrace.h> 55 #endif 56 57 #include <sys/mount.h> 58 #include <sys/syscallargs.h> 59 60 /* 61 * System call interface to the socket abstraction. 62 */ 63 extern struct fileops socketops; 64 65 int 66 sys_socket(p, v, retval) 67 struct proc *p; 68 void *v; 69 register_t *retval; 70 { 71 register struct sys_socket_args /* { 72 syscallarg(int) domain; 73 syscallarg(int) type; 74 syscallarg(int) protocol; 75 } */ *uap = v; 76 struct filedesc *fdp = p->p_fd; 77 struct socket *so; 78 struct file *fp; 79 int fd, error; 80 81 if ((error = falloc(p, &fp, &fd)) != 0) 82 return (error); 83 fp->f_flag = FREAD|FWRITE; 84 fp->f_type = DTYPE_SOCKET; 85 fp->f_ops = &socketops; 86 error = socreate(SCARG(uap, domain), &so, SCARG(uap, type), 87 SCARG(uap, protocol)); 88 if (error) { 89 fdp->fd_ofiles[fd] = 0; 90 ffree(fp); 91 } else { 92 fp->f_data = (caddr_t)so; 93 *retval = fd; 94 } 95 return (error); 96 } 97 98 /* ARGSUSED */ 99 int 100 sys_bind(p, v, retval) 101 struct proc *p; 102 void *v; 103 register_t *retval; 104 { 105 register struct sys_bind_args /* { 106 syscallarg(int) s; 107 syscallarg(const struct sockaddr *) name; 108 syscallarg(int) namelen; 109 } */ *uap = v; 110 struct file *fp; 111 struct mbuf *nam; 112 int error; 113 114 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 115 return (error); 116 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 117 MT_SONAME); 118 if (error) 119 return (error); 120 error = sobind((struct socket *)fp->f_data, nam); 121 m_freem(nam); 122 return (error); 123 } 124 125 /* ARGSUSED */ 126 int 127 sys_listen(p, v, retval) 128 struct proc *p; 129 void *v; 130 register_t *retval; 131 { 132 register struct sys_listen_args /* { 133 syscallarg(int) s; 134 syscallarg(int) backlog; 135 } */ *uap = v; 136 struct file *fp; 137 int error; 138 139 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 140 return (error); 141 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog))); 142 } 143 144 int 145 sys_accept(p, v, retval) 146 struct proc *p; 147 void *v; 148 register_t *retval; 149 { 150 register struct sys_accept_args /* { 151 syscallarg(int) s; 152 syscallarg(struct sockaddr *) name; 153 syscallarg(int *) anamelen; 154 } */ *uap = v; 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)) != 0) 164 return (error); 165 s = splsoftnet(); 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 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 181 netcon, 0); 182 if (error) { 183 splx(s); 184 return (error); 185 } 186 } 187 if (so->so_error) { 188 error = so->so_error; 189 so->so_error = 0; 190 splx(s); 191 return (error); 192 } 193 if ((error = falloc(p, &fp, &tmpfd)) != 0) { 194 splx(s); 195 return (error); 196 } 197 *retval = tmpfd; 198 { struct socket *aso = so->so_q.tqh_first; 199 if (soqremque(aso, 1) == 0) 200 panic("accept"); 201 so = aso; 202 } 203 fp->f_type = DTYPE_SOCKET; 204 fp->f_flag = FREAD|FWRITE; 205 fp->f_ops = &socketops; 206 fp->f_data = (caddr_t)so; 207 nam = m_get(M_WAIT, MT_SONAME); 208 (void) soaccept(so, nam); 209 if (SCARG(uap, name)) { 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), 214 (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0) 215 error = copyout((caddr_t)&namelen, 216 (caddr_t)SCARG(uap, anamelen), 217 sizeof(*SCARG(uap, anamelen))); 218 } 219 m_freem(nam); 220 splx(s); 221 return (error); 222 } 223 224 /* ARGSUSED */ 225 int 226 sys_connect(p, v, retval) 227 struct proc *p; 228 void *v; 229 register_t *retval; 230 { 231 register struct sys_connect_args /* { 232 syscallarg(int) s; 233 syscallarg(const struct sockaddr *) name; 234 syscallarg(int) namelen; 235 } */ *uap = v; 236 struct file *fp; 237 register struct socket *so; 238 struct mbuf *nam; 239 int error, s; 240 241 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 242 return (error); 243 so = (struct socket *)fp->f_data; 244 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 245 return (EALREADY); 246 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), 247 MT_SONAME); 248 if (error) 249 return (error); 250 error = soconnect(so, nam); 251 if (error) 252 goto bad; 253 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 254 m_freem(nam); 255 return (EINPROGRESS); 256 } 257 s = splsoftnet(); 258 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 259 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 260 netcon, 0); 261 if (error) 262 break; 263 } 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 sys_socketpair(p, v, retval) 279 struct proc *p; 280 void *v; 281 register_t *retval; 282 { 283 register struct sys_socketpair_args /* { 284 syscallarg(int) domain; 285 syscallarg(int) type; 286 syscallarg(int) protocol; 287 syscallarg(int *) rsv; 288 } */ *uap = v; 289 register struct filedesc *fdp = p->p_fd; 290 struct file *fp1, *fp2; 291 struct socket *so1, *so2; 292 int fd, error, sv[2]; 293 294 error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type), 295 SCARG(uap, protocol)); 296 if (error) 297 return (error); 298 error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type), 299 SCARG(uap, protocol)); 300 if (error) 301 goto free1; 302 if ((error = falloc(p, &fp1, &fd)) != 0) 303 goto free2; 304 sv[0] = fd; 305 fp1->f_flag = FREAD|FWRITE; 306 fp1->f_type = DTYPE_SOCKET; 307 fp1->f_ops = &socketops; 308 fp1->f_data = (caddr_t)so1; 309 if ((error = falloc(p, &fp2, &fd)) != 0) 310 goto free3; 311 fp2->f_flag = FREAD|FWRITE; 312 fp2->f_type = DTYPE_SOCKET; 313 fp2->f_ops = &socketops; 314 fp2->f_data = (caddr_t)so2; 315 sv[1] = fd; 316 if ((error = soconnect2(so1, so2)) != 0) 317 goto free4; 318 if (SCARG(uap, type) == SOCK_DGRAM) { 319 /* 320 * Datagram socket connection is asymmetric. 321 */ 322 if ((error = soconnect2(so2, so1)) != 0) 323 goto free4; 324 } 325 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv), 326 2 * sizeof(int)); 327 return (error); 328 free4: 329 ffree(fp2); 330 fdp->fd_ofiles[sv[1]] = 0; 331 free3: 332 ffree(fp1); 333 fdp->fd_ofiles[sv[0]] = 0; 334 free2: 335 (void)soclose(so2); 336 free1: 337 (void)soclose(so1); 338 return (error); 339 } 340 341 int 342 sys_sendto(p, v, retval) 343 struct proc *p; 344 void *v; 345 register_t *retval; 346 { 347 register struct sys_sendto_args /* { 348 syscallarg(int) s; 349 syscallarg(const void *) buf; 350 syscallarg(size_t) len; 351 syscallarg(int) flags; 352 syscallarg(const struct sockaddr *) to; 353 syscallarg(int) tolen; 354 } */ *uap = v; 355 struct msghdr msg; 356 struct iovec aiov; 357 358 msg.msg_name = (caddr_t)SCARG(uap, to); /* XXX kills const */ 359 msg.msg_namelen = SCARG(uap, tolen); 360 msg.msg_iov = &aiov; 361 msg.msg_iovlen = 1; 362 msg.msg_control = 0; 363 #ifdef COMPAT_OLDSOCK 364 msg.msg_flags = 0; 365 #endif 366 aiov.iov_base = (char *)SCARG(uap, buf); /* XXX kills const */ 367 aiov.iov_len = SCARG(uap, len); 368 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); 369 } 370 371 int 372 sys_sendmsg(p, v, retval) 373 struct proc *p; 374 void *v; 375 register_t *retval; 376 { 377 register struct sys_sendmsg_args /* { 378 syscallarg(int) s; 379 syscallarg(const struct msghdr *) msg; 380 syscallarg(int) flags; 381 } */ *uap = v; 382 struct msghdr msg; 383 struct iovec aiov[UIO_SMALLIOV], *iov; 384 int error; 385 386 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg)); 387 if (error) 388 return (error); 389 if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) { 390 if ((u_int)msg.msg_iovlen > IOV_MAX) 391 return (EMSGSIZE); 392 MALLOC(iov, struct iovec *, 393 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 394 M_WAITOK); 395 } else if ((u_int)msg.msg_iovlen > 0) 396 iov = aiov; 397 else 398 return (EMSGSIZE); 399 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 400 (size_t)(msg.msg_iovlen * sizeof(struct iovec))); 401 if (error) 402 goto done; 403 msg.msg_iov = iov; 404 #ifdef COMPAT_OLDSOCK 405 msg.msg_flags = 0; 406 #endif 407 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 408 done: 409 if (iov != aiov) 410 FREE(iov, M_IOV); 411 return (error); 412 } 413 414 int 415 sendit(p, s, mp, flags, retsize) 416 register struct proc *p; 417 int s; 418 register struct msghdr *mp; 419 int flags; 420 register_t *retsize; 421 { 422 struct file *fp; 423 struct uio auio; 424 register struct iovec *iov; 425 register int i; 426 struct mbuf *to, *control; 427 int len, error; 428 struct socket *so; 429 #ifdef KTRACE 430 struct iovec *ktriov = NULL; 431 #endif 432 433 if ((error = getsock(p->p_fd, s, &fp)) != 0) 434 return (error); 435 auio.uio_iov = mp->msg_iov; 436 auio.uio_iovcnt = mp->msg_iovlen; 437 auio.uio_segflg = UIO_USERSPACE; 438 auio.uio_rw = UIO_WRITE; 439 auio.uio_procp = p; 440 auio.uio_offset = 0; /* XXX */ 441 auio.uio_resid = 0; 442 iov = mp->msg_iov; 443 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 444 #if 0 445 /* cannot happen; iov_len is unsigned */ 446 if (iov->iov_len < 0) 447 return (EINVAL); 448 #endif 449 /* 450 * Writes return ssize_t because -1 is returned on error. 451 * Therefore, we must restrict the length to SSIZE_MAX to 452 * avoid garbage return values. 453 */ 454 auio.uio_resid += iov->iov_len; 455 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) 456 return (EINVAL); 457 } 458 if (mp->msg_name) { 459 error = sockargs(&to, mp->msg_name, mp->msg_namelen, 460 MT_SONAME); 461 if (error) 462 return (error); 463 } else 464 to = 0; 465 if (mp->msg_control) { 466 if (mp->msg_controllen < sizeof(struct cmsghdr) 467 #ifdef COMPAT_OLDSOCK 468 && mp->msg_flags != MSG_COMPAT 469 #endif 470 ) { 471 error = EINVAL; 472 goto bad; 473 } 474 error = sockargs(&control, mp->msg_control, 475 mp->msg_controllen, MT_CONTROL); 476 if (error) 477 goto bad; 478 #ifdef COMPAT_OLDSOCK 479 if (mp->msg_flags == MSG_COMPAT) { 480 register struct cmsghdr *cm; 481 482 M_PREPEND(control, sizeof(*cm), M_WAIT); 483 if (control == 0) { 484 error = ENOBUFS; 485 goto bad; 486 } else { 487 cm = mtod(control, struct cmsghdr *); 488 cm->cmsg_len = control->m_len; 489 cm->cmsg_level = SOL_SOCKET; 490 cm->cmsg_type = SCM_RIGHTS; 491 } 492 } 493 #endif 494 } else 495 control = 0; 496 #ifdef KTRACE 497 if (KTRPOINT(p, KTR_GENIO)) { 498 int iovlen = auio.uio_iovcnt * sizeof(struct iovec); 499 500 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 501 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); 502 } 503 #endif 504 len = auio.uio_resid; 505 so = (struct socket *)fp->f_data; 506 error = (*so->so_send)(so, to, &auio, NULL, control, flags); 507 if (error) { 508 if (auio.uio_resid != len && (error == ERESTART || 509 error == EINTR || error == EWOULDBLOCK)) 510 error = 0; 511 if (error == EPIPE) 512 psignal(p, SIGPIPE); 513 } 514 if (error == 0) 515 *retsize = len - auio.uio_resid; 516 #ifdef KTRACE 517 if (ktriov != NULL) { 518 if (error == 0) 519 ktrgenio(p->p_tracep, s, UIO_WRITE, 520 ktriov, *retsize, error); 521 FREE(ktriov, M_TEMP); 522 } 523 #endif 524 bad: 525 if (to) 526 m_freem(to); 527 return (error); 528 } 529 530 int 531 sys_recvfrom(p, v, retval) 532 struct proc *p; 533 void *v; 534 register_t *retval; 535 { 536 register struct sys_recvfrom_args /* { 537 syscallarg(int) s; 538 syscallarg(void *) buf; 539 syscallarg(size_t) len; 540 syscallarg(int) flags; 541 syscallarg(struct sockaddr *) from; 542 syscallarg(int *) fromlenaddr; 543 } */ *uap = v; 544 struct msghdr msg; 545 struct iovec aiov; 546 int error; 547 548 if (SCARG(uap, fromlenaddr)) { 549 error = copyin((caddr_t)SCARG(uap, fromlenaddr), 550 (caddr_t)&msg.msg_namelen, 551 sizeof(msg.msg_namelen)); 552 if (error) 553 return (error); 554 } else 555 msg.msg_namelen = 0; 556 msg.msg_name = (caddr_t)SCARG(uap, from); 557 msg.msg_iov = &aiov; 558 msg.msg_iovlen = 1; 559 aiov.iov_base = SCARG(uap, buf); 560 aiov.iov_len = SCARG(uap, len); 561 msg.msg_control = 0; 562 msg.msg_flags = SCARG(uap, flags); 563 return (recvit(p, SCARG(uap, s), &msg, 564 (caddr_t)SCARG(uap, fromlenaddr), retval)); 565 } 566 567 int 568 sys_recvmsg(p, v, retval) 569 struct proc *p; 570 void *v; 571 register_t *retval; 572 { 573 register struct sys_recvmsg_args /* { 574 syscallarg(int) s; 575 syscallarg(struct msghdr *) msg; 576 syscallarg(int) flags; 577 } */ *uap = v; 578 struct msghdr msg; 579 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 580 register int error; 581 582 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg, 583 sizeof(msg)); 584 if (error) 585 return (error); 586 if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) { 587 if ((u_int)msg.msg_iovlen > IOV_MAX) 588 return (EMSGSIZE); 589 MALLOC(iov, struct iovec *, 590 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 591 M_WAITOK); 592 } else if ((u_int)msg.msg_iovlen > 0) 593 iov = aiov; 594 else 595 return (EMSGSIZE); 596 #ifdef COMPAT_OLDSOCK 597 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; 598 #else 599 msg.msg_flags = SCARG(uap, flags); 600 #endif 601 uiov = msg.msg_iov; 602 msg.msg_iov = iov; 603 error = copyin((caddr_t)uiov, (caddr_t)iov, 604 (size_t)(msg.msg_iovlen * sizeof(struct iovec))); 605 if (error) 606 goto done; 607 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) { 608 msg.msg_iov = uiov; 609 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg), 610 sizeof(msg)); 611 } 612 done: 613 if (iov != aiov) 614 FREE(iov, M_IOV); 615 return (error); 616 } 617 618 int 619 recvit(p, s, mp, namelenp, retsize) 620 register struct proc *p; 621 int s; 622 register struct msghdr *mp; 623 caddr_t namelenp; 624 register_t *retsize; 625 { 626 struct file *fp; 627 struct uio auio; 628 register struct iovec *iov; 629 register int i; 630 int len, error; 631 struct mbuf *from = 0, *control = 0; 632 struct socket *so; 633 #ifdef KTRACE 634 struct iovec *ktriov = NULL; 635 #endif 636 637 if ((error = getsock(p->p_fd, s, &fp)) != 0) 638 return (error); 639 auio.uio_iov = mp->msg_iov; 640 auio.uio_iovcnt = mp->msg_iovlen; 641 auio.uio_segflg = UIO_USERSPACE; 642 auio.uio_rw = UIO_READ; 643 auio.uio_procp = p; 644 auio.uio_offset = 0; /* XXX */ 645 auio.uio_resid = 0; 646 iov = mp->msg_iov; 647 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 648 #if 0 649 /* cannot happen iov_len is unsigned */ 650 if (iov->iov_len < 0) 651 return (EINVAL); 652 #endif 653 /* 654 * Reads return ssize_t because -1 is returned on error. 655 * Therefore we must restrict the length to SSIZE_MAX to 656 * avoid garbage return values. 657 */ 658 auio.uio_resid += iov->iov_len; 659 if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) 660 return (EINVAL); 661 } 662 #ifdef KTRACE 663 if (KTRPOINT(p, KTR_GENIO)) { 664 int iovlen = auio.uio_iovcnt * sizeof(struct iovec); 665 666 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 667 memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); 668 } 669 #endif 670 len = auio.uio_resid; 671 so = (struct socket *)fp->f_data; 672 error = (*so->so_receive)(so, &from, &auio, NULL, 673 mp->msg_control ? &control : NULL, &mp->msg_flags); 674 if (error) { 675 if (auio.uio_resid != len && (error == ERESTART || 676 error == EINTR || error == EWOULDBLOCK)) 677 error = 0; 678 } 679 #ifdef KTRACE 680 if (ktriov != NULL) { 681 if (error == 0) 682 ktrgenio(p->p_tracep, s, UIO_READ, 683 ktriov, len - auio.uio_resid, error); 684 FREE(ktriov, M_TEMP); 685 } 686 #endif 687 if (error) 688 goto out; 689 *retsize = len - auio.uio_resid; 690 if (mp->msg_name) { 691 len = mp->msg_namelen; 692 if (len <= 0 || from == 0) 693 len = 0; 694 else { 695 #ifdef COMPAT_OLDSOCK 696 if (mp->msg_flags & MSG_COMPAT) 697 mtod(from, struct osockaddr *)->sa_family = 698 mtod(from, struct sockaddr *)->sa_family; 699 #endif 700 if (len > from->m_len) 701 len = from->m_len; 702 /* else if len < from->m_len ??? */ 703 error = copyout(mtod(from, caddr_t), 704 (caddr_t)mp->msg_name, (unsigned)len); 705 if (error) 706 goto out; 707 } 708 mp->msg_namelen = len; 709 if (namelenp && 710 (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) { 711 #ifdef COMPAT_OLDSOCK 712 if (mp->msg_flags & MSG_COMPAT) 713 error = 0; /* old recvfrom didn't check */ 714 else 715 #endif 716 goto out; 717 } 718 } 719 if (mp->msg_control) { 720 #ifdef COMPAT_OLDSOCK 721 /* 722 * We assume that old recvmsg calls won't receive access 723 * rights and other control info, esp. as control info 724 * is always optional and those options didn't exist in 4.3. 725 * If we receive rights, trim the cmsghdr; anything else 726 * is tossed. 727 */ 728 if (control && mp->msg_flags & MSG_COMPAT) { 729 if (mtod(control, struct cmsghdr *)->cmsg_level != 730 SOL_SOCKET || 731 mtod(control, struct cmsghdr *)->cmsg_type != 732 SCM_RIGHTS) { 733 mp->msg_controllen = 0; 734 goto out; 735 } 736 control->m_len -= sizeof(struct cmsghdr); 737 control->m_data += sizeof(struct cmsghdr); 738 } 739 #endif 740 len = mp->msg_controllen; 741 if (len <= 0 || control == 0) 742 len = 0; 743 else { 744 struct mbuf *m = control; 745 caddr_t p = (caddr_t)mp->msg_control; 746 747 do { 748 i = m->m_len; 749 if (len < i) { 750 mp->msg_flags |= MSG_CTRUNC; 751 i = len; 752 } 753 error = copyout(mtod(m, caddr_t), p, 754 (unsigned)i); 755 if (m->m_next) 756 i = ALIGN(i); 757 p += i; 758 len -= i; 759 if (error != 0 || len <= 0) 760 break; 761 } while ((m = m->m_next) != NULL); 762 len = p - (caddr_t)mp->msg_control; 763 } 764 mp->msg_controllen = len; 765 } 766 out: 767 if (from) 768 m_freem(from); 769 if (control) 770 m_freem(control); 771 return (error); 772 } 773 774 /* ARGSUSED */ 775 int 776 sys_shutdown(p, v, retval) 777 struct proc *p; 778 void *v; 779 register_t *retval; 780 { 781 register struct sys_shutdown_args /* { 782 syscallarg(int) s; 783 syscallarg(int) how; 784 } */ *uap = v; 785 struct file *fp; 786 int error; 787 788 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 789 return (error); 790 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how))); 791 } 792 793 /* ARGSUSED */ 794 int 795 sys_setsockopt(p, v, retval) 796 struct proc *p; 797 void *v; 798 register_t *retval; 799 { 800 register struct sys_setsockopt_args /* { 801 syscallarg(int) s; 802 syscallarg(int) level; 803 syscallarg(int) name; 804 syscallarg(const void *) val; 805 syscallarg(int) valsize; 806 } */ *uap = v; 807 struct file *fp; 808 struct mbuf *m = NULL; 809 int error; 810 811 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 812 return (error); 813 if (SCARG(uap, valsize) > MLEN) 814 return (EINVAL); 815 if (SCARG(uap, val)) { 816 m = m_get(M_WAIT, MT_SOOPTS); 817 error = copyin(SCARG(uap, val), mtod(m, caddr_t), 818 (u_int)SCARG(uap, valsize)); 819 if (error) { 820 (void) m_free(m); 821 return (error); 822 } 823 m->m_len = SCARG(uap, valsize); 824 } 825 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level), 826 SCARG(uap, name), m)); 827 } 828 829 /* ARGSUSED */ 830 int 831 sys_getsockopt(p, v, retval) 832 struct proc *p; 833 void *v; 834 register_t *retval; 835 { 836 register struct sys_getsockopt_args /* { 837 syscallarg(int) s; 838 syscallarg(int) level; 839 syscallarg(int) name; 840 syscallarg(void *) val; 841 syscallarg(int *) avalsize; 842 } */ *uap = v; 843 struct file *fp; 844 struct mbuf *m = NULL; 845 int valsize, error; 846 847 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) 848 return (error); 849 if (SCARG(uap, val)) { 850 error = copyin((caddr_t)SCARG(uap, avalsize), 851 (caddr_t)&valsize, sizeof(valsize)); 852 if (error) 853 return (error); 854 } else 855 valsize = 0; 856 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), 857 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize && 858 m != NULL) { 859 if (valsize > m->m_len) 860 valsize = m->m_len; 861 error = copyout(mtod(m, caddr_t), SCARG(uap, val), 862 (u_int)valsize); 863 if (error == 0) 864 error = copyout((caddr_t)&valsize, 865 (caddr_t)SCARG(uap, avalsize), sizeof(valsize)); 866 } 867 if (m != NULL) 868 (void) m_free(m); 869 return (error); 870 } 871 872 /* ARGSUSED */ 873 int 874 sys_pipe(p, v, retval) 875 struct proc *p; 876 void *v; 877 register_t *retval; 878 { 879 register struct filedesc *fdp = p->p_fd; 880 struct file *rf, *wf; 881 struct socket *rso, *wso; 882 int fd, error; 883 884 if ((error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0)) != 0) 885 return (error); 886 if ((error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0)) != 0) 887 goto free1; 888 if ((error = falloc(p, &rf, &fd)) != 0) 889 goto free2; 890 retval[0] = fd; 891 rf->f_flag = FREAD; 892 rf->f_type = DTYPE_SOCKET; 893 rf->f_ops = &socketops; 894 rf->f_data = (caddr_t)rso; 895 if ((error = falloc(p, &wf, &fd)) != 0) 896 goto free3; 897 wf->f_flag = FWRITE; 898 wf->f_type = DTYPE_SOCKET; 899 wf->f_ops = &socketops; 900 wf->f_data = (caddr_t)wso; 901 retval[1] = fd; 902 if ((error = unp_connect2(wso, rso)) != 0) 903 goto free4; 904 return (0); 905 free4: 906 ffree(wf); 907 fdp->fd_ofiles[retval[1]] = 0; 908 free3: 909 ffree(rf); 910 fdp->fd_ofiles[retval[0]] = 0; 911 free2: 912 (void)soclose(wso); 913 free1: 914 (void)soclose(rso); 915 return (error); 916 } 917 918 /* 919 * Get socket name. 920 */ 921 /* ARGSUSED */ 922 int 923 sys_getsockname(p, v, retval) 924 struct proc *p; 925 void *v; 926 register_t *retval; 927 { 928 register struct sys_getsockname_args /* { 929 syscallarg(int) fdes; 930 syscallarg(struct sockaddr *) asa; 931 syscallarg(int *) alen; 932 } */ *uap = v; 933 struct file *fp; 934 register struct socket *so; 935 struct mbuf *m; 936 int len, error; 937 938 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 939 return (error); 940 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len)); 941 if (error) 942 return (error); 943 so = (struct socket *)fp->f_data; 944 m = m_getclr(M_WAIT, MT_SONAME); 945 error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, (struct mbuf *)0, 946 m, (struct mbuf *)0, (struct proc *)0); 947 if (error) 948 goto bad; 949 if (len > m->m_len) 950 len = m->m_len; 951 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); 952 if (error == 0) 953 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), 954 sizeof(len)); 955 bad: 956 m_freem(m); 957 return (error); 958 } 959 960 /* 961 * Get name of peer for connected socket. 962 */ 963 /* ARGSUSED */ 964 int 965 sys_getpeername(p, v, retval) 966 struct proc *p; 967 void *v; 968 register_t *retval; 969 { 970 register struct sys_getpeername_args /* { 971 syscallarg(int) fdes; 972 syscallarg(struct sockaddr *) asa; 973 syscallarg(int *) alen; 974 } */ *uap = v; 975 struct file *fp; 976 register struct socket *so; 977 struct mbuf *m; 978 int len, error; 979 980 if ((error = getsock(p->p_fd, SCARG(uap, fdes), &fp)) != 0) 981 return (error); 982 so = (struct socket *)fp->f_data; 983 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 984 return (ENOTCONN); 985 error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof(len)); 986 if (error) 987 return (error); 988 m = m_getclr(M_WAIT, MT_SONAME); 989 error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, (struct mbuf *)0, 990 m, (struct mbuf *)0, (struct proc *)0); 991 if (error) 992 goto bad; 993 if (len > m->m_len) 994 len = m->m_len; 995 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len); 996 if (error) 997 goto bad; 998 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof(len)); 999 bad: 1000 m_freem(m); 1001 return (error); 1002 } 1003 1004 /* 1005 * XXX In a perfect world, we wouldn't pass around socket control 1006 * XXX arguments in mbufs, and this could go away. 1007 */ 1008 int 1009 sockargs(mp, buf, buflen, type) 1010 struct mbuf **mp; 1011 const void *buf; 1012 int buflen, type; 1013 { 1014 register struct sockaddr *sa; 1015 register struct mbuf *m; 1016 int error; 1017 1018 /* 1019 * We can't allow socket names > UCHAR_MAX in length, since that 1020 * will overflow sa_len. 1021 */ 1022 if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX) 1023 return (EINVAL); 1024 1025 /* Allocate an mbuf to hold the arguments. */ 1026 m = m_get(M_WAIT, type); 1027 if ((u_int)buflen > MLEN) { 1028 /* 1029 * Won't fit into a regular mbuf, so we allocate just 1030 * enough external storage to hold the argument. 1031 */ 1032 MEXTMALLOC(m, buflen, M_WAITOK); 1033 } 1034 m->m_len = buflen; 1035 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1036 if (error) { 1037 (void) m_free(m); 1038 return (error); 1039 } 1040 *mp = m; 1041 if (type == MT_SONAME) { 1042 sa = mtod(m, struct sockaddr *); 1043 1044 #if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1045 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1046 sa->sa_family = sa->sa_len; 1047 #endif 1048 sa->sa_len = buflen; 1049 } 1050 return (0); 1051 } 1052 1053 int 1054 getsock(fdp, fdes, fpp) 1055 struct filedesc *fdp; 1056 int fdes; 1057 struct file **fpp; 1058 { 1059 register struct file *fp; 1060 1061 if ((unsigned)fdes >= fdp->fd_nfiles || 1062 (fp = fdp->fd_ofiles[fdes]) == NULL) 1063 return (EBADF); 1064 if (fp->f_type != DTYPE_SOCKET) 1065 return (ENOTSOCK); 1066 *fpp = fp; 1067 return (0); 1068 } 1069