summaryrefslogtreecommitdiffstats
path: root/main/common/dhcpboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/common/dhcpboot.c')
-rw-r--r--main/common/dhcpboot.c2135
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