]> granicus.if.org Git - esp-idf/commitdiff
tcpip_adapter/lwip: make dhcp domain name server option configurable
authorLiu Zhi Fu <liuzhifu@espressif.com>
Wed, 7 Jun 2017 13:22:53 +0000 (21:22 +0800)
committerzhangyanjiao <zhangyanjiao@espressif.com>
Thu, 19 Oct 2017 11:28:00 +0000 (19:28 +0800)
Add api to configure dhcp option: domain name server

1.closes https://github.com/espressif/esp-idf/issues/162

2.closes https://github.com/espressif/esp-idf/issues/705

components/lwip/apps/dhcpserver.c
components/lwip/core/dns.c
components/lwip/core/ipv4/dhcp.c
components/lwip/include/lwip/apps/dhcpserver.h
components/lwip/include/lwip/lwip/dns.h
components/lwip/include/lwip/port/lwipopts.h
components/tcpip_adapter/include/tcpip_adapter.h
components/tcpip_adapter/tcpip_adapter_lwip.c

index 910219ddeef645e402293fd86979d23342cb48d2..7062b4456edf79e0c79d4a219a21cc940d8555cd 100644 (file)
@@ -84,6 +84,7 @@ static const u32_t magic_cookie  = 0x63538263;
 static struct udp_pcb *pcb_dhcps = NULL;
 static ip4_addr_t  broadcast_dhcps;
 static ip4_addr_t server_address;
+static ip4_addr_t dns_server = {0};
 static ip4_addr_t client_address;        //added
 static ip4_addr_t client_address_plus;
 
@@ -91,8 +92,9 @@ static list_node *plist = NULL;
 static bool renew = false;
 
 static dhcps_lease_t dhcps_poll;
-static dhcps_offer_t dhcps_offer = 0xFF;
 static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF;  //minute
