Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IP fragmentation checks for big-endian CPUs #2919

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
11 changes: 10 additions & 1 deletion mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ typedef enum { false = 0, true = 1 } bool;
#pragma comment(lib, "advapi32.lib")
#else
#include <bcrypt.h>
#if defined(_MSC_VER)
#if defined(_MSC_VER)
#pragma comment(lib, "bcrypt.lib")
#endif
#endif
Expand Down Expand Up @@ -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)
Expand Down
48 changes: 24 additions & 24 deletions src/arch_rtthread.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
#pragma once

#if MG_ARCH == MG_ARCH_RTTHREAD

#include <rtthread.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#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 <rtthread.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#ifndef MG_IO_SIZE
#define MG_IO_SIZE 1460
#endif

#endif // MG_ARCH == MG_ARCH_RTTHREAD
14 changes: 8 additions & 6 deletions src/net_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Copy link
Collaborator

@robertc2000 robertc2000 Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The masks should also be in big endian order.

#define IP_FRAG_OFFSET_MSK 0x1FFF
#define IP_MORE_FRAGS_MSK 0x2000

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

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);
Expand Down Expand Up @@ -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));
Expand Down
10 changes: 1 addition & 9 deletions src/tls_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
9 changes: 9 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading