home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / manage / snmp / kip / gw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-17  |  24.8 KB  |  1,024 lines

  1. /*
  2.  *  AppleTalk / Ethernet Gateway.
  3.  *
  4.  *  (c) 1986, Stanford Univ. SUMEX project.
  5.  *  May be used but not sold without permission.
  6.  *
  7.  *  (c) 1986, Kinetics, Inc.
  8.  *  May be used but not sold without permission.
  9.  */
  10.  
  11. char rcsident[] =
  12. "$Header: gw.c,v 4.1 88/11/01 19:49:12 sw0l Locked $";
  13.  
  14. #include "gw.h"
  15. #include "gwctl.h"
  16. #include "fp/pbuf.h"
  17. #include "ab.h"
  18. #include "ether.h"
  19. #include "inet.h"
  20. #include "fp/cmdmacro.h"
  21.  
  22. #include "glob.h"
  23. #include "conf.h"
  24.  
  25. #ifndef KFPSVERSION
  26. # include "kfpsversion.h"
  27. #endif
  28.  
  29. #ifdef SNMP
  30. #include "mib.h"
  31. #include "snmp_vars.h"
  32. #endif
  33.  
  34. /*
  35.  * Main event loop.
  36.  */
  37. main()
  38. {
  39.     register struct pbuf *p;
  40.     short pri;
  41.     struct fp_mem mem;
  42.     extern char begin;    /* first address in RAM */
  43.     extern char edata;    /* last address in initialized data */
  44.     extern char end;    /* last address in this downloaded program */
  45.  
  46.     K_PROMRAM(&pvars); /* get addresses of relevant prom variables */
  47.     data_init(); /* initialize data normally done at compile time */
  48.     pq    = pvars.fpr_bufs->fpb_pq; /* shorthand for queue headers */
  49.     sendq = pvars.fpr_bufs->fpb_sendq;
  50.     bcopy(pvars.fpr_state->fps_unused, (caddr_t)&conf, sizeof conf);
  51.     bcopy(conf.etheraddr, etheraddr, 6);
  52.     asminit();        /* set up ethernet interrupt vector */
  53.  
  54.     /* initialize buffer pool */
  55.     K_INIPROM();
  56.     mem.fpm_count = 0;
  57.     K_GETMEM(&mem);        /* gets address of the top of available mem */
  58.     topram = (int)mem.fpm_memp;
  59.     /* use all the rest of available ram for buffers */
  60.     bufs = (struct pbuf *)((int)(&end) + 2);
  61.     mem.fpm_count = topram - ((int)(bufs)) - 2;
  62.     mem.fpm_memp = (char *)bufs;
  63.     K_CLRMEM(&mem);        /* initialize entire area to all zeroes */
  64.     /* set free list and queue headers to empty */
  65.     *(pvars.fpr_bufs->fpb_pfree) = 0;
  66.     pq->pq_head = 0;
  67.     pq->pq_tail = 0;
  68.     pq->pq_len = 0;
  69.     sendq->pq_head = 0;
  70.     sendq->pq_tail = 0;
  71.     sendq->pq_len = 0;
  72.     K_BUFINIT(&mem);    /* divide the area into buffers */
  73.  
  74.     /* initialize interface structures */
  75.     ifnet = &ifie; ifie.if_next = &ifab; 
  76.     ifab.if_next = &ifet; ifet.if_next = 0;
  77.  
  78. #ifdef notdef
  79.     { short nodenum;
  80.       K_ATINIT(&nodenum);    /* initialize AppleTalk network interface */
  81.       atnode = nodenum;
  82.     }
  83. #else
  84.     atnode = pvars.fpr_state->fps_node;
  85. #endif
  86.     ie_init();    /* initialize Ethernet interface... */
  87.     if (conf.ipaddr == 0 || etheraddr[2] != 0x89)
  88.         panic("bad conf");
  89.  
  90.     ifie.if_addr = conf.ipaddr; /* initialize internet data structures */
  91.     ipnet = ifie.if_addrnet = ipnetpart(ifie.if_addr);
  92.     ifie.if_dnode = (conf.ipaddr & 0xFF);
  93.     ifab.if_dnode = ifab.if_haddr[0] = atnode;
  94.     ifet.if_dnode = 0;    /* no Ethertalk address known yet */
  95. #ifdef notdef
  96.     checksum(&begin, &edata); /* set up RAM memory checksum protection */
  97. #endif
  98.     if (conf.ready == confReady)
  99.         confready(0);    /* finish configuration */
  100.     K_WAIT(20);
  101.     sendf("KFPS(IP) version %s node #%d lives!! - %d buffers", 
  102.         KFPSVERSION, atnode,
  103.           mem.fpm_count/sizeof (struct pbuf));
  104.  
  105.     K_LEDOFF();
  106.     K_SPL0(&pri); /* allow interrupts */
  107.  
  108.     for (;;) {
  109.         if (pq->pq_head == 0) { /* no packets on main queue */
  110.             back();        /* perform background processing */
  111.             continue;
  112.         }
  113.         K_PDEQ(SPLIMP,pq,p);    /* remove buffer from queue */
  114.         if (p->p_len < 0) {    /* if error packet */
  115.             if (p->p_len != -1)
  116.                 goto pan;
  117.             K_PFREE(p); /* put the buffer back on the free list */
  118.             continue;
  119.         }
  120.         switch (p->p_type) {    /* switch on packet type */
  121.         case PT_ABUS:
  122. #ifdef SNMP
  123.             /*
  124.              * Check the ddp source address to see that
  125.              * this wasn't a broadcast ddp from this node.
  126.              */
  127.             if (p->p_off[1] != ifab.if_dnode)
  128.                 mib_ifEntry[1].ifInOctets += p->p_len;
  129. #endif
  130. #ifdef notdef
  131.             p_if(p) = &ifab; /* should be in prom code? */
  132. #endif
  133.             source_if = &ifab;
  134.              abreceive(p);    /* receive AppleTalk packet */
  135.             break;
  136.         case PT_ENET:
  137. #ifdef SNMP
  138.             mib_ifEntry[0].ifInOctets += p->p_len;
  139. #endif SNMP
  140.             source_if = &ifie;
  141.             iereceive(p);    /* receive ethernet packet */
  142.             break;
  143.         default:
  144. pan:
  145. #ifdef    STATS
  146.             K_SPLIMP(&pri);    /* prevent interruptions */
  147.             p_print("main",p);
  148.             dmpbf();
  149.             ieprintstats();
  150.             abprintstats();
  151. #endif    STATS
  152.             panic("main: bad pkt");
  153.         }
  154.     }
  155. }
  156.  
  157.  
  158. /*
  159.  * Complete configuration process.  Called when configuration 'ready'
  160.  * via preset struct conf or aaconf packet received.
  161.  */
  162. confready(aa)
  163.     register struct aaconf *aa;
  164. {
  165.     if (aa) {    /* configure packet received */
  166.         bcopy(aa->stuff, (caddr_t)(&conf) + confPrefix,
  167.             sizeof conf - confPrefix);
  168.         /* will go away after KIP 06/88 */
  169.         /* prevents us from doing bad things */
  170.         if (conf.startddpWKSUnix == 0)
  171.           conf.startddpWKSUnix = defddpWKSUnix;
  172.         conf.ready = confReady;
  173.     }
  174.     if (conf.ipdynamic > NIPDAD)
  175.         conf.ipdynamic = NIPDAD;
  176.     ifab.if_dnet = conf.atneta;
  177.     ifab.if_unit = 0;
  178.     aroute[0].net = conf.atneta;    /* hops=0, node=0, flags=0 */
  179.     aroute[0].port = 0;
  180.     porttoif[0] = &ifab;
  181.     ifie.if_dnet = conf.atnete;
  182.     ifie.if_unit = 1;
  183.     aroute[1].net = conf.atnete;
  184.     aroute[1].node = (conf.ipaddr & ~0xFF);    /* hops=0*/
  185.     aroute[1].flags = arouteNet;
  186.     aroute[1].port = 1;
  187.     porttoif[1] = &ifie;
  188.     if (conf.anetet) {
  189.       ifet.if_dnet = aroute[2].net = conf.anetet;
  190.       ifet.if_unit = 2;
  191.       aroute[2].port = 2; /* node=0, hops=0,flags=0 */
  192.       porttoif[2] = &ifet;
  193.       conf.anetet = 0;    /* some clients expect this to be 0 */
  194.     }
  195. }
  196.  
  197.  
  198. short    confdelay;    /* sigh, should be 'static', but checksum complains */
  199.  
  200. /*
  201.  * Configuration clock routine;  get config from appletalk admin.
  202.  */
  203. conftimer()
  204. {
  205.     if (confdelay && ++confdelay < 10)
  206.         return;
  207.     confdelay = 1;
  208.     confrequest(aaCONF);
  209. }
  210.  
  211.  
  212. /*
  213.  * Request configuration (or net table) from appletalk administrator.
  214.  */
  215. confrequest(op)
  216. {
  217.     register struct aaconf *m;
  218.     register struct udp *u;
  219.     register struct pbuf *p;
  220.  
  221.     K_PGET(PT_DATA, p);
  222.     if (p == 0)
  223.         return;
  224.     p->p_len = sizeof (struct ip) + sizeof *u + aaconfMinSize;
  225.     setiphdr(p, conf.ipadmin);
  226.     u = (struct udp *)(p->p_off + sizeof (struct ip));
  227.     u->src = aaPort;
  228.     u->dst = aaPort;
  229.     u->length = p->p_len - sizeof (struct ip);
  230.     u->checksum = 0;
  231. #ifdef SNMP
  232.     mib_udp.udpOutDatagrams++;
  233. #endif
  234.     m = (struct aaconf *)(u + 1);
  235.     m->magic = aaMagic;
  236.     m->type = op;
  237.     m->ipaddr = conf.ipaddr;
  238.     m->count = 0;
  239.     source_if = 0;
  240.     routeip(p, 0, 0);
  241. }
  242.  
  243.  
  244. int    backclock;    /* 'static' */
  245. /*
  246.  * Backround processing.  Call once per second timeout routines.
  247.  * Call 'backround' routines.
  248.  */
  249. /* The following used for Ethertalk startup */
  250. iaddr_t et_probe;        /* Current address we are trying */
  251. short et_probe_count;        /* number of times we've PROBEd it */
  252. #define ETALK_NPROBE 10        /* Number of times to probe */
  253. /*
  254.  * The Ethertalk spec requires some ungodly number of probes at an
  255.  * unreasonably short interval. In order to protect the ethernet I'm
  256.  * going to try to get away with a smaller number
  257.  */
  258. back()
  259. {
  260.     register i;
  261.  
  262.     nbpback();    /* NBP backround (sends 1 LkUp per loop) */
  263. #ifdef     KINETICS
  264.     msclock++;
  265.     if ((i = msclock - backclock) < 0)
  266.         i = -i;
  267.     if (i > 12000)        /* ~one second */
  268. #else
  269.     if ((i = msclock - backclock) < 0)
  270.         i = -i;
  271.     if (i > 1000)        /*  ~one second */
  272. #endif
  273.       {
  274.         backclock = msclock;
  275.         arptimer();    /* timeout arp cache */
  276.         if (conf.ready != confReady) {
  277.           conftimer();
  278.           return;
  279.         }
  280.  
  281.         /* Ethertalk - keep probing if address not chosen yet */
  282.         if (ifet.if_dnet && ifet.if_dnode == 0) {
  283.           /* Still probing for ethertalk address */
  284.           if (arpresolve(&ifet, (struct pbuf *) 0, &et_probe, (char *)0)) {
  285.         /* This address is known */
  286.         et_probe_count = 0;
  287.         ++((char *)&et_probe)[3];
  288.           } else ++et_probe_count;
  289.  
  290.           if (et_probe_count > ETALK_NPROBE) {
  291.         /* use this node address */
  292.         ifet.if_addr = et_probe;
  293.         ifet.if_dnode = ((char *)&et_probe)[3];
  294.           }
  295.         } /* end test if ETalk address set */
  296.           /* Don't send out RTMP packets until Etalk is set */
  297.         else {
  298.           rtmptimer();    /* routing table maint protocol timer */
  299.         }
  300.         arttimer();        /* arouteTuple timer */
  301.         ipdadtimer();    /* IP dynamic address assignment timer */
  302.         ziptimer();    /* zone info timer */
  303.       }
  304.       }
  305.  
  306.  
  307. /*
  308.  * The functions of the "abreceive" and "ilreceive" routines below might 
  309.  * normally belong in the input interrupt sections of their respective
  310.  * drivers.  But since they do some protocol translation as well, we've
  311.  * stuck them here.  (Another consideration is that the LAP input interrupt
  312.  * code is very time critical).
  313.  */
  314.  
  315. /*
  316.  * Receive next packet from AppleTalk.
  317.  * Forward the packet onto the ethernet leg, possibly encapsulating
  318.  * in a UDP packet first.
  319.  */
  320. abreceive(p)
  321.     register struct pbuf *p;
  322. {
  323.     register wasbroad;
  324.     int temp;
  325.  
  326.     bcopy(p->p_off, (caddr_t)&lap, lapSize);
  327.     wasbroad = (lap.dst == 0xFF);
  328. #ifdef SNMP
  329.     /*
  330.      *  Check the source_if to make sure that this isn't an ethertalk packet
  331.      * off of the ethernet.  Also check the ddp source address to see that
  332.      * this wasn't a broadcast ddp from this node.
  333.      */
  334.     if (source_if == &ifab && p->p_off[1] != ifab.if_dnode)
  335.         if (wasbroad)
  336.         mib_ifEntry[1].ifInNUcastPkts++;
  337.         else
  338.         mib_ifEntry[1].ifInUcastPkts++;
  339. #endif SNMP
  340.     p->p_off += lapSize;
  341.     p->p_len -= lapSize;
  342.     wasddp = 0;    /* assume not a ddp */
  343.     /*
  344.      * Below we copy the DDP header into a global structure to
  345.      * get word alignment.  Since lapSize and ddpSize are both odd,
  346.      * after handling the headers the packet is again on an even
  347.      * boundary (odd+odd=even).
  348.      */
  349.     switch (lap.type) {
  350.     case lapDDPS:
  351.         if ((p->p_len -= ddpSSize) < 0)
  352.             goto drop;
  353.         bcopy(p->p_off, (caddr_t)&ddps, ddpSSize);
  354.         p->p_off += ddpSSize;
  355.         /* reset length in case ethertalk */
  356.         temp = ddps.length - ddpSSize;
  357.         ddp.dstSkt = ddps.dstSkt;
  358.         ddp.type = ddps.type;
  359.         break;
  360.  
  361.     case lapDDP:
  362.         if ((p->p_len -= ddpSize) < 0)
  363.             goto drop;
  364.         bcopy(p->p_off, (caddr_t)&ddp, ddpSize);
  365.         /* 0 network means this_network */
  366.         if (ddp.srcNet == 0)
  367.           ddp.srcNet = source_if->if_dnet;
  368.         if (ddp.dstNet == 0)
  369.           ddp.dstNet = source_if->if_dnet;
  370.         temp = (ddp.length & ddpLengthMask) - ddpSize;
  371.         p->p_off += ddpSize;
  372.         wasddp = 1;
  373.         break;
  374.  
  375.     case 'K':        /* Kinetics protocol type */
  376.         K_KLAP(p);
  377.         K_PFREE(p);
  378.         return;
  379.  
  380.     default:
  381. #ifdef SNMP
  382.         /*
  383.          *  Check the source_if to make sure that this isn't an ethertalk packet
  384.          * off of the ethernet.  Also check the ddp source address to see that
  385.          * this wasn't a broadcast ddp from this node.
  386.          */
  387.         if (source_if == &ifab && p->p_off[1] != ifab.if_dnode)
  388.             mib_ifEntry[1].ifInUnknownProtos++;
  389. #endif
  390.         goto drop;
  391.     }
  392.  
  393.     /* MUST BE ddp at this point */
  394.     /* reset packet length in case ethertalk */
  395.     if (temp < p->p_len)    /* make sure we don't overun buffer */
  396.       p->p_len = temp;
  397.  
  398.     if (conf.ready != confReady)
  399.         goto drop;
  400.  
  401. #ifdef notdef
  402. /* Looks like EtherTalk has made it necessary to assume that */
  403. /* incoming RTMP or ZIP may be LONG DDP */
  404.     /*
  405.      * here we switch out immediately to short-DDP-only
  406.      * handlers, to avoid having to convert them to long DDPs.
  407.      */
  408.     switch (ddp.dstSkt) {
  409.     case 0:
  410.         goto drop;
  411.  
  412.     case rtmpSkt:
  413.         if (lap.src == source_if->if_dnode)
  414.             goto drop;    /* from ourself */
  415.         rtmpinput(p);
  416.         return;
  417.  
  418.     case zipSkt:
  419.         if (lap.src == source_if->if_dnode)
  420.             goto drop;    /* from ourself */
  421.         zipinput(p);
  422.         return;
  423.     }
  424. #endif
  425.     if (ddp.type == ddpIP) {
  426. #ifdef SNMP
  427.         mib_ip.ipInReceives++;
  428. #endif
  429.         routeip(p, source_if, wasbroad);
  430.         return;
  431.     }
  432.     /* not magic type, just route as a ddp */
  433.     if (wasddp == 0)
  434.         ddps2ddp(p);
  435. route:
  436.     p->p_off -= lapSize + ddpSize;
  437.     p->p_len += lapSize + ddpSize;
  438.     routeddp(p, source_if, wasbroad);
  439.     return;
  440.  
  441. drop:
  442.     /* put the buffer back on the free list */
  443.     K_PFREE(p);
  444.     stats.dropabin++;
  445.     return;
  446. }
  447.  
  448.  
  449. /*
  450.  * Convert packet from short DDP form to long DDP form.
  451.  */
  452. ddps2ddp(p)
  453.     register struct pbuf *p;
  454. {
  455.     if (wasddp)
  456.         return;
  457.     ddp.length = ddps.length - ddpSSize + ddpSize;
  458.     ddp.checksum = 0;
  459.     ddp.dstNet = ddp.srcNet = source_if->if_dnet;
  460.     ddp.srcNode = lap.src;
  461.     ddp.dstNode = lap.dst;
  462.     ddp.srcSkt = ddps.srcSkt;
  463.     ddp.dstSkt = ddps.dstSkt;
  464.     ddp.type = ddps.type;
  465.     bcopy((caddr_t)&ddp, p->p_off - ddpSize, ddpSize);
  466.     wasddp = 1;
  467. }
  468.  
  469.  
  470. /*
  471.  * Receive next packet from intel ethernet.
  472.  */
  473. iereceive(p)
  474. register struct pbuf *p;
  475. {
  476.     struct ether_header *ehp;
  477.     register struct ip *ip;
  478.     register struct udp *up;
  479.     register int l;
  480.     int wasbroad;
  481.  
  482. #ifdef    EDATA
  483.     K_WAIT(20);
  484.     p_print("ierecv", p);
  485. #endif    EDATA
  486.     ehp = (struct ether_header *)p->p_off;
  487.     wasbroad = (ehp->ether_dhost.ether_addr_octet[0] & 0x1);
  488. #ifdef SNMP
  489.     if (wasbroad)
  490.         mib_ifEntry[0].ifInNUcastPkts++;
  491.     else
  492.         mib_ifEntry[0].ifInUcastPkts++;
  493. #endif SNMP
  494.     p->p_off += sizeof *ehp;
  495.     p->p_len -= sizeof *ehp;
  496.     switch (ntohs(ehp->ether_type)) {
  497.         case ETHERTYPE_ETHERTALK:
  498.             if (ifet.if_dnet == 0){
  499.           goto drop; /* ignore unless enabled */
  500.         }
  501.             source_if = &ifet; /* switch virtual interfaces */
  502.             abreceive(p);
  503.         return;
  504.  
  505.         case ETHERTYPE_AARPTYPE:
  506.         source_if = &ifet;
  507.         /* fall through */
  508.         case ETHERTYPE_ARPTYPE:
  509.         arpinput(p);    /* pass it to ARP */
  510.         return;
  511.         case ETHERTYPE_IPTYPE:
  512. #ifdef SNMP
  513.         mib_ip.ipInReceives++;
  514. #endif
  515.         break;
  516.         default:
  517. #ifdef SNMP
  518.         mib_ifEntry[0].ifInUnknownProtos++;
  519. #endif
  520.         goto drop;        /* can't handle it */
  521.     }
  522.  
  523.     /*
  524.      *  If the proto type is IP/UDP and the port
  525.      *  number is in the magic range, remove the
  526.      *  encapsulation from the DDP datagram.
  527.      */
  528.     ip = (struct ip *)p->p_off;
  529.     /* Checksum the IP header ? */
  530.     if (p->p_len < sizeof (*ip)){
  531. #ifdef SNMP
  532.         mib_ip.ipInHdrErrors++;
  533. #endif
  534.         goto drop;
  535.     }
  536.     if (conf.ready != confReady) {
  537.         /* if conf not ready, only process control packets */
  538.         if (ip->ip_dst != conf.ipaddr)
  539.             goto drop;
  540.         ip4me(p);
  541.         return;
  542.     }
  543.     if (ip->ip_p != IPPROTO_UDP || ip->ip_dst != conf.ipaddr)
  544.         goto toip;
  545.     l = (ip->ip_hl << 2);
  546.     up = (struct udp *)(p->p_off + l);
  547.     if (p->p_len < (l + sizeof(*up))){
  548. #ifdef SNMP
  549.         mib_udp.udpInErrors++;
  550. #endif
  551.         goto drop;
  552.     }
  553.     if ((up->dst >= ddpNWKSUnix + 128 && up->dst < ddpNWKSUnix + 256)
  554.         || (up->dst >= ddpWKSUnix && up->dst < ddpWKSUnix + 128)) {
  555.         /* decapsulate */
  556. #ifdef SNMP
  557.         mib_udp.udpInDatagrams++;
  558. #endif
  559.         p->p_off += (l + sizeof(*up));
  560.         p->p_len -= (l + sizeof(*up));
  561.         /* route as ddp */
  562.         if (p->p_len < ddpSize + lapSize)
  563.             goto drop;
  564.         bcopy(p->p_off + lapSize, (caddr_t)&ddp, ddpSize);
  565.         l = (ddp.length & ddpLengthMask);
  566.         if (l < p->p_len - lapSize)
  567.             p->p_len = l + lapSize; /* zap padding */
  568.         wasddp = 1;
  569.         routeddp(p, source_if, wasbroad);
  570.         return;
  571.     }
  572. toip:
  573.     routeip(p, source_if, wasbroad);
  574.     return;
  575. drop:
  576. /*    sendf("Got bad IP packet"); */
  577.     stats.dropiein++;
  578.     /* put the buffer back on the free list */
  579.     K_PFREE(p);
  580.     return;
  581. }
  582.  
  583. /*
  584.  * These match routines return 0 if no match and 1 (true) if a match occurs.
  585.  * They are called from arpinput/nbpinput to determine if an IP
  586.  * address is in our range.
  587.  *
  588.  * A 'true' return value causes the arpinput code to return a 'fake ARP'
  589.  * to the requester:  i.e. the requester will think that the real destination
  590.  * host responded to the ARP, whereas it was really this gateway 'faking'
  591.  * a response.
  592.  */
  593.  
  594. /*
  595.  * Match an AppleTalk ARP.  If the target is not in my own
  596.  * range, return true (match).  This has the effect of forwarding all
  597.  * traffic for 'unknown' nets, to the backbone ethernet.
  598.  */
  599. abmatch(target)
  600.     iaddr_t target;
  601. {
  602.     register i;
  603.  
  604.     if (target == conf.ipaddr)
  605.         return (1);
  606.     if (ipnetpart(target) == 0x7F000000)
  607.         return (0);
  608.     if (conf.ready != confReady)
  609.         return (0);
  610.     i = target - conf.ipaddr;
  611.     if (i < 0)
  612.         return (1);
  613.     if (i >= conf.ipstatic + conf.ipdynamic + 1)
  614.         return (1);
  615.     return (0);
  616. }
  617.  
  618. /*
  619.  * Match an ethernet ARP.
  620.  */
  621. iematch(target)
  622.     iaddr_t target;
  623. {
  624.     register i;
  625.  
  626.     i = target - conf.ipaddr;
  627.     if (i == 0)
  628.         return (1);
  629.     if (conf.ready != confReady)
  630.         return (0);
  631.     if (i >= 0 && i <= conf.ipstatic + conf.ipdynamic)
  632.         return (1);
  633.     return (0);
  634. }
  635.  
  636.  
  637. /*
  638.  * Route an IP packet.  This code currently assumes only one AppleTalk and
  639.  * ether interface per gateway;  instead it should scan a list of interfaces.
  640.  * If a routing table existed within the gateway, it would determine
  641.  * which interface pointer (ifp) and destination address (dst below)
  642.  * are passed to ifp->if_output.
  643.  */
  644. routeip(p, srcif, br)
  645.      register struct pbuf *p;
  646.      struct ifnet *srcif;    /* interface packet came in on */
  647. {
  648.     register struct ifnet *ifp = &ifie;    /* default output to ether */
  649.     register struct ip *ip = (struct ip *)p->p_off;
  650.     int dst = ip->ip_dst;
  651.     register iaddr_t dstnet = ipnetpart(dst);
  652.  
  653.     /* omit any bytes past the ip data */
  654.     if (p->p_len > ip->ip_len) {
  655.         p->p_len -= (p->p_len - ip->ip_len);
  656.     }
  657.     if (dst == conf.ipaddr) {
  658.         ip4me(p);
  659.         return;
  660.     }
  661. #ifdef SNMP
  662.     /* if not from me, I must be forwarding this */
  663.     if (ip->ip_src == conf.ipaddr)
  664.         mib_ip.ipOutRequests++;
  665.     else
  666.         mib_ip.ipForwDatagrams++;
  667. #endif
  668.     if (iematch(dst))
  669.         ifp = &ifab;
  670.     else if (dstnet != ifie.if_addrnet
  671.         || (ipbroadcast(dst) && dst != conf.ipbroad))
  672.         dst = conf.iproutedef;    /* needs to be forwarded */
  673.     if (ifp != srcif) /* do not reflect packets to same net */
  674.         return((*ifp->if_output)(ifp, p, AF_IP, &dst));
  675. drop:
  676.     K_PFREE(p);
  677.     stats.droprouteip++;
  678.     return;
  679. }
  680.  
  681.  
  682. /* IP directed broadcast types, used by 'routeddp' */
  683. iaddr_t ipbroadtypes[] = { 0, 0xFF, 0xFFFF, 0xFFFFFF };
  684.  
  685.  
  686. /*
  687.  * Route a DDP packet.  Assumes ddp has already been unpacked into
  688.  * global struct ddp.  If 'si' (source interface) is 0, packet
  689.  * originates inside the gateway;  otherwise this is a forward.
  690.  * 'br' is true if the packet was received as a broadcast.
  691.  */
  692. routeddp(p, si, br)
  693.     register struct pbuf *p;
  694.     struct ifnet *si;
  695.     int br;
  696. {
  697.     register struct udp *u;
  698.     register struct aroute *ar;
  699.     iaddr_t idst;
  700.     struct ifnet *ifp;
  701.     int wasbroadcast;
  702.     register i, port;
  703.     u_char dst;
  704.  
  705.     if (ddp.dstNet == 0 || ddp.dstNode == 0)
  706.         goto drop;
  707.     if (p->p_len < (ddpSize + lapSize))
  708.         goto drop;
  709.     wasbroadcast = br && ddp.dstNode == 0xff; /* really broadcast? */
  710.     if (si && ddp.dstNet == si->if_dnet &&
  711.         (ddp.dstNode == si->if_dnode || wasbroadcast)) {
  712.       ddp4me(p);
  713.       return;
  714.     }
  715.     for (ar = &aroute[0] ; ar < &aroute[NAROUTE] ; ar++) {
  716.         if (ar->net == 0)    /* empty slot */
  717.             continue;
  718.         if (ar->net == ddp.dstNet && ar->port < MAX_PORT) {
  719.           if ((ifp = porttoif[ar->port]) == 0) /* nothing defined */
  720.             continue;
  721.           goto found;
  722.         }
  723.     }
  724.     goto drop;    /* didnt find it */
  725. found:
  726.     /*
  727.      * if this packet originates externally and is addressed
  728.      * to us (or broadcast), hand it to 'ddp4me'.
  729.      */
  730.     if (ar->hops)    /* if not one of our interfaces */
  731.         goto fwd;
  732.  
  733.     /* net already matched, just check node */
  734.     if (wasbroadcast || ifp->if_dnode == ddp.dstNode) {
  735.       ddp4me(p);
  736.       return;
  737.     }
  738. fwd:
  739.     if (((ddp.length >> ddpHopShift) & 0xF) == 0xF)
  740.         goto drop;
  741.     if (si)            /* if not internally sent */
  742.       p->p_off[lapSize] += 4; /* increment hop count in pbuf */
  743. fwd2:
  744.     if (br)
  745.         goto drop;    /* dont forward broadcasts */
  746.     if (ddp.type == ddpNBP && ddp.dstSkt != nbpNIS) /* NBP reply filter */
  747.         if (nbpfilter(p))
  748.             goto drop;
  749.  
  750.     if (ifp->if_flags & IF_APPLETYPE) {
  751.       /* your basic "LAP" or "ELAP" output routine */
  752.       i = AF_DDP;        /* assume long ddp */
  753.       /* should collapse to short ddp if we can here (internal only) */
  754.  
  755.       /* short ddp allowed on interface? (and internal?) */
  756.       if (!si && (ifp->if_flags & IF_ALAP))
  757.         if (ar->hops == 0 && ddp.srcNet == ddp.dstNet) {
  758.           /* primary interface and input/output net the same */
  759.  
  760.           /* move ahead to ddp short boundary */
  761.           p->p_off += (ddpSize - ddpSSize);
  762.           p->p_len -= (ddpSize - ddpSSize);
  763.           ddps.srcSkt = ddp.srcSkt;
  764.           ddps.dstSkt = ddp.dstSkt;
  765.           ddps.type = ddp.type;
  766.           ddps.length = ddp.length - (ddpSize - ddpSSize);
  767.           bcopy((caddr_t)&ddps, p->p_off+lapSize, ddpSSize);
  768.           i = AF_SDDP;
  769.         }
  770.       dst = (ar->hops ? ar->node : ddp.dstNode);
  771.       (*ifp->if_output)(ifp, p, i, &dst);
  772.       return;
  773.     }
  774. /*
  775.   paranoia 
  776.     if ((ifp->if_flags & IF_IPUDP) == 0)
  777.       goto drop;
  778. */
  779.     /*
  780.      * Else destination is IP address, encapsulate.
  781.      * Choose the appropriate IP host or directed broadcast address.
  782.      */
  783.     port = ddp2ipskt(ddp.dstSkt);
  784.     switch ((i=ar->flags & arouteTYPE)) {
  785.     default:
  786.       goto drop;
  787.     case arouteKbox:
  788.       idst = ar->node;
  789.       break;
  790.     case arouteNet:
  791.     case arouteHost:
  792.       if (ddp.dstNode != 0xFF) { /* not broadcast? */
  793.         idst = (ar->node & ~0xFF) + ddp.dstNode; /* nope */
  794.         break;
  795.       }
  796.       if (i == arouteNet) {
  797.         /* problematic sometimes : also conf.ipbroad should be set on */
  798.         /* ifp */
  799.         idst = (ddp.dstNet == ifp->if_dnet) ? conf.ipbroad :
  800.           ar->node + ipbroadtypes[ar->flags&arouteBMask];
  801.       } else {
  802.         idst = ar->node;
  803.         port = rebPort;
  804.       }
  805.       break;
  806.     }
  807.     lap.dst = 0xFA;
  808.     lap.src = 0xCE;
  809.     lap.type = lapDDP;
  810.     bcopy((caddr_t)&lap, p->p_off, lapSize);
  811.     p->p_off -= sizeof (struct ip) + sizeof *u;
  812.     p->p_len += sizeof (struct ip) + sizeof *u;
  813.     setiphdr(p, idst);
  814.     u = (struct udp *)(p->p_off + sizeof (struct ip));
  815.     u->src = ddp2ipskt(ddp.srcSkt);
  816.     u->dst = port;
  817.     u->length = p->p_len - sizeof (struct ip);
  818.     u->checksum = 0;
  819. #ifdef SNMP
  820.     mib_udp.udpOutDatagrams++;
  821. #endif
  822.     routeip(p, 0, 0);
  823.     return;
  824. drop:
  825.     /*
  826.     K_WAIT(20);
  827.     sendf("routeddp: dropping packet");
  828.     */
  829.     stats.droprouteddp++;
  830.     /* put the buffer back on the free list */
  831.     K_PFREE(p);
  832. }
  833.  
  834.  
  835. /*
  836.  * AppleTalk output routine.
  837.  * Encapsulate a packet of type af for the local net.
  838.  * 
  839.  * Look at a normal net output routine (such as ethernet output, iloutput),
  840.  * for the more general case of an output routine which can handle 
  841.  * multiple units (using the ifp->if_unit field) with interrupt driven
  842.  * output (and output queues).
  843.  *
  844.  * Also, normally an output routine prepends only the link 
  845.  * level header (e.g. LAP).  However this routine is a bit unusual:
  846.  *
  847.  *   Since the LAP and DDP header sizes are both odd, DDP packets are
  848.  *   usually passed about with both headers on the front, so that the
  849.  *   data will always be on an even boundary.
  850.  *
  851.  *   Since IPs are inside DDPs, we prefix a LAP/DDP header onto them.
  852.  */
  853. aboutput(ifp, p, af, dst)
  854.     register struct ifnet *ifp;
  855.     register struct pbuf *p;
  856.     caddr_t dst;
  857. {
  858.     iaddr_t idst;
  859.     AddrBlock tdst;
  860.     struct LAP l;
  861.     struct DDP d;
  862.     WDS wds[2];        /* write data structure for abuswrite */
  863.  
  864.     l.src = ifp->if_dnode;    /* (also done as part of atwrite) */
  865.     switch (af) {
  866.  
  867.     case AF_DDP:    /* DDP: already has LAP header */
  868.         l.dst = *dst;
  869.         l.type = lapDDP;
  870.         bcopy((caddr_t)&l, p->p_off, lapSize);
  871.         break;
  872.         
  873.     case AF_SDDP:    /* ShortDDP: already has LAP header */
  874.         l.dst = *dst;
  875.         l.type = lapDDPS;
  876.         bcopy((caddr_t)&l, p->p_off, lapSize);
  877.         break;
  878.  
  879.     case AF_IP:
  880.         idst = *(iaddr_t *)dst;
  881.         if (!arpresolve(ifp, p, &idst, &tdst))
  882.             return (0);    /* if not yet resolved */
  883.     lapddp:
  884.         l.type = lapDDP;
  885.         d.length = p->p_len + ddpSize;
  886.         d.checksum = 0;
  887.         d.srcNet = ifp->if_dnet;
  888.         d.dstNet = tdst.net;
  889.         d.srcNode = ifp->if_dnode;
  890.         d.dstNode = tdst.node;
  891.         d.srcSkt = d.dstSkt = ddpIPSkt;
  892.         d.type = ddpIP;
  893.         if (tdst.net == ifp->if_dnet)
  894.             l.dst = tdst.node;
  895.         else if ((l.dst = getaroute(tdst.net)) == 0)
  896.             goto drop;
  897.         p->p_off -= (lapSize + ddpSize);
  898.         p->p_len += (lapSize + ddpSize);
  899.         bcopy((caddr_t)&l, p->p_off, lapSize);
  900.         bcopy((caddr_t)&d, p->p_off+lapSize, ddpSize);
  901.         break;
  902.  
  903.     default:
  904. #ifdef SNMP
  905.         /* in case panic calls snmp_trap() */
  906.         mib_ifEntry[0].ifOutErrors++;
  907. #endif
  908.         panic("ab%d: can't handle af%d\n", ifp->if_unit, af);
  909.     }
  910.  
  911.     wds[1].size = 0;    /* terminate list */
  912.     wds[0].size = p->p_len;
  913.     wds[0].ptr = p->p_off;
  914. #ifdef SNMP
  915.     mib_ifEntry[1].ifOutOctets += p->p_len;
  916. #endif
  917.     K_ATWRITE(&wds[0]);    /* appletalk write */
  918.     if (l.dst == 0xFF) {    /* if was broadcast, give myself a copy */
  919. #ifdef SNMP
  920.         mib_ifEntry[1].ifOutNUcastPkts++;
  921. #endif
  922.         p->p_type = PT_ABUS;
  923.         /* oops, atwrite smashes src during xmit(?) */
  924.         p->p_off[1] = ifp->if_dnode;
  925.         K_PENQ(SPLIMP, pq, p);
  926.         return;
  927. #ifdef SNMP
  928.     } else {
  929.         mib_ifEntry[1].ifOutUcastPkts++;
  930. #endif
  931.     }
  932. drop:
  933.     /* put the buffer back on the free list */
  934.     K_PFREE(p);
  935.     return;
  936. }
  937.  
  938. /*
  939.  * Panic - fatal error
  940.  */
  941. /*VARARGS*/
  942. panic(s,a,b,c)
  943. {
  944.     short pri;
  945.  
  946.     K_SPLIMP(&pri);
  947.     sendf("PANIC!");
  948.     sendf(s,a,b,c);
  949. #ifdef    STATS
  950.     ieprintstats();
  951.     abprintstats();
  952. #endif    STATS
  953.     K_ERR();
  954.     K_INIPROM();
  955.     K_RESET();
  956. }
  957.  
  958. #ifdef    STATS
  959. /*
  960.  * Send AppleTalk statistics
  961.  */
  962. abprintstats()
  963. {
  964.     register struct fp_abstats *ss;
  965.  
  966.     ss = pvars.fpr_abstats;
  967.     K_WAIT(20);
  968.     sendf("appletalk stats: ints %d, in %d, out %d, crc %d, ovr %d",
  969.         ss->fpa_interrupts, ss->fpa_ipackets, ss->fpa_opackets,
  970.         ss->fpa_crc, ss->fpa_ovr);
  971.     K_WAIT(20);
  972.     sendf("iund %d, bad %d, coll %d", ss->fpa_iund, ss->fpa_bad,
  973.         ss->fpa_coll);
  974.     K_WAIT(20);
  975.     sendf("defer %d, idleto %d, nodata %d, ound %d, badddp %d, spur %d",
  976.         ss->fpa_defer, ss->fpa_idleto, ss->fpa_nodata, ss->fpa_ound,
  977.         ss->fpa_badddp, ss->fpa_spur);
  978. }
  979.  
  980. dmpbf()
  981. {
  982.     struct pbuf *qq;
  983.     int flag;
  984.     register struct fp_bufinfo *ss;
  985.  
  986.     ss = pvars.fpr_bufs;
  987.     sendf("dump pbufs - pbndrops = %d",ss->fpb_pbndrops);
  988.     sendf("pfree: 0x%x", *(ss->fpb_pfree));
  989.     sendf("   pq: head = 0x%x, tail= 0x%x, len = %d", pq->pq_head,
  990.                         pq->pq_tail, pq->pq_len);
  991.     sendf("sendq: head = 0x%x, tail= 0x%x, len = %d",sendq->pq_head,
  992.                         sendq->pq_tail, sendq->pq_len);
  993.     for (flag = 0, qq = bufs;
  994.             qq < (struct pbuf *)(topram - ss->fpb_bsize + 1);
  995.             qq++, flag++) {
  996.         sendf("%d=0x%x: %d 0x%x",flag,qq,qq->p_type,qq->p_next);
  997.     }
  998. }
  999.  
  1000. p_print(s, p)
  1001. char *s;
  1002. register struct pbuf *p;
  1003. {
  1004.     register u_char *cp = p->p_off;
  1005.     register ii,jj;
  1006.     char ll[256];
  1007.     char *lp;
  1008.     extern char tohex[];
  1009.  
  1010.     sendf("(%s) addr 0x%x p_type %d, p_len %d, p_off 0x%x\n",
  1011.         s, p, p->p_type, p->p_len, p->p_off);
  1012.     ii = p->p_len > 64 ? 64 : p->p_len;
  1013.     lp = ll;
  1014.     for (jj = 0 ; jj < ii ; jj++) {
  1015.         *lp++ = tohex[(*cp >> 4) & 0xF];
  1016.         *lp++ = tohex[*cp++ & 0xF];
  1017.         *lp++ = ' ';
  1018.     }
  1019.     *lp = '\0';
  1020.     sendf(ll);
  1021. }
  1022. #endif    STATS
  1023.  
  1024.