Merge pull request #3561 from cesanta/ipchanges

close TCP connections on DHCP/SLAAC IP address changes
This commit is contained in:
Sergey Lyubka authored and GitHub committed 2026-06-03 09:01:25 +01:00
commit b463ac0edd
4 files changed
+40 -2

No files matched your search

+18 -1
View File
@@ -7702,6 +7702,13 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO((" MAC: %M", mg_print_mac, ifp->mac));
if (ifp->l2type == MG_TCPIP_L2_ETH)
mg_tcpip_arp_request(ifp, ifp->ip, ifp->mac); // gratuitous ARP annc
if (ifp->is_ip_changed) {
struct mg_connection *c;
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if (!c->is_listening && !c->is_udp) c->is_closing = 1;
}
ifp->is_ip_changed = false;
}
} else if (ifp->state == MG_TCPIP_STATE_IP) {
if (ifp->gw != 0 && ifp->l2type == MG_TCPIP_L2_ETH)
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
@@ -8011,6 +8018,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// assume DHCP server = router until ARP resolves
memcpy(ifp->gwmac, mg_l2_getaddr(ifp, pkt->l2), sizeof(ifp->gwmac));
ifp->gw_ready = true; // NOTE(): actual gw ARP won't retry now
if (ifp->ip != ip) ifp->is_ip_changed = true;
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
ifp->state = MG_TCPIP_STATE_IP; // BOUND state
mg_random(&rand, sizeof(rand));
@@ -8266,7 +8274,7 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
struct ndp_ra *ra = (struct ndp_ra *) (pkt->icmp6 + 1);
uint8_t *opts = (uint8_t *) (ra + 1);
size_t opt_left = pkt->pay.len - 12;
bool gotl2addr = false, gotprefix = false;
bool gotl2addr = false, gotprefix = false, changed = false;
uint8_t l2[sizeof(struct mg_l2addr)];
uint32_t mtu = 0;
uint8_t *prefix, prefix_len;
@@ -8299,6 +8307,8 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
(void) pref_lifetime;
gotprefix = true;
if (prefix_len != ifp->prefix || !match_prefix(prefix, ifp->prefix, ifp->prefix_len))
changed = true;
}
opts += length;
opt_left -= length;
@@ -8306,6 +8316,7 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// fill prefix and global
if (gotprefix && !fill_global(ifp, prefix, prefix_len)) return;
if (changed) ifp->is_ip6_changed = true;
ifp->gw6[0] = pkt->ip6->src[0], ifp->gw6[1] = pkt->ip6->src[1];
if (gotl2addr) memcpy(ifp->gw6mac, l2, sizeof(ifp->gw6mac));
if (gotl2addr || ifp->l2type == MG_TCPIP_L2_PPP || ifp->l2type == MG_TCPIP_L2_PPPoE) {
@@ -8384,6 +8395,12 @@ static void onstate6change(struct mg_tcpip_if *ifp) {
(struct mg_addr *) &ip6_allrouters),
ifp->ip6, (uint64_t *) ip6_allrouters.addr.ip6, false,
ifp->mac);
if (ifp->is_ip6_changed) {
struct mg_connection *c;
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if (!c->is_listening && !c->is_udp) c->is_closing = 1;
}
ifp->is_ip6_changed = false;
}
} else if (ifp->state6 == MG_TCPIP_STATE_IP) {
if ((ifp->gw6[0] != 0 || ifp->gw6[1] != 0) && (ifp->l2type != MG_TCPIP_L2_PPP && ifp->l2type != MG_TCPIP_L2_PPPoE))
+2
View File
@@ -3644,6 +3644,7 @@ struct mg_tcpip_if {
bool enable_fcs_check; // Do a FCS check on RX frames and strip it
bool enable_mac_check; // Do a hw addr check on RX frames
bool update_mac_hash_table; // Signal drivers to update MAC controller
bool is_ip_changed; // IP address changed, close/restart conns
struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data
mg_tcpip_event_handler_t pfn; // Driver-specific event handler function
@@ -3660,6 +3661,7 @@ struct mg_tcpip_if {
uint64_t gw6[2]; // default gateway.
bool enable_slaac; // Enable IPv6 address autoconfiguration
bool enable_dhcp6_client; // Enable DCHPv6 client TODO()
bool is_ip6_changed; // IPv6 address changed, close/restart conns
#endif
// Internal state, user can use it but should not change it
+18 -1
View File
@@ -393,6 +393,13 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO((" MAC: %M", mg_print_mac, ifp->mac));
if (ifp->l2type == MG_TCPIP_L2_ETH)
mg_tcpip_arp_request(ifp, ifp->ip, ifp->mac); // gratuitous ARP annc
if (ifp->is_ip_changed) {
struct mg_connection *c;
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if (!c->is_listening && !c->is_udp) c->is_closing = 1;
}
ifp->is_ip_changed = false;
}
} else if (ifp->state == MG_TCPIP_STATE_IP) {
if (ifp->gw != 0 && ifp->l2type == MG_TCPIP_L2_ETH)
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
@@ -702,6 +709,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// assume DHCP server = router until ARP resolves
memcpy(ifp->gwmac, mg_l2_getaddr(ifp, pkt->l2), sizeof(ifp->gwmac));
ifp->gw_ready = true; // NOTE(): actual gw ARP won't retry now
if (ifp->ip != ip) ifp->is_ip_changed = true;
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
ifp->state = MG_TCPIP_STATE_IP; // BOUND state
mg_random(&rand, sizeof(rand));
@@ -957,7 +965,7 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
struct ndp_ra *ra = (struct ndp_ra *) (pkt->icmp6 + 1);
uint8_t *opts = (uint8_t *) (ra + 1);
size_t opt_left = pkt->pay.len - 12;
bool gotl2addr = false, gotprefix = false;
bool gotl2addr = false, gotprefix = false, changed = false;
uint8_t l2[sizeof(struct mg_l2addr)];
uint32_t mtu = 0;
uint8_t *prefix, prefix_len;
@@ -990,6 +998,8 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
(void) pref_lifetime;
gotprefix = true;
if (prefix_len != ifp->prefix || !match_prefix(prefix, ifp->prefix, ifp->prefix_len))
changed = true;
}
opts += length;
opt_left -= length;
@@ -997,6 +1007,7 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// fill prefix and global
if (gotprefix && !fill_global(ifp, prefix, prefix_len)) return;
if (changed) ifp->is_ip6_changed = true;
ifp->gw6[0] = pkt->ip6->src[0], ifp->gw6[1] = pkt->ip6->src[1];
if (gotl2addr) memcpy(ifp->gw6mac, l2, sizeof(ifp->gw6mac));
if (gotl2addr || ifp->l2type == MG_TCPIP_L2_PPP || ifp->l2type == MG_TCPIP_L2_PPPoE) {
@@ -1075,6 +1086,12 @@ static void onstate6change(struct mg_tcpip_if *ifp) {
(struct mg_addr *) &ip6_allrouters),
ifp->ip6, (uint64_t *) ip6_allrouters.addr.ip6, false,
ifp->mac);
if (ifp->is_ip6_changed) {
struct mg_connection *c;
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if (!c->is_listening && !c->is_udp) c->is_closing = 1;
}
ifp->is_ip6_changed = false;
}
} else if (ifp->state6 == MG_TCPIP_STATE_IP) {
if ((ifp->gw6[0] != 0 || ifp->gw6[1] != 0) && (ifp->l2type != MG_TCPIP_L2_PPP && ifp->l2type != MG_TCPIP_L2_PPPoE))
+2
View File
@@ -49,6 +49,7 @@ struct mg_tcpip_if {
bool enable_fcs_check; // Do a FCS check on RX frames and strip it
bool enable_mac_check; // Do a hw addr check on RX frames
bool update_mac_hash_table; // Signal drivers to update MAC controller
bool is_ip_changed; // IP address changed, close/restart conns
struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data
mg_tcpip_event_handler_t pfn; // Driver-specific event handler function
@@ -65,6 +66,7 @@ struct mg_tcpip_if {
uint64_t gw6[2]; // default gateway.
bool enable_slaac; // Enable IPv6 address autoconfiguration
bool enable_dhcp6_client; // Enable DCHPv6 client TODO()
bool is_ip6_changed; // IPv6 address changed, close/restart conns
#endif
// Internal state, user can use it but should not change it