From 393063428e1f3043217f4a3db6035e3e7b8df52f Mon Sep 17 00:00:00 2001 From: "Sergio R. Caprile" Date: Fri, 11 Jul 2025 10:42:54 -0300 Subject: [PATCH] Built-in TCP/IP (re-)starts DNS connection on link up --- mongoose.c | 50 +++++++++++++++++++++++-------- mongoose.h | 1 + src/dns.c | 26 +++++++++------- src/net_builtin.c | 22 +++++++++++++- src/net_builtin.h | 1 + tutorials/tcpip/tap-driver/main.c | 12 ++++---- 6 files changed, 81 insertions(+), 31 deletions(-) diff --git a/mongoose.c b/mongoose.c index 6e4eb3bb3a..98e33bf9b9 100644 --- a/mongoose.c +++ b/mongoose.c @@ -353,19 +353,24 @@ static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name, return mg_send(c, &pkt, sizeof(pkt.header) + n); } -static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, - struct mg_dns *dnsc, bool ipv6) { - struct dns_data *d = NULL; +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc); +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc) { if (dnsc->url == NULL) { - mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()"); - } else if (dnsc->c == NULL) { - dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL); - if (dnsc->c != NULL) { - dnsc->c->pfn = dns_cb; - // dnsc->c->is_hexdumping = 1; - } + mg_error(0, "DNS server URL is NULL. Call mg_mgr_init()"); + return false; } if (dnsc->c == NULL) { + dnsc->c = mg_connect(mgr, dnsc->url, NULL, NULL); + if (dnsc->c == NULL) return false; + dnsc->c->pfn = dns_cb; + } + return true; +} + +static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, + struct mg_dns *dnsc, bool ipv6) { + struct dns_data *d = NULL; + if (!mg_dnsc_init(c->mgr, dnsc)) { mg_error(c, "resolver"); } else if ((d = (struct dns_data *) mg_calloc(1, sizeof(*d))) == NULL) { mg_error(c, "resolve OOM"); @@ -467,6 +472,7 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) { return c; } + #ifdef MG_ENABLE_LINES #line 1 "src/event.c" #endif @@ -4577,6 +4583,8 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } } +static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip); + static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0; uint8_t msgtype = 0, state = ifp->state; @@ -4625,8 +4633,10 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->state = MG_TCPIP_STATE_IP; // BOUND state mg_random(&rand, sizeof(rand)); srand((unsigned int) (rand + mg_millis())); - if (ifp->enable_req_dns && dns != 0) + if (ifp->enable_req_dns && dns != 0) { + setdns4(ifp, &dns); mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns); + } if (ifp->enable_req_sntp && sntp != 0) mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp); } else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew @@ -5287,6 +5297,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { void mg_tcpip_free(struct mg_tcpip_if *ifp) { mg_free(ifp->recv_queue.buf); mg_free(ifp->tx.buf); + mg_free(ifp->dns4_url); } static void send_syn(struct mg_connection *c) { @@ -5453,6 +5464,21 @@ void mg_multicast_add(struct mg_connection *c, char *ip) { c->mgr->ifp->update_mac_hash_table = true; // mark dirty } +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc); + +static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip) { + struct mg_dns *dnsc; + mg_free(ifp->dns4_url); + ifp->dns4_url = mg_mprintf("udp://%M:53", mg_print_ip4, ip); + dnsc = &ifp->mgr->dns4; + dnsc->url = (const char *) ifp->dns4_url; + MG_DEBUG(("Set DNS URL to %s", dnsc->url)); + if (ifp->mgr->use_dns6) return; + if (dnsc->c != NULL) mg_close_conn(dnsc->c); + if (!mg_dnsc_init(ifp->mgr, dnsc)) // create DNS connection + MG_ERROR(("DNS connection creation failed")); +} + #endif // MG_ENABLE_TCPIP #ifdef MG_ENABLE_LINES @@ -8600,10 +8626,8 @@ int64_t mg_sntp_parse(const unsigned char *buf, size_t len) { static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) { uint64_t *expiration_time = (uint64_t *) c->data; if (ev == MG_EV_OPEN) { - MG_INFO(("%lu PFN OPEN", c->id)); *expiration_time = mg_millis() + 3000; // Store expiration time in 3s } else if (ev == MG_EV_CONNECT) { - MG_INFO(("%lu PFN CONNECT, sending request", c->id)); mg_sntp_request(c); } else if (ev == MG_EV_READ) { int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len); diff --git a/mongoose.h b/mongoose.h index bf838f8915..d190c84f32 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3003,6 +3003,7 @@ struct mg_tcpip_if { // Internal state, user can use it but should not change it uint8_t gwmac[6]; // Router's MAC + char *dns4_url; // DNS server URL uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state uint64_t lease_expire; // Lease expiration time, in ms diff --git a/src/dns.c b/src/dns.c index 59541f89a7..20ab8984ae 100644 --- a/src/dns.c +++ b/src/dns.c @@ -232,19 +232,24 @@ static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name, return mg_send(c, &pkt, sizeof(pkt.header) + n); } -static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, - struct mg_dns *dnsc, bool ipv6) { - struct dns_data *d = NULL; +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc); +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc) { if (dnsc->url == NULL) { - mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()"); - } else if (dnsc->c == NULL) { - dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL); - if (dnsc->c != NULL) { - dnsc->c->pfn = dns_cb; - // dnsc->c->is_hexdumping = 1; - } + mg_error(0, "DNS server URL is NULL. Call mg_mgr_init()"); + return false; } if (dnsc->c == NULL) { + dnsc->c = mg_connect(mgr, dnsc->url, NULL, NULL); + if (dnsc->c == NULL) return false; + dnsc->c->pfn = dns_cb; + } + return true; +} + +static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms, + struct mg_dns *dnsc, bool ipv6) { + struct dns_data *d = NULL; + if (!mg_dnsc_init(c->mgr, dnsc)) { mg_error(c, "resolver"); } else if ((d = (struct dns_data *) mg_calloc(1, sizeof(*d))) == NULL) { mg_error(c, "resolve OOM"); @@ -345,3 +350,4 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) { if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251"); return c; } + diff --git a/src/net_builtin.c b/src/net_builtin.c index a9e54f8d11..0790fe8d4e 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -407,6 +407,8 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } } +static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip); + static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0; uint8_t msgtype = 0, state = ifp->state; @@ -455,8 +457,10 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->state = MG_TCPIP_STATE_IP; // BOUND state mg_random(&rand, sizeof(rand)); srand((unsigned int) (rand + mg_millis())); - if (ifp->enable_req_dns && dns != 0) + if (ifp->enable_req_dns && dns != 0) { + setdns4(ifp, &dns); mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns); + } if (ifp->enable_req_sntp && sntp != 0) mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp); } else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew @@ -1117,6 +1121,7 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { void mg_tcpip_free(struct mg_tcpip_if *ifp) { mg_free(ifp->recv_queue.buf); mg_free(ifp->tx.buf); + mg_free(ifp->dns4_url); } static void send_syn(struct mg_connection *c) { @@ -1283,4 +1288,19 @@ void mg_multicast_add(struct mg_connection *c, char *ip) { c->mgr->ifp->update_mac_hash_table = true; // mark dirty } +bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc); + +static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip) { + struct mg_dns *dnsc; + mg_free(ifp->dns4_url); + ifp->dns4_url = mg_mprintf("udp://%M:53", mg_print_ip4, ip); + dnsc = &ifp->mgr->dns4; + dnsc->url = (const char *) ifp->dns4_url; + MG_DEBUG(("Set DNS URL to %s", dnsc->url)); + if (ifp->mgr->use_dns6) return; + if (dnsc->c != NULL) mg_close_conn(dnsc->c); + if (!mg_dnsc_init(ifp->mgr, dnsc)) // create DNS connection + MG_ERROR(("DNS connection creation failed")); +} + #endif // MG_ENABLE_TCPIP diff --git a/src/net_builtin.h b/src/net_builtin.h index c14d02d8e3..c4316d21ca 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -57,6 +57,7 @@ struct mg_tcpip_if { // Internal state, user can use it but should not change it uint8_t gwmac[6]; // Router's MAC + char *dns4_url; // DNS server URL uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state uint64_t lease_expire; // Lease expiration time, in ms diff --git a/tutorials/tcpip/tap-driver/main.c b/tutorials/tcpip/tap-driver/main.c index 79e47bbbe5..f297466fca 100644 --- a/tutorials/tcpip/tap-driver/main.c +++ b/tutorials/tcpip/tap-driver/main.c @@ -42,21 +42,20 @@ static size_t tap_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) { return (size_t) received; } -char *s_dns = NULL, *s_sntp = NULL; +char *s_sntp = NULL; static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) { if (ev == MG_TCPIP_EV_ST_CHG) { MG_INFO(("State change: %u", *(uint8_t *) ev_data)); } else if (ev == MG_TCPIP_EV_DHCP_DNS) { - mg_free(s_dns); - s_dns = mg_mprintf("udp://%M:53", mg_print_ip4, (uint32_t *) ev_data); - ifp->mgr->dns4.url = s_dns; - MG_INFO(("Set DNS to %s", ifp->mgr->dns4.url)); + MG_INFO(("Got DNS from DHCP: %M", mg_print_ip4, (uint32_t *) ev_data)); } else if (ev == MG_TCPIP_EV_DHCP_SNTP) { + MG_INFO(("Got SNTP from DHCP: %M", mg_print_ip4, (uint32_t *) ev_data)); mg_free(s_sntp); s_sntp = mg_mprintf("udp://%M:123", mg_print_ip4, (uint32_t *) ev_data); - MG_INFO(("Set SNTP to %s", s_sntp)); + MG_INFO(("Set SNTP server to %s", s_sntp)); // though net.c may not use it. } + (void) ifp; } int main(int argc, char *argv[]) { @@ -128,7 +127,6 @@ int main(int argc, char *argv[]) { web_init(&mgr); while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop - mg_free(s_dns); mg_free(s_sntp); mg_mgr_free(&mgr); close(fd);