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