OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [services/] [bootp.c] - Diff between revs 810 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 810 Rev 1765
/*
/*
 *      Based on LiMon - BOOTP.
 *      Based on LiMon - BOOTP.
 *
 *
 *      Copyright 1994, 1995, 2000 Neil Russell.
 *      Copyright 1994, 1995, 2000 Neil Russell.
 *      (See License)
 *      (See License)
 *      Copyright 2000 Roland Borde
 *      Copyright 2000 Roland Borde
 *      Copyright 2000 Paolo Scaffardi
 *      Copyright 2000 Paolo Scaffardi
 */
 */
 
 
#if 0
#if 0
#define DEBUG           1       /* general debug */
#define DEBUG           1       /* general debug */
#define DEBUG_BOOTP_EXT 1       /* Debug received vendor fields */
#define DEBUG_BOOTP_EXT 1       /* Debug received vendor fields */
#endif
#endif
 
 
#ifdef DEBUG_BOOTP_EXT
#ifdef DEBUG_BOOTP_EXT
#define debug_ext(fmt,args...)  printf (fmt ,##args)
#define debug_ext(fmt,args...)  printf (fmt ,##args)
#else
#else
#define debug_ext(fmt,args...)
#define debug_ext(fmt,args...)
#endif
#endif
 
 
#include "common.h"
#include "common.h"
#include "net.h"
#include "net.h"
#include "bootp.h"
#include "bootp.h"
#include "tftp.h"
#include "tftp.h"
#include "arp.h"
#include "arp.h"
 
 
#define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie         */
#define BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie         */
 
 
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if (CONFIG_COMMANDS & CFG_CMD_NET)
 
 
#define TIMEOUT         5               /* Seconds before trying BOOTP again    */
#define TIMEOUT         5               /* Seconds before trying BOOTP again    */
#define TIMEOUT_COUNT   1               /* # of timeouts before giving up       */
#define TIMEOUT_COUNT   1               /* # of timeouts before giving up       */
 
 
#define PORT_BOOTPS     67              /* BOOTP server UDP port                */
#define PORT_BOOTPS     67              /* BOOTP server UDP port                */
#define PORT_BOOTPC     68              /* BOOTP client UDP port                */
#define PORT_BOOTPC     68              /* BOOTP client UDP port                */
 
 
#ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list     */
#ifndef CONFIG_DHCP_MIN_EXT_LEN         /* minimal length of extension list     */
#define CONFIG_DHCP_MIN_EXT_LEN 64
#define CONFIG_DHCP_MIN_EXT_LEN 64
#endif
#endif
 
 
ulong           BootpID;
ulong           BootpID;
int             BootpTry;
int             BootpTry;
#ifdef CONFIG_BOOTP_RANDOM_DELAY
#ifdef CONFIG_BOOTP_RANDOM_DELAY
ulong           seed1, seed2;
ulong           seed1, seed2;
#endif
#endif
 
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
dhcp_state_t dhcp_state = INIT;
dhcp_state_t dhcp_state = INIT;
unsigned int dhcp_leasetime = 0;
unsigned int dhcp_leasetime = 0;
static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
static void DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len);
 
 
/* For Debug */
/* For Debug */
char *dhcpmsg2str(int type)
char *dhcpmsg2str(int type)
{
{
        switch (type) {
        switch (type) {
        case 1: return "DHCPDISCOVER"; break;
        case 1: return "DHCPDISCOVER"; break;
        case 2: return "DHCPOFFER"; break;
        case 2: return "DHCPOFFER"; break;
        case 3: return "DHCPREQUEST"; break;
        case 3: return "DHCPREQUEST"; break;
        case 4: return "DHCPDECLINE"; break;
        case 4: return "DHCPDECLINE"; break;
        case 5: return "DHCPACK"; break;
        case 5: return "DHCPACK"; break;
        case 6: return "DHCPNACK"; break;
        case 6: return "DHCPNACK"; break;
        case 7: return "DHCPRELEASE"; break;
        case 7: return "DHCPRELEASE"; break;
        default: return "UNKNOWN/INVALID MSG TYPE"; break;
        default: return "UNKNOWN/INVALID MSG TYPE"; break;
        }
        }
}
}
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
extern u8 *dhcp_vendorex_prep (u8 *e); /*rtn new e after add own opts. */
extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL  */
extern u8 *dhcp_vendorex_proc (u8 *e); /*rtn next e if mine,else NULL  */
#endif
#endif
 
 
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
 
 
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
{
{
        Bootp_t *bp = (Bootp_t *) pkt;
        Bootp_t *bp = (Bootp_t *) pkt;
        int retval = 0;
        int retval = 0;
 
 
        if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
        if (dest != PORT_BOOTPC || src != PORT_BOOTPS)
                retval = -1;
                retval = -1;
        if (len < sizeof (Bootp_t) - OPT_SIZE)
        if (len < sizeof (Bootp_t) - OPT_SIZE)
                retval = -2;
                retval = -2;
        if (bp->bp_op != OP_BOOTREQUEST &&
        if (bp->bp_op != OP_BOOTREQUEST &&
            bp->bp_op != OP_BOOTREPLY &&
            bp->bp_op != OP_BOOTREPLY &&
            bp->bp_op != DHCP_OFFER &&
            bp->bp_op != DHCP_OFFER &&
            bp->bp_op != DHCP_ACK &&
            bp->bp_op != DHCP_ACK &&
            bp->bp_op != DHCP_NAK ) {
            bp->bp_op != DHCP_NAK ) {
                retval = -3;
                retval = -3;
        }
        }
        if (bp->bp_htype != HWT_ETHER)
        if (bp->bp_htype != HWT_ETHER)
                retval = -4;
                retval = -4;
        if (bp->bp_hlen != HWL_ETHER)
        if (bp->bp_hlen != HWL_ETHER)
                retval = -5;
                retval = -5;
        if (bp->bp_id != BootpID)
        if (bp->bp_id != BootpID)
                retval = -6;
                retval = -6;
 
 
        debug ("Filtering pkt = %d\n", retval);
        debug ("Filtering pkt = %d\n", retval);
 
 
        return retval;
        return retval;
}
}
 
 
/*
/*
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 * Copy parameters of interest from BOOTP_REPLY/DHCP_OFFER packet
 */
 */
