⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcpboot.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 3 页
字号:
/* dhcpboot.c: *  This code implements a subset of the DHCP client protocol. *  Based on RFC2131 spec, the "automatic allocation" mode, in which DHCP *  assigns a permanent IP address to a client, is the only mode supported. * *  The idea is that the monitor boots up, and if IPADD is set to DHCP, then *  DHCP is used to populate shell variables with a server-supplied IP *  address, NetMask and Gateway IP address. Then, when the application *  is launched (probably via TFS), it can retrieve the content of those *  shell variables for use by the application. * *  Sequence of events for this limited implementation of DHCP... *  Client issues a DHCP_DISCOVER, server responds with a DHCP_OFFER, *  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. *  REQUEST: request by the client for the server (now known because an OFFER *      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 *  allocation mode" (infinite lease time).  There are several different *  application-specific enhancements that can be added and hopefully *  they have been isolated through the use of the dhcp_00.c file. *  I've attempted to isolate as much of the non-generic code to *  the file dhcp_XX.c (where dhcp_00.c is the default code).  If non-default *  code is necessary, then limit the changes to a new dhcp_XX.c file.  This *  will allow the code in this file to stay generic; hence, the user of this *  code will be able to accept monitor upgrades without the need to touch *  this file.  The makefile must link in some additional dhcp_XX.c file *  (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  *  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  *  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! * *  General notice: *  This code is part of a boot-monitor package developed as a generic base *  platform for embedded system designs.  As such, it is likely to be *  distributed to various projects beyond the control of the original *  author.  Please notify the author of any enhancements made or bugs found *  so that all may benefit from the changes.  In addition, notification back *  to the author will allow the new user to pick up changes that may have *  been made by other users after this version of the code was distributed. * *  Note1: the majority of this code was edited with 4-space tabs. *  Note2: as more and more contributions are accepted, the term "author" *         is becoming a mis-representation of credit. * *  Original author:    Ed Sutter *  Email:              esutter@lucent.com *  Phone:              908-582-2351 */#include "config.h"#include "endian.h"#include "cpuio.h"#include "ether.h"#include "tfs.h"#include "tfsprivate.h"#include "genlib.h"#include "stddefs.h"#include "cli.h"int DHCPStartup(short), BOOTPStartup(short);int DhcpSetEnv(char *,char *);int SendDHCPDiscover(int,short);void dhcpDumpVsa(void), printDhcpOptions(uchar *);unsigned short  DHCPState;#if INCLUDE_DHCPBOOTstatic int      DHCPCommandIssued;static ulong    DHCPTransactionId;/* Variables used for DHCP Class ID specification: */static char *DHCPClassId;static int  DHCPClassIdSize;/* Variables used for DHCP Client ID specification: */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;/* Variable to keep track of elapsed seconds since DHCP started: */static short    DHCPElapsedSecs;char *DhcpHelp[] = {    "Issue a DHCP discover",    "-[bvV] [vsa]",    "Options...",    " -b      use bootp",    " -v|V    verbosity",        0,};intDhcp(int argc,char *argv[]){    int opt, bootp;    bootp = 0;    DHCPCommandIssued = 1;    while ((opt=getopt(argc,argv,"bvV")) != -1) {        switch(opt) {        case 'b':            bootp = 1;            break;        case 'v':            EtherVerbose = SHOW_DHCP;            break;        case 'V':            EtherVerbose = DHCP_VERBOSE;            break;        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);    /* Initialize the retransmission delay calculator: */    RetransmitDelay(DELAY_INIT_DHCP);    if (bootp) {        DHCPState = BOOTPSTATE_INITIALIZE;        BOOTPStartup(0);    }    else {        DHCPState = DHCPSTATE_INITIALIZE;        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(). */voiddhcpDumpVsa(void){    int     i;    char    tmp[3],  *vsa_b, *vsa_a, len;    vsa_a = getenv("DHCPVSA");    if (!vsa_a)        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(vsa_b+4);    free(vsa_b);}voiddhcpDisable(){    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.*/intDHCPStartup(short seconds){    char    *id, *colon, *rlist;#if !INCLUDE_TFTP    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));}intBOOTPStartup(short seconds){    return(SendDHCPDiscover(1,seconds));}uchar *dhcpLoadShellVarOpts(uchar *options){    if (DHCPClassIdSize) {        *options++ = DHCPOPT_CLASSID;        *options++ = DHCPClassIdSize;        memcpy(options,DHCPClassId,DHCPClassIdSize);        options += DHCPClassIdSize;    }    if (DHCPClientIdSize) {        *options++ = DHCPOPT_CLIENTID;        *options++ = DHCPClientIdSize+1;        *options++ = DHCPClientIdType;        memcpy(options,DHCPClientId,DHCPClientIdSize);        options += DHCPClientIdSize;    }    if (DHCPRqstListSize) {        *options++ = DHCPOPT_PARMRQSTLIST;        *options++ = DHCPRqstListSize;        memcpy(options,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). */intSendDHCPDiscover(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,BinEnetAddr,6);    memcpy((char *)&te->ether_dhost,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(dhcpdata->bootfile,0,sizeof(dhcpdata->bootfile));    memset(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(dhcpdata->client_macaddr,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(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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -