Annotation of researchv8dc/sys/chaosld/chrouteld.c, revision 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.