diff --git a/mongoose.c b/mongoose.c index 32bd36cd..5ddb4b73 100644 --- a/mongoose.c +++ b/mongoose.c @@ -238,7 +238,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) { break; // Return success } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) { dm->addr.is_ip6 = true; - memcpy(&dm->addr.ip6, &buf[ofs - 16], 16); + memcpy(&dm->addr.ip, &buf[ofs - 16], 16); dm->resolved = true; break; // Return success } @@ -3494,15 +3494,16 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) { } static bool mg_atonl(struct mg_str str, struct mg_addr *addr) { + uint32_t localhost = mg_htonl(0x7f000001); if (mg_vcasecmp(&str, "localhost") != 0) return false; - addr->ip = mg_htonl(0x7f000001); + memcpy(addr->ip, &localhost, sizeof(uint32_t)); addr->is_ip6 = false; return true; } static bool mg_atone(struct mg_str str, struct mg_addr *addr) { if (str.len > 0) return false; - addr->ip = 0; + memset(addr->ip, 0, sizeof(addr->ip)); addr->is_ip6 = false; return true; } @@ -3530,15 +3531,18 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) { static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { int i; + uint32_t ipv4; if (str.len < 14) return false; if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false; for (i = 2; i < 6; i++) { if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false; } + //struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false; - memset(addr->ip6, 0, sizeof(addr->ip6)); - addr->ip6[10] = addr->ip6[11] = 255; - memcpy(&addr->ip6[12], &addr->ip, 4); + memcpy(&ipv4, addr->ip, sizeof(ipv4)); + memset(addr->ip, 0, sizeof(addr->ip)); + addr->ip[10] = addr->ip[11] = 255; + memcpy(&addr->ip[12], &ipv4, 4); addr->is_ip6 = true; return true; } @@ -3555,8 +3559,8 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { if (i > j + 3) return false; // MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j])); val = mg_unhexn(&str.ptr[j], i - j + 1); - addr->ip6[n] = (uint8_t) ((val >> 8) & 255); - addr->ip6[n + 1] = (uint8_t) (val & 255); + addr->ip[n] = (uint8_t) ((val >> 8) & 255); + addr->ip[n + 1] = (uint8_t) (val & 255); } else if (str.ptr[i] == ':') { j = i + 1; if (i > 0 && str.ptr[i - 1] == ':') { @@ -3566,16 +3570,17 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { n += 2; } if (n > 14) return false; - addr->ip6[n] = addr->ip6[n + 1] = 0; // For trailing :: + addr->ip[n] = addr->ip[n + 1] = 0; // For trailing :: } else { return false; } } if (n < 14 && dc == 42) return false; if (n < 14) { - memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2); - memset(&addr->ip6[dc], 0, 14 - n); + memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2); + memset(&addr->ip[dc], 0, 14 - n); } + addr->is_ip6 = true; return true; } @@ -3825,7 +3830,7 @@ size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) { size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) { struct mg_addr *addr = va_arg(*ap, struct mg_addr *); - if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip6); + if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip); return print_ip4(out, arg, (uint8_t *) &addr->ip); } @@ -4456,12 +4461,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { memset(usa, 0, sizeof(*usa)); usa->sin.sin_family = AF_INET; usa->sin.sin_port = a->port; - *(uint32_t *) &usa->sin.sin_addr = a->ip; + memcpy(&usa->sin.sin_addr, a->ip, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (a->is_ip6) { usa->sin.sin_family = AF_INET6; usa->sin6.sin6_port = a->port; - memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6)); + memcpy(&usa->sin6.sin6_addr, a->ip, sizeof(a->ip)); len = sizeof(usa->sin6); } #endif @@ -4471,10 +4476,10 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { a->is_ip6 = is_ip6; a->port = usa->sin.sin_port; - memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip)); + memcpy(&a->ip, &usa->sin.sin_addr, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (is_ip6) { - memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6)); + memcpy(a->ip, &usa->sin6.sin6_addr, sizeof(a->ip)); a->port = usa->sin6.sin6_port; } #endif @@ -7786,7 +7791,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (c != NULL && c->is_arplooking) { struct connstate *s = (struct connstate *) (c + 1); memcpy(s->mac, pkt->arp->sha, sizeof(s->mac)); - MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, &c->rem.ip, + MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip, mg_print_mac, s->mac)); c->is_arplooking = 0; } @@ -7885,7 +7890,7 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // No UDP listener on this port. Should send ICMP, but keep silent. } else { c->rem.port = pkt->udp->sport; - c->rem.ip = pkt->ip->src; + memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t)); struct connstate *s = (struct connstate *) (c + 1); memcpy(s->mac, pkt->eth->src, sizeof(s->mac)); if (c->recv.len >= MG_MAX_RECV_SIZE) { @@ -7959,7 +7964,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); memcpy(s->mac, pkt->eth->src, sizeof(s->mac)); settmout(c, MIP_TTYPE_KEEPALIVE); - c->rem.ip = pkt->ip->src; + memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t)); c->rem.port = pkt->tcp->sport; MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem)); LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c); @@ -7978,17 +7983,19 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (c->is_udp) { size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */; if (len + max_headers_len > ifp->tx.len) { len = ifp->tx.len - max_headers_len; } - tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len); + tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len); } else { size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */; if (len + max_headers_len > ifp->tx.len) len = ifp->tx.len - max_headers_len; - if (tx_tcp(ifp, s->mac, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port, + if (tx_tcp(ifp, s->mac, rem_ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) { s->seq += (uint32_t) len; if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE); @@ -8271,17 +8278,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { if (c->is_udp || c->is_listening) continue; if (c->is_connecting || c->is_resolving) continue; struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (uptime_ms > s->timer) { if (s->ttype == MIP_TTYPE_ACK) { MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack)); - tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), "", 0); } else { if (s->tmiss++ > 2) { mg_error(c, "keepalive"); } else { MG_DEBUG(("%lu keepalive", c->id)); - tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); } } @@ -8349,32 +8358,36 @@ static void send_syn(struct mg_connection *c) { struct connstate *s = (struct connstate *) (c + 1); uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port)); struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; - tx_tcp(ifp, s->mac, c->rem.ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL, + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); + tx_tcp(ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL, 0); } void mg_connect_resolved(struct mg_connection *c) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); c->is_resolving = 0; if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE; - c->loc.ip = ifp->ip; + memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t)); c->loc.port = mg_htons(ifp->eport++); MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port, &c->rem)); mg_call(c, MG_EV_RESOLVE, NULL); - if (((c->rem.ip & ifp->mask) == (ifp->ip & ifp->mask))) { + if (((rem_ip & ifp->mask) == (ifp->ip & ifp->mask))) { // If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this! MG_DEBUG(("%lu ARP lookup...", c->id)); - arp_ask(ifp, c->rem.ip); + arp_ask(ifp, rem_ip); c->is_arplooking = 1; - } else if (c->rem.ip == (ifp->ip | ~ifp->mask)) { + } else if (rem_ip == (ifp->ip | ~ifp->mask)) { struct connstate *s = (struct connstate *) (c + 1); memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast - } else if ((*((uint8_t *) &c->rem.ip) & 0xE0) == 0xE0) { + } else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) { struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group memcpy(s->mac, mcastp, 3); - memcpy(s->mac + 3, ((uint8_t *) &c->rem.ip) + 1, 3); // 23 LSb + memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3); // 23 LSb s->mac[3] &= 0x7F; } else { struct connstate *s = (struct connstate *) (c + 1); @@ -8404,11 +8417,13 @@ static void write_conn(struct mg_connection *c) { static void close_conn(struct mg_connection *c) { struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); mg_iobuf_free(&s->raw); // For TLS connections, release raw data if (c->is_udp == false && c->is_listening == false) { // For TCP conns, struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN - tx_tcp(ifp, s->mac, c->rem.ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0); } mg_close_conn(c); @@ -8441,11 +8456,13 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) { bool mg_send(struct mg_connection *c, const void *buf, size_t len) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; bool res = false; + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) { mg_error(c, "net down"); } else if (c->is_udp) { struct connstate *s = (struct connstate *) (c + 1); - tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len); + tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len); res = true; } else { res = mg_iobuf_add(&c->send, c->send.len, buf, len); diff --git a/mongoose.h b/mongoose.h index 43737085..71bf9682 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1137,10 +1137,9 @@ struct mg_dns { }; struct mg_addr { - uint16_t port; // TCP or UDP port in network byte order - uint32_t ip; // IP address in network byte order - uint8_t ip6[16]; // IPv6 address - bool is_ip6; // True when address is IPv6 address + uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order + uint16_t port; // TCP or UDP port in network byte order + bool is_ip6; // True when address is IPv6 address }; struct mg_mgr { @@ -1152,6 +1151,7 @@ struct mg_mgr { unsigned long nextid; // Next connection ID unsigned long timerid; // Next timer ID void *userdata; // Arbitrary user data pointer + void *tls_ctx; // TLS context shared by all TLS sessions uint16_t mqtt_id; // MQTT IDs for pub/sub void *active_dns_requests; // DNS requests in progress struct mg_timer *timers; // Active timers diff --git a/src/dns.c b/src/dns.c index 65745240..ca3b7d0b 100644 --- a/src/dns.c +++ b/src/dns.c @@ -126,7 +126,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) { break; // Return success } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) { dm->addr.is_ip6 = true; - memcpy(&dm->addr.ip6, &buf[ofs - 16], 16); + memcpy(&dm->addr.ip, &buf[ofs - 16], 16); dm->resolved = true; break; // Return success } diff --git a/src/net.c b/src/net.c index 285e46bf..f43dbe87 100644 --- a/src/net.c +++ b/src/net.c @@ -22,15 +22,16 @@ size_t mg_printf(struct mg_connection *c, const char *fmt, ...) { } static bool mg_atonl(struct mg_str str, struct mg_addr *addr) { + uint32_t localhost = mg_htonl(0x7f000001); if (mg_vcasecmp(&str, "localhost") != 0) return false; - addr->ip = mg_htonl(0x7f000001); + memcpy(addr->ip, &localhost, sizeof(uint32_t)); addr->is_ip6 = false; return true; } static bool mg_atone(struct mg_str str, struct mg_addr *addr) { if (str.len > 0) return false; - addr->ip = 0; + memset(addr->ip, 0, sizeof(addr->ip)); addr->is_ip6 = false; return true; } @@ -58,15 +59,18 @@ static bool mg_aton4(struct mg_str str, struct mg_addr *addr) { static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) { int i; + uint32_t ipv4; if (str.len < 14) return false; if (str.ptr[0] != ':' || str.ptr[1] != ':' || str.ptr[6] != ':') return false; for (i = 2; i < 6; i++) { if (str.ptr[i] != 'f' && str.ptr[i] != 'F') return false; } + //struct mg_str s = mg_str_n(&str.ptr[7], str.len - 7); if (!mg_aton4(mg_str_n(&str.ptr[7], str.len - 7), addr)) return false; - memset(addr->ip6, 0, sizeof(addr->ip6)); - addr->ip6[10] = addr->ip6[11] = 255; - memcpy(&addr->ip6[12], &addr->ip, 4); + memcpy(&ipv4, addr->ip, sizeof(ipv4)); + memset(addr->ip, 0, sizeof(addr->ip)); + addr->ip[10] = addr->ip[11] = 255; + memcpy(&addr->ip[12], &ipv4, 4); addr->is_ip6 = true; return true; } @@ -83,8 +87,8 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { if (i > j + 3) return false; // MG_DEBUG(("%zu %zu [%.*s]", i, j, (int) (i - j + 1), &str.ptr[j])); val = mg_unhexn(&str.ptr[j], i - j + 1); - addr->ip6[n] = (uint8_t) ((val >> 8) & 255); - addr->ip6[n + 1] = (uint8_t) (val & 255); + addr->ip[n] = (uint8_t) ((val >> 8) & 255); + addr->ip[n + 1] = (uint8_t) (val & 255); } else if (str.ptr[i] == ':') { j = i + 1; if (i > 0 && str.ptr[i - 1] == ':') { @@ -94,16 +98,17 @@ static bool mg_aton6(struct mg_str str, struct mg_addr *addr) { n += 2; } if (n > 14) return false; - addr->ip6[n] = addr->ip6[n + 1] = 0; // For trailing :: + addr->ip[n] = addr->ip[n + 1] = 0; // For trailing :: } else { return false; } } if (n < 14 && dc == 42) return false; if (n < 14) { - memmove(&addr->ip6[dc + (14 - n)], &addr->ip6[dc], n - dc + 2); - memset(&addr->ip6[dc], 0, 14 - n); + memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2); + memset(&addr->ip[dc], 0, 14 - n); } + addr->is_ip6 = true; return true; } diff --git a/src/net.h b/src/net.h index 3a2806db..fac5fe8f 100644 --- a/src/net.h +++ b/src/net.h @@ -13,10 +13,9 @@ struct mg_dns { }; struct mg_addr { - uint16_t port; // TCP or UDP port in network byte order - uint32_t ip; // IP address in network byte order - uint8_t ip6[16]; // IPv6 address - bool is_ip6; // True when address is IPv6 address + uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order + uint16_t port; // TCP or UDP port in network byte order + bool is_ip6; // True when address is IPv6 address }; struct mg_mgr { diff --git a/src/printf.c b/src/printf.c index f6ad86d6..d9998ccf 100644 --- a/src/printf.c +++ b/src/printf.c @@ -101,7 +101,7 @@ size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) { size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) { struct mg_addr *addr = va_arg(*ap, struct mg_addr *); - if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip6); + if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip); return print_ip4(out, arg, (uint8_t *) &addr->ip); } diff --git a/src/sock.c b/src/sock.c index d5ab7449..5a7ecf10 100644 --- a/src/sock.c +++ b/src/sock.c @@ -57,12 +57,12 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { memset(usa, 0, sizeof(*usa)); usa->sin.sin_family = AF_INET; usa->sin.sin_port = a->port; - *(uint32_t *) &usa->sin.sin_addr = a->ip; + memcpy(&usa->sin.sin_addr, a->ip, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (a->is_ip6) { usa->sin.sin_family = AF_INET6; usa->sin6.sin6_port = a->port; - memcpy(&usa->sin6.sin6_addr, a->ip6, sizeof(a->ip6)); + memcpy(&usa->sin6.sin6_addr, a->ip, sizeof(a->ip)); len = sizeof(usa->sin6); } #endif @@ -72,10 +72,10 @@ static socklen_t tousa(struct mg_addr *a, union usa *usa) { static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) { a->is_ip6 = is_ip6; a->port = usa->sin.sin_port; - memcpy(&a->ip, &usa->sin.sin_addr, sizeof(a->ip)); + memcpy(&a->ip, &usa->sin.sin_addr, sizeof(uint32_t)); #if MG_ENABLE_IPV6 if (is_ip6) { - memcpy(a->ip6, &usa->sin6.sin6_addr, sizeof(a->ip6)); + memcpy(a->ip, &usa->sin6.sin6_addr, sizeof(a->ip)); a->port = usa->sin6.sin6_port; } #endif diff --git a/src/tcpip/tcpip.c b/src/tcpip/tcpip.c index 3f5a970d..7d5c4411 100644 --- a/src/tcpip/tcpip.c +++ b/src/tcpip/tcpip.c @@ -308,7 +308,7 @@ static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (c != NULL && c->is_arplooking) { struct connstate *s = (struct connstate *) (c + 1); memcpy(s->mac, pkt->arp->sha, sizeof(s->mac)); - MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, &c->rem.ip, + MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip, mg_print_mac, s->mac)); c->is_arplooking = 0; } @@ -407,7 +407,7 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) { // No UDP listener on this port. Should send ICMP, but keep silent. } else { c->rem.port = pkt->udp->sport; - c->rem.ip = pkt->ip->src; + memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t)); struct connstate *s = (struct connstate *) (c + 1); memcpy(s->mac, pkt->eth->src, sizeof(s->mac)); if (c->recv.len >= MG_MAX_RECV_SIZE) { @@ -481,7 +481,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); memcpy(s->mac, pkt->eth->src, sizeof(s->mac)); settmout(c, MIP_TTYPE_KEEPALIVE); - c->rem.ip = pkt->ip->src; + memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t)); c->rem.port = pkt->tcp->sport; MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem)); LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c); @@ -500,17 +500,19 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn, long mg_io_send(struct mg_connection *c, const void *buf, size_t len) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (c->is_udp) { size_t max_headers_len = 14 + 24 /* max IP */ + 8 /* UDP */; if (len + max_headers_len > ifp->tx.len) { len = ifp->tx.len - max_headers_len; } - tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len); + tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len); } else { size_t max_headers_len = 14 + 24 /* max IP */ + 60 /* max TCP */; if (len + max_headers_len > ifp->tx.len) len = ifp->tx.len - max_headers_len; - if (tx_tcp(ifp, s->mac, c->rem.ip, TH_PUSH | TH_ACK, c->loc.port, + if (tx_tcp(ifp, s->mac, rem_ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len) > 0) { s->seq += (uint32_t) len; if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE); @@ -793,17 +795,19 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t uptime_ms) { if (c->is_udp || c->is_listening) continue; if (c->is_connecting || c->is_resolving) continue; struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (uptime_ms > s->timer) { if (s->ttype == MIP_TTYPE_ACK) { MG_DEBUG(("%lu ack %x %x", c->id, s->seq, s->ack)); - tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), "", 0); } else { if (s->tmiss++ > 2) { mg_error(c, "keepalive"); } else { MG_DEBUG(("%lu keepalive", c->id)); - tx_tcp(ifp, s->mac, c->rem.ip, TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq - 1), mg_htonl(s->ack), "", 0); } } @@ -871,32 +875,36 @@ static void send_syn(struct mg_connection *c) { struct connstate *s = (struct connstate *) (c + 1); uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port)); struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; - tx_tcp(ifp, s->mac, c->rem.ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL, + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); + tx_tcp(ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0, NULL, 0); } void mg_connect_resolved(struct mg_connection *c) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); c->is_resolving = 0; if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE; - c->loc.ip = ifp->ip; + memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t)); c->loc.port = mg_htons(ifp->eport++); MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port, &c->rem)); mg_call(c, MG_EV_RESOLVE, NULL); - if (((c->rem.ip & ifp->mask) == (ifp->ip & ifp->mask))) { + if (((rem_ip & ifp->mask) == (ifp->ip & ifp->mask))) { // If we're in the same LAN, fire an ARP lookup. TODO(cpq): handle this! MG_DEBUG(("%lu ARP lookup...", c->id)); - arp_ask(ifp, c->rem.ip); + arp_ask(ifp, rem_ip); c->is_arplooking = 1; - } else if (c->rem.ip == (ifp->ip | ~ifp->mask)) { + } else if (rem_ip == (ifp->ip | ~ifp->mask)) { struct connstate *s = (struct connstate *) (c + 1); memset(s->mac, 0xFF, sizeof(s->mac)); // local broadcast - } else if ((*((uint8_t *) &c->rem.ip) & 0xE0) == 0xE0) { + } else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) { struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group memcpy(s->mac, mcastp, 3); - memcpy(s->mac + 3, ((uint8_t *) &c->rem.ip) + 1, 3); // 23 LSb + memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3); // 23 LSb s->mac[3] &= 0x7F; } else { struct connstate *s = (struct connstate *) (c + 1); @@ -926,11 +934,13 @@ static void write_conn(struct mg_connection *c) { static void close_conn(struct mg_connection *c) { struct connstate *s = (struct connstate *) (c + 1); + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); mg_iobuf_free(&s->raw); // For TLS connections, release raw data if (c->is_udp == false && c->is_listening == false) { // For TCP conns, struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; // send TCP FIN - tx_tcp(ifp, s->mac, c->rem.ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port, + tx_tcp(ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port, c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0); } mg_close_conn(c); @@ -963,11 +973,13 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) { bool mg_send(struct mg_connection *c, const void *buf, size_t len) { struct mg_tcpip_if *ifp = (struct mg_tcpip_if *) c->mgr->priv; bool res = false; + uint32_t rem_ip; + memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) { mg_error(c, "net down"); } else if (c->is_udp) { struct connstate *s = (struct connstate *) (c + 1); - tx_udp(ifp, s->mac, ifp->ip, c->loc.port, c->rem.ip, c->rem.port, buf, len); + tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len); res = true; } else { res = mg_iobuf_add(&c->send, c->send.len, buf, len); diff --git a/test/unit_test.c b/test/unit_test.c index 4b3caa47..1acb23e3 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1892,12 +1892,20 @@ static void test_str(void) { { char buf[100]; - struct mg_addr a = {mg_htons(3), mg_htonl(0x2000001), {1, 100, 33}, false}; + struct mg_addr a; + uint32_t addr = mg_htonl(0x2000001); + memcpy(a.ip, &addr, sizeof(uint32_t)); + a.port = mg_htons(3); + a.is_ip6 = false; + ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 9); ASSERT(strcmp(buf, "2.0.0.1 7") == 0); ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip_port, &a, 7) == 11); ASSERT(strcmp(buf, "2.0.0.1:3 7") == 0); + + memset(a.ip, 0, sizeof(a.ip)); + a.ip[0] = 1, a.ip[1] = 100, a.ip[2] = 33; a.is_ip6 = true; ASSERT(mg_snprintf(buf, sizeof(buf), "%M %d", mg_print_ip, &a, 7) == 24); ASSERT(strcmp(buf, "[164:2100:0:0:0:0:0:0] 7") == 0); @@ -1985,6 +1993,7 @@ static void test_dns(void) { static void test_util(void) { char buf[100], *p, *s; struct mg_addr a; + uint32_t ipv4; memset(&a, 0, sizeof(a)); ASSERT(mg_file_printf(&mg_fs_posix, "data.txt", "%s", "hi") == true); // if (system("ls -l") != 0) (void) 0; @@ -1998,54 +2007,55 @@ static void test_util(void) { ASSERT(mg_aton(mg_str("0.0.0.-1"), &a) == false); ASSERT(mg_aton(mg_str("127.0.0.1"), &a) == true); ASSERT(a.is_ip6 == false); - ASSERT(a.ip == mg_htonl(0x7f000001)); + memcpy(&ipv4, a.ip, sizeof(ipv4)); + ASSERT(ipv4 == mg_htonl(0x7f000001)); ASSERT(mg_aton(mg_str("1:2:3:4:5:6:7:8"), &a) == true); ASSERT(a.is_ip6 == true); ASSERT( - memcmp(a.ip6, + memcmp(a.ip, "\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); - memset(a.ip6, 0xaa, sizeof(a.ip6)); + memset(a.ip, 0xaa, sizeof(a.ip)); ASSERT(mg_aton(mg_str("1::1"), &a) == true); ASSERT(a.is_ip6 == true); ASSERT( - memcmp(a.ip6, + memcmp(a.ip, "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); - memset(a.ip6, 0xaa, sizeof(a.ip6)); + memset(a.ip, 0xaa, sizeof(a.ip)); ASSERT(mg_aton(mg_str("::fFff:1.2.3.4"), &a) == true); ASSERT(a.is_ip6 == true); - ASSERT(memcmp(a.ip6, + ASSERT(memcmp(a.ip, "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\xff\xff\x01\x02\x03\x04", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); - memset(a.ip6, 0xaa, sizeof(a.ip6)); + memset(a.ip, 0xaa, sizeof(a.ip)); ASSERT(mg_aton(mg_str("::1"), &a) == true); ASSERT(a.is_ip6 == true); ASSERT( - memcmp(a.ip6, + memcmp(a.ip, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); - memset(a.ip6, 0xaa, sizeof(a.ip6)); + memset(a.ip, 0xaa, sizeof(a.ip)); ASSERT(mg_aton(mg_str("1::"), &a) == true); ASSERT(a.is_ip6 == true); ASSERT( - memcmp(a.ip6, + memcmp(a.ip, "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); - memset(a.ip6, 0xaa, sizeof(a.ip6)); + memset(a.ip, 0xaa, sizeof(a.ip)); ASSERT(mg_aton(mg_str("2001:4860:4860::8888"), &a) == true); ASSERT(a.is_ip6 == true); ASSERT( - memcmp(a.ip6, + memcmp(a.ip, "\x20\x01\x48\x60\x48\x60\x00\x00\x00\x00\x00\x00\x00\x00\x88\x88", - sizeof(a.ip6)) == 0); + sizeof(a.ip)) == 0); ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 0); ASSERT(mg_url_decode("a=%", 3, buf, sizeof(buf), 0) < 0);