diff options
Diffstat (limited to 'main/common/dhcpboot.c')
-rw-r--r-- | main/common/dhcpboot.c | 2135 |
1 files changed, 1085 insertions, 1050 deletions
diff --git a/main/common/dhcpboot.c b/main/common/dhcpboot.c index e0ded6a..12a02ed 100644 --- a/main/common/dhcpboot.c +++ b/main/common/dhcpboot.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 @@ -35,12 +35,12 @@ * client issues a DHCP_REQUEST and server responds with a DHCP_ACK. * DISCOVER: request by the client to broadcast the fact that it is looking * for a DHCP server. - * OFFER: reply from the server when it receives a DISCOVER request from - * a client. The offer may contain all the information that the DHCP - * client needs to bootup, but this is dependent on the configuration of - * the server. + * OFFER: reply from the server when it receives a DISCOVER request from + * a client. The offer may contain all the information that the DHCP + * client needs to bootup, but this is dependent on the configuration of + * the server. * REQUEST: request by the client for the server (now known because an OFFER - * was received) to send it the information it needs. + * was received) to send it the information it needs. * ACK: reply from the server with the information requested. * * NOTE: this file contains a generic DHCP client supporting "automatic @@ -56,12 +56,12 @@ * (default is dhcp_00.c). Bottom line... there should be no need to modify * this file for application-specific stuff; if there is, please let me know. * - * NOTE1: the shell variable IPADD can also be set to DHCPV or DHCPv to + * NOTE1: the shell variable IPADD can also be set to DHCPV or DHCPv to * enable different levels of verbosity during DHCP transactions... 'V' * is full DHCP verbosity and 'v' only prints the DhcpSetEnv() calls. * * NOTE2: this file supports DHCP and BOOTP. Most of the function names - * refer to DHCP even though their functionality is shared by both DHCP + * refer to DHCP even though their functionality is shared by both DHCP * and BOOTP. This is because I wrote this originally for DHCP, then added * the hooks for BOOTP... Bottom line: don't let the names confuse you! * @@ -81,1248 +81,1283 @@ #include "cli.h" #include "timer.h" -int DHCPStartup(short), BOOTPStartup(short); +int DHCPStartup(short), BOOTPStartup(short); int DhcpSetEnv(char *,char *); int SendDHCPDiscover(int,short); void dhcpDumpVsa(void), printDhcpOptions(uchar *); -unsigned short DHCPState; +unsigned short DHCPState; #if INCLUDE_DHCPBOOT static struct elapsed_tmr dhcpTmr; -static int DHCPCommandIssued; -static ulong DHCPTransactionId; +static int DHCPCommandIssued; +static ulong DHCPTransactionId; /* Variables used for DHCP Class ID specification: */ -static char *DHCPClassId; -static int DHCPClassIdSize; +static char *DHCPClassId; +static int DHCPClassIdSize; /* Variables used for DHCP Client ID specification: */ -static char DHCPClientId[32]; -static int DHCPClientIdSize, DHCPClientIdType; +static char DHCPClientId[32]; +static int DHCPClientIdSize, DHCPClientIdType; /* Variables used for setting up a DHCP Parameter Request List: */ -static uchar DHCPRequestList[32]; -static int DHCPRqstListSize; +static uchar DHCPRequestList[32]; +static int DHCPRqstListSize; /* Variable to keep track of elapsed seconds since DHCP started: */ -static short DHCPElapsedSecs; +static short DHCPElapsedSecs; char *DhcpHelp[] = { - "Issue a DHCP discover", - "-[brvV] [vsa]", + "Issue a DHCP discover", + "-[brvV] [vsa]", #if INCLUDE_VERBOSEHELP - "Options...", - " -b use bootp", - " -r retry", - " -v|V verbosity", + "Options...", + " -b use bootp", + " -r retry", + " -v|V verbosity", #endif - 0, + 0, }; int Dhcp(int argc,char *argv[]) { - int opt, bootp; - - bootp = 0; - DHCPCommandIssued = 1; - while ((opt=getopt(argc,argv,"brvV")) != -1) { - switch(opt) { - case 'b': - bootp = 1; - break; - case 'r': - DHCPCommandIssued = 0; - break; + int opt, bootp; + + bootp = 0; + DHCPCommandIssued = 1; + while((opt=getopt(argc,argv,"brvV")) != -1) { + switch(opt) { + case 'b': + bootp = 1; + break; + case 'r': + DHCPCommandIssued = 0; + break; #if INCLUDE_ETHERVERBOSE - case 'v': - EtherVerbose = SHOW_DHCP; - break; - case 'V': - EtherVerbose = DHCP_VERBOSE; - break; + case 'v': + EtherVerbose = SHOW_DHCP; + break; + case 'V': + EtherVerbose = DHCP_VERBOSE; + break; #endif - default: - return(CMD_PARAM_ERROR); - } - } - - if (argc == optind+1) { - if (!strcmp(argv[optind],"vsa")) { - dhcpDumpVsa(); - return(CMD_SUCCESS); - } - else - return(CMD_PARAM_ERROR); - } - else if (argc != optind) - return(CMD_PARAM_ERROR); - - startElapsedTimer(&dhcpTmr,RetransmitDelay(DELAY_INIT_DHCP)*1000); - - if (bootp) { - DHCPState = BOOTPSTATE_INITIALIZE; - if (DHCPCommandIssued) - BOOTPStartup(0); - } - else { - DHCPState = DHCPSTATE_INITIALIZE; - if (DHCPCommandIssued) - DHCPStartup(0); - } - return(CMD_SUCCESS); + default: + return(CMD_PARAM_ERROR); + } + } + + if(argc == optind+1) { + if(!strcmp(argv[optind],"vsa")) { + dhcpDumpVsa(); + return(CMD_SUCCESS); + } else { + return(CMD_PARAM_ERROR); + } + } else if(argc != optind) { + return(CMD_PARAM_ERROR); + } + + startElapsedTimer(&dhcpTmr,RetransmitDelay(DELAY_INIT_DHCP)*1000); + + if(bootp) { + DHCPState = BOOTPSTATE_INITIALIZE; + if(DHCPCommandIssued) { + BOOTPStartup(0); + } + } else { + DHCPState = DHCPSTATE_INITIALIZE; + if(DHCPCommandIssued) { + DHCPStartup(0); + } + } + return(CMD_SUCCESS); } /* dhcpDumpVsa(): - * Simply dump the content of the VSA shell variable in DHCP format. - * The variable content is stored in ascii and must be converted to binary - * prior to calling printDhcpOptions(). + * Simply dump the content of the VSA shell variable in DHCP format. + * The variable content is stored in ascii and must be converted to binary + * prior to calling printDhcpOptions(). */ void dhcpDumpVsa(void) { - int i; - char tmp[3], *vsa_b, *vsa_a, len; - - vsa_a = getenv("DHCPVSA"); - if ((!vsa_a) || (!strcmp(vsa_a,"TRUE"))) - return; - len = strlen(vsa_a); - vsa_b = malloc(len); - if (!vsa_b) - return; - - len >>= 1; - tmp[2] = 0; - for(i=0;i<len;i++) { - tmp[0] = *vsa_a++; - tmp[1] = *vsa_a++; - vsa_b[i] = (char)strtol(tmp,0,16); - } - /* First 4 bytes of DHCPVSA is the cookie, so skip over that. */ - printDhcpOptions((unsigned char *)vsa_b+4); - free(vsa_b); + int i; + char tmp[3], *vsa_b, *vsa_a, len; + + vsa_a = getenv("DHCPVSA"); + if((!vsa_a) || (!strcmp(vsa_a,"TRUE"))) { + return; + } + len = strlen(vsa_a); + vsa_b = malloc(len); + if(!vsa_b) { + return; + } + + len >>= 1; + tmp[2] = 0; + for(i=0; i<len; i++) { + tmp[0] = *vsa_a++; + tmp[1] = *vsa_a++; + vsa_b[i] = (char)strtol(tmp,0,16); + } + /* First 4 bytes of DHCPVSA is the cookie, so skip over that. */ + printDhcpOptions((unsigned char *)vsa_b+4); + free(vsa_b); } void dhcpDisable() { - DHCPState = DHCPSTATE_NOTUSED; + DHCPState = DHCPSTATE_NOTUSED; } /* DHCPStartup(): - * This function is called at the point in which the ethernet interface is - * started if, and only if, the IPADD shell variable is set to DHCP. - * In older version of DHCP, the default was to use "LUCENT.PPA.1.1" as - * the default vcid. Now it is only used if specified in the shell variable - * DHCPCLASSID. The same strategy applies to DHCPCLIENTID. + * This function is called at the point in which the ethernet interface is + * started if, and only if, the IPADD shell variable is set to DHCP. + * In older version of DHCP, the default was to use "LUCENT.PPA.1.1" as + * the default vcid. Now it is only used if specified in the shell variable + * DHCPCLASSID. The same strategy applies to DHCPCLIENTID. */ int DHCPStartup(short seconds) { - char *id, *colon, *rlist; + char *id, *colon, *rlist; #if !INCLUDE_TFTP - printf("WARNING: DHCP can't load bootfile, TFTP not built into monitor.\n"); + printf("WARNING: DHCP can't load bootfile, TFTP not built into monitor.\n"); #endif - /* The format of DHCPCLASSID is simply a string of characters. */ - id = getenv("DHCPCLASSID"); - if (id) - DHCPClassId = id; - else - DHCPClassId = ""; - DHCPClassIdSize = strlen(DHCPClassId); - - /* The format of DHCPCLIENTID is "TYPE:ClientID" where 'TYPE is a - * decimal number ranging from 1-255 used as the "type" portion of - * the option, and ClientID is a string of ascii-coded hex pairs - * that are converted to binary and used as the client identifier. - */ - id = getenv("DHCPCLIENTID"); - if (id) { - colon = strchr(id,':'); - if ((colon) && (!(strlen(colon+1) & 1))) { - DHCPClientIdType = atoi(id); - colon++; - for(DHCPClientIdSize=0;*colon;DHCPClientIdSize++) { - uchar tmp; - - tmp = colon[2]; - colon[2] = 0; - DHCPClientId[DHCPClientIdSize] = (uchar)strtol(colon,0,16); - colon[2] = tmp; - colon+=2; - } - } - } - else - DHCPClientIdSize = 0; - - /* The format of DHCPRQSTLIST is #:#:#:#:# where each '#' is a decimal - * number representing a parameter to be requested via the Parameter - * Request List option... - */ - rlist = getenv("DHCPRQSTLIST"); - if (rlist) { - DHCPRqstListSize = 0; - colon = rlist; - while(*colon) { - if (*colon++ == ':') - DHCPRqstListSize++; - } - if (DHCPRqstListSize > sizeof(DHCPRequestList)) { - printf("DHCPRQSTLIST too big.\n"); - DHCPRqstListSize = 0; - } - else { - char *rqst; - - DHCPRqstListSize = 0; - rqst = rlist; - while(1) { - DHCPRequestList[DHCPRqstListSize++] = strtol(rqst,&colon,0); - if (*colon != ':') - break; - rqst = colon+1; - } - DHCPRequestList[DHCPRqstListSize] = 0; - } - } - else - DHCPRqstListSize = 0; - - return(SendDHCPDiscover(0,seconds)); + /* The format of DHCPCLASSID is simply a string of characters. */ + id = getenv("DHCPCLASSID"); + if(id) { + DHCPClassId = id; + } else { + DHCPClassId = ""; + } + DHCPClassIdSize = strlen(DHCPClassId); + + /* The format of DHCPCLIENTID is "TYPE:ClientID" where 'TYPE is a + * decimal number ranging from 1-255 used as the "type" portion of + * the option, and ClientID is a string of ascii-coded hex pairs + * that are converted to binary and used as the client identifier. + */ + id = getenv("DHCPCLIENTID"); + if(id) { + colon = strchr(id,':'); + if((colon) && (!(strlen(colon+1) & 1))) { + DHCPClientIdType = atoi(id); + colon++; + for(DHCPClientIdSize=0; *colon; DHCPClientIdSize++) { + uchar tmp; + + tmp = colon[2]; + colon[2] = 0; + DHCPClientId[DHCPClientIdSize] = (uchar)strtol(colon,0,16); + colon[2] = tmp; + colon+=2; + } + } + } else { + DHCPClientIdSize = 0; + } + + /* The format of DHCPRQSTLIST is #:#:#:#:# where each '#' is a decimal + * number representing a parameter to be requested via the Parameter + * Request List option... + */ + rlist = getenv("DHCPRQSTLIST"); + if(rlist) { + DHCPRqstListSize = 0; + colon = rlist; + while(*colon) { + if(*colon++ == ':') { + DHCPRqstListSize++; + } + } + if(DHCPRqstListSize > sizeof(DHCPRequestList)) { + printf("DHCPRQSTLIST too big.\n"); + DHCPRqstListSize = 0; + } else { + char *rqst; + + DHCPRqstListSize = 0; + rqst = rlist; + while(1) { + DHCPRequestList[DHCPRqstListSize++] = strtol(rqst,&colon,0); + if(*colon != ':') { + break; + } + rqst = colon+1; + } + DHCPRequestList[DHCPRqstListSize] = 0; + } + } else { + DHCPRqstListSize = 0; + } + + return(SendDHCPDiscover(0,seconds)); } int BOOTPStartup(short seconds) { - return(SendDHCPDiscover(1,seconds)); + return(SendDHCPDiscover(1,seconds)); } uchar * dhcpLoadShellVarOpts(uchar *options) { - if (DHCPClassIdSize) { - *options++ = DHCPOPT_CLASSID; - *options++ = DHCPClassIdSize; - memcpy((char *)options, (char *)DHCPClassId, DHCPClassIdSize); - options += DHCPClassIdSize; - } - if (DHCPClientIdSize) { - *options++ = DHCPOPT_CLIENTID; - *options++ = DHCPClientIdSize+1; - *options++ = DHCPClientIdType; - memcpy((char *)options, (char *)DHCPClientId, DHCPClientIdSize); - options += DHCPClientIdSize; - } - if (DHCPRqstListSize) { - *options++ = DHCPOPT_PARMRQSTLIST; - *options++ = DHCPRqstListSize; - memcpy((char *)options, (char *)DHCPRequestList, DHCPRqstListSize); - options += DHCPRqstListSize; - } - return(options); + if(DHCPClassIdSize) { + *options++ = DHCPOPT_CLASSID; + *options++ = DHCPClassIdSize; + memcpy((char *)options, (char *)DHCPClassId, DHCPClassIdSize); + options += DHCPClassIdSize; + } + if(DHCPClientIdSize) { + *options++ = DHCPOPT_CLIENTID; + *options++ = DHCPClientIdSize+1; + *options++ = DHCPClientIdType; + memcpy((char *)options, (char *)DHCPClientId, DHCPClientIdSize); + options += DHCPClientIdSize; + } + if(DHCPRqstListSize) { + *options++ = DHCPOPT_PARMRQSTLIST; + *options++ = DHCPRqstListSize; + memcpy((char *)options, (char *)DHCPRequestList, DHCPRqstListSize); + options += DHCPRqstListSize; + } + return(options); } /* SendDHCPDiscover() - * The DHCPDISCOVER is issued as an ethernet broadcast. IF the bootp - * flag is non-zero then just do a bootp request (a subset of the - * DHCPDISCOVER stuff). + * The DHCPDISCOVER is issued as an ethernet broadcast. IF the bootp + * flag is non-zero then just do a bootp request (a subset of the + * DHCPDISCOVER stuff). */ int SendDHCPDiscover(int bootp,short seconds) { - struct dhcphdr *dhcpdata; - struct bootphdr *bootpdata; - struct ether_header *te; - struct ip *ti; - struct Udphdr *tu; - ushort uh_ulen; - int optlen; - char *dhcpflags; - ulong cookie; - uchar *dhcpOptions, *dhcpOptionsBase; - - /* Retrieve an ethernet buffer from the driver and populate the - * ethernet level of packet: - */ - 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_IP); - - /* Move to the IP portion of the packet and populate it appropriately: */ - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; - ti->ip_id = 0; - ti->ip_off = ecs(0x4000); /* No fragmentation allowed */ - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memset((char *)&ti->ip_src.s_addr,0,4); - memset((char *)&ti->ip_dst.s_addr,0xff,4); - - /* Now udp... */ - tu = (struct Udphdr *) (ti + 1); - tu->uh_sport = ecs(DhcpClientPort); - tu->uh_dport = ecs(DhcpServerPort); - - /* First the stuff that is the same for BOOTP or DHCP... */ - bootpdata = (struct bootphdr *)(tu+1); - dhcpdata = (struct dhcphdr *)(tu+1); - dhcpdata->op = DHCPBOOTP_REQUEST; - dhcpdata->htype = 1; - dhcpdata->hlen = 6; - dhcpdata->hops = 0; - dhcpdata->seconds = ecs(seconds); - memset((char *)dhcpdata->bootfile,0,sizeof(dhcpdata->bootfile)); - memset((char *)dhcpdata->server_hostname,0,sizeof(dhcpdata->server_hostname)); - - /* For the first DHCPDISCOVER issued, establish a transaction id based - * on a crc32 of the mac address. For each DHCPDISCOVER after that, - * just increment. - */ - if (!DHCPTransactionId) - DHCPTransactionId = crc32(BinEnetAddr,6); - else - DHCPTransactionId++; - - memcpy((char *)&dhcpdata->transaction_id,(char *)&DHCPTransactionId,4); - memset((char *)&dhcpdata->client_ip,0,4); - memset((char *)&dhcpdata->your_ip,0,4); - memset((char *)&dhcpdata->server_ip,0,4); - memset((char *)&dhcpdata->router_ip,0,4); - memcpy((char *)dhcpdata->client_macaddr, (char *)BinEnetAddr,6); - dhcpflags = getenv("DHCPFLAGS"); - if (dhcpflags) /* 0x8000 is the only bit used currently. */ - dhcpdata->flags = (ushort)strtoul(dhcpflags,0,0); - else - dhcpdata->flags = 0; - - self_ecs(dhcpdata->flags); - - /* Finally, the DHCP or BOOTP specific stuff... - * Based on RFC1534 (Interoperation Between DHCP and BOOTP), any message - * received by a DHCP server that contains a 'DHCP_MESSAGETYPE' option - * is assumed to have been sent by a DHCP client. A message without the - * DHCP_MESSAGETYPE option is assumed to have been sent by a BOOTP - * client. - */ - uh_ulen = optlen = 0; - if (bootp) { - memset((char *)bootpdata->vsa,0,sizeof(bootpdata->vsa)); - uh_ulen = sizeof(struct Udphdr) + sizeof(struct bootphdr); - tu->uh_ulen = ecs(uh_ulen); - } - else { - if (!buildDhcpHdr(dhcpdata)) { - /* The cookie should only be loaded at the start of the - * vendor specific area if vendor-specific options are present. - */ - cookie = ecl(STANDARD_MAGIC_COOKIE); - memcpy((char *)&dhcpdata->magic_cookie,(char *)&cookie,4); - dhcpOptionsBase = (uchar *)(dhcpdata+1); - dhcpOptions = dhcpOptionsBase; - *dhcpOptions++ = DHCPOPT_MESSAGETYPE; - *dhcpOptions++ = 1; - *dhcpOptions++ = DHCPDISCOVER; - dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions); - *dhcpOptions++ = 0xff; - - /* Calculate ip and udp lengths after all DHCP options are loaded - * so that the size is easily computed based on the value of the - * dhcpOptions pointer. Apparently, the minimum size of the - * options space is 64 bytes, we determined this simply because - * the DHCP server we are using complains if the size is smaller. - * Also, NULL out the space that is added to get a minimum option - * size of 64 bytes, - */ - optlen = dhcpOptions - dhcpOptionsBase; - if (optlen < 64) { - memset((char *)dhcpOptions,0,64-optlen); - optlen = 64; - } - uh_ulen = sizeof(struct Udphdr)+sizeof(struct dhcphdr)+optlen; - tu->uh_ulen = ecs(uh_ulen); - } - } - ti->ip_len = ecs((sizeof(struct ip) + uh_ulen)); - - ipChksum(ti); /* Compute checksum of ip hdr */ - udpChksum(ti); /* Compute UDP checksum */ - - if (bootp) { - DHCPState = BOOTPSTATE_REQUEST; - sendBuffer(BOOTPSIZE); - } - else { - DHCPState = DHCPSTATE_SELECT; - sendBuffer(DHCPSIZE+optlen); - } + struct dhcphdr *dhcpdata; + struct bootphdr *bootpdata; + struct ether_header *te; + struct ip *ti; + struct Udphdr *tu; + ushort uh_ulen; + int optlen; + char *dhcpflags; + ulong cookie; + uchar *dhcpOptions, *dhcpOptionsBase; + + /* Retrieve an ethernet buffer from the driver and populate the + * ethernet level of packet: + */ + 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_IP); + + /* Move to the IP portion of the packet and populate it appropriately: */ + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; + ti->ip_id = 0; + ti->ip_off = ecs(0x4000); /* No fragmentation allowed */ + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memset((char *)&ti->ip_src.s_addr,0,4); + memset((char *)&ti->ip_dst.s_addr,0xff,4); + + /* Now udp... */ + tu = (struct Udphdr *)(ti + 1); + tu->uh_sport = ecs(DhcpClientPort); + tu->uh_dport = ecs(DhcpServerPort); + + /* First the stuff that is the same for BOOTP or DHCP... */ + bootpdata = (struct bootphdr *)(tu+1); + dhcpdata = (struct dhcphdr *)(tu+1); + dhcpdata->op = DHCPBOOTP_REQUEST; + dhcpdata->htype = 1; + dhcpdata->hlen = 6; + dhcpdata->hops = 0; + dhcpdata->seconds = ecs(seconds); + memset((char *)dhcpdata->bootfile,0,sizeof(dhcpdata->bootfile)); + memset((char *)dhcpdata->server_hostname,0,sizeof(dhcpdata->server_hostname)); + + /* For the first DHCPDISCOVER issued, establish a transaction id based + * on a crc32 of the mac address. For each DHCPDISCOVER after that, + * just increment. + */ + if(!DHCPTransactionId) { + DHCPTransactionId = crc32(BinEnetAddr,6); + } else { + DHCPTransactionId++; + } + + memcpy((char *)&dhcpdata->transaction_id,(char *)&DHCPTransactionId,4); + memset((char *)&dhcpdata->client_ip,0,4); + memset((char *)&dhcpdata->your_ip,0,4); + memset((char *)&dhcpdata->server_ip,0,4); + memset((char *)&dhcpdata->router_ip,0,4); + memcpy((char *)dhcpdata->client_macaddr, (char *)BinEnetAddr,6); + dhcpflags = getenv("DHCPFLAGS"); + if(dhcpflags) { /* 0x8000 is the only bit used currently. */ + dhcpdata->flags = (ushort)strtoul(dhcpflags,0,0); + } else { + dhcpdata->flags = 0; + } + + self_ecs(dhcpdata->flags); + + /* Finally, the DHCP or BOOTP specific stuff... + * Based on RFC1534 (Interoperation Between DHCP and BOOTP), any message + * received by a DHCP server that contains a 'DHCP_MESSAGETYPE' option + * is assumed to have been sent by a DHCP client. A message without the + * DHCP_MESSAGETYPE option is assumed to have been sent by a BOOTP + * client. + */ + uh_ulen = optlen = 0; + if(bootp) { + memset((char *)bootpdata->vsa,0,sizeof(bootpdata->vsa)); + uh_ulen = sizeof(struct Udphdr) + sizeof(struct bootphdr); + tu->uh_ulen = ecs(uh_ulen); + } else { + if(!buildDhcpHdr(dhcpdata)) { + /* The cookie should only be loaded at the start of the + * vendor specific area if vendor-specific options are present. + */ + cookie = ecl(STANDARD_MAGIC_COOKIE); + memcpy((char *)&dhcpdata->magic_cookie,(char *)&cookie,4); + dhcpOptionsBase = (uchar *)(dhcpdata+1); + dhcpOptions = dhcpOptionsBase; + *dhcpOptions++ = DHCPOPT_MESSAGETYPE; + *dhcpOptions++ = 1; + *dhcpOptions++ = DHCPDISCOVER; + dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions); + *dhcpOptions++ = 0xff; + + /* Calculate ip and udp lengths after all DHCP options are loaded + * so that the size is easily computed based on the value of the + * dhcpOptions pointer. Apparently, the minimum size of the + * options space is 64 bytes, we determined this simply because + * the DHCP server we are using complains if the size is smaller. + * Also, NULL out the space that is added to get a minimum option + * size of 64 bytes, + */ + optlen = dhcpOptions - dhcpOptionsBase; + if(optlen < 64) { + memset((char *)dhcpOptions,0,64-optlen); + optlen = 64; + } + uh_ulen = sizeof(struct Udphdr)+sizeof(struct dhcphdr)+optlen; + tu->uh_ulen = ecs(uh_ulen); + } + } + ti->ip_len = ecs((sizeof(struct ip) + uh_ulen)); + + ipChksum(ti); /* Compute checksum of ip hdr */ + udpChksum(ti); /* Compute UDP checksum */ + + if(bootp) { + DHCPState = BOOTPSTATE_REQUEST; + sendBuffer(BOOTPSIZE); + } else { + DHCPState = DHCPSTATE_SELECT; + sendBuffer(DHCPSIZE+optlen); + } #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - printf(" %s startup (%d elapsed secs)\n", - bootp ? "BOOTP" : "DHCP",seconds); + if(EtherVerbose & SHOW_DHCP) + printf(" %s startup (%d elapsed secs)\n", + bootp ? "BOOTP" : "DHCP",seconds); #endif - return(0); + return(0); } /* SendDHCPRequest() - * The DHCP request is broadcast back with the "server identifier" option - * set to indicate which server has been selected (in case more than one - * has offered). + * The DHCP request is broadcast back with the "server identifier" option + * set to indicate which server has been selected (in case more than one + * has offered). */ int SendDHCPRequest(struct dhcphdr *dhdr) { - uchar *op; - struct dhcphdr *dhcpdata; - struct ether_header *te; - struct ip *ti; - struct Udphdr *tu; - int optlen; - uchar *dhcpOptions, *dhcpOptionsBase; - ushort uh_ulen; - ulong cookie; - - 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_IP); - - ti = (struct ip *) (te + 1); - ti->ip_vhl = IP_HDR_VER_LEN; - ti->ip_tos = 0; - ti->ip_id = 0; - ti->ip_off = ecs(IP_DONTFRAG); /* No fragmentation allowed */ - ti->ip_ttl = UDP_TTL; - ti->ip_p = IP_UDP; - memset((char *)&ti->ip_src.s_addr,0,4); - memset((char *)&ti->ip_dst.s_addr,0xff,4); - - tu = (struct Udphdr *) (ti + 1); - tu->uh_sport = ecs(DhcpClientPort); - tu->uh_dport = ecs(DhcpServerPort); - - dhcpdata = (struct dhcphdr *)(tu+1); - dhcpdata->op = DHCPBOOTP_REQUEST; - dhcpdata->htype = 1; - dhcpdata->hlen = 6; - dhcpdata->hops = 0; - dhcpdata->seconds = ecs(DHCPElapsedSecs); - /* Use the same xid for the request as was used for the discover... - * (rfc2131 section 4.4.1) - */ - memcpy((char *)&dhcpdata->transaction_id,(char *)&dhdr->transaction_id,4); - - dhcpdata->flags = dhdr->flags; - memset((char *)&dhcpdata->client_ip,0,4); - memcpy((char *)&dhcpdata->your_ip,(char *)&dhdr->your_ip,4); - memset((char *)&dhcpdata->server_ip,0,4); - memset((char *)&dhcpdata->router_ip,0,4); - cookie = ecl(STANDARD_MAGIC_COOKIE); - memcpy((char *)&dhcpdata->magic_cookie,(char *)&cookie,4); - memcpy((char *)dhcpdata->client_macaddr, (char *)BinEnetAddr,6); - - dhcpOptionsBase = (uchar *)(dhcpdata+1); - dhcpOptions = dhcpOptionsBase; - *dhcpOptions++ = DHCPOPT_MESSAGETYPE; - *dhcpOptions++ = 1; - *dhcpOptions++ = DHCPREQUEST; - - *dhcpOptions++ = DHCPOPT_SERVERID; /* Server id ID */ - *dhcpOptions++ = 4; - op = DhcpGetOption(DHCPOPT_SERVERID,(uchar *)(dhdr+1)); - if (op) - memcpy((char *)dhcpOptions, (char *)op+2,4); - else - memset((char *)dhcpOptions, (char)0,4); - dhcpOptions+=4; - - *dhcpOptions++ = DHCPOPT_REQUESTEDIP; /* Requested IP */ - *dhcpOptions++ = 4; - memcpy((char *)dhcpOptions,(char *)&dhdr->your_ip,4); - dhcpOptions += 4; - dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions); - *dhcpOptions++ = 0xff; - - /* See note in SendDHCPDiscover() regarding the computation of the - * ip and udp lengths. - */ - optlen = dhcpOptions - dhcpOptionsBase; - if (optlen < 64) - optlen = 64; - uh_ulen = sizeof(struct Udphdr) + sizeof(struct dhcphdr) + optlen; - tu->uh_ulen = ecs(uh_ulen); - ti->ip_len = ecs((sizeof(struct ip) + uh_ulen)); - - ipChksum(ti); /* Compute checksum of ip hdr */ - udpChksum(ti); /* Compute UDP checksum */ - - DHCPState = DHCPSTATE_REQUEST; - sendBuffer(DHCPSIZE+optlen); - return(0); + uchar *op; + struct dhcphdr *dhcpdata; + struct ether_header *te; + struct ip *ti; + struct Udphdr *tu; + int optlen; + uchar *dhcpOptions, *dhcpOptionsBase; + ushort uh_ulen; + ulong cookie; + + 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_IP); + + ti = (struct ip *)(te + 1); + ti->ip_vhl = IP_HDR_VER_LEN; + ti->ip_tos = 0; + ti->ip_id = 0; + ti->ip_off = ecs(IP_DONTFRAG); /* No fragmentation allowed */ + ti->ip_ttl = UDP_TTL; + ti->ip_p = IP_UDP; + memset((char *)&ti->ip_src.s_addr,0,4); + memset((char *)&ti->ip_dst.s_addr,0xff,4); + + tu = (struct Udphdr *)(ti + 1); + tu->uh_sport = ecs(DhcpClientPort); + tu->uh_dport = ecs(DhcpServerPort); + + dhcpdata = (struct dhcphdr *)(tu+1); + dhcpdata->op = DHCPBOOTP_REQUEST; + dhcpdata->htype = 1; + dhcpdata->hlen = 6; + dhcpdata->hops = 0; + dhcpdata->seconds = ecs(DHCPElapsedSecs); + /* Use the same xid for the request as was used for the discover... + * (rfc2131 section 4.4.1) + */ + memcpy((char *)&dhcpdata->transaction_id,(char *)&dhdr->transaction_id,4); + + dhcpdata->flags = dhdr->flags; + memset((char *)&dhcpdata->client_ip,0,4); + memcpy((char *)&dhcpdata->your_ip,(char *)&dhdr->your_ip,4); + memset((char *)&dhcpdata->server_ip,0,4); + memset((char *)&dhcpdata->router_ip,0,4); + cookie = ecl(STANDARD_MAGIC_COOKIE); + memcpy((char *)&dhcpdata->magic_cookie,(char *)&cookie,4); + memcpy((char *)dhcpdata->client_macaddr, (char *)BinEnetAddr,6); + + dhcpOptionsBase = (uchar *)(dhcpdata+1); + dhcpOptions = dhcpOptionsBase; + *dhcpOptions++ = DHCPOPT_MESSAGETYPE; + *dhcpOptions++ = 1; + *dhcpOptions++ = DHCPREQUEST; + + *dhcpOptions++ = DHCPOPT_SERVERID; /* Server id ID */ + *dhcpOptions++ = 4; + op = DhcpGetOption(DHCPOPT_SERVERID,(uchar *)(dhdr+1)); + if(op) { + memcpy((char *)dhcpOptions, (char *)op+2,4); + } else { + memset((char *)dhcpOptions, (char)0,4); + } + dhcpOptions+=4; + + *dhcpOptions++ = DHCPOPT_REQUESTEDIP; /* Requested IP */ + *dhcpOptions++ = 4; + memcpy((char *)dhcpOptions,(char *)&dhdr->your_ip,4); + dhcpOptions += 4; + dhcpOptions = dhcpLoadShellVarOpts(dhcpOptions); + *dhcpOptions++ = 0xff; + + /* See note in SendDHCPDiscover() regarding the computation of the + * ip and udp lengths. + */ + optlen = dhcpOptions - dhcpOptionsBase; + if(optlen < 64) { + optlen = 64; + } + uh_ulen = sizeof(struct Udphdr) + sizeof(struct dhcphdr) + optlen; + tu->uh_ulen = ecs(uh_ulen); + ti->ip_len = ecs((sizeof(struct ip) + uh_ulen)); + + ipChksum(ti); /* Compute checksum of ip hdr */ + udpChksum(ti); /* Compute UDP checksum */ + + DHCPState = DHCPSTATE_REQUEST; + sendBuffer(DHCPSIZE+optlen); + return(0); } /* randomDhcpStartupDelay(): - * Randomize the startup for DHCP/BOOTP (see RFC2131 Sec 4.4.1)... - * Return a value between 1 and 10 based on the last 4 bits of the - * board's MAC address. - * The presence of the DHCPSTARTUPDELAY shell variable overrides - * this random value. + * Randomize the startup for DHCP/BOOTP (see RFC2131 Sec 4.4.1)... + * Return a value between 1 and 10 based on the last 4 bits of the + * board's MAC address. + * The presence of the DHCPSTARTUPDELAY shell variable overrides + * this random value. */ int randomDhcpStartupDelay(void) { - char *env; - int randomsec; - - env = getenv("DHCPSTARTUPDELAY"); - if (env) { - randomsec = (int)strtol(env,0,0); - } - else { - randomsec = (BinEnetAddr[5] & 0xf); - if (randomsec > 10) - randomsec -= 7; - else if (randomsec == 0) - randomsec = 10; - } - return(randomsec); + char *env; + int randomsec; + + env = getenv("DHCPSTARTUPDELAY"); + if(env) { + randomsec = (int)strtol(env,0,0); + } else { + randomsec = (BinEnetAddr[5] & 0xf); + if(randomsec > 10) { + randomsec -= 7; + } else if(randomsec == 0) { + randomsec = 10; + } + } + return(randomsec); } /* dhcpStateCheck(): - * Called by pollethernet() to monitor the progress of DHCPState. - * The retry rate is "almost" what is specified in the RFC... - * Refer to the RetransmitDelay() function for details. + * Called by pollethernet() to monitor the progress of DHCPState. + * The retry rate is "almost" what is specified in the RFC... + * Refer to the RetransmitDelay() function for details. * - * Regarding timing... - * The DHCP startup may be running without an accurate measure of elapsed - * time. The value of LoopsPerMillisecond is used as an approximation of - * the number of times this function must be called for one second to - * pass (dependent on network traffic, etc...). RetransmitDelay() is - * called to retrieve the number of seconds that must elapse prior to - * retransmitting the last DHCP message. The static variables in this - * function are used to keep track of that timeout. + * Regarding timing... + * The DHCP startup may be running without an accurate measure of elapsed + * time. The value of LoopsPerMillisecond is used as an approximation of + * the number of times this function must be called for one second to + * pass (dependent on network traffic, etc...). RetransmitDelay() is + * called to retrieve the number of seconds that must elapse prior to + * retransmitting the last DHCP message. The static variables in this + * function are used to keep track of that timeout. */ void dhcpStateCheck(void) { - int delaysecs; - - /* If the DHCP command has been issued, it is assumed that the script - * is handling retries... - */ - if (DHCPCommandIssued) - return; - - /* Return, restart or fall through; depending on DHCPState... */ - switch(DHCPState) { - case DHCPSTATE_NOTUSED: - case BOOTPSTATE_COMPLETE: - case DHCPSTATE_BOUND: - return; - case DHCPSTATE_RESTART: - DHCPStartup(0); - return; - case BOOTPSTATE_RESTART: - BOOTPStartup(0); - return; - case DHCPSTATE_INITIALIZE: - case BOOTPSTATE_INITIALIZE: - delaysecs = randomDhcpStartupDelay(); - startElapsedTimer(&dhcpTmr,delaysecs * 1000); + int delaysecs; + + /* If the DHCP command has been issued, it is assumed that the script + * is handling retries... + */ + if(DHCPCommandIssued) { + return; + } + + /* Return, restart or fall through; depending on DHCPState... */ + switch(DHCPState) { + case DHCPSTATE_NOTUSED: + case BOOTPSTATE_COMPLETE: + case DHCPSTATE_BOUND: + return; + case DHCPSTATE_RESTART: + DHCPStartup(0); + return; + case BOOTPSTATE_RESTART: + BOOTPStartup(0); + return; + case DHCPSTATE_INITIALIZE: + case BOOTPSTATE_INITIALIZE: + delaysecs = randomDhcpStartupDelay(); + startElapsedTimer(&dhcpTmr,delaysecs * 1000); #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - printf("\nDHCP/BOOTP %d sec startup delay...\n",delaysecs); + if(EtherVerbose & SHOW_DHCP) { + printf("\nDHCP/BOOTP %d sec startup delay...\n",delaysecs); + } #endif - if (DHCPState & BOOTP_MODE) - DHCPState = BOOTPSTATE_INITDELAY; - else - DHCPState = DHCPSTATE_INITDELAY; - return; - case DHCPSTATE_INITDELAY: - case BOOTPSTATE_INITDELAY: - if (msecElapsed(&dhcpTmr) || (gotachar())) { - DHCPElapsedSecs = 0; - startElapsedTimer(&dhcpTmr, - RetransmitDelay(DELAY_INIT_DHCP)*1000); - if (DHCPState & BOOTP_MODE) - BOOTPStartup(0); - else - DHCPStartup(0); - } - return; - default: - break; - } - - if (msecElapsed(&dhcpTmr)) { - int lastdelay; - - lastdelay = RetransmitDelay(DELAY_RETURN); - delaysecs = RetransmitDelay(DELAY_INCREMENT); - - if (delaysecs != RETRANSMISSION_TIMEOUT) { - DHCPElapsedSecs += delaysecs; - startElapsedTimer(&dhcpTmr,delaysecs*1000); - - if (DHCPState & BOOTP_MODE) - BOOTPStartup(DHCPElapsedSecs); - else - DHCPStartup(DHCPElapsedSecs); + if(DHCPState & BOOTP_MODE) { + DHCPState = BOOTPSTATE_INITDELAY; + } else { + DHCPState = DHCPSTATE_INITDELAY; + } + return; + case DHCPSTATE_INITDELAY: + case BOOTPSTATE_INITDELAY: + if(msecElapsed(&dhcpTmr) || (gotachar())) { + DHCPElapsedSecs = 0; + startElapsedTimer(&dhcpTmr, + RetransmitDelay(DELAY_INIT_DHCP)*1000); + if(DHCPState & BOOTP_MODE) { + BOOTPStartup(0); + } else { + DHCPStartup(0); + } + } + return; + default: + break; + } + + if(msecElapsed(&dhcpTmr)) { + int lastdelay; + + lastdelay = RetransmitDelay(DELAY_RETURN); + delaysecs = RetransmitDelay(DELAY_INCREMENT); + + if(delaysecs != RETRANSMISSION_TIMEOUT) { + DHCPElapsedSecs += delaysecs; + startElapsedTimer(&dhcpTmr,delaysecs*1000); + + if(DHCPState & BOOTP_MODE) { + BOOTPStartup(DHCPElapsedSecs); + } else { + DHCPStartup(DHCPElapsedSecs); + } #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - printf(" DHCP/BOOTP retry (%d secs)\n",lastdelay); + if(EtherVerbose & SHOW_DHCP) { + printf(" DHCP/BOOTP retry (%d secs)\n",lastdelay); + } #endif - } - else { + } else { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - printf(" DHCP/BOOTP giving up\n"); + if(EtherVerbose & SHOW_DHCP) { + printf(" DHCP/BOOTP giving up\n"); + } #endif - } - } + } + } } /* xidCheck(): - * Common function used for DHCP and BOOTP to verify incoming transaction - * id... + * Common function used for DHCP and BOOTP to verify incoming transaction + * id... */ int xidCheck(char *id,int bootp) { - if (memcmp(id,(char *)&DHCPTransactionId,4)) { + if(memcmp(id,(char *)&DHCPTransactionId,4)) { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) { - printf("%s ignored: unexpected transaction id.\n", - bootp ? "BOOTP":"DHCP"); - } + if(EtherVerbose & SHOW_DHCP) { + printf("%s ignored: unexpected transaction id.\n", + bootp ? "BOOTP":"DHCP"); + } #endif - return(-1); - } - return(0); + return(-1); + } + return(0); } int loadBootFile(int bootp) { #if INCLUDE_TFTP - ulong addr; - char bfile[TFSNAMESIZE+TFSINFOSIZE+32]; - char *tfsfile, *bootfile, *tftpsrvr, *flags, *info; - - /* If the DHCPDONTBOOT variable is present, then don't put - * the file in TFS and don't run it. Just complete the TFTP - * transfer, and allow the user to deal with the downloaded - * data using APPRAMBASE and TFTPGET shell variables (probably - * through some boot script). - */ - if (getenv("DHCPDONTBOOT")) - tfsfile = (char *)0; - else - tfsfile = bfile; - - /* If both bootfile and server-ip are specified, then boot it. - * The name of the file must contain information that tells the monitor - * what type of file it is, so the first 'comma' extension is used as - * the flag field (if it is a valid flag set) and the second 'comma' - * extension is used as the info field. - */ - bootfile = getenv("BOOTFILE"); - tftpsrvr = getenv("BOOTSRVR"); - - if (bootfile && tftpsrvr) { - int tftpworked; - - addr = getAppRamStart(); - info = ""; - flags = "e"; - strncpy(bfile,bootfile,sizeof(bfile)); - - if (tfsfile) { - char *icomma, *fcomma; - - fcomma = strchr(bfile,','); - if (fcomma) { - icomma = strchr(fcomma+1,','); - if (icomma) { - *icomma = 0; - info = icomma+1; - } - *fcomma = 0; - if (tfsctrl(TFS_FATOB,(long)(fcomma+1),0) != 0) - flags = fcomma+1; - } - } - - /* Since we are about to transition to TFTP, match TFTP's - * verbosity to the verbosity currently set for DHCP... - */ + ulong addr; + char bfile[TFSNAMESIZE+TFSINFOSIZE+32]; + char *tfsfile, *bootfile, *tftpsrvr, *flags, *info; + + /* If the DHCPDONTBOOT variable is present, then don't put + * the file in TFS and don't run it. Just complete the TFTP + * transfer, and allow the user to deal with the downloaded + * data using APPRAMBASE and TFTPGET shell variables (probably + * through some boot script). + */ + if(getenv("DHCPDONTBOOT")) { + tfsfile = (char *)0; + } else { + tfsfile = bfile; + } + + /* If both bootfile and server-ip are specified, then boot it. + * The name of the file must contain information that tells the monitor + * what type of file it is, so the first 'comma' extension is used as + * the flag field (if it is a valid flag set) and the second 'comma' + * extension is used as the info field. + */ + bootfile = getenv("BOOTFILE"); + tftpsrvr = getenv("BOOTSRVR"); + + if(bootfile && tftpsrvr) { + int tftpworked; + + addr = getAppRamStart(); + info = ""; + flags = "e"; + strncpy(bfile,bootfile,sizeof(bfile)); + + if(tfsfile) { + char *icomma, *fcomma; + + fcomma = strchr(bfile,','); + if(fcomma) { + icomma = strchr(fcomma+1,','); + if(icomma) { + *icomma = 0; + info = icomma+1; + } + *fcomma = 0; + if(tfsctrl(TFS_FATOB,(long)(fcomma+1),0) != 0) { + flags = fcomma+1; + } + } + } + + /* Since we are about to transition to TFTP, match TFTP's + * verbosity to the verbosity currently set for DHCP... + */ #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - EtherVerbose |= SHOW_TFTP_STATE; + if(EtherVerbose & SHOW_DHCP) { + EtherVerbose |= SHOW_TFTP_STATE; + } #endif - /* If the TFTP transfer succeeds, attempt to run the boot file; - * if the TFTP transfer fails, then re-initialize the tftp state - * and set the DHCP state such that dhcpStateCheck() will - * cause the handshake to start over again... - */ - tftpworked = tftpGet(addr,tftpsrvr,"octet",bfile,tfsfile,flags,info); - if (tftpworked) { + /* If the TFTP transfer succeeds, attempt to run the boot file; + * if the TFTP transfer fails, then re-initialize the tftp state + * and set the DHCP state such that dhcpStateCheck() will + * cause the handshake to start over again... + */ + tftpworked = tftpGet(addr,tftpsrvr,"octet",bfile,tfsfile,flags,info); + if(tftpworked) { #if INCLUDE_ETHERVERBOSE - EtherVerbose = 0; + EtherVerbose = 0; #endif - if (tfsfile) { - int err; - char *argv[2]; - - argv[0] = bfile; - argv[1] = 0; - err = tfsrun(argv,0); - if (err != TFS_OKAY) - printf("DHCP-invoked tfsrun(%s) failed: %s\n", - bfile,tfserrmsg(err)); - } - } - else { - tftpInit(); - RetransmitDelay(DELAY_INIT_TFTP); + if(tfsfile) { + int err; + char *argv[2]; + + argv[0] = bfile; + argv[1] = 0; + err = tfsrun(argv,0); + if(err != TFS_OKAY) + printf("DHCP-invoked tfsrun(%s) failed: %s\n", + bfile,tfserrmsg(err)); + } + } else { + tftpInit(); + RetransmitDelay(DELAY_INIT_TFTP); #if INCLUDE_ETHERVERBOSE - EtherVerbose &= ~SHOW_TFTP_STATE; + EtherVerbose &= ~SHOW_TFTP_STATE; #endif - if (bootp) - DHCPState = BOOTPSTATE_RESTART; - else - DHCPState = DHCPSTATE_RESTART; - } - } + if(bootp) { + DHCPState = BOOTPSTATE_RESTART; + } else { + DHCPState = DHCPSTATE_RESTART; + } + } + } #if INCLUDE_ETHERVERBOSE - else - EtherVerbose &= ~(SHOW_DHCP|DHCP_VERBOSE); + else { + EtherVerbose &= ~(SHOW_DHCP|DHCP_VERBOSE); + } #endif #endif - return(0); + return(0); } /* processBOOTP(): - * A subset of processDHCP(). - * We get here from processDHCP, because it detects that the current - * value of DHCPState is BOOTPSTATE_REQUEST. + * A subset of processDHCP(). + * We get here from processDHCP, because it detects that the current + * value of DHCPState is BOOTPSTATE_REQUEST. */ int processBOOTP(struct ether_header *ehdr,ushort size) { - struct ip *ihdr; - struct Udphdr *uhdr; - struct bootphdr *bhdr; - ulong ip, temp_ip, cookie; - uchar buf[16], *op; + struct ip *ihdr; + struct Udphdr *uhdr; + struct bootphdr *bhdr; + ulong ip, temp_ip, cookie; + uchar buf[16], *op; #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_HEX) - printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII); + if(EtherVerbose & SHOW_HEX) { + printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII); + } #endif - ihdr = (struct ip *)(ehdr + 1); - uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); - bhdr = (struct bootphdr *)(uhdr+1); - - /* Verify incoming transaction id matches the previous outgoing value: */ - if (xidCheck((char *)&bhdr->transaction_id,1) < 0) - return(-1); - - /* If bootfile is nonzero, store it into BOOTFILE shell var: */ - if (bhdr->bootfile[0]) - DhcpSetEnv("BOOTFILE", (char *)bhdr->bootfile); - - /* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */ - memcpy((char *)&temp_ip,(char *)&bhdr->server_ip,4); - if (temp_ip) - DhcpSetEnv("BOOTSRVR",(char *)IpToString(temp_ip,(char *)buf)); - - /* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */ - memcpy((char *)&temp_ip,(char *)&bhdr->router_ip,4); - if (temp_ip) - DhcpSetEnv("RLYAGNT",(char *)IpToString(temp_ip,(char *)buf)); - - /* Assign IP address loaded in "your_ip" to the IPADD shell var: */ - memcpy((char *)BinIpAddr,(char *)&bhdr->your_ip,4); - memcpy((char *)&temp_ip,(char *)&bhdr->your_ip,4); - DhcpSetEnv("IPADD",(char *)IpToString(temp_ip,(char *)buf)); - - /* If STANDARD_MAGIC_COOKIE exists, then process options... */ - memcpy((char *)&cookie,(char *)bhdr->vsa,4); - if (cookie == ecl(STANDARD_MAGIC_COOKIE)) { - /* Assign subnet mask option to NETMASK shell var (if found): */ - op = DhcpGetOption(DHCPOPT_SUBNETMASK,&bhdr->vsa[4]); - if (op) { - memcpy((char *)&ip,(char *)op+2,4); - DhcpSetEnv("NETMASK",(char *)IpToString(ip,(char *)buf)); - } - /* Assign first router option to GIPADD shell var (if found): */ - /* (the router option can have multiple entries, and they are */ - /* supposed to be in order of preference, so use the first one) */ - op = DhcpGetOption(DHCPOPT_ROUTER,&bhdr->vsa[4]); - if (op) { - memcpy((char *)&ip, (char *)op+2,4); - DhcpSetEnv("GIPADD",(char *)IpToString(ip,(char *)buf)); - } - } - - DhcpBootpDone(1,(struct dhcphdr *)bhdr, - size - ((int)((int)&bhdr->vsa - (int)ehdr))); - - DHCPState = BOOTPSTATE_COMPLETE; - - /* Call loadBootFile() which will then kick off a tftp client - * transfer if both BOOTFILE and BOOTSRVR shell variables are - * loaded; otherwise, we are done. - */ - loadBootFile(1); - - return(0); + ihdr = (struct ip *)(ehdr + 1); + uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); + bhdr = (struct bootphdr *)(uhdr+1); + + /* Verify incoming transaction id matches the previous outgoing value: */ + if(xidCheck((char *)&bhdr->transaction_id,1) < 0) { + return(-1); + } + + /* If bootfile is nonzero, store it into BOOTFILE shell var: */ + if(bhdr->bootfile[0]) { + DhcpSetEnv("BOOTFILE", (char *)bhdr->bootfile); + } + + /* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */ + memcpy((char *)&temp_ip,(char *)&bhdr->server_ip,4); + if(temp_ip) { + DhcpSetEnv("BOOTSRVR",(char *)IpToString(temp_ip,(char *)buf)); + } + + /* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */ + memcpy((char *)&temp_ip,(char *)&bhdr->router_ip,4); + if(temp_ip) { + DhcpSetEnv("RLYAGNT",(char *)IpToString(temp_ip,(char *)buf)); + } + + /* Assign IP address loaded in "your_ip" to the IPADD shell var: */ + memcpy((char *)BinIpAddr,(char *)&bhdr->your_ip,4); + memcpy((char *)&temp_ip,(char *)&bhdr->your_ip,4); + DhcpSetEnv("IPADD",(char *)IpToString(temp_ip,(char *)buf)); + + /* If STANDARD_MAGIC_COOKIE exists, then process options... */ + memcpy((char *)&cookie,(char *)bhdr->vsa,4); + if(cookie == ecl(STANDARD_MAGIC_COOKIE)) { + /* Assign subnet mask option to NETMASK shell var (if found): */ + op = DhcpGetOption(DHCPOPT_SUBNETMASK,&bhdr->vsa[4]); + if(op) { + memcpy((char *)&ip,(char *)op+2,4); + DhcpSetEnv("NETMASK",(char *)IpToString(ip,(char *)buf)); + } + /* Assign first router option to GIPADD shell var (if found): */ + /* (the router option can have multiple entries, and they are */ + /* supposed to be in order of preference, so use the first one) */ + op = DhcpGetOption(DHCPOPT_ROUTER,&bhdr->vsa[4]); + if(op) { + memcpy((char *)&ip, (char *)op+2,4); + DhcpSetEnv("GIPADD",(char *)IpToString(ip,(char *)buf)); + } + } + + DhcpBootpDone(1,(struct dhcphdr *)bhdr, + size - ((int)((int)&bhdr->vsa - (int)ehdr))); + + DHCPState = BOOTPSTATE_COMPLETE; + + /* Call loadBootFile() which will then kick off a tftp client + * transfer if both BOOTFILE and BOOTSRVR shell variables are + * loaded; otherwise, we are done. + */ + loadBootFile(1); + + return(0); } int processDHCP(struct ether_header *ehdr,ushort size) { - struct ip *ihdr; - struct Udphdr *uhdr; - struct dhcphdr *dhdr; - uchar buf[16], *op, msgtype; - ulong ip, temp_ip, leasetime; + struct ip *ihdr; + struct Udphdr *uhdr; + struct dhcphdr *dhdr; + uchar buf[16], *op, msgtype; + ulong ip, temp_ip, leasetime; - if (DHCPState == BOOTPSTATE_REQUEST) - return(processBOOTP(ehdr,size)); + if(DHCPState == BOOTPSTATE_REQUEST) { + return(processBOOTP(ehdr,size)); + } #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_HEX) - printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII); + if(EtherVerbose & SHOW_HEX) { + printMem((uchar *)ehdr,size,EtherVerbose & SHOW_ASCII); + } #endif - ihdr = (struct ip *)(ehdr + 1); - uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); - dhdr = (struct dhcphdr *)(uhdr+1); - - /* Verify incoming transaction id matches the previous outgoing value: */ - if (xidCheck((char *)&dhdr->transaction_id,0) < 0) - return(-1); - - op = DhcpGetOption(DHCPOPT_MESSAGETYPE,(uchar *)(dhdr+1)); - if (op) - msgtype = *(op+2); - else - msgtype = DHCPUNKNOWN; - - if ((DHCPState == DHCPSTATE_SELECT) && (msgtype == DHCPOFFER)) { - /* Target issued the DISCOVER, the incoming packet is the server's - * OFFER reply. The function "ValidDHCPOffer() will return - * non-zero if the request is to be sent. - */ - if (ValidDHCPOffer(dhdr)) - SendDHCPRequest(dhdr); + ihdr = (struct ip *)(ehdr + 1); + uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr)); + dhdr = (struct dhcphdr *)(uhdr+1); + + /* Verify incoming transaction id matches the previous outgoing value: */ + if(xidCheck((char *)&dhdr->transaction_id,0) < 0) { + return(-1); + } + + op = DhcpGetOption(DHCPOPT_MESSAGETYPE,(uchar *)(dhdr+1)); + if(op) { + msgtype = *(op+2); + } else { + msgtype = DHCPUNKNOWN; + } + + if((DHCPState == DHCPSTATE_SELECT) && (msgtype == DHCPOFFER)) { + /* Target issued the DISCOVER, the incoming packet is the server's + * OFFER reply. The function "ValidDHCPOffer() will return + * non-zero if the request is to be sent. + */ + if(ValidDHCPOffer(dhdr)) { + SendDHCPRequest(dhdr); + } #if INCLUDE_ETHERVERBOSE - else if (EtherVerbose & SHOW_DHCP) { - char ip[4]; - memcpy(ip,(char *)&ihdr->ip_src,4); - printf(" DHCP offer from %d.%d.%d.%d ignored\n", - ip[0],ip[1],ip[2],ip[3]); - } + else if(EtherVerbose & SHOW_DHCP) { + char ip[4]; + memcpy(ip,(char *)&ihdr->ip_src,4); + printf(" DHCP offer from %d.%d.%d.%d ignored\n", + ip[0],ip[1],ip[2],ip[3]); + } #endif - } - else if ((DHCPState == DHCPSTATE_REQUEST) && (msgtype == DHCPACK)) { - ulong cookie; - uchar ipsrc[4]; - - /* Target issued the REQUEST, the incoming packet is the server's - * ACK reply. We're done so load the environment now. - */ - memcpy((char *)ipsrc,(char *)&ihdr->ip_src,4); - shell_sprintf("DHCPOFFERFROM","%d.%d.%d.%d", - ipsrc[0],ipsrc[1],ipsrc[2],ipsrc[3]); - - /* If bootfile is nonzero, store it into BOOTFILE shell var: */ - if (dhdr->bootfile[0]) - DhcpSetEnv("BOOTFILE",(char *)dhdr->bootfile); - - /* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */ - memcpy((char *)&temp_ip,(char *)&dhdr->server_ip,4); - if (temp_ip) - DhcpSetEnv("BOOTSRVR",(char *)IpToString(temp_ip,(char *)buf)); - - /* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */ - memcpy((char *)&temp_ip,(char *)&dhdr->router_ip,4); - if (temp_ip) - DhcpSetEnv("RLYAGNT",(char *)IpToString(temp_ip,(char *)buf)); - - /* Assign IP address loaded in "your_ip" to the IPADD shell var: */ - memcpy((char *)BinIpAddr,(char *)&dhdr->your_ip,4); - memcpy((char *)&temp_ip,(char *)&dhdr->your_ip,4); - DhcpSetEnv("IPADD",IpToString(temp_ip,(char *)buf)); - - op = DhcpGetOption(DHCPOPT_ROOTPATH,(uchar *)(dhdr+1)); - if (op) - DhcpSetEnv("ROOTPATH",(char *)op+2); - - /* If STANDARD_MAGIC_COOKIE exists, process options... */ - memcpy((char *)&cookie,(char *)&dhdr->magic_cookie,4); - if (cookie == ecl(STANDARD_MAGIC_COOKIE)) { - /* Assign subnet mask to NETMASK shell var (if found): */ - op = DhcpGetOption(DHCPOPT_SUBNETMASK,(uchar *)(dhdr+1)); - if (op) { - memcpy((char *)&ip,(char *)op+2,4); - DhcpSetEnv("NETMASK",(char *)IpToString(ip,(char *)buf)); - } - - /* Assign Hostname to HOSTNAME shell var (if found): */ - op = DhcpGetOption(DHCPOPT_HOSTNAME,(uchar *)(dhdr+1)); - if (op) { - char tmpnam[64]; - int optlen = *(op+1); - - if (optlen < sizeof(tmpnam)-1) { - memset(tmpnam,0,sizeof(tmpnam)); - memcpy(tmpnam,(char *)(op+2),optlen); - DhcpSetEnv("HOSTNAME",tmpnam); - } - } - - /* Assign gateway IP to GIPADD shell var (if found): - * (the router option can have multiple entries, and they are - * supposed to be in order of preference, so use the first one). - */ - op = DhcpGetOption(DHCPOPT_ROUTER,(uchar *)(dhdr+1)); - if (op) { - memcpy((char *)&ip,(char *)op+2,4); - DhcpSetEnv("GIPADD",(char *)IpToString(ip,(char *)buf)); - } - /* Process DHCPOPT_LEASETIME option as follows... - * If not set, assume infinite and clear DHCPLEASETIME shellvar. - * If set, then look for the presence of the DHCPLEASETIME shell - * variable and use it as a minimum. If the incoming value is - * >= what is in the shell variable, accept it and load the shell - * variable with this value. If incoming lease time is less than - * what is stored in DHCPLEASETIME, ignore the request. - * If DHCPLEASETIME is not set, then just load the incoming lease - * into the DHCPLEASETIME shell variable and accept the offer. - */ - op = DhcpGetOption(DHCPOPT_LEASETIME,(uchar *)(dhdr+1)); - if (op) { - memcpy((char *)&leasetime,(char *)op+2,4); - leasetime = ecl(leasetime); - if (getenv("DHCPLEASETIME")) { - ulong minleasetime; - minleasetime = strtol(getenv("DHCPLEASETIME"),0,0); - if (leasetime < minleasetime) { - printf("DHCP: incoming lease time 0x%lx too small.\n", - leasetime); - return(-1); - } - } - sprintf((char *)buf,"0x%lx",leasetime); - setenv("DHCPLEASETIME",(char *)buf); - } - else - setenv("DHCPLEASETIME",(char *)0); - } - - /* Check for vendor specific stuff... */ - DhcpVendorSpecific(dhdr); - - DhcpBootpDone(0,dhdr, - size - ((int)((int)&dhdr->magic_cookie - (int)ehdr))); - - DHCPState = DHCPSTATE_BOUND; - - /* Call loadBootFile() which will then kick off a tftp client - * transfer if both BOOTFILE and BOOTSRVR shell variables are - * loaded; otherwise, we are done. - */ - loadBootFile(0); - } - return(0); + } else if((DHCPState == DHCPSTATE_REQUEST) && (msgtype == DHCPACK)) { + ulong cookie; + uchar ipsrc[4]; + + /* Target issued the REQUEST, the incoming packet is the server's + * ACK reply. We're done so load the environment now. + */ + memcpy((char *)ipsrc,(char *)&ihdr->ip_src,4); + shell_sprintf("DHCPOFFERFROM","%d.%d.%d.%d", + ipsrc[0],ipsrc[1],ipsrc[2],ipsrc[3]); + + /* If bootfile is nonzero, store it into BOOTFILE shell var: */ + if(dhdr->bootfile[0]) { + DhcpSetEnv("BOOTFILE",(char *)dhdr->bootfile); + } + + /* Assign IP "server_ip" to the BOOTSRVR shell var (if non-zero): */ + memcpy((char *)&temp_ip,(char *)&dhdr->server_ip,4); + if(temp_ip) { + DhcpSetEnv("BOOTSRVR",(char *)IpToString(temp_ip,(char *)buf)); + } + + /* Assign IP "router_ip" to the RLYAGNT shell var (if non-zero): */ + memcpy((char *)&temp_ip,(char *)&dhdr->router_ip,4); + if(temp_ip) { + DhcpSetEnv("RLYAGNT",(char *)IpToString(temp_ip,(char *)buf)); + } + + /* Assign IP address loaded in "your_ip" to the IPADD shell var: */ + memcpy((char *)BinIpAddr,(char *)&dhdr->your_ip,4); + memcpy((char *)&temp_ip,(char *)&dhdr->your_ip,4); + DhcpSetEnv("IPADD",IpToString(temp_ip,(char *)buf)); + + op = DhcpGetOption(DHCPOPT_ROOTPATH,(uchar *)(dhdr+1)); + if(op) { + DhcpSetEnv("ROOTPATH",(char *)op+2); + } + + /* If STANDARD_MAGIC_COOKIE exists, process options... */ + memcpy((char *)&cookie,(char *)&dhdr->magic_cookie,4); + if(cookie == ecl(STANDARD_MAGIC_COOKIE)) { + /* Assign subnet mask to NETMASK shell var (if found): */ + op = DhcpGetOption(DHCPOPT_SUBNETMASK,(uchar *)(dhdr+1)); + if(op) { + memcpy((char *)&ip,(char *)op+2,4); + DhcpSetEnv("NETMASK",(char *)IpToString(ip,(char *)buf)); + } + + /* Assign Hostname to HOSTNAME shell var (if found): */ + op = DhcpGetOption(DHCPOPT_HOSTNAME,(uchar *)(dhdr+1)); + if(op) { + char tmpnam[64]; + int optlen = *(op+1); + + if(optlen < sizeof(tmpnam)-1) { + memset(tmpnam,0,sizeof(tmpnam)); + memcpy(tmpnam,(char *)(op+2),optlen); + DhcpSetEnv("HOSTNAME",tmpnam); + } + } + + /* Assign gateway IP to GIPADD shell var (if found): + * (the router option can have multiple entries, and they are + * supposed to be in order of preference, so use the first one). + */ + op = DhcpGetOption(DHCPOPT_ROUTER,(uchar *)(dhdr+1)); + if(op) { + memcpy((char *)&ip,(char *)op+2,4); + DhcpSetEnv("GIPADD",(char *)IpToString(ip,(char *)buf)); + } + /* Process DHCPOPT_LEASETIME option as follows... + * If not set, assume infinite and clear DHCPLEASETIME shellvar. + * If set, then look for the presence of the DHCPLEASETIME shell + * variable and use it as a minimum. If the incoming value is + * >= what is in the shell variable, accept it and load the shell + * variable with this value. If incoming lease time is less than + * what is stored in DHCPLEASETIME, ignore the request. + * If DHCPLEASETIME is not set, then just load the incoming lease + * into the DHCPLEASETIME shell variable and accept the offer. + */ + op = DhcpGetOption(DHCPOPT_LEASETIME,(uchar *)(dhdr+1)); + if(op) { + memcpy((char *)&leasetime,(char *)op+2,4); + leasetime = ecl(leasetime); + if(getenv("DHCPLEASETIME")) { + ulong minleasetime; + minleasetime = strtol(getenv("DHCPLEASETIME"),0,0); + if(leasetime < minleasetime) { + printf("DHCP: incoming lease time 0x%lx too small.\n", + leasetime); + return(-1); + } + } + sprintf((char *)buf,"0x%lx",leasetime); + setenv("DHCPLEASETIME",(char *)buf); + } else { + setenv("DHCPLEASETIME",(char *)0); + } + } + + /* Check for vendor specific stuff... */ + DhcpVendorSpecific(dhdr); + + DhcpBootpDone(0,dhdr, + size - ((int)((int)&dhdr->magic_cookie - (int)ehdr))); + + DHCPState = DHCPSTATE_BOUND; + + /* Call loadBootFile() which will then kick off a tftp client + * transfer if both BOOTFILE and BOOTSRVR shell variables are + * loaded; otherwise, we are done. + */ + loadBootFile(0); + } + return(0); } char * DHCPop(int op) { - switch(op) { - case DHCPBOOTP_REQUEST: - return("REQUEST"); - case DHCPBOOTP_REPLY: - return("REPLY"); - default: - return("???"); - } + switch(op) { + case DHCPBOOTP_REQUEST: + return("REQUEST"); + case DHCPBOOTP_REPLY: + return("REPLY"); + default: + return("???"); + } } char * DHCPmsgtype(int msg) { - char *type; - - switch(msg) { - case DHCPDISCOVER: - type = "DISCOVER"; - break; - case DHCPOFFER: - type = "OFFER"; - break; - case DHCPREQUEST: - type = "REQUEST"; - break; - case DHCPDECLINE: - type = "DECLINE"; - break; - case DHCPACK: - type = "ACK"; - break; - case DHCPNACK: - type = "NACK"; - break; - case DHCPRELEASE: - type = "RELEASE"; - break; - case DHCPINFORM: - type = "INFORM"; - break; - case DHCPFORCERENEW: - type = "FORCERENEW"; - break; - case DHCPLEASEQUERY: - type = "LEASEQUERY"; - break; - case DHCPLEASEUNASSIGNED: - type = "LEASEUNASSIGNED"; - break; - case DHCPLEASEUNKNOWN: - type = "LEASEUNKNOWN"; - break; - case DHCPLEASEACTIVE: - type = "LEASEACTIVE"; - break; - default: - type = "???"; - break; - } - return(type); + char *type; + + switch(msg) { + case DHCPDISCOVER: + type = "DISCOVER"; + break; + case DHCPOFFER: + type = "OFFER"; + break; + case DHCPREQUEST: + type = "REQUEST"; + break; + case DHCPDECLINE: + type = "DECLINE"; + break; + case DHCPACK: + type = "ACK"; + break; + case DHCPNACK: + type = "NACK"; + break; + case DHCPRELEASE: + type = "RELEASE"; + break; + case DHCPINFORM: + type = "INFORM"; + break; + case DHCPFORCERENEW: + type = "FORCERENEW"; + break; + case DHCPLEASEQUERY: + type = "LEASEQUERY"; + break; + case DHCPLEASEUNASSIGNED: + type = "LEASEUNASSIGNED"; + break; + case DHCPLEASEUNKNOWN: + type = "LEASEUNKNOWN"; + break; + case DHCPLEASEACTIVE: + type = "LEASEACTIVE"; + break; + default: + type = "???"; + break; + } + return(type); } /* printDhcpOptions(): - * Verbosely display the DHCP options pointed to by the incoming - * options pointer. + * Verbosely display the DHCP options pointed to by the incoming + * options pointer. */ void printDhcpOptions(uchar *options) { - int i, safety, opt, optlen; - - safety = 0; - while(*options != 0xff) { - if (safety++ > 10000) { - printf("Aborting, overflow likely\n"); - break; - } - opt = (int)*options++; - if (opt == 0) /* padding */ - continue; - printf(" option %3d: ",opt); - optlen = (int)*options++; - if (opt==DHCPOPT_MESSAGETYPE) { - printf("DHCP_%s",DHCPmsgtype(*options++)); - } - else if ((opt < DHCPOPT_HOSTNAME) || - (opt == DHCPOPT_BROADCASTADDRESS) || - (opt == DHCPOPT_REQUESTEDIP) || - (opt == DHCPOPT_SERVERID) || - (opt == DHCPOPT_NISSERVER)) { - for(i=0;i<optlen;i++) - printf("%d ",*options++); - } - else if ((opt == DHCPOPT_NISDOMAINNAME) || (opt == DHCPOPT_CLASSID)) { - for(i=0;i<optlen;i++) - printf("%c",*options++); - } - else if (opt == DHCPOPT_CLIENTID) { - printf("%d 0x",(int)*options++); - for(i=1;i<optlen;i++) - printf("%02x",*options++); - } - else { - printf("0x"); - for(i=0;i<optlen;i++) - printf("%02x",*options++); - } - printf("\n"); - } + int i, safety, opt, optlen; + + safety = 0; + while(*options != 0xff) { + if(safety++ > 10000) { + printf("Aborting, overflow likely\n"); + break; + } + opt = (int)*options++; + if(opt == 0) { /* padding */ + continue; + } + printf(" option %3d: ",opt); + optlen = (int)*options++; + if(opt==DHCPOPT_MESSAGETYPE) { + printf("DHCP_%s",DHCPmsgtype(*options++)); + } else if((opt < DHCPOPT_HOSTNAME) || + (opt == DHCPOPT_BROADCASTADDRESS) || + (opt == DHCPOPT_REQUESTEDIP) || + (opt == DHCPOPT_SERVERID) || + (opt == DHCPOPT_NISSERVER)) { + for(i=0; i<optlen; i++) { + printf("%d ",*options++); + } + } else if((opt == DHCPOPT_NISDOMAINNAME) || (opt == DHCPOPT_CLASSID)) { + for(i=0; i<optlen; i++) { + printf("%c",*options++); + } + } else if(opt == DHCPOPT_CLIENTID) { + printf("%d 0x",(int)*options++); + for(i=1; i<optlen; i++) { + printf("%02x",*options++); + } + } else { + printf("0x"); + for(i=0; i<optlen; i++) { + printf("%02x",*options++); + } + } + printf("\n"); + } } /* printDhcp(): - * Try to format the DHCP stuff... + * Try to format the DHCP stuff... */ void printDhcp(struct Udphdr *p) { - struct dhcphdr *d; - uchar *client_ip, *your_ip, *server_ip, *router_ip; - ulong cookie, xid; - - d = (struct dhcphdr *)(p+1); - - client_ip = (uchar *)&(d->client_ip); - your_ip = (uchar *)&(d->your_ip); - server_ip = (uchar *)&(d->server_ip); - router_ip = (uchar *)&(d->router_ip); - memcpy((char *)&xid,(char *)&d->transaction_id,4); - /* xid = ecl(xid) */ - - printf(" DHCP: sport dport ulen sum\n"); - printf(" %4d %4d %4d %4d\n", - ecs(p->uh_sport), ecs(p->uh_dport), ecs(p->uh_ulen),ecs(p->uh_sum)); - printf(" op = %s, htype = %d, hlen = %d, hops = %d\n", - DHCPop(d->op),d->htype,d->hlen,d->hops); - printf(" seconds = %d, flags = 0x%x, xid= 0x%lx\n", - ecs(d->seconds),ecs(d->flags),xid); - printf(" client_macaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", - d->client_macaddr[0], d->client_macaddr[1], - d->client_macaddr[2], d->client_macaddr[3], - d->client_macaddr[4], d->client_macaddr[5]); - printf(" client_ip = %d.%d.%d.%d\n", - client_ip[0],client_ip[1],client_ip[2],client_ip[3]); - printf(" your_ip = %d.%d.%d.%d\n", - your_ip[0],your_ip[1],your_ip[2],your_ip[3]); - printf(" server_ip = %d.%d.%d.%d\n", - server_ip[0],server_ip[1],server_ip[2],server_ip[3]); - printf(" router_ip = %d.%d.%d.%d\n", - router_ip[0],router_ip[1],router_ip[2],router_ip[3]); - if (d->bootfile[0]) - printf(" bootfile: %s\n", d->bootfile); - if (d->server_hostname[0]) - printf(" server_hostname: %s\n", d->server_hostname); - - /* If STANDARD_MAGIC_COOKIE doesn't exist, then don't process options... */ - memcpy((char *)&cookie,(char *)&d->magic_cookie,4); - if (cookie != ecl(STANDARD_MAGIC_COOKIE)) - return; - - printDhcpOptions((uchar *)(d+1)); + struct dhcphdr *d; + uchar *client_ip, *your_ip, *server_ip, *router_ip; + ulong cookie, xid; + + d = (struct dhcphdr *)(p+1); + + client_ip = (uchar *)&(d->client_ip); + your_ip = (uchar *)&(d->your_ip); + server_ip = (uchar *)&(d->server_ip); + router_ip = (uchar *)&(d->router_ip); + memcpy((char *)&xid,(char *)&d->transaction_id,4); + /* xid = ecl(xid) */ + + printf(" DHCP: sport dport ulen sum\n"); + printf(" %4d %4d %4d %4d\n", + ecs(p->uh_sport), ecs(p->uh_dport), ecs(p->uh_ulen),ecs(p->uh_sum)); + printf(" op = %s, htype = %d, hlen = %d, hops = %d\n", + DHCPop(d->op),d->htype,d->hlen,d->hops); + printf(" seconds = %d, flags = 0x%x, xid= 0x%lx\n", + ecs(d->seconds),ecs(d->flags),xid); + printf(" client_macaddr = %02x:%02x:%02x:%02x:%02x:%02x\n", + d->client_macaddr[0], d->client_macaddr[1], + d->client_macaddr[2], d->client_macaddr[3], + d->client_macaddr[4], d->client_macaddr[5]); + printf(" client_ip = %d.%d.%d.%d\n", + client_ip[0],client_ip[1],client_ip[2],client_ip[3]); + printf(" your_ip = %d.%d.%d.%d\n", + your_ip[0],your_ip[1],your_ip[2],your_ip[3]); + printf(" server_ip = %d.%d.%d.%d\n", + server_ip[0],server_ip[1],server_ip[2],server_ip[3]); + printf(" router_ip = %d.%d.%d.%d\n", + router_ip[0],router_ip[1],router_ip[2],router_ip[3]); + if(d->bootfile[0]) { + printf(" bootfile: %s\n", d->bootfile); + } + if(d->server_hostname[0]) { + printf(" server_hostname: %s\n", d->server_hostname); + } + + /* If STANDARD_MAGIC_COOKIE doesn't exist, then don't process options... */ + memcpy((char *)&cookie,(char *)&d->magic_cookie,4); + if(cookie != ecl(STANDARD_MAGIC_COOKIE)) { + return; + } + + printDhcpOptions((uchar *)(d+1)); } /* DhcpGetOption(): - * Based on the incoming option pointer and a specified option value, - * search through the options list for the value and return a pointer - * to that option. + * Based on the incoming option pointer and a specified option value, + * search through the options list for the value and return a pointer + * to that option. */ uchar * DhcpGetOption(unsigned char optval,unsigned char *options) { - int safety; - - safety = 0; - while(*options != 0xff) { - if (safety++ > 1000) - break; - if (*options == 0) { /* Skip over padding. */ - options++; - continue; - } - if (*options == optval) - return(options); - options += ((*(options+1)) + 2); - } - return((uchar *)0); + int safety; + + safety = 0; + while(*options != 0xff) { + if(safety++ > 1000) { + break; + } + if(*options == 0) { /* Skip over padding. */ + options++; + continue; + } + if(*options == optval) { + return(options); + } + options += ((*(options+1)) + 2); + } + return((uchar *)0); } int DhcpSetEnv(char *name,char *value) { #if INCLUDE_ETHERVERBOSE - if (EtherVerbose & SHOW_DHCP) - printf(" Dhcp/Bootp SetEnv: %s = %s\n",name,value); + if(EtherVerbose & SHOW_DHCP) { + printf(" Dhcp/Bootp SetEnv: %s = %s\n",name,value); + } #endif - return(setenv(name,value)); + return(setenv(name,value)); } int DhcpIPCheck(char *ipadd) { - char verbose; - - if (!memcmp(ipadd,"DHCP",4)) { - verbose = ipadd[4]; - DHCPState = DHCPSTATE_INITIALIZE; - } - else if (!memcmp(ipadd,"BOOTP",5)) { - verbose = ipadd[5]; - DHCPState = BOOTPSTATE_INITIALIZE; - } - else { - if (IpToBin(ipadd,BinIpAddr) < 0) { - verbose = 0; - DHCPState = BOOTPSTATE_INITIALIZE; - } - else { - DHCPState = DHCPSTATE_NOTUSED; - return(0); - } - } - - BinIpAddr[0] = 0; - BinIpAddr[1] = 0; - BinIpAddr[2] = 0; - BinIpAddr[3] = 0; + char verbose; + + if(!memcmp(ipadd,"DHCP",4)) { + verbose = ipadd[4]; + DHCPState = DHCPSTATE_INITIALIZE; + } else if(!memcmp(ipadd,"BOOTP",5)) { + verbose = ipadd[5]; + DHCPState = BOOTPSTATE_INITIALIZE; + } else { + if(IpToBin(ipadd,BinIpAddr) < 0) { + verbose = 0; + DHCPState = BOOTPSTATE_INITIALIZE; + } else { + DHCPState = DHCPSTATE_NOTUSED; + return(0); + } + } + + BinIpAddr[0] = 0; + BinIpAddr[1] = 0; + BinIpAddr[2] = 0; + BinIpAddr[3] = 0; #if INCLUDE_ETHERVERBOSE - if (verbose == 'V') - EtherVerbose = DHCP_VERBOSE; - else if (verbose == 'v') - EtherVerbose = SHOW_DHCP; + if(verbose == 'V') { + EtherVerbose = DHCP_VERBOSE; + } else if(verbose == 'v') { + EtherVerbose = SHOW_DHCP; + } #endif - return(0); + return(0); } char * dhcpStringState(int state) { - switch(state) { - case DHCPSTATE_INITIALIZE: - return("DHCP_INITIALIZE"); - case DHCPSTATE_SELECT: - return("DHCP_SELECT"); - case DHCPSTATE_REQUEST: - return("DHCP_REQUEST"); - case DHCPSTATE_BOUND: - return("DHCP_BOUND"); - case DHCPSTATE_RENEW: - return("DHCP_RENEW"); - case DHCPSTATE_REBIND: - return("DHCP_REBIND"); - case DHCPSTATE_NOTUSED: - return("DHCP_NOTUSED"); - case DHCPSTATE_RESTART: - return("DHCP_RESTART"); - case BOOTPSTATE_INITIALIZE: - return("BOOTP_INITIALIZE"); - case BOOTPSTATE_REQUEST: - return("BOOTP_REQUEST"); - case BOOTPSTATE_RESTART: - return("BOOTP_RESTART"); - case BOOTPSTATE_COMPLETE: - return("BOOTP_COMPLETE"); - default: - return("???"); - } + switch(state) { + case DHCPSTATE_INITIALIZE: + return("DHCP_INITIALIZE"); + case DHCPSTATE_SELECT: + return("DHCP_SELECT"); + case DHCPSTATE_REQUEST: + return("DHCP_REQUEST"); + case DHCPSTATE_BOUND: + return("DHCP_BOUND"); + case DHCPSTATE_RENEW: + return("DHCP_RENEW"); + case DHCPSTATE_REBIND: + return("DHCP_REBIND"); + case DHCPSTATE_NOTUSED: + return("DHCP_NOTUSED"); + case DHCPSTATE_RESTART: + return("DHCP_RESTART"); + case BOOTPSTATE_INITIALIZE: + return("BOOTP_INITIALIZE"); + case BOOTPSTATE_REQUEST: + return("BOOTP_REQUEST"); + case BOOTPSTATE_RESTART: + return("BOOTP_RESTART"); + case BOOTPSTATE_COMPLETE: + return("BOOTP_COMPLETE"); + default: + return("???"); + } } void ShowDhcpStats() { - printf("Current DHCP State: %s\n",dhcpStringState(DHCPState)); + printf("Current DHCP State: %s\n",dhcpStringState(DHCPState)); } #endif |