+static dhcps_offer_t dhcps_offer = 0xFF;
+static dhcps_offer_t dhcps_dns = 0xFF;
 
 /******************************************************************************
  * FunctionName : dhcps_option_info
@@ -127,6 +129,13 @@ void *dhcps_option_info(u8_t op_id, u32_t opt_len)
 
             break;
 
+        case DOMAIN_NAME_SERVER:
+            if (opt_len == sizeof(dhcps_offer_t)) {
+                option_arg = &dhcps_dns;
+            }
+
+            break;
+
         default:
             break;
     }
@@ -134,6 +143,53 @@ void *dhcps_option_info(u8_t op_id, u32_t opt_len)
     return option_arg;
 }
 
+/******************************************************************************
+ * FunctionName : dhcps_set_option_info
+ * Description  : set the DHCP message option info
+ * Parameters   : op_id -- DHCP message option id
+ *                opt_info -- DHCP message option info
+ *                opt_len -- DHCP message option length
+ * Returns      : none
+*******************************************************************************/
+void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len)
+{
+    if (opt_info == NULL) {
+        return;
+    }
+    switch (op_id) {
+        case IP_ADDRESS_LEASE_TIME:
+            if (opt_len == sizeof(dhcps_time_t)) {
+                dhcps_lease_time = *(dhcps_time_t *)opt_info;
+            }
+
+            break;
+
+        case REQUESTED_IP_ADDRESS:
+            if (opt_len == sizeof(dhcps_lease_t)) {
+                dhcps_poll = *(dhcps_lease_t *)opt_info;
+            }
+
+            break;
+
+        case ROUTER_SOLICITATION_ADDRESS:
+            if (opt_len == sizeof(dhcps_offer_t)) {
+                dhcps_offer = *(dhcps_offer_t *)opt_info;
+            }
+
+            break;
+
+        case DOMAIN_NAME_SERVER:
+            if (opt_len == sizeof(dhcps_offer_t)) {
+                dhcps_dns = *(dhcps_offer_t *)opt_info;
+            }
+            break;
+
+        default:
+            break;
+    }
+    return;
+}
+
 /******************************************************************************
  * FunctionName : node_insert_to_list
  * Description  : insert the node to the list
@@ -284,14 +340,19 @@ static u8_t *add_offer_options(u8_t *optptr)
         }
     }
 
-#ifdef USE_DNS
     *optptr++ = DHCP_OPTION_DNS_SERVER;
     *optptr++ = 4;
-    *optptr++ = ip4_addr1(&ipadd);
-    *optptr++ = ip4_addr2(&ipadd);
-    *optptr++ = ip4_addr3(&ipadd);
-    *optptr++ = ip4_addr4(&ipadd);
-#endif
+    if (dhcps_dns_enabled(dhcps_dns)) {
+        *optptr++ = ip4_addr1(&dns_server);
+        *optptr++ = ip4_addr2(&dns_server);
+        *optptr++ = ip4_addr3(&dns_server);
+        *optptr++ = ip4_addr4(&dns_server);
+    }else {
+        *optptr++ = ip4_addr1(&ipadd);
+        *optptr++ = ip4_addr2(&ipadd);
+        *optptr++ = ip4_addr3(&ipadd);
+        *optptr++ = ip4_addr4(&ipadd);
+    }
 
 #ifdef CLASS_B_NET
     *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
@@ -1216,5 +1277,33 @@ bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip)
 
     return ret;
 }
+
+/******************************************************************************
+ * FunctionName : dhcps_dns_setserver
+ * Description  : set DNS server address for dhcpserver
+ * Parameters   : dnsserver -- The DNS server address
+ * Returns      : none
+*******************************************************************************/
+void
+dhcps_dns_setserver(const ip_addr_t *dnsserver)
+{
+    if (dnsserver != NULL) {
+        dns_server = *(ip_2_ip4(dnsserver));
+    } else {
+        dns_server = *(ip_2_ip4(IP_ADDR_ANY));
+    } 
+}
+
+/******************************************************************************
+ * FunctionName : dhcps_dns_getserver
+ * Description  : get DNS server address for dhcpserver
+ * Parameters   : none
+ * Returns      : ip4_addr_t
+*******************************************************************************/
+ip4_addr_t 
+dhcps_dns_getserver()
+{
+    return dns_server;
+}
 #endif
 
index 8f0ac5cc81d3b53cbc4cbefcd9dda8fb90d3b45b..4e1641516cad8214c33e73bdeb62cdb1b0f87812 100755 (executable)
@@ -363,18 +363,19 @@ dns_stricmp(const char* str1, const char* str2)
 #endif /* LWIP_DNS_STRICMP */
 
 /**
- * Initialize the resolver: set up the UDP pcb and configure the default server
- * (if DNS_SERVER_ADDRESS is set).
+ * Initialize the resolver: set up the UDP pcb and configure the fallback dns server
+ * (if FALLBACK_DNS_SERVER_ADDRESS is set).
  */
 void
 dns_init(void)
 {
-#ifdef DNS_SERVER_ADDRESS
+#ifdef FALLBACK_DNS_SERVER_ADDRESS
   /* initialize default DNS server address */
   ip_addr_t dnsserver;
-  DNS_SERVER_ADDRESS(&dnsserver);
-  dns_setserver(0, &dnsserver);
-#endif /* DNS_SERVER_ADDRESS */
+  FALLBACK_DNS_SERVER_ADDRESS(&dnsserver);
+  dnsserver.type = IPADDR_TYPE_V4;
+  dns_setserver(DNS_FALLBACK_SERVER_INDEX, &dnsserver);
+#endif /* FALLBACK_DNS_SERVER_ADDRESS */
 
   LWIP_ASSERT("sanity check SIZEOF_DNS_QUERY",
     sizeof(struct dns_query) == SIZEOF_DNS_QUERY);
@@ -423,6 +424,21 @@ dns_setserver(u8_t numdns, const ip_addr_t *dnsserver)
   }
 }
 
