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