|
|
1.1 ! root 1: #include <sys/param.h> ! 2: #include <sys/enio.h> ! 3: #include <sys/filio.h> ! 4: #include <errno.h> ! 5: #include <ipc.h> ! 6: #include <signal.h> ! 7: ! 8: typedef unsigned char uchar; ! 9: ! 10: /* ! 11: * one structure per fd to decide what to do with ! 12: * input on the fd. ! 13: */ ! 14: typedef struct { ! 15: void (*func)(); /* function to call */ ! 16: void *ptr; ! 17: } Fdesc; ! 18: Fdesc f[NOFILE]; ! 19: ! 20: /* ! 21: * bit mask of fds to listen on ! 22: */ ! 23: fd_set master; ! 24: int etherfd; ! 25: ! 26: /* ! 27: * name to address translation ! 28: */ ! 29: typedef struct Address { ! 30: char *name; ! 31: uchar addr[6]; ! 32: int ack; ! 33: } Address; ! 34: Address addr[] = { ! 35: { "ross", 0x02, 0x07, 0x01, 0x00, 0x5e, 0xff, 0 }, ! 36: { "research", 0x02, 0x07, 0x01, 0x00, 0x62, 0x8a, 1 }, ! 37: { "ara", 0x08, 0x00, 0x47, 0x00, 0x09, 0xfa, 1 }, ! 38: { "shamash", 0x08, 0x00, 0x20, 0x01, 0x37, 0x78, 1 }, ! 39: { "ra", 0x08, 0x00, 0x20, 0x01, 0x34, 0x13, 1 }, ! 40: { "aten", 0x08, 0x00, 0x20, 0x01, 0x3b, 0x74, 1 }, ! 41: { "pipe", 0x08, 0x00, 0x2b, 0x09, 0x57, 0x94, 1 }, ! 42: { "sol", 0x08, 0x00, 0x20, 0x01, 0x64, 0xab, 1 }, ! 43: { "bowell", 0x08, 0x00, 0x2b, 0x0b, 0xce, 0xda, 1 }, ! 44: { "pyxis", 0x08, 0x00, 0x69, 0x02, 0x01, 0x4e, 1 }, ! 45: { "r70", 0x08, 0x00, 0x2b, 0x04, 0x26, 0x5d, 1 }, ! 46: { "nun", 0x08, 0x00, 0x20, 0x00, 0x24, 0xc4, 1 }, ! 47: { "wild", 0x02, 0x07, 0x01, 0x00, 0x4e, 0x05, 1 }, ! 48: { "coma", 0x08, 0x00, 0x2b, 0x0b, 0x1d, 0x9b, 1 }, ! 49: { "tempel", 0x02, 0xcf, 0x1f, 0x11, 0x73, 0x13, 1 }, ! 50: { "bootes", 0x08, 0x00, 0x69, 0x02, 0x02, 0x05, 0 }, ! 51: { "helix", 0x08, 0x00, 0x69, 0x02, 0x04, 0x27, 1 }, ! 52: { "spindle", 0x08, 0x00, 0x69, 0x02, 0x01, 0x9e, 1 }, ! 53: { "hr4784", 0x00, 0x00, 0xa7, 0x00, 0x08, 0x28, 1 }, ! 54: { 0 } ! 55: }; ! 56: ! 57: /* ! 58: * ethernet header ! 59: */ ! 60: typedef struct Etherhdr { ! 61: uchar d[6]; ! 62: uchar s[6]; ! 63: uchar type[2]; ! 64: uchar circuit[3]; /* circuit number */ ! 65: uchar flag; ! 66: uchar mid; /* message id */ ! 67: uchar ack; /* piggy back ack */ ! 68: uchar remain[2]; /* count of remaing bytes of data */ ! 69: uchar sum[2]; /* checksum (0 means none) */ ! 70: } Etherhdr; ! 71: ! 72: /* ! 73: * ethernet packet ! 74: */ ! 75: typedef struct Ethermsg { ! 76: uchar d[6]; ! 77: uchar s[6]; ! 78: uchar type[2]; ! 79: uchar circuit[3]; /* circuit number */ ! 80: uchar flag; ! 81: uchar mid; /* message id */ ! 82: uchar ack; /* piggy back ack */ ! 83: uchar remain[2]; /* count of remaing bytes of data */ ! 84: uchar sum[2]; /* checksum (0 means none) */ ! 85: uchar data[1500 - 10]; ! 86: } Ethermsg; ! 87: #define HDRSIZE 24 ! 88: #define NEWCALL 0x1 /* flag bit marking a new circuit */ ! 89: #define HANGUP 0x2 /* flag bit requesting hangup */ ! 90: #define ACKME 0x4 /* acknowledge this message */ ! 91: #define ETHER_TYPE 0x9 /* most significant byte last */ ! 92: ! 93: char *dev[] = { ! 94: "/dev/qe02", ! 95: "/dev/il02", ! 96: "/dev/bna02", ! 97: 0, ! 98: }; ! 99: ! 100: /* ! 101: * nonet conversations ! 102: */ ! 103: #define NCIRC (NOFILE/2) ! 104: #define MAXMSG (8*1024+100) ! 105: typedef struct Circuit { ! 106: Fdesc *f; ! 107: int hangingup; ! 108: int hungup; ! 109: int version; ! 110: ! 111: uchar rcved; /* last msg rcved */ ! 112: int mid; /* id of current input message */ ! 113: int rem; /* remaining bytes for input current message */ ! 114: int rcvcircuit; /* circuit number of incoming packets */ ! 115: uchar ibuf[MAXMSG]; ! 116: int ibi; ! 117: int eofs; ! 118: ! 119: uchar sent; /* last msg sent */ ! 120: uchar ackrcved; /* last ack received */ ! 121: int resent; /* number of times a message is transmitted */ ! 122: Etherhdr eh; /* prototype ethernet header */ ! 123: uchar obuf[MAXMSG]; ! 124: int obi; ! 125: } Circuit; ! 126: Circuit circ[NCIRC]; ! 127: ! 128: void announce(); ! 129: void openether(); ! 130: void newcall(); ! 131: void fromclient(); ! 132: void fromether(); ! 133: void timeout(); ! 134: void fillhdr(); ! 135: void send(); ! 136: void hangup(); ! 137: void ack(); ! 138: void resend(); ! 139: void ackdead(); ! 140: ! 141: int debug; ! 142: ! 143: main(ac, av) ! 144: int ac; ! 145: char *av[]; ! 146: { ! 147: fd_set set; ! 148: int fds; ! 149: int i; ! 150: ! 151: debug = 0; ! 152: if(ac > 1 && strcmp(av[1], "-d")==0) ! 153: debug = 1; ! 154: chdir("/cs"); ! 155: FD_ZERO(master); ! 156: if(!debug) ! 157: detach("nonet"); ! 158: announce(); ! 159: openether(); ! 160: signal(SIGPIPE, SIG_IGN); ! 161: for(;;){ ! 162: /* ! 163: * keep polling the fds for input. call an ! 164: * fd's input routine whenever it has any input. ! 165: */ ! 166: set = master; ! 167: switch(fds = select(NOFILE, &set, 0, 1000)){ ! 168: case -1: ! 169: logevent("switch returned -1"); ! 170: exit(1); ! 171: case 0: ! 172: timeout(); ! 173: continue; ! 174: } ! 175: for(i = 0; fds && i < NOFILE; i++){ ! 176: if(FD_ISSET(i, set)) { ! 177: fds--; ! 178: if(f[i].func != 0) ! 179: (*f[i].func)(i); ! 180: else { ! 181: logevent("io on bad fd %d\n", i); ! 182: FD_CLR(i, master); ! 183: close(i); ! 184: } ! 185: } ! 186: } ! 187: } ! 188: } ! 189: ! 190: /* ! 191: * set up a connected pair of fd's to listen on. ! 192: * if fd2 < 0, then there is only 1 fd. ! 193: */ ! 194: newf(fd, func) ! 195: int fd; ! 196: void (*func)(); ! 197: { ! 198: f[fd].func = func; ! 199: FD_SET(fd, master); ! 200: } ! 201: ! 202: /* ! 203: * close an fd, stop listening to it, and close off it's related fd. ! 204: */ ! 205: delf(fd) ! 206: int fd; ! 207: { ! 208: if(fd < 0) ! 209: return; ! 210: if(f[fd].func == 0) ! 211: return; ! 212: f[fd].func = 0; ! 213: close(fd); ! 214: FD_CLR(fd, master); ! 215: } ! 216: ! 217: /* ! 218: * plug into the name space ! 219: */ ! 220: void ! 221: announce() ! 222: { ! 223: int fd; ! 224: ! 225: fd = ipccreat("/cs/nonet", ""); ! 226: if(fd<0){ ! 227: logconsole("error announcing /cs/nonet\n"); ! 228: exit(1); ! 229: } ! 230: newf(fd, newcall); ! 231: logconsole("/cs/nonet announced\n"); ! 232: } ! 233: ! 234: /* ! 235: * listen to the nonet ether type ! 236: */ ! 237: void ! 238: openether() ! 239: { ! 240: int fd; ! 241: int i; ! 242: extern int buf_ld; ! 243: ! 244: for(i = 0; dev[i]; i++){ ! 245: fd = open(dev[i], 2); ! 246: if(fd >= 0) ! 247: break; ! 248: } ! 249: if(fd < 0){ ! 250: logevent("opening ethernet device\n"); ! 251: exit(1); ! 252: } ! 253: i = ETHER_TYPE; ! 254: if(ioctl(fd, ENIOTYPE, &i) < 0){ ! 255: perror("ENIOTYPE"); ! 256: exit(1); ! 257: } ! 258: newf(fd, fromether); ! 259: etherfd = fd; ! 260: if(ioctl(etherfd, FIOPUSHLD, &buf_ld)<0){ ! 261: perror("pushing buf_ld"); ! 262: } ! 263: if(ioctl(etherfd, FIOPUSHLD, &buf_ld)<0){ ! 264: perror("pushing buf_ld"); ! 265: } ! 266: } ! 267: ! 268: /* ! 269: * there is input on the announcement channel. see if a ! 270: * new call has come in. ! 271: */ ! 272: void ! 273: newcall(fd) ! 274: int fd; ! 275: { ! 276: ipcinfo *ipc; ! 277: Circuit *cp; ! 278: Address *a; ! 279: int circuit; ! 280: int nfd; ! 281: char *service; ! 282: char *strchr(); ! 283: ! 284: logevent("newcall\n"); ! 285: ipc = ipclisten(fd); ! 286: if(ipc == 0){ ! 287: logevent("listening %s\n", errstr); ! 288: return; ! 289: } ! 290: ! 291: /* ! 292: * Find a new circuit for the call. ! 293: */ ! 294: for(cp = circ; cp < &circ[NCIRC]; cp++){ ! 295: if(cp->f == 0) ! 296: break; ! 297: } ! 298: if(cp == &circ[NCIRC]){ ! 299: logevent("call from %s!%s busy\n", ipc->machine, ipc->user); ! 300: ipcreject(ipc, EBUSY, "out of output channels"); ! 301: return; ! 302: } ! 303: logevent("call from %s!%s on %d\n", ipc->machine, ipc->user, cp - circ); ! 304: ! 305: /* ! 306: * separate name and service ! 307: */ ! 308: service = strchr(ipc->name, '.'); ! 309: if(service) ! 310: *service++ = 0; ! 311: else{ ! 312: service = strchr(ipc->name, '!'); ! 313: if(service) ! 314: *service++ = 0; ! 315: } ! 316: if(service==0) ! 317: service = ""; ! 318: ! 319: /* ! 320: * see if we know the destination ! 321: */ ! 322: for(a = addr; a->name; a++){ ! 323: if(strcmp(a->name, ipc->name) == 0) ! 324: break; ! 325: } ! 326: if(a->name == 0){ ! 327: logevent("call from %s!%s, %s!%s unknown dest\n", ipc->machine, ipc->user, ! 328: ipc->name, service); ! 329: ipcreject(ipc, EEXIST, "unknown destination"); ! 330: return; ! 331: } ! 332: nfd = ipcaccept(ipc); ! 333: if(nfd < 0){ ! 334: logevent("call from %s!%s error accepting\n", ipc->machine, ipc->user); ! 335: return; ! 336: } ! 337: logevent("call from %s!%s to %s!%s accepted\n", ipc->machine, ipc->user, ipc->name, ! 338: service); ! 339: ! 340: /* ! 341: * init the circuit ! 342: */ ! 343: f[nfd].ptr = (void *)cp; ! 344: cp->f = &f[nfd]; ! 345: cp->hangingup = 0; ! 346: cp->hungup = 0; ! 347: cp->eofs = 0; ! 348: cp->ackrcved = 0; ! 349: cp->sent = 0; ! 350: cp->ibi = 0; ! 351: cp->obi = 0; ! 352: cp->rcved = 0; ! 353: cp->mid = 0; ! 354: circuit = 2*((cp - circ)+cp->version*NCIRC); ! 355: cp->rcvcircuit = circuit+1; ! 356: cp->version++; ! 357: if(a->ack) ! 358: cp->eh.flag = NEWCALL|ACKME; ! 359: else ! 360: cp->eh.flag = NEWCALL; ! 361: cp->eh.circuit[2] = circuit>>16; ! 362: cp->eh.circuit[1] = circuit>>8; ! 363: cp->eh.circuit[0] = circuit; ! 364: memcpy(cp->eh.d, a->addr, sizeof(a->addr)); ! 365: cp->eh.type[1] = ETHER_TYPE>>8; ! 366: cp->eh.type[0] = ETHER_TYPE; ! 367: newf(nfd, fromclient); ! 368: ! 369: if(strcmp(service, "bootfs") == 0){ ! 370: /* ! 371: * send ok to the caller ! 372: */ ! 373: write(nfd, "OK", 2); ! 374: } else if(strcmp(service, "fs") != 0){ ! 375: /* ! 376: * send user id ! 377: */ ! 378: sprint(cp->obuf, "%s %s", ipc->user, service); ! 379: cp->obi += strlen(cp->obuf); ! 380: send(cp); ! 381: } ! 382: } ! 383: ! 384: /* ! 385: * input from the ethernet ! 386: */ ! 387: void ! 388: fromether(fd) ! 389: int fd; ! 390: { ! 391: int len; ! 392: short r; ! 393: int c; ! 394: Circuit *cp; ! 395: Ethermsg em; ! 396: int hungup; ! 397: ! 398: /* ! 399: * read/parse an ethernet message ! 400: */ ! 401: len = read(fd, &em, sizeof(Ethermsg)); ! 402: if(len <= 0){ ! 403: logevent("error reading from ether\n"); ! 404: return; ! 405: } ! 406: if(debug) ! 407: printpacket("in", &em); ! 408: r = (em.remain[1]<<8) | em.remain[0]; ! 409: c = (em.circuit[2]<<16) | (em.circuit[1]<<8) | em.circuit[0]; ! 410: hungup = em.flag & HANGUP; ! 411: ! 412: /* ! 413: * look for an existing client ! 414: */ ! 415: for(cp = circ; cp < &circ[NCIRC]; cp++){ ! 416: if(cp->f && c == cp->rcvcircuit ! 417: && memcmp(cp->eh.d, em.s, sizeof(em.s)) == 0) ! 418: break; ! 419: } ! 420: if(cp == &circ[NCIRC]) { ! 421: logevent("no client found\n"); ! 422: ackdead(&em); ! 423: return; ! 424: } ! 425: ! 426: len -= HDRSIZE; ! 427: if(r>=0){ ! 428: /* ! 429: * a new message, forget any old messages ! 430: */ ! 431: cp->ibi = 0; ! 432: cp->mid = em.mid; ! 433: cp->rem = r; ! 434: } else { ! 435: /* ! 436: * a continuation ! 437: */ ! 438: if(cp->mid != em.mid || -r != cp->rem) { ! 439: /* bad fragment -- drop anything ibuffered */ ! 440: logevent("cp->mid %d em.mid %d r %d cp->rem %d\n", cp->mid, em.mid, ! 441: r, cp->rem); ! 442: cp->ibi = 0; ! 443: return; ! 444: } ! 445: } ! 446: cp->rem -= len; ! 447: ! 448: /* ! 449: * last packet may be ``padded out''. adjust size if it is. ! 450: */ ! 451: if(cp->rem < 0){ ! 452: if(-cp->rem <= len){ ! 453: len += cp->rem; ! 454: cp->rem = 0; ! 455: } else { ! 456: logevent("short packet\n"); ! 457: return; ! 458: } ! 459: } ! 460: ! 461: /* ! 462: * copy the packet into the buffer ! 463: */ ! 464: memcpy(&(cp->ibuf[cp->ibi]), em.data, len); ! 465: cp->ibi += len; ! 466: ! 467: /* ! 468: * if last packet of a message... ! 469: */ ! 470: if(cp->rem == 0){ ! 471: /* ! 472: * ... is it what we expected? ! 473: */ ! 474: if(((cp->rcved+1)&0xff) != cp->mid){ ! 475: if(cp->rcved == cp->mid){ ! 476: cp->ackrcved = em.ack; ! 477: if(cp->ibi) ! 478: ack(cp); /* retransmission */ ! 479: fd = cp->f - f; ! 480: if(cp->ackrcved == cp->sent && f[fd].func) ! 481: FD_SET(fd, master); ! 482: return; ! 483: } ! 484: logevent("expected %d got %d\n", (cp->rcved+1)&0xff, cp->mid); ! 485: cp->ibi = 0; ! 486: return; ! 487: } ! 488: /* ! 489: * ... update state and send packet to client ! 490: */ ! 491: cp->eh.flag &= ~NEWCALL; ! 492: cp->rcved = cp->mid; ! 493: cp->ackrcved = em.ack; ! 494: fd = cp->f - f; ! 495: if(cp->ackrcved == cp->sent && f[fd].func) ! 496: FD_SET(fd, master); ! 497: if(cp->ibi && write(fd, cp->ibuf, cp->ibi) != cp->ibi){ ! 498: logevent("error writing to client %d %d\n", fd, cp->ibi); ! 499: hangup(cp); ! 500: } ! 501: if(hungup){ ! 502: cp->hungup = 1; ! 503: hangup(cp); ! 504: } ! 505: if(cp->eh.flag & ACKME) ! 506: ack(cp); ! 507: } ! 508: } ! 509: ! 510: /* ! 511: * collect a message from a client. 4 eofs in a row mean the connection ! 512: * is closed. ! 513: */ ! 514: void ! 515: fromclient(fd) ! 516: int fd; ! 517: { ! 518: int len; ! 519: Circuit *cp; ! 520: ! 521: cp = (Circuit *)(f[fd].ptr); ! 522: ! 523: /* ! 524: * read in the message ! 525: */ ! 526: len = read(fd, cp->obuf, sizeof(cp->obuf)); ! 527: if(len < 0){ ! 528: hangup(cp); ! 529: return; ! 530: } ! 531: if(len == 0){ ! 532: if(++(cp->eofs) == 4){ ! 533: hangup(cp); ! 534: return; ! 535: } ! 536: } else ! 537: cp->eofs = 0; ! 538: cp->obi = len; ! 539: ! 540: /* ! 541: * send message ! 542: */ ! 543: send(cp); ! 544: } ! 545: ! 546: /* ! 547: * send a message on a circuit ! 548: */ ! 549: void ! 550: send(cp) ! 551: Circuit *cp; ! 552: { ! 553: cp->sent++; ! 554: cp->resent = 0; ! 555: FD_CLR(cp->f - f, master); ! 556: resend(cp); ! 557: } ! 558: ! 559: /* ! 560: * resend a message on a circuit ! 561: */ ! 562: void ! 563: resend(cp) ! 564: Circuit *cp; ! 565: { ! 566: Ethermsg em; ! 567: int rem, len, first; ! 568: ! 569: /* ! 570: * break up the message into some number of ! 571: * ethernet packets and send them. ! 572: */ ! 573: first = 1; ! 574: for (rem = cp->obi; first || rem > 0; rem -= len){ ! 575: first = 0; ! 576: fillhdr(cp, &em, rem == cp->obi ? rem : -rem); ! 577: len = rem > sizeof(em.data) ? sizeof(em.data) : rem; ! 578: memcpy(em.data, &(cp->obuf[cp->obi - rem]), len); ! 579: if(len < 128-HDRSIZE) ! 580: len = 128-HDRSIZE; ! 581: if(debug) ! 582: printpacket("out", &em); ! 583: if(write(etherfd, &em, len + HDRSIZE) != len + HDRSIZE){ ! 584: logevent("error writing to ether\n"); ! 585: return; ! 586: } ! 587: } ! 588: } ! 589: ! 590: /* ! 591: * ack a dead client ! 592: */ ! 593: void ! 594: ackdead(e) ! 595: Ethermsg *e; ! 596: { ! 597: Ethermsg em; ! 598: ! 599: memcpy(em.d, e->s, sizeof(em.d)); ! 600: memcpy(em.s, e->d, sizeof(em.s)); ! 601: em.mid = e->ack; ! 602: em.ack = e->mid; ! 603: em.flag = HANGUP; ! 604: e->remain[1] = 0; ! 605: e->remain[0] = 0; ! 606: e->sum[0] = e->sum[1] = 0; ! 607: ! 608: if(write(etherfd, &em, HDRSIZE) != HDRSIZE){ ! 609: logevent("error writing to ether\n"); ! 610: return; ! 611: } ! 612: } ! 613: ! 614: /* ! 615: * fill in an ethernet/nonet header ! 616: */ ! 617: void ! 618: fillhdr(cp, e, rem) ! 619: Circuit *cp; ! 620: Ethermsg *e; ! 621: int rem; ! 622: { ! 623: memcpy(e, &cp->eh, HDRSIZE); ! 624: e->mid = cp->sent; ! 625: e->ack = cp->rcved; ! 626: e->remain[1] = rem>>8; ! 627: e->remain[0] = rem; ! 628: e->sum[0] = e->sum[1] = 0; ! 629: } ! 630: ! 631: /* ! 632: * retransmit any unacknowledged messages ! 633: */ ! 634: void ! 635: timeout(sig) ! 636: int sig; ! 637: { ! 638: Circuit *cp; ! 639: ! 640: for(cp = circ; cp < &circ[NCIRC]; cp++){ ! 641: if(cp->f && cp->sent != cp->ackrcved){ ! 642: if(++(cp->resent) > 15) { ! 643: logevent("too many rexmits, giving up %d\n", cp - circ); ! 644: delf(cp->f - f); ! 645: cp->f = 0; ! 646: } else ! 647: resend(cp); ! 648: } ! 649: if(cp->f && cp->hungup && cp->hangingup && cp->sent == cp->ackrcved) ! 650: cp->f = 0; ! 651: } ! 652: } ! 653: ! 654: /* ! 655: * hangup a connection ! 656: */ ! 657: void ! 658: hangup(cp) ! 659: Circuit *cp; ! 660: { ! 661: Ethermsg em; ! 662: ! 663: logevent("hanging up %d\n", cp - circ); ! 664: if(cp->hangingup) ! 665: return; ! 666: cp->hangingup = 1; ! 667: cp->eh.flag |= HANGUP; ! 668: cp->obi = 0; ! 669: delf(cp->f - f); ! 670: send(cp); ! 671: cp->f = 0; ! 672: } ! 673: ! 674: /* ! 675: * ack a message ! 676: */ ! 677: void ! 678: ack(cp) ! 679: Circuit *cp; ! 680: { ! 681: Ethermsg em; ! 682: ! 683: fillhdr(cp, &em, 0); ! 684: if(write(etherfd, &em, HDRSIZE) != HDRSIZE){ ! 685: logevent("error writing to ether\n"); ! 686: return; ! 687: } ! 688: } ! 689: ! 690: printpacket(tag, p) ! 691: char *tag; ! 692: Ethermsg *p; ! 693: { ! 694: uchar *cp; ! 695: cp = p->circuit; ! 696: fprint(2, "%s: d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%ux %ux)d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)\n", ! 697: tag, ! 698: p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5], ! 699: p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5], p->type[0], p->type[1], ! 700: cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], ! 701: cp[6], cp[7], cp[8], cp[9], cp[10], cp[11]); ! 702: } ! 703:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.