From 380e87ddfac09c59fddb48a300227c1f4ffe6ee0 Mon Sep 17 00:00:00 2001
From: Alexander Alashkin <alexander.alashkin@cesanta.com>
Date: Mon, 20 Mar 2017 09:43:05 +0000
Subject: [PATCH] Honor DNS server from DHCP

PUBLISHED_FROM=10772301ef115c31ada3521ff4235c33a421b782
---
 docs/c-api/net.h/struct_mg_connect_opts.md    |  1 +
 docs/c-api/net.h/struct_mg_mgr.md             |  1 +
 docs/c-api/net.h/struct_mg_mgr_init_opts.md   |  1 +
 docs/c-api/resolv.h/intro.md                  |  1 +
 docs/c-api/resolv.h/mg_set_nameserver.md      | 10 ++++
 .../resolv.h/struct_mg_resolve_async_opts.md  |  2 +-
 mongoose.c                                    | 48 ++++++++++++-------
 mongoose.h                                    |  8 +++-
 8 files changed, 54 insertions(+), 18 deletions(-)
 create mode 100644 docs/c-api/resolv.h/mg_set_nameserver.md

diff --git a/docs/c-api/net.h/struct_mg_connect_opts.md b/docs/c-api/net.h/struct_mg_connect_opts.md
index f4ef502d7..f05bf25f4 100644
--- a/docs/c-api/net.h/struct_mg_connect_opts.md
+++ b/docs/c-api/net.h/struct_mg_connect_opts.md
@@ -8,6 +8,7 @@ signature: |
     unsigned int flags;        /* Extra connection flags */
     const char **error_string; /* Placeholder for the error string */
     struct mg_iface *iface;    /* Interface instance */
+    const char *nameserver;    /* DNS server to use, NULL for default */
   #if MG_ENABLE_SSL
     /*
      * SSL settings.
diff --git a/docs/c-api/net.h/struct_mg_mgr.md b/docs/c-api/net.h/struct_mg_mgr.md
index dcc2b523d..63d946339 100644
--- a/docs/c-api/net.h/struct_mg_mgr.md
+++ b/docs/c-api/net.h/struct_mg_mgr.md
@@ -17,6 +17,7 @@ signature: |
   #if MG_ENABLE_JAVASCRIPT
     struct v7 *v7;
   #endif
+    const char *nameserver; /* DNS server to use */
   };
 ---
 
diff --git a/docs/c-api/net.h/struct_mg_mgr_init_opts.md b/docs/c-api/net.h/struct_mg_mgr_init_opts.md
index c0b658166..7db23de5b 100644
--- a/docs/c-api/net.h/struct_mg_mgr_init_opts.md
+++ b/docs/c-api/net.h/struct_mg_mgr_init_opts.md
@@ -7,6 +7,7 @@ signature: |
     const struct mg_iface_vtable *main_iface;
     int num_ifaces;
     const struct mg_iface_vtable **ifaces;
+    const char *nameserver;
   };
 ---
 
diff --git a/docs/c-api/resolv.h/intro.md b/docs/c-api/resolv.h/intro.md
index 3fc5fc069..f77184f9e 100644
--- a/docs/c-api/resolv.h/intro.md
+++ b/docs/c-api/resolv.h/intro.md
@@ -6,6 +6,7 @@ items:
   - { name: mg_resolve_async.md }
   - { name: mg_resolve_async_opt.md }
   - { name: mg_resolve_from_hosts_file.md }
+  - { name: mg_set_nameserver.md }
   - { name: struct_mg_resolve_async_opts.md }
 ---
 
diff --git a/docs/c-api/resolv.h/mg_set_nameserver.md b/docs/c-api/resolv.h/mg_set_nameserver.md
new file mode 100644
index 000000000..2e33c629c
--- /dev/null
+++ b/docs/c-api/resolv.h/mg_set_nameserver.md
@@ -0,0 +1,10 @@
+---
+title: "mg_set_nameserver()"
+decl_name: "mg_set_nameserver"
+symbol_kind: "func"
+signature: |
+  void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver);
+---
+
+Set default DNS server 
+
diff --git a/docs/c-api/resolv.h/struct_mg_resolve_async_opts.md b/docs/c-api/resolv.h/struct_mg_resolve_async_opts.md
index 6c39e2f1a..8a836b9a0 100644
--- a/docs/c-api/resolv.h/struct_mg_resolve_async_opts.md
+++ b/docs/c-api/resolv.h/struct_mg_resolve_async_opts.md
@@ -4,7 +4,7 @@ decl_name: "struct mg_resolve_async_opts"
 symbol_kind: "struct"
 signature: |
   struct mg_resolve_async_opts {
-    const char *nameserver_url;
+    const char *nameserver;
     int max_retries;    /* defaults to 2 if zero */
     int timeout;        /* in seconds; defaults to 5 if zero */
     int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
diff --git a/mongoose.c b/mongoose.c
index 3db5e8134..4780bdda1 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -2173,6 +2173,9 @@ void mg_mgr_init_opt(struct mg_mgr *m, void *user_data,
       m->ifaces[i]->vtable->init(m->ifaces[i]);
     }
   }
+  if (opts.nameserver != NULL) {
+    m->nameserver = strdup(opts.nameserver);
+  }
   DBG(("=================================="));
   DBG(("init mgr=%p", m));
 }
@@ -2230,6 +2233,8 @@ void mg_mgr_free(struct mg_mgr *m) {
     }
     MG_FREE(m->ifaces);
   }
