uipc_syscalls.c revision 35188
1/* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 34 * $Id: uipc_syscalls.c,v 1.38 1998/04/11 20:31:46 phk Exp $ 35 */ 36 37#include "opt_compat.h" 38#include "opt_ktrace.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/sysproto.h> 43#include <sys/malloc.h> 44#include <sys/filedesc.h> 45#include <sys/proc.h> 46#include <sys/fcntl.h> 47#include <sys/file.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/uio.h> 54#ifdef KTRACE 55#include <sys/ktrace.h> 56#endif 57 58static int sendit __P((struct proc *p, int s, struct msghdr *mp, int flags)); 59static int recvit __P((struct proc *p, int s, struct msghdr *mp, 60 caddr_t namelenp)); 61 62static int accept1 __P((struct proc *p, struct accept_args *uap, int compat)); 63static int getsockname1 __P((struct proc *p, struct getsockname_args *uap, 64 int compat)); 65static int getpeername1 __P((struct proc *p, struct getpeername_args *uap, 66 int compat)); 67 68/* 69 * System call interface to the socket abstraction. 70 */ 71#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 72#define COMPAT_OLDSOCK 73#endif 74 75extern struct fileops socketops; 76 77int 78socket(p, uap) 79 struct proc *p; 80 register struct socket_args /* { 81 int domain; 82 int type; 83 int protocol; 84 } */ *uap; 85{ 86 struct filedesc *fdp = p->p_fd; 87 struct socket *so; 88 struct file *fp; 89 int fd, error; 90 91 error = falloc(p, &fp, &fd); 92 if (error) 93 return (error); 94 fp->f_flag = FREAD|FWRITE; 95 fp->f_type = DTYPE_SOCKET; 96 fp->f_ops = &socketops; 97 error = socreate(uap->domain, &so, uap->type, uap->protocol, p); 98 if (error) { 99 fdp->fd_ofiles[fd] = 0; 100 ffree(fp); 101 } else { 102 fp->f_data = (caddr_t)so; 103 p->p_retval[0] = fd; 104 } 105 return (error); 106} 107 108/* ARGSUSED */ 109int 110bind(p, uap) 111 struct proc *p; 112 register struct bind_args /* { 113 int s; 114 caddr_t name; 115 int namelen; 116 } */ *uap; 117{ 118 struct file *fp; 119 struct sockaddr *sa; 120 int error; 121 122 error = getsock(p->p_fd, uap->s, &fp); 123 if (error) 124 return (error); 125 error = getsockaddr(&sa, uap->name, uap->namelen); 126 if (error) 127 return (error); 128 error = sobind((struct socket *)fp->f_data, sa, p); 129 FREE(sa, M_SONAME); 130 return (error); 131} 132 133/* ARGSUSED */ 134int 135listen(p, uap) 136 struct proc *p; 137 register struct listen_args /* { 138 int s; 139 int backlog; 140 } */ *uap; 141{ 142 struct file *fp; 143 int error; 144 145 error = getsock(p->p_fd, uap->s, &fp); 146 if (error) 147 return (error); 148 return (solisten((struct socket *)fp->f_data, uap->backlog, p)); 149} 150 151static int 152accept1(p, uap, compat) 153 struct proc *p; 154 register struct accept_args /* { 155 int s; 156 caddr_t name; 157 int *anamelen; 158 } */ *uap; 159 int compat; 160{ 161 struct file *fp; 162 struct sockaddr *sa; 163 int namelen, error, s; 164 struct socket *head, *so; 165 short fflag; /* type must match fp->f_flag */ 166 167 if (uap->name) { 168 error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 169 sizeof (namelen)); 170 if(error) 171 return (error); 172 } 173 error = getsock(p->p_fd, uap->s, &fp); 174 if (error) 175 return (error); 176 s = splnet(); 177 head = (struct socket *)fp->f_data; 178 if ((head->so_options & SO_ACCEPTCONN) == 0) { 179 splx(s); 180 return (EINVAL); 181 } 182 if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) { 183 splx(s); 184 return (EWOULDBLOCK); 185 } 186 while (head->so_comp.tqh_first == NULL && head->so_error == 0) { 187 if (head->so_state & SS_CANTRCVMORE) { 188 head->so_error = ECONNABORTED; 189 break; 190 } 191 error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH, 192 "accept", 0); 193 if (error) { 194 splx(s); 195 return (error); 196 } 197 } 198 if (head->so_error) { 199 error = head->so_error; 200 head->so_error = 0; 201 splx(s); 202 return (error); 203 } 204 205 /* 206 * At this point we know that there is at least one connection 207 * ready to be accepted. Remove it from the queue prior to 208 * allocating the file descriptor for it since falloc() may 209 * block allowing another process to accept the connection 210 * instead. 211 */ 212 so = head->so_comp.tqh_first; 213 TAILQ_REMOVE(&head->so_comp, so, so_list); 214 head->so_qlen--; 215 216 fflag = fp->f_flag; 217 error = falloc(p, &fp, p->p_retval); 218 if (error) { 219 /* 220 * Probably ran out of file descriptors. Put the 221 * unaccepted connection back onto the queue and 222 * do another wakeup so some other process might 223 * have a chance at it. 224 */ 225 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list); 226 head->so_qlen++; 227 wakeup_one(&head->so_timeo); 228 splx(s); 229 return (error); 230 } 231 232 so->so_state &= ~SS_COMP; 233 so->so_head = NULL; 234 235 fp->f_type = DTYPE_SOCKET; 236 fp->f_flag = fflag; 237 fp->f_ops = &socketops; 238 fp->f_data = (caddr_t)so; 239 sa = 0; 240 (void) soaccept(so, &sa); 241 if (sa == 0) { 242 namelen = 0; 243 if (uap->name) 244 goto gotnoname; 245 return 0; 246 } 247 if (uap->name) { 248 /* check sa_len before it is destroyed */ 249 if (namelen > sa->sa_len) 250 namelen = sa->sa_len; 251#ifdef COMPAT_OLDSOCK 252 if (compat) 253 ((struct osockaddr *)sa)->sa_family = 254 sa->sa_family; 255#endif 256 error = copyout(sa, (caddr_t)uap->name, (u_int)namelen); 257 if (!error) 258gotnoname: 259 error = copyout((caddr_t)&namelen, 260 (caddr_t)uap->anamelen, sizeof (*uap->anamelen)); 261 } 262 FREE(sa, M_SONAME); 263 splx(s); 264 return (error); 265} 266 267int 268accept(p, uap) 269 struct proc *p; 270 struct accept_args *uap; 271{ 272 273 return (accept1(p, uap, 0)); 274} 275 276#ifdef COMPAT_OLDSOCK 277int 278oaccept(p, uap) 279 struct proc *p; 280 struct accept_args *uap; 281{ 282 283 return (accept1(p, uap, 1)); 284} 285#endif /* COMPAT_OLDSOCK */ 286 287/* ARGSUSED */ 288int 289connect(p, uap) 290 struct proc *p; 291 register struct connect_args /* { 292 int s; 293 caddr_t name; 294 int namelen; 295 } */ *uap; 296{ 297 struct file *fp; 298 register struct socket *so; 299 struct sockaddr *sa; 300 int error, s; 301 302 error = getsock(p->p_fd, uap->s, &fp); 303 if (error) 304 return (error); 305 so = (struct socket *)fp->f_data; 306 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) 307 return (EALREADY); 308 error = getsockaddr(&sa, uap->name, uap->namelen); 309 if (error) 310 return (error); 311 error = soconnect(so, sa, p); 312 if (error) 313 goto bad; 314 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { 315 FREE(sa, M_SONAME); 316 return (EINPROGRESS); 317 } 318 s = splnet(); 319 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { 320 error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, 321 "connec", 0); 322 if (error) 323 break; 324 } 325 if (error == 0) { 326 error = so->so_error; 327 so->so_error = 0; 328 } 329 splx(s); 330bad: 331 so->so_state &= ~SS_ISCONNECTING; 332 FREE(sa, M_SONAME); 333 if (error == ERESTART) 334 error = EINTR; 335 return (error); 336} 337 338int 339socketpair(p, uap) 340 struct proc *p; 341 register struct socketpair_args /* { 342 int domain; 343 int type; 344 int protocol; 345 int *rsv; 346 } */ *uap; 347{ 348 register struct filedesc *fdp = p->p_fd; 349 struct file *fp1, *fp2; 350 struct socket *so1, *so2; 351 int fd, error, sv[2]; 352 353 error = socreate(uap->domain, &so1, uap->type, uap->protocol, p); 354 if (error) 355 return (error); 356 error = socreate(uap->domain, &so2, uap->type, uap->protocol, p); 357 if (error) 358 goto free1; 359 error = falloc(p, &fp1, &fd); 360 if (error) 361 goto free2; 362 sv[0] = fd; 363 fp1->f_flag = FREAD|FWRITE; 364 fp1->f_type = DTYPE_SOCKET; 365 fp1->f_ops = &socketops; 366 fp1->f_data = (caddr_t)so1; 367 error = falloc(p, &fp2, &fd); 368 if (error) 369 goto free3; 370 fp2->f_flag = FREAD|FWRITE; 371 fp2->f_type = DTYPE_SOCKET; 372 fp2->f_ops = &socketops; 373 fp2->f_data = (caddr_t)so2; 374 sv[1] = fd; 375 error = soconnect2(so1, so2); 376 if (error) 377 goto free4; 378 if (uap->type == SOCK_DGRAM) { 379 /* 380 * Datagram socket connection is asymmetric. 381 */ 382 error = soconnect2(so2, so1); 383 if (error) 384 goto free4; 385 } 386 error = copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 387 return (error); 388free4: 389 ffree(fp2); 390 fdp->fd_ofiles[sv[1]] = 0; 391free3: 392 ffree(fp1); 393 fdp->fd_ofiles[sv[0]] = 0; 394free2: 395 (void)soclose(so2); 396free1: 397 (void)soclose(so1); 398 return (error); 399} 400 401static int 402sendit(p, s, mp, flags) 403 register struct proc *p; 404 int s; 405 register struct msghdr *mp; 406 int flags; 407{ 408 struct file *fp; 409 struct uio auio; 410 register struct iovec *iov; 411 register int i; 412 struct mbuf *control; 413 struct sockaddr *to; 414 int len, error; 415 struct socket *so; 416#ifdef KTRACE 417 struct iovec *ktriov = NULL; 418#endif 419 420 error = getsock(p->p_fd, s, &fp); 421 if (error) 422 return (error); 423 auio.uio_iov = mp->msg_iov; 424 auio.uio_iovcnt = mp->msg_iovlen; 425 auio.uio_segflg = UIO_USERSPACE; 426 auio.uio_rw = UIO_WRITE; 427 auio.uio_procp = p; 428 auio.uio_offset = 0; /* XXX */ 429 auio.uio_resid = 0; 430 iov = mp->msg_iov; 431 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 432 if ((auio.uio_resid += iov->iov_len) < 0) 433 return (EINVAL); 434 } 435 if (mp->msg_name) { 436 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); 437 if (error) 438 return (error); 439 } else 440 to = 0; 441 if (mp->msg_control) { 442 if (mp->msg_controllen < sizeof(struct cmsghdr) 443#ifdef COMPAT_OLDSOCK 444 && mp->msg_flags != MSG_COMPAT 445#endif 446 ) { 447 error = EINVAL; 448 goto bad; 449 } 450 error = sockargs(&control, mp->msg_control, 451 mp->msg_controllen, MT_CONTROL); 452 if (error) 453 goto bad; 454#ifdef COMPAT_OLDSOCK 455 if (mp->msg_flags == MSG_COMPAT) { 456 register struct cmsghdr *cm; 457 458 M_PREPEND(control, sizeof(*cm), M_WAIT); 459 if (control == 0) { 460 error = ENOBUFS; 461 goto bad; 462 } else { 463 cm = mtod(control, struct cmsghdr *); 464 cm->cmsg_len = control->m_len; 465 cm->cmsg_level = SOL_SOCKET; 466 cm->cmsg_type = SCM_RIGHTS; 467 } 468 } 469#endif 470 } else 471 control = 0; 472#ifdef KTRACE 473 if (KTRPOINT(p, KTR_GENIO)) { 474 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 475 476 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 477 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 478 } 479#endif 480 len = auio.uio_resid; 481 so = (struct socket *)fp->f_data; 482 error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, 483 flags, p); 484 if (error) { 485 if (auio.uio_resid != len && (error == ERESTART || 486 error == EINTR || error == EWOULDBLOCK)) 487 error = 0; 488 if (error == EPIPE) 489 psignal(p, SIGPIPE); 490 } 491 if (error == 0) 492 p->p_retval[0] = len - auio.uio_resid; 493#ifdef KTRACE 494 if (ktriov != NULL) { 495 if (error == 0) 496 ktrgenio(p->p_tracep, s, UIO_WRITE, 497 ktriov, p->p_retval[0], error); 498 FREE(ktriov, M_TEMP); 499 } 500#endif 501bad: 502 if (to) 503 FREE(to, M_SONAME); 504 return (error); 505} 506 507int 508sendto(p, uap) 509 struct proc *p; 510 register struct sendto_args /* { 511 int s; 512 caddr_t buf; 513 size_t len; 514 int flags; 515 caddr_t to; 516 int tolen; 517 } */ *uap; 518{ 519 struct msghdr msg; 520 struct iovec aiov; 521 522 msg.msg_name = uap->to; 523 msg.msg_namelen = uap->tolen; 524 msg.msg_iov = &aiov; 525 msg.msg_iovlen = 1; 526 msg.msg_control = 0; 527#ifdef COMPAT_OLDSOCK 528 msg.msg_flags = 0; 529#endif 530 aiov.iov_base = uap->buf; 531 aiov.iov_len = uap->len; 532 return (sendit(p, uap->s, &msg, uap->flags)); 533} 534 535#ifdef COMPAT_OLDSOCK 536int 537osend(p, uap) 538 struct proc *p; 539 register struct osend_args /* { 540 int s; 541 caddr_t buf; 542 int len; 543 int flags; 544 } */ *uap; 545{ 546 struct msghdr msg; 547 struct iovec aiov; 548 549 msg.msg_name = 0; 550 msg.msg_namelen = 0; 551 msg.msg_iov = &aiov; 552 msg.msg_iovlen = 1; 553 aiov.iov_base = uap->buf; 554 aiov.iov_len = uap->len; 555 msg.msg_control = 0; 556 msg.msg_flags = 0; 557 return (sendit(p, uap->s, &msg, uap->flags)); 558} 559 560int 561osendmsg(p, uap) 562 struct proc *p; 563 register struct osendmsg_args /* { 564 int s; 565 caddr_t msg; 566 int flags; 567 } */ *uap; 568{ 569 struct msghdr msg; 570 struct iovec aiov[UIO_SMALLIOV], *iov; 571 int error; 572 573 error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr)); 574 if (error) 575 return (error); 576 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 577 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 578 return (EMSGSIZE); 579 MALLOC(iov, struct iovec *, 580 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 581 M_WAITOK); 582 } else 583 iov = aiov; 584 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 585 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 586 if (error) 587 goto done; 588 msg.msg_flags = MSG_COMPAT; 589 msg.msg_iov = iov; 590 error = sendit(p, uap->s, &msg, uap->flags); 591done: 592 if (iov != aiov) 593 FREE(iov, M_IOV); 594 return (error); 595} 596#endif 597 598int 599sendmsg(p, uap) 600 struct proc *p; 601 register struct sendmsg_args /* { 602 int s; 603 caddr_t msg; 604 int flags; 605 } */ *uap; 606{ 607 struct msghdr msg; 608 struct iovec aiov[UIO_SMALLIOV], *iov; 609 int error; 610 611 error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 612 if (error) 613 return (error); 614 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 615 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 616 return (EMSGSIZE); 617 MALLOC(iov, struct iovec *, 618 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 619 M_WAITOK); 620 } else 621 iov = aiov; 622 if (msg.msg_iovlen && 623 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 624 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) 625 goto done; 626 msg.msg_iov = iov; 627#ifdef COMPAT_OLDSOCK 628 msg.msg_flags = 0; 629#endif 630 error = sendit(p, uap->s, &msg, uap->flags); 631done: 632 if (iov != aiov) 633 FREE(iov, M_IOV); 634 return (error); 635} 636 637static int 638recvit(p, s, mp, namelenp) 639 register struct proc *p; 640 int s; 641 register struct msghdr *mp; 642 caddr_t namelenp; 643{ 644 struct file *fp; 645 struct uio auio; 646 register struct iovec *iov; 647 register int i; 648 int len, error; 649 struct mbuf *m, *control = 0; 650 caddr_t ctlbuf; 651 struct socket *so; 652 struct sockaddr *fromsa = 0; 653#ifdef KTRACE 654 struct iovec *ktriov = NULL; 655#endif 656 657 error = getsock(p->p_fd, s, &fp); 658 if (error) 659 return (error); 660 auio.uio_iov = mp->msg_iov; 661 auio.uio_iovcnt = mp->msg_iovlen; 662 auio.uio_segflg = UIO_USERSPACE; 663 auio.uio_rw = UIO_READ; 664 auio.uio_procp = p; 665 auio.uio_offset = 0; /* XXX */ 666 auio.uio_resid = 0; 667 iov = mp->msg_iov; 668 for (i = 0; i < mp->msg_iovlen; i++, iov++) { 669 if ((auio.uio_resid += iov->iov_len) < 0) 670 return (EINVAL); 671 } 672#ifdef KTRACE 673 if (KTRPOINT(p, KTR_GENIO)) { 674 int iovlen = auio.uio_iovcnt * sizeof (struct iovec); 675 676 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 677 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 678 } 679#endif 680 len = auio.uio_resid; 681 so = (struct socket *)fp->f_data; 682 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, 683 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, 684 &mp->msg_flags); 685 if (error) { 686 if (auio.uio_resid != len && (error == ERESTART || 687 error == EINTR || error == EWOULDBLOCK)) 688 error = 0; 689 } 690#ifdef KTRACE 691 if (ktriov != NULL) { 692 if (error == 0) 693 ktrgenio(p->p_tracep, s, UIO_READ, 694 ktriov, len - auio.uio_resid, error); 695 FREE(ktriov, M_TEMP); 696 } 697#endif 698 if (error) 699 goto out; 700 p->p_retval[0] = len - auio.uio_resid; 701 if (mp->msg_name) { 702 len = mp->msg_namelen; 703 if (len <= 0 || fromsa == 0) 704 len = 0; 705 else { 706#ifndef MIN 707#define MIN(a,b) ((a)>(b)?(b):(a)) 708#endif 709 /* save sa_len before it is destroyed by MSG_COMPAT */ 710 len = MIN(len, fromsa->sa_len); 711#ifdef COMPAT_OLDSOCK 712 if (mp->msg_flags & MSG_COMPAT) 713 ((struct osockaddr *)fromsa)->sa_family = 714 fromsa->sa_family; 715#endif 716 error = copyout(fromsa, 717 (caddr_t)mp->msg_name, (unsigned)len); 718 if (error) 719 goto out; 720 } 721 mp->msg_namelen = len; 722 if (namelenp && 723 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { 724#ifdef COMPAT_OLDSOCK 725 if (mp->msg_flags & MSG_COMPAT) 726 error = 0; /* old recvfrom didn't check */ 727 else 728#endif 729 goto out; 730 } 731 } 732 if (mp->msg_control) { 733#ifdef COMPAT_OLDSOCK 734 /* 735 * We assume that old recvmsg calls won't receive access 736 * rights and other control info, esp. as control info 737 * is always optional and those options didn't exist in 4.3. 738 * If we receive rights, trim the cmsghdr; anything else 739 * is tossed. 740 */ 741 if (control && mp->msg_flags & MSG_COMPAT) { 742 if (mtod(control, struct cmsghdr *)->cmsg_level != 743 SOL_SOCKET || 744 mtod(control, struct cmsghdr *)->cmsg_type != 745 SCM_RIGHTS) { 746 mp->msg_controllen = 0; 747 goto out; 748 } 749 control->m_len -= sizeof (struct cmsghdr); 750 control->m_data += sizeof (struct cmsghdr); 751 } 752#endif 753 len = mp->msg_controllen; 754 m = control; 755 mp->msg_controllen = 0; 756 ctlbuf = (caddr_t) mp->msg_control; 757 758 while (m && len > 0) { 759 unsigned int tocopy; 760 761 if (len >= m->m_len) 762 tocopy = m->m_len; 763 else { 764 mp->msg_flags |= MSG_CTRUNC; 765 tocopy = len; 766 } 767 768 if (error = copyout((caddr_t)mtod(m, caddr_t), 769 ctlbuf, tocopy)) 770 goto out; 771 772 ctlbuf += tocopy; 773 len -= tocopy; 774 m = m->m_next; 775 } 776 mp->msg_controllen = ctlbuf - mp->msg_control; 777 } 778out: 779 if (fromsa) 780 FREE(fromsa, M_SONAME); 781 if (control) 782 m_freem(control); 783 return (error); 784} 785 786int 787recvfrom(p, uap) 788 struct proc *p; 789 register struct recvfrom_args /* { 790 int s; 791 caddr_t buf; 792 size_t len; 793 int flags; 794 caddr_t from; 795 int *fromlenaddr; 796 } */ *uap; 797{ 798 struct msghdr msg; 799 struct iovec aiov; 800 int error; 801 802 if (uap->fromlenaddr) { 803 error = copyin((caddr_t)uap->fromlenaddr, 804 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)); 805 if (error) 806 return (error); 807 } else 808 msg.msg_namelen = 0; 809 msg.msg_name = uap->from; 810 msg.msg_iov = &aiov; 811 msg.msg_iovlen = 1; 812 aiov.iov_base = uap->buf; 813 aiov.iov_len = uap->len; 814 msg.msg_control = 0; 815 msg.msg_flags = uap->flags; 816 return (recvit(p, uap->s, &msg, (caddr_t)uap->fromlenaddr)); 817} 818 819#ifdef COMPAT_OLDSOCK 820int 821orecvfrom(p, uap) 822 struct proc *p; 823 struct recvfrom_args *uap; 824{ 825 826 uap->flags |= MSG_COMPAT; 827 return (recvfrom(p, uap)); 828} 829#endif 830 831 832#ifdef COMPAT_OLDSOCK 833int 834orecv(p, uap) 835 struct proc *p; 836 register struct orecv_args /* { 837 int s; 838 caddr_t buf; 839 int len; 840 int flags; 841 } */ *uap; 842{ 843 struct msghdr msg; 844 struct iovec aiov; 845 846 msg.msg_name = 0; 847 msg.msg_namelen = 0; 848 msg.msg_iov = &aiov; 849 msg.msg_iovlen = 1; 850 aiov.iov_base = uap->buf; 851 aiov.iov_len = uap->len; 852 msg.msg_control = 0; 853 msg.msg_flags = uap->flags; 854 return (recvit(p, uap->s, &msg, (caddr_t)0)); 855} 856 857/* 858 * Old recvmsg. This code takes advantage of the fact that the old msghdr 859 * overlays the new one, missing only the flags, and with the (old) access 860 * rights where the control fields are now. 861 */ 862int 863orecvmsg(p, uap) 864 struct proc *p; 865 register struct orecvmsg_args /* { 866 int s; 867 struct omsghdr *msg; 868 int flags; 869 } */ *uap; 870{ 871 struct msghdr msg; 872 struct iovec aiov[UIO_SMALLIOV], *iov; 873 int error; 874 875 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, 876 sizeof (struct omsghdr)); 877 if (error) 878 return (error); 879 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 880 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 881 return (EMSGSIZE); 882 MALLOC(iov, struct iovec *, 883 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 884 M_WAITOK); 885 } else 886 iov = aiov; 887 msg.msg_flags = uap->flags | MSG_COMPAT; 888 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov, 889 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 890 if (error) 891 goto done; 892 msg.msg_iov = iov; 893 error = recvit(p, uap->s, &msg, (caddr_t)&uap->msg->msg_namelen); 894 895 if (msg.msg_controllen && error == 0) 896 error = copyout((caddr_t)&msg.msg_controllen, 897 (caddr_t)&uap->msg->msg_accrightslen, sizeof (int)); 898done: 899 if (iov != aiov) 900 FREE(iov, M_IOV); 901 return (error); 902} 903#endif 904 905int 906recvmsg(p, uap) 907 struct proc *p; 908 register struct recvmsg_args /* { 909 int s; 910 struct msghdr *msg; 911 int flags; 912 } */ *uap; 913{ 914 struct msghdr msg; 915 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; 916 register int error; 917 918 error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 919 if (error) 920 return (error); 921 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { 922 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) 923 return (EMSGSIZE); 924 MALLOC(iov, struct iovec *, 925 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, 926 M_WAITOK); 927 } else 928 iov = aiov; 929#ifdef COMPAT_OLDSOCK 930 msg.msg_flags = uap->flags &~ MSG_COMPAT; 931#else 932 msg.msg_flags = uap->flags; 933#endif 934 uiov = msg.msg_iov; 935 msg.msg_iov = iov; 936 error = copyin((caddr_t)uiov, (caddr_t)iov, 937 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); 938 if (error) 939 goto done; 940 error = recvit(p, uap->s, &msg, (caddr_t)0); 941 if (!error) { 942 msg.msg_iov = uiov; 943 error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg)); 944 } 945done: 946 if (iov != aiov) 947 FREE(iov, M_IOV); 948 return (error); 949} 950 951/* ARGSUSED */ 952int 953shutdown(p, uap) 954 struct proc *p; 955 register struct shutdown_args /* { 956 int s; 957 int how; 958 } */ *uap; 959{ 960 struct file *fp; 961 int error; 962 963 error = getsock(p->p_fd, uap->s, &fp); 964 if (error) 965 return (error); 966 return (soshutdown((struct socket *)fp->f_data, uap->how)); 967} 968 969/* ARGSUSED */ 970int 971setsockopt(p, uap) 972 struct proc *p; 973 register struct setsockopt_args /* { 974 int s; 975 int level; 976 int name; 977 caddr_t val; 978 int valsize; 979 } */ *uap; 980{ 981 struct file *fp; 982 struct mbuf *m = NULL; 983 int error; 984 985 error = getsock(p->p_fd, uap->s, &fp); 986 if (error) 987 return (error); 988 if (uap->valsize > MCLBYTES) 989 return (EINVAL); 990 if (uap->val) { 991 m = m_get(M_WAIT, MT_SOOPTS); 992 if (m == NULL) 993 return (ENOBUFS); 994 if (uap->valsize > MLEN) { 995 MCLGET(m, M_WAIT); 996 if(!(m->m_flags & M_EXT)) { 997 m_free(m); 998 return (ENOBUFS); 999 } 1000 } 1001 error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 1002 if (error) { 1003 (void) m_free(m); 1004 return (error); 1005 } 1006 m->m_len = uap->valsize; 1007 } 1008 return (sosetopt((struct socket *)fp->f_data, uap->level, 1009 uap->name, m, p)); 1010} 1011 1012/* ARGSUSED */ 1013int 1014getsockopt(p, uap) 1015 struct proc *p; 1016 register struct getsockopt_args /* { 1017 int s; 1018 int level; 1019 int name; 1020 caddr_t val; 1021 int *avalsize; 1022 } */ *uap; 1023{ 1024 struct file *fp; 1025 struct mbuf *m = NULL, *m0; 1026 int op, i, valsize, error; 1027 1028 error = getsock(p->p_fd, uap->s, &fp); 1029 if (error) 1030 return (error); 1031 if (uap->val) { 1032 error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 1033 sizeof (valsize)); 1034 if (error) 1035 return (error); 1036 } else 1037 valsize = 0; 1038 if ((error = sogetopt((struct socket *)fp->f_data, uap->level, 1039 uap->name, &m, p)) == 0 && uap->val && valsize && m != NULL) { 1040 op = 0; 1041 while (m && !error && op < valsize) { 1042 i = min(m->m_len, (valsize - op)); 1043 error = copyout(mtod(m, caddr_t), uap->val, (u_int)i); 1044 op += i; 1045 uap->val += i; 1046 m0 = m; 1047 MFREE(m0,m); 1048 } 1049 valsize = op; 1050 if (error == 0) 1051 error = copyout((caddr_t)&valsize, 1052 (caddr_t)uap->avalsize, sizeof (valsize)); 1053 } 1054 if (m != NULL) 1055 (void) m_free(m); 1056 return (error); 1057} 1058 1059/* 1060 * Get socket name. 1061 */ 1062/* ARGSUSED */ 1063static int 1064getsockname1(p, uap, compat) 1065 struct proc *p; 1066 register struct getsockname_args /* { 1067 int fdes; 1068 caddr_t asa; 1069 int *alen; 1070 } */ *uap; 1071 int compat; 1072{ 1073 struct file *fp; 1074 register struct socket *so; 1075 struct sockaddr *sa; 1076 int len, error; 1077 1078 error = getsock(p->p_fd, uap->fdes, &fp); 1079 if (error) 1080 return (error); 1081 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1082 if (error) 1083 return (error); 1084 so = (struct socket *)fp->f_data; 1085 sa = 0; 1086 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa); 1087 if (error) 1088 goto bad; 1089 if (sa == 0) { 1090 len = 0; 1091 goto gotnothing; 1092 } 1093 1094 len = MIN(len, sa->sa_len); 1095#ifdef COMPAT_OLDSOCK 1096 if (compat) 1097 ((struct osockaddr *)sa)->sa_family = sa->sa_family; 1098#endif 1099 error = copyout(sa, (caddr_t)uap->asa, (u_int)len); 1100 if (error == 0) 1101gotnothing: 1102 error = copyout((caddr_t)&len, (caddr_t)uap->alen, 1103 sizeof (len)); 1104bad: 1105 if (sa) 1106 FREE(sa, M_SONAME); 1107 return (error); 1108} 1109 1110int 1111getsockname(p, uap) 1112 struct proc *p; 1113 struct getsockname_args *uap; 1114{ 1115 1116 return (getsockname1(p, uap, 0)); 1117} 1118 1119#ifdef COMPAT_OLDSOCK 1120int 1121ogetsockname(p, uap) 1122 struct proc *p; 1123 struct getsockname_args *uap; 1124{ 1125 1126 return (getsockname1(p, uap, 1)); 1127} 1128#endif /* COMPAT_OLDSOCK */ 1129 1130/* 1131 * Get name of peer for connected socket. 1132 */ 1133/* ARGSUSED */ 1134static int 1135getpeername1(p, uap, compat) 1136 struct proc *p; 1137 register struct getpeername_args /* { 1138 int fdes; 1139 caddr_t asa; 1140 int *alen; 1141 } */ *uap; 1142 int compat; 1143{ 1144 struct file *fp; 1145 register struct socket *so; 1146 struct sockaddr *sa; 1147 int len, error; 1148 1149 error = getsock(p->p_fd, uap->fdes, &fp); 1150 if (error) 1151 return (error); 1152 so = (struct socket *)fp->f_data; 1153 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) 1154 return (ENOTCONN); 1155 error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 1156 if (error) 1157 return (error); 1158 sa = 0; 1159 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa); 1160 if (error) 1161 goto bad; 1162 if (sa == 0) { 1163 len = 0; 1164 goto gotnothing; 1165 } 1166 len = MIN(len, sa->sa_len); 1167#ifdef COMPAT_OLDSOCK 1168 if (compat) 1169 ((struct osockaddr *)sa)->sa_family = 1170 sa->sa_family; 1171#endif 1172 error = copyout(sa, (caddr_t)uap->asa, (u_int)len); 1173 if (error) 1174 goto bad; 1175gotnothing: 1176 error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 1177bad: 1178 if (sa) FREE(sa, M_SONAME); 1179 return (error); 1180} 1181 1182int 1183getpeername(p, uap) 1184 struct proc *p; 1185 struct getpeername_args *uap; 1186{ 1187 1188 return (getpeername1(p, uap, 0)); 1189} 1190 1191#ifdef COMPAT_OLDSOCK 1192int 1193ogetpeername(p, uap) 1194 struct proc *p; 1195 struct ogetpeername_args *uap; 1196{ 1197 1198 /* XXX uap should have type `getpeername_args *' to begin with. */ 1199 return (getpeername1(p, (struct getpeername_args *)uap, 1)); 1200} 1201#endif /* COMPAT_OLDSOCK */ 1202 1203int 1204sockargs(mp, buf, buflen, type) 1205 struct mbuf **mp; 1206 caddr_t buf; 1207 int buflen, type; 1208{ 1209 register struct sockaddr *sa; 1210 register struct mbuf *m; 1211 int error; 1212 1213 if ((u_int)buflen > MLEN) { 1214#ifdef COMPAT_OLDSOCK 1215 if (type == MT_SONAME && (u_int)buflen <= 112) 1216 buflen = MLEN; /* unix domain compat. hack */ 1217 else 1218#endif 1219 return (EINVAL); 1220 } 1221 m = m_get(M_WAIT, type); 1222 if (m == NULL) 1223 return (ENOBUFS); 1224 m->m_len = buflen; 1225 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen); 1226 if (error) 1227 (void) m_free(m); 1228 else { 1229 *mp = m; 1230 if (type == MT_SONAME) { 1231 sa = mtod(m, struct sockaddr *); 1232 1233#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1234 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1235 sa->sa_family = sa->sa_len; 1236#endif 1237 sa->sa_len = buflen; 1238 } 1239 } 1240 return (error); 1241} 1242 1243int 1244getsockaddr(namp, uaddr, len) 1245 struct sockaddr **namp; 1246 caddr_t uaddr; 1247 size_t len; 1248{ 1249 struct sockaddr *sa; 1250 int error; 1251 1252 if (len > SOCK_MAXADDRLEN) 1253 return ENAMETOOLONG; 1254 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK); 1255 error = copyin(uaddr, sa, len); 1256 if (error) { 1257 FREE(sa, M_SONAME); 1258 } else { 1259#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN 1260 if (sa->sa_family == 0 && sa->sa_len < AF_MAX) 1261 sa->sa_family = sa->sa_len; 1262#endif 1263 sa->sa_len = len; 1264 *namp = sa; 1265 } 1266 return error; 1267} 1268 1269int 1270getsock(fdp, fdes, fpp) 1271 struct filedesc *fdp; 1272 int fdes; 1273 struct file **fpp; 1274{ 1275 register struct file *fp; 1276 1277 if ((unsigned)fdes >= fdp->fd_nfiles || 1278 (fp = fdp->fd_ofiles[fdes]) == NULL) 1279 return (EBADF); 1280 if (fp->f_type != DTYPE_SOCKET) 1281 return (ENOTSOCK); 1282 *fpp = fp; 1283 return (0); 1284} 1285