From 93dd7a85f63bea5adb10409a4503b1a1465093f7 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Mon, 30 Sep 2024 12:12:37 +0100 Subject: [PATCH] Fix IP fragmentation checks for big-endian CPUs --- mongoose.c | 24 +++++++++-------------- mongoose.h | 11 ++++++++++- src/arch_rtthread.h | 48 ++++++++++++++++++++++----------------------- src/net_builtin.c | 14 +++++++------ src/tls_builtin.c | 10 +--------- src/util.h | 9 +++++++++ 6 files changed, 61 insertions(+), 55 deletions(-) diff --git a/mongoose.c b/mongoose.c index 9440a68b..2722dba7 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4970,8 +4970,8 @@ struct ip { uint16_t len; // Length uint16_t id; // Unused uint16_t frag; // Fragmentation -#define IP_FRAG_OFFSET_MSK 0xFF1F -#define IP_MORE_FRAGS_MSK 0x20 +#define IP_FRAG_OFFSET_MSK 0x1fff +#define IP_MORE_FRAGS_MSK 0x2000 uint8_t ttl; // Time to live uint8_t proto; // Upper level protocol uint16_t csum; // Checksum @@ -5145,8 +5145,8 @@ static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst, memcpy(eth->src, ifp->mac, sizeof(eth->src)); // Use our MAC eth->type = mg_htons(0x800); memset(ip, 0, sizeof(*ip)); - ip->ver = 0x45; // Version 4, header length 5 words - ip->frag = 0x40; // Don't fragment + ip->ver = 0x45; // Version 4, header length 5 words + ip->frag = mg_htons(0x4000); // Don't fragment ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->ttl = 64; ip->proto = proto; @@ -5706,7 +5706,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) { - if (pkt->ip->frag & IP_MORE_FRAGS_MSK || pkt->ip->frag & IP_FRAG_OFFSET_MSK) { + 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); @@ -5870,7 +5871,8 @@ 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; + 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; memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); @@ -9475,6 +9477,7 @@ int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input, + #if MG_TLS == MG_TLS_BUILTIN #define CHACHA20 1 @@ -9557,15 +9560,6 @@ struct tls_data { struct tls_enc enc; }; -#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) -#define MG_LOAD_BE24(p) \ - ((uint32_t) ((MG_U8P(p)[0] << 16U) | (MG_U8P(p)[1] << 8U) | MG_U8P(p)[2])) -#define MG_STORE_BE16(p, n) \ - do { \ - MG_U8P(p)[0] = ((n) >> 8U) & 255; \ - MG_U8P(p)[1] = (n) &255; \ - } while (0) - #define TLS_RECHDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes length #define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length diff --git a/mongoose.h b/mongoose.h index f8057e4d..2504160c 100644 --- a/mongoose.h +++ b/mongoose.h @@ -472,7 +472,7 @@ typedef enum { false = 0, true = 1 } bool; #pragma comment(lib, "advapi32.lib") #else #include -#if defined(_MSC_VER) +#if defined(_MSC_VER) #pragma comment(lib, "bcrypt.lib") #endif #endif @@ -1112,6 +1112,15 @@ bool mg_path_is_sane(const struct mg_str path); #define MG_IPADDR_PARTS(ADDR) \ MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] +#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) +#define MG_LOAD_BE24(p) \ + ((uint32_t) ((MG_U8P(p)[0] << 16U) | (MG_U8P(p)[1] << 8U) | MG_U8P(p)[2])) +#define MG_STORE_BE16(p, n) \ + do { \ + MG_U8P(p)[0] = ((n) >> 8U) & 255; \ + MG_U8P(p)[1] = (n) &255; \ + } while (0) + #define MG_REG(x) ((volatile uint32_t *) (x))[0] #define MG_BIT(x) (((uint32_t) 1U) << (x)) #define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK) diff --git a/src/arch_rtthread.h b/src/arch_rtthread.h index 937c4a33..962723e0 100644 --- a/src/arch_rtthread.h +++ b/src/arch_rtthread.h @@ -1,24 +1,24 @@ -#pragma once - -#if MG_ARCH == MG_ARCH_RTTHREAD - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MG_IO_SIZE -#define MG_IO_SIZE 1460 -#endif - -#endif // MG_ARCH == MG_ARCH_RTTHREAD +#pragma once + +#if MG_ARCH == MG_ARCH_RTTHREAD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MG_IO_SIZE +#define MG_IO_SIZE 1460 +#endif + +#endif // MG_ARCH == MG_ARCH_RTTHREAD diff --git a/src/net_builtin.c b/src/net_builtin.c index c46f637a..76c091ec 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -48,8 +48,8 @@ struct ip { uint16_t len; // Length uint16_t id; // Unused uint16_t frag; // Fragmentation -#define IP_FRAG_OFFSET_MSK 0xFF1F -#define IP_MORE_FRAGS_MSK 0x20 +#define IP_FRAG_OFFSET_MSK 0x1fff +#define IP_MORE_FRAGS_MSK 0x2000 uint8_t ttl; // Time to live uint8_t proto; // Upper level protocol uint16_t csum; // Checksum @@ -223,8 +223,8 @@ static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst, memcpy(eth->src, ifp->mac, sizeof(eth->src)); // Use our MAC eth->type = mg_htons(0x800); memset(ip, 0, sizeof(*ip)); - ip->ver = 0x45; // Version 4, header length 5 words - ip->frag = 0x40; // Don't fragment + ip->ver = 0x45; // Version 4, header length 5 words + ip->frag = mg_htons(0x4000); // Don't fragment ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->ttl = 64; ip->proto = proto; @@ -784,7 +784,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) { - if (pkt->ip->frag & IP_MORE_FRAGS_MSK || pkt->ip->frag & IP_FRAG_OFFSET_MSK) { + 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); @@ -948,7 +949,8 @@ 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; + 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; memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); diff --git a/src/tls_builtin.c b/src/tls_builtin.c index 9c4c585d..ca597f07 100644 --- a/src/tls_builtin.c +++ b/src/tls_builtin.c @@ -7,6 +7,7 @@ #include "tls_chacha20.h" #include "tls_uecc.h" #include "tls_x25519.h" +#include "util.h" #if MG_TLS == MG_TLS_BUILTIN @@ -90,15 +91,6 @@ struct tls_data { struct tls_enc enc; }; -#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) -#define MG_LOAD_BE24(p) \ - ((uint32_t) ((MG_U8P(p)[0] << 16U) | (MG_U8P(p)[1] << 8U) | MG_U8P(p)[2])) -#define MG_STORE_BE16(p, n) \ - do { \ - MG_U8P(p)[0] = ((n) >> 8U) & 255; \ - MG_U8P(p)[1] = (n) &255; \ - } while (0) - #define TLS_RECHDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes length #define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length diff --git a/src/util.h b/src/util.h index 78405946..7ae6f1a7 100644 --- a/src/util.h +++ b/src/util.h @@ -34,6 +34,15 @@ bool mg_path_is_sane(const struct mg_str path); #define MG_IPADDR_PARTS(ADDR) \ MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] +#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) +#define MG_LOAD_BE24(p) \ + ((uint32_t) ((MG_U8P(p)[0] << 16U) | (MG_U8P(p)[1] << 8U) | MG_U8P(p)[2])) +#define MG_STORE_BE16(p, n) \ + do { \ + MG_U8P(p)[0] = ((n) >> 8U) & 255; \ + MG_U8P(p)[1] = (n) &255; \ + } while (0) + #define MG_REG(x) ((volatile uint32_t *) (x))[0] #define MG_BIT(x) (((uint32_t) 1U) << (x)) #define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK)