alienwalker 3 лет назад
Родитель
Сommit
d7c5aa6153

+ 247 - 938
components/ethernet/common/dhcp_client.c

@@ -2,21 +2,25 @@
 #ifdef LUAT_USE_DHCP
 #include "dhcp_def.h"
 #include "bsp_common.h"
+extern void DBG_Printf(const char* format, ...);
+extern void DBG_HexPrintf(void *Data, unsigned int len);
+#define DBG(x,y...)		DBG_Printf("%s %d:"x"\r\n", __FUNCTION__,__LINE__,##y)
 
-void make_ip4_dhcp_msg_base(uint8_t *mac, uint32_t xid, uint32_t cip, uint32_t dhcp_ip, Buffer_Struct *out)
+void make_ip4_dhcp_msg_base(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out)
 {
+	dhcp->xid++;
 	BytesPut8ToBuf(out, DHCP_BOOTREQUEST);
 	BytesPut8ToBuf(out, DHCP_HTYPE_ETH);
 	BytesPut8ToBuf(out, 6);
 	BytesPut8ToBuf(out, 0);
-	BytesPutBe32ToBuf(out, xid);
+	BytesPutBe32ToBuf(out, dhcp->xid);
 	BytesPutBe16ToBuf(out, 0);
-	BytesPutBe16ToBuf(out, 0);
-	BytesPutLe32ToBuf(out, cip);
-	BytesPutLe32ToBuf(out, dhcp_ip);
+	BytesPutBe16ToBuf(out, flag);
+	BytesPutLe32ToBuf(out, dhcp->ip);
+	BytesPutLe32ToBuf(out, 0);
 	BytesPutLe32ToBuf(out, 0);
 	BytesPutLe32ToBuf(out, 0);
-	OS_BufferWrite(out, mac, 6);
+	OS_BufferWrite(out, dhcp->mac, 6);
 	memset(out->Data + out->Pos, 0, 10 + 64 + 128);
 	out->Pos += 10 + 64 + 128;
 	BytesPutBe32ToBuf(out, DHCP_MAGIC_COOKIE);
@@ -29,6 +33,14 @@ void ip4_dhcp_msg_add_bytes_option(uint8_t id, uint8_t *data, uint8_t len, Buffe
 	OS_BufferWrite(out, data, len);
 }
 
+void ip4_dhcp_msg_add_client_id_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out)
+{
+	BytesPut8ToBuf(out, id);
+	BytesPut8ToBuf(out, len + 1);
+	BytesPut8ToBuf(out, 1);
+	OS_BufferWrite(out, data, len);
+}
+
 void ip4_dhcp_msg_add_ip_option(uint8_t id, uint32_t ip, Buffer_Struct *out)
 {
 	BytesPut8ToBuf(out, id);
@@ -54,1004 +66,301 @@ void ip4_dhcp_msg_add_integer_option(uint8_t id, uint8_t len, uint32_t value, Bu
 	}
 }
 
-void make_ip4_dhcp_discover_msg(uint8_t *mac, const char *host_name, uint32_t xid, uint16_t mtu, Buffer_Struct *out)
+void make_ip4_dhcp_discover_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
 {
 	uint8_t dhcp_discover_request_options[] = {
-	  DHCP_OPTION_SUBNET_MASK,
-	  DHCP_OPTION_ROUTER,
-	  DHCP_OPTION_BROADCAST,
-	  DHCP_OPTION_DNS_SERVER,
-	  };
+			  DHCP_OPTION_SUBNET_MASK,
+			  DHCP_OPTION_ROUTER,
+			  DHCP_OPTION_BROADCAST,
+			  DHCP_OPTION_SERVER_ID,
+			  DHCP_OPTION_LEASE_TIME,
+			  DHCP_OPTION_IP_TTL,
+	};
 	out->Pos = 0;
-	make_ip4_dhcp_msg_base(mac, xid, 0, 0, out);
+	make_ip4_dhcp_msg_base(dhcp, 0x8000, out);
 	ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DISCOVER, out);
 	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, host_name, strlen(host_name), out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_CLIENT_ID, mac, 6, out);
+	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, dhcp->name, strlen(dhcp->name), out);
+	ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, dhcp->mac, 6, out);
 	BytesPut8ToBuf(out, 0xff);
+	if (out->Pos < (DHCP_MSG_LEN + 72))
+	{
+		out->Pos = (DHCP_MSG_LEN + 72);
+	}
+	else
+	{
+		out->Pos = (out->Pos + (4 - 1)) & (~(4 - 1));
+	}
 }
 
-void make_ip4_dhcp_select_msg(uint8_t *mac, const char *host_name, uint32_t xid, uint32_t now_ip, uint32_t dhcp_ip, uint32_t server_ip, uint16_t mtu, Buffer_Struct *out)
+void make_ip4_dhcp_select_msg(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out)
 {
 	uint8_t dhcp_discover_request_options[] = {
 			  DHCP_OPTION_SUBNET_MASK,
 			  DHCP_OPTION_ROUTER,
 			  DHCP_OPTION_BROADCAST,
-			  DHCP_OPTION_DNS_SERVER,
-			  DHCP_OPTION_T1,
-			  DHCP_OPTION_T2,
+			  DHCP_OPTION_SERVER_ID,
+			  DHCP_OPTION_LEASE_TIME,
 			  DHCP_OPTION_IP_TTL,
-			  DHCP_OPTION_NTP,
 	  };
 	out->Pos = 0;
-	make_ip4_dhcp_msg_base(mac, xid, 0, now_ip, out);
+	make_ip4_dhcp_msg_base(dhcp, flag, out);
 	ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_REQUEST, out);
-	ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN, mtu, out);
-	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp_ip, out);
-	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, server_ip, out);
+	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
+	if (!flag)
+	{
+		ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
+	}
 	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_PARAMETER_REQUEST_LIST, dhcp_discover_request_options, sizeof(dhcp_discover_request_options), out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, host_name, strlen(host_name), out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_CLIENT_ID, mac, 6, out);
+	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, dhcp->name, strlen(dhcp->name), out);
+	ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, dhcp->mac, 6, out);
 	BytesPut8ToBuf(out, 0xff);
 }
 
-void make_ip4_dhcp_decline_msg(uint8_t *mac, const char *host_name, uint32_t xid, uint32_t dhcp_ip, uint32_t server_ip, Buffer_Struct *out)
+void make_ip4_dhcp_decline_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out)
 {
 
 	out->Pos = 0;
-	make_ip4_dhcp_msg_base(mac, xid, dhcp_ip, dhcp_ip, out);
+	make_ip4_dhcp_msg_base(dhcp, 0, out);
 	ip4_dhcp_msg_add_integer_option(DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, DHCP_DECLINE, out);
-	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp_ip, out);
-	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, server_ip, out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, host_name, strlen(host_name), out);
-	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_CLIENT_ID, mac, 6, out);
+	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_REQUESTED_IP, dhcp->temp_ip, out);
+	ip4_dhcp_msg_add_ip_option(DHCP_OPTION_SERVER_ID, dhcp->server_ip, out);
+	ip4_dhcp_msg_add_bytes_option(DHCP_OPTION_HOSTNAME, dhcp->name, strlen(dhcp->name), out);
+	ip4_dhcp_msg_add_client_id_option(DHCP_OPTION_CLIENT_ID, dhcp->mac, 6, out);
 	BytesPut8ToBuf(out, 0xff);
 }
 