void BootpCopyNetParams(Bootp_t *bp)
void BootpCopyNetParams(Bootp_t *bp)
{
{
        NetOurIP = bp->bp_yiaddr;
        NetOurIP = bp->bp_yiaddr;
        NetServerIP = bp->bp_siaddr;
        NetServerIP = bp->bp_siaddr;
        NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
        NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
        copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
        copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
 
 
        debug ("Bootfile: %s\n", BootFile);
        debug ("Bootfile: %s\n", BootFile);
 
 
        /* Propagate to environment:
        /* Propagate to environment:
         * don't delete exising entry when BOOTP / DHCP reply does
         * don't delete exising entry when BOOTP / DHCP reply does
         * not contain a new value
         * not contain a new value
         */
         */
        if (*BootFile) {
        if (*BootFile) {
                setenv ("bootfile", BootFile);
                setenv ("bootfile", BootFile);
        }
        }
}
}
 
 
static int truncate_sz (const char *name, int maxlen, int curlen)
static int truncate_sz (const char *name, int maxlen, int curlen)
{
{
        if (curlen >= maxlen) {
        if (curlen >= maxlen) {
                printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
                printf("*** WARNING: %s is too long (%d - max: %d) - truncated\n",
                        name, curlen, maxlen);
                        name, curlen, maxlen);
                curlen = maxlen - 1;
                curlen = maxlen - 1;
        }
        }
        return (curlen);
        return (curlen);
}
}
 
 
#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
#if !(CONFIG_COMMANDS & CFG_CMD_DHCP)
 
 
static void BootpVendorFieldProcess(u8 *ext)
static void BootpVendorFieldProcess(u8 *ext)
{
{
    int size = *(ext+1) ;
    int size = *(ext+1) ;
 
 
    debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
    debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
 
 
    NetBootFileSize = 0;
    NetBootFileSize = 0;
 
 
    switch (*ext) {
    switch (*ext) {
    /* Fixed length fields */
    /* Fixed length fields */
        case 1:         /* Subnet mask                                  */
        case 1:         /* Subnet mask                                  */
                if (NetOurSubnetMask == 0)
                if (NetOurSubnetMask == 0)
                    memcpy(&NetOurSubnetMask, ext+2, 4);
                    memcpy(&NetOurSubnetMask, ext+2, 4);
                break;
                break;
        case 2:         /* Time offset - Not yet supported              */
        case 2:         /* Time offset - Not yet supported              */
                break;
                break;
    /* Variable length fields */
    /* Variable length fields */
        case 3:         /* Gateways list                                */
        case 3:         /* Gateways list                                */
                if (NetOurGatewayIP == 0) {
                if (NetOurGatewayIP == 0) {
                    memcpy(&NetOurGatewayIP, ext+2, 4);
                    memcpy(&NetOurGatewayIP, ext+2, 4);
                }
                }
                break;
                break;
        case 4:         /* Time server - Not yet supported              */
        case 4:         /* Time server - Not yet supported              */
                break;
                break;
        case 5:         /* IEN-116 name server - Not yet supported      */
        case 5:         /* IEN-116 name server - Not yet supported      */
                break;
                break;
        case 6:
        case 6:
                if (NetOurDNSIP == 0) {
                if (NetOurDNSIP == 0) {
                    memcpy(&NetOurDNSIP, ext+2, 4);
                    memcpy(&NetOurDNSIP, ext+2, 4);
                }
                }
                break;
                break;
        case 7:         /* Log server - Not yet supported               */
        case 7:         /* Log server - Not yet supported               */
                break;
                break;
        case 8:         /* Cookie/Quote server - Not yet supported      */
        case 8:         /* Cookie/Quote server - Not yet supported      */
                break;
                break;
        case 9:         /* LPR server - Not yet supported               */
        case 9:         /* LPR server - Not yet supported               */
                break;
                break;
        case 10:        /* Impress server - Not yet supported           */
        case 10:        /* Impress server - Not yet supported           */
                break;
                break;
        case 11:        /* RPL server - Not yet supported               */
        case 11:        /* RPL server - Not yet supported               */
                break;
                break;
        case 12:        /* Host name                                    */
        case 12:        /* Host name                                    */
                if (NetOurHostName[0] == 0) {
                if (NetOurHostName[0] == 0) {
                    size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
                    size = truncate_sz("Host Name", sizeof(NetOurHostName), size);
                    memcpy(&NetOurHostName, ext+2, size);
                    memcpy(&NetOurHostName, ext+2, size);
                    NetOurHostName[size] = 0 ;
                    NetOurHostName[size] = 0 ;
                }
                }
                break;
                break;
        case 13:        /* Boot file size                               */
        case 13:        /* Boot file size                               */
                memcpy(&NetBootFileSize, ext+2, size);
                memcpy(&NetBootFileSize, ext+2, size);
                break;
                break;
        case 14:        /* Merit dump file - Not yet supported          */
        case 14:        /* Merit dump file - Not yet supported          */
                break;
                break;
        case 15:        /* Domain name - Not yet supported              */
        case 15:        /* Domain name - Not yet supported              */
                break;
                break;
        case 16:        /* Swap server - Not yet supported              */
        case 16:        /* Swap server - Not yet supported              */
                break;
                break;
        case 17:        /* Root path                                    */
        case 17:        /* Root path                                    */
                if (NetOurRootPath[0] == 0) {
                if (NetOurRootPath[0] == 0) {
                    size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
                    size = truncate_sz("Root Path", sizeof(NetOurRootPath), size);
                    memcpy(&NetOurRootPath, ext+2, size);
                    memcpy(&NetOurRootPath, ext+2, size);
                    NetOurRootPath[size] = 0 ;
                    NetOurRootPath[size] = 0 ;
                }
                }
                break;
                break;
        case 18:        /* Extension path - Not yet supported           */
        case 18:        /* Extension path - Not yet supported           */
                /*
                /*
                 * This can be used to send the informations of the
                 * This can be used to send the informations of the
                 * vendor area in another file that the client can
                 * vendor area in another file that the client can
                 * access via TFTP.
                 * access via TFTP.
                 */
                 */
                break;
                break;
    /* IP host layer fields */
    /* IP host layer fields */
        case 40:        /* NIS Domain name                              */
        case 40:        /* NIS Domain name                              */
                if (NetOurNISDomain[0] == 0) {
                if (NetOurNISDomain[0] == 0) {
                    size = truncate_sz ("NIS Domain Name",
                    size = truncate_sz ("NIS Domain Name",
                                        sizeof(NetOurNISDomain),
                                        sizeof(NetOurNISDomain),
                                        size);
                                        size);
                    memcpy(&NetOurNISDomain, ext+2, size);
                    memcpy(&NetOurNISDomain, ext+2, size);
                    NetOurNISDomain[size] = 0 ;
                    NetOurNISDomain[size] = 0 ;
                }
                }
                break;
                break;
    /* Application layer fields */
    /* Application layer fields */
        case 43:        /* Vendor specific info - Not yet supported     */
        case 43:        /* Vendor specific info - Not yet supported     */
                /*
                /*
                 * Binary informations to exchange specific
                 * Binary informations to exchange specific
                 * product information.
                 * product information.
                 */
                 */
                break;
                break;
    /* Reserved (custom) fields (128..254) */
    /* Reserved (custom) fields (128..254) */
    }
    }
}
}
 
 
static void BootpVendorProcess(u8 *ext, int size)
static void BootpVendorProcess(u8 *ext, int size)
{
{
    u8 *end = ext + size ;
    u8 *end = ext + size ;
 
 
    debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
    debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
 
 
    while ((ext < end) && (*ext != 0xff)) {
    while ((ext < end) && (*ext != 0xff)) {
        if (*ext == 0) {
        if (*ext == 0) {
            ext ++ ;
            ext ++ ;
        } else {
        } else {
                u8 *opt = ext ;
                u8 *opt = ext ;
                ext += ext[1] + 2 ;
                ext += ext[1] + 2 ;
                if (ext <= end)
                if (ext <= end)
                    BootpVendorFieldProcess (opt) ;
                    BootpVendorFieldProcess (opt) ;
        }
        }
    }
    }
 
 
#ifdef DEBUG_BOOTP_EXT
#ifdef DEBUG_BOOTP_EXT
    printf("[BOOTP] Received fields: \n");
    printf("[BOOTP] Received fields: \n");
    if (NetOurSubnetMask) {
    if (NetOurSubnetMask) {
        puts ("NetOurSubnetMask : ");
        puts ("NetOurSubnetMask : ");
        print_IPaddr (NetOurSubnetMask);
        print_IPaddr (NetOurSubnetMask);
        putc('\n');
        putc('\n');
    }
    }
 
 
    if (NetOurGatewayIP) {
    if (NetOurGatewayIP) {
        puts ("NetOurGatewayIP  : ");
        puts ("NetOurGatewayIP  : ");
        print_IPaddr (NetOurGatewayIP);
        print_IPaddr (NetOurGatewayIP);
        putc('\n');
        putc('\n');
    }
    }
 
 
    if (NetBootFileSize) {
    if (NetBootFileSize) {
        printf("NetBootFileSize : %d\n", NetBootFileSize);
        printf("NetBootFileSize : %d\n", NetBootFileSize);
    }
    }
 
 
    if (NetOurHostName[0]) {
    if (NetOurHostName[0]) {
        printf("NetOurHostName  : %s\n", NetOurHostName);
        printf("NetOurHostName  : %s\n", NetOurHostName);
    }
    }
 
 
    if (NetOurRootPath[0]) {
    if (NetOurRootPath[0]) {
        printf("NetOurRootPath  : %s\n", NetOurRootPath);
        printf("NetOurRootPath  : %s\n", NetOurRootPath);
    }
    }
 
 
    if (NetOurNISDomain[0]) {
    if (NetOurNISDomain[0]) {
        printf("NetOurNISDomain : %s\n", NetOurNISDomain);
        printf("NetOurNISDomain : %s\n", NetOurNISDomain);
    }
    }
#endif  /* DEBUG_BOOTP_EXT */
#endif  /* DEBUG_BOOTP_EXT */
}
}
 
 
/*
/*
 *      Handle a BOOTP received packet.
 *      Handle a BOOTP received packet.
 */
 */
static void
static void
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
{
        Bootp_t *bp;
        Bootp_t *bp;
        char    *s;
        char    *s;
 
 
        debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
        debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
                src, dest, len, sizeof (Bootp_t));
                src, dest, len, sizeof (Bootp_t));
 
 
        bp = (Bootp_t *)pkt;
        bp = (Bootp_t *)pkt;
 
 
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
                return;
 
 
        /*
        /*
         *      Got a good BOOTP reply.  Copy the data into our variables.
         *      Got a good BOOTP reply.  Copy the data into our variables.
         */
         */
#ifdef CONFIG_STATUS_LED
#ifdef CONFIG_STATUS_LED
        status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
        status_led_set (STATUS_LED_BOOT, STATUS_LED_OFF);
#endif
#endif
 
 
        BootpCopyNetParams(bp);         /* Store net parameters from reply */
        BootpCopyNetParams(bp);         /* Store net parameters from reply */
 
 
        /* Retrieve extended informations (we must parse the vendor area) */
        /* Retrieve extended informations (we must parse the vendor area) */
        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
            BootpVendorProcess(&bp->bp_vend[4], len);
            BootpVendorProcess(&bp->bp_vend[4], len);
 
 
        NetSetTimeout(0, (thand_f *)0);
        NetSetTimeout(0, (thand_f *)0);
 
 
        debug ("Got good BOOTP\n");
        debug ("Got good BOOTP\n");
 
 
        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
                /*
                /*
                 * Just use BOOTP to configure system;
                 * Just use BOOTP to configure system;
                 * Do not use TFTP to load the bootfile.
                 * Do not use TFTP to load the bootfile.
                 */
                 */
                NetState = NETLOOP_SUCCESS;
                NetState = NETLOOP_SUCCESS;
                return;
                return;
        }
        }
 
 
        /* Send ARP request to get TFTP server ethernet address.
        /* Send ARP request to get TFTP server ethernet address.
         * This automagically starts TFTP, too.
         * This automagically starts TFTP, too.
         */
         */
        ArpRequest();
        ArpRequest();
}
}
#endif  /* !CFG_CMD_DHCP */
#endif  /* !CFG_CMD_DHCP */
 
 
/*
/*
 *      Timeout on BOOTP/DHCP request.
 *      Timeout on BOOTP/DHCP request.
 */
 */
