关于移植W5500 DHCP获取IP失败

2019-07-21 00:30发布

下面是部分代码,我用红 {MOD}标记了下 我跟踪后执行的步骤 不知分析的是否对。请用过的人帮看下。一直获取不到IP 总是在检查超时--发DISSEVER包---在返回获取失败

/**
*@brief                发送DISCOVER信息给DHCP服务器
*@param                无
*@return        无
*/
void send_DHCP_DISCOVER(void)
{
        uint8 ip[4] = {255,255,255,255};
        uint16 i=0;
        //the host name modified
        uint8 host_name[12];
        //*((uint32*)DHCP_SIP)=0;
        //*((uint32*)DHCP_REAL_SIP)=0;
        memset((void*)pRIPMSG,0,sizeof(RIP_MSG));                                /*清空pRIPMSG的 sizeof(RIP_MSG)        个空间*/
       
        pRIPMSG->op = DHCP_BOOTREQUEST;
        pRIPMSG->htype = DHCP_HTYPE10MB;
        pRIPMSG->hlen = DHCP_HLENETHERNET;
        pRIPMSG->hops = DHCP_HOPS;
        pRIPMSG->xid = htonl(DHCP_XID);
        pRIPMSG->secs = htons(DHCP_SECS);
        pRIPMSG->flags =htons(DHCP_FLAGSBROADCAST);
        pRIPMSG->chaddr[0] = SRC_MAC_ADDR[0];
        pRIPMSG->chaddr[1] = SRC_MAC_ADDR[1];
        pRIPMSG->chaddr[2] = SRC_MAC_ADDR[2];
        pRIPMSG->chaddr[3] = SRC_MAC_ADDR[3];
        pRIPMSG->chaddr[4] = SRC_MAC_ADDR[4];
        pRIPMSG->chaddr[5] = SRC_MAC_ADDR[5];   
       
       
        /* MAGIC_COOKIE */
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 24)& 0xFF);
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 16)& 0xFF);
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 8)& 0xFF);
        pRIPMSG->OPT[i++] = (uint8)(MAGIC_COOKIE& 0xFF);
       
        /* Option Request Param. */
        pRIPMSG->OPT[i++] = dhcpMessageType;
        pRIPMSG->OPT[i++] = 0x01;
        pRIPMSG->OPT[i++] = DHCP_DISCOVER;
       
        /*Client identifier*/
        pRIPMSG->OPT[i++] = dhcpClientIdentifier;
        pRIPMSG->OPT[i++] = 0x07;
        pRIPMSG->OPT[i++] = 0x01;
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[0];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[1];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[2];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[3];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[4];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[5];
       
        // host name
        pRIPMSG->OPT[i++] = hostName;
        // set the host name
        sprintf((char*)host_name,"%.4s-%02X%02X%02X",DEVICE_ID,SRC_MAC_ADDR[3],SRC_MAC_ADDR[4],SRC_MAC_ADDR[5]);
       
       
        pRIPMSG->OPT[i++] = (uint8)strlen((char*)host_name);
       
        strcpy((char*)(&(pRIPMSG->OPT)),(char*)host_name);
       
       
        i+=(uint16)strlen((char*)host_name);       
       
        pRIPMSG->OPT[i++] = dhcpParamRequest;
        pRIPMSG->OPT[i++] = 0x06;
        pRIPMSG->OPT[i++] = subnetMask;
        pRIPMSG->OPT[i++] = routersOnSubnet;
        pRIPMSG->OPT[i++] = dns;
        pRIPMSG->OPT[i++] = domainName;
        pRIPMSG->OPT[i++] = dhcpT1value;
        pRIPMSG->OPT[i++] = dhcpT2value;
        pRIPMSG->OPT[i++] = endOption;
       
        /* send broadcasting packet */
        //printf("send dhcp discover %s ",EXTERN_DHCPBUF);
        //for(uint8 i=0; i<3; i++)
        //Delay_ms(800);
        sendto(SOCK_DHCP, (uint8 *)pRIPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);       
       
        #ifdef DHCP_DEBUG       
        printf("sent DHCP_DISCOVER ");
        #endif       
}


