Annotation of researchv8dc/sys/chaosld/chrcv.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *             C H  R C V
                      3:  *
                      4:  * Chaosnet line discipline - handle a received packet.
                      5:  * Chrcv() is called by the service routine for the RD queue.
                      6:  *
                      7:  *
                      8:  * (c) Copyright 1984  Nirvonics, Inc.
                      9:  *
                     10:  * Written by Kurt Gollhardt
                     11:  * Last update Fri Nov 16 11:16:20 1984
                     12:  *
                     13:  * This software is the property of Nirvonics, Inc.
                     14:  * All rights reserved.
                     15:  *
                     16:  */
                     17: 
                     18: #include "ch.h"
                     19: #if NCH > 0
                     20: #include "../h/param.h"
                     21: #include "../h/systm.h"
                     22: #include "../h/stream.h"
                     23: #include "../h/conf.h"
                     24: #include "../chaosld/types.h"
                     25: #include "../chaosld/constants.h"
                     26: #include "../chaosld/globals.h"
                     27: 
                     28: #define send_los(pkt,str)     sendlos(pkt,str,sizeof(str)-1)
                     29: 
                     30: #define STS_AGE            hz/4      /* Minimum pkt age for re-xmission on STS */
                     31: 
                     32: 
                     33: chrcv(q)
                     34:      struct queue   *q;
                     35: {
                     36:      register struct packet        *pkt;
                     37:      register struct connection    *conn;
                     38:      register struct sts_data      *sts;
                     39:      register unsigned   index;
                     40: 
                     41:      debug(DPKT,printf("Chrcv: "));
                     42:      if ((pkt = get_packet(q, 0)) == NOPKT)
                     43:           return;
                     44:      pkt->next = NOPKT;
                     45: 
                     46:      ch_busy++;
                     47:      if (pkt->pk_op == MNTOP)
                     48:           free_packet(pkt);
                     49:      else if (pkt->pk_op == RFCOP)
                     50:           rcvrfc(pkt);
                     51:      else if (pkt->pk_op == BRDOP)
                     52:           rcvbrd(pkt);
                     53:      /*
                     54:       * Check for various flavors of bad indices
                     55:       */
                     56:      else if ((index = pkt->pk_didx.ci_tidx) >= NCH ||
                     57:                (conn = Chconn[index]) == NOCONN ||
                     58:               pkt->pk_didx.ci_idx != conn->cn_lidx.ci_idx) {
                     59:           debug(DPKT|DABNOR,printf("Packet with bad index: %x, op:0%o\n",
                     60:                pkt->pk_didx, pkt->pk_op));
                     61:           send_los(pkt, "Connection doesn't exist");
                     62:      /*
                     63:       * Handle responses to our RFC
                     64:       */
                     65:      } else if (conn->cn_state == CSRFCSENT)
                     66:           switch(pkt->pk_op) {
                     67:           case OPNOP:
                     68:                debug(DCONN,printf("Conn #%x: OPEN received\n", conn->cn_lidx));
                     69:                /*
                     70:                 * Mark the connection as open, saving his index
                     71:                 */
                     72:                conn->cn_state = CSOPEN;
                     73:                conn->cn_fidx = pkt->pk_sidx;
                     74:                conn->cn_time = Chclock;
                     75:                /*
                     76:                 * Indicate we have received AND "read" the OPEN
                     77:                 * Read his window size, indicate that he has
                     78:                 * received and acked the RFC, and acknowledge the OPN
                     79:                 */
                     80:                conn->cn_rread = conn->cn_rlast = pkt->pk_pkn;
                     81:               flatten(pkt);
                     82:               sts = (struct sts_data *)pkt->data->rptr;
                     83:                conn->cn_twsize = sts->sts_rwsize;
                     84:                receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
                     85:                /*
                     86:                 * Send him back an STS to get things going.
                     87:                 */
                     88:                setsts(conn, pkt);
                     89:                reflect(pkt);
                     90:               chd_newstate(conn);
                     91:                break;
                     92:           case CLSOP:
                     93:           case ANSOP:
                     94:           case FWDOP:
                     95:                debug(DCONN,printf("Conn #%x: CLOSE/ANS received for RFC\n", conn->cn_lidx));
                     96:                close_conn(conn, CSCLOSED, pkt);
                     97:                break;
                     98:           default:
                     99:                debug(DPKT|DABNOR,
                    100:                     printf("bad packet type for conn #%x in CSRFCSENT: %d\n",
                    101:                          conn->cn_lidx, pkt->pk_op));
                    102:                send_los(pkt, "Bad packet type reponse to RFC");
                    103:           }
                    104:      /*
                    105:       * Process a packet for an open connection
                    106:       */
                    107:      else if (conn->cn_state == CSOPEN) {
                    108:           conn->cn_time = Chclock;
                    109:           if (ISDATA(pkt))
                    110:                rcvdata(conn, pkt);
                    111:           else switch (pkt->pk_op) {
                    112:               case OPNOP:
                    113:                /*
                    114:                 * Ignore duplicate opens.
                    115:                 */
                    116:                debug(DPKT|DABNOR,printf("Duplicate open received\n"));
                    117:                free_packet(pkt);
                    118:                break;
                    119:           case SNSOP:
                    120:                debug(DPKT,prpkt(pkt, "SNS"));
                    121:                receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
                    122:                setsts(conn, pkt);
                    123:                reflect(pkt);
                    124:                break;
                    125:           case EOFOP:
                    126:                rcvdata(conn, pkt);
                    127:                break;
                    128:           case LOSOP:
                    129:           case CLSOP:
                    130:                debug(DCONN, printf("Close rcvd on %x\n", conn->cn_lidx));
                    131:                close_conn(conn, pkt->pk_op == CLSOP ? CSCLOSED : CSLOST,
                    132:                     pkt);
                    133:                break;
                    134:                /*
                    135:                 * Uncontrolled data - queue it at the head of the rlist
                    136:                 */
                    137:           case UNCOP:
                    138:                receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
                    139:               ch_input(conn, pkt);  /* Send packet to pseudo-device */
                    140:                break;
                    141:           case STSOP:
                    142:                flatten(pkt);
                    143:               sts = (struct sts_data *)pkt->data->rptr;
                    144:                if (sts->sts_rwsize > conn->cn_twsize)
                    145:                     chd_newout(conn);
                    146:                conn->cn_twsize = sts->sts_rwsize;
                    147:                receipt(conn, pkt->pk_ackn, sts->sts_receipt);
                    148:                free_packet(pkt);
                    149:               chretran(conn, STS_AGE);  /* Re-xmit all but very recent pkts */
                    150:                break;
                    151:           default:
                    152:                debug(DPKT|DABNOR, printf("bad opcode:%d\n", pkt->pk_op));
                    153:                send_los(pkt, "Bad opcode");
                    154:                /* should we do close_conn here? */
                    155:           }
                    156:      /*
                    157:       * Connection is neither waiting for an OPEN nor OPEN.
                    158:       */
                    159:      } else {
                    160:           debug(DPKT|DABNOR,printf("Packet for conn #%x (not open) state=%d, op:%d\n", conn->cn_lidx, conn->cn_state, pkt->pk_op));
                    161:           send_los(pkt, "Connection is closed");
                    162:      }
                    163: 
                    164:      --ch_busy;
                    165: }
                    166: 
                    167: /*
                    168:  * Process a received data packet - or an EOF packet which is mostly treated
                    169:  * the same.
                    170:  */
                    171: rcvdata(conn, pkt)
                    172:      register struct connection    *conn;
                    173:      register struct packet        *pkt;
                    174: {
                    175:      register struct packet   *npkt;
                    176: 
                    177:      debug(DPKT,(prpkt(pkt,"DATA"),printf("\n")) );
                    178:      if (cmp_gt(pkt->pk_pkn, conn->cn_rread + conn->cn_rwsize)) {
                    179:           debug(DPKT|DABNOR,printf("Discarding data out of window\n"));
                    180:           free_packet(pkt);
                    181:           return;
                    182:      }
                    183:      receipt(conn, pkt->pk_ackn, pkt->pk_ackn);
                    184:      if (cmp_le(pkt->pk_pkn, conn->cn_rlast)) {
                    185:           debug(DPKT,printf("Duplicate data packet\n"));
                    186:           setsts(conn, pkt);
                    187:           reflect(pkt);
                    188:           return;
                    189:      }
                    190: 
                    191:      /*
                    192:       * Link the out of order list onto the new packet in case
                    193:       * it fills the gap between in-order and out-of-order lists
                    194:       * and to make it easy to grab all now-in-order packets from the
                    195:       * out-of-order list.
                    196:       */
                    197:      pkt->next = conn->cn_routorder;
                    198:      /*
                    199:       * Now transfer all in-order packets to the pseudo-device
                    200:       */
                    201:      for (npkt = pkt; npkt != NOPKT &&
                    202:                     npkt->pk_pkn == (unsigned short)(conn->cn_rlast + 1);
                    203:                     npkt = npkt->next) {
                    204:           conn->cn_rlast++;
                    205:           ch_input(conn, npkt);
                    206:      }
                    207:      /*
                    208:       * If we received any in-order pkts, check if spontaneous STS is needed
                    209:       */
                    210:      if (pkt != npkt) {
                    211:           debug(DPKT,printf("new ordered data packet\n"));
                    212:           conn->cn_routorder = npkt;
                    213:      } else {
                    214:      /*
                    215:       * Here we have received an out of order packet which must be
                    216:       * inserted into the out-of-order queue, in packet number order. 
                    217:       */
                    218:           for (npkt = pkt; (npkt = npkt->next) != NOPKT &&
                    219:                      cmp_gt(pkt->pk_pkn, npkt->pk_pkn); )
                    220:                pkt->next = npkt;     /* save the last pkt here */
                    221: 
                    222:           if (npkt != NOPKT && pkt->pk_pkn == npkt->pk_pkn) {
                    223:                debug(DPKT|DABNOR,
                    224:                     printf("Duplicate out of order packet\n"));
                    225:                pkt->next = NOPKT;
                    226:                setsts(conn, pkt);
                    227:                reflect(pkt);
                    228:           } else {
                    229:                if (npkt == conn->cn_routorder)
                    230:                     conn->cn_routorder = pkt;
                    231:                else
                    232:                     pkt->next->next = pkt;
                    233:                pkt->next = npkt;
                    234:                debug(DPKT|DABNOR,
                    235:                      printf("New out of order packet\n"));
                    236:           }
                    237:      }
                    238: }
                    239: 
                    240: /*
                    241:  * Process receipts and acknowledgements using recnum as the receipt.
                    242:  */
                    243: receipt(conn, acknum, recnum)
                    244: register struct connection *conn;
                    245: unsigned short acknum, recnum;
                    246: {
                    247:      register struct packet *pkt, *pktl;
                    248: 
                    249:      ch_busy++;
                    250:      /*
                    251:       * Process a receipt, freeing packets that we now know have been
                    252:       * received.
                    253:       */
                    254:      if (cmp_gt(recnum, conn->cn_trecvd)) {
                    255:           for (pktl = conn->cn_thead;
                    256:                pktl != NOPKT && cmp_le(pktl->pk_pkn, recnum);
                    257:                pktl = pkt) {
                    258:                pkt = pktl->next;
                    259:                free_packet(pktl);
                    260:           }
                    261:           if ((conn->cn_thead = pktl) == NOPKT)
                    262:                conn->cn_ttail = NOPKT;
                    263:           conn->cn_trecvd = recnum;
                    264:      }
                    265:      /*
                    266:       * If the acknowledgement is new, update our idea of the
                    267:       * latest acknowledged packet, and wakeup output that might be blocked
                    268:       * on a full transmit window.
                    269:       */
                    270:      if (cmp_gt(acknum, conn->cn_tacked))
                    271:           if (cmp_gt(acknum, conn->cn_tlast)) {
                    272:                debug(DABNOR, (printf("Invalid acknowledgment(%d,%d)\n",
                    273:                     acknum, conn->cn_tlast)));
                    274:           } else {
                    275:                conn->cn_tacked = acknum;
                    276:                chd_newout(conn);
                    277:           }
                    278:      --ch_busy;
                    279: }
                    280: 
                    281: 
                    282: #ifdef BRDBRIDGE
                    283: 
                    284: int Chbrdbridge = 1;
                    285: #define MAXBRD    8
                    286: 
                    287: #endif BRDBRIDGE
                    288: 
                    289: /*
                    290:  * Process a received BRD
                    291:  * The trickiness is that we must modify the bit map completely before
                    292:  * sending it to anyone - thus we must remember all those to send it to.
                    293:  */
                    294: 
                    295: rcvbrd(pkt)
                    296:      register struct packet   *pkt;
                    297: {
                    298:      int       bitlen = pkt->pk_ackn;
                    299: 
                    300:           /* Here pk_ackn is # bytes in subnet bitmap */
                    301:      if ((pkt->pk_len <= bitlen) || (bitlen >= CHNSUBNET/8)) {
                    302:           free_packet(pkt);
                    303:           return;
                    304:      }
                    305:      if (flatten(pkt))
                    306:           return;
                    307: 
                    308: #ifdef BRDBRIDGE
                    309:      if (Chbrdbridge) {
                    310:           register struct chroute  *r;
                    311:           register int   mask, i;
                    312:           struct packet  *npkt;
                    313:          chaddr    addrs[MAXBRD], *adp;
                    314: 
                    315:           bitp = pkt->data->rptr;
                    316:           for (i = 0, r = Chroutetab; r < bitlen; i++)
                    317:                for (mask = 1; mask & 0377; mask <<= 1, r++)
                    318:                     if (r->rt_type == CHDIRECT && r->rt_cost < HIGH_COST &&
                    319:                               *bitp & mask && adp < &addrs[MAXBRD]) {
                    320:                          *bitp &= ~mask;
                    321:                         *adp++ = r->rt_path.ifp->my_addr;
                    322:                     }
                    323:           while (adp > addrs) {                         
                    324:                if ((npkt = new_packet()) == NOPKT)
                    325:                     return;
                    326:                npkt->ph = pkt->ph;
                    327:                append_packet(npkt, pkt->data->rptr, pkt->pk_len);
                    328:                npkt->pk_daddr = *--adp;
                    329:                npkt->pk_daddr.ch_host = 0;
                    330:               npkt->pk_pkn = 1;
                    331:                sendctl(npkt);
                    332:           }
                    333:      }
                    334: #endif BRDBRIDGE
                    335: 
                    336:      pkt->pk_lenword = pkt->pk_len - bitlen;
                    337:      pkt->data->rptr += bitlen;
                    338:      pkt->pk_ackn = 0;
                    339:      rcvrfc(pkt);
                    340: }
                    341: 
                    342: /*
                    343:  * Process a received RFC
                    344:  */
                    345: rcvrfc(pkt)
                    346:      register struct packet   *pkt;
                    347: {
                    348:      register struct connection    *conn, **conptr;
                    349:      register struct service  *svp;
                    350:      extern struct service    Chservice[];
                    351:      struct packet  **opkt, *pktl;
                    352: 
                    353:      debug(DPKT,prpkt(pkt,"RFC/BRD"));
                    354:      /*
                    355:       * Check if this is a duplicate RFC, and if so throw it away,
                    356:       * and retransmit the OPEN.
                    357:       */
                    358:      for (conptr = &Chconn[0]; conptr < &Chconn[NCH];)
                    359:           if ((conn = *conptr++) != NOCONN &&
                    360:                     conn->cn_fidx.ci_idx == pkt->pk_sidx.ci_idx &&
                    361:                      conn->cn_faddr.ch_addr == pkt->pk_saddr.ch_addr) {
                    362:                if (conn->cn_state == CSOPEN) {
                    363:                     debug(DPKT|DABNOR,
                    364:                          printf("Rcvrfc: Retransmitting open chan #%x\n",
                    365:                                   (*conptr)->cn_lidx.ci_idx));
                    366:                     chretran(conn, 0);
                    367:                } else {
                    368:                     debug(DPKT|DABNOR,
                    369:                          printf("Rcvrfc: Duplicate RFC: %x\n",
                    370:                               conn->cn_lidx.ci_idx));
                    371:                }
                    372:                free_packet(pkt);
                    373:                return;
                    374:           }
                    375: 
                    376:      if (flatten(pkt)) {
                    377:           free_packet(pkt);
                    378:          return;
                    379:      }
                    380: 
                    381:      /*
                    382:       * Scan the listen list for a listener and if one is found
                    383:       * open the connection and remove the listen packet from the
                    384:       * listen list.
                    385:       */
                    386:      for (opkt = &Chlsnlist; (pktl = *opkt) != NOPKT; opkt = &pktl->next)
                    387:           if(concmp(pkt, pktl->data->rptr, (int)pktl->pk_len)) {
                    388:                conn = Chconn[pktl->pk_sidx.ci_tidx];
                    389:                *opkt = pktl->next;
                    390:                free_packet(pktl);
                    391:                lsnmatch(pkt, conn);
                    392:                chd_newstate(conn);
                    393:                return;
                    394:           }
                    395:      /*
                    396:       * Check for built-in services.
                    397:       */
                    398:      for (svp = Chservice; svp->name != 0; ++svp)
                    399:           if (concmp(pkt, svp->name, svp->len)) {
                    400:               (*svp->func)(pkt);
                    401:               return;
                    402:           }
                    403:      /*
                    404:       * There was no listener, so queue the RFC on the unmatched RFC list
                    405:       * again checking for duplicates.
                    406:       */
                    407:      if ((pktl = Chrfclist) == NOPKT) 
                    408:           Chrfclist = Chrfctail = pkt;
                    409:      else {
                    410:           do {
                    411:                if(pktl->pk_sidx.ci_idx == pkt->pk_sidx.ci_idx &&
                    412:                   pktl->pk_saddr.ch_addr == pkt->pk_saddr.ch_addr) {
                    413:                     debug(DPKT/*|DABNOR*/,printf("Rcvrfc: Discarding duplicate Rfc on Chrfclist\n"));
                    414:                     free_packet(pkt);
                    415:                     return;
                    416:                }
                    417:           } while ((pktl = pktl->next) != NOPKT);
                    418:           Chrfctail->next = pkt;
                    419:           Chrfctail = pkt;
                    420:      }
                    421:      debug(DCONN,printf("Rcvrfc: Queued Rfc on Chrfclist\n"));
                    422:      /*
                    423:       * A new unmatched RFC has been received.  Send a copy of it up to the
                    424:       * unmatched RFC server.
                    425:       */
                    426:      copy_pkdata(ChaosQ, pkt);
                    427: }
                    428: 
                    429: /*
                    430:  * An RFC has matched a listener, either by an RFC coming and finding a match
                    431:  * on the listener list, or by a listen being done and matching an RFC on the
                    432:  * unmatched RFC list. So we change the state of the connection to CSRFCRCVD
                    433:  */
                    434: lsnmatch(rfcpkt, conn)
                    435:      register struct packet        *rfcpkt;
                    436:      register struct connection    *conn;
                    437: {
                    438:      debug(DCONN,printf("Conn #%x: LISTEN matched \n", conn->cn_lidx));
                    439:      /*
                    440:       * Initialize the conection
                    441:       */
                    442:      conn->cn_time = Chclock;
                    443:      conn->cn_state = CSRFCRCVD;
                    444:      if (conn->cn_rwsize == 0)
                    445:           conn->cn_rwsize = CHDRWSIZE;
                    446:      conn->cn_faddr = rfcpkt->pk_saddr;
                    447:      conn->cn_fidx = rfcpkt->pk_sidx;
                    448: 
                    449:      /*
                    450:       * Indicate to the other end that we have received and "read"
                    451:       * the RFC so that the open will truly acknowledge it.
                    452:       */
                    453:      conn->cn_rlast = conn->cn_rread = rfcpkt->pk_pkn;
                    454:      /*
                    455:       * Queue up the RFC for the user to read if he wants it.
                    456:       */
                    457:      chdrint(conn, rfcpkt);
                    458: }
                    459: 
                    460: /*
                    461:  * Remove a listener from the listener list, due to the listener bailing out.
                    462:  * Called from top level at high priority
                    463:  */
                    464: rmlisten(conn)
                    465:      register struct connection    *conn;
                    466: {
                    467:      register struct packet   *opkt, *pkt;
                    468: 
                    469:      opkt = NOPKT;
                    470:      for (pkt = Chlsnlist; pkt != NOPKT; opkt = pkt, pkt = pkt->next)
                    471:           if (pkt->pk_sidx.ci_tidx == conn->cn_lidx.ci_tidx) {
                    472:                if(opkt == NOPKT)
                    473:                     Chlsnlist = pkt->next;
                    474:                else
                    475:                     opkt->next = pkt->next;
                    476:                free_packet(pkt);
                    477:                break;
                    478:           }
                    479: }
                    480: 
                    481: /*
                    482:  * Compare the RFC contact name with the listener name.
                    483:  */
                    484: concmp(rfcpkt, lsnstr, lsnlen)
                    485:      struct packet  *rfcpkt;
                    486:      register char  *lsnstr;
                    487:      register int   lsnlen;
                    488: {
                    489:      register char *rfcstr = (char *)rfcpkt->data->rptr;
                    490:      register int rfclen;
                    491: 
                    492:      debug(DPKT,{printf("Rcvrfc: Comparing ");
                    493:                  print_str(rfcpkt->pk_len, rfcstr);
                    494:                 printf(" and ");
                    495:                 print_str(lsnlen, lsnstr);
                    496:                 printf("\n");});
                    497:      for (rfclen = rfcpkt->pk_len; rfclen; rfclen--, lsnlen--)
                    498:           if (lsnlen <= 0)
                    499:                return ((*rfcstr == ' ') ? 1 : 0);
                    500:           else if (*rfcstr++ != *lsnstr++)
                    501:                return(0);
                    502:      return (lsnlen == 0);
                    503: }
                    504: 
                    505: 
                    506: ch_input(conn, pkt)
                    507:      struct connection   *conn;
                    508:      struct packet       *pkt;
                    509: {
                    510:      int       pkn, op, controlled;
                    511: 
                    512:      pkn = pkt->pk_pkn;
                    513:      op = pkt->pk_op;
                    514:      controlled = CONTROLLED(pkt);
                    515: 
                    516:      chdrint(conn, pkt);
                    517: 
                    518:      if (controlled) {
                    519:           conn->cn_rread = pkn;
                    520:          if (op == EOFOP)
                    521:               sendsts(conn);
                    522:      }
                    523: }
                    524: 
                    525: 
                    526: #ifdef DEBUG
                    527: prpkt(pkt, str)
                    528: register struct packet *pkt;
                    529: char *str;
                    530: {
                    531:      printf("op=%s(%o) len=%d fc=%d\ndhost=%o didx=%x\nshost=%o sidx=%x\npkn=%d ackn=%d\n",
                    532:           str, pkt->pk_op, pkt->pk_len, pkt->pk_fc, pkt->pk_daddr.ch_addr,
                    533:           pkt->pk_didx.ci_idx, pkt->pk_saddr.ch_addr, pkt->pk_sidx.ci_idx,
                    534:           (unsigned)pkt->pk_pkn, (unsigned)pkt->pk_ackn);
                    535: }
                    536: 
                    537: print_str(len, s)
                    538:      register int   len;
                    539:      register char  *s;
                    540: {
                    541:      while (len-- > 0 && *s != '\0')
                    542:           printf("%c", *s++);
                    543: }
                    544: #endif DEBUG
                    545: 
                    546: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.