static void
static void
BootpTimeout(void)
BootpTimeout(void)
{
{
        if (BootpTry >= TIMEOUT_COUNT) {
        if (BootpTry >= TIMEOUT_COUNT) {
                puts ("\nRetry count exceeded; starting again\n");
                puts ("\nRetry count exceeded; starting again\n");
                NetStartAgain ();
                NetStartAgain ();
        } else {
        } else {
                NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
                NetSetTimeout (TIMEOUT * CFG_HZ, BootpTimeout);
                BootpRequest ();
                BootpRequest ();
        }
        }
}
}
 
 
/*
/*
 *      Initialize BOOTP extension fields in the request.
 *      Initialize BOOTP extension fields in the request.
 */
 */
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
static int DhcpExtended(u8 *e, int message_type, IPaddr_t ServerID, IPaddr_t RequestedIP)
{
{
    u8 *start = e ;
    u8 *start = e ;
    u8 *cnt;
    u8 *cnt;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
    u8 *x;
    u8 *x;
#endif
#endif
 
 
    *e++ =  99;         /* RFC1048 Magic Cookie */
    *e++ =  99;         /* RFC1048 Magic Cookie */
    *e++ = 130;
    *e++ = 130;
    *e++ =  83;
    *e++ =  83;
    *e++ =  99;
    *e++ =  99;
 
 
    *e++ = 53;          /* DHCP Message Type */
    *e++ = 53;          /* DHCP Message Type */
    *e++ = 1;
    *e++ = 1;
    *e++ = message_type;
    *e++ = message_type;
 
 
    *e++ = 57;          /* Maximum DHCP Message Size */
    *e++ = 57;          /* Maximum DHCP Message Size */
    *e++ = 2;
    *e++ = 2;
    *e++ = (576-312+OPT_SIZE) >> 8;
    *e++ = (576-312+OPT_SIZE) >> 8;
    *e++ = (576-312+OPT_SIZE) & 0xff;
    *e++ = (576-312+OPT_SIZE) & 0xff;
 
 
    if ( ServerID ) {
    if ( ServerID ) {
            *e++ = 54;  /* ServerID */
            *e++ = 54;  /* ServerID */
            *e++ = 4;
            *e++ = 4;
            *e++ = ServerID >> 24;
            *e++ = ServerID >> 24;
            *e++ = ServerID >> 16;
            *e++ = ServerID >> 16;
            *e++ = ServerID >> 8;
            *e++ = ServerID >> 8;
            *e++ = ServerID & 0xff;
            *e++ = ServerID & 0xff;
    }
    }
 
 
    if ( RequestedIP ) {
    if ( RequestedIP ) {
            *e++ = 50;  /* Requested IP */
            *e++ = 50;  /* Requested IP */
            *e++ = 4;
            *e++ = 4;
            *e++ = RequestedIP >> 24;
            *e++ = RequestedIP >> 24;
            *e++ = RequestedIP >> 16;
            *e++ = RequestedIP >> 16;
            *e++ = RequestedIP >> 8;
            *e++ = RequestedIP >> 8;
            *e++ = RequestedIP & 0xff;
            *e++ = RequestedIP & 0xff;
    }
    }
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
    if ((x = dhcp_vendorex_prep (e)))
    if ((x = dhcp_vendorex_prep (e)))
        return x - start ;
        return x - start ;
#endif
#endif
 
 
    *e++ = 55;          /* Parameter Request List */
    *e++ = 55;          /* Parameter Request List */
    cnt  = e++;         /* Pointer to count of requested items */
    cnt  = e++;         /* Pointer to count of requested items */
    *cnt = 0;
    *cnt = 0;
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
    *e++ = 1;           /* Subnet Mask */
    *e++ = 1;           /* Subnet Mask */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
    *e++ = 3;           /* Router Option */
    *e++ = 3;           /* Router Option */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
    *e++ = 6;           /* DNS Server(s) */
    *e++ = 6;           /* DNS Server(s) */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
    *e++ = 12;          /* Hostname */
    *e++ = 12;          /* Hostname */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
    *e++ = 13;          /* Boot File Size */
    *e++ = 13;          /* Boot File Size */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
    *e++ = 17;          /* Boot path */
    *e++ = 17;          /* Boot path */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
    *e++ = 40;          /* NIS Domain name request */
    *e++ = 40;          /* NIS Domain name request */
    *cnt += 1;
    *cnt += 1;
#endif
#endif
    *e++ = 255;         /* End of the list */
    *e++ = 255;         /* End of the list */
 
 
    /* Pad to minimal length */
    /* Pad to minimal length */
#ifdef  CONFIG_DHCP_MIN_EXT_LEN
#ifdef  CONFIG_DHCP_MIN_EXT_LEN
    while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
    while ((e - start) <= CONFIG_DHCP_MIN_EXT_LEN)
        *e++ = 0;
        *e++ = 0;
#endif
#endif
 
 
    return e - start ;
    return e - start ;
}
}
 
 
#else   /* CFG_CMD_DHCP */
#else   /* CFG_CMD_DHCP */
/*
/*
 *      Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
 *      Warning: no field size check - change CONFIG_BOOTP_MASK at your own risk!
 */
 */
