Fix IP fragmentation checks for big-endian CPUs

This commit is contained in:
Sergey Lyubka 2024-09-30 12:12:37 +01:00
parent 5af2de635e
commit 93dd7a85f6
6 changed files with 61 additions and 55 deletions

View File

@ -4970,8 +4970,8 @@ struct ip {
uint16_t len; // Length uint16_t len; // Length
uint16_t id; // Unused uint16_t id; // Unused
uint16_t frag; // Fragmentation uint16_t frag; // Fragmentation
#define IP_FRAG_OFFSET_MSK 0xFF1F #define IP_FRAG_OFFSET_MSK 0x1fff
#define IP_MORE_FRAGS_MSK 0x20 #define IP_MORE_FRAGS_MSK 0x2000
uint8_t ttl; // Time to live uint8_t ttl; // Time to live
uint8_t proto; // Upper level protocol uint8_t proto; // Upper level protocol
uint16_t csum; // Checksum 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 memcpy(eth->src, ifp->mac, sizeof(eth->src)); // Use our MAC
eth->type = mg_htons(0x800); eth->type = mg_htons(0x800);
memset(ip, 0, sizeof(*ip)); memset(ip, 0, sizeof(*ip));
ip->ver = 0x45; // Version 4, header length 5 words ip->ver = 0x45; // Version 4, header length 5 words
ip->frag = 0x40; // Don't fragment ip->frag = mg_htons(0x4000); // Don't fragment
ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
ip->ttl = 64; ip->ttl = 64;
ip->proto = proto; 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) { 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 == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1); if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
struct mg_connection *c = getpeer(ifp->mgr, pkt, false); 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 // Process timeouts
for (c = ifp->mgr->conns; c != NULL; c = c->next) { 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); struct connstate *s = (struct connstate *) (c + 1);
uint32_t rem_ip; uint32_t rem_ip;
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); 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 #if MG_TLS == MG_TLS_BUILTIN
#define CHACHA20 1 #define CHACHA20 1
@ -9557,15 +9560,6 @@ struct tls_data {
struct tls_enc enc; 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_RECHDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes length
#define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length #define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length

View File

@ -472,7 +472,7 @@ typedef enum { false = 0, true = 1 } bool;
#pragma comment(lib, "advapi32.lib") #pragma comment(lib, "advapi32.lib")
#else #else
#include <bcrypt.h> #include <bcrypt.h>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma comment(lib, "bcrypt.lib") #pragma comment(lib, "bcrypt.lib")
#endif #endif
#endif #endif
@ -1112,6 +1112,15 @@ bool mg_path_is_sane(const struct mg_str path);
#define MG_IPADDR_PARTS(ADDR) \ #define MG_IPADDR_PARTS(ADDR) \
MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] 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_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x)) #define MG_BIT(x) (((uint32_t) 1U) << (x))
#define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK) #define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK)

View File

@ -1,24 +1,24 @@
#pragma once #pragma once
#if MG_ARCH == MG_ARCH_RTTHREAD #if MG_ARCH == MG_ARCH_RTTHREAD
#include <rtthread.h> #include <rtthread.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/select.h> #include <sys/select.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#ifndef MG_IO_SIZE #ifndef MG_IO_SIZE
#define MG_IO_SIZE 1460 #define MG_IO_SIZE 1460
#endif #endif
#endif // MG_ARCH == MG_ARCH_RTTHREAD #endif // MG_ARCH == MG_ARCH_RTTHREAD

View File

@ -48,8 +48,8 @@ struct ip {
uint16_t len; // Length uint16_t len; // Length
uint16_t id; // Unused uint16_t id; // Unused
uint16_t frag; // Fragmentation uint16_t frag; // Fragmentation
#define IP_FRAG_OFFSET_MSK 0xFF1F #define IP_FRAG_OFFSET_MSK 0x1fff
#define IP_MORE_FRAGS_MSK 0x20 #define IP_MORE_FRAGS_MSK 0x2000
uint8_t ttl; // Time to live uint8_t ttl; // Time to live
uint8_t proto; // Upper level protocol uint8_t proto; // Upper level protocol
uint16_t csum; // Checksum 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 memcpy(eth->src, ifp->mac, sizeof(eth->src)); // Use our MAC
eth->type = mg_htons(0x800); eth->type = mg_htons(0x800);
memset(ip, 0, sizeof(*ip)); memset(ip, 0, sizeof(*ip));
ip->ver = 0x45; // Version 4, header length 5 words ip->ver = 0x45; // Version 4, header length 5 words
ip->frag = 0x40; // Don't fragment ip->frag = mg_htons(0x4000); // Don't fragment
ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen)); ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
ip->ttl = 64; ip->ttl = 64;
ip->proto = proto; 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) { 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 == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1); if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
struct mg_connection *c = getpeer(ifp->mgr, pkt, false); 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 // Process timeouts
for (c = ifp->mgr->conns; c != NULL; c = c->next) { 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); struct connstate *s = (struct connstate *) (c + 1);
uint32_t rem_ip; uint32_t rem_ip;
memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t)); memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));

View File

@ -7,6 +7,7 @@
#include "tls_chacha20.h" #include "tls_chacha20.h"
#include "tls_uecc.h" #include "tls_uecc.h"
#include "tls_x25519.h" #include "tls_x25519.h"
#include "util.h"
#if MG_TLS == MG_TLS_BUILTIN #if MG_TLS == MG_TLS_BUILTIN
@ -90,15 +91,6 @@ struct tls_data {
struct tls_enc enc; 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_RECHDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes length
#define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length #define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length

View File

@ -34,6 +34,15 @@ bool mg_path_is_sane(const struct mg_str path);
#define MG_IPADDR_PARTS(ADDR) \ #define MG_IPADDR_PARTS(ADDR) \
MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] 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_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x)) #define MG_BIT(x) (((uint32_t) 1U) << (x))
#define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK) #define MG_SET_BITS(R, CLRMASK, SETMASK) (R) = ((R) & ~(CLRMASK)) | (SETMASK)