home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msvp98b1.lzh / MSNARP.C < prev    next >
Text File  |  1993-05-14  |  13KB  |  477 lines

  1. /* File MSNARP.C
  2.  * ARP and RARP packet processor
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1985, 1992, Trustees of Columbia University in the 
  6.  * City of New York.  Permission is granted to any individual or institution
  7.  * to use this software as long as it is not sold for profit.  This copyright
  8.  * notice must be retained.  This software may not be included in commercial
  9.  * products without written permission of Columbia University.
  10.  *
  11.  * Original version created by Erick Engelke of the University of
  12.  *  Waterloo, Waterloo, Ontario, Canada.
  13.  * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik, 
  14.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  15.  *
  16.  * Last edit
  17.  * 2 June 1992
  18.  *
  19.  * Address Resolution Protocol
  20.  *
  21.  *  Externals:
  22.  *  ap_handler(pb) - returns 1 on handled correctly, 0 on problems
  23.  *  arp_resolve - rets 1 on success, 0 on fail
  24.  *               - does not return hardware address if passed NULL for buffer
  25.  *
  26.  */
  27. #include "msntcp.h"
  28. #include "msnlib.h"
  29.  
  30. #ifdef KERMIT
  31. #define MAX_ARP_DATA 10
  32. #else
  33. #define MAX_ARP_DATA 40
  34. #endif    /* KERMIT */
  35.  
  36. #define NEW_EXPIRY
  37. #define MAX_ARP_ALIVE  300        /* five minutes */
  38. #define MAX_ARP_GRACE  100        /* additional grace upon expiration */
  39. #define PLEN    4            /* bytes in an IP address longword */
  40.  
  41. eth_address eth_none = { 0,0,0 };
  42.  
  43. /* ARP and RARP header. Note that address lengths and hardware type ident
  44.    vary depending on frame type at the hardware level. The frame handler
  45.    (Packet Driver or ODI driver) will set these values. */
  46.  
  47. typedef    struct {
  48.     word    hwType;            /* hardware type ident */
  49.     word    protType;        /* protocol ident */
  50.     byte    hlen;            /* length of MAC hardware address */
  51.     byte    plen;            /* plen, length of protocol address */
  52.     word    opcode;
  53.     byte    addr[6+6+2*PLEN];    /* address fields, frame dependent */
  54. } arp_header;
  55.  
  56. typedef struct
  57.     {
  58.     longword    ip;
  59.     eth_address    hardware;
  60.     byte        flags;
  61.     byte        bits;        /* bits in network */
  62.     longword    expiry;
  63.     } arp_tables;
  64.  
  65. typedef struct
  66.     {
  67.     longword    gate_ip;
  68.     longword    subnet;
  69.     longword    mask;
  70.     } gate_tables;
  71.  
  72. #define ARP_FLAG_NEED    0
  73. #define ARP_FLAG_FOUND  1
  74. #define ARP_FLAG_FIXED  255        /* cannot be removed */
  75. extern longword ipbcast;        /* IP broadcast address */
  76. /* MAC_len and arp_hardware can be set by the packet frame routines */
  77. word MAC_len = 6;            /* bytes in MAC level hardware addr */
  78. word arp_hardware = 0x0100;        /* ARP, hardware kind ident */
  79. /*
  80.  * arp resolution cache - we zero fill it to save an initialization routine
  81.  */
  82.  
  83. static arp_tables arp_data[MAX_ARP_DATA];
  84. gate_tables arp_gate_data[MAX_GATE_DATA];
  85. word arp_last_gateway = 0;
  86. static word arp_index = 0;        /* rotates round-robin */
  87.  
  88. void
  89. arp_init()        /* init to zero ARP and arp_gateway tables */
  90. {
  91.     static first_time = 0;
  92.  
  93.     if (first_time == 0)
  94.         {
  95.         memset((byte *)arp_data, 0, sizeof(arp_tables) * MAX_ARP_DATA);
  96.         memset((byte *)arp_gate_data, 0, 
  97.                 sizeof(gate_tables) * MAX_GATE_DATA);
  98.         }
  99.     arp_last_gateway = 0;        /* reset the gateway table */
  100.     first_time = 1;            /* to keep arp_tables on hot start */
  101. }
  102.  
  103. /*
  104.  * arp_add_gateway - if data is NULL, don't use string
  105.  */
  106. void 
  107. arp_add_gateway(byte *data, longword ip)
  108. {
  109.     int i;
  110.     register byte *subnetp, *maskp;
  111.     longword subnet, mask;
  112.  
  113.     if ((data == NULL) && (ip == 0L)) return;     /* nothing to do */
  114.     subnet = mask = 0;
  115.     if (data != NULL)
  116.         {
  117.         maskp = NULL;
  118.         if ((subnetp = strchr(data, ',')) != NULL)
  119.             {
  120.             *subnetp++ = 0;
  121.             if (maskp = strchr(subnetp, ','))
  122.                 {
  123.                 *maskp++ = 0;
  124.                 mask = aton(maskp);
  125.                 subnet = aton(subnetp);
  126.                 }
  127.             else
  128.                 {
  129.                 subnet = aton(subnetp);
  130.                 switch (i = (subnet >> 30) & 0x000f)
  131.                     {
  132.                     case 0:
  133.                         case 1: mask = 0xff000000L; break;
  134.                     case 2: mask = 0xfffffe00L; break;
  135.                     case 3: mask = 0xffffff00L; break;
  136.                     }
  137.                 }
  138.             }
  139.             }
  140.  
  141.     if (arp_last_gateway >= MAX_GATE_DATA) return;
  142.  
  143.     for (i = 0; i < arp_last_gateway; i++)
  144.         if (arp_gate_data[i].mask < mask)
  145.             {
  146.             bcopy(&arp_gate_data[i], &arp_gate_data[i+1],
  147.                 (arp_last_gateway - i) * sizeof(gate_tables));
  148.             break;
  149.             }
  150.  
  151.     if ((data != NULL) && (ip == 0L))    /* if text form given */
  152.         ip = aton(data);        /* convert to 32 bit long */
  153.  
  154.     arp_gate_data[i].gate_ip = ip;
  155.     arp_gate_data[i].subnet = subnet;
  156.     arp_gate_data[i].mask = mask;
  157.     arp_last_gateway++;            /* used up another one */
  158. }
  159.  
  160. longword
  161. arp_rpt_gateway(int i)            /* report IP of gateway i */
  162. {
  163.     if (i >= 0 && i < MAX_GATE_DATA)
  164.         return (arp_gate_data[i].gate_ip);
  165.     else    return (0L);
  166. }
  167.  
  168. static void 
  169. arp_request(longword ip)
  170. {
  171.     register arp_header *op;
  172.     longword temp;
  173.  
  174.     op = (arp_header *)eth_formatpacket(ð_brdcast[0], 0x0608);
  175.     op->hwType = arp_hardware;            /* hardware frame */
  176.     op->protType = 0x0008;                /* IP protocol */
  177.     op->hlen = MAC_len;                /* MAC address len */
  178.     op->plen = PLEN;                /* IP address len */
  179.     op->opcode = ARP_REQUEST;
  180.     bcopy(eth_addr, op->addr, MAC_len);    /* our MAC address */
  181.     temp = htonl(my_ip_addr);
  182.     bcopy(&temp, &op->addr[MAC_len], PLEN);    /* our IP */
  183.     temp = htonl(ip);
  184.     bcopy(&temp, &op->addr[2*MAC_len+PLEN], PLEN);    /* host IP */
  185.     if (ip == my_ip_addr)
  186.         return;
  187.     eth_send(8+2*MAC_len+2*PLEN);            /* send the packet */
  188. }
  189.  
  190. static arp_tables *
  191. arp_search(longword ip, int create)
  192. {
  193.     register int i;
  194.     register arp_tables *arp_ptr;
  195.  
  196.     for (i = 0; i < MAX_ARP_DATA; i++)
  197.         if (ip == arp_data[i].ip)
  198.                 return(&arp_data[i]);
  199.                         /* didn't find any */
  200.     if (create != 0)
  201.         {            /* pick an old or empty one */
  202.         for (i = 0; i < MAX_ARP_DATA; i++)
  203.             {
  204.             arp_ptr = &arp_data[i];
  205.             if ((arp_ptr->ip == 0L) ||
  206.                     chk_timeout(arp_ptr->expiry + MAX_ARP_GRACE))
  207.             return(arp_ptr);
  208.             }
  209.                     /* pick one at pseudo-random */
  210.         return (&arp_data[arp_index =
  211.                 (arp_index + 1) % MAX_ARP_DATA]);
  212.         }
  213.     return (NULL);
  214. }
  215.  
  216. void 
  217. arp_register(longword use, longword instead_of)
  218. {    /* new IP to use   instead of this IP */
  219.     register arp_tables *arp_ptr;
  220.  
  221.     if (arp_ptr = arp_search(instead_of, 0)) /* if in ARP cache */
  222.         {        /* insert Ethernet address of new IP */
  223.         arp_resolve(use, arp_ptr->hardware);
  224.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  225.         return;
  226.         }
  227.     arp_ptr = arp_search(use, 1);    /* create a new one */
  228.     arp_ptr->flags = ARP_FLAG_NEED;
  229.     arp_ptr->ip = instead_of;
  230.     arp_resolve(use, arp_ptr->hardware);
  231.     arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  232. }
  233.  
  234. void
  235. arp_tick(longword ip)
  236. {
  237.     register arp_tables *arp_ptr;
  238.  
  239.     if (arp_ptr = arp_search(ip, 0))
  240.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  241. }
  242.  
  243. /*
  244.  * arp_handler - handle incomming ARP packets
  245.  */
  246. int
  247. arp_handler(arp_header *in)
  248. {
  249.     register arp_header *op;
  250.     longword his_ip, temp;
  251.     register arp_tables *arp_ptr;
  252.     int i;
  253.  
  254.     if (in == NULL) return (0);            /* failure */
  255.  
  256.     if (in->protType != 0x0008)        /* IP protocol */
  257.         return(0);            /* 0 means no, fail */
  258.  
  259.     /* continuously accept data - but only for people we talk to */
  260.     bcopy(&in->addr[MAC_len], &his_ip, PLEN);
  261.     his_ip = ntohl(his_ip);
  262.  
  263.     if ((arp_ptr = arp_search(his_ip, 0)) != NULL)/* do not create entry */
  264.         {
  265.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  266.         bcopy(in->addr, arp_ptr->hardware, MAC_len);
  267.         arp_ptr->flags = ARP_FLAG_FOUND;
  268.         }
  269.  
  270.             /* does someone else want our hardware address? */
  271.     bcopy(&in->addr[2*MAC_len+PLEN], &temp, PLEN);
  272.     if (in->opcode == ARP_REQUEST &&        /* and be a resolution req */
  273.             temp ==    htonl(my_ip_addr))    /* for my IP */
  274.         {
  275.         op = (arp_header *)eth_formatpacket(in->addr, 0x0608);
  276.         op->hwType = arp_hardware;
  277.         op->protType = 0x0008;            /* IP protocol */
  278.         op->hlen = MAC_len;             /* MAC address len */
  279.         op->plen = PLEN;            /* IP address len */
  280.         op->opcode = ARP_REPLY;
  281.                         /* host's MAC and IP address */
  282.         bcopy(in->addr, &op->addr[MAC_len+PLEN], MAC_len + PLEN);
  283.         bcopy(eth_addr, op->addr, MAC_len); /* our MAC addr */
  284.         temp = htonl(my_ip_addr);    /* our IP in net order */
  285.         bcopy(&temp, &op->addr[MAC_len], PLEN);
  286.         return(eth_send(8+2*MAC_len+2*PLEN));    /* send the packet */
  287.         }
  288.     return (1);                    /* for success */
  289. }
  290.  
  291. /*
  292.  * arp_resolve - resolve IP address to hardware address
  293.  */
  294. int
  295. arp_resolve(longword ina, eth_address *ethap)
  296. {
  297.     register arp_tables *arp_ptr;
  298.     register int i;
  299.     int j;
  300.     longword timeout, resend;
  301.     static int recurse = 0;
  302.  
  303.     if (pktdevclass == PD_SLIP)
  304.     /* we are running slip or something which does not use addresses */
  305.         return(1);
  306.  
  307.     if (ina == my_ip_addr)
  308.             {
  309.         if (ethap != NULL)
  310.             bcopy(eth_addr, ethap, MAC_len);
  311.         recurse = 0;
  312.         return(1);                /* success */
  313.         }
  314.     if (ina == 0L || ina == 0xffffffffL || ina == ipbcast)
  315.         return (0);    /* cannot resolve IP of 0's or 0xff's*/
  316.  
  317.     if (recurse > 6) return (0);            /* fail */
  318.     recurse++;
  319.     tcp_tick(NULL);
  320.                 /* attempt to solve with ARP cache */
  321.     if ((arp_ptr = arp_search(ina, 0)) != NULL)
  322.         if (strncmp(arp_ptr->hardware, eth_none, MAC_len))
  323.             {    /* have non-NULL Ethernet address */
  324.                          /* has been resolved */
  325. #ifdef NEW_EXPIRY
  326.             if (chk_timeout(arp_ptr->expiry))
  327.                 {
  328.                 if (! chk_timeout(arp_ptr->expiry +
  329.                     MAX_ARP_GRACE))
  330.                     /* we wish to refresh it asynchronously */
  331.                     arp_request(ina);
  332.                 }
  333. #endif /* NEW_EXPIRY */
  334.             if ((arp_ptr->flags == ARP_FLAG_FOUND) ||
  335.                 (arp_ptr->flags == ARP_FLAG_FIXED))
  336.                 {
  337.                         /* we found a valid hardware address */
  338.                 if (ethap != NULL)
  339.                         {
  340.                     bcopy(arp_ptr->hardware, ethap, 
  341.                         MAC_len);
  342.                     recurse = 0;
  343.                     return(1);        /* success */
  344.                     }
  345.                 }    /* end of if ((arp_ptr... */
  346.             }        /* end of if (strncmp... main */
  347.  
  348.                         /* make a new one if necessary */
  349.     if (arp_ptr == NULL)
  350.             {
  351.         arp_ptr = arp_search(ina, 1);    /* 1 means create an entry */
  352.         arp_ptr->flags = ARP_FLAG_NEED;    /* say need a real entry */
  353.         }
  354.  
  355.         /* we must look elsewhere - but is it on our subnet? */
  356.     if ((ina ^ my_ip_addr) & sin_mask)    /* not of this network */
  357.         {
  358.         j = 0;                /* init status return */
  359.         for (i = 0; i < arp_last_gateway; i++)
  360.             {        /* compare the various subnet bits */
  361.                 if ((arp_gate_data[i].mask & ina) == 
  362.                 arp_gate_data[i].subnet)
  363.                     /* watch out RECURSIVE CALL! */
  364.                 if ((j = arp_resolve(arp_gate_data[i].gate_ip,
  365.                     ethap)) != 0)
  366.                         break;        /* success */
  367.             }
  368.         recurse--;
  369.         return (j);
  370.             }
  371.  
  372.     if (ina == 0L)        /* return if no host, or no gateway */
  373.             {
  374.         recurse--;
  375.         outs("\r\n Cannot find a gateway");
  376.         return(0);                    /* fail */
  377.         }
  378.  
  379.                     /* is on our subnet, we must resolve */
  380.     timeout = set_timeout(2);    /* two seconds is long for ARP */
  381.     while (!chk_timeout(timeout))
  382.         {    /* do the request */
  383.         arp_request(arp_ptr->ip = ina);
  384.         resend = set_timeout(1) - 14L;        /* 250 ms */
  385.         while (!chk_timeout(resend))
  386.             {
  387.             tcp_tick(NULL);            /* read packets */
  388.             if (arp_ptr->flags)
  389.                 {
  390.                 if (ethap != NULL)
  391.                     bcopy(arp_ptr->hardware, ethap, 
  392.                         MAC_len);
  393.                 arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  394.                 arp_ptr->flags = ARP_FLAG_FOUND;
  395.                 recurse = 0;
  396.                 return(1);            /* success */
  397.                 }
  398.             }
  399.             }
  400.     recurse--;
  401.     return(0);            /* fail */
  402. }
  403.  
  404.  
  405. int
  406. rarp_handler(arp_header *in)
  407. {
  408.     register int i;
  409.     longword his_ip;
  410.     register arp_tables *arp_ptr;
  411.  
  412.     if (in == NULL) return (0);            /* failure */
  413.  
  414.             /* require Ethernet hardware and Internet software */
  415.     if ((in->protType != 0x0008))
  416.         return (0);                /* 0 means no, fail */
  417.  
  418.     bcopy(&in->addr[MAC_len], &his_ip, PLEN);
  419.     his_ip = ntohl(his_ip);
  420.     if ((arp_ptr = arp_search(his_ip, 0)) != NULL)
  421.         {
  422.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  423.         bcopy(in->addr, arp_ptr->hardware, MAC_len);
  424.         arp_ptr->flags = ARP_FLAG_FOUND;
  425.         }
  426.  
  427.                     /* look for RARP Reply */
  428.     if ((my_ip_addr == 0) && (in->opcode == RARP_REPLY))
  429.         {              /* match our Ethernet address too */
  430.         for (i = 0; i < MAC_len; i++)
  431.             if (in->addr[i+MAC_len+PLEN] != (byte)eth_addr[i])
  432.                 return (1);        /* not for us */
  433.         bcopy(&in->addr[2*MAC_len+PLEN], &my_ip_addr, PLEN);
  434.         my_ip_addr = ntohl(my_ip_addr);        /* our IP addr */
  435.         }
  436.     return (1);                    /* for success */
  437. }
  438.  
  439. /* send a RARP packet to request an IP address for our Ethernet address */
  440. static void 
  441. arp_rev_request(void)
  442. {
  443.     register arp_header *op;
  444.  
  445.     op = (arp_header *)eth_formatpacket(ð_brdcast[0], 0x3580); /*RARP */
  446.     op->hwType = arp_hardware;
  447.     op->protType = 0x0008;                /* IP protocol */
  448.     op->hlen = MAC_len;                /* MAC address len */
  449.     op->plen = PLEN;                /* IP address len */
  450.     op->opcode = RARP_REQUEST;
  451.     bcopy(eth_addr, op->addr, MAC_len);        /* our MAC address */
  452.     bcopy(eth_addr, &op->addr[MAC_len+PLEN], MAC_len); /* in target too */
  453.     eth_send(8+2*MAC_len+2*PLEN);              /* send the packet */
  454. }
  455.  
  456. /* Send a series of RARP requests until our IP address is non-zero or
  457.    we timeout.
  458. */
  459. int
  460. do_rarp(void)
  461. {
  462.     longword timeout, resend;
  463.  
  464.     timeout = set_timeout(10);            /* 10 seconds total */
  465.     while (chk_timeout(timeout) == 0)
  466.             {
  467.         arp_rev_request();            /* ask for our IP */
  468.         resend = set_timeout(1);        /* two second retry */
  469.         while (chk_timeout(resend) == 0)
  470.             {
  471.             tcp_tick(NULL);            /* read packets */
  472.             if (my_ip_addr != 0L) return (1); /* got a reply */
  473.             }
  474.         }
  475.     return (0);                    /* got no reply */
  476. }
  477.