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

1.1       root        1: /*
                      2:  *             C H R O U T E  L D
                      3:  *
                      4:  * Chaosnet packet routing line discipline.
                      5:  *
                      6:  *
                      7:  * (c) Copyright 1985  Nirvonics, Inc.
                      8:  *
                      9:  * Written by Kurt Gollhardt
                     10:  * Last update Tue Mar 12 04:21:35 1985
                     11:  *
                     12:  * This software is the property of Nirvonics, Inc.
                     13:  * All rights reserved.
                     14:  *
                     15:  */
                     16: 
                     17: #include "chroute.h"
                     18: #if NCHROUTE > 0
                     19: #include "../h/param.h"
                     20: #include "../h/systm.h"
                     21: #include "../h/stream.h"
                     22: #include "../h/ioctl.h"
                     23: #include "../h/ttyld.h"
                     24: #include "../h/conf.h"
                     25: #include "../h/order.h"
                     26: #include "../h/ethernet.h"
                     27: #include "../chaosld/types.h"
                     28: #include "../chaosld/constants.h"
                     29: #include "../chaosld/chrouteld.h"
                     30: 
                     31: 
                     32: struct chif    Chif[NCHROUTE];
                     33: struct chroute Chroute[CHNSUBNET];
                     34: 
                     35: static struct chif  *primary;
                     36: 
                     37: int  NChropen;
                     38: int  NChroute = NCHROUTE;
                     39: int  NChsubnet = CHNSUBNET;
                     40: 
                     41: int  Chrtimer; /* Routing timer running */
                     42: 
                     43: int chroute_open(), chroute_close(), chroute_put(), chroute_srv();
                     44: static struct qinit chroute_init = {
                     45:           chroute_put, chroute_srv, chroute_open, chroute_close, 512, 64
                     46: };
                     47: struct streamtab chrouteinfo = { &chroute_init, &chroute_init };
                     48: 
                     49: #define DEBUG
                     50: 
                     51: #ifdef DEBUG
                     52:      int  Chrdebug = 0;
                     53: #    define debug(x)     if (Chrdebug) x
                     54: #else
                     55: #    define debug(x)
                     56: #endif
                     57: 
                     58: static struct statxcvr  zstat;
                     59: 
                     60: 
                     61: chroute_open(q, dev)
                     62:      register struct queue    *q;
                     63:      dev_t     dev;
                     64: {
                     65:      register int   i;
                     66:      register struct chif     *ifp;
                     67: 
                     68:      if (q->ptr)    /* If this stream is already open, don't do anything */
                     69:           return 1;
                     70: 
                     71:      /* Look for a free interface structure */
                     72: 
                     73:      if (NChropen++ == NCHROUTE)
                     74:          return 0;  /* If there are none left, the open fails */
                     75:      for (i = 0, ifp = Chif; ifp->rdq != 0; ++ifp)
                     76:           ;
                     77: 
                     78:      ifp->rdq = q;
                     79:      ifp->my_addr.ch_addr = 0;
                     80:      ifp->arp = -1;
                     81:      ifp->if_dev = dev;
                     82:      ifp->if_cost = HIGH_COST / 4;  /* We expect this to be set by an ioctl,
                     83:                                         but just in case ... */
                     84:      ifp->if_stat = zstat;
                     85: 
                     86:      q->flag |= QDELIM|QNOENB;
                     87:      WR(q)->flag |= QDELIM|QNOENB;
                     88:      q->ptr = WR(q)->ptr = (caddr_t)ifp;
                     89: 
                     90:      if (!Chrtimer)
                     91:          ch_rtimer();
                     92: 
                     93:      return 1;
                     94: }
                     95: 
                     96: 
                     97: chroute_close(q)
                     98:      register struct queue    *q;
                     99: {
                    100:      register struct chif     *ifp;
                    101: 
                    102:      --NChropen;
                    103:      ifp = (struct chif *)q->ptr;
                    104:      Chroute[ifp->my_addr.ch_subnet].rt_type = CHNOPATH;
                    105:      arp_disable(ifp->arp);
                    106:      ifp->rdq = (struct queue *)0;
                    107:      ifp->my_addr.ch_addr = 0;
                    108:      if (ifp == primary)
                    109:           primary = (struct chif *)0;
                    110:      q->ptr = 0;
                    111: }
                    112: 
                    113: 
                    114: chroute_put(q, bp)
                    115:      register struct queue    *q;
                    116:      register struct block    *bp;
                    117: {
                    118:      debug(printf("chroute_put(%s, %d)\n",
                    119:                     ((q->flag & QREADR)? "RD" : "WR"), bp->type));
                    120: 
                    121:      switch (bp->type) {
                    122:           case M_DATA:
                    123:               putq(q, bp);
                    124:               break;
                    125:           case M_DELIM:
                    126:               putq(q, bp);
                    127:               qenable(q);
                    128:               break;
                    129:           case M_IOCTL:
                    130:               /* Process an ioctl only if it's going towards the device */
                    131:               if (!(q->flag & QREADR) && chroute_ioctl(q, bp))
                    132:                    break;
                    133:           default:  /* Anything else, just pass on to the next guy */
                    134:               (*q->next->qinfo->putp)(q->next, bp);
                    135:      }
                    136: }
                    137: 
                    138: 
                    139: chroute_srv(q)
                    140:      register struct queue    *q;
                    141: {
                    142:      register struct block    *bp;
                    143:      register struct chif     *ifp;
                    144:      register struct chroute  *r;
                    145:      int       minsize;
                    146: 
                    147:      /* We have a complete packet in the queue, composed of some number
                    148:           of M_DATA's followed by an M_DELIM.
                    149:         We know there are no other block types, because chroute_put()
                    150:          won't give us anything else.  */
                    151: 
                    152:      debug(printf("chroute_srv(%s)\n", ((q->flag & QREADR)? "RD" : "WR")));
                    153: 
                    154:      if (bp = q->first) {
                    155:           if (bp->type == M_DELIM) {
                    156:               printf("chroute: delimiter without data\n");
                    157:               flush_packet(q);
                    158:               return;
                    159:           }
                    160:          minsize = sizeof(struct pkt_header);
                    161:          if (q->flag & QREADR) {
                    162:               /* The packet is coming from the device */
                    163:               minsize += sizeof(struct ether_in);
                    164:           }
                    165:           if (block_pullup(q, minsize) == 0) {
                    166:               flush_packet(q);
                    167:               return;
                    168:           }
                    169:          if (q->flag & QREADR) {
                    170:               /* Packet is from device; strip off ethernet header */
                    171:               q->first->rptr += sizeof(struct ether_in);
                    172:               ifp = (struct chif *)q->ptr;
                    173:               ifp->ist_rcvd++;
                    174:               if (ifp->my_addr.ch_addr != 0) {
                    175:                    r = &Chroute[ifp->my_addr.ch_subnet];
                    176:                    r->rt_type = CHDIRECT;
                    177:                    r->rt_cost = ifp->if_cost;
                    178:                    r->rt_path.ifp = ifp;
                    179:               }
                    180:           }
                    181:          chroute_dispatch(q);
                    182: 
                    183:           /* See if there's another packet on the queue */
                    184:          for (bp = q->first; bp != NOBLOCK; bp = bp->next)
                    185:               if (bp->type == M_DELIM) {
                    186:                    qenable(q);    /* re-enable queue for the next packet */
                    187:                    break;
                    188:                }
                    189:      }
                    190: }
                    191: 
                    192: 
                    193:      /* Handle an ioctl */
                    194: 
                    195: chroute_ioctl(q, bp)
                    196:      register struct queue    *q;
                    197:      register struct block    *bp;
                    198: {
                    199:      register union stmsg     *sp;
                    200:      register struct chif     *ifp;
                    201:      register struct chroute  *rt;
                    202:      register struct chaddr_pair   *chp;
                    203: 
                    204:      ifp = (struct chif *)q->ptr;
                    205:      sp = (union stmsg *)bp->rptr;
                    206:      switch (sp->iocx.com) {
                    207:           case CHIOCADDR:
                    208:               bp->wptr = bp->rptr;
                    209:               if (ifp->my_addr.ch_addr != 0) {
                    210:                    Chroute[ifp->my_addr.ch_subnet].rt_type = CHNOPATH;
                    211:                    arp_disable(ifp->arp);
                    212:                }
                    213:               ifp->my_addr.ch_addr = *(int *)(sp->iocx.xxx);
                    214:               if (ifp->my_addr.ch_subnet >= CHNSUBNET
                    215:                         || ifp->my_addr.ch_subnet == 0) {
                    216:                    ifp->my_addr.ch_addr = 0;
                    217:                    bp->type = M_IOCNAK;
                    218:                    break;
                    219:                }
                    220:               rt = &Chroute[ifp->my_addr.ch_subnet];
                    221:               rt->rt_type = CHDIRECT;
                    222:               rt->rt_cost = ifp->if_cost;
                    223:               rt->rt_path.ifp = ifp;
                    224:                /* Should we check if this fails? */
                    225:               ifp->arp = arp_enable(ifp->if_dev, ETHERPUP_CHAOSTYPE,
                    226:                              sizeof(chaddr), 0, &ifp->my_addr);
                    227:                bp->type = M_IOCACK;
                    228:               break;
                    229:           case CRIOCOST:
                    230:               ifp->if_cost = *(u_short *)(sp->iocx.xxx);
                    231:               bp->wptr = bp->rptr;
                    232:               bp->type = M_IOCACK;
                    233:               break;
                    234:           case CRIOPRIMARY:
                    235:               primary = ifp;
                    236:               bp->wptr = bp->rptr;
                    237:               bp->type = M_IOCACK;
                    238:               break;
                    239:           default:
                    240:               return 0;   /* Let someone else deal with it */
                    241:      }
                    242: 
                    243:      qreply(q, bp);
                    244:      return 1;
                    245: }
                    246: 
                    247: 
                    248:      /* We've got a packet to send (or receive); send it to the right place */
                    249: 
                    250: chroute_dispatch(q)
                    251:      register struct queue    *q;
                    252: {
                    253:      register struct block    *bp;
                    254:      register struct pkt_header *ph;
                    255:      register struct chroute  *rt;
                    256:      register struct chif     *ifp;
                    257:      register int        len, isdelim;
                    258:      struct ether_out    *ep;
                    259:      chaddr              dest;
                    260: 
                    261:      ph = (struct pkt_header *)q->first->rptr;
                    262:      ifp = (struct chif *)q->ptr;
                    263:      debug(printf("chroute_dispatch: op 0%o len %d\n", ph->ph_op, ph->ph_len));
                    264: 
                    265:      if (q->flag & QREADR && ph->ph_op == RUTOP) {
                    266:           if (block_pullup(q, ph->ph_len + sizeof(*ph)) == 0) {
                    267:               ifp->ist_rej++;
                    268:               flush_packet(q);
                    269:               return;
                    270:           }
                    271:           chroute_rcvrut(q->first->rptr);
                    272:          flush_packet(q);
                    273:          return;
                    274:      }
                    275: 
                    276:      if (primary && (ph->ph_daddr.ch_addr == primary->my_addr.ch_addr
                    277:                       || (q->flag & QREADR && ph->ph_daddr.ch_addr == 0))) {
                    278:           ph->ph_daddr = primary->my_addr;
                    279:           if (ph->ph_len > CHMAXDATA) {
                    280:               ifp->ist_len++;
                    281:               flush_packet(q);
                    282:               return;
                    283:           }
                    284:          len = sizeof(struct pkt_header) + ph->ph_len;
                    285:          while (bp = getq(q)) {
                    286:               if (bp->type == M_DATA) {
                    287:                    if (bp->wptr - bp->rptr > len)
                    288:                         bp->wptr = bp->rptr + len;
                    289:                     len -= bp->wptr - bp->rptr;
                    290:                    if (bp->wptr <= bp->rptr) {
                    291:                         freeb(bp);
                    292:                         continue;
                    293:                    }
                    294:               }
                    295:                debug(print_buf(bp, "rcvd:"));
                    296:                isdelim = (bp->type == M_DELIM);
                    297:               (*primary->rdq->next->qinfo->putp)(primary->rdq->next, bp);
                    298:               if (isdelim)
                    299:                    break;
                    300:           }
                    301:          if (len != 0)
                    302:               ifp->ist_len++;
                    303:           return;
                    304:      }
                    305: 
                    306:      if (q->flag & QREADR) {
                    307:           if (ph->ph_daddr.ch_host == 0) {
                    308:               ifp->ist_rej++;
                    309:               flush_packet(q);
                    310:               return;
                    311:           } else if (++ph->ph_fc == 0) {
                    312:                /* Overforwarded packet */
                    313:               flush_packet(q);
                    314:               return;
                    315:           }
                    316:      }
                    317: 
                    318:      dest = ph->ph_daddr;
                    319:      if (ph->ph_daddr.ch_host == 0)
                    320:           ph->ph_daddr.ch_subnet = 0;
                    321:      if (dest.ch_subnet >= CHNSUBNET
                    322:             || (rt = &Chroute[dest.ch_subnet])->rt_type == CHNOPATH) {
                    323:          flush_packet(q);
                    324:          return;
                    325:      }
                    326: 
                    327:      if (rt->rt_type == CHFIXED || rt->rt_type == CHBRIDGE)
                    328:           dest = rt->rt_path.bridge;
                    329:      ifp = Chroute[dest.ch_subnet].rt_path.ifp;
                    330: 
                    331:      if ((bp = allocb(sizeof(struct ether_out))) == 0) {
                    332:           ifp->ist_abrt++;
                    333:          flush_packet(q);
                    334:          return;
                    335:      }
                    336:      ep = (struct ether_out *)bp->wptr;
                    337:      bp->wptr += sizeof(struct ether_out);
                    338:      ep->type = hfirst_short(ETHERPUP_CHAOSTYPE);
                    339: 
                    340:      if (dest.ch_host == 0) /* If address is 0, broadcast to everyone */
                    341:           arp_broadcast(ep->dhost);
                    342:      else if (arp_getaddr(ifp->arp, &dest, ep->dhost) == -1) {
                    343:           ifp->ist_abrt++;
                    344:           flush_packet(q);
                    345:          return;
                    346:      }
                    347: 
                    348:      do {
                    349:           debug(print_buf(bp, "xmit:"));
                    350:           isdelim = (bp->type == M_DELIM);
                    351:           (*(WR(ifp->rdq)->next->qinfo->putp)) (WR(ifp->rdq)->next, bp);
                    352:           if (isdelim)
                    353:                break;
                    354:      } while (bp = getq(q));
                    355: 
                    356:      ifp->ist_xmit++;
                    357: }
                    358: 
                    359: 
                    360:      /* Handle RUT (Routing) Packets */
                    361: chroute_rcvrut(ph)
                    362:      register struct pkt_header    *ph;
                    363: {
                    364:      register struct rut_data      *rd;
                    365:      register struct chroute       *rt;
                    366:      register int   i;
                    367: 
                    368:      if ((i = ph->ph_saddr.ch_subnet) >= CHNSUBNET) {
                    369:           printf("CHAOS: Bad subnet (%d) in RUT packet\n", i);
                    370:          return;
                    371:      }
                    372:      if (Chroute[i].rt_type != CHDIRECT) {
                    373:           printf("CHAOS: RUT packet from unconnected subnet %d\n", i);
                    374:          return;
                    375:      }
                    376: 
                    377:      debug(printf("chroute_rcvrut(%d)\n", i));
                    378: 
                    379:      rd = (struct rut_data *)((char *)ph + sizeof(struct pkt_header));
                    380:      for (i = ph->ph_len; i > 0; i -= sizeof(struct rut_data), ++rd) {
                    381:           if (rd->rd_subnet >= CHNSUBNET)
                    382:               continue;
                    383:          rt = &Chroute[rd->rd_subnet];
                    384:          switch (rt->rt_type) {
                    385:               case CHBRIDGE:
                    386:                    if (rd->rd_cost > rt->rt_cost)
                    387:                         break;
                    388:               case CHNOPATH:
                    389:                     rt->rt_cost = rd->rd_cost;
                    390:                    rt->rt_type = CHBRIDGE;
                    391:                    rt->rt_path.bridge = ph->ph_saddr;
                    392:                    break;
                    393:                case CHDIRECT:
                    394:               case CHFIXED:
                    395:                    break;
                    396:                default:
                    397:                    printf("CHAOS: Bad entry in routing table, type = %d\n",
                    398:                              rt->rt_type);
                    399:           }
                    400:      }
                    401: }
                    402: 
                    403: 
                    404: #ifdef DEBUG
                    405: 
                    406: print_buf(bp, s)
                    407:      register struct block *bp;
                    408:      register char *s;
                    409: {
                    410:      register u_char *p;
                    411:      register int   i;
                    412: 
                    413:      printf("%s msg type %d len %d", s, bp->type, bp->wptr - bp->rptr);
                    414:      for (i = 0, p = bp->rptr; p < bp->wptr; ++i, ++p) {
                    415:           if ((i & 31) == 0)
                    416:               printf("\n%s", s);
                    417:           printf(" %x", *p);
                    418:      }
                    419:      printf("\n");
                    420: }
                    421: 
                    422: #endif DEBUG

unix.superglobalmegacorp.com

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