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