+void 
+dns_clear_servers(bool keep_fallback)
+{
+  u8_t numdns = 0; 
+  
+  for (numdns = 0; numdns < DNS_MAX_SERVERS; numdns ++) {
+    if (keep_fallback && numdns == DNS_FALLBACK_SERVER_INDEX) {
+      continue;
+    }
+
+    dns_setserver(numdns, NULL);
+  }
+}
+
+
 /**
  * Obtain one of the currently configured DNS server.
  *
@@ -730,11 +746,6 @@ dns_send(u8_t idx)
               (u16_t)(entry->server_idx), entry->name));
   LWIP_ASSERT("dns server out of array", entry->server_idx < DNS_MAX_SERVERS);
   if (ip_addr_isany_val(dns_servers[entry->server_idx])) {
-    /* DNS server not valid anymore, e.g. PPP netif has been shut down */
-    /* call specified callback function if provided */
-    dns_call_found(idx, NULL);
-    /* flush this entry */
-    entry->state = DNS_STATE_UNUSED;
     return ERR_OK;
   }
 
@@ -992,6 +1003,11 @@ dns_check_entry(u8_t i)
     case DNS_STATE_ASKING:
       if (--entry->tmr == 0) {
         if (++entry->retries == DNS_MAX_RETRIES) {
+          /* skip DNS servers with zero address */
+          while ((entry->server_idx + 1 < DNS_MAX_SERVERS) && ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
+            entry->server_idx++;
+          }
+
           if ((entry->server_idx + 1 < DNS_MAX_SERVERS) && !ip_addr_isany_val(dns_servers[entry->server_idx + 1])) {
             /* change of server */
             entry->server_idx++;
@@ -1417,6 +1433,17 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
   return dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, LWIP_DNS_ADDRTYPE_DEFAULT);
 }
 
+static bool dns_server_is_set (void)
+{
+  int i = 0;
+  for (i = 0;i < DNS_MAX_SERVERS; i++) {
+    if (!ip_addr_isany_val(dns_servers[i])) {
+      return true;
+    }
+  }
+  return false;
+}
+
 /** Like dns_gethostbyname, but returned address type can be controlled:
  * @param dns_addrtype: - LWIP_DNS_ADDRTYPE_IPV4_IPV6: try to resolve IPv4 first, try IPv6 if IPv4 fails only
  *                      - LWIP_DNS_ADDRTYPE_IPV6_IPV4: try to resolve IPv6 first, try IPv4 if IPv6 fails only
@@ -1485,7 +1512,8 @@ dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_call
 #endif /* LWIP_IPV4 && LWIP_IPV6 */
 
   /* prevent calling found callback if no server is set, return error instead */
-  if (ip_addr_isany_val(dns_servers[0])) {
+  
+  if (dns_server_is_set() == false) {
     return ERR_VAL;
   }
 
index 74c9403dc86936d2fd09a35c0200b0119da5f770..2c4a6b3d261820461ccdf12098b651607aa363d0 100755 (executable)
@@ -692,6 +692,9 @@ dhcp_handle_ack(struct netif *netif)
   /* DNS servers */
   for (n = 0; (n < DNS_MAX_SERVERS) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
     ip_addr_t dns_addr;
+    if (n == DNS_FALLBACK_SERVER_INDEX) {
+        continue;
+    }
     ip_addr_set_ip4_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
     dns_setserver(n, &dns_addr);
   }
index a0024ab5f05354fb72368d50b13566411d3cfb8f..943f02a917119299e26fbd5145a36861a2598a88 100644 (file)
@@ -15,8 +15,6 @@
 #define __DHCPS_H__
 
 #include "lwip/ip_addr.h"
-//#include "esp_common.h"
-#define USE_DNS
 
 typedef struct dhcps_state{
         s16_t state;
@@ -46,6 +44,7 @@ typedef struct {
 enum dhcps_offer_option{
        OFFER_START = 0x00,
        OFFER_ROUTER = 0x01,
+       OFFER_DNS = 0x02,
        OFFER_END
 };
 
@@ -63,17 +62,29 @@ typedef u32_t dhcps_time_t;
 typedef u8_t dhcps_offer_t;
 
 typedef struct {
-       dhcps_offer_t dhcps_offer;
-       dhcps_time_t  dhcps_time;
-       dhcps_lease_t dhcps_poll;
+        dhcps_offer_t dhcps_offer;
+        dhcps_offer_t dhcps_dns;
+        dhcps_time_t  dhcps_time;
+        dhcps_lease_t dhcps_poll;
 } dhcps_options_t;
 
-#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0)
+static inline bool dhcps_router_enabled (dhcps_offer_t offer) 
+{
+    return (offer & OFFER_ROUTER) != 0;
+}
+
+static inline bool dhcps_dns_enabled (dhcps_offer_t offer) 
+{
+    return (offer & OFFER_DNS) != 0;
+}
 
 void dhcps_start(struct netif *netif, ip4_addr_t ip);
 void dhcps_stop(struct netif *netif);
 void *dhcps_option_info(u8_t op_id, u32_t opt_len);
+void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len);
 bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip);
+void dhcps_dns_setserver(const ip_addr_t *dnsserver);
+ip4_addr_t dhcps_dns_getserver();
 
 #endif
 
index 5ef12e56c2cf0a1d81ec038c65c37e056bfe44f5..e080280391d5238f359c022418fcc7475a0af63d 100755 (executable)
@@ -96,6 +96,7 @@ typedef void (*dns_found_callback)(const char *name, const ip_addr_t *ipaddr, vo
 void           dns_init(void);
 void           dns_tmr(void);
 void           dns_setserver(u8_t numdns, const ip_addr_t *dnsserver);
+void           dns_clear_servers(bool keep_fallback);
 ip_addr_t      dns_getserver(u8_t numdns);
 err_t          dns_gethostbyname(const char *hostname, ip_addr_t *addr,
                                  dns_found_callback found, void *callback_arg);
index 4b87af9578366ef7cc9618e4c0f46517cb35589d..88f4b1184d8492866cf3bca9cc42dcd310204d55 100644 (file)
  */
 #define LWIP_DNS                        1
 
+#define DNS_MAX_SERVERS                 3
+#define DNS_FALLBACK_SERVER_INDEX        (DNS_MAX_SERVERS - 1)
+
 /*
    ---------------------------------
    ---------- UDP options ----------
index 2e6db6b5a71cfce77fc59ac6b71aeaabbf92a201..d7ee00ea0990b8bdeb5956ce6cd05a8adf9a6682 100644 (file)
@@ -113,6 +113,19 @@ typedef enum {
     TCPIP_ADAPTER_IF_MAX
 } tcpip_adapter_if_t;
 
+/*type of DNS server*/
+typedef enum {
+    TCPIP_ADAPTER_DNS_MAIN= 0,       /**DNS main server address*/
+    TCPIP_ADAPTER_DNS_BACKUP,        /**DNS backup server address,for STA only,support soft-AP in future*/
+    TCPIP_ADAPTER_DNS_FALLBACK,      /**DNS fallback server address,for STA only*/
+    TCPIP_ADAPTER_DNS_MAX            /**Max DNS */
+} tcpip_adapter_dns_type_t;
+
+/*info of DNS server*/
+typedef struct {
+    ip_addr_t ip;
+} tcpip_adapter_dns_info_t;
+
 /* status of DHCP client or DHCP server */
 typedef enum {
     TCPIP_ADAPTER_DHCP_INIT = 0,    /**< DHCP client/server in initial state */
@@ -130,6 +143,7 @@ typedef enum{
 } tcpip_adapter_option_mode_t;
 
 typedef enum{
+    TCPIP_ADAPTER_DOMAIN_NAME_SERVER            = 6,    /**< domain name server */
     TCPIP_ADAPTER_ROUTER_SOLICITATION_ADDRESS   = 32,   /**< solicitation router address */
     TCPIP_ADAPTER_REQUESTED_IP_ADDRESS          = 50,   /**< request IP address pool */
     TCPIP_ADAPTER_IP_ADDRESS_LEASE_TIME         = 51,   /**< request IP address lease time */
@@ -145,14 +159,19 @@ typedef struct tcpip_adapter_api_msg_s {
     tcpip_adapter_if_t tcpip_if;
     tcpip_adapter_ip_info_t *ip_info;
     uint8_t *mac;
-    const char *hostname;
+    void    *data;
 } tcpip_adapter_api_msg_t;
 
+typedef struct tcpip_adapter_dns_param_s {
+    tcpip_adapter_dns_type_t dns_type;
+    tcpip_adapter_dns_info_t *dns_info;
+} tcpip_adapter_dns_param_t;
+
 #define TCPIP_ADAPTER_TRHEAD_SAFE 1
 #define TCPIP_ADAPTER_IPC_LOCAL   0 
 #define TCPIP_ADAPTER_IPC_REMOTE  1
 
-#define TCPIP_ADAPTER_IPC_CALL(_if, _mac, _ip, _hostname, _fn) do {\
+#define TCPIP_ADAPTER_IPC_CALL(_if, _mac, _ip, _data, _fn) do {\
     tcpip_adapter_api_msg_t msg;\
     if (tcpip_inited == false) {\
         ESP_LOGE(TAG, "tcpip_adapter is not initialized!");\
@@ -160,9 +179,9 @@ typedef struct tcpip_adapter_api_msg_s {
     }\
     memset(&msg, 0, sizeof(msg));\
     msg.tcpip_if = (_if);\
-    msg.mac      = (_mac);\
-    msg.ip_info  = (_ip);\
-    msg.hostname = (_hostname);\
+    msg.mac      = (uint8_t*)(_mac);\
+    msg.ip_info  = (tcpip_adapter_ip_info_t*)(_ip);\
+    msg.data     = (void*)(_data);\
     msg.api_fn   = (_fn);\
     if (TCPIP_ADAPTER_IPC_REMOTE == tcpip_adapter_ipc_check(&msg)) {\
         ESP_LOGD(TAG, "check: remote, if=%d fn=%p\n", (_if), (_fn));\
@@ -292,6 +311,47 @@ esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i
  */
 esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
 
+/**
+ * @brief  Set DNS Server's information
+ *
+ * There has an DNS Server information copy in adapter library, set DNS Server for appointed interface and type.
+ *
+ * 1.In station mode, if dhcp client is enabled, then only the fallback DNS server can be set(TCPIP_ADAPTER_DNS_FALLBACK).
+ *   Fallback DNS server is only used if no DNS servers are set via DHCP.
+ *   If dhcp client is disabled, then need to set main/backup dns server(TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP).
+ * 
+ * 2.In soft-AP mode, the DNS Server's main dns server offered to the station is the IP address of soft-AP, 
+ *   if the application don't want to use the IP address of soft-AP, they can set the main dns server.
+ *
+ * This function is mainly used for setting static or Fallback DNS Server.
+ *
+ * @param[in]  tcpip_if: the interface which we want to set DNS Server information
+ * @param[in]  type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK
+ * @param[in]  dns:  the DNS Server address to be set
+ * 
+ * @return 
+ *      - ESP_OK on success
+ *      - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params
+ */
+esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns);
+
+/**
+ * @brief  Get DNS Server's information
+ *
+ * When set the DNS Server information successfully, can get the DNS Server's information via the appointed tcpip_if and type 
+ *
+ * This function is mainly used for getting DNS Server information.
+ *
+ * @param[in]  tcpip_if: the interface which we want to get DNS Server information
+ * @param[in]  type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK
+ * @param[in]  dns:  the DNS Server address to be get
+ * 
+ * @return 
+ *      - ESP_OK on success
+ *      - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params
+ */
+esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns);
+
 /**
  * @brief  Get interface's old IP information
  *
index 394ad69c9c71dc23304e23086b88f3b4b49bd8e7..267ae681b31cf73b33be398a1f5caaee69ae90b5 100644 (file)
@@ -52,6 +52,8 @@ static esp_err_t tcpip_adapter_stop_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_up_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_down_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_set_ip_info_api(tcpip_adapter_api_msg_t * msg);
+static esp_err_t tcpip_adapter_set_dns_info_api(tcpip_adapter_api_msg_t * msg);
+static esp_err_t tcpip_adapter_get_dns_info_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_create_ip6_linklocal_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_dhcps_start_api(tcpip_adapter_api_msg_t * msg);
 static esp_err_t tcpip_adapter_dhcps_stop_api(tcpip_adapter_api_msg_t * msg);
@@ -65,7 +67,6 @@ static sys_sem_t api_sync_sem = NULL;
 static bool tcpip_inited = false;
 static sys_sem_t api_lock_sem = NULL;
 extern sys_thread_t g_lwip_task;
-
 #define TAG "tcpip_adapter"
 
 static void tcpip_adapter_api_cb(void* api_msg)
@@ -395,10 +396,7 @@ esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_i
             return ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED;
         }
 #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-        u8_t numdns = 0;
-        for (numdns = 0; numdns < DNS_MAX_SERVERS; numdns ++) {
-            dns_setserver(numdns, NULL);
-        }
+        dns_clear_servers(true);
 #endif
     }
 
@@ -567,7 +565,19 @@ esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_option_mode_t opt_op, tcpip_a
             break;
         }
         case ROUTER_SOLICITATION_ADDRESS: {
-            *(uint8_t *)opt_val = (*(uint8_t *)opt_info) & OFFER_ROUTER;
+            if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
+                *(uint8_t *)opt_val = 1;
+            } else {
+                *(uint8_t *)opt_val = 0;
+            }
+            break;
+        }
+        case DOMAIN_NAME_SERVER: {
+            if ((*(uint8_t *)opt_info) & OFFER_DNS) {
+                *(uint8_t *)opt_val = 1;
+            } else {
+                *(uint8_t *)opt_val = 0;
+            }
             break;
         }
         default:
@@ -622,19 +632,125 @@ esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_option_mode_t opt_op, tcpip_a
             break;
         }
         case ROUTER_SOLICITATION_ADDRESS: {
-            *(uint8_t *)opt_info = (*(uint8_t *)opt_val) & OFFER_ROUTER;
+            if (*(uint8_t *)opt_val) {
+                *(uint8_t *)opt_info |= OFFER_ROUTER;
+            } else {
+                *(uint8_t *)opt_info &= ((~OFFER_ROUTER)&0xFF);
+            }
+            break;
+        }
+        case DOMAIN_NAME_SERVER: {
+            if (*(uint8_t *)opt_val) {
+                *(uint8_t *)opt_info |= OFFER_DNS;
+            } else {
+                *(uint8_t *)opt_info &= ((~OFFER_DNS)&0xFF);
+            }
             break;
         }
+       
         default:
             break;
         }
+        dhcps_set_option_info(opt_id, opt_info,opt_len);
+    } else {
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns)
+{
+    tcpip_adapter_dns_param_t dns_param;
+
+    dns_param.dns_type =  type;
+    dns_param.dns_info =  dns;
+
+    TCPIP_ADAPTER_IPC_CALL(tcpip_if, type,  0, &dns_param, tcpip_adapter_set_dns_info_api);
+
+    if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) {
+        ESP_LOGD(TAG, "set dns invalid if=%d", tcpip_if);
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+    if (!dns) {
+        ESP_LOGD(TAG, "set dns null dns");
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+
+    if (type >= TCPIP_ADAPTER_DNS_MAX) {
+        ESP_LOGD(TAG, "set dns invalid type=%d", type);
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+    
+    if (ip4_addr_isany_val(dns->ip.u_addr.ip4)) {
+        ESP_LOGD(TAG, "set dns invalid dns");
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+
+    ESP_LOGD(TAG, "set dns if=%d type=%d dns=%x", tcpip_if, type, dns->ip.u_addr.ip4.addr);
+    dns->ip.type = IPADDR_TYPE_V4;
+
+    if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) {
+        dns_setserver(type, &(dns->ip));
     } else {
+        if (type != TCPIP_ADAPTER_DNS_MAIN) {
+            ESP_LOGD(TAG, "set dns invalid type");
+            return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+        } else {
+            dhcps_dns_setserver(&(dns->ip));
+        }
+    }
+
+    return ESP_OK;
+}
+
+static esp_err_t tcpip_adapter_set_dns_info_api(tcpip_adapter_api_msg_t * msg)
+{
+    tcpip_adapter_dns_param_t *dns_param = (tcpip_adapter_dns_param_t*)msg->data;
+
+    return tcpip_adapter_set_dns_info(msg->tcpip_if, dns_param->dns_type, dns_param->dns_info);
+}
+
+esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns)
+{ 
+    tcpip_adapter_dns_param_t dns_param;
+
+    dns_param.dns_type =  type;
+    dns_param.dns_info =  dns;
+    
+    TCPIP_ADAPTER_IPC_CALL(tcpip_if, type,  0, &dns_param, tcpip_adapter_get_dns_info_api);
+    if (!dns) {
+        ESP_LOGD(TAG, "get dns null dns");
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+
+    if (type >= TCPIP_ADAPTER_DNS_MAX) {
+        ESP_LOGD(TAG, "get dns invalid type=%d", type);
         return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
     }
+    
+    if (tcpip_if >= TCPIP_ADAPTER_IF_MAX) {
+        ESP_LOGD(TAG, "get dns invalid tcpip_if=%d",tcpip_if);
+        return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
+    }
+
+    if (tcpip_if == TCPIP_ADAPTER_IF_STA || tcpip_if == TCPIP_ADAPTER_IF_ETH) {
+        dns->ip = dns_getserver(type);
+    } else {
+        dns->ip.u_addr.ip4 = dhcps_dns_getserver();
+    }
 
     return ESP_OK;
 }
 
+static esp_err_t tcpip_adapter_get_dns_info_api(tcpip_adapter_api_msg_t * msg)
+{
+    tcpip_adapter_dns_param_t *dns_param = (tcpip_adapter_dns_param_t*)msg->data;
+
+    return tcpip_adapter_get_dns_info(msg->tcpip_if, dns_param->dns_type, dns_param->dns_info);
+}
+
 esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status)
 {
     *status = dhcps_status;
@@ -858,6 +974,9 @@ esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if)
         struct netif *p_netif = esp_netif[tcpip_if];
 
         tcpip_adapter_reset_ip_info(tcpip_if);
+#if LWIP_DNS
+        dns_clear_servers(true);
+#endif
 
         if (p_netif != NULL) {
             if (netif_is_up(p_netif)) {
@@ -1023,7 +1142,9 @@ esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *ho
 
 static esp_err_t tcpip_adapter_set_hostname_api(tcpip_adapter_api_msg_t * msg)
 {
-    return tcpip_adapter_set_hostname(msg->tcpip_if, msg->hostname);
+    const char *hostname = (char*) msg->data;
+
+    return tcpip_adapter_set_hostname(msg->tcpip_if, hostname);
 }
 
 esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname)