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