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