Merge pull request #3409 from cesanta/eseenetepe

Allow more than 1 address in received DHCP options
This commit is contained in:
Sergio R. Caprile authored and GitHub committed 2026-01-14 17:40:25 -03:00
commit a28decbef4
2 files changed
+34 -22

No files matched your search

+17 -11
View File
@@ -4941,8 +4941,8 @@ struct tcp {
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_STDFLAGS 0x3f
//#define TH_ECE 0x40 // not part of TCP but RFC-3168 (ECN)
//#define TH_CWR 0x80
// #define TH_ECE 0x40 // not part of TCP but RFC-3168 (ECN)
// #define TH_CWR 0x80
uint16_t win; // Window
uint16_t csum; // Checksum
uint16_t urp; // Urgent pointer
@@ -5378,6 +5378,10 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip);
static inline bool dhcp_opt_len_ok(uint8_t len, uint8_t *p, uint8_t *end) {
return (len >= 4 && (len & 3) == 0 && p + 6 < end);
}
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;
@@ -5386,17 +5390,17 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
*end = (uint8_t *) &pkt->pay.buf[pkt->pay.len];
if (end < p) return; // options are optional, check min header length
if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return;
while (p + 1 < end && p[0] != 255) { // Parse options RFC-1533 #9
if (p[0] == 1 && p[1] == sizeof(ifp->mask) && p + 6 < end) { // Mask
while (p + 1 < end && p[0] != 255) { // Parse options, get #1; RFC-2132 9
if (p[0] == 1 && p[1] == 4 && p + 6 < end) { // Mask, 3.3
memcpy(&mask, p + 2, sizeof(mask));
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
} else if (p[0] == 3 && dhcp_opt_len_ok(p[1], p, end)) { // GW, 3.5
memcpy(&gw, p + 2, sizeof(gw));
ip = pkt->dhcp->yiaddr;
} else if (ifp->enable_req_dns && p[0] == 6 && p[1] == sizeof(dns) &&
p + 6 < end) { // DNS
} else if (ifp->enable_req_dns && p[0] == 6 &&
dhcp_opt_len_ok(p[1], p, end)) { // DNS, 3.8
memcpy(&dns, p + 2, sizeof(dns));
} else if (ifp->enable_req_sntp && p[0] == 42 && p[1] == sizeof(sntp) &&
p + 6 < end) { // SNTP
} else if (ifp->enable_req_sntp && p[0] == 42 &&
dhcp_opt_len_ok(p[1], p, end)) { // SNTP, 8.3
memcpy(&sntp, p + 2, sizeof(sntp));
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
memcpy(&lease, p + 2, sizeof(lease));
@@ -6271,7 +6275,7 @@ static void handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) {
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
pkt->tcp->flags &= TH_STDFLAGS; // tolerate creative usage (ECN, ?)
pkt->tcp->flags &= TH_STDFLAGS; // tolerate creative usage (ECN, ?)
// Order is VERY important; RFC-9293 3.5.2
// - check clients (Group 1) and established connections (Group 3)
if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
@@ -6443,7 +6447,9 @@ static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
case 59: // No Next Header 4.7
return;
case 50: // IPsec ESP RFC-4303, unsupported
default: loop = false; break;
default:
loop = false;
break;
}
}
if (len >= plen) return;
+17 -11
View File
@@ -119,8 +119,8 @@ struct tcp {
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_STDFLAGS 0x3f
//#define TH_ECE 0x40 // not part of TCP but RFC-3168 (ECN)
//#define TH_CWR 0x80
// #define TH_ECE 0x40 // not part of TCP but RFC-3168 (ECN)
// #define TH_CWR 0x80
uint16_t win; // Window
uint16_t csum; // Checksum
uint16_t urp; // Urgent pointer
@@ -556,6 +556,10 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void setdns4(struct mg_tcpip_if *ifp, uint32_t *ip);
static inline bool dhcp_opt_len_ok(uint8_t len, uint8_t *p, uint8_t *end) {
return (len >= 4 && (len & 3) == 0 && p + 6 < end);
}
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;
@@ -564,17 +568,17 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
*end = (uint8_t *) &pkt->pay.buf[pkt->pay.len];
if (end < p) return; // options are optional, check min header length
if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return;
while (p + 1 < end && p[0] != 255) { // Parse options RFC-1533 #9
if (p[0] == 1 && p[1] == sizeof(ifp->mask) && p + 6 < end) { // Mask
while (p + 1 < end && p[0] != 255) { // Parse options, get #1; RFC-2132 9
if (p[0] == 1 && p[1] == 4 && p + 6 < end) { // Mask, 3.3
memcpy(&mask, p + 2, sizeof(mask));
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
} else if (p[0] == 3 && dhcp_opt_len_ok(p[1], p, end)) { // GW, 3.5
memcpy(&gw, p + 2, sizeof(gw));
ip = pkt->dhcp->yiaddr;
} else if (ifp->enable_req_dns && p[0] == 6 && p[1] == sizeof(dns) &&
p + 6 < end) { // DNS
} else if (ifp->enable_req_dns && p[0] == 6 &&
dhcp_opt_len_ok(p[1], p, end)) { // DNS, 3.8
memcpy(&dns, p + 2, sizeof(dns));
} else if (ifp->enable_req_sntp && p[0] == 42 && p[1] == sizeof(sntp) &&
p + 6 < end) { // SNTP
} else if (ifp->enable_req_sntp && p[0] == 42 &&
dhcp_opt_len_ok(p[1], p, end)) { // SNTP, 8.3
memcpy(&sntp, p + 2, sizeof(sntp));
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
memcpy(&lease, p + 2, sizeof(lease));
@@ -1449,7 +1453,7 @@ static void handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) {
static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
pkt->tcp->flags &= TH_STDFLAGS; // tolerate creative usage (ECN, ?)
pkt->tcp->flags &= TH_STDFLAGS; // tolerate creative usage (ECN, ?)
// Order is VERY important; RFC-9293 3.5.2
// - check clients (Group 1) and established connections (Group 3)
if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
@@ -1621,7 +1625,9 @@ static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
case 59: // No Next Header 4.7
return;
case 50: // IPsec ESP RFC-4303, unsupported
default: loop = false; break;
default:
loop = false;
break;
}
}
if (len >= plen) return;