+
+  MG_FREE((char *) m->nameserver);
 }
 
 time_t mg_mgr_poll(struct mg_mgr *m, int timeout_ms) {
@@ -2742,6 +2747,7 @@ struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
     struct mg_resolve_async_opts o;
     memset(&o, 0, sizeof(o));
     o.dns_conn = &dns_conn;
+    o.nameserver = opts.nameserver;
     if (mg_resolve_async_opt(nc->mgr, host, MG_DNS_A_RECORD, resolve_cb, nc,
                              o) != 0) {
       MG_SET_PTRPTR(opts.error_string, "cannot schedule DNS lookup");
@@ -10692,10 +10698,6 @@ int mg_dns_reply_record(struct mg_dns_reply *reply,
 #define MG_DEFAULT_NAMESERVER "8.8.8.8"
 #endif
 
-static const char *mg_default_dns_server = "udp://" MG_DEFAULT_NAMESERVER ":53";
-
-MG_INTERNAL char mg_dns_server[256];
-
 struct mg_resolve_async_request {
   char name[1024];
   int query;
@@ -10755,7 +10757,8 @@ static int mg_get_ip_address_of_nameserver(char *name, size_t name_len) {
         if (comma != NULL) {
           *comma = '\0';
         }
-        snprintf(name, name_len, "udp://%S:53", value);
+        /* %S will convert wchar_t -> char */
+        snprintf(name, name_len, "%S", value);
         ret = 0;
         RegCloseKey(hSub);
         break;
@@ -10774,7 +10777,7 @@ static int mg_get_ip_address_of_nameserver(char *name, size_t name_len) {
     for (ret = -1; fgets(line, sizeof(line), fp) != NULL;) {
       unsigned int a, b, c, d;
       if (sscanf(line, "nameserver %u.%u.%u.%u", &a, &b, &c, &d) == 4) {
-        snprintf(name, name_len, "udp://%u.%u.%u.%u:53", a, b, c, d);
+        snprintf(name, name_len, "%u.%u.%u.%u", a, b, c, d);
         ret = 0;
         break;
       }
@@ -10782,7 +10785,7 @@ static int mg_get_ip_address_of_nameserver(char *name, size_t name_len) {
     (void) fclose(fp);
   }
 #else
-  snprintf(name, name_len, "%s", mg_default_dns_server);
+  snprintf(name, name_len, "%s", MG_DEFAULT_NAMESERVER);
 #endif /* _WIN32 */
 
   return ret;
@@ -10910,7 +10913,12 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
                          struct mg_resolve_async_opts opts) {
   struct mg_resolve_async_request *req;
   struct mg_connection *dns_nc;
-  const char *nameserver = opts.nameserver_url;
+  const char *nameserver = opts.nameserver;
+  char dns_server_buff[17], nameserver_url[26];
+
+  if (nameserver == NULL) {
+    nameserver = mgr->nameserver;
+  }
 
   DBG(("%s %d %p", name, query, opts.dns_conn));
 
@@ -10929,17 +10937,18 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
   req->timeout = opts.timeout ? opts.timeout : 5;
 
   /* Lazily initialize dns server */
-  if (nameserver == NULL && mg_dns_server[0] == '\0' &&
-      mg_get_ip_address_of_nameserver(mg_dns_server, sizeof(mg_dns_server)) ==
-          -1) {
-    strncpy(mg_dns_server, mg_default_dns_server, sizeof(mg_dns_server));
-  }
-
   if (nameserver == NULL) {
-    nameserver = mg_dns_server;
+    if (mg_get_ip_address_of_nameserver(dns_server_buff,
+                                        sizeof(dns_server_buff)) != -1) {
+      nameserver = dns_server_buff;
+    } else {
+      nameserver = MG_DEFAULT_NAMESERVER;
+    }
   }
 
-  dns_nc = mg_connect(mgr, nameserver, MG_CB(mg_resolve_async_eh, NULL));
+  snprintf(nameserver_url, sizeof(nameserver_url), "udp://%s:53", nameserver);
+
+  dns_nc = mg_connect(mgr, nameserver_url, MG_CB(mg_resolve_async_eh, NULL));
   if (dns_nc == NULL) {
     free(req);
     return -1;
@@ -10952,6 +10961,13 @@ int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
   return 0;
 }
 
+void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver) {
+  free((char *) mgr->nameserver);
+  if (nameserver != NULL) {
+    mgr->nameserver = strdup(nameserver);
+  }
+}
+
 #endif /* MG_ENABLE_ASYNC_RESOLVER */
 #ifdef MG_MODULE_LINES
 #line 1 "mongoose/src/coap.c"
diff --git a/mongoose.h b/mongoose.h
index 6fdf3bb16..6b37f4180 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -3274,6 +3274,7 @@ struct mg_mgr {
 #if MG_ENABLE_JAVASCRIPT
   struct v7 *v7;
 #endif
+  const char *nameserver; /* DNS server to use */
 };
 
 /*
@@ -3368,6 +3369,7 @@ struct mg_mgr_init_opts {
   const struct mg_iface_vtable *main_iface;
   int num_ifaces;
   const struct mg_iface_vtable **ifaces;
+  const char *nameserver;
 };
 
 /*
@@ -3538,6 +3540,7 @@ struct mg_connect_opts {
   unsigned int flags;        /* Extra connection flags */
   const char **error_string; /* Placeholder for the error string */
   struct mg_iface *iface;    /* Interface instance */
+  const char *nameserver;    /* DNS server to use, NULL for default */
 #if MG_ENABLE_SSL
   /*
    * SSL settings.
@@ -5609,7 +5612,7 @@ typedef void (*mg_resolve_callback_t)(struct mg_dns_message *dns_message,
 
 /* Options for `mg_resolve_async_opt`. */
 struct mg_resolve_async_opts {
-  const char *nameserver_url;
+  const char *nameserver;
   int max_retries;    /* defaults to 2 if zero */
   int timeout;        /* in seconds; defaults to 5 if zero */
   int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
@@ -5621,6 +5624,9 @@ struct mg_resolve_async_opts {
 int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
                      mg_resolve_callback_t cb, void *data);
 
+/* Set default DNS server */
+void mg_set_nameserver(struct mg_mgr *mgr, const char *nameserver);
+
 /*
  * Resolved a DNS name asynchronously.
  *
-- 
GitLab