/**
*@brief                发送释放消息
*@param                msgtype:是否为7
*@return        无
*/
void send_DHCP_RELEASE_DECLINE(char msgtype)
{
        uint16 i =0;
        uint8  ip[4];
       
        memset((void*)pRIPMSG,0,sizeof(RIP_MSG));
       
        pRIPMSG->op = DHCP_BOOTREQUEST;
        pRIPMSG->htype = DHCP_HTYPE10MB;
        pRIPMSG->hlen = DHCP_HLENETHERNET;
        pRIPMSG->hops = DHCP_HOPS;
        pRIPMSG->xid = htonl(DHCP_XID);
        pRIPMSG->secs = htons(DHCP_SECS);
        pRIPMSG->flags =0;// DHCP_FLAGSBROADCAST;
       
        memcpy(pRIPMSG->chaddr,SRC_MAC_ADDR,6);
       
        /* MAGIC_COOKIE */
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 24) & 0xFF);
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 16) & 0xFF);
        pRIPMSG->OPT[i++] = (uint8)((MAGIC_COOKIE >> 8) & 0xFF);
        pRIPMSG->OPT[i++] = (uint8)(MAGIC_COOKIE & 0xFF);
       
        /* Option Request Param. */
        pRIPMSG->OPT[i++] = dhcpMessageType;
        pRIPMSG->OPT[i++] = 0x01;
        pRIPMSG->OPT[i++] = ((!msgtype) ? DHCP_RELEASE : DHCP_DECLINE);
       
        pRIPMSG->OPT[i++] = dhcpClientIdentifier;
        pRIPMSG->OPT[i++] = 0x07;
        pRIPMSG->OPT[i++] = 0x01;
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[0];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[1];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[2];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[3];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[4];
        pRIPMSG->OPT[i++] = SRC_MAC_ADDR[5];       
       
        pRIPMSG->OPT[i++] = dhcpServerIdentifier;
        pRIPMSG->OPT[i++] = 0x04;
        pRIPMSG->OPT[i++] = DHCP_SIP[0];
        pRIPMSG->OPT[i++] = DHCP_SIP[1];
        pRIPMSG->OPT[i++] = DHCP_SIP[2];
        pRIPMSG->OPT[i++] = DHCP_SIP[3];
       
        if(msgtype)
        {
        pRIPMSG->OPT[i++] = dhcpRequestedIPaddr;
        pRIPMSG->OPT[i++] = 0x04;
        pRIPMSG->OPT[i++] = GET_SIP[0];
        pRIPMSG->OPT[i++] = GET_SIP[1];
        pRIPMSG->OPT[i++] = GET_SIP[2];
        pRIPMSG->OPT[i++] = GET_SIP[3];               
        #ifdef DHCP_DEBUG               
        printf("sent DHCP_DECLINE ");
        #endif               
        }
        #ifdef DHCP_DEBUG       
        else
        {
        printf("sent DHCP_RELEASE ");
        }
        #endif       
       
        pRIPMSG->OPT[i++] = endOption;       
       
       
        if(msgtype) memset(ip,0xFF,4);
        else
        memcpy(ip,DHCP_SIP,4);
        //printf("send dhcp decline ");
        sendto(SOCK_DHCP, (uint8 *)pRIPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
}

