diff --git a/mongoose.c b/mongoose.c index df80dfc3..80b5d326 100644 --- a/mongoose.c +++ b/mongoose.c @@ -5223,9 +5223,9 @@ static uint16_t pcsum(void *d, void *p, size_t plen) { uint32_t sum; struct ip *ip = (struct ip *) d; #if defined(__DCC__) - volatile /* Makes PPC & Diab4.3 happy */ + volatile /* Makes PPC & Diab4.3 happy */ #endif - struct pseudoip pip; + struct pseudoip pip; pip.src = ip->src; pip.dst = ip->dst; pip.zero = 0; @@ -5254,9 +5254,9 @@ static uint16_t p6csum(void *d, void *p, size_t plen) { uint32_t sum; struct ip6 *ip6 = (struct ip6 *) d; #if defined(__DCC__) - volatile /* Makes PPC & Diab4.3 happy */ + volatile /* Makes PPC & Diab4.3 happy */ #endif - struct pseudoip6 pip6; + struct pseudoip6 pip6; pip6.src[0] = ip6->src[0], pip6.src[1] = ip6->src[1]; pip6.dst[0] = ip6->dst[0], pip6.dst[1] = ip6->dst[1]; pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0; @@ -5517,7 +5517,7 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt, #if MG_ENABLE_IPV6 || (c->loc.is_ip6 && MG_IP6MATCH(c->rem.addr.ip6, pkt->ip6->src)) #endif - )))) // validate addr for established (not listening) conns + )))) // validate addr for established (not listening) conns break; } return c; @@ -5603,7 +5603,7 @@ static bool dhcp_opt_len_ok(uint8_t len, uint8_t *p, uint8_t *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; + uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0, owner = 0; uint8_t msgtype = 0, state = ifp->state; // perform size check first, then access fields uint8_t *p = pkt->dhcp->options, @@ -5627,6 +5627,8 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { lease = mg_ntohl(lease); } else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type msgtype = p[2]; + } else if (p[0] == 54 && p[1] == 4 && p + 6 < end) { // Server id 9.7 + memcpy(&owner, p + 2, sizeof(sntp)); // This is the lease owner } p += p[1] + 2; } @@ -5635,9 +5637,13 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; } else if (msgtype == 2 && ifp->state == MG_TCPIP_STATE_UP && ip && gw && lease) { // DHCPOFFER - // select IP, (4.4.1) (fallback to IP source addr on foul play) + // select a server (2131 4.4.1, 2132 9.7): lease owner takes precedence, + // otherwise use siaddr (fallback to IP source addr on foul play). + // This is broadcast, otherwise siaddr would be the destination. tx_dhcp_request_sel(ifp, ip, - pkt->dhcp->siaddr ? pkt->dhcp->siaddr : pkt->ip->src); + owner ? owner + : pkt->dhcp->siaddr ? pkt->dhcp->siaddr + : pkt->ip->src); ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state } else if (msgtype == 5) { // DHCPACK if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP @@ -6467,9 +6473,9 @@ static bool handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) { s->dmss = ip6 ? 1220 : 536; // assume default, RFC-9293 3.7.1 while (len > 0) { // RFC-9293 3.1 3.2 uint8_t kind = opts[0], optlen = 1; - if (kind != 1) { // No-Operation - if (kind == 0) break; // End of Option List - if (len < 2 || opts[1] == 0) return false; // Malformed options + if (kind != 1) { // No-Operation + if (kind == 0) break; // End of Option List + if (len < 2 || opts[1] == 0) return false; // Malformed options optlen = opts[1]; if (kind == 2 && optlen == 4) // set received MSS s->dmss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); @@ -6493,7 +6499,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // - check clients (Group 1) and established connections (Group 3) if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) { // client got a server connection accept - if (!handle_opt(s, pkt->tcp, pkt->ip6 != NULL)) return; // process options (MSS) + if (!handle_opt(s, pkt->tcp, pkt->ip6 != NULL)) + return; // process options (MSS) s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1; tx_tcp_ctrlresp(ifp, pkt, TH_ACK, pkt->tcp->ack); c->is_connecting = 0; // Client connected @@ -6528,7 +6535,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { int key; uint32_t isn; if (pkt->tcp->sport != 0) { - if (!handle_opt(&cs, pkt->tcp, pkt->ip6 != NULL)) return; // process options (MSS) + if (!handle_opt(&cs, pkt->tcp, pkt->ip6 != NULL)) + return; // process options (MSS) key = backlog_insert(c, pkt->tcp->sport, cs.dmss); // backlog options (MSS) if (key < 0) return; // no room in backlog, discard SYN, client retries diff --git a/src/net_builtin.c b/src/net_builtin.c index be8349cd..710813cb 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -263,9 +263,9 @@ static uint16_t pcsum(void *d, void *p, size_t plen) { uint32_t sum; struct ip *ip = (struct ip *) d; #if defined(__DCC__) - volatile /* Makes PPC & Diab4.3 happy */ + volatile /* Makes PPC & Diab4.3 happy */ #endif - struct pseudoip pip; + struct pseudoip pip; pip.src = ip->src; pip.dst = ip->dst; pip.zero = 0; @@ -294,9 +294,9 @@ static uint16_t p6csum(void *d, void *p, size_t plen) { uint32_t sum; struct ip6 *ip6 = (struct ip6 *) d; #if defined(__DCC__) - volatile /* Makes PPC & Diab4.3 happy */ + volatile /* Makes PPC & Diab4.3 happy */ #endif - struct pseudoip6 pip6; + struct pseudoip6 pip6; pip6.src[0] = ip6->src[0], pip6.src[1] = ip6->src[1]; pip6.dst[0] = ip6->dst[0], pip6.dst[1] = ip6->dst[1]; pip6.zero[0] = 0, pip6.zero[1] = 0, pip6.zero[2] = 0; @@ -557,7 +557,7 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt, #if MG_ENABLE_IPV6 || (c->loc.is_ip6 && MG_IP6MATCH(c->rem.addr.ip6, pkt->ip6->src)) #endif - )))) // validate addr for established (not listening) conns + )))) // validate addr for established (not listening) conns break; } return c; @@ -643,7 +643,7 @@ static bool dhcp_opt_len_ok(uint8_t len, uint8_t *p, uint8_t *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; + uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0, owner = 0; uint8_t msgtype = 0, state = ifp->state; // perform size check first, then access fields uint8_t *p = pkt->dhcp->options, @@ -667,6 +667,8 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { lease = mg_ntohl(lease); } else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type msgtype = p[2]; + } else if (p[0] == 54 && p[1] == 4 && p + 6 < end) { // Server id 9.7 + memcpy(&owner, p + 2, sizeof(sntp)); // This is the lease owner } p += p[1] + 2; } @@ -675,9 +677,13 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; } else if (msgtype == 2 && ifp->state == MG_TCPIP_STATE_UP && ip && gw && lease) { // DHCPOFFER - // select IP, (4.4.1) (fallback to IP source addr on foul play) + // select a server (2131 4.4.1, 2132 9.7): lease owner takes precedence, + // otherwise use siaddr (fallback to IP source addr on foul play). + // This is broadcast, otherwise siaddr would be the destination. tx_dhcp_request_sel(ifp, ip, - pkt->dhcp->siaddr ? pkt->dhcp->siaddr : pkt->ip->src); + owner ? owner + : pkt->dhcp->siaddr ? pkt->dhcp->siaddr + : pkt->ip->src); ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state } else if (msgtype == 5) { // DHCPACK if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP @@ -1507,9 +1513,9 @@ static bool handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) { s->dmss = ip6 ? 1220 : 536; // assume default, RFC-9293 3.7.1 while (len > 0) { // RFC-9293 3.1 3.2 uint8_t kind = opts[0], optlen = 1; - if (kind != 1) { // No-Operation - if (kind == 0) break; // End of Option List - if (len < 2 || opts[1] == 0) return false; // Malformed options + if (kind != 1) { // No-Operation + if (kind == 0) break; // End of Option List + if (len < 2 || opts[1] == 0) return false; // Malformed options optlen = opts[1]; if (kind == 2 && optlen == 4) // set received MSS s->dmss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]); @@ -1533,7 +1539,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // - check clients (Group 1) and established connections (Group 3) if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) { // client got a server connection accept - if (!handle_opt(s, pkt->tcp, pkt->ip6 != NULL)) return; // process options (MSS) + if (!handle_opt(s, pkt->tcp, pkt->ip6 != NULL)) + return; // process options (MSS) s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1; tx_tcp_ctrlresp(ifp, pkt, TH_ACK, pkt->tcp->ack); c->is_connecting = 0; // Client connected @@ -1568,7 +1575,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { int key; uint32_t isn; if (pkt->tcp->sport != 0) { - if (!handle_opt(&cs, pkt->tcp, pkt->ip6 != NULL)) return; // process options (MSS) + if (!handle_opt(&cs, pkt->tcp, pkt->ip6 != NULL)) + return; // process options (MSS) key = backlog_insert(c, pkt->tcp->sport, cs.dmss); // backlog options (MSS) if (key < 0) return; // no room in backlog, discard SYN, client retries