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

📄 dhcp_prot.c

📁 Mavell 无线模块原厂IC AP32源代码。DHCP客户端与服务端源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*==========================================================================////      dhcp_prot.c////      DHCP protocol implementation for DHCP client////==========================================================================//####ECOSPDCOPYRIGHTBEGIN####//// Copyright (C) 2000, 2001, 2002 Red Hat, Inc.// All Rights Reserved.//// Permission is granted to use, copy, modify and redistribute this// file.////####ECOSPDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):   hmt// Contributors: gthomas// Date:        2000-07-01// Purpose:     DHCP support// Description: ////####DESCRIPTIONEND####////========================================================================*//* Define these locally because we are porting this code from a later package, * therefore these are not defined in pkgconf/net.h */#define CYGPKG_NET_DHCP#define CYGOPT_NET_DHCP_DHCP_THREAD#ifdef CYGPKG_NET_DHCP#include <pkgconf/system.h>#include <pkgconf/net.h>#if 0#define perror( txt ) // nothing#endif#include <network.h>#include <dhcp.h>#include <errno.h>#include <cyg/infra/cyg_ass.h>#ifdef INET6#include <net/if_var.h>#include <netinet6/in6_var.h>#endif#ifdef AP5X#include "oem.h"#define DHCP_TIMEOUT_IN_SEC 20#else//#define CYGDBG_NET_DHCP_CHATTER#ifdef CYGDBG_NET_DHCP_CHATTER#define perror diag_printf#endif#include "buildModes.h"#endif// ------------------------------------------------------------------------// Returns a pointer to the end of dhcp message (or NULL if invalid)// meaning the address of the byte *after* the TAG_END token in the vendor// data.static unsigned char *scan_dhcp_size( struct bootp *ppkt ){    unsigned char *op;    op = &ppkt->bp_vend[0];    // First check for the cookie!    if ( op[0] != 99 ||            op[1] != 130 ||            op[2] != 83 ||            op[3] != 99 )    {        CYG_FAIL( "Bad DHCP cookie" );        return NULL;    }    op += 4;    while (*op != TAG_END)    {#if 1        if(*op == 0x0f)  /* temp code to bypass the len problem, later remove this        				  if stat completely */        {            //op += *(op + 1) + 2;            *op = TAG_END;        }        else#endif        {            op += *(op + 1) + 2;        }#if 1        if ( op > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in dhcp_size");            return NULL;        }#endif    }    // Check op has not gone wild    CYG_ASSERT( op > (unsigned char *)(&ppkt[0]), "op pointer underflow!" );    // Compare op with non-existent "next" struct bootp in the array.    CYG_ASSERT( op < (unsigned char *)(&ppkt[1]), "op pointer overflow!" );    return op + 1; // Address of first invalid byte}// ------------------------------------------------------------------------// Get the actual packet size of an initialized bufferstatic intdhcp_size( struct bootp *ppkt ){    unsigned char *op;    op = scan_dhcp_size( ppkt );    if ( !op )        return 0;    return (op - (unsigned char *)ppkt);}// ------------------------------------------------------------------------// Get the actual packet size of an initialized buffer// This will also pad the packet with 0 if length is less// than BP_STD_TX_MINPKTSZ.static intdhcp_size_for_send( struct bootp *ppkt ){    unsigned char *op;    op = scan_dhcp_size( ppkt );    if ( !op )        return 0; // Better not scribble!    // Zero extra bytes until the packet is large enough.    for ( ; op < (((unsigned char *)ppkt) + BP_STD_TX_MINPKTSZ); op++ )        *op = 0;    return (op - (unsigned char *)ppkt);}// ------------------------------------------------------------------------// Insert/set an option value in an initialized bufferstatic intset_fixed_tag( struct bootp *ppkt,               unsigned char tag,               cyg_uint32 value,               int len){    unsigned char *op;    // Initially this will only scan the options field.    op = &ppkt->bp_vend[4];    while (*op != TAG_END)    {        if ( op > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in set_fixed_tag" );            return false;        }        if (*op == tag)                 // Found it...            break;        op += *(op + 1) + 2;    }    if (*op == tag)    { // Found it...        if ( *(op + 1) != len )        {            CYG_FAIL( "Wrong size in set_fixed_tag" );            return false;           // wrong size        }    }    else    { // overwrite the end tag and install a new one        if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in set_fixed_tag append" );            return false;        }        *op = tag;        *(op + 1) = len;        *(op + len + 2) = TAG_END;    }    // and insert the value.  Net order is BE.    op += len + 2 - 1;              // point to end of value    while ( len-- > 0 )    {        *op-- = (unsigned char)(value & 255);        value >>= 8;    }    return true;}// Note that this does not permit changing the size of an extant tag.static intset_variable_tag( struct bootp *ppkt,                  unsigned char tag,                  cyg_uint8 *pvalue,                  int len){    unsigned char *op;    // Initially this will only scan the options field.    op = &ppkt->bp_vend[4];    while (*op != TAG_END)    {        if ( op > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in set_variable_tag" );            return false;        }        if (*op == tag)                 // Found it...            break;        op += *(op + 1) + 2;    }    if (*op == tag)    { // Found it...        if ( *(op + 1) != len )        {            CYG_FAIL( "Wrong size in set_variable_tag" );            return false;           // wrong size        }    }    else    { // overwrite the end tag and install a new one        if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in set_variable_tag append" );            return false;        }        *op = tag;        *(op + 1) = len;        *(op + len + 2) = TAG_END;    }    // and insert the value.  No order is implied.    op += 2;               // point to start of value    while ( len-- > 0 )    {        *op++ = *pvalue++;    }    return true;}static intunset_tag( struct bootp *ppkt,           unsigned char tag ){    unsigned char *op, *nextp = 0, *killp = 0;    // Initially this will only scan the options field.    op = &ppkt->bp_vend[4];    while (*op != TAG_END)    {        if ( op > &ppkt->bp_vend[BP_VEND_LEN - 1] )        {            CYG_FAIL( "Oversize DHCP packet in unset_tag" );            return false;        }        if (*op == tag)        {               // Found it...            killp = op;                 // item to kill            nextp = op + *(op + 1) + 2;     // next item address        }        op += *(op + 1) + 2;                // scan to the end    }    if ( !killp )        return false;    // Obliterate the found op by copying down: *op is the end.    while ( nextp <= op )                // <= to copy the TAG_END too.        *killp++ = *nextp++;    return true;}// ------------------------------------------------------------------------// Bring up an interface enough to broadcast, before we know who we arestatic intbring_half_up(const char *intf, struct ifreq *ifrp, int *s_p , cyg_uint8 state ){    int s;    int one = 1;    struct sockaddr_in *addrp;    s = socket(AF_INET, SOCK_DGRAM, 0);    *s_p = s;    if (s < 0)    {        perror("socket");        return false;    }    if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)))    {        perror("setsockopt");        return false;    }    addrp = (struct sockaddr_in *) &ifrp->ifr_addr;    memset(addrp, 0, sizeof(*addrp));    addrp->sin_family = AF_INET;    addrp->sin_len = sizeof(*addrp);    addrp->sin_port = 0;    addrp->sin_addr.s_addr = INADDR_ANY;    strcpy(ifrp->ifr_name, intf);    /* ioctl calls only on init, MAC addr get is for building packet*/    if(state == DHCPSTATE_INIT){    if (ioctl(s, SIOCSIFADDR, ifrp))    { /* set ifnet address */	        if (errno != EEXIST) {        perror("SIOCSIFADDR");#ifdef CYGDBG_NET_DHCP_CHATTER	            diag_printf (" errno = %d\n", errno);#endif        return false;    }	    }    if (ioctl(s, SIOCSIFNETMASK, ifrp))    { /* set net addr mask */        perror("SIOCSIFNETMASK");        return false;    }    /* the broadcast address is 255.255.255.255 */    memset(&addrp->sin_addr, 255, sizeof(addrp->sin_addr));    if (ioctl(s, SIOCSIFBRDADDR, ifrp))    { /* set broadcast addr */        perror("SIOCSIFBRDADDR");        return false;    }    ifrp->ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;    if (ioctl(s, SIOCSIFFLAGS, ifrp))    { /* set ifnet flags */        perror("SIOCSIFFLAGS up");        return false;    }    }    if (ioctl(s, SIOCGIFHWADDR, ifrp) < 0)    { /* get MAC address */        perror("SIOCGIFHWADDR 1");        return false;    }    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))        {        perror("setsockopt SO_REUSEADDR");            return false;        }    if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)))    {        perror("setsockopt SO_REUSEPORT");        return false;    }    *s_p = s;    return true;}// ------------------------------------------------------------------------// DHCP retransmission timeouts and number of tries//// To work better with simulated failures (or real ones!) so that the rest// of the system is tested, rather than DHCP renewal failures pulling// everything down, we try a little more zealously than the RFC suggests.static unsigned char timeout_random = 0;struct timeout_state{    unsigned int secs;    int countdown;};static inline void reset_timeout( struct timeval *ptv, struct timeout_state *pstate ){    timeout_random++;    pstate->countdown = 4; // initial fast retries    pstate->secs = 3 + (timeout_random & 3);    ptv->tv_sec = 0;    ptv->tv_usec = 65536 * (2 + (timeout_random & 3)); // 0.1 - 0.3S, about//    ptv->tv_usec = 65536 * (7 + (timeout_random & 3)); // 0.1 - 0.3S, about}static inline int next_timeout( struct timeval *ptv, struct timeout_state *pstate ){    if ( 0 < pstate->countdown-- )        return true;    if ( 0 == ptv->tv_sec )        ptv->tv_sec = pstate->secs;

⌨️ 快捷键说明

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