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