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_usrreq.c 7.1.2 (2.11BSD GTE) 1997/1/18 7: */ 8: 9: #include "param.h" 10: #include "user.h" 11: #include "mbuf.h" 12: #include "domain.h" 13: #include "protosw.h" 14: #include "socket.h" 15: #include "socketvar.h" 16: #include "unpcb.h" 17: #include "un.h" 18: #include "inode.h" 19: #include "file.h" 20: #include "stat.h" 21: 22: /* 23: * Unix communications domain. 24: * 25: * TODO: 26: * SEQPACKET, RDM 27: * rethink name space problems 28: * need a proper out-of-band 29: */ 30: struct sockaddr sun_noname = { AF_UNIX }; 31: ino_t unp_ino; /* prototype for fake inode numbers */ 32: 33: extern void unpdisc(), unpgc1(); 34: extern int fadjust(); 35: 36: /*ARGSUSED*/ 37: uipc_usrreq(so, req, m, nam, rights) 38: struct socket *so; 39: int req; 40: struct mbuf *m, *nam, *rights; 41: { 42: struct unpcb *unp = sotounpcb(so); 43: register struct socket *so2; 44: int error = 0; 45: 46: if (req == PRU_CONTROL) 47: return (EOPNOTSUPP); 48: if (req != PRU_SEND && rights && rights->m_len) { 49: error = EOPNOTSUPP; 50: goto release; 51: } 52: if (unp == 0 && req != PRU_ATTACH) { 53: error = EINVAL; 54: goto release; 55: } 56: switch (req) { 57: 58: case PRU_ATTACH: 59: if (unp) { 60: error = EISCONN; 61: break; 62: } 63: error = unp_attach(so); 64: break; 65: 66: case PRU_DETACH: 67: unp_detach(unp); 68: break; 69: 70: case PRU_BIND: 71: error = unp_bind(unp, nam); 72: break; 73: 74: case PRU_LISTEN: 75: if (unp->unp_inode == 0) 76: error = EINVAL; 77: break; 78: 79: case PRU_CONNECT: 80: error = unp_connect(so, nam); 81: break; 82: 83: case PRU_CONNECT2: 84: error = unp_connect2(so, (struct socket *)nam); 85: break; 86: 87: case PRU_DISCONNECT: 88: unp_disconnect(unp); 89: break; 90: 91: case PRU_ACCEPT: 92: /* 93: * Pass back name of connected socket, 94: * if it was bound and we are still connected 95: * (our peer may have closed already!). 96: */ 97: if (unp->unp_conn && unp->unp_conn->unp_addr) { 98: nam->m_len = unp->unp_conn->unp_addr->m_len; 99: bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), 100: mtod(nam, caddr_t), (unsigned)nam->m_len); 101: } else { 102: nam->m_len = sizeof(sun_noname); 103: *(mtod(nam, struct sockaddr *)) = sun_noname; 104: } 105: break; 106: 107: case PRU_SHUTDOWN: 108: socantsendmore(so); 109: unp_usrclosed(unp); 110: break; 111: 112: case PRU_RCVD: 113: switch (so->so_type) { 114: 115: case SOCK_DGRAM: 116: panic("uipc 1"); 117: /*NOTREACHED*/ 118: 119: case SOCK_STREAM: 120: #define rcv (&so->so_rcv) 121: #define snd (&so2->so_snd) 122: if (unp->unp_conn == 0) 123: break; 124: so2 = unp->unp_conn->unp_socket; 125: /* 126: * Adjust backpressure on sender 127: * and wakeup any waiting to write. 128: */ 129: snd->sb_mbmax += unp->unp_mbcnt - rcv->sb_mbcnt; 130: unp->unp_mbcnt = rcv->sb_mbcnt; 131: snd->sb_hiwat += unp->unp_cc - rcv->sb_cc; 132: unp->unp_cc = rcv->sb_cc; 133: sowwakeup(so2); 134: #undef snd 135: #undef rcv 136: break; 137: 138: default: 139: panic("uipc 2"); 140: } 141: break; 142: 143: case PRU_SEND: 144: if (rights) { 145: error = unp_internalize(rights); 146: if (error) 147: break; 148: } 149: switch (so->so_type) { 150: 151: case SOCK_DGRAM: { 152: struct sockaddr *from; 153: 154: if (nam) { 155: if (unp->unp_conn) { 156: error = EISCONN; 157: break; 158: } 159: error = unp_connect(so, nam); 160: if (error) 161: break; 162: } else { 163: if (unp->unp_conn == 0) { 164: error = ENOTCONN; 165: break; 166: } 167: } 168: so2 = unp->unp_conn->unp_socket; 169: if (unp->unp_addr) 170: from = mtod(unp->unp_addr, struct sockaddr *); 171: else 172: from = &sun_noname; 173: if (sbspace(&so2->so_rcv) > 0 && 174: sbappendaddr(&so2->so_rcv, from, m, rights)) { 175: sorwakeup(so2); 176: m = 0; 177: } else 178: error = ENOBUFS; 179: if (nam) 180: unp_disconnect(unp); 181: break; 182: } 183: 184: case SOCK_STREAM: 185: #define rcv (&so2->so_rcv) 186: #define snd (&so->so_snd) 187: if (so->so_state & SS_CANTSENDMORE) { 188: error = EPIPE; 189: break; 190: } 191: if (unp->unp_conn == 0) 192: panic("uipc 3"); 193: so2 = unp->unp_conn->unp_socket; 194: /* 195: * Send to paired receive port, and then reduce 196: * send buffer hiwater marks to maintain backpressure. 197: * Wake up readers. 198: */ 199: if (rights) 200: (void)sbappendrights(rcv, m, rights); 201: else 202: sbappend(rcv, m); 203: snd->sb_mbmax -= 204: rcv->sb_mbcnt - unp->unp_conn->unp_mbcnt; 205: unp->unp_conn->unp_mbcnt = rcv->sb_mbcnt; 206: snd->sb_hiwat -= rcv->sb_cc - unp->unp_conn->unp_cc; 207: unp->unp_conn->unp_cc = rcv->sb_cc; 208: sorwakeup(so2); 209: m = 0; 210: #undef snd 211: #undef rcv 212: break; 213: 214: default: 215: panic("uipc 4"); 216: } 217: break; 218: 219: case PRU_ABORT: 220: unp_drop(unp, ECONNABORTED); 221: break; 222: 223: case PRU_SENSE: 224: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat; 225: if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { 226: so2 = unp->unp_conn->unp_socket; 227: ((struct stat *) m)->st_blksize += so2->so_rcv.sb_cc; 228: } 229: ((struct stat *) m)->st_dev = NODEV; 230: if (unp->unp_ino == 0) 231: unp->unp_ino = unp_ino++; 232: ((struct stat *) m)->st_ino = unp->unp_ino; 233: return (0); 234: 235: case PRU_RCVOOB: 236: return (EOPNOTSUPP); 237: 238: case PRU_SENDOOB: 239: error = EOPNOTSUPP; 240: break; 241: 242: case PRU_SOCKADDR: 243: break; 244: 245: case PRU_PEERADDR: 246: if (unp->unp_conn && unp->unp_conn->unp_addr) { 247: nam->m_len = unp->unp_conn->unp_addr->m_len; 248: bcopy(mtod(unp->unp_conn->unp_addr, caddr_t), 249: mtod(nam, caddr_t), (unsigned)nam->m_len); 250: } 251: break; 252: 253: case PRU_SLOWTIMO: 254: break; 255: 256: default: 257: panic("piusrreq"); 258: } 259: release: 260: if (m) 261: m_freem(m); 262: return (error); 263: } 264: 265: /* 266: * Both send and receive buffers are allocated PIPSIZ bytes of buffering 267: * for stream sockets, although the total for sender and receiver is 268: * actually only PIPSIZ. 269: * Datagram sockets really use the sendspace as the maximum datagram size, 270: * and don't really want to reserve the sendspace. Their recvspace should 271: * be large enough for at least one max-size datagram plus address. 272: */ 273: #define PIPSIZ 4096 274: int unpst_sendspace = PIPSIZ; 275: int unpst_recvspace = PIPSIZ; 276: int unpdg_sendspace = 2*1024; /* really max datagram size */ 277: int unpdg_recvspace = 4*1024; 278: 279: int unp_rights; /* file descriptors in flight */ 280: 281: unp_attach(so) 282: struct socket *so; 283: { 284: register struct mbuf *m; 285: register struct unpcb *unp; 286: int error; 287: 288: switch (so->so_type) { 289: 290: case SOCK_STREAM: 291: error = soreserve(so, unpst_sendspace, unpst_recvspace); 292: break; 293: 294: case SOCK_DGRAM: 295: error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 296: break; 297: } 298: if (error) 299: return (error); 300: m = m_getclr(M_DONTWAIT, MT_PCB); 301: if (m == NULL) 302: return (ENOBUFS); 303: unp = mtod(m, struct unpcb *); 304: so->so_pcb = (caddr_t)unp; 305: unp->unp_socket = so; 306: return (0); 307: } 308: 309: unp_detach(unp) 310: register struct unpcb *unp; 311: { 312: 313: if (unp->unp_inode) { 314: UNPDET(unp->unp_inode); 315: unp->unp_inode = 0; 316: } 317: if (unp->unp_conn) 318: unp_disconnect(unp); 319: while (unp->unp_refs) 320: unp_drop(unp->unp_refs, ECONNRESET); 321: soisdisconnected(unp->unp_socket); 322: unp->unp_socket->so_pcb = 0; 323: m_freem(unp->unp_addr); 324: (void) m_free(dtom(unp)); 325: if (unp_rights) 326: unp_gc(); 327: } 328: 329: unp_bind(unp, nam) 330: struct unpcb *unp; 331: struct mbuf *nam; 332: { 333: struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 334: struct inode *ip; 335: int error; 336: 337: if (unp->unp_inode != NULL || nam->m_len >= MLEN) 338: return (EINVAL); 339: *(mtod(nam, caddr_t) + nam->m_len) = 0; 340: error = UNPBIND(soun->sun_path, nam->m_len, &ip, unp->unp_socket); 341: if (error) 342: return(error); 343: if (!ip) 344: panic("unp_bind"); 345: unp->unp_inode = ip; 346: unp->unp_addr = m_copy(nam, 0, M_COPYALL); 347: return (0); 348: } 349: 350: unp_connect(so, nam) 351: struct socket *so; 352: struct mbuf *nam; 353: { 354: register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); 355: struct inode *ip; 356: int error; 357: struct socket *so2; 358: 359: if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) 360: return (EMSGSIZE); 361: *(mtod(nam, caddr_t) + nam->m_len) = 0; 362: 363: error = UNPCONN(soun->sun_path, nam->m_len, &so2, &ip); 364: if (error || !so2 || !ip) 365: goto bad; 366: if (so->so_type != so2->so_type) { 367: error = EPROTOTYPE; 368: goto bad; 369: } 370: if (so->so_proto->pr_flags & PR_CONNREQUIRED && 371: ((so2->so_options&SO_ACCEPTCONN) == 0 || 372: (so2 = sonewconn(so2)) == 0)) { 373: error = ECONNREFUSED; 374: goto bad; 375: } 376: error = unp_connect2(so, so2); 377: bad: 378: if (ip) 379: IPUT(ip); 380: return (error); 381: } 382: 383: unp_connect2(so, so2) 384: register struct socket *so; 385: register struct socket *so2; 386: { 387: register struct unpcb *unp = sotounpcb(so); 388: register struct unpcb *unp2; 389: 390: if (so2->so_type != so->so_type) 391: return (EPROTOTYPE); 392: unp2 = sotounpcb(so2); 393: unp->unp_conn = unp2; 394: switch (so->so_type) { 395: 396: case SOCK_DGRAM: 397: unp->unp_nextref = unp2->unp_refs; 398: unp2->unp_refs = unp; 399: soisconnected(so); 400: break; 401: 402: case SOCK_STREAM: 403: unp2->unp_conn = unp; 404: soisconnected(so2); 405: soisconnected(so); 406: break; 407: 408: default: 409: panic("unp_connect2"); 410: } 411: return (0); 412: } 413: 414: unp_disconnect(unp) 415: struct unpcb *unp; 416: { 417: register struct unpcb *unp2 = unp->unp_conn; 418: 419: if (unp2 == 0) 420: return; 421: unp->unp_conn = 0; 422: switch (unp->unp_socket->so_type) { 423: 424: case SOCK_DGRAM: 425: if (unp2->unp_refs == unp) 426: unp2->unp_refs = unp->unp_nextref; 427: else { 428: unp2 = unp2->unp_refs; 429: for (;;) { 430: if (unp2 == 0) 431: panic("unp_disconnect"); 432: if (unp2->unp_nextref == unp) 433: break; 434: unp2 = unp2->unp_nextref; 435: } 436: unp2->unp_nextref = unp->unp_nextref; 437: } 438: unp->unp_nextref = 0; 439: unp->unp_socket->so_state &= ~SS_ISCONNECTED; 440: break; 441: 442: case SOCK_STREAM: 443: soisdisconnected(unp->unp_socket); 444: unp2->unp_conn = 0; 445: soisdisconnected(unp2->unp_socket); 446: break; 447: } 448: } 449: 450: #ifdef notdef 451: unp_abort(unp) 452: struct unpcb *unp; 453: { 454: 455: unp_detach(unp); 456: } 457: #endif 458: 459: /*ARGSUSED*/ 460: unp_usrclosed(unp) 461: struct unpcb *unp; 462: { 463: 464: } 465: 466: unp_drop(unp, errno) 467: struct unpcb *unp; 468: int errno; 469: { 470: struct socket *so = unp->unp_socket; 471: 472: so->so_error = errno; 473: unp_disconnect(unp); 474: if (so->so_head) { 475: so->so_pcb = (caddr_t) 0; 476: m_freem(unp->unp_addr); 477: (void) m_free(dtom(unp)); 478: sofree(so); 479: } 480: } 481: 482: #ifdef notdef 483: unp_drain() 484: { 485: 486: } 487: #endif 488: 489: unp_externalize(rights) 490: struct mbuf *rights; 491: { 492: int newfds = rights->m_len / sizeof (int); 493: register int i; 494: register struct file **rp = mtod(rights, struct file **); 495: register struct file *fp; 496: int f; 497: 498: printf("unp_externalize(0%o)\n",rights); 499: if (newfds > ufavail()) { 500: for (i = 0; i < newfds; i++) { 501: fp = *rp; 502: unp_discard(fp); 503: *rp++ = 0; 504: } 505: return (EMSGSIZE); 506: } 507: for (i = 0; i < newfds; i++) { 508: f = ufalloc(0); 509: if (f < 0) 510: panic("unp_externalize"); 511: fp = *rp; 512: u.u_ofile[f] = fp; 513: /* -1 added to msgcount, 0 to count */ 514: SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int), 515: fp, -1, 0); 516: unp_rights--; 517: *(int *)rp++ = f; 518: } 519: return (0); 520: } 521: 522: unp_internalize(rights) 523: struct mbuf *rights; 524: { 525: register struct file **rp; 526: int oldfds = rights->m_len / sizeof (int); 527: register int i; 528: register struct file *fp; 529: 530: printf("unp_internalize(0%o)\n",rights); 531: rp = mtod(rights, struct file **); 532: for (i = 0; i < oldfds; i++, rp++) 533: GETF(fp, *(int *)rp); 534: rp = mtod(rights, struct file **); 535: for (i = 0; i < oldfds; i++) { 536: GETF(fp, *(int *)rp); 537: *rp++ = fp; 538: /* bump both the message count and reference count of fp */ 539: SKcall(fadjust, sizeof(fp) + sizeof(int) + sizeof(int), 540: fp, 1, 1); 541: unp_rights++; 542: } 543: return (0); 544: } 545: 546: int unp_defer, unp_gcing; 547: int unp_mark(); 548: extern struct domain unixdomain; 549: 550: /* 551: * What I did to the next routine isn't pretty, feel free to redo it, but 552: * I doubt it'd be worth it since this isn't used very much. SMS 553: */ 554: unp_gc() 555: { 556: register struct file *fp; 557: register struct socket *so; 558: struct file *file, *fileNFILE, xf; 559: 560: if (unp_gcing) 561: return; 562: unp_gcing = 1; 563: restart: 564: unp_defer = 0; 565: /* get limits AND clear FMARK|FDEFER in all file table entries */ 566: SKcall(unpgc1, sizeof(file) + sizeof(fileNFILE), &file, &fileNFILE); 567: do { 568: for (fp = file; fp < fileNFILE; fp++) { 569: /* get file table entry, the return value is f_count */ 570: if (FPFETCH(fp, &xf) == 0) 571: continue; 572: if (xf.f_flag & FDEFER) { 573: FPFLAGS(fp, 0, FDEFER); 574: unp_defer--; 575: } else { 576: if (xf.f_flag & FMARK) 577: continue; 578: if (xf.f_count == xf.f_msgcount) 579: continue; 580: FPFLAGS(fp, FMARK, 0); 581: } 582: if (xf.f_type != DTYPE_SOCKET) 583: continue; 584: so = xf.f_socket; 585: if (so->so_proto->pr_domain != &unixdomain || 586: (so->so_proto->pr_flags&PR_RIGHTS) == 0) 587: continue; 588: if (so->so_rcv.sb_flags & SB_LOCK) { 589: sbwait(&so->so_rcv); 590: goto restart; 591: } 592: unp_scan(so->so_rcv.sb_mb, unp_mark); 593: } 594: } while (unp_defer); 595: for (fp = file; fp < fileNFILE; fp++) { 596: if (FPFETCH(fp, &xf) == 0) 597: continue; 598: if (xf.f_count == xf.f_msgcount && (xf.f_flag & FMARK) == 0) 599: while (FPFETCH(fp, &xf) && xf.f_msgcount) 600: unp_discard(fp); 601: } 602: unp_gcing = 0; 603: } 604: 605: unp_dispose(m) 606: struct mbuf *m; 607: { 608: int unp_discard(); 609: 610: if (m) 611: unp_scan(m, unp_discard); 612: } 613: 614: unp_scan(m0, op) 615: register struct mbuf *m0; 616: int (*op)(); 617: { 618: register struct mbuf *m; 619: register struct file **rp; 620: register int i; 621: int qfds; 622: 623: while (m0) { 624: for (m = m0; m; m = m->m_next) 625: if (m->m_type == MT_RIGHTS && m->m_len) { 626: qfds = m->m_len / sizeof (struct file *); 627: rp = mtod(m, struct file **); 628: for (i = 0; i < qfds; i++) 629: (*op)(*rp++); 630: break; /* XXX, but saves time */ 631: } 632: m0 = m0->m_act; 633: } 634: } 635: 636: unp_mark(fp) 637: struct file *fp; 638: { 639: struct file xf; 640: 641: FPFETCH(fp, &xf); 642: if (xf.f_flag & FMARK) 643: return; 644: unp_defer++; 645: FPFLAGS(fp, FMARK|FDEFER, 0); 646: } 647: 648: unp_discard(fp) 649: struct file *fp; 650: { 651: unp_rights--; 652: SKcall(unpdisc, sizeof(fp), fp); 653: }