home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso
/
altsrc
/
articles
/
11108
/
iphash.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-11
|
6KB
|
198 lines
/* Routines for maintaining a totally encapsulated table of IP addresses
* and their associated hardware addresses, indexed by IP address. The
* hash function is extremely simple--the fourth octet of the IP address
* becomes the index into a 256-cell array of linked lists. This seems
* fast and simple enough for most applications, without being restrictive.
*
* To facilitate the common application of proxy-arping entire networks,
* I've added lookup tables for Class B and Class C networks we proxy-arp.
* The overhead associated with searching these should be a lot less than
* the overhead of, say, adding 65,536 hash table entries for a Class B.
*
* See proxyarpd.h and iphash.h for type definitions.
*
* Written by Matt Kimmel, kimmel@cs.umass.edu, 8/94.
* Copyright (c) 1994, University of Massachusetts. This program may be
* freely distributed, modified, or incorporated into other programs
* provided that the following conditions are met: 1) This copyright
* remains unmodified and is included in any derivative works; and 2)
* No profit is made through the sale of this program or derivative
* works.
*/
#include <stdio.h>
#include <string.h>
#include "proxyarpd.h"
#include "iphash.h"
/* Global variables */
static struct iphash_node *iphash_table[256]; /* The hash table */
static struct iphash_node *iphash_classb; /* List of Class B's we proxy-arp */
static struct iphash_node *iphash_classc; /* List of Class C's we proxy-arp */
/* Function prototypes */
void iphash_init();
int iphash_add(ipaddr,etheraddr *);
int iphash_add_classb(char *,etheraddr *);
int iphash_add_classc(char *,etheraddr *);
etheraddr *iphash_retrieve(ipaddr);
/* This function initializes the hash table. It should be called before
* any data is added to the hash table. It will re-initialize the table
* if it's already been used, but it will NOT free up the space allocated
* to the records, so it should not be used for this purpose.
*/
void iphash_init()
{
int i;
for(i=0;i<256;i++)
iphash_table[i] = NULL;
iphash_classb = NULL;
iphash_classc = NULL;
}
/* This function adds an IP address/ethernet address pair to the hash
* table. Returns 0 on success, non-zero on failure.
*/
int iphash_add(ipaddr ip,etheraddr *ether)
{
struct iphash_node *newnode;
int hash;
/* First, hash the IP address */
hash = iphash_hashfunc(ip);
/* Now, create a new node to store the information. */
if((newnode = (struct iphash_node *)malloc(sizeof(struct iphash_node))) == NULL)
return(-1);
newnode->ip = ip;
memcpy(newnode->ether.ether_octet,ether->ether_octet,6);
/* Finally, add the node to the appropriate slot in the hash table. */
newnode->next = iphash_table[hash];
iphash_table[hash] = newnode;
return(0);
}
/* This function adds a network to the list of Class B networks. It expects
* the network number to be represented in a string of the form "xxx.xxx".
* Returns nonzero on failure, 0 on success.
*/
int iphash_add_classb(char *network,etheraddr *ether)
{
struct iphash_node *newnode;
int o1, o2;
char *s, n[20];
/* Parse the address */
strcpy(n,network);
s = strchr(n,'.');
if(s == NULL)
return(-1);
*s = '\0';
s++;
o1 = atoi(n);
o2 = atoi(s);
/* Allocate and fill in a new node */
if((newnode = (struct iphash_node *)malloc(sizeof(struct iphash_node))) == NULL)
return(-1);
newnode->ip = (((o2 << 8) & 0xff00) | (o1 & 0xff)) & 0xffff;
memcpy(newnode->ether.ether_octet,ether->ether_octet,6);
/* And add it. */
newnode->next = iphash_classb;
iphash_classb = newnode;
return(0);
}
/* This function adds a network to the list of Class C networks. It expects
* the network number to be represented in a string of the form "xxx.xxx.xxx".
* Returns nonzero on failure, 0 on success.
*/
int iphash_add_classc(char *network,etheraddr *ether)
{
struct iphash_node *newnode;
int o1, o2, o3;
char *s, *s2, n[20];
/* Parse the address */
strcpy(n,network);
s = strchr(n,'.');
if(s == NULL)
return(-1);
*s = '\0';
s++;
s2 = strchr(s,'.');
if(s2 == NULL)
return(-1);
*s2 = '\0';
s2++;
o1 = atoi(n);
o2 = atoi(s);
o3 = atoi(s2);
/* Allocate and fill in a new node */
if((newnode = (struct iphash_node *)malloc(sizeof(struct iphash_node))) == NULL)
return(-1);
newnode->ip = ((((o3 << 16) & 0xff0000) | ((o2 << 8) & 0xff00)) | (o1 & 0xff)) & 0xffffff;
memcpy(newnode->ether.ether_octet,ether->ether_octet,6);
/* And add it. */
newnode->next = iphash_classc;
iphash_classc = newnode;
return(0);
}
/* This function retrieves the ethernet address associated with the
* specified IP number and returns a pointer to the etheraddr structure.
* It returns NULL if the IP number cannot be found.
*/
etheraddr *iphash_retrieve(ipaddr ip)
{
int hash;
struct iphash_node *p;
#ifdef DEBUG
printf("Looking up %d.%d.%d.%d\n",
(ip & 0xff),
((ip >> 8) & 0xff),
((ip >> 16) & 0xff),
((ip >> 24) & 0xff));
#endif
/* Hash the IP address */
hash = iphash_hashfunc(ip);
/* Now search the appropriate linked list. */
p = iphash_table[hash];
while(p != NULL)
if(p->ip == ip) /* A match! */
return(&(p->ether));
else
p = p->next;
/* After accessing the hash table, see if this address is in any of the
* Class B or Class C networks we're proxy-arping.
*/
p = iphash_classc;
while(p != NULL) {
if((ip & 0x00ffffff) == (p->ip & 0x00ffffff)) /* A match! */
return(&(p->ether));
p = p->next;
}
p = iphash_classb;
while(p != NULL) {
if((ip & 0x0000ffff) == (p->ip & 0x0000ffff)) /* A match! */
return(&(p->ether));
p = p->next;
}
/* If we make it here, there was no match. */
return(NULL);
}