-#endif
-#if 0
-#include <stdio.h>
-#include <string.h>
-#include "w5500.h"
-#include "socket.h"
-#include "dhcp.h"
-
-//#define _DHCP_DEBUG_
-
-extern uint8_t MAC[6];
-extern uint8_t LocalIp[4];
-extern uint8_t Subnet[4];
-extern uint8_t Gateway[4];
-extern uint8_t DNS[4];
-
-/// <summary>DHCP Client MAC address.  20180625.</summary>
-uint8_t* DHCP_CHADDR = MAC;
-
-/// <summary>Subnet mask received from the DHCP server.</summary>
-uint8_t* GET_SN_MASK = Subnet;
-
-/// <summary>Gateway ip address received from the DHCP server.</summary>
-uint8_t* GET_GW_IP = Gateway;
-
-/// <summary>DNS server ip address received from the DHCP server.</summary>
-uint8_t* GET_DNS_IP = DNS;
-
-/// <summary>Local ip address received from the DHCP server.</summary>
-uint8_t* GET_SIP = LocalIp;
-
-/// <summary>DNS server ip address is discovered.</summary>
-uint8_t	DHCP_SIP[4] = { 0 };
-
-/// <summary>For extract my DHCP server in a few DHCP servers.</summary>
-uint8_t	DHCP_REAL_SIP[4] = { 0 };
-
-/// <summary>Previous local ip address received from DHCP server.</summary>
-uint8_t	OLD_SIP[4];
-
-uint32_t dhcp_tick_next = DHCP_WAIT_TIME;
-
-/// <summary>Network information from DHCP Server.</summary>
-
-/// <summary>Previous IP address.</summary>
-uint8_t OLD_allocated_ip[4] = { 0, };
-
-/// <summary>IP address from DHCP.</summary>
-uint8_t DHCP_allocated_ip[4] = { 0, };
-
-/// <summary>Gateway address from DHCP.</summary>
-uint8_t DHCP_allocated_gw[4] = { 0, };
-
-/// <summary>Subnet mask from DHCP.</summary>
-uint8_t DHCP_allocated_sn[4] = { 0, };
-
-/// <summary>DNS address from DHCP.</summary>
-uint8_t DHCP_allocated_dns[4] = { 0, };
-
-uint8_t HOST_NAME[] = DEVICE_TYPE;
-
-/// <summary>DHCP client status.</summary>
-uint8_t  dhcp_state = STATE_DHCP_READY;
-
-/// <summary>retry count.</summary>
-uint8_t  dhcp_retry_count = 0;
-
-/// <summary>DHCP Timeout flag.</summary>
-uint8_t  DHCP_timeout = 0;
-
-/// <summary>Leased time.</summary>
-uint32_t  dhcp_lease_time;
-
-uint32_t  dhcp_time = 0;
-
-/// <summary>DHCP Time 1s.</summary>
-uint32_t  next_dhcp_time = 0;
-
-/// <summary>1ms.</summary>
-uint32_t  dhcp_tick_cnt = 0;
-
-uint8_t  DHCP_timer;
-
-uint32_t  DHCP_XID = DEFAULT_XID;
-
-uint8_t EXTERN_DHCPBUF[1024];
-
-/// <summary>Pointer for the DHCP message.</summary>
-RIP_MSG* pDHCPMSG = (RIP_MSG*)EXTERN_DHCPBUF;
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>The default handler of ip assign first.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void default_ip_assign(void)
-{
-	setSIPR(DHCP_allocated_ip);
-	setSUBR(DHCP_allocated_sn);
-	setGAR(DHCP_allocated_gw);
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>The default handler of ip chaged.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void default_ip_update(void)
-{
-	/* WIZchip Software Reset */
-	setMR(MR_RST);
-	getMR(); // for delay
-	default_ip_assign();
-	setSHAR(DHCP_CHADDR);
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>The default handler of ip chaged.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void default_ip_conflict(void)
-{
-	// WIZchip Software Reset
-	setMR(MR_RST);
-	getMR(); // for delay
-	setSHAR(DHCP_CHADDR);
-}
-
-void (*dhcp_ip_assign)(void) = default_ip_assign;     /* handler to be called when the IP address from DHCP server is first assigned */
-void (*dhcp_ip_update)(void) = default_ip_update;     /* handler to be called when the IP address from DHCP server is updated */
-void (*dhcp_ip_conflict)(void) = default_ip_conflict;   /* handler to be called when the IP address from DHCP server is conflict */
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>Resets the DHCP timeout.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void reset_DHCP_timeout(void)//20180625
-{
-	dhcp_time = 0;
-	dhcp_tick_next = DHCP_WAIT_TIME;
-	dhcp_retry_count = 0;
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>Check DHCP timeout.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///
-/// <returns>DHCP state.</returns>
-///-------------------------------------------------------------------------------------------------
-
-uint8_t check_DHCP_timeout(void)//20180625
-{
-	uint8_t ret = DHCP_RUNNING;
-	if (dhcp_retry_count < MAX_DHCP_RETRY) {
-		if (dhcp_tick_next < dhcp_time) {
-
-			switch (dhcp_state) {
-			case STATE_DHCP_DISCOVER:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
-#endif
-				send_DHCP_DISCOVER();
-				break;
-			case STATE_DHCP_REQUEST:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
-#endif
-				send_DHCP_REQUEST();
-				break;
-			case STATE_DHCP_REREQUEST:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
-#endif
-				send_DHCP_REQUEST();
-				break;
-			default:
-				break;
-			}
-			dhcp_time = 0;
-			dhcp_tick_next = dhcp_time + DHCP_WAIT_TIME;
-			dhcp_retry_count++;
-		}
-	}
-	else { // timeout occurred
-
-		switch (dhcp_state) {
-		case STATE_DHCP_DISCOVER:
-			dhcp_state = STATE_DHCP_READY;
-			ret = DHCP_FAILED;
-			break;
-		case STATE_DHCP_REQUEST:
-		case STATE_DHCP_REREQUEST:
-			send_DHCP_DISCOVER();
-			dhcp_time = 0;
-			dhcp_state = STATE_DHCP_DISCOVER;
-			break;
-		default:
-			break;
-		}
-		reset_DHCP_timeout();
-	}
-	return ret;
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>Make the common DHCP message.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void makeDHCPMSG(void)
+int analyze_ip4_dhcp(dhcp_client_info_t *dhcp, Buffer_Struct *in)
 {
-	uint8_t  bk_mac[6];
-	uint8_t* ptmp;
-	uint8_t  i;
-
-	getSHAR(bk_mac);
-
-	pDHCPMSG->op = DHCP_BOOTREQUEST;
-	pDHCPMSG->htype = DHCP_HTYPE10MB;
-	pDHCPMSG->hlen = DHCP_HLENETHERNET;
-	pDHCPMSG->hops = DHCP_HOPS;
-	ptmp = (uint8_t*)(&pDHCPMSG->xid);
-	*(ptmp + 0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
-	*(ptmp + 1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
-	*(ptmp + 2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
-	*(ptmp + 3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
-	pDHCPMSG->secs = DHCP_SECS;
-	ptmp = (uint8_t*)(&pDHCPMSG->flags);
-	*(ptmp + 0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
-	*(ptmp + 1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
-
-	pDHCPMSG->ciaddr[0] = 0;
-	pDHCPMSG->ciaddr[1] = 0;
-	pDHCPMSG->ciaddr[2] = 0;
-	pDHCPMSG->ciaddr[3] = 0;
-
-	pDHCPMSG->yiaddr[0] = 0;
-	pDHCPMSG->yiaddr[1] = 0;
-	pDHCPMSG->yiaddr[2] = 0;
-	pDHCPMSG->yiaddr[3] = 0;
-
-	pDHCPMSG->siaddr[0] = 0;
-	pDHCPMSG->siaddr[1] = 0;
-	pDHCPMSG->siaddr[2] = 0;
-	pDHCPMSG->siaddr[3] = 0;
-
-	pDHCPMSG->giaddr[0] = 0;
-	pDHCPMSG->giaddr[1] = 0;
-	pDHCPMSG->giaddr[2] = 0;
-	pDHCPMSG->giaddr[3] = 0;
-
-	pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
-	pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
-	pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
-	pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
-	pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
-	pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
-
-	for (i = 6; i < 16; i++)  pDHCPMSG->chaddr[i] = 0;
-	for (i = 0; i < 64; i++)  pDHCPMSG->sname[i] = 0;
-	for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
-
-	// MAGIC_COOKIE
-	pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
-	pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
-	pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
-	pDHCPMSG->OPT[3] = (uint8_t)(MAGIC_COOKIE & 0x000000FF) >> 0;
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>This function sends DHCP DISCOVER message to DHCP server.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void send_DHCP_DISCOVER(void)
-{
-	uint8_t ip[4];
-	uint16_t k = 0;
-	uint8_t host_name[18];
-
-	makeDHCPMSG();
-
-	k = 4;     // beacaue MAGIC_COOKIE already made by makeDHCPMSG()
-
-	 // Option Request Param
-	pDHCPMSG->OPT[k++] = dhcpMessageType;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
-
-	// Client identifier
-	pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
-	pDHCPMSG->OPT[k++] = 0x07;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
-	// host name
-	pDHCPMSG->OPT[k++] = hostName;
-	sprintf((char*)host_name, "%.11s-%02X%02X%02X", DEVICE_TYPE, DHCP_CHADDR[3], DHCP_CHADDR[4], DHCP_CHADDR[5]);
-
-	pDHCPMSG->OPT[k++] = strlen((char*)host_name);
-
-	strcpy((char*)(&(pDHCPMSG->OPT[k])), (char*)host_name);
-
-	k += strlen((char*)host_name);
-
-	pDHCPMSG->OPT[k++] = dhcpParamRequest;
-	pDHCPMSG->OPT[k++] = 0x06;	// length of request
-	pDHCPMSG->OPT[k++] = subnetMask;
-	pDHCPMSG->OPT[k++] = routersOnSubnet;
-	pDHCPMSG->OPT[k++] = dns;
-	pDHCPMSG->OPT[k++] = domainName;
-	pDHCPMSG->OPT[k++] = dhcpT1value;
-	pDHCPMSG->OPT[k++] = dhcpT2value;
-	pDHCPMSG->OPT[k++] = endOption;
-
-	// send broadcasting packet
-	ip[0] = 255;
-	ip[1] = 255;
-	ip[2] = 255;
-	ip[3] = 255;
-
-#ifdef _DHCP_DEBUG_
-	printf("> Send DHCP_DISCOVER\r\n");
-#endif
-	sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>This function sends DHCP REQUEST message to DHCP server.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void send_DHCP_REQUEST(void)
-{
-	uint8_t ip[4];
-	uint16_t k = 0;
-	uint8_t host_name[18];
-
-	makeDHCPMSG();
-
-	if (dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
+	int ack;
+	uint64_t lease_time;
+	if (in->Data[0] != DHCP_BOOTREPLY)
 	{
-		*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00) >> 8);
-		*((uint8_t*)(&pDHCPMSG->flags) + 1) = (DHCP_FLAGSUNICAST & 0x00FF);
-		pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
-		pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
-		pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
-		pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
-		ip[0] = DHCP_SIP[0];
-		ip[1] = DHCP_SIP[1];
-		ip[2] = DHCP_SIP[2];
-		ip[3] = DHCP_SIP[3];
+		DBG("!");
+		return -1;
 	}
-	else
+	if (BytesGetBe32(&in->Data[DHCP_MSG_LEN]) != DHCP_MAGIC_COOKIE)
 	{
-		ip[0] = 255;
-		ip[1] = 255;
-		ip[2] = 255;
-		ip[3] = 255;
+		DBG("!");
+		return -2;
 	}
-
-	k = 4;      // beacaue MAGIC_COOKIE already made by makeDHCPMSG()
-
-	 // Option Request Param.
-	pDHCPMSG->OPT[k++] = dhcpMessageType;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_REQUEST;
-
-	pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
-	pDHCPMSG->OPT[k++] = 0x07;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
-	if (ip[3] == 255)  // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
+	if (BytesGetBe32(&in->Data[4]) != dhcp->xid)
 	{
-		pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
-		pDHCPMSG->OPT[k++] = 0x04;
-		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
-		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
-		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
-		pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
-		pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
-		pDHCPMSG->OPT[k++] = 0x04;
-		pDHCPMSG->OPT[k++] = DHCP_SIP[0];
-		pDHCPMSG->OPT[k++] = DHCP_SIP[1];
-		pDHCPMSG->OPT[k++] = DHCP_SIP[2];
-		pDHCPMSG->OPT[k++] = DHCP_SIP[3];
+		DBG("!");
+		return -3;
 	}
-
-	// host name
-	pDHCPMSG->OPT[k++] = hostName;
-
-	sprintf((char*)host_name, "%.11s-%02X%02X%02X", DEVICE_TYPE, DHCP_CHADDR[3], DHCP_CHADDR[4], DHCP_CHADDR[5]);
-
-
-	pDHCPMSG->OPT[k++] = (uint8_t)strlen((char*)host_name);
-
-	strcpy((char*)(&(pDHCPMSG->OPT[k])), (char*)host_name);
-
-
-	k += (uint8_t)strlen((char*)host_name);
-
-	pDHCPMSG->OPT[k++] = dhcpParamRequest;
-	pDHCPMSG->OPT[k++] = 0x08;
-	pDHCPMSG->OPT[k++] = subnetMask;
-	pDHCPMSG->OPT[k++] = routersOnSubnet;
-	pDHCPMSG->OPT[k++] = dns;
-	pDHCPMSG->OPT[k++] = domainName;
-	pDHCPMSG->OPT[k++] = dhcpT1value;
-	pDHCPMSG->OPT[k++] = dhcpT2value;
-	pDHCPMSG->OPT[k++] = performRouterDiscovery;
-	pDHCPMSG->OPT[k++] = staticRoute;
-	pDHCPMSG->OPT[k++] = endOption;
-
-#ifdef _DHCP_DEBUG_
-	printf("> Send DHCP_REQUEST\r\n");
-#endif
-	sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>This function sends DHCP RELEASE message to DHCP server.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void send_DHCP_DECLINE(void)
-{
-	//	int i;
-	uint8_t ip[4];
-	uint16_t k = 0;
-
-	makeDHCPMSG();
-
-	k = 4;      // beacaue MAGIC_COOKIE already made by makeDHCPMSG()
-
-	*((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00) >> 8);
-	*((uint8_t*)(&pDHCPMSG->flags) + 1) = (DHCP_FLAGSUNICAST & 0x00FF);
-
-	// Option Request Param.
-	pDHCPMSG->OPT[k++] = dhcpMessageType;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_DECLINE;
-
-	pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
-	pDHCPMSG->OPT[k++] = 0x07;
-	pDHCPMSG->OPT[k++] = 0x01;
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
-	pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
-	pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
-	pDHCPMSG->OPT[k++] = 0x04;
-	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
-	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
-	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
-	pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
-	pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
-	pDHCPMSG->OPT[k++] = 0x04;
-	pDHCPMSG->OPT[k++] = DHCP_SIP[0];
-	pDHCPMSG->OPT[k++] = DHCP_SIP[1];
-	pDHCPMSG->OPT[k++] = DHCP_SIP[2];
-	pDHCPMSG->OPT[k++] = DHCP_SIP[3];
-
-	pDHCPMSG->OPT[k++] = endOption;
-
-	//send broadcasting packet
-	ip[0] = 0xFF;
-	ip[1] = 0xFF;
-	ip[2] = 0xFF;
-	ip[3] = 0xFF;
-
-#ifdef _DHCP_DEBUG_
-	printf("\r\n> Send DHCP_DECLINE\r\n");
-#endif
-
-	sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, sizeof(RIP_MSG), ip, DHCP_SERVER_PORT);
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>This function parses the reply message from DHCP server.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///
-/// <returns>Success - return type, Fail - 0.</returns>
-///-------------------------------------------------------------------------------------------------
-
-int8_t parseDHCPMSG(void)
-{
-	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;
-
-	if ((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
+	if (memcmp(dhcp->mac, &in->Data[28], 6))
 	{
-		len = recvfrom(DHCP_SOCKET, (uint8_t*)pDHCPMSG, len, svr_addr, &svr_port);
-#ifdef _DHCP_DEBUG_
-		printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3], svr_port, len);
-#endif
+		DBG("!");
+		return -4;
 	}
-	else return 0;
-	if (svr_port == DHCP_SERVER_PORT) {
-		// compare mac address
-		if ((pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
-			(pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
-			(pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]))
-			return 0;
-		type = 0;
-		p = (uint8_t*)(&pDHCPMSG->op);//2
-		p = p + 240;      // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
-		e = p + (len - 240);
-
-		while (p < e) {
-			switch (*p) {
-			case endOption:
-				p = e;   // for break while(p < e)
-				break;
-			case padOption:
-				p++;
-				break;
-			case dhcpMessageType:
-				p++;
-				p++;
-				type = *p++;
-				break;
-			case subnetMask:
-				p++;
-				p++;
-				DHCP_allocated_sn[0] = *p++;
-				DHCP_allocated_sn[1] = *p++;
-				DHCP_allocated_sn[2] = *p++;
-				DHCP_allocated_sn[3] = *p++;
-				break;
-			case routersOnSubnet:
-				p++;
-				opt_len = *p++;
-				DHCP_allocated_gw[0] = *p++;
-				DHCP_allocated_gw[1] = *p++;
-				DHCP_allocated_gw[2] = *p++;
-				DHCP_allocated_gw[3] = *p++;
-				p = p + (opt_len - 4);
-				break;
-			case dns:
-				p++;
-				opt_len = *p++;
-				DHCP_allocated_dns[0] = *p++;
-				DHCP_allocated_dns[1] = *p++;
-				DHCP_allocated_dns[2] = *p++;
-				DHCP_allocated_dns[3] = *p++;
-				p = p + (opt_len - 4);
-				break;
-			case dhcpIPaddrLeaseTime:
-				p++;
-				opt_len = *p++;
-				dhcp_lease_time = *p++;
-				dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
-				dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
-				dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
-#ifdef _DHCP_DEBUG_
-				//               dhcp_lease_time = 10;
-				//				printf("dhcp_lease_time:%d\r\n",(int)dhcp_lease_time);
-#endif
-				break;
-			case dhcpServerIdentifier:
-				p++;
-				opt_len = *p++;
-				DHCP_SIP[0] = *p++;
-				DHCP_SIP[1] = *p++;
-				DHCP_SIP[2] = *p++;
-				DHCP_SIP[3] = *p++;
-				break;
-			default:
-				p++;
-				opt_len = *p++;
-				p += opt_len;
-				break;
-			} // switch
-		} // while
-	} // if
-	return	type;
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>This function checks the timeout of DHCP in each state.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void check_DHCP_Timeout(void)
-{
-	if (dhcp_retry_count < MAX_DHCP_RETRY)
+	dhcp->temp_ip = BytesGetLe32(&in->Data[16]);
+	in->Pos = DHCP_OPTIONS_OFS;
+	while (in->Pos < in->MaxLen)
 	{
-		if (dhcp_time > next_dhcp_time)
+__CHECK:
+		switch(in->Data[in->Pos])
 		{
-			dhcp_time = 0;
-			next_dhcp_time = dhcp_time + DHCP_WAIT_TIME;
-			dhcp_retry_count++;
-			switch (dhcp_state)
+		case DHCP_OPTION_MESSAGE_TYPE:
+			ack = in->Data[in->Pos + 2];
+			break;
+		case DHCP_OPTION_SERVER_ID:
+			dhcp->server_ip = BytesGetLe32(&in->Data[in->Pos + 2]);
+			break;
+		case DHCP_OPTION_LEASE_TIME:
+			if (DHCP_ACK == ack)
 			{
-			case STATE_DHCP_DISCOVER:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
-#endif
-				send_DHCP_DISCOVER();
-				break;
-			case STATE_DHCP_REQUEST:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n");
-#endif
-				send_DHCP_REQUEST();
-				break;
-			case STATE_DHCP_REREQUEST:
-#ifdef _DHCP_DEBUG_
-				printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n");
-#endif
-				send_DHCP_REQUEST();
-				break;
-			default:
-				break;
+				lease_time = BytesGetBe32(&in->Data[in->Pos + 2]);
+				lease_time *= 1000;
+				dhcp->lease_end_time = GetSysTickMS() + lease_time;
+				dhcp->lease_p1_time = dhcp->lease_end_time - (lease_time >> 1);
+				dhcp->lease_p2_time = dhcp->lease_end_time - (lease_time >> 3);
 			}
+			break;
+		case DHCP_OPTION_PAD:
+			in->Pos++;
+			goto __CHECK;
+			break;
+		case DHCP_OPTION_END:
+			return ack;
+		case DHCP_OPTION_SUBNET_MASK:
+			dhcp->submask = BytesGetLe32(&in->Data[in->Pos + 2]);
+			break;
+		case DHCP_OPTION_ROUTER:
+			dhcp->gateway = BytesGetLe32(&in->Data[in->Pos + 2]);
+			break;
+		default:
+//			DBG("jump %d,%d", in->Data[in->Pos], in->Data[in->Pos+1]);
+			break;
 		}
+		in->Pos += 2 + in->Data[in->Pos+1];
 	}
-	else
-	{
-		reset_DHCP_timeout();
-		DHCP_timeout = 1;
-
-		send_DHCP_DISCOVER();
-		dhcp_state = STATE_DHCP_DISCOVER;
-#ifdef _DHCP_DEBUG_
-		printf("timeout : state : STATE_DHCP_DISCOVER\r\n");
-#endif
-	}
+	return ack;
 }
 
-///-------------------------------------------------------------------------------------------------
-/// <summary>Check if a leased IP is valid.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///
-/// <returns>Success - 1, Fail - 0..</returns>
-///-------------------------------------------------------------------------------------------------
-
-int8_t check_DHCP_leasedIP(void)
+int ip4_dhcp_run(dhcp_client_info_t *dhcp, Buffer_Struct *in, Buffer_Struct *out, uint32_t *remote_ip)
 {
-	uint8_t tmp;
-	int32_t ret;
-
-	//WIZchip RCR value changed for ARP Timeout count control
-	tmp = getRCR();
-	setRCR(0x03);
-#ifdef _DHCP_DEBUG_
-	printf("<Check the IP Conflict %d.%d.%d.%d: ", DHCP_allocated_ip[0], DHCP_allocated_ip[1], DHCP_allocated_ip[2], DHCP_allocated_ip[3]);
-#endif
-	// IP conflict detection : ARP request - ARP reply
-	// Broadcasting ARP Request for check the IP conflict using UDP sendto() function
-	ret = sendto(DHCP_SOCKET, (uint8_t*)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
-
-	// RCR value restore
-	setRCR(tmp);
-
-	if (ret) {
-		// Received ARP reply or etc : IP address conflict occur, DHCP Failed
-		send_DHCP_DECLINE();
-		ret = dhcp_time;
-		while ((dhcp_time - ret) < 2);   // wait for 1s over; wait to complete to send DECLINE message;
-
-		return 0;
-	}
-	else
+	uint16_t flag = 0x8000;
+	*remote_ip = 0xffffffff;
+	int result;
+	if (in)
 	{
-		// UDP send Timeout occurred : allocated IP address is unique, DHCP Success
-#ifdef _DHCP_DEBUG_
-		printf("\r\n> Check leased IP - OK\r\n");
-#endif
-		return 1;
-	}
-}
+		result = analyze_ip4_dhcp(dhcp, in);
 
-///-------------------------------------------------------------------------------------------------
-/// <summary>Timer interrupt handler(For checking dhcp lease time), Increase 'my_time' each one second.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void DHCP_timer_handler(void)
-{
-	if (dhcp_tick_cnt++ > 1000)
-	{
-		dhcp_tick_cnt = 0;
-		dhcp_time++;
+		if (result > 0)
+		{
+			if (result == DHCP_NAK)
+			{
+				dhcp->state = DHCP_STATE_DISCOVER;
+				dhcp->temp_ip = 0;
+				dhcp->server_ip = 0;
+				dhcp->submask = 0;
+				dhcp->gateway = 0;
+				dhcp->ip = 0;
+				dhcp->last_tx_time = 0;
+				dhcp->lease_p1_time = 0;
+				dhcp->lease_p2_time = 0;
+			}
+		}
+		else
+		{
+			return -1;
+		}
 	}
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>Initializes the DHCP client.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///-------------------------------------------------------------------------------------------------
-
-void init_dhcp_client(void)
-{
-	uint8_t txsize[MAX_SOCK_NUM] = { 2,2,2,2,2,2,2,2 };
-	uint8_t rxsize[MAX_SOCK_NUM] = { 2,2,2,2,2,2,2,2 };
-
-	uint8_t ip_0[4] = { 0, };
-	DHCP_XID = 0x12345678;
-	memset(OLD_SIP, 0, sizeof(OLD_SIP));
-	memset(DHCP_SIP, 0, sizeof(DHCP_SIP));
-	memset(DHCP_REAL_SIP, 0, sizeof(GET_SN_MASK));
-
-	iinchip_init();
-
-	setSHAR(DHCP_CHADDR);
-	setSUBR(ip_0);
-	setGAR(ip_0);
-	setSIPR(ip_0);
-	printf("MAC=%02x:%02x:%02x:%02x:%02x:%02x\r\n", DHCP_CHADDR[0], DHCP_CHADDR[1], DHCP_CHADDR[2], DHCP_CHADDR[3], DHCP_CHADDR[4], DHCP_CHADDR[5]);
-	sysinit(txsize, rxsize);
-	//clear ip setted flag
-
-	dhcp_state = STATE_DHCP_READY;
-#ifdef _DHCP_DEBUG
-	printf("init_dhcp_client:%u\r\n", DHCP_SOCKET);
-#endif
-}
-
-///-------------------------------------------------------------------------------------------------
-/// <summary>Process the DHCP client.</summary>
-///
-/// <remarks>Tony Wang, 2021/6/28.</remarks>
-///
-/// <returns>An uint8_t.</returns>
-///-------------------------------------------------------------------------------------------------
-
-uint8_t DHCP(void)//20180625
-{
-	uint8_t  type;
-	uint8_t  ret;
-
-	if (dhcp_state == STATE_DHCP_STOP)
-		return DHCP_STOPPED;
-
-	if (getSn_SR(DHCP_SOCKET) != SOCK_UDP)
-		socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
-
-	ret = DHCP_RUNNING;
-
-	type = parseDHCPMSG();
-
-	switch (dhcp_state)
+//	DBG("%d,%d", dhcp->state, result);
+	switch(dhcp->state)
 	{
-
-	case STATE_DHCP_READY:
-
-		DHCP_allocated_ip[0] = 0;
-		DHCP_allocated_ip[1] = 0;
-		DHCP_allocated_ip[2] = 0;
-		DHCP_allocated_ip[3] = 0;
-
-		send_DHCP_DISCOVER();
-
-		dhcp_time = 0;
-
-		dhcp_state = STATE_DHCP_DISCOVER;
-
+	case DHCP_STATE_WAIT_LEASE_P1:
+		if (GetSysTickMS() >= dhcp->lease_p1_time)
+		{
+			flag = 0;
+			*remote_ip = dhcp->server_ip;
+			dhcp->state = DHCP_STATE_WAIT_LEASE_P1_ACK;
+			goto DHCP_NEED_REQUIRE;
+		}
 		break;
-
-	case STATE_DHCP_DISCOVER:
-
-		if (type == DHCP_OFFER)
+	case DHCP_STATE_WAIT_LEASE_P1_ACK:
+		if (in && (result == DHCP_ACK))
 		{
-#ifdef _DHCP_DEBUG_
-			printf("> Receive DHCP_OFFER\r\n");
-#endif
-			DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
-			DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
-			DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
-			DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
-
-			send_DHCP_REQUEST();
-
-			dhcp_time = 0;
-
-			dhcp_state = STATE_DHCP_REQUEST;
+			DBG("lease p1 require ip ok");
+			dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
+			break;
+		}
+		if (GetSysTickMS() >= (dhcp->last_tx_time + 2500))
+		{
+			DBG("lease p1 require ip long time no ack");
+			dhcp->state = DHCP_STATE_WAIT_LEASE_P2;
 		}
-		else
-			ret = check_DHCP_timeout();
-
 		break;
-
-	case STATE_DHCP_REQUEST:
-
-		if (type == DHCP_ACK)
+	case DHCP_STATE_WAIT_LEASE_P2:
+		if (GetSysTickMS() >= dhcp->lease_p2_time)
 		{
-#ifdef _DHCP_DEBUG_
-			printf("> Receive DHCP_ACK\r\n");
-#endif
-			if (check_DHCP_leasedIP())
-			{
-				printf("DHCP Update\r\n");
-
-				// Network info assignment from DHCP
-				printf("W5500EVB IP : %d.%d.%d.%d\r\n", DHCP_allocated_ip[0], DHCP_allocated_ip[1], DHCP_allocated_ip[2], DHCP_allocated_ip[3]);
-				printf("W5500EVB SN : %d.%d.%d.%d\r\n", DHCP_allocated_sn[0], DHCP_allocated_sn[1], DHCP_allocated_sn[2], DHCP_allocated_sn[3]);
-				printf("W5500EVB GW : %d.%d.%d.%d\r\n", DHCP_allocated_gw[0], DHCP_allocated_gw[1], DHCP_allocated_gw[2], DHCP_allocated_gw[3]);
-
-				dhcp_ip_assign();
-
-				reset_DHCP_timeout();
-
-				dhcp_state = STATE_DHCP_LEASED;
-			}
-			else
-			{
-				// IP address conflict occurred
-				reset_DHCP_timeout();
-
-				dhcp_ip_conflict();
-
-				dhcp_state = STATE_DHCP_READY;
-			}
+			dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
+			goto DHCP_NEED_REQUIRE;
 		}
-		else if (type == DHCP_NAK)
+		break;
+	case DHCP_STATE_WAIT_LEASE_P2_ACK:
+		if (in && (result == DHCP_ACK))
 		{
-#ifdef _DHCP_DEBUG_
-			printf("> Receive DHCP_NACK\r\n");
-#endif
-			reset_DHCP_timeout();
-
-			dhcp_state = STATE_DHCP_DISCOVER;
-	}
-		else
-			ret = check_DHCP_timeout();
-
+			DBG("lease p2 require ip ok");
+			dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
+			break;
+		}
+		if (GetSysTickMS() >= (dhcp->last_tx_time + 2500))
+		{
+			DBG("lease p2 require ip long time no ack");
+			dhcp->state = DHCP_STATE_WAIT_LEASE_END;
+		}
 		break;
-
-	case STATE_DHCP_LEASED:
-
-		ret = DHCP_IP_LEASED;
-
-		if ((dhcp_lease_time != DEFAULT_LEASETIME) && ((dhcp_lease_time / 2) < dhcp_time))
+	case DHCP_STATE_WAIT_LEASE_END:
+		if (GetSysTickMS() >= dhcp->lease_end_time)
 		{
-#ifdef _DHCP_DEBUG_
-			printf("> Maintains the IP address \r\n");
-#endif
-
-			type = 0;
-
-			OLD_allocated_ip[0] = DHCP_allocated_ip[0];
-			OLD_allocated_ip[1] = DHCP_allocated_ip[1];
-			OLD_allocated_ip[2] = DHCP_allocated_ip[2];
-			OLD_allocated_ip[3] = DHCP_allocated_ip[3];
-
-			DHCP_XID++;
-
-			send_DHCP_REQUEST();
-
-			reset_DHCP_timeout();
-
-			dhcp_state = STATE_DHCP_REREQUEST;
-}
-
+			dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
+			goto DHCP_NEED_REQUIRE;
+		}
 		break;
-
-	case STATE_DHCP_REREQUEST:
-
-		ret = DHCP_IP_LEASED;
-
-		if (type == DHCP_ACK)
+	case DHCP_STATE_WAIT_REQUIRE_ACK:
+		if (in && (result == DHCP_ACK))
 		{
-			dhcp_retry_count = 0;
-
-			if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
-				OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
-				OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
-				OLD_allocated_ip[3] != DHCP_allocated_ip[3])
-			{
-				ret = DHCP_IP_CHANGED;
-
-				dhcp_ip_update();
-
-#ifdef _DHCP_DEBUG_
-				printf(">IP changed.\r\n");
-#endif
-			}
-
-#ifdef _DHCP_DEBUG_
-			else printf(">IP is continued.\r\n");
-#endif
-
-			reset_DHCP_timeout();
-
-			dhcp_state = STATE_DHCP_LEASED;
-			}
-		else if (type == DHCP_NAK)
+			DBG("require ip ok");
+			dhcp->state = DHCP_STATE_WAIT_LEASE_P1;
+			break;
+		}
+		if (GetSysTickMS() >= (dhcp->last_tx_time + 2500))
 		{
-#ifdef _DHCP_DEBUG_
-			printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
-#endif
-
-			reset_DHCP_timeout();
-
-			dhcp_state = STATE_DHCP_DISCOVER;
+			DBG("require ip long time no ack");
+			OS_ReInitBuffer(out, 512);
+			make_ip4_dhcp_discover_msg(dhcp, out);
+			dhcp->last_tx_time = GetSysTickMS();
+			dhcp->discover_cnt = 0;
+			dhcp->state = DHCP_STATE_WAIT_OFFER;
 		}
-		else
-			ret = check_DHCP_timeout();
-
 		break;
+	case DHCP_STATE_DISCOVER:
 
-	default:
-
+		OS_ReInitBuffer(out, 512);
+		make_ip4_dhcp_discover_msg(dhcp, out);
+		dhcp->last_tx_time = GetSysTickMS();
+		dhcp->discover_cnt = 0;
+		dhcp->state = DHCP_STATE_WAIT_OFFER;
+		break;
+	case DHCP_STATE_WAIT_OFFER:
+		if (in && (result == DHCP_OFFER))
+		{
+			dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
+			goto DHCP_NEED_REQUIRE;
+		}
+		if (GetSysTickMS() >= (dhcp->last_tx_time + 2500))
+		{
+			DBG("long time no offer");
+			dhcp->discover_cnt++;
+			OS_ReInitBuffer(out, 512);
+			make_ip4_dhcp_discover_msg(dhcp, out);
+			dhcp->last_tx_time = GetSysTickMS();
+		}
+		break;
+	case DHCP_STATE_WAIT_SELECT_ACK:
+		if (in && (result == DHCP_ACK))
+		{
+//			DBG("need check ip %x,%x,%x,%x", dhcp->temp_ip, dhcp->submask, dhcp->gateway, dhcp->server_ip);
+			dhcp->ip = dhcp->temp_ip;
+			dhcp->state = DHCP_STATE_CHECK;
+			break;
+		}
+		if (GetSysTickMS() >= (dhcp->last_tx_time + 2500))
+		{
+			DBG("select ip long time no ack");
+			OS_ReInitBuffer(out, 512);
+			make_ip4_dhcp_discover_msg(dhcp, out);
+			dhcp->last_tx_time = GetSysTickMS();
+			dhcp->discover_cnt = 0;
+			dhcp->state = DHCP_STATE_WAIT_OFFER;
+		}
+		break;
+	case DHCP_STATE_REQUIRE:
+	case DHCP_STATE_SELECT:
+		dhcp->state = DHCP_STATE_WAIT_SELECT_ACK;
+		goto DHCP_NEED_REQUIRE;
+		break;
+	case DHCP_STATE_CHECK:
+		break;
+	case DHCP_STATE_DECLINE:
+		flag = 0;
+		*remote_ip = dhcp->server_ip;
+		OS_ReInitBuffer(out, 512);
+		make_ip4_dhcp_decline_msg(dhcp, out);
+		dhcp->last_tx_time = GetSysTickMS();
+		dhcp->state = DHCP_STATE_DISCOVER;
+		break;
+	case DHCP_STATE_NOT_WORK:
 		break;
 	}
-	return ret;
+	return 0;
+DHCP_NEED_REQUIRE:
+	OS_ReInitBuffer(out, 512);
+	make_ip4_dhcp_select_msg(dhcp, flag, out);
+	dhcp->last_tx_time = GetSysTickMS();
+	return 0;
 }
+
 #endif

+ 46 - 14
components/ethernet/common/dhcp_def.h

@@ -1,8 +1,9 @@
 
 #ifndef __ETHERNET_COMMON_DHCP_DEF_H__
 #define __ETHERNET_COMMON_DHCP_DEF_H__
-
-
+#include "luat_base.h"
+#ifdef LUAT_USE_DHCP
+#include "bsp_common.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -25,27 +26,48 @@ extern "C" {
 
 typedef struct
 {
-	unsigned int dhcp_server_ip;
-	unsigned int dhcp_ip;
-	unsigned int dhcp_submask;
-	unsigned int dhcp_gateway;
-	unsigned int dhcp_t1;
-	unsigned int dhcp_t2;
-	unsigned char state;
+	uint64_t lease_end_time;
+	uint64_t lease_p1_time;
+	uint64_t lease_p2_time;
+	uint64_t last_tx_time;
+	uint32_t server_ip;
+	uint32_t temp_ip;	//服务器给的动态IP
+	uint32_t submask;
+	uint32_t gateway;
+	uint32_t ip;	//当前的动态IP
+	uint32_t xid;
+
+	char name[32];
+	uint8_t mac[6];
+	uint8_t state;
+	uint8_t discover_cnt;
 }dhcp_client_info_t;
 
+typedef struct
+{
+	uint8_t *p;
+	uint16_t len;
+	uint8_t id;
+	uint8_t unuse;
+}dhcp_option_t;
 
 
 /* DHCP client states */
 enum {
   DHCP_STATE_NOT_WORK             = 0,
-  DHCP_STATE_WAIT_LINK_READY,
-  DHCP_STATE_REQUEST,
+  DHCP_STATE_WAIT_LEASE_P1,
+  DHCP_STATE_WAIT_LEASE_P1_ACK,
+  DHCP_STATE_WAIT_LEASE_P2,
+  DHCP_STATE_WAIT_LEASE_P2_ACK,
+  DHCP_STATE_WAIT_LEASE_END,
+  DHCP_STATE_DISCOVER,
+  DHCP_STATE_WAIT_OFFER,
   DHCP_STATE_SELECT,
+  DHCP_STATE_WAIT_SELECT_ACK,
+  DHCP_STATE_REQUIRE,
+  DHCP_STATE_WAIT_REQUIRE_ACK,
+  DHCP_STATE_DECLINE,
   DHCP_STATE_CHECK,
-  DHCP_STATE_WAIT_P1,
-  DHCP_STATE_WAIT_P2,
-
 };
 
 /* DHCP op codes */
@@ -111,8 +133,18 @@ enum {
 #define DHCP_OVERLOAD_SNAME         2
 #define DHCP_OVERLOAD_SNAME_FILE    3
 
+void make_ip4_dhcp_msg_base(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out);
+void ip4_dhcp_msg_add_bytes_option(uint8_t id, uint8_t *data, uint8_t len, Buffer_Struct *out);
+void ip4_dhcp_msg_add_ip_option(uint8_t id, uint32_t ip, Buffer_Struct *out);
+void ip4_dhcp_msg_add_integer_option(uint8_t id, uint8_t len, uint32_t value, Buffer_Struct *out);
+void make_ip4_dhcp_discover_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out);
+void make_ip4_dhcp_select_msg(dhcp_client_info_t *dhcp, uint16_t flag, Buffer_Struct *out);
+void make_ip4_dhcp_decline_msg(dhcp_client_info_t *dhcp, Buffer_Struct *out);
+int analyze_ip4_dhcp(dhcp_client_info_t *dhcp, Buffer_Struct *in);
+int ip4_dhcp_run(dhcp_client_info_t *dhcp, Buffer_Struct *in, Buffer_Struct *out, uint32_t *remote_ip);
 #ifdef __cplusplus
 }
 #endif
 
 #endif
+#endif

+ 1 - 1
components/ethernet/common/dns_def.h

@@ -8,6 +8,6 @@
 #ifndef __ETHERNET_COMMON_DNS_DEF_H__
 #define __ETHERNET_COMMON_DNS_DEF_H__
 
-
+#define DNS_SERVER_PORT                    (53)
 
 #endif /* __ETHERNET_COMMON_DNS_DEF_H__ */

+ 282 - 143
components/ethernet/w5500/w5500.c

@@ -136,6 +136,7 @@ enum
 
 	EV_W5500_IRQ = USER_EVENT_ID_START + 1,
 	EV_W5500_LINK,
+	//以下event的顺序不能变,新增event请在上方添加
 	EV_W5500_SOCKET_TX,
 	EV_W5500_SOCKET_CONNECT,
 	EV_W5500_SOCKET_CLOSE,
@@ -163,8 +164,6 @@ typedef struct
 	CBFuncEx_t socket_cb;
 	void *user_data;
 	void *task_handle;
-	void *period_timer;
-	void *dhcp_timer;
 	uint32_t static_ip; //大端格式存放
 	uint32_t static_submask; //大端格式存放
 	uint32_t static_gateway; //大端格式存放
@@ -182,14 +181,14 @@ typedef struct
 	uint8_t network_ready;
 	uint8_t inter_error;
 	uint8_t device_on;
-	uint8_t socket_irq[MAX_SOCK_NUM];
-	uint8_t data_buf[2048 + 8];
+	uint8_t rx_buf[2048 + 8];
 	uint8_t socket_state[MAX_SOCK_NUM];
 }w5500_ctrl_t;
 
 static w5500_ctrl_t *prv_w5500_ctrl;
 
 static void w5500_ip_state(w5500_ctrl_t *w5500, uint8_t check_state);
+static void w5500_check_dhcp(w5500_ctrl_t *w5500);
 
 static int32_t w5500_irq(int pin, void *args)
 {
@@ -209,42 +208,47 @@ static void w5500_callback_to_nw_task(w5500_ctrl_t *w5500, uint32_t event, uint3
 
 }
 
-static void w5500_xfer(w5500_ctrl_t *w5500, uint16_t address, uint8_t ctrl, uint8_t *data, uint32_t len, uint8_t *buf)
+static void w5500_xfer(w5500_ctrl_t *w5500, uint16_t address, uint8_t ctrl, uint8_t *data, uint32_t len)
 {
-	BytesPutBe16(buf, address);
-	buf[2] = ctrl;
+	BytesPutBe16(w5500->rx_buf, address);
+	w5500->rx_buf[2] = ctrl;
 	if (data && len)
 	{
-		memcpy(buf + 3, data, len);
+		memcpy(w5500->rx_buf + 3, data, len);
 	}
 	luat_gpio_set(w5500->cs_pin, 0);
-	luat_spi_transfer(w5500->spi_id, buf, len + 3, buf, len + 3);
+	luat_spi_transfer(w5500->spi_id, w5500->rx_buf, len + 3, w5500->rx_buf, len + 3);
 	luat_gpio_set(w5500->cs_pin, 1);
+	if (data && len)
+	{
+		memcpy(data, w5500->rx_buf + 3, len);
+	}
 }
 
 
 static uint8_t w5500_socket_state(w5500_ctrl_t *w5500, uint8_t socket_id)
 {
 	uint8_t retry = 0;
+	uint8_t temp[4];
 	do
 	{
-		w5500_xfer(w5500, 0, socket_index(socket_id)|socket_reg, NULL, 4, w5500->data_buf);
-		if (w5500->data_buf[3 + W5500_SOCKET_MR] == 0xff)	//模块读不到了
+		w5500_xfer(w5500, W5500_SOCKET_MR, socket_index(socket_id)|socket_reg, temp, 4);
+		if (temp[W5500_SOCKET_MR] == 0xff)	//模块读不到了
 		{
 			w5500->device_on = 0;
 			return 0;
 		}
 		retry++;
-	}while(w5500->data_buf[3 + W5500_SOCKET_CR] && (retry < 10));
+	}while(temp[W5500_SOCKET_CR] && (retry < 10));
 	if (retry >= 10)
 	{
 		DBG("!");
 		w5500->inter_error = 1;
 	}
-	return w5500->data_buf[3 + W5500_SOCKET_SR];
+	return temp[W5500_SOCKET_SR];
 }
 
-static void w5500_socket_close(w5500_ctrl_t *w5500, uint8_t socket_id)
+static void w5500_socket_disconnect(w5500_ctrl_t *w5500, uint8_t socket_id)
 {
 	uint8_t temp;
 	temp = w5500_socket_state(w5500, socket_id);
@@ -264,10 +268,26 @@ static void w5500_socket_close(w5500_ctrl_t *w5500, uint8_t socket_id)
 
 	}
 	temp = Sn_CR_DISCON;
-	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, &temp, 1, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, &temp, 1);
 	w5500->socket_state[socket_id] = W5500_SOCKET_CLOSING;
 }
 
+static void w5500_socket_close(w5500_ctrl_t *w5500, uint8_t socket_id)
+{
+	uint8_t temp;
+	temp = w5500_socket_state(w5500, socket_id);
+	if (!w5500->device_on) return;
+
+	if (SOCK_CLOSED == temp)
+	{
+		w5500->socket_state[socket_id] = W5500_SOCKET_OFFLINE;
+		DBG("socket %d already closed");
+		return;
+	}
+	temp = Sn_CR_CLOSE;
+	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, &temp, 1);
+	w5500->socket_state[socket_id] = W5500_SOCKET_OFFLINE;
+}
 
 static int w5500_socket_config(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t is_tcp, uint16_t local_port)
 {
@@ -277,7 +297,7 @@ static int w5500_socket_config(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t i
 	if (!w5500->device_on) return -1;
 	if (SOCK_CLOSED != temp)
 	{
-		DBG("socket %d not closed state %x", temp);
+		DBG("socket %d not closed state %x", socket_id, temp);
 		return -1;
 	}
 	uint8_t cmd[32];
@@ -285,14 +305,14 @@ static int w5500_socket_config(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t i
 	for(temp = 0; temp < 3; temp++)
 	{
 		cmd[W5500_SOCKET_MR] = is_tcp?Sn_MR_TCP:Sn_MR_UDP;
-		cmd[W5500_SOCKET_CR] = Sn_CR_OPEN;
+		cmd[W5500_SOCKET_CR] = 0;
 		cmd[W5500_SOCKET_IR] = 0xff;
 		BytesPutBe16(&cmd[W5500_SOCKET_SOURCE_PORT0], local_port);
-		BytesPutLe32(&cmd[W5500_SOCKET_DEST_IP0], 0);
-		BytesPutBe16(&cmd[W5500_SOCKET_DEST_PORT0], 0);
+		BytesPutLe32(&cmd[W5500_SOCKET_DEST_IP0], 0xffffffff);
+		BytesPutBe16(&cmd[W5500_SOCKET_DEST_PORT0], 67);
 		BytesPutBe16(&cmd[W5500_SOCKET_SEGMENT0], is_tcp?1460:1472);
-		w5500_xfer(w5500, W5500_SOCKET_MR, socket_index(socket_id)|socket_reg|is_write, cmd, W5500_SOCKET_TOS - 1, w5500->data_buf);
-		w5500_xfer(w5500, W5500_SOCKET_MR, socket_index(socket_id)|socket_reg, cmd, W5500_SOCKET_TOS - 1, w5500->data_buf);
+		w5500_xfer(w5500, W5500_SOCKET_MR, socket_index(socket_id)|socket_reg|is_write, cmd, W5500_SOCKET_TOS - 1);
+		w5500_xfer(w5500, W5500_SOCKET_MR, socket_index(socket_id)|socket_reg, cmd, W5500_SOCKET_TOS - 1);
 		wtemp = BytesGetBe16(&cmd[W5500_SOCKET_SOURCE_PORT0]);
 		if (wtemp != local_port)
 		{
@@ -302,25 +322,21 @@ static int w5500_socket_config(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t i
 		{
 			goto W5500_SOCKET_CONFIG_START;
 		}
+
 	}
 	return -1;
 W5500_SOCKET_CONFIG_START:
+	cmd[0] = Sn_CR_OPEN;
+	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, cmd, 1);
 	do
 	{
-		luat_timer_mdelay(1);
 		temp = w5500_socket_state(w5500, socket_id);
 		if (!w5500->device_on) return -1;
-		if (SOCK_CLOSED != temp)
-		{
-			DBG("socket %d not closed");
-			return -1;
-		}
 		delay_cnt++;
 	}while((temp != SOCK_INIT) && (temp != SOCK_UDP) && (delay_cnt < 100));
-
 	if (delay_cnt >= 100)
 	{
-		DBG("socket %d config timeout");
+		DBG("socket %d config timeout", socket_id);
 		return -1;
 	}
 
@@ -330,46 +346,43 @@ W5500_SOCKET_CONFIG_START:
 
 static int w5500_socket_connect(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t is_listen, uint32_t remote_ip, uint16_t remote_port)
 {
+	uint32_t ip;
+	uint16_t port;
 	uint8_t delay_cnt;
 	uint8_t temp;
-	uint8_t cmd[32];
+	uint8_t cmd[16];
 	temp = w5500_socket_state(w5500, socket_id);
 	if (!w5500->device_on) return -1;
 	if ((temp != SOCK_INIT) && (temp != SOCK_UDP))
 	{
-		DBG("socket %d not config state %x", temp);
+		DBG("socket %d not config state %x", socket_id, temp);
 		return -1;
 	}
-
+//	DBG("%08x, %u", remote_ip, remote_port);
 	if (!is_listen)
 	{
-		uint16_t wtemp;
-		uint32_t ip;
-		for(temp = 0; temp < 3; temp++)
+		w5500_xfer(w5500, W5500_SOCKET_DEST_IP0, socket_index(socket_id)|socket_reg, cmd, 6);
+		ip = BytesGetLe32(cmd);
+		port = BytesGetBe16(cmd + 4);
+		if (ip != remote_ip || port != remote_port)
 		{
-			BytesPutLe32(&cmd[0], remote_ip);
+			BytesPutLe32(cmd, remote_ip);
 			BytesPutBe16(&cmd[W5500_SOCKET_DEST_PORT0 - W5500_SOCKET_DEST_IP0], remote_port);
-			w5500_xfer(w5500, W5500_SOCKET_DEST_IP0, socket_index(socket_id)|socket_reg|is_write, cmd, 6, w5500->data_buf);
-			w5500_xfer(w5500, W5500_SOCKET_DEST_IP0, socket_index(socket_id)|socket_reg, cmd, 6, w5500->data_buf);
-			wtemp = BytesGetBe16(&cmd[W5500_SOCKET_DEST_PORT0 - W5500_SOCKET_DEST_IP0]);
-			ip = BytesGetLe32(&cmd[0]);
-			if ((wtemp != remote_port) || (ip != remote_ip))
-			{
-				DBG("error ip port %u,%u,%x,%x", wtemp, remote_port, ip, remote_ip);
-			}
-			else
-			{
-				goto W5500_SOCKET_CONNECT_START;
-			}
+			w5500_xfer(w5500, W5500_SOCKET_DEST_IP0, socket_index(socket_id)|socket_reg|is_write, cmd, 6);
+//			if (temp == SOCK_UDP)
+//			{
+//				cmd[0] = Sn_CR_SEND;
+//				w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, cmd, 1);
+//			}
 		}
-		return -1;
+
 	}
 W5500_SOCKET_CONNECT_START:
 	if (temp != SOCK_UDP)
 	{
 
 		uint8_t temp = is_listen?Sn_CR_LISTEN:Sn_CR_CONNECT;
-		w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, &temp, 1, w5500->data_buf);
+		w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, &temp, 1);
 		w5500->socket_state[socket_id] = W5500_SOCKET_CONNECT;
 	}
 	return 0;
@@ -377,18 +390,9 @@ W5500_SOCKET_CONNECT_START:
 
 static int w5500_socket_auto_heart(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t time)
 {
-	uint8_t temp;
 	uint8_t point[6];
-	uint16_t tx_free, tx_point;
-	temp = w5500_socket_state(w5500, socket_id);
-	if (!w5500->device_on) return -1;
-	if ((temp != SOCK_ESTABLISHED))
-	{
-		DBG("socket %d not online tcp state %x", temp);
-		return -1;
-	}
 	point[0] = time;
-	w5500_xfer(w5500, W5500_SOCKET_KEEP_TIME, socket_index(socket_id)|socket_reg|is_write, point, 1, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_KEEP_TIME, socket_index(socket_id)|socket_reg|is_write, point, 1);
 	return 0;
 }
 
@@ -402,29 +406,29 @@ static int w5500_socket_tx(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t *data
 	if (!w5500->device_on) return -1;
 	if ((temp != SOCK_ESTABLISHED) && (temp != SOCK_UDP))
 	{
-		DBG("socket %d not online state %x", temp);
+		DBG("socket %d not online state %x", socket_id, temp);
 		return -1;
 	}
 	w5500->socket_state[socket_id] = W5500_SOCKET_ONLINE;
 	if (!data || !len)
 	{
 		point[0] = Sn_CR_SEND_KEEP;
-		w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1, w5500->data_buf);
+		w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1);
 	}
 
-	w5500_xfer(w5500, W5500_SOCKET_TX_FREE_SIZE0, socket_index(socket_id)|socket_reg, point, 6, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_TX_FREE_SIZE0, socket_index(socket_id)|socket_reg, point, 6);
 	tx_free = BytesGetBe16(point);
 	tx_point = BytesGetBe16(point + 4);
 	if (len > tx_free)
 	{
 		len = tx_free;
 	}
-	w5500_xfer(w5500, tx_point, socket_index(socket_id)|socket_tx|is_write, data, len, w5500->data_buf);
+	w5500_xfer(w5500, tx_point, socket_index(socket_id)|socket_tx|is_write, data, len);
 	tx_point += len;
 	BytesPutBe16(point, tx_point);
-	w5500_xfer(w5500, W5500_SOCKET_TX_WRITE_POINT0, socket_index(socket_id)|socket_reg|is_write, point, 2, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_TX_WRITE_POINT0, socket_index(socket_id)|socket_reg|is_write, point, 2);
 	point[0] = Sn_CR_SEND;
-	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1);
 	return len;
 }
 
@@ -438,27 +442,26 @@ static int w5500_socket_rx(w5500_ctrl_t *w5500, uint8_t socket_id, uint8_t *data
 	if (!w5500->device_on) return -1;
 	if ((temp != SOCK_ESTABLISHED) && (temp != SOCK_UDP))
 	{
-		DBG("socket %d not config state %x", temp);
+		DBG("socket %d not config state %x", socket_id, temp);
 		return -1;
 	}
 	w5500->socket_state[socket_id] = W5500_SOCKET_ONLINE;
-	w5500_xfer(w5500, W5500_SOCKET_RX_SIZE0, socket_index(socket_id)|socket_reg, point, 4, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_RX_SIZE0, socket_index(socket_id)|socket_reg, point, 4);
 
 	rx_size = BytesGetBe16(point);
 	rx_point = BytesGetBe16(point + 2);
-
+//	DBG("%x,%u", rx_point, rx_size);
 	if (!rx_size) return 0;
 	if (rx_size < len)
 	{
 		len = rx_size;
 	}
-	w5500_xfer(w5500, rx_point, socket_index(socket_id)|socket_rx, NULL, len, w5500->data_buf);
-	memcpy(data, &w5500->data_buf[3], len);
+	w5500_xfer(w5500, rx_point, socket_index(socket_id)|socket_rx, data, len);
 	rx_point += len;
 	BytesPutBe16(point, rx_point);
-	w5500_xfer(w5500, W5500_SOCKET_RX_READ_POINT0, socket_index(socket_id)|socket_reg|is_write, point, 2, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_RX_READ_POINT0, socket_index(socket_id)|socket_reg|is_write, point, 2);
 	point[0] = Sn_CR_RECV;
-	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1, w5500->data_buf);
+	w5500_xfer(w5500, W5500_SOCKET_CR, socket_index(socket_id)|socket_reg|is_write, point, 1);
 	return len;
 }
 
@@ -484,17 +487,53 @@ static void w5500_nw_state(w5500_ctrl_t *w5500)
 	}
 }
 
+
+static void w5500_check_dhcp(w5500_ctrl_t *w5500)
+{
+	if (w5500->static_ip) return;
+	if (DHCP_STATE_CHECK == w5500->dhcp_client.state)
+	{
+		w5500->dhcp_client.state = DHCP_STATE_WAIT_LEASE_P1;
+		uint8_t temp[24];
+		memset(temp, 0, sizeof(temp));
+		BytesPutLe32(&temp[W5500_COMMON_GAR0], w5500->dhcp_client.gateway);
+		BytesPutLe32(&temp[W5500_COMMON_SUBR0], w5500->dhcp_client.submask);
+		BytesPutLe32(&temp[W5500_COMMON_IP0], w5500->dhcp_client.ip);
+		memcpy(&temp[W5500_COMMON_MAC0], w5500->dhcp_client.mac, 6);
+		w5500_xfer(w5500, W5500_COMMON_MR, is_write, temp, W5500_COMMON_INTLEVEL0);
+		w5500->dhcp_client.discover_cnt = 0;
+		w5500_ip_state(w5500, 1);
+	}
+	if (w5500->dhcp_client.discover_cnt > 5)
+	{
+		DBG("dhcp long time not get ip, reboot w5500");
+		memset(&w5500->dhcp_client, 0, sizeof(w5500->dhcp_client));
+		luat_send_event_to_task(w5500->task_handle, EV_W5500_RE_INIT, 0, 0, 0);
+	}
+
+}
+
 static void w5500_link_state(w5500_ctrl_t *w5500, uint8_t check_state)
 {
+	Buffer_Struct tx_msg_buf = {0,0,0};
+	uint32_t remote_ip;
+	int result;
 	if (w5500->link_ready != check_state)
 	{
 		DBG("link %d -> %d", w5500->link_ready, check_state);
 		w5500->link_ready = check_state;
 		if (w5500->link_ready && !w5500->static_ip)
 		{
-			w5500->dhcp_client.state = DHCP_STATE_REQUEST;
-			w5500_socket_connect(w5500, SYS_SOCK_ID, 0, 0xffffffff, DHCP_SERVER_PORT);
-
+			w5500_ip_state(w5500, 0);
+			w5500->dhcp_client.state = w5500->dhcp_client.ip?DHCP_STATE_REQUIRE:DHCP_STATE_DISCOVER;
+			result = ip4_dhcp_run(&w5500->dhcp_client, NULL, &tx_msg_buf, &remote_ip);
+			if (tx_msg_buf.Pos)
+			{
+				w5500_socket_connect(w5500, SYS_SOCK_ID, 0, remote_ip, DHCP_SERVER_PORT);
+				w5500_socket_tx(w5500, SYS_SOCK_ID, tx_msg_buf.Data, tx_msg_buf.Pos);
+			}
+			OS_DeInitBuffer(&tx_msg_buf);
+			w5500_check_dhcp(w5500);
 		}
 		w5500_nw_state(w5500);
 	}
@@ -512,26 +551,53 @@ static void w5500_ip_state(w5500_ctrl_t *w5500, uint8_t check_state)
 
 static void w5500_init_reg(w5500_ctrl_t *w5500)
 {
+
 	uint8_t temp[64];
 	uint8_t *uid;
 	size_t t;
+	luat_gpio_set(w5500->rst_pin, 0);
+	luat_timer_mdelay(1);
+	luat_gpio_set(w5500->rst_pin, 1);
+	luat_timer_mdelay(1);
 	w5500->ip_ready = 0;
 	w5500->network_ready = 0;
-	w5500->dhcp_client.state = w5500->static_ip ? DHCP_STATE_NOT_WORK : DHCP_STATE_WAIT_LINK_READY;
+	if (w5500->static_ip)
+	{
+		w5500->dhcp_client.state = DHCP_STATE_NOT_WORK;
+	}
+	else
+	{
+		if ((w5500->dhcp_client.state == DHCP_STATE_NOT_WORK) || !w5500->dhcp_client.ip)
+		{
+			w5500->dhcp_client.state = DHCP_STATE_DISCOVER;
+		}
+		else
+		{
+			w5500->dhcp_client.state = DHCP_STATE_REQUIRE;
+		}
+	}
 	w5500_callback_to_nw_task(w5500, 0, 0, 0, 0);
 
 	luat_gpio_close(w5500->link_pin);
 	luat_gpio_close(w5500->irq_pin);
 
-	w5500_xfer(w5500, W5500_COMMON_MR, 0, NULL, W5500_COMMON_QTY, w5500->data_buf);
-	w5500->device_on = (0x04 == w5500->data_buf[3 + W5500_COMMON_VERSIONR])?1:0;
-	w5500_link_state(w5500, w5500->device_on?(w5500->data_buf[3 + W5500_COMMON_PHY] & 0x01):0);
+	w5500_xfer(w5500, W5500_COMMON_MR, 0, temp, W5500_COMMON_QTY);
+	w5500->device_on = (0x04 == temp[W5500_COMMON_VERSIONR])?1:0;
+	w5500_link_state(w5500, w5500->device_on?(temp[W5500_COMMON_PHY] & 0x01):0);
 
-	memcpy(temp, w5500->data_buf + 3, W5500_COMMON_QTY);
-	temp[W5500_COMMON_MR] = MR_WOL;
-	BytesPutLe32(&temp[W5500_COMMON_GAR0], w5500->static_gateway);	//已经是大端格式了不需要转换
-	BytesPutLe32(&temp[W5500_COMMON_SUBR0], w5500->static_submask); //已经是大端格式了不需要转换
-	BytesPutLe32(&temp[W5500_COMMON_IP0], w5500->static_ip); //已经是大端格式了不需要转换
+	temp[W5500_COMMON_MR] = 0;
+	if (w5500->static_ip)
+	{
+		BytesPutLe32(&temp[W5500_COMMON_GAR0], w5500->static_gateway);	//已经是大端格式了不需要转换
+		BytesPutLe32(&temp[W5500_COMMON_SUBR0], w5500->static_submask); //已经是大端格式了不需要转换
+		BytesPutLe32(&temp[W5500_COMMON_IP0], w5500->static_ip); //已经是大端格式了不需要转换
+	}
+	else if (w5500->dhcp_client.ip)
+	{
+		BytesPutLe32(&temp[W5500_COMMON_GAR0], w5500->dhcp_client.gateway);
+		BytesPutLe32(&temp[W5500_COMMON_SUBR0], w5500->dhcp_client.submask);
+		BytesPutLe32(&temp[W5500_COMMON_IP0], w5500->dhcp_client.ip);
+	}
 
 	if (w5500->mac1 || w5500->mac2)
 	{
@@ -543,17 +609,23 @@ static void w5500_init_reg(w5500_ctrl_t *w5500)
 		uid = luat_mcu_unique_id(&t);
 		memcpy(&temp[W5500_COMMON_MAC0], &uid[10], 6);
 	}
+	memcpy(w5500->dhcp_client.mac, &temp[W5500_COMMON_MAC0], 6);
+	sprintf_(w5500->dhcp_client.name, "airm2m-%02x%02x%02x%02x%02x%02x",
+			w5500->dhcp_client.mac[0],w5500->dhcp_client.mac[1], w5500->dhcp_client.mac[2],
+			w5500->dhcp_client.mac[3],w5500->dhcp_client.mac[4], w5500->dhcp_client.mac[5]);
+
+
 	BytesPutBe16(&temp[W5500_COMMON_SOCKET_RTR0], w5500->RTR);
 	temp[W5500_COMMON_IMR] = IR_CONFLICT|IR_UNREACH|IR_MAGIC;
 	temp[W5500_COMMON_SOCKET_IMR] = 0xff;
 	temp[W5500_COMMON_PHY] = 0xf8;
 	temp[W5500_COMMON_SOCKET_RCR] = w5500->RCR;
 //	DBG_HexPrintf(temp, W5500_COMMON_QTY);
-	w5500_xfer(w5500, W5500_COMMON_MR, is_write, temp, W5500_COMMON_QTY, w5500->data_buf);
-
+	w5500_xfer(w5500, W5500_COMMON_MR, is_write, temp, W5500_COMMON_QTY);
+//	memset(temp, 0, sizeof(temp));
+//	w5500_xfer(w5500, W5500_COMMON_MR, 0, NULL, W5500_COMMON_QTY);
+//	DBG_HexPrintf(temp, W5500_COMMON_QTY);
 	w5500_ip_state(w5500, w5500->static_ip?1:0);
-	w5500->common_irq = 0;
-	memset(w5500->socket_irq, 0, MAX_SOCK_NUM);
 
 	luat_gpio_t gpio = {0};
 	gpio.pin = w5500->irq_pin;
@@ -572,15 +644,10 @@ static void w5500_init_reg(w5500_ctrl_t *w5500)
 	luat_gpio_setup(&gpio);
 
 	memset(w5500->socket_state, W5500_SOCKET_OFFLINE, MAX_SOCK_NUM);
+	w5500_socket_auto_heart(w5500, SYS_SOCK_ID, 2);
 	w5500_socket_config(w5500, SYS_SOCK_ID, 0, DHCP_CLIENT_PORT);
 }
 
-
-static void w5500_dhcp_run(w5500_ctrl_t *w5500)
-{
-
-}
-
 static int32_t w5500_dummy_callback(void *pData, void *pParam)
 {
 	OS_EVENT *socket_event = (OS_EVENT *)pData;
@@ -601,12 +668,53 @@ static int32_t w5500_dummy_callback(void *pData, void *pParam)
 
 static void w5500_sys_socket_callback(w5500_ctrl_t *w5500, uint8_t event)
 {
-	Buffer_Struct dhcp_msg_buf;
+	Buffer_Struct rx_buf;
+	Buffer_Struct msg_buf;
+	Buffer_Struct tx_msg_buf = {0,0,0};
+	int result, i;
+	uint32_t ip;
+	uint16_t port;
+	uint16_t len;
 	switch(event)
 	{
-	case NW_EVENT_RECV:
+	case Sn_IR_SEND_OK:
+		//DBG("send ok");
 		break;
-	case NW_EVENT_ERR:
+	case Sn_IR_RECV:
+		OS_InitBuffer(&rx_buf, 2048);
+		result = w5500_socket_rx(w5500, SYS_SOCK_ID, rx_buf.Data, rx_buf.MaxLen);
+		if (result > 0)
+		{
+			rx_buf.Pos = 0;
+			while (rx_buf.Pos < result)
+			{
+				ip = BytesGetBe32(rx_buf.Data + rx_buf.Pos);
+				port = BytesGetBe16(rx_buf.Data + rx_buf.Pos + 4);
+				len = BytesGetBe16(rx_buf.Data + rx_buf.Pos + 6);
+				msg_buf.Data = rx_buf.Data + rx_buf.Pos + 8;
+				msg_buf.MaxLen = len;
+				msg_buf.Pos = 0;
+				switch(port)
+				{
+				case DHCP_SERVER_PORT:
+					ip4_dhcp_run(w5500, &msg_buf, &tx_msg_buf, &ip);
+					if (tx_msg_buf.Pos)
+					{
+						w5500_socket_connect(w5500, SYS_SOCK_ID, 0, ip, DHCP_SERVER_PORT);
+						w5500_socket_tx(w5500, SYS_SOCK_ID, tx_msg_buf.Data, tx_msg_buf.Pos);
+					}
+					OS_DeInitBuffer(&tx_msg_buf);
+					w5500_check_dhcp(w5500);
+					break;
+				case DNS_SERVER_PORT:
+					break;
+				}
+				rx_buf.Pos += 8 + len;
+			}
+		}
+
+		break;
+	case Sn_IR_TIMEOUT:
 		break;
 	default:
 		break;
@@ -617,18 +725,17 @@ static void w5500_read_irq(w5500_ctrl_t *w5500)
 {
 	OS_EVENT socket_event;
 	uint8_t temp[64];
+	uint8_t socket_irqs[MAX_SOCK_NUM];
 	uint8_t socket_irq, common_irq;
-	int i, j;
-	w5500_xfer(w5500, W5500_COMMON_IR, 0, NULL, W5500_COMMON_QTY - W5500_COMMON_IR, w5500->data_buf);
-	memcpy(temp, w5500->data_buf + 3, W5500_COMMON_QTY - W5500_COMMON_IR);
+	Buffer_Struct tx_msg_buf = {0,0,0};
+	uint32_t remote_ip;
+	int i;
+	w5500_xfer(w5500, W5500_COMMON_IR, 0, temp, W5500_COMMON_QTY - W5500_COMMON_IR);
 	common_irq = temp[0] & 0xf0;
 	socket_irq = temp[W5500_COMMON_SOCKET_IR - W5500_COMMON_IR];
-	w5500->device_on = (0x04 == w5500->data_buf[3 + W5500_COMMON_VERSIONR])?1:0;
-	w5500_link_state(w5500, w5500->device_on?(w5500->data_buf[W5500_COMMON_PHY - W5500_COMMON_IR] & 0x01):0);
-	temp[0] = 0;
-	temp[W5500_COMMON_IMR - W5500_COMMON_IR] = IR_CONFLICT|IR_UNREACH|IR_MAGIC;
-	temp[W5500_COMMON_SOCKET_IR - W5500_COMMON_IR] = 0;
-	w5500_xfer(w5500, W5500_COMMON_IR, is_write, temp, 3, w5500->data_buf);
+	w5500->device_on = (0x04 == temp[W5500_COMMON_VERSIONR - W5500_COMMON_IR])?1:0;
+	w5500_link_state(w5500, w5500->device_on?(temp[W5500_COMMON_PHY - W5500_COMMON_IR] & 0x01):0);
+	memset(socket_irqs, 0, MAX_SOCK_NUM);
 
 	if (!w5500->device_on)
 	{
@@ -637,42 +744,65 @@ static void w5500_read_irq(w5500_ctrl_t *w5500)
 
 		return;
 	}
-	if (common_irq & IR_CONFLICT)
+	if (common_irq)
 	{
-		DBG("!");
+		DBG("%x", common_irq);
+		if (common_irq & IR_CONFLICT)
+		{
+			memset(temp, 0, 4);
+			w5500_xfer(w5500, W5500_COMMON_IP0, is_write, temp, 4);
+			w5500->dhcp_client.state = DHCP_STATE_DECLINE;
+			ip4_dhcp_run(&w5500->dhcp_client, NULL, &tx_msg_buf, &remote_ip);
+			if (tx_msg_buf.Pos)
+			{
+				w5500_socket_connect(w5500, SYS_SOCK_ID, 0, remote_ip, DHCP_SERVER_PORT);
+				w5500_socket_tx(w5500, SYS_SOCK_ID, tx_msg_buf.Data, tx_msg_buf.Pos);
+			}
+			OS_DeInitBuffer(&tx_msg_buf);
+			w5500_ip_state(w5500, 0);
+		}
 	}
+
+	if (socket_irq)
+	{
+		for(i = 0; i < MAX_SOCK_NUM; i++)
+		{
+			if (socket_irq & (1 << i))
+			{
+				w5500_xfer(w5500, W5500_SOCKET_IR, socket_index(i)|socket_reg, &socket_irqs[i], 1);
+				temp[0] = socket_irqs[i];
+				w5500_xfer(w5500, W5500_SOCKET_IR, socket_index(i)|socket_reg|is_write, temp, 1);
+			}
+		}
+	}
+
+	temp[0] = 0;
+	temp[W5500_COMMON_IMR - W5500_COMMON_IR] = IR_CONFLICT|IR_UNREACH|IR_MAGIC;
+	temp[W5500_COMMON_SOCKET_IR - W5500_COMMON_IR] = 0;
+	w5500_xfer(w5500, W5500_COMMON_IR, is_write, temp, 1);
 	if (socket_irq)
 	{
-		if (socket_irq & 0x01)
+
+		if (socket_irqs[0])
 		{
-			for(j = 0; j < 5; j++)
+			for(i = 0; i < 5; i++)
 			{
-				if (socket_irq & (1 << j))
+				if (socket_irqs[0] & (1 << i))
 				{
-					w5500_sys_socket_callback(w5500, j);
+					w5500_sys_socket_callback(w5500, (1 << i));
 				}
 			}
 		}
 		for(i = 1; i < MAX_SOCK_NUM; i++)
 		{
-			if (socket_irq & (1 << i))
+			if (socket_irqs[i])
 			{
-				w5500_xfer(w5500, W5500_SOCKET_IR, socket_index(i)|socket_reg, temp, 1, w5500->data_buf);
-				if (temp[0] != 0xff)
-				{
-					for(j = 0; j < 5; j++)
-					{
-						if (socket_irq & (1 << j))
-						{
-							socket_event.ID = j;
-							socket_event.Param1 = i;
-							w5500->socket_cb(&socket_event, w5500->user_data);
-						}
-					}
-				}
+				DBG("%d,0x%x", i, socket_irqs[i]);
 			}
 		}
+
 	}
+
 }
 
 
@@ -682,18 +812,16 @@ static void w5500_task(void *param)
 	w5500_ctrl_t *w5500 = (w5500_ctrl_t *)param;
 	OS_EVENT event;
 	int result;
-
-	luat_timer_mdelay(1);
-	luat_gpio_set(w5500->rst_pin, 1);
-	luat_timer_mdelay(1);
+	Buffer_Struct tx_msg_buf = {0,0,0};
+	uint32_t remote_ip;
 	w5500_init_reg(w5500);
 	while(1)
 	{
-		result = luat_wait_event_from_task(w5500->task_handle, 0, &event, NULL, (w5500->link_pin != 0xff)?0:1000);
+		result = luat_wait_event_from_task(w5500->task_handle, 0, &event, NULL, (w5500->link_ready || (w5500->link_pin != 0xff))?1000:100);
 
-		w5500_xfer(w5500, W5500_COMMON_MR, 0, NULL, W5500_COMMON_QTY, w5500->data_buf);
-		w5500->device_on = (0x04 == w5500->data_buf[3 + W5500_COMMON_VERSIONR])?1:0;
-		if (w5500->device_on && w5500->data_buf[3 + W5500_COMMON_IMR] != (IR_CONFLICT|IR_UNREACH|IR_MAGIC))
+		w5500_xfer(w5500, W5500_COMMON_MR, 0, NULL, W5500_COMMON_QTY);
+		w5500->device_on = (0x04 == w5500->rx_buf[3 + W5500_COMMON_VERSIONR])?1:0;
+		if (w5500->device_on && w5500->rx_buf[3 + W5500_COMMON_IMR] != (IR_CONFLICT|IR_UNREACH|IR_MAGIC))
 		{
 			w5500_init_reg(w5500);
 		}
@@ -705,11 +833,19 @@ static void w5500_task(void *param)
 		}
 		else
 		{
-			w5500_link_state(w5500, w5500->data_buf[3 + W5500_COMMON_PHY] & 0x01);
+			w5500_link_state(w5500, w5500->rx_buf[3 + W5500_COMMON_PHY] & 0x01);
 		}
 
-		if (result)
+		if (result && w5500->link_ready)
 		{
+			result = ip4_dhcp_run(&w5500->dhcp_client, NULL, &tx_msg_buf, &remote_ip);
+			if (tx_msg_buf.Pos)
+			{
+				w5500_socket_connect(w5500, SYS_SOCK_ID, 0, remote_ip, DHCP_SERVER_PORT);
+				w5500_socket_tx(w5500, SYS_SOCK_ID, tx_msg_buf.Data, tx_msg_buf.Pos);
+			}
+			OS_DeInitBuffer(&tx_msg_buf);
+			w5500_check_dhcp(w5500);
 			continue;
 		}
 		switch(event.ID)
@@ -736,10 +872,6 @@ static void w5500_task(void *param)
 			break;
 		case EV_W5500_RE_INIT:
 			w5500_init_reg(w5500);
-			if (!w5500->static_ip)
-			{
-				//尝试DHCP
-			}
 			break;
 		case EV_W5500_SET_IP:
 			w5500->static_ip = event.Param1;
@@ -807,6 +939,7 @@ int w5500_request(uint32_t cmd, uint32_t param1, uint32_t param2, uint32_t param
 
 void w5500_init(luat_spi_t* spi, uint8_t irq_pin, uint8_t rst_pin, uint8_t link_pin)
 {
+
 	if (!prv_w5500_ctrl)
 	{
 		w5500_ctrl_t *w5500 = luat_heap_malloc(sizeof(w5500_ctrl_t));
@@ -821,7 +954,7 @@ void w5500_init(luat_spi_t* spi, uint8_t irq_pin, uint8_t rst_pin, uint8_t link_
 		w5500->link_pin = link_pin;
 		spi->cs = 0xff;
 		luat_spi_setup(spi);
-//		luat_spi_config_dma(w5500->spi_id, 0xffff, 0xffff);
+		luat_spi_config_dma(w5500->spi_id, 0xffff, 0xffff);
 		luat_gpio_t gpio = {0};
 		gpio.pin = w5500->cs_pin;
 		gpio.mode = Luat_GPIO_OUTPUT;
@@ -833,10 +966,16 @@ void w5500_init(luat_spi_t* spi, uint8_t irq_pin, uint8_t rst_pin, uint8_t link_
 		luat_gpio_setup(&gpio);
 		luat_gpio_set(w5500->rst_pin, 0);
 
+
+		char rands[16];
+		luat_crypto_trng(rands, 16);
+
+		w5500->dhcp_client.xid = BytesGetBe32(rands);
+		w5500->dhcp_client.state = DHCP_STATE_DISCOVER;
 		luat_thread_t thread;
 		thread.task_fun = w5500_task;
 		thread.name = "w5500";
-		thread.stack_size = 1024;
+		thread.stack_size = 2 * 1024;
 		thread.priority = 3;
 		thread.userdata = w5500;
 		luat_thread_start(&thread);