home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / telecomm / ka9q_src / arp.c next >
Encoding:
C/C++ Source or Header  |  1988-11-29  |  9.6 KB  |  255 lines

  1. /* Address Resolution Protocol (ARP) functions. Sits between IP and
  2.  * Level 2, mapping IP to Level 2 addresses for all outgoing datagrams.
  3.  */
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "timer.h"
  7. #include "iface.h"
  8. #ifndef ATARI_ST        /* DG2KK */
  9. #include "enet.h"
  10. #endif
  11. #include "ax25.h"
  12. #include "arp.h"
  13.  
  14. extern int32 ip_addr;        /* Our IP address */
  15.  
  16. /* ARP entries for particular subnetwork types. The table values
  17.  * are filled in by calls to arp_init() at device attach time
  18.  */
  19. #define    NTYPES    9
  20. struct arp_type arp_type[NTYPES];
  21.  
  22. /* Hash table headers */
  23. struct arp_tab *arp_tab[ARPSIZE];
  24.  
  25. struct arp_stat arp_stat;
  26.  
  27. /* Initialize an entry in the ARP table
  28.  * Called by the device driver at attach time
  29.  */
  30. arp_init(hwtype,hwalen,iptype,arptype,bdcst,format,scan)
  31. unsigned int hwtype;    /* ARP Hardware type */
  32. int hwalen;        /* Hardware address length */
  33. int iptype;        /* Subnet's protocol ID for IP */
  34. int arptype;        /* Subnet's protocol ID for ARP */
  35. char *bdcst;        /* Subnet's broadcast address (if any) */
  36. int (*format)();    /* Function to format hardware addresses */
  37. int (*scan)();        /* Function to scan addresses in ascii */    
  38. {
  39.     register struct arp_type *at;
  40.  
  41.     if(hwtype >= NTYPES)
  42.         return -1;    /* Table too small */
  43.  
  44.     at = &arp_type[hwtype];
  45.     at->hwalen = (int16)hwalen;
  46.     at->iptype = (int16)iptype;
  47.     at->arptype = (int16)arptype;
  48.     at->bdcst = bdcst;
  49.     at->format = format;
  50.     at->scan = scan;
  51.     return 0;
  52. }
  53.  
  54. /* Resolve an IP address to a hardware address; if not found,
  55.  * initiate query and return NULLCHAR.  If an address is returned, the
  56.  * interface driver may send the packet; if NULLCHAR is returned,
  57.  * res_arp() will have saved the packet on its pending queue,
  58.  * so no further action (like freeing the packet) is necessary.
  59.  */
  60. char *
  61. res_arp(interface,hardware,target,bp)
  62. struct interface *interface;    /* Pointer to interface block */
  63. int16 hardware;        /* Hardware type */
  64. int32 target;        /* Target IP address */
  65. struct mbuf *bp;    /* IP datagram to be queued if unresolved */
  66. {
  67.     void arp_output();
  68.     register struct arp_tab *arp;
  69.  
  70.     if((arp = arp_lookup(hardware,target)) != NULLARP && arp->state == ARP_VALID)
  71.         return arp->hw_addr;
  72.     /* Create an entry and put the datagram on the
  73.      * queue pending an answer
  74.      */
  75.     arp = arp_add(target,hardware,NULLCHAR,0);
  76.     enqueue(&arp->pending,bp);
  77.     arp_output(interface,hardware,target);
  78.     return NULLCHAR;
  79. }
  80. /* Handle incoming ARP packets. This is almost a direct implementation of
  81.  * the algorithm on page 5 of RFC 826, except for:
  82.  * 1. Outgoing datagrams to unresolved addresses are kept on a queue
  83.  *    pending a reply to our ARP request.
  84.  * 2. The names of the fields in the ARP packet were made more mnemonic.
  85.  */
  86. void
  87. arp_input(interface,bp)
  88. struct interface *interface;
  89. struct mbuf *bp;
  90. {
  91.     struct arp arp;
  92.     struct arp_tab *ap;
  93.     struct arp_type *at;
  94.     struct mbuf *htonarp();
  95.     
  96.     arp_stat.recv++;
  97.     if(ntoharp(&arp,&bp) == -1)    /* Convert into host format */
  98.         return;
  99.     if(arp.hardware >= NTYPES){
  100.         /* Unknown hardware type, ignore */
  101.         arp_stat.badtype++;
  102.         return;
  103.     }
  104.     at = &arp_type[arp.hardware];
  105.     if(arp.protocol != at->iptype){
  106.         /* Unsupported protocol type, ignore */
  107.         arp_stat.badtype++;
  108.         return;
  109.     }
  110.     if(arp.hwalen > MAXHWALEN || arp.pralen != sizeof(int32)){
  111.         /* Incorrect protocol addr length (different hw addr lengths
  112.          * are OK since AX.25 addresses can be of variable length)
  113.          */
  114.         arp_stat.badlen++;
  115.         return;
  116.     }
  117.     if(memcmp(arp.shwaddr,at->bdcst,at->hwalen) == 0){
  118.         /* This guy is trying to say he's got the broadcast address! */
  119.         arp_stat.badaddr++;
  120.         return;
  121.     }
  122.     /* If this guy is already in the table, update its entry
  123.      * unless it's a manual entry (noted by the lack of a timer)
  124.      */
  125.     ap = NULLARP;    /* ap plays the role of merge_flag in the spec */
  126.     if((ap = arp_lookup(arp.hardware,arp.sprotaddr)) != NULLARP
  127.      && ap->timer.start != 0){
  128.         ap = arp_add(arp.sprotaddr,arp.hardware,arp.shwaddr,arp.hwalen & 0xff);
  129.     }
  130.     /* See if we're the address they're looking for */
  131.     if(arp.tprotaddr == ip_addr){
  132.         if(ap == NULLARP)    /* Only if not already in the table */
  133.             arp_add(arp.sprotaddr,arp.hardware,arp.shwaddr,arp.hwalen & 0xff);
  134.  
  135.         if(arp.opcode == ARP_REQUEST){
  136.             /* Swap sender's and target's (us) hardware and protocol
  137.              * fields, and send the packet back as a reply
  138.              */
  139.             memcpy(arp.thwaddr,arp.shwaddr,arp.hwalen);
  140.             /* Mark the end of the sender's AX.25 address
  141.              * in case he didn't
  142.              */
  143.             if(arp.hardware == ARP_AX25)
  144.                 arp.thwaddr[arp.hwalen-1] |= E;
  145.  
  146.             memcpy(arp.shwaddr,inte2face->hwaddr,at->hwalen);
  147.             arp.tprotaddr = arp.sprotaddr;
  148.             arp.sprotaddr = ip_addr;
  149.             arp.opcode = ARP_REPLY;
  150.             bp = htonarp(&arp);
  151.             (*interface->output)(interface,arp.thwaddr,
  152.                 interface->hwaddr,at->arptype,bp);
  153.             arp_stat.inreq++;
  154.         } else {
  155.             arp_stat.replies++;
  156.         }
  157.     }
  158. }
  159. /* Add an IP-addr / hardware-addr pair to the ARP table */
  160. struct arp_tab *
  161. arp_add(ipaddr,hardware,hw_addr,hw_alen)
  162. int32 ipaddr;    /* IP address, host order */
  163. int16 hardware;    /* HardwareHardwareHardwareHardwareHardwarehtonarp();
  164.     struct arp_type *at;
  165.  
  166.     at = &arp_type[hardware];
  167.     if(interface->output == NULLFP)
  168.         return;
  169.     
  170.     arp.hardware = hardware;
  171.     arp.protocol = at->iptype;
  172.     arp.hwalen = at->hwalen;
  173.     arp.pralen = sizeof(int32);
  174.     arp.opcode = ARP_REQUEST;
  175.     memcpy(arp.shwaddr,interface->hwaddr,at->hwalen);
  176.     arp.sprotaddr = ip_addr;
  177.     memset(arp.thwaddr,0,at->hwalen);
  178.     arp.tprotaddr = target;
  179.     bp = htonarp(&arp);
  180.     (*interface->output)(interface,at->bdcst,
  181.         interface->hwaddr,at->arptype,bp);
  182.     arp_stat.outreq++;
  183. }
  184.  
  185. /* Hash a {hardware type, IP address} pair */
  186. static
  187. unsigned
  188. arp_hash(hardware,ipaddr)
  189. int16 hardware;
  190. int32 ipaddr;
  191. {
  192.     register unsigned hashval;
  193.  
  194.     hashval = hardware;
  195.     hashval ^= hiword(ipaddr);
  196.     hashval ^= loword(ipaddr);
  197.     hashval %= ARPSIZE;
  198.     return hashval;
  199. }        
  200. /* Copy a host format arp structure into mbuf for transmission */
  201. struct mbuf *
  202. htonarp(arp)
  203. register struct arp *arp;
  204. {
  205.     struct mbuf *bp;
  206.     register char *buf;
  207.  
  208.     if(arp == (struct arp *)0)
  209.         return NULLBUF;
  210.     if((bp = alloc_mbuf(sizeof(struct arp))) == NULLBUF)
  211.         return NULLBUF;
  212.  
  213.     buf = bp->data;
  214.  
  215.     buf = put16(buf,arp->hardware);
  216.     buf = put16(buf,arp->protocol);
  217.     *buf++ = arp->hwalen;
  218.     *buf++ = arp->pralen;
  219.     buf = put16(buf,arp->opcode);
  220.     memcpy(buf,arp->shwaddr,arp->hwalen);
  221.     buf += arp->hwalen;
  222.     buf = put32(buf,arp->sprotaddr);
  223.     memcpy(buf,arp->thwaddr,arp->hwalen);
  224.     buf += arp->hwalen;
  225.     buf = put32(buf,arp->tprotaddr);
  226.  
  227.     bp->cnt = buf - bp->data;
  228.     return bp;
  229. }
  230. /* Convert an incoming ARP packet into a host-format structure */
  231. int
  232. ntoharp(arp,bpp)
  233. register struct arp *arp;
  234. struct mbuf **bpp;
  235. {
  236.     if(arp == (struct arp *)0 || bpp == NULLBUFP)
  237.         return -1;
  238.  
  239.     arp->hardware = pull16(bpp);
  240.     arp->protocol = pull16(bpp);
  241.     arp->hwalen = pullchar(bpp);
  242.     arp->pralen = pullchar(bpp);
  243.     arp->opcode = pull16(bpp);
  244.     pullup(bpp,arp->shwaddr,arp->hwalen);
  245.     arp->sprotaddr = pull32(bpp);
  246.     pullup(bpp,arp->thwaddr,arp->hwalen);
  247.  
  248.     arp->tprotaddr = pull32(bpp);
  249.  
  250.     /* Get rid of anything left over */
  251.     free_p(*bpp);
  252.     *bpp = NULLBUF;
  253.     return 0;
  254. }
  255.