1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)uipc_syscalls.c 7.1.3 (2.11BSD) 1999/9/13 7: */ 8: 9: #include "param.h" 10: 11: #include "../machine/seg.h" 12: #include "../machine/psl.h" 13: 14: #include "systm.h" 15: #include "user.h" 16: #include "proc.h" 17: #include "file.h" 18: #include "inode.h" 19: #include "buf.h" 20: #include "mbuf.h" 21: #include "protosw.h" 22: #include "socket.h" 23: #include "socketvar.h" 24: #include "uio.h" 25: #include "domain.h" 26: #include "pdpif/if_uba.h" 27: #include "netinet/in.h" 28: #include "netinet/in_systm.h" 29: 30: static void 31: MBZAP(m, len, type) 32: register struct mbuf *m; 33: int len, type; 34: { 35: m->m_next = 0; 36: m->m_off = MMINOFF; 37: m->m_len = len; 38: m->m_type = type; 39: m->m_act = 0; 40: } 41: 42: /* 43: * System call interface to the socket abstraction. 44: */ 45: 46: extern int netoff; 47: struct file *gtsockf(); 48: 49: socket() 50: { 51: register struct a { 52: int domain; 53: int type; 54: int protocol; 55: } *uap = (struct a *)u.u_ap; 56: struct socket *so; 57: register struct file *fp; 58: 59: if (netoff) 60: return(u.u_error = ENETDOWN); 61: if ((fp = falloc()) == NULL) 62: return; 63: fp->f_flag = FREAD|FWRITE; 64: fp->f_type = DTYPE_SOCKET; 65: u.u_error = SOCREATE(uap->domain, &so, uap->type, uap->protocol); 66: if (u.u_error) 67: goto bad; 68: fp->f_socket = so; 69: return; 70: bad: 71: u.u_ofile[u.u_r.r_val1] = 0; 72: fp->f_count = 0; 73: } 74: 75: bind() 76: { 77: register struct a { 78: int s; 79: caddr_t name; 80: u_int namelen; 81: } *uap = (struct a *)u.u_ap; 82: register struct file *fp; 83: register struct mbuf *nam; 84: char sabuf[MSIZE]; 85: 86: if (netoff) 87: return(u.u_error = ENETDOWN); 88: fp = gtsockf(uap->s); 89: if (fp == 0) 90: return; 91: nam = (struct mbuf *)sabuf; 92: MBZAP(nam, uap->namelen, MT_SONAME); 93: if (uap->namelen > MLEN) 94: return (u.u_error = EINVAL); 95: u.u_error = copyin(uap->name, mtod(nam, caddr_t), uap->namelen); 96: if (u.u_error) 97: return; 98: u.u_error = SOBIND(fp->f_socket, nam); 99: } 100: 101: listen() 102: { 103: register struct a { 104: int s; 105: int backlog; 106: } *uap = (struct a *)u.u_ap; 107: register struct file *fp; 108: 109: if (netoff) 110: return(u.u_error = ENETDOWN); 111: fp = gtsockf(uap->s); 112: if (fp == 0) 113: return; 114: u.u_error = SOLISTEN(fp->f_socket, uap->backlog); 115: } 116: 117: accept() 118: { 119: register struct a { 120: int s; 121: caddr_t name; 122: int *anamelen; 123: } *uap = (struct a *)u.u_ap; 124: register struct file *fp; 125: struct mbuf *nam; 126: int namelen; 127: int s; 128: register struct socket *so; 129: char sabuf[MSIZE]; 130: 131: if (netoff) 132: return(u.u_error = ENETDOWN); 133: if (uap->name == 0) 134: goto noname; 135: u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, 136: sizeof (namelen)); 137: if (u.u_error) 138: return; 139: #ifndef pdp11 140: if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { 141: u.u_error = EFAULT; 142: return; 143: } 144: #endif 145: noname: 146: fp = gtsockf(uap->s); 147: if (fp == 0) 148: return; 149: s = splnet(); 150: so = fp->f_socket; 151: if (SOACC1(so)) { 152: splx(s); 153: return; 154: } 155: if (ufalloc(0) < 0) { 156: splx(s); 157: return; 158: } 159: fp = falloc(); 160: if (fp == 0) { 161: u.u_ofile[u.u_r.r_val1] = 0; 162: splx(s); 163: return; 164: } 165: if (!(so = (struct socket *)ASOQREMQUE(so, 1))) /* deQ in super */ 166: panic("accept"); 167: fp->f_type = DTYPE_SOCKET; 168: fp->f_flag = FREAD|FWRITE; 169: fp->f_socket = so; 170: nam = (struct mbuf *)sabuf; 171: MBZAP(nam, 0, MT_SONAME); 172: u.u_error = SOACCEPT(so, nam); 173: if (uap->name) { 174: if (namelen > nam->m_len) 175: namelen = nam->m_len; 176: /* SHOULD COPY OUT A CHAIN HERE */ 177: (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, 178: (u_int)namelen); 179: (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, 180: sizeof (*uap->anamelen)); 181: } 182: splx(s); 183: } 184: 185: connect() 186: { 187: register struct a { 188: int s; 189: caddr_t name; 190: u_int namelen; 191: } *uap = (struct a *)u.u_ap; 192: register struct file *fp; 193: register struct socket *so; 194: struct mbuf *nam; 195: int s; 196: char sabuf[MSIZE]; 197: struct socket kcopy; 198: 199: if (netoff) 200: return(u.u_error = ENETDOWN); 201: fp = gtsockf(uap->s); 202: if (fp == 0) 203: return; 204: if (uap->namelen > MLEN) 205: return (u.u_error = EINVAL); 206: nam = (struct mbuf *)sabuf; 207: MBZAP(nam, uap->namelen, MT_SONAME); 208: u.u_error = copyin(uap->name, mtod(nam, caddr_t), uap->namelen); 209: if (u.u_error) 210: return; 211: so = fp->f_socket; 212: /* 213: * soconnect was modified to clear the isconnecting bit on errors. 214: * also, it was changed to return the EINPROGRESS error if 215: * nonblocking, etc. 216: */ 217: u.u_error = SOCON1(so, nam); 218: if (u.u_error) 219: return; 220: /* 221: * i don't think the setjmp stuff works too hot in supervisor mode, 222: * so what is done instead is do the setjmp here and then go back 223: * to supervisor mode to do the "while (isconnecting && !error) 224: * sleep()" loop. 225: */ 226: s = splnet(); 227: if (setjmp(&u.u_qsave)) 228: { 229: u.u_error = EINTR; 230: goto bad2; 231: } 232: u.u_error = CONNWHILE(so); 233: bad2: 234: splx(s); 235: } 236: 237: socketpair() 238: { 239: register struct a { 240: int domain; 241: int type; 242: int protocol; 243: int *rsv; 244: } *uap = (struct a *)u.u_ap; 245: register struct file *fp1, *fp2; 246: struct socket *so1, *so2; 247: int sv[2]; 248: 249: if (netoff) 250: return(u.u_error = ENETDOWN); 251: u.u_error = SOCREATE(uap->domain, &so1, uap->type, uap->protocol); 252: if (u.u_error) 253: return; 254: u.u_error = SOCREATE(uap->domain, &so2, uap->type, uap->protocol); 255: if (u.u_error) 256: goto free; 257: fp1 = falloc(); 258: if (fp1 == NULL) 259: goto free2; 260: sv[0] = u.u_r.r_val1; 261: fp1->f_flag = FREAD|FWRITE; 262: fp1->f_type = DTYPE_SOCKET; 263: fp1->f_socket = so1; 264: fp2 = falloc(); 265: if (fp2 == NULL) 266: goto free3; 267: fp2->f_flag = FREAD|FWRITE; 268: fp2->f_type = DTYPE_SOCKET; 269: fp2->f_socket = so2; 270: sv[1] = u.u_r.r_val1; 271: u.u_error = SOCON2(so1, so2); 272: if (u.u_error) 273: goto free4; 274: if (uap->type == SOCK_DGRAM) { 275: /* 276: * Datagram socket connection is asymmetric. 277: */ 278: u.u_error = SOCON2(so2, so1); 279: if (u.u_error) 280: goto free4; 281: } 282: u.u_r.r_val1 = 0; 283: (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int)); 284: return; 285: free4: 286: fp2->f_count = 0; 287: u.u_ofile[sv[1]] = 0; 288: free3: 289: fp1->f_count = 0; 290: u.u_ofile[sv[0]] = 0; 291: free2: 292: (void)SOCLOSE(so2); 293: free: 294: (void)SOCLOSE(so1); 295: } 296: 297: sendto() 298: { 299: register struct a { 300: int s; 301: caddr_t buf; 302: int len; 303: int flags; 304: caddr_t to; 305: int tolen; 306: } *uap = (struct a *)u.u_ap; 307: struct msghdr msg; 308: struct iovec aiov; 309: 310: msg.msg_name = uap->to; 311: msg.msg_namelen = uap->tolen; 312: msg.msg_iov = &aiov; 313: msg.msg_iovlen = 1; 314: aiov.iov_base = uap->buf; 315: aiov.iov_len = uap->len; 316: msg.msg_accrights = 0; 317: msg.msg_accrightslen = 0; 318: sendit(uap->s, &msg, uap->flags); 319: } 320: 321: send() 322: { 323: register struct a { 324: int s; 325: caddr_t buf; 326: int len; 327: int flags; 328: } *uap = (struct a *)u.u_ap; 329: struct msghdr msg; 330: struct iovec aiov; 331: 332: msg.msg_name = 0; 333: msg.msg_namelen = 0; 334: msg.msg_iov = &aiov; 335: msg.msg_iovlen = 1; 336: aiov.iov_base = uap->buf; 337: aiov.iov_len = uap->len; 338: msg.msg_accrights = 0; 339: msg.msg_accrightslen = 0; 340: sendit(uap->s, &msg, uap->flags); 341: } 342: 343: sendmsg() 344: { 345: register struct a { 346: int s; 347: caddr_t msg; 348: int flags; 349: } *uap = (struct a *)u.u_ap; 350: struct msghdr msg; 351: struct iovec aiov[MSG_MAXIOVLEN]; 352: 353: u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); 354: if (u.u_error) 355: return; 356: if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 357: u.u_error = EMSGSIZE; 358: return; 359: } 360: u.u_error = 361: copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 362: (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); 363: if (u.u_error) 364: return; 365: msg.msg_iov = aiov; 366: sendit(uap->s, &msg, uap->flags); 367: } 368: 369: sendit(s, mp, flags) 370: int s; 371: register struct msghdr *mp; 372: int flags; 373: { 374: register struct file *fp; 375: struct uio auio; 376: register struct iovec *iov; 377: register int i; 378: struct mbuf *to, *rights; 379: int len; 380: char sabuf[MSIZE], ribuf[MSIZE]; 381: 382: if (netoff) 383: return(u.u_error = ENETDOWN); 384: fp = gtsockf(s); 385: if (fp == 0) 386: return; 387: auio.uio_iov = mp->msg_iov; 388: auio.uio_iovcnt = mp->msg_iovlen; 389: auio.uio_segflg = UIO_USERSPACE; 390: auio.uio_offset = 0; /* XXX */ 391: auio.uio_resid = 0; 392: auio.uio_rw = UIO_WRITE; 393: iov = mp->msg_iov; 394: for (i = 0; i < mp->msg_iovlen; i++, iov++) 395: { 396: if (iov->iov_len == 0) 397: continue; 398: auio.uio_resid += iov->iov_len; 399: } 400: if (mp->msg_name) { 401: to = (struct mbuf *)sabuf; 402: MBZAP(to, mp->msg_namelen, MT_SONAME); 403: u.u_error = 404: copyin(mp->msg_name, mtod(to, caddr_t), mp->msg_namelen); 405: if (u.u_error) 406: return; 407: } else 408: to = 0; 409: if (mp->msg_accrights) { 410: rights = (struct mbuf *)ribuf; 411: MBZAP(rights, mp->msg_accrightslen, MT_RIGHTS); 412: if (mp->msg_accrightslen > MLEN) 413: return(u.u_error = EINVAL); 414: u.u_error = copyin(mp->msg_accrights, mtod(rights, caddr_t), 415: mp->msg_accrightslen); 416: if (u.u_error) 417: return; 418: } else 419: rights = 0; 420: len = auio.uio_resid; 421: if (setjmp(&u.u_qsave)) 422: { 423: if (auio.uio_resid == len) 424: return; 425: else 426: u.u_error = 0; 427: } 428: else 429: u.u_error = SOSEND(fp->f_socket, to, &auio, flags, rights); 430: u.u_r.r_val1 = len - auio.uio_resid; 431: } 432: 433: recvfrom() 434: { 435: register struct a { 436: int s; 437: caddr_t buf; 438: int len; 439: int flags; 440: caddr_t from; 441: int *fromlenaddr; 442: } *uap = (struct a *)u.u_ap; 443: struct msghdr msg; 444: struct iovec aiov; 445: int len; 446: 447: u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, 448: sizeof (len)); 449: if (u.u_error) 450: return; 451: msg.msg_name = uap->from; 452: msg.msg_namelen = len; 453: msg.msg_iov = &aiov; 454: msg.msg_iovlen = 1; 455: aiov.iov_base = uap->buf; 456: aiov.iov_len = uap->len; 457: msg.msg_accrights = 0; 458: msg.msg_accrightslen = 0; 459: recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0); 460: } 461: 462: recv() 463: { 464: register struct a { 465: int s; 466: caddr_t buf; 467: int len; 468: int flags; 469: } *uap = (struct a *)u.u_ap; 470: struct msghdr msg; 471: struct iovec aiov; 472: 473: msg.msg_name = 0; 474: msg.msg_namelen = 0; 475: msg.msg_iov = &aiov; 476: msg.msg_iovlen = 1; 477: aiov.iov_base = uap->buf; 478: aiov.iov_len = uap->len; 479: msg.msg_accrights = 0; 480: msg.msg_accrightslen = 0; 481: recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0); 482: } 483: 484: recvmsg() 485: { 486: register struct a { 487: int s; 488: struct msghdr *msg; 489: int flags; 490: } *uap = (struct a *)u.u_ap; 491: struct msghdr msg; 492: struct iovec aiov[MSG_MAXIOVLEN]; 493: 494: u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); 495: if (u.u_error) 496: return; 497: if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { 498: u.u_error = EMSGSIZE; 499: return; 500: } 501: u.u_error = 502: copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, 503: (unsigned)(msg.msg_iovlen * sizeof(aiov[0]))); 504: if (u.u_error) 505: return; 506: recvit(uap->s, &msg, uap->flags, 507: (caddr_t)&uap->msg->msg_namelen, 508: (caddr_t)&uap->msg->msg_accrightslen); 509: } 510: 511: recvit(s, mp, flags, namelenp, rightslenp) 512: int s; 513: register struct msghdr *mp; 514: int flags; 515: caddr_t namelenp, rightslenp; 516: { 517: register struct file *fp; 518: struct uio auio; 519: register struct iovec *iov; 520: register int i; 521: struct mbuf *from, *rights; 522: int len, m_freem(); 523: 524: if (netoff) 525: return(u.u_error = ENETDOWN); 526: fp = gtsockf(s); 527: if (fp == 0) 528: return; 529: auio.uio_iov = mp->msg_iov; 530: auio.uio_iovcnt = mp->msg_iovlen; 531: auio.uio_segflg = UIO_USERSPACE; 532: auio.uio_offset = 0; /* XXX */ 533: auio.uio_resid = 0; 534: auio.uio_rw = UIO_READ; 535: iov = mp->msg_iov; 536: for (i = 0; i < mp->msg_iovlen; i++, iov++) 537: { 538: if (iov->iov_len == 0) 539: continue; 540: auio.uio_resid += iov->iov_len; 541: } 542: len = auio.uio_resid; 543: if (setjmp(&u.u_qsave)) 544: { 545: if (auio.uio_resid == len) 546: return; 547: else 548: u.u_error = 0; 549: } 550: else 551: u.u_error = SORECEIVE((struct socket *)fp->f_data, 552: &from, &auio,flags, &rights); 553: if (u.u_error) 554: return; 555: u.u_r.r_val1 = len - auio.uio_resid; 556: if (mp->msg_name) { 557: len = mp->msg_namelen; 558: if (len <= 0 || from == 0) 559: len = 0; 560: else 561: (void) NETCOPYOUT(from, mp->msg_name, &len); 562: (void) copyout((caddr_t)&len, namelenp, sizeof(int)); 563: } 564: if (mp->msg_accrights) { 565: len = mp->msg_accrightslen; 566: if (len <= 0 || rights == 0) 567: len = 0; 568: else 569: (void) NETCOPYOUT(rights, mp->msg_accrights, &len); 570: (void) copyout((caddr_t)&len, rightslenp, sizeof(int)); 571: } 572: if (rights) 573: M_FREEM(rights); 574: if (from) 575: M_FREEM(from); 576: } 577: 578: shutdown() 579: { 580: register struct a { 581: int s; 582: int how; 583: } *uap = (struct a *)u.u_ap; 584: register struct file *fp; 585: 586: if (netoff) 587: return(u.u_error = ENETDOWN); 588: fp = gtsockf(uap->s); 589: if (fp == 0) 590: return; 591: u.u_error = SOSHUTDOWN(fp->f_socket, uap->how); 592: } 593: 594: setsockopt() 595: { 596: register struct a { 597: int s; 598: int level; 599: int name; 600: caddr_t val; 601: u_int valsize; 602: } *uap = (struct a *)u.u_ap; 603: register struct file *fp; 604: register struct mbuf *m = NULL; 605: char optbuf[MSIZE]; 606: 607: if (netoff) 608: return(u.u_error = ENETDOWN); 609: fp = gtsockf(uap->s); 610: if (fp == 0) 611: return; 612: if (uap->valsize > MLEN) { 613: u.u_error = EINVAL; 614: return; 615: } 616: if (uap->val) { 617: m = (struct mbuf *)optbuf; 618: MBZAP(m, uap->valsize, MT_SOOPTS); 619: u.u_error = 620: copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 621: if (u.u_error) 622: return; 623: } 624: u.u_error = SOSETOPT(fp->f_socket, uap->level, uap->name, m); 625: } 626: 627: getsockopt() 628: { 629: register struct a { 630: int s; 631: int level; 632: int name; 633: caddr_t val; 634: int *avalsize; 635: } *uap = (struct a *)u.u_ap; 636: register struct file *fp; 637: struct mbuf *m = NULL, *m_free(); 638: int valsize; 639: 640: if (netoff) 641: return(u.u_error = ENETDOWN); 642: fp = gtsockf(uap->s); 643: if (fp == 0) 644: return; 645: if (uap->val) { 646: u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 647: sizeof (valsize)); 648: if (u.u_error) 649: return; 650: } else 651: valsize = 0; 652: u.u_error = 653: SOGETOPT(fp->f_socket, uap->level, uap->name, &m); 654: if (u.u_error) 655: goto bad; 656: if (uap->val && valsize && m != NULL) { 657: u.u_error = NETCOPYOUT(m, uap->val, &valsize); 658: if (u.u_error) 659: goto bad; 660: u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, 661: sizeof (valsize)); 662: } 663: bad: 664: if (m != NULL) 665: M_FREE(m); 666: } 667: 668: /* 669: * Get socket name. 670: */ 671: getsockname() 672: { 673: register struct a { 674: int fdes; 675: caddr_t asa; 676: int *alen; 677: } *uap = (struct a *)u.u_ap; 678: register struct file *fp; 679: struct mbuf *m; 680: int len; 681: char sabuf[MSIZE]; 682: 683: if (netoff) 684: return(u.u_error = ENETDOWN); 685: fp = gtsockf(uap->fdes); 686: if (fp == 0) 687: return; 688: u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 689: if (u.u_error) 690: return; 691: m = (struct mbuf *)sabuf; 692: MBZAP(m, 0, MT_SONAME); 693: u.u_error = SOGETNAM(fp->f_socket, m); 694: if (u.u_error) 695: return; 696: if (len > m->m_len) 697: len = m->m_len; 698: u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 699: if (u.u_error) 700: return; 701: u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 702: } 703: 704: /* 705: * Get name of peer for connected socket. 706: */ 707: getpeername() 708: { 709: register struct a { 710: int fdes; 711: caddr_t asa; 712: int *alen; 713: } *uap = (struct a *)u.u_ap; 714: register struct file *fp; 715: struct mbuf *m; 716: u_int len; 717: char sabuf[MSIZE]; 718: 719: if (netoff) 720: return(u.u_error = ENETDOWN); 721: fp = gtsockf(uap->fdes); 722: if (fp == 0) 723: return; 724: m = (struct mbuf *)sabuf; 725: MBZAP(m, 0, MT_SONAME); 726: u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); 727: if (u.u_error) 728: return; 729: u.u_error = SOGETPEER(fp->f_socket, m); 730: if (u.u_error) 731: return; 732: if (len > m->m_len) 733: len = m->m_len; 734: u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len); 735: if (u.u_error) 736: return; 737: u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len)); 738: } 739: 740: #ifndef pdp11 741: sockargs(aname, name, namelen, type) 742: struct mbuf **aname; 743: caddr_t name; 744: int namelen, type; 745: { 746: register struct mbuf *m; 747: int error; 748: struct mbuf *m_free(); 749: 750: if (namelen > MLEN) 751: return (EINVAL); 752: m = m_get(M_WAIT, type); 753: if (m == NULL) 754: return (ENOBUFS); 755: m->m_len = namelen; 756: error = copyin(name, mtod(m, caddr_t), (u_int)namelen); 757: if (error) 758: (void) m_free(m); 759: else 760: *aname = m; 761: return (error); 762: } 763: #endif 764: 765: struct file * 766: gtsockf(fdes) 767: int fdes; 768: { 769: register struct file *fp; 770: 771: fp = getf(fdes); 772: if (fp == NULL) 773: return (0); 774: if (fp->f_type != DTYPE_SOCKET) { 775: u.u_error = ENOTSOCK; 776: return (0); 777: } 778: return (fp); 779: }