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

📄 dhcp_prot.c

📁 Mavell 无线模块原厂IC AP32源代码。DHCP客户端与服务端源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    else    {        timeout_random++;        pstate->secs = ptv->tv_sec * 2 - 2 + (timeout_random & 3);        pstate->countdown = 2; // later fast retries        ptv->tv_sec = 0;    }    return (pstate->secs < DHCP_TIMEOUT_IN_SEC); // If longer, too many tries...}// ------------------------------------------------------------------------// Lease expiry and alarms to notify itstatic cyg_alarm_t alarm_function;static void alarm_function(cyg_handle_t alarm, cyg_addrword_t data){    struct dhcp_lease *lease = (struct dhcp_lease *)data;#ifdef CYGDBG_NET_DHCP_CHATTER     diag_printf("alarm_function\n");#endif    lease->which |= lease->next;    if ( lease->needs_attention )        cyg_semaphore_post( lease->needs_attention );    // Step the lease on into its next state of being alarmed ;-)    if ( lease->next & DHCP_LEASE_EX )    {        cyg_alarm_disable( alarm );    }    else if ( lease->next & DHCP_LEASE_T2 )    {        lease->next = DHCP_LEASE_EX;        cyg_alarm_initialize( lease->alarm, lease->expiry, 0 );        cyg_alarm_enable( lease->alarm );    }    else if ( lease->next & DHCP_LEASE_T1 )    {        lease->next = DHCP_LEASE_T2;        cyg_alarm_initialize( lease->alarm, lease->t2, 0 );        cyg_alarm_enable( lease->alarm );    }}static inline void no_lease( struct dhcp_lease *lease ){    if ( lease->alarm )    {        // Already set: delete this.        cyg_alarm_disable( lease->alarm );        cyg_alarm_delete( lease->alarm );        lease->alarm = 0;    }}static inline void new_lease( struct bootp *bootp, struct dhcp_lease *lease ){    cyg_tick_count_t now = cyg_current_time();    cyg_tick_count_t then;    cyg_uint32 tag = 0;    cyg_uint32 expiry_then;    cyg_resolution_t resolution =        cyg_clock_get_resolution(cyg_real_time_clock());    cyg_handle_t h;    unsigned int length;#ifdef CYGDBG_NET_DHCP_CHATTER     diag_printf("new_lease  \n");#endif    // Silence any jabbering from past lease on this interface    no_lease( lease );    lease->which = lease->next = 0;    cyg_clock_to_counter(cyg_real_time_clock(), &h);    cyg_alarm_create( h, alarm_function, (cyg_addrword_t)lease,                      &lease->alarm, &lease->alarm_obj );    // extract the lease time and scale it &c to now.    length = sizeof(tag);    if (!get_bootp_option( bootp, TAG_DHCP_LEASE_TIME, &tag ))        tag = 0xffffffff;    if ( 0xffffffff == tag )    {        lease->expiry = 0xffffffffffffffff;        lease->t2 = 0xffffffffffffffff;        lease->t1 = 0xffffffffffffffff;        return ; // it's an infinite lease, hurrah!    }    then = (cyg_uint64)(ntohl(tag));    expiry_then = then;    then *= 1000000000; // into nS - we know there is room in a tick_count_t    then = (then / resolution.dividend) * resolution.divisor; // into system ticks    lease->expiry = now + then;    length = sizeof(tag);    if (get_bootp_option( bootp, TAG_DHCP_REBIND_TIME, &tag ))        then = (cyg_uint64)(ntohl(tag));    else        then = expiry_then - expiry_then / 4;    then *= 1000000000; // into nS - we know there is room in a tick_count_t    then = (then / resolution.dividend) * resolution.divisor; // into system ticks    lease->t2 = now + then;    length = sizeof(tag);    if (get_bootp_option( bootp, TAG_DHCP_RENEWAL_TIME, &tag ))        then = (cyg_uint64)(ntohl(tag));    else        then = expiry_then / 2;    then *= 1000000000; // into nS - we know there is room in a tick_count_t    then = (then / resolution.dividend) * resolution.divisor; // into system ticks    lease->t1 = now + then;#if 0 // for testing this mechanism    lease->expiry = now + 5000; // 1000 here makes for failure in the DHCP test    lease->t2 = now + 3500;    lease->t1 = now + 2500;#endif#ifdef CYGDBG_NET_DHCP_CHATTER    diag_printf("new_lease:\n");    diag_printf("  expiry = %d\n", lease->expiry);    diag_printf("      t1 = %d\n", lease->t1);    diag_printf("      t2 = %d\n", lease->t2);#endif    lease->next = DHCP_LEASE_T1;    cyg_alarm_initialize( lease->alarm, lease->t1, 0 );    cyg_alarm_enable( lease->alarm );}// ------------------------------------------------------------------------// Set all the tags we want to use when sending a packet.// This has expanded to a large, explicit set to interwork better// with a variety of DHCP servers.static void set_default_dhcp_tags( struct bootp *xmit ){    // Explicitly request full set of params that are default for LINUX    // dhcp servers, but not default for others.  This is rather arbitrary,    // but it preserves behaviour for people using those servers.    // Perhaps configury of this set will be needed in future?    //    // Here's the set:    static cyg_uint8 req_list[] = {#ifdef CYGOPT_NET_DHCP_PARM_REQ_LIST_REPLACE                                      CYGOPT_NET_DHCP_PARM_REQ_LIST_REPLACE ,#else                                      TAG_DHCP_SERVER_ID ,      //     DHCP server id: 10.16.19.66                                      TAG_DHCP_LEASE_TIME ,      //     DHCP time 51: 60                                      TAG_DHCP_RENEWAL_TIME ,      //     DHCP time 58: 30                                      TAG_DHCP_REBIND_TIME ,      //     DHCP time 59: 52                                      TAG_SUBNET_MASK ,      //     subnet mask: 255.255.255.0                                      //        TAG_GATEWAY           ,     //     gateway: 10.16.19.66                                      TAG_DOMAIN_SERVER ,      //     domain server: 10.16.19.66                                      TAG_DOMAIN_NAME ,      //     domain name: hmt10.cambridge.redhat.com                                      TAG_IP_BROADCAST ,      //     IP broadcast: 10.16.19.255#endif#ifdef CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL                                      CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL ,#endif                                  };    if ( req_list[0] ) // So that one may easily turn it all off by configury        set_variable_tag( xmit, TAG_DHCP_PARM_REQ_LIST,                          &req_list[0], sizeof( req_list ) );    // Explicitly specify our max message size.#ifndef BP_MAXPKTSZ#define BP_MAXPKTSZ 364#endif    set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MAXPKTSZ, 2 );}#ifndef ORIG_DHCP_CODE/* this code is intended to overcome the failure of socket interface to sent to a  a specific interface.  we cannot use the "default route "  because it harms routing in the LAN *//* buffer type definition */typedef struct {        unsigned int key;        unsigned int totalLen;#ifdef GATEWAY        unsigned int interface;/*0 - LAN ;1 - WAN*/#endif        unsigned char data[1600];} dsQ_LlcData_t;/* buff allocation function type definition */extern dsQ_LlcData_t *ds_GetLlcDataBuf(void);/* driver send function type definition */extern  int dsQ_LlcDataWriteNoBlock(dsQ_LlcData_t *txbd);/* IP header format */typedef struct dhcp_iphdr {        char verhdrlen;        char service;        unsigned short len;        unsigned short ident;        unsigned short frags;        char ttl;        char protocol;        unsigned short chksum;        cyg_uint32        saddr;        cyg_uint32        daddr;}P_ip_hdr_dhcp;/* IP checksum calculation */unsigned short dhcp_ipchksum(register unsigned short *ip, register int len){    unsigned long sum = 0;    len >>= 1;    while (len--)    {        sum += *(ip++);        if (sum > 0xFFFF)            sum -= 0xFFFF;    }    return((~sum) & 0x0000FFFF);}int dhcp_send_broadcast_to_driver(            cyg_uint32 datalen,            cyg_uint8 *data_PTR,            cyg_uint8 *my_mac_addr){    /* build the packet and send it directly to WAN driver */    dsQ_LlcData_t *txbd;    P_ip_hdr_dhcp *ip_hdr_PTR;    cyg_uint16 *u16_PTR;#ifdef CYGDBG_NET_DHCP_CHATTER    diag_printf("\n dhcp_send_broadcast_to_driver\n");#endif    /*allocate application buffer */    txbd = ds_GetLlcDataBuf();    if (txbd == NULL) {      return -1;#ifdef CYGDBG_NET_DHCP_CHATTER        diag_printf("dhcp_send_broadcast_to_driver: failed to alloc buffer\n");#endif    }    /* fill buffer parameters */    txbd->key = 0;  /* key 0 mean no notification on Transmit completed */    #ifdef GATEWAY    txbd->interface = 1; /* WAN eth interface */#endif        txbd->totalLen = datalen + 42;  /* Eth size = 14 , ip size  20 , udp size= 8 = 42*/    /* copy dhcp data */    memcpy(txbd->data + 42, data_PTR, datalen);    /* clear header areas */    memset(txbd->data, 0,42);/* build IP UDP and ETHernet */  /* ========= */  /* build UDP */  /* ========= */    /* src port 68 */    txbd->data[35] = 68;    /* dest port 67 */    txbd->data[37] = 67;    /* length */    u16_PTR =(cyg_uint16 *) &(txbd->data[38]);    datalen += 8;/* data size including UDP length */    *u16_PTR = htons(datalen);    /* leave checksum to 0  */  /* ========= */  /* build IP */  /* ========= */    ip_hdr_PTR = (P_ip_hdr_dhcp *)(txbd->data + 14);    ip_hdr_PTR->verhdrlen = 0x45;    ip_hdr_PTR->service = 0;    datalen +=  20;/* add ip header size to data size */    ip_hdr_PTR->len = htons(datalen);    ip_hdr_PTR->ident = 0x7179;//    ip_hdr_PTR->frags = htons(0x4000);    ip_hdr_PTR->ttl = 1;    ip_hdr_PTR->protocol = 17;/* UDP */    /* dest IP 255.255.255.255 - limited broadcast       not doe directly due to problems in ARM arc which wrote it aligned to       2 bytes below*/    memset(txbd->data + 30 ,0xff, 4);    ip_hdr_PTR->chksum = dhcp_ipchksum((unsigned short *)ip_hdr_PTR, 20);  /* ========= */  /* build Eth */  /* ========= */     txbd->data[12] = 0x08; /* ip Ethertype 0800 */     /* src Eth address */     memcpy( (txbd->data + 6),my_mac_addr, 6);     /* dest addr Eth address */     u16_PTR = (cyg_uint16 *)(txbd->data);     u16_PTR[0] = 0xFFFF;     u16_PTR[1] = 0xFFFF;     u16_PTR[2] = 0xFFFF;    /*try to send the frame to the bridge task*/    dsQ_LlcDataWriteNoBlock(txbd);    return 1;}#endif// ------------------------------------------------------------------------// the DHCP state machine - this does all the workintdo_dhcp(const char *intf, struct bootp *res,        cyg_uint8 *pstate, struct dhcp_lease *lease){    struct ifreq ifr;    struct sockaddr_in cli_addr, broadcast_addr, server_addr, rx_addr;    int s, addrlen;    unsigned char mincookie[] = {99, 130, 83, 99, 255} ;    struct timeval tv;    struct timeout_state timeout_scratch;    cyg_uint8 oldstate = *pstate;    cyg_uint8 msgtype = 0, seen_bootp_reply = 0;    unsigned int length;    cyg_uint32 xid;#define CHECK_XID() (  /* and other details */                                  \    received->bp_xid   != xid            || /* not the same transaction */      \    received->bp_htype != xmit->bp_htype || /* not the same ESA type    */      \    received->bp_hlen  != xmit->bp_hlen  || /* not the same length      */      \    bcmp( &received->bp_chaddr, &xmit->bp_chaddr, xmit->bp_hlen )               \    )    // IMPORTANT: xmit is the same as res throughout this; *received is a    // scratch buffer for reception; its contents are always copied to res    // when we are happy with them.  So we always transmit from the    // existing state.    struct bootp rx_local;    struct bootp *received = &rx_local;    struct bootp *xmit = res;    struct bootp xmit2;    int xlen;    // First, get a socket on the interface in question.  But Zeroth, if    // needs be, bring it to the half-up broadcast only state if needs be.#ifdef CYGDBG_NET_DHCP_CHATTER     diag_printf("do_dhcp:  on interface %s\n",intf);#endif    if ( DHCPSTATE_INIT == oldstate            || DHCPSTATE_FAILED == oldstate            || 0 == oldstate )    {        // either explicit init state or the beginning of time or retry        *pstate = DHCPSTATE_INIT;    }    if ( ! bring_half_up(  intf, &ifr,&s, *pstate ) ){    	if(s >= 0)            close(s);        return false;    }    memset((char *) &cli_addr, 0, sizeof(cli_addr));    cli_addr.sin_family = AF_INET;    cli_addr.sin_len = sizeof(cli_addr);    cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);    cli_addr.sin_port = htons(IPPORT_BOOTPC);    memset((char *) &broadcast_addr, 0, sizeof(broadcast_addr));    broadcast_addr.sin_family = AF_INET;    broadcast_addr.sin_len = sizeof(broadcast_addr);    broadcast_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);    broadcast_addr.sin_port = htons(IPPORT_BOOTPS);    memset((char *) &server_addr, 0, sizeof(server_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_len = sizeof(server_addr);    server_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST); // overwrite later    server_addr.sin_port = htons(IPPORT_BOOTPS);    if (bind(s, (struct sockaddr *) &cli_addr, sizeof(cli_addr)) < 0)    {        perror("bind error");        close(s);        return false;    }    // Now, we can launch into the DHCP state machine.  I think this will    // be the neatest way to do it; it returns from within the switch arms    // when all is well, or utterly failed.    reset_timeout( &tv, &timeout_scratch );

⌨️ 快捷键说明

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