static int BootpExtended (u8 *e)
static int BootpExtended (u8 *e)
{
{
    u8 *start = e ;
    u8 *start = e ;
 
 
    *e++ =  99;         /* RFC1048 Magic Cookie */
    *e++ =  99;         /* RFC1048 Magic Cookie */
    *e++ = 130;
    *e++ = 130;
    *e++ =  83;
    *e++ =  83;
    *e++ =  99;
    *e++ =  99;
 
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
    *e++ = 53;          /* DHCP Message Type */
    *e++ = 53;          /* DHCP Message Type */
    *e++ = 1;
    *e++ = 1;
    *e++ = DHCP_DISCOVER;
    *e++ = DHCP_DISCOVER;
 
 
    *e++ = 57;          /* Maximum DHCP Message Size */
    *e++ = 57;          /* Maximum DHCP Message Size */
    *e++ = 2;
    *e++ = 2;
    *e++ = (576-312+OPT_SIZE) >> 16;
    *e++ = (576-312+OPT_SIZE) >> 16;
    *e++ = (576-312+OPT_SIZE) & 0xff;
    *e++ = (576-312+OPT_SIZE) & 0xff;
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_SUBNETMASK)
    *e++ =  1;          /* Subnet mask request */
    *e++ =  1;          /* Subnet mask request */
    *e++ =  4;
    *e++ =  4;
     e  +=  4;
     e  +=  4;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_GATEWAY)
    *e++ =  3;          /* Default gateway request */
    *e++ =  3;          /* Default gateway request */
    *e++ =  4;
    *e++ =  4;
     e  +=  4;
     e  +=  4;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS)
    *e++ =  6;          /* Domain Name Server */
    *e++ =  6;          /* Domain Name Server */
    *e++ =  4;
    *e++ =  4;
     e  +=  4;
     e  +=  4;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_HOSTNAME)
    *e++ = 12;          /* Host name request */
    *e++ = 12;          /* Host name request */
    *e++ = 32;
    *e++ = 32;
     e  += 32;
     e  += 32;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTFILESIZE)
    *e++ = 13;          /* Boot file size */
    *e++ = 13;          /* Boot file size */
    *e++ =  2;
    *e++ =  2;
     e  +=  2;
     e  +=  2;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_BOOTPATH)
    *e++ = 17;          /* Boot path */
    *e++ = 17;          /* Boot path */
    *e++ = 32;
    *e++ = 32;
     e  += 32;
     e  += 32;
#endif
#endif
 
 
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_NISDOMAIN)
    *e++ = 40;          /* NIS Domain name request */
    *e++ = 40;          /* NIS Domain name request */
    *e++ = 32;
    *e++ = 32;
     e  += 32;
     e  += 32;
#endif
#endif
 
 
    *e++ = 255;         /* End of the list */
    *e++ = 255;         /* End of the list */
 
 
    return e - start ;
    return e - start ;
}
}
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
 
 
void
void
BootpRequest (void)
BootpRequest (void)
{
{
        volatile uchar *pkt, *iphdr;
        volatile uchar *pkt, *iphdr;
        Bootp_t *bp;
        Bootp_t *bp;
        int ext_len, pktlen, iplen;
        int ext_len, pktlen, iplen;
 
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
        dhcp_state = INIT;
        dhcp_state = INIT;
#endif
#endif
 
 
#ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
#ifdef CONFIG_BOOTP_RANDOM_DELAY                /* Random BOOTP delay */
        unsigned char bi_enetaddr[6];
        unsigned char bi_enetaddr[6];
        int   reg;
        int   reg;
        char  *e,*s;
        char  *e,*s;
        uchar tmp[64];
        uchar tmp[64];
        ulong tst1, tst2, sum, m_mask, m_value = 0;
        ulong tst1, tst2, sum, m_mask, m_value = 0;
 
 
        if (BootpTry ==0) {
        if (BootpTry ==0) {
                /* get our mac */
                /* get our mac */
                reg = getenv_r ("ethaddr", tmp, sizeof(tmp));
                reg = getenv_r ("ethaddr", tmp, sizeof(tmp));
                s = (reg > 0) ? tmp : NULL;
                s = (reg > 0) ? tmp : NULL;
 
 
                for (reg=0; reg<6; ++reg) {
                for (reg=0; reg<6; ++reg) {
                        bi_enetaddr[reg] = s ? simple_strtoul(s, &e, 16) : 0;
                        bi_enetaddr[reg] = s ? simple_strtoul(s, &e, 16) : 0;
                        if (s) {
                        if (s) {
                                s = (*e) ? e+1 : e;
                                s = (*e) ? e+1 : e;
                        }
                        }
                }
                }
#ifdef DEBUG
#ifdef DEBUG
                printf("BootpRequest => Our Mac: ");
                printf("BootpRequest => Our Mac: ");
                for (reg=0; reg<6; reg++) {
                for (reg=0; reg<6; reg++) {
                        printf ("%x%c",
                        printf ("%x%c",
                                bi_enetaddr[reg],
                                bi_enetaddr[reg],
                                reg==5 ? '\n' : ':');
                                reg==5 ? '\n' : ':');
                }
                }
#endif /* DEBUG */
#endif /* DEBUG */
 
 
                /* Mac-Manipulation 2 get seed1 */
                /* Mac-Manipulation 2 get seed1 */
                tst1=0;
                tst1=0;
                tst2=0;
                tst2=0;
                for (reg=2; reg<6; reg++) {
                for (reg=2; reg<6; reg++) {
                        tst1 = tst1 << 8;
                        tst1 = tst1 << 8;
                        tst1 = tst1 | bi_enetaddr[reg];
                        tst1 = tst1 | bi_enetaddr[reg];
                }
                }
                for (reg=0; reg<2; reg++) {
                for (reg=0; reg<2; reg++) {
                        tst2 = tst2 | bi_enetaddr[reg];
                        tst2 = tst2 | bi_enetaddr[reg];
                        tst2 = tst2 << 8;
                        tst2 = tst2 << 8;
                }
                }
 
 
                seed1 = tst1^tst2;
                seed1 = tst1^tst2;
 
 
                /* Mirror seed1*/
                /* Mirror seed1*/
                m_mask=0x1;
                m_mask=0x1;
                for (reg=1;reg<=32;reg++) {
                for (reg=1;reg<=32;reg++) {
                        m_value |= (m_mask & seed1);
                        m_value |= (m_mask & seed1);
                        seed1 = seed1 >> 1;
                        seed1 = seed1 >> 1;
                        m_value = m_value << 1;
                        m_value = m_value << 1;
                }
                }
                seed1 = m_value;
                seed1 = m_value;
                seed2 = 0xB78D0945;
                seed2 = 0xB78D0945;
        }
        }
 
 
        /* Random Number Generator */
        /* Random Number Generator */
 
 
        for (reg=0;reg<=0;reg++) {
        for (reg=0;reg<=0;reg++) {
                sum = seed1 + seed2;
                sum = seed1 + seed2;
                if (sum < seed1 || sum < seed2)
                if (sum < seed1 || sum < seed2)
                        sum++;
                        sum++;
                seed2 = seed1;
                seed2 = seed1;
                seed1 = sum;
                seed1 = sum;
 
 
                if (BootpTry<=2) {      /* Start with max 1024 * 1ms */
                if (BootpTry<=2) {      /* Start with max 1024 * 1ms */
                        sum = sum >> (22-BootpTry);
                        sum = sum >> (22-BootpTry);
                } else {                /*After 3rd BOOTP request max 8192 * 1ms */
                } else {                /*After 3rd BOOTP request max 8192 * 1ms */
                        sum = sum >> 19;
                        sum = sum >> 19;
                }
                }
        }
        }
 
 
        printf ("Random delay: %ld ms...\n", sum);
        printf ("Random delay: %ld ms...\n", sum);
        for (reg=0; reg <sum; reg++) {
        for (reg=0; reg <sum; reg++) {
                udelay(1000); /*Wait 1ms*/
                udelay(1000); /*Wait 1ms*/
        }
        }
#endif  /* CONFIG_BOOTP_RANDOM_DELAY */
#endif  /* CONFIG_BOOTP_RANDOM_DELAY */
 
 
        printf("BOOTP broadcast %d\n", ++BootpTry);
        printf("BOOTP broadcast %d\n", ++BootpTry);
        pkt = NetTxPacket;
        pkt = NetTxPacket;
        memset ((void*)pkt, 0, PKTSIZE);
        memset ((void*)pkt, 0, PKTSIZE);
 
 
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
        pkt += ETHER_HDR_SIZE;
        pkt += ETHER_HDR_SIZE;
 
 
        /*
        /*
         * Next line results in incorrect packet size being transmitted, resulting
         * Next line results in incorrect packet size being transmitted, resulting
         * in errors in some DHCP servers, reporting missing bytes.  Size must be
         * in errors in some DHCP servers, reporting missing bytes.  Size must be
         * set in packet header after extension length has been determined.
         * set in packet header after extension length has been determined.
         * C. Hallinan, DS4.COM, Inc.
         * C. Hallinan, DS4.COM, Inc.
         */
         */
        /* NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
        /* NetSetIP(pkt, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, sizeof (Bootp_t)); */
        iphdr = pkt;    /* We need this later for NetSetIP() */
        iphdr = pkt;    /* We need this later for NetSetIP() */
        pkt += IP_HDR_SIZE;
        pkt += IP_HDR_SIZE;
 
 
        bp = (Bootp_t *)pkt;
        bp = (Bootp_t *)pkt;
        bp->bp_op = OP_BOOTREQUEST;
        bp->bp_op = OP_BOOTREQUEST;
        bp->bp_htype = HWT_ETHER;
        bp->bp_htype = HWT_ETHER;
        bp->bp_hlen = HWL_ETHER;
        bp->bp_hlen = HWL_ETHER;
        bp->bp_hops = 0;
        bp->bp_hops = 0;
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
        bp->bp_ciaddr = 0;
        bp->bp_ciaddr = 0;
        bp->bp_yiaddr = 0;
        bp->bp_yiaddr = 0;
        bp->bp_siaddr = 0;
        bp->bp_siaddr = 0;
        bp->bp_giaddr = 0;
        bp->bp_giaddr = 0;
        NetCopyEther(bp->bp_chaddr, NetOurEther);
        NetCopyEther(bp->bp_chaddr, NetOurEther);
        copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file));
        copy_filename (bp->bp_file, BootFile, sizeof(bp->bp_file));
 
 
        /* Request additional information from the BOOTP/DHCP server */
        /* Request additional information from the BOOTP/DHCP server */
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
        ext_len = DhcpExtended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
        ext_len = DhcpExtended(bp->bp_vend, DHCP_DISCOVER, 0, 0);
#else
#else
        ext_len = BootpExtended(bp->bp_vend);
        ext_len = BootpExtended(bp->bp_vend);
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
 
 
        /*
        /*
         *      Bootp ID is the lower 4 bytes of our ethernet address
         *      Bootp ID is the lower 4 bytes of our ethernet address
         *      plus the current time in HZ.
         *      plus the current time in HZ.
         */
         */
        BootpID = ((ulong)NetOurEther[2] << 24)
        BootpID = ((ulong)NetOurEther[2] << 24)
                | ((ulong)NetOurEther[3] << 16)
                | ((ulong)NetOurEther[3] << 16)
                | ((ulong)NetOurEther[4] << 8)
                | ((ulong)NetOurEther[4] << 8)
                | (ulong)NetOurEther[5];
                | (ulong)NetOurEther[5];
        BootpID += get_timer(0);
        BootpID += get_timer(0);
        bp->bp_id = BootpID;
        bp->bp_id = BootpID;
 
 
        /*
        /*
         * Calculate proper packet lengths taking into account the
         * Calculate proper packet lengths taking into account the
         * variable size of the options field
         * variable size of the options field
         */
         */
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + ext_len;
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + ext_len;
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
        NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
        NetSetTimeout(SELECT_TIMEOUT * CFG_HZ, BootpTimeout);
 
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
        dhcp_state = SELECTING;
        dhcp_state = SELECTING;
        NetSetHandler(DhcpHandler);
        NetSetHandler(DhcpHandler);
