#ifndefSTM32_VET6_W5500_DHCP_H#defineSTM32_VET6_W5500_DHCP_H#include"w5500_dhcp_struct.h"#include"socket.h"#defineDEVICE_ID"w5500"#defineIP_CONFLICT_STR"CHECK_IP_CONFLICT"#defineDHCP_FLAGSBROADCAST0x8000/* UDP port numbers for DHCP */#defineDHCP_SERVER_PORT67/* from server to client */#defineDHCP_CLIENT_PORT68/* from client to server *//* DHCP message OP code */#defineDHCP_BOOTREQUEST1#defineDHCP_BOOTREPLY2/* DHCP message type */#defineDHCP_DISCOVER1#defineDHCP_OFFER2#defineDHCP_REQUEST3#defineDHCP_DECLINE4#defineDHCP_ACK5#defineDHCP_NAK6#defineDHCP_RELEASE7#defineDHCP_INFORM8#defineDHCP_HTYPE10MB1#defineDHCP_HTYPE100MB2#defineDHCP_HLENETHERNET6#defineDHCP_HOPS0#defineDHCP_SECS0#defineMAGIC_COOKIE0x63825363#defineDEFAULT_XID0x12345678#defineMAX_DHCP_OPT16voiddhcp_init();voiddhcp_config_registry(module_w5500_t*conf);
bool do_dhcp(SOCKET s,uint32_t wait_ms);#endif//STM32_VET6_W5500_DHCP_H
源文件
#include"w5500_dhcp.h"#defineDBG_ENABLE#defineDBG_SECTION_NAME"dhcp"#defineDBG_LEVELDBG_INFO#include"sys_dbg.h"uint8_t EXTERN_DHCPBUF[1024];
RIP_MSG *pRIPMSG =(RIP_MSG *) EXTERN_DHCPBUF;/*DHCP消息指针*/uint32_t DHCP_XID = DEFAULT_XID;uint8_t OLD_SIP[4];/*最初获取到的IP地址*/uint8_t DHCP_SIP[4]={0};/*已发现的DNS服务器地址*/uint8_t DHCP_REAL_SIP[4]={0};/*从DHCP列表中选择使用的DHCP服务器*/staticmodule_w5500_t*w5500_ptr;uint32_t dhcp_lease_time;/*租约时间*/voidsend_DHCP_DISCOVER(SOCKET s);/*向DHCP服务器发送发现报文*/voidsend_DHCP_REQUEST(SOCKET s,uint8_t pkt_type);/*向DHCP服务器发送请求报文*/voidsend_DHCP_RELEASE_DECLINE(SOCKET s,char msgtype);/*向DHCP服务器发送释放报文*/uint8_tparseDHCPMSG(SOCKET s,uint16_t length);uint8_tcheck_leasedIP(SOCKET s);/*检查获取的IP是否冲突*/uint8_t*SRC_MAC_ADDR =NULL;/*本地MAC地址*/uint8_t*GET_SIP =NULL;/*从DHCP服务器获取到的本机IP*/uint8_t*GET_GW_IP =NULL;/*从DHCP服务器获取到的网关地址*/uint8_t*GET_SN_MASK =NULL;/*从DHCP服务器获取到的子网掩码*/uint8_t GET_DNS_IP[4]={0};/*从DHCP服务器获取到的DNS服务器地址*/voiddhcp_config_registry(module_w5500_t*conf){
w5500_ptr = conf;
GET_SIP = conf->net_conf.ip;
GET_SN_MASK = conf->net_conf.sub;
SRC_MAC_ADDR = conf->net_conf.mac;
GET_GW_IP = conf->net_conf.gw;}voiddhcp_init(){/*该引脚需要保持低电平至少 500 us,才能重置 W5500;*/
w5500_ptr->driver.rst_low();
w5500_ptr->driver.delay(3);
w5500_ptr->driver.rst_high();
w5500_ptr->driver.delay(1600);w5500_chip_init();/*设置mac地址*/w5500_writes(MAC_ADDR, w5500_ptr->net_conf.mac,6);/*初始化Socket的发送接收缓存大小*/for(uint8_t i =0; i < w5500_ptr->base_conf.socket_num; i++){w5500_write(Sn_TXMEM_SIZE(i), w5500_ptr->base_conf.tx_size[i]);w5500_write(Sn_RXMEM_SIZE(i), w5500_ptr->base_conf.rx_size[i]);}}uint16_twait_DHCP_Response(SOCKET s,uint32_t timeout_ms){uint16_t len =0;for(int i =0; i < timeout_ms /10;++i){
w5500_ptr->driver.delay(10);
len =w5500_socket_rx_size_read(s);if(len >0){returnparseDHCPMSG(s, len);}}return0;}
bool do_dhcp(SOCKET s,uint32_t wait_ms){uint16_t type;if(udp_client_init(s, DHCP_CLIENT_PORT)){// 01-发送DISCOVER包send_DHCP_DISCOVER(s);// 02-等待响应
type =wait_DHCP_Response(s, wait_ms);if(type == DHCP_OFFER){send_DHCP_REQUEST(s, STATE_DHCP_REQUEST);/*发送REQUEST包*/
type =wait_DHCP_Response(s, wait_ms);if(type == DHCP_ACK){LOG_D("dhcp_lease_time is %d", dhcp_lease_time);if(check_leasedIP(s)){memcpy(OLD_SIP, GET_SIP,4);
DHCP_XID++;send_DHCP_REQUEST(s, STATE_DHCP_LEASED);
type =wait_DHCP_Response(s, wait_ms);if(type != DHCP_ACK && type !=0){LOG_W("release dhcp connect error:%d", type);}LOG_D("config ip start");w5500_writes(SUB_ADDR, w5500_ptr->net_conf.sub,4);/*子网掩码*/w5500_writes(GAR_ADDR, w5500_ptr->net_conf.gw,4);/*网关*/w5500_writes(SIPR_ADDR, w5500_ptr->net_conf.ip,4);/*IP配置*/LOG_I("<DHCP GET IP OK>");LOG_I("IP:%d.%d.%d.%d", w5500_ptr->net_conf.ip[0], w5500_ptr->net_conf.ip[1],
w5500_ptr->net_conf.ip[2], w5500_ptr->net_conf.ip[3]);return true;}else{LOG_W("state : DHCP_RET_CONFLICT");}}elseif(type == DHCP_NAK){LOG_W("send_DHCP_REQUEST is DHCP_NAK ");}}}return false;}uint8_tcheck_leasedIP(SOCKET s){LOG_D("<Check the IP Conflict %d.%d.%d.%d: ", GET_SIP[0], GET_SIP[1], GET_SIP[2], GET_SIP[3]);if(sendto(s,(uint8_t*) IP_CONFLICT_STR,strlen(IP_CONFLICT_STR), GET_SIP,5000)){send_DHCP_RELEASE_DECLINE(s,1);return0;}return1;}/**
*@brief 解析获得的DHCP消息
*@param length:解析消息长度
*@return 0:解析失败 其他:解析成功
*/uint8_tparseDHCPMSG(SOCKET s,uint16_t length){uint8_t svr_addr[6];uint16_t svr_port;uint16_t len;uint8_t*p;uint8_t*e;uint8_t type;uint8_t opt_len =0;
len =recvfrom(s,(uint8_t*) pRIPMSG, length, svr_addr,&svr_port);LOG_D("DHCP_SIP:%u.%u.%u.%u", DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);LOG_D("DHCP_RIP:%u.%u.%u.%u", DHCP_REAL_SIP[0], DHCP_REAL_SIP[1], DHCP_REAL_SIP[2], DHCP_REAL_SIP[3]);LOG_D("svr_addr:%u.%u.%u.%u", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3]);if(pRIPMSG->op != DHCP_BOOTREPLY || svr_port != DHCP_SERVER_PORT){LOG_D("DHCP : NO DHCP MSG");return0;}if(memcmp(pRIPMSG->chaddr, SRC_MAC_ADDR,6)!=0|| pRIPMSG->xid !=htonl(DHCP_XID)){LOG_W("No My DHCP Message. This message is ignored.");LOG_W("\tSRC_MAC_ADDR(%02X.%02X.%02X.%02X.%02X.%02X)",
SRC_MAC_ADDR[0], SRC_MAC_ADDR[1], SRC_MAC_ADDR[2],
SRC_MAC_ADDR[3], SRC_MAC_ADDR[4], SRC_MAC_ADDR[5]);LOG_W(", pRIPMSG->chaddr(%02X.%02X.%02X.",(char) pRIPMSG->chaddr[0],(char) pRIPMSG->chaddr[1],(char) pRIPMSG->chaddr[2]);LOG_W("%02X.%02X.%02X)", pRIPMSG->chaddr[3], pRIPMSG->chaddr[4], pRIPMSG->chaddr[5]);LOG_W("\tpRIPMSG->xid(%08X), DHCP_XID(%08X)", pRIPMSG->xid,(DHCP_XID));LOG_W("\tpRIMPMSG->yiaddr:%d.%d.%d.%d", pRIPMSG->yiaddr[0], pRIPMSG->yiaddr[1], pRIPMSG->yiaddr[2],
pRIPMSG->yiaddr[3]);return0;}if(*((uint32_t*) DHCP_SIP)!=0x00000000){if(*((uint32_t*) DHCP_REAL_SIP)!=*((uint32_t*) svr_addr)&&*((uint32_t*) DHCP_SIP)!=*((uint32_t*) svr_addr)){LOG_D("Another DHCP sever send a response message. This is ignored.");LOG_D("\tIP:%u.%u.%u.%u", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3]);return0;}}memcpy(GET_SIP, pRIPMSG->yiaddr,4);LOG_D("DHCP MSG received");LOG_D("yiaddr : %u.%u.%u.%u", GET_SIP[0], GET_SIP[1], GET_SIP[2], GET_SIP[3]);
type =0;
p =(uint8_t*)(&pRIPMSG->op);
p = p +240;
e = p +(len -240);LOG_D("p : %08X e : %08X len : %d",(uint32_t) p,(uint32_t) e, len);while(p < e){switch(*p++){case endOption:return type;case padOption:break;case dhcpMessageType:
opt_len =*p++;
type =*p;LOG_D("dhcpMessageType : %02X", type);break;case subnetMask:
opt_len =*p++;memcpy(GET_SN_MASK, p,4);break;case routersOnSubnet:
opt_len =*p++;memcpy(GET_GW_IP, p,4);break;case dns:
opt_len =*p++;memcpy(GET_DNS_IP, p,4);break;case dhcpIPaddrLeaseTime:
opt_len =*p++;
dhcp_lease_time =ntohl(*((uint32_t*) p));break;case dhcpServerIdentifier:
opt_len =*p++;if(*((uint32_t*) DHCP_SIP)==0||*((uint32_t*) DHCP_REAL_SIP)==*((uint32_t*) svr_addr)||*((uint32_t*) DHCP_SIP)==*((uint32_t*) svr_addr)){memcpy(DHCP_SIP, p,4);memcpy(DHCP_REAL_SIP, svr_addr,4);// Copy the real ip address of my DHCP serverLOG_D("My dhcpServerIdentifier : %u.%u.%u.%u",
DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3]);LOG_D("My DHCP server real IP address :%u.%u.%u.%u",
DHCP_REAL_SIP[0], DHCP_REAL_SIP[1], DHCP_REAL_SIP[2], DHCP_REAL_SIP[3]);}else{LOG_D("Another dhcpServerIdentifier : MY(%u.%u.%u.%u) Another(%u.%u.%u.%u)",
DHCP_SIP[0], DHCP_SIP[1], DHCP_SIP[2], DHCP_SIP[3],
svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3]);}break;default:
opt_len =*p++;break;}// switch
p += opt_len;}// whilereturn0;}/**
*@brief 发送DISCOVER信息给DHCP服务器
*@param 无
*@return 无
*/voidsend_DHCP_DISCOVER(SOCKET s){uint8_t ip[4]={255,255,255,255};uint16_t i =0;// the host name modifieduint8_t host_name[12];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);/*mac地址*/memcpy(pRIPMSG->chaddr, SRC_MAC_ADDR,6);/* MAGIC_COOKIE */
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>24)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>16)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>8)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)(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;memcpy(pRIPMSG->OPT + i, SRC_MAC_ADDR,6);
i +=6;// host name
pRIPMSG->OPT[i++]= hostName;// set the host namesprintf((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_t)strlen((char*) host_name);strcpy((char*)(&(pRIPMSG->OPT[i])),(char*) host_name);
i +=(uint16_t)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 */sendto(s,(uint8_t*) pRIPMSG,sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);LOG_D("sent DHCP_DISCOVER");}voidsend_DHCP_REQUEST(SOCKET s,uint8_t pkt_type){uint8_t ip[4], host_name[12];uint16_t i =0;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);if(pkt_type < STATE_DHCP_LEASED)
pRIPMSG->flags =htons(DHCP_FLAGSBROADCAST);else{
pRIPMSG->flags =0;// For Unicastmemcpy(pRIPMSG->ciaddr, GET_SIP,4);}memcpy(pRIPMSG->chaddr, SRC_MAC_ADDR,6);/* MAGIC_COOKIE */
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>24)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>16)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>8)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)(MAGIC_COOKIE &0xFF);/* Option Request Param. */
pRIPMSG->OPT[i++]= dhcpMessageType;
pRIPMSG->OPT[i++]=0x01;
pRIPMSG->OPT[i++]= DHCP_REQUEST;
pRIPMSG->OPT[i++]= dhcpClientIdentifier;
pRIPMSG->OPT[i++]=0x07;
pRIPMSG->OPT[i++]=0x01;memcpy(pRIPMSG->OPT + i, SRC_MAC_ADDR,6);
i +=6;if(pkt_type < STATE_DHCP_LEASED){
pRIPMSG->OPT[i++]= dhcpRequestedIPaddr;
pRIPMSG->OPT[i++]=0x04;memcpy(pRIPMSG->OPT + i, GET_SIP,4);
i +=4;
pRIPMSG->OPT[i++]= dhcpServerIdentifier;
pRIPMSG->OPT[i++]=0x04;memcpy(pRIPMSG->OPT + i, DHCP_SIP,4);
i +=4;}// host name
pRIPMSG->OPT[i++]= hostName;// set the host namesprintf((char*) host_name,(char*)"%.4s-%02X%02X%02X", DEVICE_ID, SRC_MAC_ADDR[3], SRC_MAC_ADDR[4],
SRC_MAC_ADDR[5]);
pRIPMSG->OPT[i++]=(uint8_t)strlen((char*) host_name);strcpy((char*)&(pRIPMSG->OPT[i]),(char*) host_name);
i +=strlen((char*) host_name);
pRIPMSG->OPT[i++]= dhcpParamRequest;
pRIPMSG->OPT[i++]=0x08;
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++]= performRouterDiscovery;
pRIPMSG->OPT[i++]= staticRoute;
pRIPMSG->OPT[i++]= endOption;/* send broadcasting packet */if(pkt_type < STATE_DHCP_LEASED)memset(ip,0xFF,4);elsememcpy(ip, DHCP_SIP,4);sendto(s,(uint8_t*) pRIPMSG,sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);LOG_D("sent DHCP_REQUEST");}voidsend_DHCP_RELEASE_DECLINE(SOCKET s,char msgtype){uint16_t i =0;uint8_t 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_t)((MAGIC_COOKIE >>24)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>16)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)((MAGIC_COOKIE >>8)&0xFF);
pRIPMSG->OPT[i++]=(uint8_t)(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;memcpy(pRIPMSG->OPT + i, SRC_MAC_ADDR,6);
i +=6;
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];LOG_D("sent DHCP_DECLINE\r\n");}else{LOG_D("sent DHCP_RELEASE");}
pRIPMSG->OPT[i++]= endOption;if(msgtype)memset(ip,0xFF,4);elsememcpy(ip, DHCP_SIP,4);// printf("send dhcp decline\r\n");sendto(s,(uint8_t*) pRIPMSG,sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);}