make TCP/IP C89-friendly

This commit is contained in:
Sergio R. Caprile 2025-07-08 11:15:32 -03:00
parent 52ab6bc499
commit b3ee71acbe
6 changed files with 115 additions and 78 deletions

View File

@ -54,6 +54,18 @@ jobs:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0
mip89:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1 # no parallel runs, to minimize MQTT errors
matrix:
target: [mip_vc98]
name: mip89 ${{ matrix.target }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: make -C test ${{ matrix.target }}
s390:
runs-on: ubuntu-latest
strategy:

View File

@ -4327,7 +4327,7 @@ static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
static uint16_t csumfin(uint32_t sum) {
while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
return mg_htons(~sum & 0xffff);
return mg_htons((uint16_t) (~sum & 0xffff));
}
static uint16_t ipcsum(const void *buf, size_t len) {
@ -4414,12 +4414,13 @@ static bool tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
tx_ip(ifp, mac_dst, 17, ip_src, ip_dst, len + sizeof(struct udp));
struct udp *udp = (struct udp *) (ip + 1);
size_t eth_len;
uint32_t cs;
// MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len));
udp->sport = sport;
udp->dport = dport;
udp->len = mg_htons((uint16_t) (sizeof(*udp) + len));
udp->csum = 0;
uint32_t cs = csumup(0, udp, sizeof(*udp));
cs = csumup(0, udp, sizeof(*udp));
cs = csumup(cs, buf, len);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
@ -4503,7 +4504,8 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
break;
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
lsn == (bool) c->is_listening &&
(lsn || c->rem.port == pkt->tcp->sport))
break;
}
return c;
@ -4558,10 +4560,12 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
struct ip *ip;
struct icmp *icmp;
if (plen > space) plen = space;
struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
sizeof(struct icmp) + plen);
struct icmp *icmp = (struct icmp *) (ip + 1);
ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
sizeof(*icmp) + plen);
icmp = (struct icmp *) (ip + 1);
memset(icmp, 0, sizeof(*icmp)); // Set csum to 0
memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX
icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
@ -4608,13 +4612,13 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
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
uint64_t rand;
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_IP; // BOUND state
uint64_t rand;
mg_random(&rand, sizeof(rand));
srand((unsigned int) (rand + mg_millis()));
if (ifp->enable_req_dns && dns != 0)
@ -4633,9 +4637,9 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
uint8_t op = 0, *p = pkt->dhcp->options,
*end = (uint8_t *) &pkt->raw.buf[pkt->raw.len];
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
// struct dhcp *req = pkt->dhcp;
struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
res.yiaddr = ifp->ip;
((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
while (p + 1 < end && p[0] != 255) { // Parse options
@ -4674,9 +4678,9 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
if (c == NULL) {
// No UDP listener on this port. Should send ICMP, but keep silent.
} else {
struct connstate *s = (struct connstate *) (c + 1);
c->rem.port = pkt->udp->sport;
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) {
mg_error(c, "max_recv_buf_size reached");
@ -4697,9 +4701,9 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
struct ip *ip;
struct tcp *tcp;
uint16_t opts[4 / 2];
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
opts[1] = mg_htons(ifp->mtu - 40); // RFC-6691
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
opts[1] = mg_htons((uint16_t) (ifp->mtu - 40)); // RFC-6691
buf = opts;
len = sizeof(opts);
}
@ -4715,15 +4719,16 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
tcp->win = mg_htons(MIP_TCP_WIN);
tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
if (flags & TH_SYN) tcp->off += (uint8_t) (sizeof(opts) / 4 << 4);
uint32_t cs = 0;
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
cs = csumup(cs, tcp, n);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
cs = csumup(cs, pseudo, sizeof(pseudo));
tcp->csum = csumfin(cs);
{
uint32_t cs = 0;
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
cs = csumup(cs, tcp, n);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
cs = csumup(cs, pseudo, sizeof(pseudo));
tcp->csum = csumfin(cs);
}
MG_VERBOSE(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst,
mg_ntohs(tcp->dport), tcp->flags, len));
@ -4743,11 +4748,12 @@ static size_t tx_tcp_pkt(struct mg_tcpip_if *ifp, struct pkt *pkt,
static struct mg_connection *accept_conn(struct mg_connection *lsn,
struct pkt *pkt) {
struct mg_connection *c = mg_alloc_conn(lsn->mgr);
struct connstate *s;
if (c == NULL) {
MG_ERROR(("OOM"));
return NULL;
}
struct connstate *s = (struct connstate *) (c + 1);
s = (struct connstate *) (c + 1);
s->dmss = 536; // assume default, RFC-9293 3.7.1
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
@ -5005,10 +5011,10 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
uint16_t frag = mg_ntohs(pkt->ip->frag);
if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
if (c) mg_error(c, "Received fragmented packet");
if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
} else if (pkt->ip->proto == 1) {
pkt->icmp = (struct icmp *) (pkt->ip + 1);
if (pkt->pay.len < sizeof(*pkt->icmp)) return;
@ -5033,11 +5039,12 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
rx_udp(ifp, pkt);
}
} else if (pkt->ip->proto == 6) {
uint16_t iplen, off;
pkt->tcp = (struct tcp *) (pkt->ip + 1);
if (pkt->pay.len < sizeof(*pkt->tcp)) return;
mkpay(pkt, pkt->tcp + 1);
uint16_t iplen = mg_ntohs(pkt->ip->len);
uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
iplen = mg_ntohs(pkt->ip->len);
off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
@ -5075,8 +5082,9 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
return;
if (ifp->enable_crc32_check && len > 4) {
uint32_t crc;
len -= 4; // TODO(scaprile): check on bigendian
uint32_t crc = mg_crc32(0, (const char *) buf, len);
crc = mg_crc32(0, (const char *) buf, len);
if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
}
if (pkt.eth->type == mg_htons(0x806)) {
@ -5185,10 +5193,10 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
// Process timeouts
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
continue;
struct connstate *s = (struct connstate *) (c + 1);
uint32_t rem_ip;
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
continue;
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
if (ifp->now > s->timer) {
if (s->ttype == MIP_TTYPE_ARP) {
@ -5386,10 +5394,10 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
mg_tcpip_poll(mgr->ifp, now);
for (c = mgr->conns; c != NULL; c = tmp) {
tmp = c->next;
struct connstate *s = (struct connstate *) (c + 1);
bool is_tls = c->is_tls && !c->is_resolving && !c->is_arplooking &&
!c->is_listening && !c->is_connecting;
tmp = c->next;
mg_call(c, MG_EV_POLL, &now);
MG_VERBOSE(("%lu .. %c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
@ -22062,8 +22070,8 @@ struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
#endif
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
MG_PHY_DP83x = 0x2000,
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
@ -22071,7 +22079,7 @@ enum { // ID1 ID2
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
MG_PHY_RTL8201 = 0x1C, // 001c c816 - RTL8201,
MG_PHY_ICS1894x = 0x15,
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
};
enum {
@ -22144,11 +22152,13 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
} else if (id1 == MG_PHY_KSZ8x) {
// Disable isolation (override hw, it doesn't make sense at this point)
phy->write_reg( // #2848, some NXP boards set ISO, even though
phy_addr, MG_PHY_REG_BCR, // docs say they don't
phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
// - #2848, some NXP boards set ISO, even though docs say they don't
phy->write_reg(phy_addr, MG_PHY_REG_BCR,
(uint16_t) (phy->read_reg(phy_addr, MG_PHY_REG_BCR) &
(uint16_t) ~MG_BIT(10)));
// now do clock stuff
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R,
(uint16_t) (MG_BIT(15) | MG_BIT(8) | MG_BIT(7)));
} else if (id1 == MG_PHY_LAN87x) {
// nothing to do
} else if (id1 == MG_PHY_RTL8201) {

View File

@ -1,7 +1,7 @@
#include "phy.h"
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
MG_PHY_DP83x = 0x2000,
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
@ -9,7 +9,7 @@ enum { // ID1 ID2
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
MG_PHY_RTL8201 = 0x1C, // 001c c816 - RTL8201,
MG_PHY_ICS1894x = 0x15,
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
};
enum {
@ -82,11 +82,13 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
} else if (id1 == MG_PHY_KSZ8x) {
// Disable isolation (override hw, it doesn't make sense at this point)
phy->write_reg( // #2848, some NXP boards set ISO, even though
phy_addr, MG_PHY_REG_BCR, // docs say they don't
phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
// - #2848, some NXP boards set ISO, even though docs say they don't
phy->write_reg(phy_addr, MG_PHY_REG_BCR,
(uint16_t) (phy->read_reg(phy_addr, MG_PHY_REG_BCR) &
(uint16_t) ~MG_BIT(10)));
// now do clock stuff
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R,
(uint16_t) (MG_BIT(15) | MG_BIT(8) | MG_BIT(7)));
} else if (id1 == MG_PHY_LAN87x) {
// nothing to do
} else if (id1 == MG_PHY_RTL8201) {

View File

@ -161,7 +161,7 @@ static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
static uint16_t csumfin(uint32_t sum) {
while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
return mg_htons(~sum & 0xffff);
return mg_htons((uint16_t) ((uint16_t) ~sum & 0xffff));
}
static uint16_t ipcsum(const void *buf, size_t len) {
@ -248,12 +248,13 @@ static bool tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
tx_ip(ifp, mac_dst, 17, ip_src, ip_dst, len + sizeof(struct udp));
struct udp *udp = (struct udp *) (ip + 1);
size_t eth_len;
uint32_t cs;
// MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len));
udp->sport = sport;
udp->dport = dport;
udp->len = mg_htons((uint16_t) (sizeof(*udp) + len));
udp->csum = 0;
uint32_t cs = csumup(0, udp, sizeof(*udp));
cs = csumup(0, udp, sizeof(*udp));
cs = csumup(cs, buf, len);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
@ -337,7 +338,8 @@ static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
break;
if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
lsn == (bool) c->is_listening &&
(lsn || c->rem.port == pkt->tcp->sport))
break;
}
return c;
@ -392,10 +394,12 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
struct ip *ip;
struct icmp *icmp;
if (plen > space) plen = space;
struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
sizeof(struct icmp) + plen);
struct icmp *icmp = (struct icmp *) (ip + 1);
ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
sizeof(*icmp) + plen);
icmp = (struct icmp *) (ip + 1);
memset(icmp, 0, sizeof(*icmp)); // Set csum to 0
memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX
icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
@ -442,13 +446,13 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
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
uint64_t rand;
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_IP; // BOUND state
uint64_t rand;
mg_random(&rand, sizeof(rand));
srand((unsigned int) (rand + mg_millis()));
if (ifp->enable_req_dns && dns != 0)
@ -467,9 +471,9 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
uint8_t op = 0, *p = pkt->dhcp->options,
*end = (uint8_t *) &pkt->raw.buf[pkt->raw.len];
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
// struct dhcp *req = pkt->dhcp;
struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
if (end < (uint8_t *) (pkt->dhcp + 1)) return;
res.yiaddr = ifp->ip;
((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
while (p + 1 < end && p[0] != 255) { // Parse options
@ -508,9 +512,9 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
if (c == NULL) {
// No UDP listener on this port. Should send ICMP, but keep silent.
} else {
struct connstate *s = (struct connstate *) (c + 1);
c->rem.port = pkt->udp->sport;
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) {
mg_error(c, "max_recv_buf_size reached");
@ -531,9 +535,9 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
struct ip *ip;
struct tcp *tcp;
uint16_t opts[4 / 2];
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
opts[1] = mg_htons(ifp->mtu - 40); // RFC-6691
if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
opts[1] = mg_htons((uint16_t) (ifp->mtu - 40)); // RFC-6691
buf = opts;
len = sizeof(opts);
}
@ -549,15 +553,16 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
tcp->win = mg_htons(MIP_TCP_WIN);
tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
if (flags & TH_SYN) tcp->off += (uint8_t) (sizeof(opts) / 4 << 4);
uint32_t cs = 0;
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
cs = csumup(cs, tcp, n);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
cs = csumup(cs, pseudo, sizeof(pseudo));
tcp->csum = csumfin(cs);
{
uint32_t cs = 0;
uint16_t n = (uint16_t) (sizeof(*tcp) + len);
uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
cs = csumup(cs, tcp, n);
cs = csumup(cs, &ip->src, sizeof(ip->src));
cs = csumup(cs, &ip->dst, sizeof(ip->dst));
cs = csumup(cs, pseudo, sizeof(pseudo));
tcp->csum = csumfin(cs);
}
MG_VERBOSE(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst,
mg_ntohs(tcp->dport), tcp->flags, len));
@ -577,11 +582,12 @@ static size_t tx_tcp_pkt(struct mg_tcpip_if *ifp, struct pkt *pkt,
static struct mg_connection *accept_conn(struct mg_connection *lsn,
struct pkt *pkt) {
struct mg_connection *c = mg_alloc_conn(lsn->mgr);
struct connstate *s;
if (c == NULL) {
MG_ERROR(("OOM"));
return NULL;
}
struct connstate *s = (struct connstate *) (c + 1);
s = (struct connstate *) (c + 1);
s->dmss = 536; // assume default, RFC-9293 3.7.1
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
@ -839,10 +845,10 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
uint16_t frag = mg_ntohs(pkt->ip->frag);
if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
if (c) mg_error(c, "Received fragmented packet");
if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
} else if (pkt->ip->proto == 1) {
pkt->icmp = (struct icmp *) (pkt->ip + 1);
if (pkt->pay.len < sizeof(*pkt->icmp)) return;
@ -867,11 +873,12 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
rx_udp(ifp, pkt);
}
} else if (pkt->ip->proto == 6) {
uint16_t iplen, off;
pkt->tcp = (struct tcp *) (pkt->ip + 1);
if (pkt->pay.len < sizeof(*pkt->tcp)) return;
mkpay(pkt, pkt->tcp + 1);
uint16_t iplen = mg_ntohs(pkt->ip->len);
uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
iplen = mg_ntohs(pkt->ip->len);
off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
@ -909,8 +916,9 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
return;
if (ifp->enable_crc32_check && len > 4) {
uint32_t crc;
len -= 4; // TODO(scaprile): check on bigendian
uint32_t crc = mg_crc32(0, (const char *) buf, len);
crc = mg_crc32(0, (const char *) buf, len);
if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
}
if (pkt.eth->type == mg_htons(0x806)) {
@ -1019,10 +1027,10 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
// Process timeouts
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
continue;
struct connstate *s = (struct connstate *) (c + 1);
uint32_t rem_ip;
if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
continue;
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
if (ifp->now > s->timer) {
if (s->ttype == MIP_TTYPE_ARP) {
@ -1220,10 +1228,10 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
mg_tcpip_poll(mgr->ifp, now);
for (c = mgr->conns; c != NULL; c = tmp) {
tmp = c->next;
struct connstate *s = (struct connstate *) (c + 1);
bool is_tls = c->is_tls && !c->is_resolving && !c->is_arplooking &&
!c->is_listening && !c->is_connecting;
tmp = c->next;
mg_call(c, MG_EV_POLL, &now);
MG_VERBOSE(("%lu .. %c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',

View File

@ -91,6 +91,10 @@ mip_tap_test: mip_tap_test.c mongoose.c mongoose.h packed_fs.c Makefile tls_mult
$(CC) mip_tap_test.c packed_fs.c $(CFLAGS) $(LDFLAGS) -o $@
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
mip_vc98: mip_test.c mongoose.c mongoose.h packed_fs.c Makefile
$(DOCKER) mdashnet/vc98 wine cl mip_test.c packed_fs.c $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc98 wine $@.exe
packed_fs.c: Makefile data/ssi.h fuzz.c data/a.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key
$(CC) $(CFLAGS) pack.c -o pack
$(RUN) ./pack Makefile data/ssi.h fuzz.c data/a.txt data/range.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key certs/client.key certs/client.crt > $@

View File

@ -74,9 +74,9 @@ static void frag_send_fn(struct mg_connection *c, int ev, void *ev_data) {
static void test_poll(void) {
int count = 0, i;
struct mg_tcpip_if mif;
struct mg_mgr mgr;
mg_mgr_init(&mgr);
struct mg_tcpip_if mif;
memset(&mif, 0, sizeof(mif));
mif.driver = &mg_tcpip_driver_mock;
mg_tcpip_init(&mgr, &mif);
@ -295,6 +295,7 @@ static void test_frag_send_path(void) {
struct mg_mgr mgr;
struct mg_tcpip_driver driver;
struct mg_tcpip_if mif;
unsigned int i;
mg_mgr_init(&mgr);
memset(&mif, 0, sizeof(mif));
@ -307,7 +308,7 @@ static void test_frag_send_path(void) {
mif.mtu = 500; // force ad hoc small MTU to fragment IP
mg_http_listen(&mgr, "http://0.0.0.0:0", frag_send_fn, NULL);
mgr.conns->pfn = NULL;
for (int i = 0; i < 10; i++) mg_mgr_poll(&mgr, 0);
for (i = 0; i < 10; i++) mg_mgr_poll(&mgr, 0);
ASSERT(s_seg_sent == 3);
s_driver_data.len = 0;
mg_mgr_free(&mgr);