#else
#else
        NetSetHandler(BootpHandler);
        NetSetHandler(BootpHandler);
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
        NetSendPacket(NetTxPacket, pktlen);
        NetSendPacket(NetTxPacket, pktlen);
}
}
 
 
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
#if (CONFIG_COMMANDS & CFG_CMD_DHCP)
void DhcpOptionsProcess(char *popt)
void DhcpOptionsProcess(char *popt)
{
{
        char *end = popt + BOOTP_HDR_SIZE;
        char *end = popt + BOOTP_HDR_SIZE;
        int oplen, size;
        int oplen, size;
 
 
        while ( popt < end && *popt != 0xff ) {
        while ( popt < end && *popt != 0xff ) {
                oplen = *(popt + 1);
                oplen = *(popt + 1);
                switch(*popt) {
                switch(*popt) {
                        case  1:
                        case  1:
                                NetOurSubnetMask = *(IPaddr_t *)(popt + 2);
                                NetOurSubnetMask = *(IPaddr_t *)(popt + 2);
                                break;
                                break;
                        case  3:
                        case  3:
                                NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
                                NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
                                break;
                                break;
                        case  6:
                        case  6:
                                NetOurDNSIP = *(IPaddr_t *)(popt +2);
                                NetOurDNSIP = *(IPaddr_t *)(popt +2);
                                break;
                                break;
                        case 12:
                        case 12:
                                size = truncate_sz ("Host Name",
                                size = truncate_sz ("Host Name",
                                                    sizeof(NetOurHostName),
                                                    sizeof(NetOurHostName),
                                                    oplen);
                                                    oplen);
                                memcpy(&NetOurHostName, popt+2, size);
                                memcpy(&NetOurHostName, popt+2, size);
                                NetOurHostName[size] = 0 ;
                                NetOurHostName[size] = 0 ;
                                break;
                                break;
                        case 15:                /* Ignore Domain Name Option */
                        case 15:                /* Ignore Domain Name Option */
                                break;
                                break;
                        case 17:
                        case 17:
                                size = truncate_sz ("Root Path",
                                size = truncate_sz ("Root Path",
                                                    sizeof(NetOurRootPath),
                                                    sizeof(NetOurRootPath),
                                                    oplen);
                                                    oplen);
                                memcpy(&NetOurRootPath, popt+2, size);
                                memcpy(&NetOurRootPath, popt+2, size);
                                NetOurRootPath[size] = 0 ;
                                NetOurRootPath[size] = 0 ;
                                break;
                                break;
                        case 51:
                        case 51:
                                dhcp_leasetime = *(unsigned int *)(popt + 2);
                                dhcp_leasetime = *(unsigned int *)(popt + 2);
                                break;
                                break;
                        case 53:                /* Ignore Message Type Option */
                        case 53:                /* Ignore Message Type Option */
                                break;
                                break;
                        case 54:
                        case 54:
                                NetServerIP = *(IPaddr_t *)(popt+2);
                                NetServerIP = *(IPaddr_t *)(popt+2);
                                break;
                                break;
                        case 58:                /* Ignore Renewal Time Option */
                        case 58:                /* Ignore Renewal Time Option */
                                break;
                                break;
                        case 59:                /* Ignore Rebinding Time Option */
                        case 59:                /* Ignore Rebinding Time Option */
                                break;
                                break;
                        default:
                        default:
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_VENDOREX)
                            if (dhcp_vendorex_proc(popt))
                            if (dhcp_vendorex_proc(popt))
                                break;
                                break;
#endif
#endif
                                printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
                                printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
                                        *popt);
                                        *popt);
                                break;
                                break;
                }
                }
                popt += oplen + 2;      /* Process next option */
                popt += oplen + 2;      /* Process next option */
        }
        }
}
}
 
 
static int DhcpMessageType(unsigned char *popt)
static int DhcpMessageType(unsigned char *popt)
{
{
        if ((*(uint *)popt) != BOOTP_VENDOR_MAGIC)
        if ((*(uint *)popt) != BOOTP_VENDOR_MAGIC)
                return -1;
                return -1;
 
 
        popt += 4;
        popt += 4;
        while ( *popt != 0xff ) {
        while ( *popt != 0xff ) {
                if ( *popt == 53 )      /* DHCP Message Type */
                if ( *popt == 53 )      /* DHCP Message Type */
                        return *(popt + 2);
                        return *(popt + 2);
                popt += *(popt + 1) + 2;        /* Scan through all options */
                popt += *(popt + 1) + 2;        /* Scan through all options */
        }
        }
        return -1;
        return -1;
}
}
 
 
void DhcpSendRequestPkt(Bootp_t *bp_offer)
void DhcpSendRequestPkt(Bootp_t *bp_offer)
{
{
        volatile uchar *pkt, *iphdr;
        volatile uchar *pkt, *iphdr;
        Bootp_t *bp;
        Bootp_t *bp;
        int pktlen, iplen, extlen;
        int pktlen, iplen, extlen;
 
 
        debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
        debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
        pkt = NetTxPacket;
        pkt = NetTxPacket;
        memset ((void*)pkt, 0, PKTSIZE);
        memset ((void*)pkt, 0, PKTSIZE);
 
 
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
        NetSetEther(pkt, NetBcastAddr, PROT_IP);
        pkt += ETHER_HDR_SIZE;
        pkt += ETHER_HDR_SIZE;
 
 
        iphdr = pkt;            /* We'll need this later to set proper pkt size */
        iphdr = pkt;            /* We'll need this later to set proper pkt size */
        pkt += IP_HDR_SIZE;
        pkt += IP_HDR_SIZE;
 
 
        bp = (Bootp_t *)pkt;
        bp = (Bootp_t *)pkt;
        bp->bp_op = OP_BOOTREQUEST;
        bp->bp_op = OP_BOOTREQUEST;
        bp->bp_htype = HWT_ETHER;
        bp->bp_htype = HWT_ETHER;
        bp->bp_hlen = HWL_ETHER;
        bp->bp_hlen = HWL_ETHER;
        bp->bp_hops = 0;
        bp->bp_hops = 0;
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
        bp->bp_ciaddr =  bp_offer->bp_ciaddr;
        bp->bp_ciaddr =  bp_offer->bp_ciaddr;
        bp->bp_yiaddr =  bp_offer->bp_yiaddr;
        bp->bp_yiaddr =  bp_offer->bp_yiaddr;
        bp->bp_siaddr =  bp_offer->bp_siaddr;
        bp->bp_siaddr =  bp_offer->bp_siaddr;
        bp->bp_giaddr =  bp_offer->bp_giaddr;
        bp->bp_giaddr =  bp_offer->bp_giaddr;
        NetCopyEther(bp->bp_chaddr, NetOurEther);
        NetCopyEther(bp->bp_chaddr, NetOurEther);
 
 
        /*
        /*
         * ID is the id of the OFFER packet
         * ID is the id of the OFFER packet
         */
         */
 
 
        bp->bp_id = bp_offer->bp_id;
        bp->bp_id = bp_offer->bp_id;
 
 
        /*
        /*
         * Copy options from OFFER packet if present
         * Copy options from OFFER packet if present
         */
         */
        extlen = DhcpExtended(bp->bp_vend, DHCP_REQUEST, NetServerIP, bp->bp_yiaddr);
        extlen = DhcpExtended(bp->bp_vend, DHCP_REQUEST, NetServerIP, bp->bp_yiaddr);
 
 
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
        pktlen = BOOTP_SIZE - sizeof(bp->bp_vend) + extlen;
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
 
        debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
        debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
        NetSendPacket(NetTxPacket, pktlen);
        NetSendPacket(NetTxPacket, pktlen);
}
}
 
 
/*
/*
 *      Handle DHCP received packets.
 *      Handle DHCP received packets.
 */
 */
