diff options
Diffstat (limited to 'main/common/arp.c')
-rw-r--r-- | main/common/arp.c | 906 |
1 files changed, 456 insertions, 450 deletions
diff --git a/main/common/arp.c b/main/common/arp.c index 0c8d762..6649f1f 100644 --- a/main/common/arp.c +++ b/main/common/arp.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -21,7 +21,7 @@ * arp.c: * This code supports some basic arp/rarp stuff. * - * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com) + * Original author: Ed Sutter (ed.sutter@alcatel-lucent.com) * */ #include "config.h" @@ -33,11 +33,11 @@ #include "cli.h" #include "timer.h" -static void ArpFlush(void); +static void ArpFlush(void); static void ArpShow(char *); static void llas(char *); -static int ArpStore(uchar *,uchar *); -static int IpIsOnThisNet(uchar *); +static int ArpStore(uchar *,uchar *); +static int IpIsOnThisNet(uchar *); static unsigned long probeIP; static char probeAbort; @@ -45,135 +45,139 @@ static char probeAbort; /* Constants used by Dynamic IPV4 Local-Link Address setup... * (see RFC 3927) */ -#define PROBE_WAIT 1000 /* (msec) */ -#define PROBE_NUM 3 -#define PROBE_MIN 1000 /* (msec) */ -#define PROBE_MAX 2000 /* (msec) */ -#define ANNOUNCE_WAIT 2000 /* (msec) */ -#define ANNOUNCE_NUM 2 -#define ANNOUNCE_INTERVAL 2000 /* (msec) */ -#define MAX_CONFLICTS 10 -#define RATE_LIMIT_INTERVAL 60000 /* (msec) */ -#define DEFEND_INTERVAL 10000 /* (msec) */ +#define PROBE_WAIT 1000 /* (msec) */ +#define PROBE_NUM 3 +#define PROBE_MIN 1000 /* (msec) */ +#define PROBE_MAX 2000 /* (msec) */ +#define ANNOUNCE_WAIT 2000 /* (msec) */ +#define ANNOUNCE_NUM 2 +#define ANNOUNCE_INTERVAL 2000 /* (msec) */ +#define MAX_CONFLICTS 10 +#define RATE_LIMIT_INTERVAL 60000 /* (msec) */ +#define DEFEND_INTERVAL 10000 /* (msec) */ /* arpcache[]: - * Used to store the most recent set of IP-to-MAC address correlations. + * Used to store the most recent set of IP-to-MAC address correlations. */ struct arpcache { - uchar ip[4]; - uchar ether[6]; + uchar ip[4]; + uchar ether[6]; } ArpCache[SIZEOFARPCACHE]; /* ArpIdx & ArpTot: - * Used for keeping track of current arp cache content. + * Used for keeping track of current arp cache content. */ int ArpIdx, ArpTot; /* ArpStore(): - * Called with binary ip and ethernet addresses. - * It will store that set away in the cache. + * Called with binary ip and ethernet addresses. + * It will store that set away in the cache. */ int ArpStore(uchar *ip,uchar *ether) { - if (EtherFromCache(ip)) - return(0); - if (ArpIdx >= SIZEOFARPCACHE) - ArpIdx=0; - memcpy((char *)ArpCache[ArpIdx].ip,(char *)ip,4); - memcpy((char *)ArpCache[ArpIdx].ether,(char *)ether,6); - ArpIdx++; - ArpTot++; - return(0); + if(EtherFromCache(ip)) { + return(0); + } + if(ArpIdx >= SIZEOFARPCACHE) { + ArpIdx=0; + } + memcpy((char *)ArpCache[ArpIdx].ip,(char *)ip,4); + memcpy((char *)ArpCache[ArpIdx].ether,(char *)ether,6); + ArpIdx++; + ArpTot++; + return(0); } /* EtherFromCache(): - * Called with a binary (4-byte) ip address. If a match is found - * in the cache, return a pointer to that ethernet address; else - * return NULL. + * Called with a binary (4-byte) ip address. If a match is found + * in the cache, return a pointer to that ethernet address; else + * return NULL. */ uchar * EtherFromCache(uchar *ip) { - int i; - - for(i=0;i<SIZEOFARPCACHE;i++) { - if (!memcmp((char *)ArpCache[i].ip, (char *)ip,4)) - return(ArpCache[i].ether); - } - return(0); + int i; + + for(i=0; i<SIZEOFARPCACHE; i++) { + if(!memcmp((char *)ArpCache[i].ip, (char *)ip,4)) { + return(ArpCache[i].ether); + } + } + return(0); } void ArpFlush(void) { - int i; + int i; - for(i=0;i<SIZEOFARPCACHE;i++) { - memset((char *)ArpCache[i].ip,0,4); - memset((char *)ArpCache[i].ether,0,6); - } - ArpIdx = ArpTot = 0; + for(i=0; i<SIZEOFARPCACHE; i++) { + memset((char *)ArpCache[i].ip,0,4); + memset((char *)ArpCache[i].ether,0,6); + } + ArpIdx = ArpTot = 0; } /* ArpShow(): - * Dump the content of the current arp cache. + * Dump the content of the current arp cache. */ void ArpShow(char *ip) { - struct arpcache *ap, *end; - - if (ArpTot < SIZEOFARPCACHE) - end = &ArpCache[ArpTot]; - else - end = &ArpCache[SIZEOFARPCACHE]; - - for (ap=ArpCache;ap<end;ap++) { - if ((!ip) || (!memcmp((char *)ip, (char *)ap->ip,4))) { - printf("%02x:%02x:%02x:%02x:%02x:%02x = ", - ap->ether[0], ap->ether[1], ap->ether[2], ap->ether[3], - ap->ether[4], ap->ether[5]); - printf("%d.%d.%d.%d\n", - ap->ip[0], ap->ip[1], ap->ip[2], ap->ip[3]); - } - } + struct arpcache *ap, *end; + + if(ArpTot < SIZEOFARPCACHE) { + end = &ArpCache[ArpTot]; + } else { + end = &ArpCache[SIZEOFARPCACHE]; + } + + for(ap=ArpCache; ap<end; ap++) { + if((!ip) || (!memcmp((char *)ip, (char *)ap->ip,4))) { + printf("%02x:%02x:%02x:%02x:%02x:%02x = ", + ap->ether[0], ap->ether[1], ap->ether[2], ap->ether[3], + ap->ether[4], ap->ether[5]); + printf("%d.%d.%d.%d\n", + ap->ip[0], ap->ip[1], ap->ip[2], ap->ip[3]); + } + } } /* SendArpResp(): - * Called in response to an ARP REQUEST. The incoming ethernet - * header pointer points to the memory area that contains the incoming - * ethernet packet that this function is called in response to. - * In other words, it is used to fill the majority of the response - * packet fields. + * Called in response to an ARP REQUEST. The incoming ethernet + * header pointer points to the memory area that contains the incoming + * ethernet packet that this function is called in response to. + * In other words, it is used to fill the majority of the response + * packet fields. */ int SendArpResp(struct ether_header *re) { - struct ether_header *te; - struct arphdr *ta, *ra; - - te = (struct ether_header *) getXmitBuffer(); - memcpy((char *)&(te->ether_shost), (char *)BinEnetAddr,6); - memcpy((char *)&(te->ether_dhost),(char *)&(re->ether_shost),6); - te->ether_type = ecs(ETHERTYPE_ARP); - - ta = (struct arphdr *) (te + 1); - ra = (struct arphdr *) (re + 1); - ta->hardware = ra->hardware; - ta->protocol = ra->protocol; - ta->hlen = ra->hlen; - ta->plen = ra->plen; - ta->operation = ARP_RESPONSE; - memcpy((char *)ta->senderha, (char *)BinEnetAddr,6); - memcpy((char *)ta->senderia, (char *)ra->targetia,4); - memcpy((char *)ta->targetha, (char *)ra->senderha,6); - memcpy((char *)ta->targetia, (char *)ra->senderia,4); - self_ecs(ta->hardware); - self_ecs(ta->protocol); - self_ecs(ta->operation); - sendBuffer(ARPSIZE); - return(0); + struct ether_header *te; + struct arphdr *ta, *ra; + + te = (struct ether_header *) getXmitBuffer(); + memcpy((char *)&(te->ether_shost), (char *)BinEnetAddr,6); + memcpy((char *)&(te->ether_dhost),(char *)&(re->ether_shost),6); + te->ether_type = ecs(ETHERTYPE_ARP); + + ta = (struct arphdr *)(te + 1); + ra = (struct arphdr *)(re + 1); + ta->hardware = ra->hardware; + ta->protocol = ra->protocol; + ta->hlen = ra->hlen; + ta->plen = ra->plen; + ta->operation = ARP_RESPONSE; + memcpy((char *)ta->senderha, (char *)BinEnetAddr,6); + memcpy((char *)ta->senderia, (char *)ra->targetia,4); + memcpy((char *)ta->targetha, (char *)ra->senderha,6); + memcpy((char *)ta->targetia, (char *)ra->senderia,4); + self_ecs(ta->hardware); + self_ecs(ta->protocol); + self_ecs(ta->operation); + sendBuffer(ARPSIZE); + return(0); } /* SendArpRequest(): @@ -183,410 +187,411 @@ SendArpResp(struct ether_header *re) static int SendArpRequest(uchar *ip, int probe) { - struct ether_header *te; - struct arphdr *ta; - - /* Populate the ethernet header: */ - te = (struct ether_header *) getXmitBuffer(); - memcpy((char *)&(te->ether_shost), (char *)BinEnetAddr,6); - memcpy((char *)&(te->ether_dhost), (char *)BroadcastAddr,6); - te->ether_type = ecs(ETHERTYPE_ARP); - - /* Populate the arp header: */ - ta = (struct arphdr *) (te + 1); - ta->hardware = ecs(1); /* 1 for ethernet */ - ta->protocol = ecs(ETHERTYPE_IP); - ta->hlen = 6; /* Length of hdware (ethernet) address */ - ta->plen = 4; /* Length of protocol (ip) address */ - ta->operation = ecs(ARP_REQUEST); - memcpy((char *)ta->senderha, (char *)BinEnetAddr,6); - if (probe) { - memset((char *)ta->senderia,0,4); - memset((char *)ta->targetha,0,6); - } - else { - memcpy((char *)ta->senderia, (char *)BinIpAddr,4); - memcpy((char *)ta->targetha, (char *)BroadcastAddr,6); - } - memcpy((char *)ta->targetia, (char *)ip,4); - sendBuffer(ARPSIZE); - return(0); + struct ether_header *te; + struct arphdr *ta; + + /* Populate the ethernet header: */ + te = (struct ether_header *) getXmitBuffer(); + memcpy((char *)&(te->ether_shost), (char *)BinEnetAddr,6); + memcpy((char *)&(te->ether_dhost), (char *)BroadcastAddr,6); + te->ether_type = ecs(ETHERTYPE_ARP); + + /* Populate the arp header: */ + ta = (struct arphdr *)(te + 1); + ta->hardware = ecs(1); /* 1 for ethernet */ + ta->protocol = ecs(ETHERTYPE_IP); + ta->hlen = 6; /* Length of hdware (ethernet) address */ + ta->plen = 4; /* Length of protocol (ip) address */ + ta->operation = ecs(ARP_REQUEST); + memcpy((char *)ta->senderha, (char *)BinEnetAddr,6); + if(probe) { + memset((char *)ta->senderia,0,4); + memset((char *)ta->targetha,0,6); + } else { + memcpy((char *)ta->senderia, (char *)BinIpAddr,4); + memcpy((char *)ta->targetha, (char *)BroadcastAddr,6); + } + memcpy((char *)ta->targetia, (char *)ip,4); + sendBuffer(ARPSIZE); + return(0); } /* GetBinNetMask(): * Return a subnet mask in binary form. - * Since this function needs a netmask, if NETMASK is not set, then - * it uses the default based on the upper 3 bits of the IP address - * (refer to TCP/IP Illustrated Volume 1 Pg8 for details). + * Since this function needs a netmask, if NETMASK is not set, then + * it uses the default based on the upper 3 bits of the IP address + * (refer to TCP/IP Illustrated Volume 1 Pg8 for details). */ void GetBinNetMask(uchar *binnetmask) { - char *nm; - - nm = getenv("NETMASK"); - if (!nm) { - memset((char *)binnetmask,0xff,4); - if ((BinIpAddr[0] & 0xe0) == 0xc0) { /* Class C */ - binnetmask[3] = 0; - } - else if ((BinIpAddr[0] & 0xc0) == 0x80) { /* Class B */ - binnetmask[3] = 0; - binnetmask[2] = 0; - } - else if ((BinIpAddr[0] & 0x80) == 0x00) { /* Class A */ - binnetmask[3] = 0; - binnetmask[2] = 0; - binnetmask[1] = 0; - } - } - else - IpToBin(nm,binnetmask); + char *nm; + + nm = getenv("NETMASK"); + if(!nm) { + memset((char *)binnetmask,0xff,4); + if((BinIpAddr[0] & 0xe0) == 0xc0) { /* Class C */ + binnetmask[3] = 0; + } else if((BinIpAddr[0] & 0xc0) == 0x80) { /* Class B */ + binnetmask[3] = 0; + binnetmask[2] = 0; + } else if((BinIpAddr[0] & 0x80) == 0x00) { /* Class A */ + binnetmask[3] = 0; + binnetmask[2] = 0; + binnetmask[1] = 0; + } + } else { + IpToBin(nm,binnetmask); + } } /* IpIsOnThisNet(): - * Return 1 if the incoming ip is on this subnet; else 0. - * For each bit in the netmask that is set to 1... - * If the corresponding bits in the incoming IP and this board's IP - * do not match, return 0; else return 1. + * Return 1 if the incoming ip is on this subnet; else 0. + * For each bit in the netmask that is set to 1... + * If the corresponding bits in the incoming IP and this board's IP + * do not match, return 0; else return 1. */ int IpIsOnThisNet(uchar *ip) { - int i; - uchar binnetmask[8]; + int i; + uchar binnetmask[8]; - GetBinNetMask(binnetmask); + GetBinNetMask(binnetmask); - for(i=0;i<4;i++) { - if ((ip[i] & binnetmask[i]) != (BinIpAddr[i] & binnetmask[i])) { - return(0); - } - } - return(1); + for(i=0; i<4; i++) { + if((ip[i] & binnetmask[i]) != (BinIpAddr[i] & binnetmask[i])) { + return(0); + } + } + return(1); } /* Arp(): - * If no args, just dump the arp cache. - * If arg is present, then assume it to be an ip address. - * Check the arp cache for the presence of that ip<->correlation, if - * present, print it; else issue and arp request for that IP and wait - * for a response. + * If no args, just dump the arp cache. + * If arg is present, then assume it to be an ip address. + * Check the arp cache for the presence of that ip<->correlation, if + * present, print it; else issue and arp request for that IP and wait + * for a response. */ char *ArpHelp[] = { - "Address resolution protocol", - "-[flps:v] [IP]", + "Address resolution protocol", + "-[flps:v] [IP]", #if INCLUDE_VERBOSEHELP - " -f flush cache", - " -l dynamic config using link-local arp probe", - " -p proxy arp", - " -s{eadr} store eadr/IP into cache", + " -f flush cache", + " -l dynamic config using link-local arp probe", + " -p proxy arp", + " -s{eadr} store eadr/IP into cache", #if INCLUDE_ETHERVERBOSE - " -v verbose", + " -v verbose", #endif #endif - 0, + 0, }; int Arp(int argc,char *argv[]) { - int opt, proxyarp, llad; - char binip[8], binether[8], *storeether; - - llad = proxyarp = 0; - storeether = (char *)0; - while ((opt=getopt(argc,argv,"flps:v")) != -1) { - switch(opt) { - case 'f': /* Flush current arp cache */ - ArpFlush(); - break; - case 'l': /* Dynamic ip-config using link-local addressing */ - llad = 1; /* (refer to RFC 3927) */ - break; - case 's': /* Store specified IP/MAC combination in arp cache. */ - storeether = optarg; - break; - case 'p': /* Assume gateway will run proxy arp */ - proxyarp = 1; - break; + int opt, proxyarp, llad; + char binip[8], binether[8], *storeether; + + llad = proxyarp = 0; + storeether = (char *)0; + while((opt=getopt(argc,argv,"flps:v")) != -1) { + switch(opt) { + case 'f': /* Flush current arp cache */ + ArpFlush(); + break; + case 'l': /* Dynamic ip-config using link-local addressing */ + llad = 1; /* (refer to RFC 3927) */ + break; + case 's': /* Store specified IP/MAC combination in arp cache. */ + storeether = optarg; + break; + case 'p': /* Assume gateway will run proxy arp */ + proxyarp = 1; + break; #if INCLUDE_ETHERVERBOSE - case 'v': /* Enable verbosity for ARP. */ - EtherVerbose |= SHOW_ARP; - break; + case 'v': /* Enable verbosity for ARP. */ + EtherVerbose |= SHOW_ARP; + break; #endif - default: - return(CMD_PARAM_ERROR); - } - } - - /* If llad flag is set, then we do a dynamic configuration using the - * link-local protocol as described in RFC 3927... - */ - if (llad) { - char buf[32]; - struct elapsed_tmr tmr; - int i, retry, conflicts, psval; + default: + return(CMD_PARAM_ERROR); + } + } + + /* If llad flag is set, then we do a dynamic configuration using the + * link-local protocol as described in RFC 3927... + */ + if(llad) { + char buf[32]; + struct elapsed_tmr tmr; + int i, retry, conflicts, psval; #if INCLUDE_DHCPBOOT - dhcpDisable(); + dhcpDisable(); #endif - probeAbort = retry = conflicts = 0; + probeAbort = retry = conflicts = 0; - /* Use MAC address to establish a uniformly selected pseudo random - * value between 0 and 1000... - */ - psval = (BinEnetAddr[5] * 4); + /* Use MAC address to establish a uniformly selected pseudo random + * value between 0 and 1000... + */ + psval = (BinEnetAddr[5] * 4); - monDelay(psval); + monDelay(psval); - if (argc == (optind+1)) - IpToBin((char *)argv[optind],(unsigned char *)&probeIP); - else - llas((char *)&probeIP); + if(argc == (optind+1)) { + IpToBin((char *)argv[optind],(unsigned char *)&probeIP); + } else { + llas((char *)&probeIP); + } nextllas: - SendArpRequest((uchar *)&probeIP,1); - startElapsedTimer(&tmr,ANNOUNCE_WAIT); - while(!msecElapsed(&tmr)) { - if (probeAbort) { - llas((char *)&probeIP); - probeAbort = retry = 0; - monDelay(psval + PROBE_MIN); - goto nextllas; - } - if (EtherFromCache((uchar *)&probeIP)) { - if (++conflicts > MAX_CONFLICTS) - monDelay(RATE_LIMIT_INTERVAL); - else - monDelay(psval + PROBE_MIN); - if (++retry == PROBE_NUM) { - llas((char *)&probeIP); - retry = 0; - } - goto nextllas; - } - pollethernet(); - } - /* If we're here, then we found an IP address that is not being - * used on the local subnet... - */ - setenv("IPADD",IpToString(probeIP,buf)); - setenv("NETMASK","255.255.0.0"); - setenv("GIPADD",0); + SendArpRequest((uchar *)&probeIP,1); + startElapsedTimer(&tmr,ANNOUNCE_WAIT); + while(!msecElapsed(&tmr)) { + if(probeAbort) { + llas((char *)&probeIP); + probeAbort = retry = 0; + monDelay(psval + PROBE_MIN); + goto nextllas; + } + if(EtherFromCache((uchar *)&probeIP)) { + if(++conflicts > MAX_CONFLICTS) { + monDelay(RATE_LIMIT_INTERVAL); + } else { + monDelay(psval + PROBE_MIN); + } + if(++retry == PROBE_NUM) { + llas((char *)&probeIP); + retry = 0; + } + goto nextllas; + } + pollethernet(); + } + /* If we're here, then we found an IP address that is not being + * used on the local subnet... + */ + setenv("IPADD",IpToString(probeIP,buf)); + setenv("NETMASK","255.255.0.0"); + setenv("GIPADD",0); #if INCLUDE_ETHERVERBOSE - EthernetStartup(EtherVerbose,0); + EthernetStartup(EtherVerbose,0); #else - EthernetStartup(0,0); + EthernetStartup(0,0); #endif - for(i=0;i<ANNOUNCE_NUM;i++) { - SendArpRequest(BinIpAddr,0); - monDelay(ANNOUNCE_INTERVAL); - } - } - else if (argc == (optind+1)) { - IpToBin((char *)argv[optind],(unsigned char *)binip); - if (storeether) { - EtherToBin((char *)storeether, (unsigned char *)binether); - ArpStore((unsigned char *)binip,(unsigned char *)binether); - } - else { - if (ArpEther((unsigned char *)binip,(unsigned char *)0,proxyarp)) - ArpShow(binip); - } - } - else - ArpShow(0); + for(i=0; i<ANNOUNCE_NUM; i++) { + SendArpRequest(BinIpAddr,0); + monDelay(ANNOUNCE_INTERVAL); + } + } else if(argc == (optind+1)) { + IpToBin((char *)argv[optind],(unsigned char *)binip); + if(storeether) { + EtherToBin((char *)storeether, (unsigned char *)binether); + ArpStore((unsigned char *)binip,(unsigned char *)binether); + } else { + if(ArpEther((unsigned char *)binip,(unsigned char *)0,proxyarp)) { + ArpShow(binip); + } + } + } else { + ArpShow(0); + } #if INCLUDE_ETHERVERBOSE - EtherVerbose &= ~ SHOW_ARP; + EtherVerbose &= ~ SHOW_ARP; #endif - return(CMD_SUCCESS); + return(CMD_SUCCESS); } /* ArpEther(): - * Retrieve the ethernet address that corresponds to the incoming IP - * address. First check the local ArpCache[], then if not found issue - * an ARP request... If the incoming IP is on this net, then issue the - * request for the MAC address of that IP; otherwise, issue the request - * for this net's GATEWAY. + * Retrieve the ethernet address that corresponds to the incoming IP + * address. First check the local ArpCache[], then if not found issue + * an ARP request... If the incoming IP is on this net, then issue the + * request for the MAC address of that IP; otherwise, issue the request + * for this net's GATEWAY. */ uchar * ArpEther(uchar *binip, uchar *ecpy, int proxyarp) { - char *gip; - struct elapsed_tmr tmr; - uchar gbinip[8], *Ip, *ep; - int timeoutsecs, retry; - - if (!EtherIsActive) { - printf("Ethernet disabled\n"); - return(0); - } - - /* First check local cache. If found, return with pointer to MAC. */ - ep = EtherFromCache(binip); - if (ep) { - if (ecpy) { - memcpy((char *)ecpy, (char *)ep,6); - ep = ecpy; - } - return(ep); - } - - retry = 0; - RetransmitDelay(DELAY_INIT_ARP); - while(1) { - /* If IP is not on this net, then get the GATEWAY IP address. */ - if (!proxyarp && !IpIsOnThisNet(binip)) { - gip = getenv("GIPADD"); - if (gip) { - IpToBin(gip,gbinip); - if (!IpIsOnThisNet(gbinip)) { - printf("GIPADD/IPADD subnet confusion.\n"); - return(0); - } - ep = EtherFromCache(gbinip); - if (ep) { - if (ecpy) { - memcpy((char *)ecpy, (char *)ep,6); - ep = ecpy; - } - return(ep); - } - SendArpRequest(gbinip,0); - Ip = gbinip; - } - else { - SendArpRequest(binip,0); - Ip = binip; - } - } - else { - SendArpRequest(binip,0); - Ip = binip; - } - if (retry) { - printf(" ARP Retry #%d (%d.%d.%d.%d)\n",retry, - binip[0],binip[1],binip[2],binip[3]); - } - - /* Now that the request has been issued, wait for a while to see if - * the ARP cache is loaded with the result of the request. - */ - timeoutsecs = RetransmitDelay(DELAY_OR_TIMEOUT_RETURN); - if (timeoutsecs == RETRANSMISSION_TIMEOUT) - break; - startElapsedTimer(&tmr,timeoutsecs*1000); - while(!msecElapsed(&tmr)) { - ep = EtherFromCache(Ip); - if (ep) - break; - - pollethernet(); - } - if (ep) { - if (ecpy) { - memcpy((char *)ecpy, (char *)ep,6); - ep = ecpy; - } - return(ep); - } - RetransmitDelay(DELAY_INCREMENT); - retry++; - } + char *gip; + struct elapsed_tmr tmr; + uchar gbinip[8], *Ip, *ep; + int timeoutsecs, retry; + + if(!EtherIsActive) { + printf("Ethernet disabled\n"); + return(0); + } + + /* First check local cache. If found, return with pointer to MAC. */ + ep = EtherFromCache(binip); + if(ep) { + if(ecpy) { + memcpy((char *)ecpy, (char *)ep,6); + ep = ecpy; + } + return(ep); + } + + retry = 0; + RetransmitDelay(DELAY_INIT_ARP); + while(1) { + /* If IP is not on this net, then get the GATEWAY IP address. */ + if(!proxyarp && !IpIsOnThisNet(binip)) { + gip = getenv("GIPADD"); + if(gip) { + IpToBin(gip,gbinip); + if(!IpIsOnThisNet(gbinip)) { + printf("GIPADD/IPADD subnet confusion.\n"); + return(0); + } + ep = EtherFromCache(gbinip); + if(ep) { + if(ecpy) { + memcpy((char *)ecpy, (char *)ep,6); + ep = ecpy; + } + return(ep); + } + SendArpRequest(gbinip,0); + Ip = gbinip; + } else { + SendArpRequest(binip,0); + Ip = binip; + } + } else { + SendArpRequest(binip,0); + Ip = binip; + } + if(retry) { + printf(" ARP Retry #%d (%d.%d.%d.%d)\n",retry, + binip[0],binip[1],binip[2],binip[3]); + } + + /* Now that the request has been issued, wait for a while to see if + * the ARP cache is loaded with the result of the request. + */ + timeoutsecs = RetransmitDelay(DELAY_OR_TIMEOUT_RETURN); + if(timeoutsecs == RETRANSMISSION_TIMEOUT) { + break; + } + startElapsedTimer(&tmr,timeoutsecs*1000); + while(!msecElapsed(&tmr)) { + ep = EtherFromCache(Ip); + if(ep) { + break; + } + + pollethernet(); + } + if(ep) { + if(ecpy) { + memcpy((char *)ecpy, (char *)ep,6); + ep = ecpy; + } + return(ep); + } + RetransmitDelay(DELAY_INCREMENT); + retry++; + } #if INCLUDE_ETHERVERBOSE - if ((EtherVerbose & SHOW_ARP) && (retry)) - printf(" ARP giving up\n"); + if((EtherVerbose & SHOW_ARP) && (retry)) { + printf(" ARP giving up\n"); + } #endif - return(0); + return(0); } /* processRARP(); - * Called by the fundamental ethernet driver code to process a RARP - * request. + * Called by the fundamental ethernet driver code to process a RARP + * request. */ int processRARP(struct ether_header *ehdr,ushort size) { - struct arphdr *arpp; + struct arphdr *arpp; - arpp = (struct arphdr *)(ehdr+1); - self_ecs(arpp->hardware); - self_ecs(arpp->protocol); - self_ecs(arpp->operation); + arpp = (struct arphdr *)(ehdr+1); + self_ecs(arpp->hardware); + self_ecs(arpp->protocol); + self_ecs(arpp->operation); - switch(arpp->operation) { - case RARP_RESPONSE: - if (!memcmp((char *)arpp->targetha, (char *)BinEnetAddr,6)) { + switch(arpp->operation) { + case RARP_RESPONSE: + if(!memcmp((char *)arpp->targetha, (char *)BinEnetAddr,6)) { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_ARP) { - printf(" RARP Response from %d.%d.%d.%d\n", - arpp->senderia[0],arpp->senderia[1], - arpp->senderia[2],arpp->senderia[3]); - printf(" MY IP: from %d.%d.%d.%d\n", - arpp->targetia[0],arpp->targetia[1], - arpp->targetia[2],arpp->targetia[3]); - } + if(EtherVerbose & SHOW_ARP) { + printf(" RARP Response from %d.%d.%d.%d\n", + arpp->senderia[0],arpp->senderia[1], + arpp->senderia[2],arpp->senderia[3]); + printf(" MY IP: from %d.%d.%d.%d\n", + arpp->targetia[0],arpp->targetia[1], + arpp->targetia[2],arpp->targetia[3]); + } #endif - memcpy((char *)BinIpAddr, (char *)arpp->targetia,6); - } - break; - case RARP_REQUEST: - break; - default: - printf(" Invalid RARP operation: 0x%x\n",arpp->operation); - return(-1); - } - return(0); + memcpy((char *)BinIpAddr, (char *)arpp->targetia,6); + } + break; + case RARP_REQUEST: + break; + default: + printf(" Invalid RARP operation: 0x%x\n",arpp->operation); + return(-1); + } + return(0); } /* processARP(); - * Called by the fundamental ethernet driver code to process a ARP - * request. + * Called by the fundamental ethernet driver code to process a ARP + * request. */ char * processARP(struct ether_header *ehdr,ushort size) { - struct arphdr *arpp; - - arpp = (struct arphdr *)(ehdr+1); - self_ecs(arpp->hardware); - self_ecs(arpp->protocol); - self_ecs(arpp->operation); - - /* If the sender IP address is all zeroes, then assume this is - * an arp probe. If we are currently doing a probe, and the - * address we are probing matches the target IP address of this - * probe, then set a flag that will abort the current probe. - */ - if ((arpp->senderia[0] == 0) && (arpp->senderia[1] == 0) && - (arpp->senderia[2] == 0) && (arpp->senderia[3] == 0)) { - if (memcmp((char *)arpp->targetia,(char *)&probeIP,4) == 0) - probeAbort = 1; - } - - switch(arpp->operation) { - case ARP_REQUEST: - if (!memcmp((char *)arpp->targetia, (char *)BinIpAddr,4)) { - ArpStore(arpp->senderia,arpp->senderha); - SendArpResp(ehdr); - } - break; - case ARP_RESPONSE: - if (!memcmp((char *)arpp->targetia, (char *)BinIpAddr,4)) { - if (!memcmp((char *)arpp->targetia,(char *)arpp->senderia,4)) - printf("WARNING: IP %s may be in use on network\n",IPadd); - - ArpStore(arpp->senderia,arpp->senderha); - } - break; - default: - printf(" Invalid ARP operation: 0x%x\n",arpp->operation); - printPkt(ehdr,(int)size,ETHER_INCOMING); - return((char *)0); - } - return((char *)(arpp + 1)); + struct arphdr *arpp; + + arpp = (struct arphdr *)(ehdr+1); + self_ecs(arpp->hardware); + self_ecs(arpp->protocol); + self_ecs(arpp->operation); + + /* If the sender IP address is all zeroes, then assume this is + * an arp probe. If we are currently doing a probe, and the + * address we are probing matches the target IP address of this + * probe, then set a flag that will abort the current probe. + */ + if((arpp->senderia[0] == 0) && (arpp->senderia[1] == 0) && + (arpp->senderia[2] == 0) && (arpp->senderia[3] == 0)) { + if(memcmp((char *)arpp->targetia,(char *)&probeIP,4) == 0) { + probeAbort = 1; + } + } + + switch(arpp->operation) { + case ARP_REQUEST: + if(!memcmp((char *)arpp->targetia, (char *)BinIpAddr,4)) { + ArpStore(arpp->senderia,arpp->senderha); + SendArpResp(ehdr); + } + break; + case ARP_RESPONSE: + if(!memcmp((char *)arpp->targetia, (char *)BinIpAddr,4)) { + if(!memcmp((char *)arpp->targetia,(char *)arpp->senderia,4)) { + printf("WARNING: IP %s may be in use on network\n",IPadd); + } + + ArpStore(arpp->senderia,arpp->senderha); + } + break; + default: + printf(" Invalid ARP operation: 0x%x\n",arpp->operation); + printPkt(ehdr,(int)size,ETHER_INCOMING); + return((char *)0); + } + return((char *)(arpp + 1)); } /* sendGratuitousARP(): @@ -602,7 +607,7 @@ processARP(struct ether_header *ehdr,ushort size) void sendGratuitousArp(void) { - SendArpRequest(BinIpAddr,0); + SendArpRequest(BinIpAddr,0); } /* llas(): @@ -613,38 +618,39 @@ sendGratuitousArp(void) * To do this, we run a 32-bit CRC on the 6-byte MAC address, then add the * least significant 8 bits of that value to the base of the address * range. Each successive time this function is called, then increment - * by the least significant 4 bits of the LSB of the MAC. + * by the least significant 4 bits of the LSB of the MAC. */ -#define LLAD_BEGIN 0xa9fe0100 -#define LLAD_END 0xa9fefeff +#define LLAD_BEGIN 0xa9fe0100 +#define LLAD_END 0xa9fefeff static void llas(char *ipptr) { - static char beenhere; - static unsigned long llad; - unsigned long pseudorandval, tmp; - - if (beenhere == 0) { - pseudorandval = crc32(BinEnetAddr,6); - llad = LLAD_BEGIN + (pseudorandval & 0xff); - } - else { - pseudorandval = (unsigned long)(BinEnetAddr[5] & 0xf); - llad += pseudorandval; - if (llad >= LLAD_END) - llad = LLAD_BEGIN + pseudorandval + beenhere; - } - beenhere++; - - printf("LLAD: %d.%d.%d.%d\n", - (llad & 0xff000000) >> 24, (llad & 0xff0000) >> 16, - (llad & 0xff00) >> 8, (llad & 0xff)); - - tmp = ecl(llad); - - if (ipptr) - memcpy(ipptr,(char *)&tmp,4); + static char beenhere; + static unsigned long llad; + unsigned long pseudorandval, tmp; + + if(beenhere == 0) { + pseudorandval = crc32(BinEnetAddr,6); + llad = LLAD_BEGIN + (pseudorandval & 0xff); + } else { + pseudorandval = (unsigned long)(BinEnetAddr[5] & 0xf); + llad += pseudorandval; + if(llad >= LLAD_END) { + llad = LLAD_BEGIN + pseudorandval + beenhere; + } + } + beenhere++; + + printf("LLAD: %d.%d.%d.%d\n", + (llad & 0xff000000) >> 24, (llad & 0xff0000) >> 16, + (llad & 0xff00) >> 8, (llad & 0xff)); + + tmp = ecl(llad); + + if(ipptr) { + memcpy(ipptr,(char *)&tmp,4); + } } #endif |