|
|
1.1 root 1: #include "../chunix/chsys.h"
2: #include "../chunix/chconf.h"
3: #include "../chaos/chaos.h"
4:
5: /*
6: * Receive side - basically driven by an incoming packet.
7: */
8:
9: #define send_los(x,y) sendlos(x,y,sizeof(y) - 1)
10:
11: /*
12: * Receive a packet - called from receiver interrupt level.
13: */
14: rcvpkt(pkt)
15: register struct packet *pkt;
16: {
17: register struct connection *conn;
18: register unsigned index;
19:
20: debug(DPKT,printf("Rcvpkt: "));
21: pkt->pk_next = NOPKT;
22: if (pkt->pk_op == RUTOP)
23: rcvrut(pkt);
24: else if (pkt->pk_op >= MAXOP && !ISDATOP(pkt))
25: ch_free((char *)pkt);
26: else if (pkt->pk_daddr != Chmyaddr)
27: if ((++pkt->pk_fc) == 0) {
28: debug(DPKT|DABNOR,printf("Overforwarded packet\n"));
29: ignore:
30: ch_free((char *)pkt);
31: } else if (pkt->pk_saddr == Chmyaddr) {
32: debug(DPKT|DABNOR,printf("Got my own packet back\n"));
33: ch_free((char *)pkt);
34: } else if (Chmyaddr == -1)
35: ch_free((char *)pkt);
36: else {
37: debug(DPKT,printf("Forwarding pkt daddr=%x\n", pkt->pk_daddr));
38: sendctl(pkt);
39: }
40: else if (pkt->pk_op == MNTOP)
41: goto ignore;
42: else if (pkt->pk_op == RFCOP)
43: rcvrfc(pkt);
44: /*
45: * Check for various flavors of bad indexes
46: */
47: else if ((index = pkt->pk_dtindex) >= CHNCONNS ||
48: ((conn = Chconntab[index]) == NOCONN) ||
49: conn->cn_lidx != pkt->pk_didx) {
50: debug(DPKT|DABNOR,printf("Packet with bad index: %x, op:%d\n",
51: pkt->pk_didx, pkt->pk_op));
52: send_los(pkt, "Connection doesn't exist");
53: /*
54: * Handle responses to our RFC
55: */
56: } else if (conn->cn_state == CSRFCSENT)
57: switch(pkt->pk_op) {
58: case OPNOP:
59: debug(DCONN,printf("Conn #%x: OPEN received\n", conn->cn_lidx));
60: /*
61: * Make the connection open, taking his index
62: */
63: conn->cn_state = CSOPEN;
64: conn->cn_fidx = pkt->pk_sidx;
65: conn->cn_active = Chclock;
66: /*
67: * Indicate we have received AND "read" the OPEN
68: * Read his window size, indicate that he has
69: * received and acked the RFC, and acknowledge the OPN
70: */
71: conn->cn_rread = conn->cn_rlast = pkt->pk_pkn;
72: conn->cn_twsize = pkt->pk_rwsize;
73: receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
74: /*
75: * Wakeup the user waiting for the connection to open.
76: */
77: makests(conn, pkt);
78: reflect(pkt);
79: NEWSTATE(conn);
80: break;
81: case CLSOP:
82: case ANSOP:
83: case FWDOP:
84: debug(DCONN,printf("Conn #%x: CLOSE/ANS received for RFC\n", conn->cn_lidx));
85: clsconn(conn, CSCLOSED, pkt);
86: break;
87: default:
88: debug(DPKT|DABNOR,
89: printf("bad packet type for conn #%x in CSRFCSENT: %d\n",
90: conn->cn_lidx, pkt->pk_op));
91: send_los(pkt, "Bad packet type reponse to RFC");
92: }
93: /*
94: * Process a packet for an open connection
95: */
96: else if (conn->cn_state == CSOPEN) {
97: conn->cn_active = Chclock;
98: if (ISDATOP(pkt))
99: rcvdata(conn, pkt);
100: else switch (pkt->pk_op) {
101: case OPNOP:
102: /*
103: * Ignore duplicate opens.
104: */
105: debug(DPKT|DABNOR,printf("Duplicate open received\n"));
106: ch_free((char *)pkt);
107: break;
108: case SNSOP:
109: debug(DPKT,prpkt(pkt, "SNS"));
110: receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
111: makests(conn, pkt);
112: reflect(pkt);
113: break;
114: case EOFOP:
115: rcvdata(conn, pkt);
116: break;
117: case LOSOP:
118: case CLSOP:
119: debug(DCONN, printf("Close rcvd on %x\n", conn->cn_lidx));
120: clsconn(conn, pkt->pk_op == CLSOP ? CSCLOSED : CSLOST,
121: pkt);
122: break;
123: /*
124: * Uncontrolled data - que it at the head of the rlist
125: */
126: case UNCOP:
127: if ((pkt->pk_next = conn->cn_rhead) == NOPKT)
128: conn->cn_rtail = pkt;
129: conn->cn_rhead = pkt;
130: if (pkt == conn->cn_rtail)
131: INPUT(conn);
132: receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
133: break;
134: case STSOP:
135: debug(DABNOR,prpkt(pkt, "STS"));
136: debug(DABNOR,printf("Receipt=%d, Trans Window=%d\n",(unsigned)pkt->pk_idata[0], pkt->pk_idata[1]));
137: if (pkt->pk_rwsize > conn->cn_twsize)
138: OUTPUT(conn);
139: conn->cn_twsize = pkt->pk_rwsize;
140: receipt(conn, pkt->pk_ackn, pkt->pk_receipt);
141: ch_free((char *)pkt);
142: /* could check for very recent packets here */
143: if ((pkt = conn->cn_thead) != NOPKT) {
144: conn->cn_thead = conn->cn_ttail = NOPKT;
145: senddata(pkt);
146: }
147: break;
148: default:
149: debug(DPKT|DABNOR, printf("bad opcode:%d\n", pkt->pk_op));
150: send_los(pkt, "Bad opcode");
151: /* should we do clsconn here? */
152: }
153: /*
154: * Connection is neither waiting for an OPEN nor OPEN.
155: */
156: } else {
157: debug(DPKT|DABNOR,printf("Packet for conn #%x (not open) state=%d, op:%d\n", conn->cn_lidx, conn->cn_state, pkt->pk_op));
158: send_los(pkt, "Connection is closed");
159: }
160: }
161:
162: /*
163: * Send a control packet back to its source
164: */
165: reflect(pkt)
166: register struct packet *pkt;
167: {
168: register short temp;
169:
170: temp = pkt->pk_sidx;
171: pkt->pk_sidx = pkt->pk_didx;
172: pkt->pk_didx = temp;
173: temp = pkt->pk_saddr;
174: pkt->pk_saddr = pkt->pk_daddr;
175: pkt->pk_daddr = temp;
176: sendctl(pkt);
177: }
178:
179: /*
180: * Process a received data packet - or an EOF packet which is mostly treated
181: * the same.
182: */
183: rcvdata(conn, pkt)
184: register struct connection *conn;
185: register struct packet *pkt;
186: {
187: register struct packet *npkt;
188:
189: debug(DPKT,(prpkt(pkt,"DATA"),printf("\n")) );
190: if (cmp_gt(pkt->pk_pkn, conn->cn_rread + conn->cn_rwsize)) {
191: debug(DPKT|DABNOR,printf("Discarding data out of window\n"));
192: ch_free((char *)pkt);
193: return;
194: }
195: receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
196: if (cmp_le(pkt->pk_pkn, conn->cn_rlast)) {
197: debug(DPKT,printf("Duplicate data packet\n"));
198: makests(conn, pkt);
199: reflect(pkt);
200: return;
201: }
202:
203: /*
204: * Link the out of order list onto the new packet in case
205: * it fills the gap between in-order and out-of-order lists
206: * and to make it easy to grab all now-in-order packets from the
207: * out-of-order list.
208: */
209: pkt->pk_next = conn->cn_routorder;
210: /*
211: * Now transfer all in-order packets to the in-order list
212: */
213: for (npkt = pkt;
214: npkt != NOPKT &&
215: npkt->pk_pkn == (unsigned short)(conn->cn_rlast + 1);
216: npkt = npkt->pk_next) {
217: if (conn->cn_rhead == NOPKT)
218: conn->cn_rhead = npkt;
219: else
220: conn->cn_rtail->pk_next = npkt;
221: conn->cn_rtail = npkt;
222: conn->cn_rlast++;
223:
224: }
225: /*
226: * If we queued up any in-order pkts, check if spontaneous STS is needed
227: */
228: if (pkt != npkt) {
229: debug(DPKT,printf("new ordered data packet\n"));
230: conn->cn_rtail->pk_next = NOPKT;
231: conn->cn_routorder = npkt;
232: if (conn->cn_rhead == pkt)
233: INPUT(conn);
234: /*
235: * If we are buffering "many" packets, keep him up to date
236: * about the window. The second test can be flushed if it is
237: * more important to receipt than to save sending an "extra"
238: * STS with no new acknowledgement.
239: * Lets do without it for a while.
240: if ((short)(conn->cn_rlast - conn->cn_racked) > conn->cn_rsts &&
241: conn->cn_racked != conn->cn_rread)
242: sendsts(conn);
243: */
244: /*
245: * Here we have received an out of order packet which must be
246: * inserted into the out-of-order queue, in packet number order.
247: */
248: } else {
249: for (npkt = pkt; (npkt = npkt->pk_next) != NOPKT &&
250: cmp_gt(pkt->pk_pkn, npkt->pk_pkn); )
251: pkt->pk_next = npkt; /* save the last pkt here */
252: if (npkt != NOPKT && pkt->pk_pkn == npkt->pk_pkn) {
253: debug(DPKT|DABNOR,
254: printf("Duplicate out of order packet\n"));
255: pkt->pk_next = NOPKT;
256: makests(conn, pkt);
257: reflect(pkt);
258: } else {
259: if (npkt == conn->cn_routorder)
260: conn->cn_routorder = pkt;
261: else
262: pkt->pk_next->pk_next = pkt;
263: pkt->pk_next = npkt;
264: debug(DPKT|DABNOR,
265: printf("New out of order packet\n"));
266: }
267: }
268: }
269:
270: /*
271: * Make a STS packet for a connection, reflecting its current state
272: */
273: makests(conn, pkt)
274: register struct connection *conn;
275: register struct packet *pkt;
276: {
277: pkt->pk_op = STSOP;
278: pkt->pk_lenword = sizeof(struct sts_data);
279: pkt->pk_ackn = conn->cn_racked = conn->cn_rread;
280: pkt->pk_receipt = conn->cn_rlast;
281: pkt->pk_rwsize = conn->cn_rwsize;
282: }
283:
284: /*
285: * Process receipts and acknowledgements using recnum as the receipt.
286: */
287: receipt(conn, acknum, recnum)
288: register struct connection *conn;
289: unsigned short acknum, recnum;
290: {
291: register struct packet *pkt, *pktl;
292:
293: /*
294: * Process a receipt, freeing packets that we now know have been
295: * received.
296: */
297: if (cmp_gt(recnum, conn->cn_trecvd)) {
298: for (pktl = conn->cn_thead;
299: pktl != NOPKT && cmp_le(pktl->pk_pkn, recnum);
300: pktl = pkt) {
301: pkt = pktl->pk_next;
302: ch_free((char *)pktl);
303: }
304: if ((conn->cn_thead = pktl) == NOPKT)
305: conn->cn_ttail = NOPKT;
306: conn->cn_trecvd = recnum;
307: }
308: /*
309: * If the acknowledgement is new, update our idea of the
310: * latest acknowledged packet, and wakeup output that might be blocked
311: * on a full transmit window.
312: */
313: if (cmp_gt(acknum, conn->cn_tacked))
314: if (cmp_gt(acknum, conn->cn_tlast))
315: debug(DABNOR, (printf("Invalid acknowledgment(%d,%d)\n",
316: acknum, conn->cn_tlast)));
317: else {
318: conn->cn_tacked = acknum;
319: OUTPUT(conn);
320: }
321: }
322:
323: /*
324: * Send a LOS in response to the given packet.
325: * Don't bother if the packet is itself a LOS or a CLS since the other
326: * end doesn't care anyway and would only return it again.
327: * Append the host name to the error message.
328: */
329: sendlos(pkt, str, len)
330: register struct packet *pkt;
331: char *str;
332: {
333: if (pkt->pk_op == LOSOP || pkt->pk_op == CLSOP)
334: ch_free((char *)pkt);
335: else {
336: register char *cp;
337: register int length;
338:
339: for (cp = Chmyname, length = 0; *cp && length < CHSTATNAME;) {
340: length++;
341: cp++;
342: }
343: if (pkt = pktstr(pkt, str, len + length + sizeof("(from )") - 1)) {
344: chmove("(from ", &pkt->pk_cdata[len], 6);
345: chmove(Chmyname, &pkt->pk_cdata[len + 6], length);
346: chmove(")", &pkt->pk_cdata[len + 6 + length], 1);
347: pkt->pk_op = LOSOP;
348: reflect(pkt);
349: }
350: }
351: }
352:
353: /*
354: * Process a received RFC
355: */
356: rcvrfc(pkt)
357: register struct packet *pkt;
358: {
359: register struct connection *conn, **conptr;
360: struct packet **opkt, *pktl;
361:
362: debug(DPKT,prpkt(pkt,"RFC"));
363: debug(DPKT,printf("contact = %s\n", pkt->pk_cdata));
364: /*
365: * Check if this is a duplicate RFC, and if so throw it away,
366: * and retransmit the OPEN.
367: */
368: for (conptr = &Chconntab[0]; conptr < &Chconntab[CHNCONNS];)
369: if ((conn = *conptr++) != NOCONN &&
370: conn->cn_fidx == pkt->pk_sidx &&
371: conn->cn_faddr == pkt->pk_saddr) {
372: if (conn->cn_state == CSOPEN) {
373: debug(DPKT|DABNOR,
374: printf("Rcvrfc: Retransmitting open chan #%x\n", (*conptr)->cn_lidx));
375: sendopn(conn);
376: } else {
377: debug(DPKT|DABNOR,
378: printf("Rcvrfc: Duplicate RFC: %x\n",
379: conn->cn_lidx));
380: }
381: ch_free((char *)pkt);
382: return;
383: }
384: /*
385: * Scan the listen list for a listener and if one is found
386: * open the connection and remove the listen packet from the
387: * listen list.
388: */
389: for (opkt = &Chlsnlist; (pktl = *opkt) != NOPKT; opkt = &pktl->pk_next)
390: if(concmp(pkt, pktl->pk_cdata, (int)pktl->pk_len)) {
391: conn = Chconntab[pktl->pk_stindex];
392: *opkt = pktl->pk_next;
393: ch_free((char *)pktl);
394: lsnmatch(pkt, conn);
395: NEWSTATE(conn);
396: return;
397: }
398: if (concmp(pkt, "STATUS", 6)) {
399: statusrfc(pkt);
400: return;
401: }
402: if (concmp(pkt, "TIME", 4)) {
403: timerfc(pkt);
404: return;
405: }
406: if (Chrfcrcv == 0) {
407: send_los(pkt, "All servers disabled");
408: return;
409: }
410: /*
411: * There was no listener, so queue the RFC on the unmatched RFC list
412: * again checking for duplicates.
413: */
414: pkt->pk_ackn = 0; /* this is for ch_rskip, in chuser.c */
415: pkt->pk_next = NOPKT;
416: if ((pktl = Chrfclist) == NOPKT)
417: Chrfclist = Chrfctail = pkt;
418: else {
419: do {
420: if(pktl->pk_sidx == pkt->pk_sidx &&
421: pktl->pk_saddr == pkt->pk_saddr) {
422: debug(DPKT/*|DABNOR*/,printf("Rcvrfc: Discarding duplicate Rfc on Chrfclist\n"));
423: ch_free((char *)pkt);
424: return;
425: }
426: } while ((pktl = pktl->pk_next) != NOPKT);
427: Chrfctail->pk_next = pkt;
428: Chrfctail = pkt;
429: }
430: debug(DCONN,printf("Rcvrfc: Queued Rfc on Chrfclist: '%c%c%c%c'\n",
431: pkt->pk_cdata[0], pkt->pk_cdata[1], pkt->pk_cdata[2],
432: pkt->pk_cdata[3]));
433: RFCINPUT;
434: }
435: /*
436: * An RFC has matched a listener, either by an RFC coming and finding a match
437: * on the listener list, or by a listen being done and matching an RFC on the
438: * unmatched RFC list. So we change the state of the connection to CSRFCRCVD
439: */
440: lsnmatch(rfcpkt, conn)
441: register struct packet *rfcpkt;
442: register struct connection *conn;
443: {
444: debug(DCONN,printf("Conn #%x: LISTEN matched \n", conn->cn_lidx));
445: /*
446: * Initialize the conection
447: */
448: conn->cn_active = Chclock;
449: conn->cn_state = CSRFCRCVD;
450: conn->cn_rwsize = CHDRWSIZE;
451: conn->cn_faddr = rfcpkt->pk_saddr;
452: conn->cn_fidx = rfcpkt->pk_sidx;
453: /*
454: * Queue up the RFC for the user to read if he wants it.
455: */
456: rfcpkt->pk_next = NOPKT;
457: conn->cn_rhead = conn->cn_rtail = rfcpkt;
458: /*
459: * Indicate to the other end that we have received and "read"
460: * the RFC so that the open will truly acknowledge it.
461: */
462: conn->cn_rlast = conn->cn_rread = rfcpkt->pk_pkn;
463: }
464: /*
465: * Remove a listener from the listener list, due to the listener bailing out.
466: * Called from top level at high priority
467: */
468: rmlisten(conn)
469: register struct connection *conn;
470: {
471: register struct packet *opkt, *pkt;
472:
473: opkt = NOPKT;
474: for (pkt = Chlsnlist; pkt != NOPKT; opkt = pkt, pkt = pkt->pk_next)
475: if (pkt->pk_stindex == conn->cn_ltidx) {
476: if(opkt == NOPKT)
477: Chlsnlist = pkt->pk_next;
478: else
479: opkt->pk_next = pkt->pk_next;
480: ch_free((char *)pkt);
481: break;
482: }
483: }
484: /*
485: * Compare the RFC contact name with the listener name.
486: */
487: concmp(rfcpkt, lsnstr, lsnlen)
488: struct packet *rfcpkt;
489: register char *lsnstr;
490: register int lsnlen;
491: {
492: register char *rfcstr = rfcpkt->pk_cdata;
493: register int rfclen;
494:
495: debug(DPKT,printf("Rcvrfc: Comparing %s and %s\n", rfcstr, lsnstr));
496: for (rfclen = rfcpkt->pk_len; rfclen; rfclen--, lsnlen--)
497: if (lsnlen <= 0)
498: return ((*rfcstr == ' ') ? 1 : 0);
499: else if (*rfcstr++ != *lsnstr++)
500: return(0);
501: return (lsnlen == 0);
502: }
503: /*
504: * Process a routing packet.
505: */
506: rcvrut(pkt)
507: struct packet *pkt;
508: {
509: register int i;
510: register struct rut_data *rd;
511: register struct chroute *r;
512:
513: debug(DPKT, ( prpkt(pkt,"RUT"),printf("\n") ) );
514: rd = pkt->pk_rutdata;
515: if (pkt->pk_ssubnet >= CHNSUBNET)
516: printf("CHAOS: bad subnet %d in RUT pkt\n", pkt->pk_ssubnet);
517: else if (Chroutetab[pkt->pk_ssubnet].rt_type != CHDIRECT)
518: printf("CHAOS: RUT pkt from unconnected subnet %d\n",
519: pkt->pk_ssubnet);
520: else for (i = pkt->pk_len; i; i -= sizeof(struct rut_data), rd++) {
521: if (rd->pk_subnet >= CHNSUBNET) {
522: debug(DABNOR, printf("CHAOS: bad subnet %d in RUT pkt\n",
523: rd->pk_subnet));
524: continue;
525: }
526: r = &Chroutetab[rd->pk_subnet];
527: switch (r->rt_type) {
528: case 0:
529: case CHBRIDGE:
530: if (rd->pk_cost <= r->rt_cost) {
531: r->rt_cost = rd->pk_cost;
532: r->rt_type = CHBRIDGE;
533: r->rt_addr = pkt->pk_saddr;
534: }
535: break;
536: case CHDIRECT:
537: case CHFIXED:
538: break;
539: default:
540: printf("CHAOS: Illegal chaos routing table entry %d",
541: r->rt_type);
542: }
543: }
544: ch_free((char *)pkt);
545: }
546:
547: /*
548: * process a RFC for contact name STATUS
549: */
550: statusrfc(rpkt)
551: register struct packet *rpkt;
552: {
553: register struct packet *pkt;
554: register struct chroute *r;
555: register struct chxcvr *xp;
556: register struct statdata *sp;
557: register int i;
558:
559: for (i = 0, r = Chroutetab; r < &Chroutetab[CHNSUBNET]; r++)
560: if (r->rt_type == CHDIRECT)
561: i++;
562: i *= sizeof(struct stathead) + sizeof(struct statxcvr);
563: i += CHSTNAME;
564: if ((pkt = pkalloc(i, 1)) == NOPKT) {
565: ch_free((char *)rpkt);
566: return;
567: }
568: pkt->pk_daddr = rpkt->pk_saddr;
569: pkt->pk_didx = rpkt->pk_sidx;
570: ch_free((char *)rpkt);
571: pkt->pk_type = 0;
572: pkt->pk_op = ANSOP;
573: pkt->pk_next = NOPKT;
574: pkt->pk_saddr = Chmyaddr;
575: pkt->pk_sidx = pkt->pk_pkn = pkt->pk_ackn = 0;
576: pkt->pk_lenword = i;
577: chmove(Chmyname, pkt->pk_status.sb_name, CHSTATNAME);
578: sp = &pkt->pk_status.sb_data[0];
579: for (r = Chroutetab; r < &Chroutetab[CHNSUBNET]; r++)
580: if (r->rt_type == CHDIRECT) {
581: xp = r->rt_xcvr;
582: sp->sb_ident = 0400 + xp->xc_subnet;
583: sp->sb_nshorts = sizeof(struct statxcvr) / sizeof(short);
584: sp->sb_xstat = xp->xc_xstat;
585: #ifdef pdp11
586: swaplong(&sp->sb_xstat,
587: sizeof(struct statxcvr) / sizeof(long));
588: #endif
589: sp = (struct statdata *)((char *)sp +
590: sizeof(struct stathead) +
591: sizeof(struct statxcvr));
592: }
593: sendctl(pkt);
594: }
595:
596: /*
597: * process a RFC for contact name TIME
598: */
599: timerfc(pkt)
600: register struct packet *pkt;
601: {
602: long t;
603:
604: pkt->pk_op = ANSOP;
605: pkt->pk_next = NOPKT;
606: pkt->pk_pkn = pkt->pk_ackn = 0;
607: pkt->pk_lenword = sizeof(long);
608: ch_time(&t);
609: pkt->pk_ldata[0] = t;
610: #ifdef pdp11
611: swaplong(&pkt->pk_ldata, 1);
612: #endif pdp11
613: reflect(pkt);
614: }
615: #ifdef DEBUG
616: prpkt(pkt, str)
617: register struct packet *pkt;
618: char *str;
619: {
620: printf("op=%s(%o) len=%d fc=%d\ndhost=%o didx=%x\nshost=%o sidx=%x\npkn=%d ackn=%d ",
621: str, pkt->pk_op, pkt->pk_len, pkt->pk_fc, pkt->pk_dhost,
622: pkt->pk_didx, pkt->pk_shost, pkt->pk_sidx,
623: (unsigned)pkt->pk_pkn, (unsigned)pkt->pk_ackn);
624: }
625: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.