static void
static void
DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
{
        Bootp_t *bp = (Bootp_t *)pkt;
        Bootp_t *bp = (Bootp_t *)pkt;
 
 
        debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
        debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
                src, dest, len, dhcp_state);
                src, dest, len, dhcp_state);
 
 
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
                return;
 
 
        debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
        debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
                src, dest, len, dhcp_state);
                src, dest, len, dhcp_state);
 
 
        switch (dhcp_state) {
        switch (dhcp_state) {
        case SELECTING:
        case SELECTING:
                /*
                /*
                 * Wait an appropriate time for any potential DHCPOFFER packets
                 * Wait an appropriate time for any potential DHCPOFFER packets
                 * to arrive.  Then select one, and generate DHCPREQUEST response.
                 * to arrive.  Then select one, and generate DHCPREQUEST response.
                 * If filename is in format we recognize, assume it is a valid
                 * If filename is in format we recognize, assume it is a valid
                 * OFFER from a server we want.
                 * OFFER from a server we want.
                 */
                 */
                debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
                debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
#ifdef CFG_BOOTFILE_PREFIX
#ifdef CFG_BOOTFILE_PREFIX
                if (strncmp(bp->bp_file,
                if (strncmp(bp->bp_file,
                            CFG_BOOTFILE_PREFIX,
                            CFG_BOOTFILE_PREFIX,
                            strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
                            strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
#endif  /* CFG_BOOTFILE_PREFIX */
#endif  /* CFG_BOOTFILE_PREFIX */
 
 
                        debug ("TRANSITIONING TO REQUESTING STATE\n");
                        debug ("TRANSITIONING TO REQUESTING STATE\n");
                        dhcp_state = REQUESTING;
                        dhcp_state = REQUESTING;
#if 0
#if 0
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
                                DhcpOptionsProcess(&bp->bp_vend[4]);
                                DhcpOptionsProcess(&bp->bp_vend[4]);
 
 
#endif
#endif
                        BootpCopyNetParams(bp); /* Store net params from reply */
                        BootpCopyNetParams(bp); /* Store net params from reply */
 
 
                        NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
                        NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
                        DhcpSendRequestPkt(bp);
                        DhcpSendRequestPkt(bp);
#ifdef CFG_BOOTFILE_PREFIX
#ifdef CFG_BOOTFILE_PREFIX
                }
                }
#endif  /* CFG_BOOTFILE_PREFIX */
#endif  /* CFG_BOOTFILE_PREFIX */
 
 
                return;
                return;
                break;
                break;
        case REQUESTING:
        case REQUESTING:
                debug ("DHCP State: REQUESTING\n");
                debug ("DHCP State: REQUESTING\n");
 
 
                if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
                if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
                        char *s;
                        char *s;
 
 
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
                                DhcpOptionsProcess(&bp->bp_vend[4]);
                                DhcpOptionsProcess(&bp->bp_vend[4]);
                        BootpCopyNetParams(bp); /* Store net params from reply */
                        BootpCopyNetParams(bp); /* Store net params from reply */
                        dhcp_state = BOUND;
                        dhcp_state = BOUND;
                        printf("DHCP client bound to address ");
                        printf("DHCP client bound to address ");
                        print_IPaddr(NetOurIP);
                        print_IPaddr(NetOurIP);
                        printf("\n");
                        printf("\n");
 
 
                        /* Obey the 'autoload' setting */
                        /* Obey the 'autoload' setting */
                        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
                        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
                                NetState = NETLOOP_SUCCESS;
                                NetState = NETLOOP_SUCCESS;
                                return;
                                return;
                        }
                        }
                        /* Send ARP request to get TFTP server ethernet address.
                        /* Send ARP request to get TFTP server ethernet address.
                         * This automagically starts TFTP, too.
                         * This automagically starts TFTP, too.
                         */
                         */
                        ArpRequest();
                        ArpRequest();
                        return;
                        return;
                }
                }
                break;
                break;
        default:
        default:
                printf("DHCP: INVALID STATE\n");
                printf("DHCP: INVALID STATE\n");
                break;
                break;
        }
        }
 
 
}
}
 
 
void DhcpRequest(void)
void DhcpRequest(void)
{
{
        BootpRequest();
        BootpRequest();
}
}
#endif  /* CFG_CMD_DHCP */
#endif  /* CFG_CMD_DHCP */
 
 
#endif /* CFG_CMD_NET */
#endif /* CFG_CMD_NET */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.