|
|
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.