diff --git a/mongoose.c b/mongoose.c index 81d3d7ae..46ecafba 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7712,19 +7712,24 @@ static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src, } static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src, - uint32_t ip_dst, uint8_t *opts, size_t optslen) { + uint32_t ip_dst, uint8_t *opts, size_t optslen, + bool ciaddr) { // https://datatracker.ietf.org/doc/html/rfc2132#section-9.6 struct dhcp dhcp = {1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}}; dhcp.magic = mg_htonl(0x63825363); memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac)); memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid)); memcpy(&dhcp.options, opts, optslen); + if (ciaddr) dhcp.ciaddr = ip_src; tx_udp(ifp, mac_dst, ip_src, mg_htons(68), ip_dst, mg_htons(67), &dhcp, sizeof(dhcp)); } -static void tx_dhcp_request(struct mg_tcpip_if *ifp, uint8_t *mac_dst, - uint32_t ip_src, uint32_t ip_dst) { +static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255}; + +// RFC-2131 #4.3.6, #4.4.1 +static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req, + uint32_t ip_srv) { uint8_t opts[] = { 53, 1, 3, // Type: DHCP request 55, 2, 1, 3, // GW and mask @@ -7733,20 +7738,30 @@ static void tx_dhcp_request(struct mg_tcpip_if *ifp, uint8_t *mac_dst, 50, 4, 0, 0, 0, 0, // Requested IP 255 // End of options }; - memcpy(opts + 14, &ip_dst, sizeof(ip_dst)); - memcpy(opts + 20, &ip_src, sizeof(ip_src)); - tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts)); + memcpy(opts + 14, &ip_srv, sizeof(ip_srv)); + memcpy(opts + 20, &ip_req, sizeof(ip_req)); + tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false); + MG_DEBUG(("DHCP req sent")); +} + +// RFC-2131 #4.3.6, #4.4.5 (renewing: unicast, rebinding: bcast) +static void tx_dhcp_request_re(struct mg_tcpip_if *ifp, uint8_t *mac_dst, + uint32_t ip_src, uint32_t ip_dst) { + uint8_t opts[] = { + 53, 1, 3, // Type: DHCP request + 255 // End of options + }; + tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts), true); MG_DEBUG(("DHCP req sent")); } static void tx_dhcp_discover(struct mg_tcpip_if *ifp) { - uint8_t mac[6] = {255, 255, 255, 255, 255, 255}; uint8_t opts[] = { 53, 1, 1, // Type: DHCP discover 55, 2, 1, 3, // Parameters: ip, mask 255 // End of options }; - tx_dhcp(ifp, mac, 0, 0xffffffff, opts, sizeof(opts)); + tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false); MG_DEBUG(("DHCP discover sent. Our MAC: %M", mg_print_mac, ifp->mac)); } @@ -7816,37 +7831,51 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { - uint32_t ip = 0, gw = 0, mask = 0; + uint32_t ip = 0, gw = 0, mask = 0, lease = 0; + uint8_t msgtype = 0, state = ifp->state; // perform size check first, then access fields uint8_t *p = pkt->dhcp->options, *end = (uint8_t *) &pkt->raw.ptr[pkt->raw.len]; if (end < (uint8_t *) (pkt->dhcp + 1)) return; if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return; - while (p + 1 < end && p[0] != 255) { // Parse options + 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 memcpy(&mask, p + 2, sizeof(mask)); } else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW memcpy(&gw, p + 2, sizeof(gw)); ip = pkt->dhcp->yiaddr; } else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease - uint32_t lease = 0; memcpy(&lease, p + 2, sizeof(lease)); lease = mg_ntohl(lease); - ifp->lease_expire = ifp->now + lease * 1000; - MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + } else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type + msgtype = p[2]; } p += p[1] + 2; } - if (ip && mask && gw && ifp->ip == 0) { - memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); - ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; - ifp->state = MG_TCPIP_STATE_READY; - onstatechange(ifp); - tx_dhcp_request(ifp, pkt->eth->src, ip, pkt->dhcp->siaddr); - uint64_t rand; - mg_random(&rand, sizeof(rand)); - srand((unsigned int) (rand + mg_millis())); + // Process message type, RFC-1533 (9.4); RFC-2131 (3.1, 4) + if (msgtype == 6 && ifp->ip == ip) { // DHCPNACK, release IP + ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; + } else if (msgtype == 2 && ifp->state == MG_TCPIP_STATE_UP && ip && gw && + lease) { // DHCPOFFER + tx_dhcp_request_sel(ifp, ip, pkt->dhcp->siaddr); // select IP, (4.4.1) + 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 + ifp->lease_expire = ifp->now + lease * 1000; + MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + // assume DHCP server = router until ARP resolves + memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); + ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; + ifp->state = MG_TCPIP_STATE_READY; // BOUND state + uint64_t rand; + mg_random(&rand, sizeof(rand)); + srand((unsigned int) (rand + mg_millis())); + } else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew + ifp->lease_expire = ifp->now + lease * 1000; + MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + } // TODO(): accept provided T1/T2 and store server IP for renewal (4.4) } + if (ifp->state != state) onstatechange(ifp); } // Simple DHCP server that assigns a next IP address: ifp->ip + 1 @@ -8033,16 +8062,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { if (s->ack == ack) { MG_VERBOSE(("ignoring duplicate pkt")); } else { - // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather - // than close this connection + // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit + // rather than close this connection mg_error(c, "SEQ != ACK: %x %x %x", seq, s->ack, ack); } } else if (io->size - io->len < pkt->pay.len && !mg_iobuf_resize(io, io->len + pkt->pay.len)) { mg_error(c, "oom"); } else { - // Copy TCP payload into the IO buffer. If the connection is plain text, we - // copy to c->recv. If the connection is TLS, this data is encrypted, + // Copy TCP payload into the IO buffer. If the connection is plain text, + // we copy to c->recv. If the connection is TLS, this data is encrypted, // therefore we copy that encrypted data to the s->raw iobuffer instead, // and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will // call back mg_io_recv() which grabs raw data from s->raw @@ -8080,7 +8109,8 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { } } } else { - // Plain text connection, data is already in c->recv, trigger MG_EV_READ + // Plain text connection, data is already in c->recv, trigger + // MG_EV_READ mg_call(c, MG_EV_READ, &pkt->pay.len); } } @@ -8189,7 +8219,6 @@ static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { - const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255}; struct pkt pkt; memset(&pkt, 0, sizeof(pkt)); pkt.raw.ptr = (char *) buf; @@ -8251,14 +8280,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { } if (ifp->state == MG_TCPIP_STATE_DOWN) return; - // If IP not configured, send DHCP - if (ifp->ip == 0 && expired_1000ms) tx_dhcp_discover(ifp); - - // If a DHCP lease is 30 min prior to expire, attempt to renew (every 10s) - if (expired_1000ms && ifp->lease_expire > 0 && ifp->ip != 0 && - ifp->now + 30 * 60 * 1000 > ifp->lease_expire && - ((ifp->now / 1000) % 10) == 0) { - tx_dhcp_request(ifp, ifp->gwmac, ifp->ip, ifp->gw); // Renew DHCP lease + // DHCP RFC-2131 (4.4) + if (ifp->state == MG_TCPIP_STATE_UP && expired_1000ms) { + tx_dhcp_discover(ifp); // INIT (4.4.1) + } else if (expired_1000ms && ifp->state == MG_TCPIP_STATE_READY && + ifp->lease_expire > 0) { // BOUND / RENEWING / REBINDING + if (ifp->now >= ifp->lease_expire) { + ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; // expired, release IP + onstatechange(ifp); + } else if (ifp->now + 30 * 60 * 1000 > ifp->lease_expire && + ((ifp->now / 1000) % 60) == 0) { + // hack: 30 min before deadline, try to rebind (4.3.6) every min + tx_dhcp_request_re(ifp, (uint8_t *) broadcast, ifp->ip, 0xffffffff); + } // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5) } // Read data from the network @@ -8339,8 +8373,8 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { if (ifp->ip == 0) ifp->enable_dhcp_client = true; memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set to broadcast mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535 - ifp->eport |= - MG_EPHEMERAL_PORT_BASE; // Random from MG_EPHEMERAL_PORT_BASE to 65535 + ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from + // MG_EPHEMERAL_PORT_BASE to 65535 if (ifp->tx.ptr == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM")); } } diff --git a/mongoose.h b/mongoose.h index 71bf9682..5f708680 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1628,7 +1628,7 @@ struct mg_tcpip_if { uint8_t gwmac[6]; // Router's MAC uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state - uint64_t lease_expire; // Lease expiration time + uint64_t lease_expire; // Lease expiration time, in ms uint16_t eport; // Next ephemeral port volatile uint32_t ndrop; // Number of received, but dropped frames volatile uint32_t nrecv; // Number of received frames @@ -1637,7 +1637,8 @@ struct mg_tcpip_if { uint8_t state; // Current state #define MG_TCPIP_STATE_DOWN 0 // Interface is down #define MG_TCPIP_STATE_UP 1 // Interface is up -#define MG_TCPIP_STATE_READY 2 // Interface is up and has IP +#define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP +#define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned }; void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index 121ec5a6..c415d3d5 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -229,19 +229,24 @@ static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src, } static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src, - uint32_t ip_dst, uint8_t *opts, size_t optslen) { + uint32_t ip_dst, uint8_t *opts, size_t optslen, + bool ciaddr) { // https://datatracker.ietf.org/doc/html/rfc2132#section-9.6 struct dhcp dhcp = {1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}}; dhcp.magic = mg_htonl(0x63825363); memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac)); memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid)); memcpy(&dhcp.options, opts, optslen); + if (ciaddr) dhcp.ciaddr = ip_src; tx_udp(ifp, mac_dst, ip_src, mg_htons(68), ip_dst, mg_htons(67), &dhcp, sizeof(dhcp)); } -static void tx_dhcp_request(struct mg_tcpip_if *ifp, uint8_t *mac_dst, - uint32_t ip_src, uint32_t ip_dst) { +static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255}; + +// RFC-2131 #4.3.6, #4.4.1 +static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req, + uint32_t ip_srv) { uint8_t opts[] = { 53, 1, 3, // Type: DHCP request 55, 2, 1, 3, // GW and mask @@ -250,20 +255,30 @@ static void tx_dhcp_request(struct mg_tcpip_if *ifp, uint8_t *mac_dst, 50, 4, 0, 0, 0, 0, // Requested IP 255 // End of options }; - memcpy(opts + 14, &ip_dst, sizeof(ip_dst)); - memcpy(opts + 20, &ip_src, sizeof(ip_src)); - tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts)); + memcpy(opts + 14, &ip_srv, sizeof(ip_srv)); + memcpy(opts + 20, &ip_req, sizeof(ip_req)); + tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false); + MG_DEBUG(("DHCP req sent")); +} + +// RFC-2131 #4.3.6, #4.4.5 (renewing: unicast, rebinding: bcast) +static void tx_dhcp_request_re(struct mg_tcpip_if *ifp, uint8_t *mac_dst, + uint32_t ip_src, uint32_t ip_dst) { + uint8_t opts[] = { + 53, 1, 3, // Type: DHCP request + 255 // End of options + }; + tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts), true); MG_DEBUG(("DHCP req sent")); } static void tx_dhcp_discover(struct mg_tcpip_if *ifp) { - uint8_t mac[6] = {255, 255, 255, 255, 255, 255}; uint8_t opts[] = { 53, 1, 1, // Type: DHCP discover 55, 2, 1, 3, // Parameters: ip, mask 255 // End of options }; - tx_dhcp(ifp, mac, 0, 0xffffffff, opts, sizeof(opts)); + tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false); MG_DEBUG(("DHCP discover sent. Our MAC: %M", mg_print_mac, ifp->mac)); } @@ -333,37 +348,51 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { - uint32_t ip = 0, gw = 0, mask = 0; + uint32_t ip = 0, gw = 0, mask = 0, lease = 0; + uint8_t msgtype = 0, state = ifp->state; // perform size check first, then access fields uint8_t *p = pkt->dhcp->options, *end = (uint8_t *) &pkt->raw.ptr[pkt->raw.len]; if (end < (uint8_t *) (pkt->dhcp + 1)) return; if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return; - while (p + 1 < end && p[0] != 255) { // Parse options + 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 memcpy(&mask, p + 2, sizeof(mask)); } else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW memcpy(&gw, p + 2, sizeof(gw)); ip = pkt->dhcp->yiaddr; } else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease - uint32_t lease = 0; memcpy(&lease, p + 2, sizeof(lease)); lease = mg_ntohl(lease); - ifp->lease_expire = ifp->now + lease * 1000; - MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + } else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type + msgtype = p[2]; } p += p[1] + 2; } - if (ip && mask && gw && ifp->ip == 0) { - memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); - ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; - ifp->state = MG_TCPIP_STATE_READY; - onstatechange(ifp); - tx_dhcp_request(ifp, pkt->eth->src, ip, pkt->dhcp->siaddr); - uint64_t rand; - mg_random(&rand, sizeof(rand)); - srand((unsigned int) (rand + mg_millis())); + // Process message type, RFC-1533 (9.4); RFC-2131 (3.1, 4) + if (msgtype == 6 && ifp->ip == ip) { // DHCPNACK, release IP + ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; + } else if (msgtype == 2 && ifp->state == MG_TCPIP_STATE_UP && ip && gw && + lease) { // DHCPOFFER + tx_dhcp_request_sel(ifp, ip, pkt->dhcp->siaddr); // select IP, (4.4.1) + 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 + ifp->lease_expire = ifp->now + lease * 1000; + MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + // assume DHCP server = router until ARP resolves + memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); + ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; + ifp->state = MG_TCPIP_STATE_READY; // BOUND state + uint64_t rand; + mg_random(&rand, sizeof(rand)); + srand((unsigned int) (rand + mg_millis())); + } else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew + ifp->lease_expire = ifp->now + lease * 1000; + MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); + } // TODO(): accept provided T1/T2 and store server IP for renewal (4.4) } + if (ifp->state != state) onstatechange(ifp); } // Simple DHCP server that assigns a next IP address: ifp->ip + 1 @@ -550,16 +579,16 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { if (s->ack == ack) { MG_VERBOSE(("ignoring duplicate pkt")); } else { - // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit rather - // than close this connection + // TODO(cpq): peer sent us SEQ which we don't expect. Retransmit + // rather than close this connection mg_error(c, "SEQ != ACK: %x %x %x", seq, s->ack, ack); } } else if (io->size - io->len < pkt->pay.len && !mg_iobuf_resize(io, io->len + pkt->pay.len)) { mg_error(c, "oom"); } else { - // Copy TCP payload into the IO buffer. If the connection is plain text, we - // copy to c->recv. If the connection is TLS, this data is encrypted, + // Copy TCP payload into the IO buffer. If the connection is plain text, + // we copy to c->recv. If the connection is TLS, this data is encrypted, // therefore we copy that encrypted data to the s->raw iobuffer instead, // and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will // call back mg_io_recv() which grabs raw data from s->raw @@ -597,7 +626,8 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) { } } } else { - // Plain text connection, data is already in c->recv, trigger MG_EV_READ + // Plain text connection, data is already in c->recv, trigger + // MG_EV_READ mg_call(c, MG_EV_READ, &pkt->pay.len); } } @@ -706,7 +736,6 @@ static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) { - const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255}; struct pkt pkt; memset(&pkt, 0, sizeof(pkt)); pkt.raw.ptr = (char *) buf; @@ -768,14 +797,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { } if (ifp->state == MG_TCPIP_STATE_DOWN) return; - // If IP not configured, send DHCP - if (ifp->ip == 0 && expired_1000ms) tx_dhcp_discover(ifp); - - // If a DHCP lease is 30 min prior to expire, attempt to renew (every 10s) - if (expired_1000ms && ifp->lease_expire > 0 && ifp->ip != 0 && - ifp->now + 30 * 60 * 1000 > ifp->lease_expire && - ((ifp->now / 1000) % 10) == 0) { - tx_dhcp_request(ifp, ifp->gwmac, ifp->ip, ifp->gw); // Renew DHCP lease + // DHCP RFC-2131 (4.4) + if (ifp->state == MG_TCPIP_STATE_UP && expired_1000ms) { + tx_dhcp_discover(ifp); // INIT (4.4.1) + } else if (expired_1000ms && ifp->state == MG_TCPIP_STATE_READY && + ifp->lease_expire > 0) { // BOUND / RENEWING / REBINDING + if (ifp->now >= ifp->lease_expire) { + ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; // expired, release IP + onstatechange(ifp); + } else if (ifp->now + 30 * 60 * 1000 > ifp->lease_expire && + ((ifp->now / 1000) % 60) == 0) { + // hack: 30 min before deadline, try to rebind (4.3.6) every min + tx_dhcp_request_re(ifp, (uint8_t *) broadcast, ifp->ip, 0xffffffff); + } // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5) } // Read data from the network @@ -856,8 +890,8 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) { if (ifp->ip == 0) ifp->enable_dhcp_client = true; memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set to broadcast mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535 - ifp->eport |= - MG_EPHEMERAL_PORT_BASE; // Random from MG_EPHEMERAL_PORT_BASE to 65535 + ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from + // MG_EPHEMERAL_PORT_BASE to 65535 if (ifp->tx.ptr == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM")); } } diff --git a/src/tcpip/tcpip.h b/src/tcpip/tcpip.h index 0eb2822b..93780ac6 100644 --- a/src/tcpip/tcpip.h +++ b/src/tcpip/tcpip.h @@ -32,7 +32,7 @@ struct mg_tcpip_if { uint8_t gwmac[6]; // Router's MAC uint64_t now; // Current time uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state - uint64_t lease_expire; // Lease expiration time + uint64_t lease_expire; // Lease expiration time, in ms uint16_t eport; // Next ephemeral port volatile uint32_t ndrop; // Number of received, but dropped frames volatile uint32_t nrecv; // Number of received frames @@ -41,7 +41,8 @@ struct mg_tcpip_if { uint8_t state; // Current state #define MG_TCPIP_STATE_DOWN 0 // Interface is down #define MG_TCPIP_STATE_UP 1 // Interface is up -#define MG_TCPIP_STATE_READY 2 // Interface is up and has IP +#define MG_TCPIP_STATE_REQ 2 // Interface is up and has requested an IP +#define MG_TCPIP_STATE_READY 3 // Interface is up and has an IP assigned }; void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);