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