/**         
*@brief                 解析获得的DHCP消息
*@param                length:解析消息长度
*@return        0:解析失败  其他:解析成功
*/
uint8 parseDHCPMSG(uint16 length)
{
        uint8  svr_addr[6];
        uint16 svr_port;
        uint16 len;
        uint8  * p;
        uint8  * e;
        uint8  type;
        uint8  opt_len = 0;
       
        len = recvfrom(SOCK_DHCP, (uint8 *)pRIPMSG, length, svr_addr, &svr_port);
       
        #ifdef DHCP_DEBUG
                printf("DHCP_SIP:%u.%u.%u.%u ",DHCP_SIP[0],DHCP_SIP[1],DHCP_SIP[2],DHCP_SIP[3]);
                printf("DHCP_RIP:%u.%u.%u.%u ",DHCP_REAL_SIP[0],DHCP_REAL_SIP[1],DHCP_REAL_SIP[2],DHCP_REAL_SIP[3]);
                printf("svr_addr:%u.%u.%u.%u ",svr_addr[0],svr_addr[1],svr_addr[2],svr_addr[3]);
        #endif       
       
        if(pRIPMSG->op != DHCP_BOOTREPLY || svr_port != DHCP_SERVER_PORT)
        {
                #ifdef DHCP_DEBUG          
                printf("DHCP : NO DHCP MSG ");
                #endif               
                return 0;
        }
        if(memcmp(pRIPMSG->chaddr,SRC_MAC_ADDR,6) != 0 || pRIPMSG->xid != htonl(DHCP_XID))
        {
                #ifdef DHCP_DEBUG
                printf("No My DHCP Message. This message is ignored. ");
                printf(" SRC_MAC_ADDR(%02X.%02X.%02X.",SRC_MAC_ADDR[0],SRC_MAC_ADDR[1],SRC_MAC_ADDR[2]);
                printf("%02X.%02X.%02X)",SRC_MAC_ADDR[3],SRC_MAC_ADDR[4],SRC_MAC_ADDR[5]);
                printf(", pRIPMSG->chaddr(%02X.%02X.%02X.",(char)pRIPMSG->chaddr[0],(char)pRIPMSG->chaddr[1],(char)pRIPMSG->chaddr[2]);
                printf("%02X.%02X.%02X)",pRIPMSG->chaddr[3],pRIPMSG->chaddr[4],pRIPMSG->chaddr[5]);
                printf(" pRIPMSG->xid(%08X), DHCP_XID(%08X)",pRIPMSG->xid,(DHCP_XID));
                printf(" pRIMPMSG->yiaddr:%d.%d.%d.%d ",pRIPMSG->yiaddr[0],pRIPMSG->yiaddr[1],pRIPMSG->yiaddr[2],pRIPMSG->yiaddr[3]);
                #endif                               
                return 0;
        }
       
        if( *((uint32*)DHCP_SIP) != 0x00000000 )
        {
                if( *((uint32*)DHCP_REAL_SIP) != *((uint32*)svr_addr) &&
                *((uint32*)DHCP_SIP) != *((uint32*)svr_addr) )
                {
                        #ifdef DHCP_DEBUG               
                        printf("Another DHCP sever send a response message. This is ignored. ");
                        printf(" IP:%u.%u.%u.%u ",svr_addr[0],svr_addr[1],svr_addr[2],svr_addr[3]);
                        #endif                               
                        return 0;                                                               
                }
        }       
        memcpy(GET_SIP,pRIPMSG->yiaddr,4);
       
        #ifdef DHCP_DEBUG       
                printf("DHCP MSG received ");
                printf("yiaddr : %u.%u.%u.%u ",GET_SIP[0],GET_SIP[1],GET_SIP[2],GET_SIP[3]);
        #endif       
        type = 0;
        p = (uint8 *)(&pRIPMSG->op);
        p = p + 240;
        e = p + (len - 240);
        #ifdef DHCP_DEBUG
                printf("p : %08X  e : %08X  len : %d ", (uint32)p, (uint32)e, len);
        #endif
        while ( p < e )
        {
                switch ( *p++ )
                {
                        case endOption :
                                return type;
               
                        case padOption :
                                break;
                       
                        case dhcpMessageType :
                                opt_len = *p++;
                                type = *p;
                                #ifdef DHCP_DEBUG                       
                                        printf("dhcpMessageType : %02X ", type);
                                #endif                       
                                break;
                       
                        case subnetMask :
                                opt_len =* p++;
                                memcpy(GET_SN_MASK,p,4);
                                #ifdef DHCP_DEBUG
                                        printf("subnetMask : ");
                                        printf("%u.%u.%u.%u ",GET_SN_MASK[0],GET_SN_MASK[1],GET_SN_MASK[2],GET_SN_MASK[3]);
                                #endif                       
                                break;
                       
                        case routersOnSubnet :
                                opt_len = *p++;
                                memcpy(GET_GW_IP,p,4);
                                #ifdef DHCP_DEBUG
                                        printf("routersOnSubnet : ");
                                        printf("%u.%u.%u.%u ",GET_GW_IP[0],GET_GW_IP[1],GET_GW_IP[2],GET_GW_IP[3]);
                                #endif                       
                                break;
                       
                        case dns :
                                opt_len = *p++;
                                memcpy(GET_DNS_IP,p,4);
                                break;
                       
                        case dhcpIPaddrLeaseTime :
                                opt_len = *p++;
                                dhcp_lease_time = ntohl(*((uint32*)p));
                                #ifdef DHCP_DEBUG                       
                                        printf("dhcpIPaddrLeaseTime : %d ", dhcp_lease_time);
                                #endif                       
                                break;
                       
                        case dhcpServerIdentifier :
                                opt_len = *p++;
                                #ifdef DHCP_DEBUG                                               
                                        printf("DHCP_SIP : %u.%u.%u.%u ", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
                                #endif                       
                                if( *((uint32*)DHCP_SIP) == 0 ||
                                *((uint32*)DHCP_REAL_SIP) == *((uint32*)svr_addr) ||
                                *((uint32*)DHCP_SIP) == *((uint32*)svr_addr) )
                                {
                                        memcpy(DHCP_SIP,p,4);
                                        memcpy(DHCP_REAL_SIP,svr_addr,4);        // Copy the real ip address of my DHCP server
                                        #ifdef DHCP_DEBUG                                               
                                                printf("My dhcpServerIdentifier : ");
                                                printf("%u.%u.%u.%u ", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
                                                printf("My DHCP server real IP address : ");
                                                printf("%u.%u.%u.%u ", DHCP_REAL_SIP[0], DHCP_REAL_SIP[1], DHCP_REAL_SIP[2], DHCP_REAL_SIP[3]);
                                        #endif                                               
                                }
                                else
                                {
                                #ifdef DHCP_DEBUG                          
                                        printf("Another dhcpServerIdentifier : ");
                                        printf(" MY(%u.%u.%u.%u) ", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);
                                        printf("Another(%u.%u.%u.%u) ", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3]);
                                #endif                               
                                }
                                break;
                               
                        default :
                                opt_len = *p++;
                                #ifdef DHCP_DEBUG                       
                                        printf("opt_len : %u ", opt_len);
                                #endif                       
                                break;
                } // switch
                p+=opt_len;
        } // while       
        return 0;
}

/**       
*@brief                 检查DHCP状态
*@param                s: socket数
*@return        返回得到的DHCP状态
                                        DHCP_RET_NONE: 未获取到IP地址
                                        DHCP_RET_TIMEOUT:超时
                                        DHCP_RET_UPDATE: 获取成功
                                        DHCP_RET_CONFLICT:IP地址冲突
*/
uint8 check_DHCP_state(SOCKET s)
{
        uint16 len;                                                                                                                                                           /*定义一个表示接收数据大小变量*/
        uint8  type;                                                                                                                                                                /*定义一个表示接收封包类型变量*/
       
        type = 0;
        if(getSn_SR(s)!=SOCK_CLOSED)                        /*socket处于打开状态*/
        {
                if ((len = getSn_RX_RSR(s)) > 0)                                                                        /*接收到数据*/
                {
                        printf("len = %d ",len);
                        type = parseDHCPMSG(len);                                                                                                /*解析收到的封包类型*/
                        printf("analysis type =%d ",type);
                }
        }
        else                                                                                                                                                                                                /*socket处于关闭状态,重新初始化socket*/
        {
                printf("socket close ");
                if(dhcp_state == STATE_DHCP_READY)
                {
                        printf("dhcp client strus ");
                第三步        init_dhcp_client();
                        #ifdef DHCP_DEBUG                       
                                printf("state : STATE_DHCP_READY ");
                        #endif                  
                }       
                if(!socket(SOCK_DHCP,Sn_MR_UDP,DHCP_CLIENT_PORT,0x00))/*初始化socket和端口*/
                {
                        #ifdef DHCP_DEBUG          
                                printf("Fail to create the DHCPC_SOCK(%u) ",SOCK_DHCP);
                        #endif   
                        return DHCP_RET_ERR;                                                                                                                /*socket初始化错误*/
                }
        }
        switch ( dhcp_state )
        {
                case STATE_DHCP_READY:第四步                                                                                            /*DHCP初始化状态*/
                        DHCP_timeout = 0;                                                                                                                                /*DHCP超时标志设置为1*/
                        reset_DHCP_time();                                                                                                                        /*复位超时时间*/
                        send_DHCP_DISCOVER();                                                                                                                /*发送DISCOVER包*/
                        DHCP_timer = 0;                                                                                                                                        /*set_timer0(DHCP_timer_handler);  */        
                        dhcp_state = STATE_DHCP_DISCOVER;                                                                /*DHCP的DISCOVER状态*/
                printf("in>>STATE_DHCP_DISCOVER ");
                        break;         

                case STATE_DHCP_DISCOVER:第五步
                        if (type == DHCP_OFFER)
                        {
                                printf("input DHCP_OFFER>> ");
                                reset_DHCP_time();                                                                                                                /*复位超时时间*/
                                printf("input1 DHCP_OFFER>> ");
                                send_DHCP_REQUEST();                                                                                                        /*发送REQUEST包*/
                                printf("input2 DHCP_OFFER>> ");
                                dhcp_state = STATE_DHCP_REQUEST;
                                printf("STATE_DHCP_REQUEST DHCP_OFFER ");
                                #ifdef DHCP_DEBUG                       
                                        printf("state : STATE_DHCP_REQUEST ");
                                #endif                       
                        }
                        else
                                printf("dhcp timeout ");
                                第六步check_DHCP_Timeout();        一直是重复的 执行了
                                printf("check_DHCP_Timeout ");
                        break;
               
                case STATE_DHCP_REQUEST :                                                                                                        /*DHCP的REQUEST状态*/
                        if (type == DHCP_ACK)                                                                                                         /*接收到DHCP服务器回应的off封包*/
                        {
                                reset_DHCP_time();
                                if (check_leasedIP())
                                {
                                        #ifdef DHCP_DEBUG                                       
                                                printf("state : STATE_DHCP_LEASED ");
                                        #endif               
                                        dhcp_state = STATE_DHCP_LEASED;
                                        return DHCP_RET_UPDATE;
                                }
                                else
                                {
                                        #ifdef DHCP_DEBUG                                       
                                                printf("state : STATE_DHCP_DISCOVER ");
                                        #endif                               
                                        dhcp_state = STATE_DHCP_DISCOVER;
                                        return DHCP_RET_CONFLICT;
                                }
                        }       
                        else if (type == DHCP_NAK)
                        {
                                reset_DHCP_time();                                                                                                                /*复位超时时间*/
                                dhcp_state = STATE_DHCP_DISCOVER;
                                #ifdef DHCP_DEBUG                               
                                        printf("state : STATE_DHCP_DISCOVER ");
                                #endif                       
                        }
                        else
                                check_DHCP_Timeout();                                                                                                        /*检查是否超时*/
                        break;
                       
                case STATE_DHCP_LEASED :
                        if ((dhcp_lease_time != 0xffffffff) && (dhcp_time>(dhcp_lease_time/2)))
                        {
                                type = 0;
                                memcpy(OLD_SIP,GET_SIP,4);
                                DHCP_XID++;
                                send_DHCP_REQUEST();
                                dhcp_state = STATE_DHCP_REREQUEST;
                                #ifdef DHCP_DEBUG
                                        printf("state : STATE_DHCP_REREQUEST ");
                                #endif
                                reset_DHCP_time();
                        }
                        break;
                case STATE_DHCP_REREQUEST :
                        if (type == DHCP_ACK)
                        {
                                if(memcmp(OLD_SIP,GET_SIP,4)!=0)       
                                {
                                        #ifdef DHCP_DEBUG
                                                printf("The IP address from the DHCP server is updated. ");
                                                printf("OLD_SIP=%u.%u.%u.%u",OLD_SIP[0],OLD_SIP[1],OLD_SIP[2],OLD_SIP[3]);
                                                printf("GET_SIP=%u.%u.%u.%u ",GET_SIP[0],GET_SIP[1],GET_SIP[2],GET_SIP[3]);
                                        #endif
                                        return DHCP_RET_UPDATE;
                                }
                                #ifdef DHCP_DEBUG
                                else
                                {
                                        printf("state : STATE_DHCP_LEASED : same IP ");
                                }
                                #endif
                                reset_DHCP_time();
                                dhcp_state = STATE_DHCP_LEASED;
                        }
                        else if (type == DHCP_NAK)
                        {
                                reset_DHCP_time();
                                dhcp_state = STATE_DHCP_DISCOVER;
                                #ifdef DHCP_DEBUG
                                        printf("state : STATE_DHCP_DISCOVER ");
                                #endif
                        }
                        else
                                check_DHCP_Timeout();
                        break;
                       
                default :
                        dhcp_state = STATE_DHCP_READY;
                        break;
        }
        if (DHCP_timeout == 1)
        {
                //kill_timer0(DHCP_timer);
                dhcp_state = STATE_DHCP_READY;
                return DHCP_RET_TIMEOUT;
        }
        第八步return DHCP_RET_NONE; /*一直返回获取失败*/
}

/**       
*@brief                 检查DHCP请求释放超时
*@param                无
*@return        无
*/
void check_DHCP_Timeout(void)
{
        if (dhcp_retry_count < MAX_DHCP_RETRY) //dhcp_retry_count重试次数<3
        {
                if (dhcp_time > next_dhcp_time) //DHCP运行计数>DHCP超时时间 5
                {
                        printf("in dhcp_time ");
                        dhcp_time = 0;
                        next_dhcp_time = dhcp_time + DHCP_WAIT_TIME; //5
                        dhcp_retry_count++;
                        switch ( dhcp_state )
                        {
                                case STATE_DHCP_DISCOVER :
                                        //#ifdef DHCP_DEBUG                          
                                                printf("<<timeout>> state : STATE_DHCP_DISCOVER ");
                                        //#endif                               
                                        第七步send_DHCP_DISCOVER();//发送DISCOVER信息给DHCP服务器 //发了也没用
                                        break;
                               
                                case STATE_DHCP_REQUEST :
                                        //#ifdef DHCP_DEBUG                          
                                                printf("<<timeout>> state : STATE_DHCP_REQUEST ");
                                        //#endif                               
                                        send_DHCP_REQUEST();
                                        break;               
                               
                                case STATE_DHCP_REREQUEST :
                                        //#ifdef DHCP_DEBUG                          
                                                printf("<<timeout>> state : STATE_DHCP_REREQUEST ");
                                        //#endif                               
                                        send_DHCP_REQUEST();
                                        break;
                               
                                default :
                                        break;
      &n
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。