From 7ae8f000f87ad1ea5d56e5041efa5b276b65c679 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 12 Nov 2025 18:36:47 +0100 Subject: [PATCH 1/3] First draft for wolfSentry integration, WIP --- Makefile | 17 +- config.h | 4 + src/test/ipfilter_logger.c | 393 +++++++++++++++++++++++++++++++++++++ src/wolfip.c | 381 +++++++++++++++++++++++++++++++---- wolfip-filter.h | 67 +++++++ wolfip.h | 25 ++- 6 files changed, 845 insertions(+), 42 deletions(-) create mode 100644 src/test/ipfilter_logger.c create mode 100644 wolfip-filter.h diff --git a/Makefile b/Makefile index c2fd74e..e2e554e 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,9 @@ CPPCHECK_FLAGS=--enable=warning,performance,portability,missingInclude \ OBJ=build/wolfip.o \ $(TAP_OBJ) +IPFILTER_OBJ=build/ipfilter/wolfip.o \ + $(TAP_OBJ) + HAVE_WOLFSSL:=$(shell printf "#include \nint main(void){return 0;}\n" | $(CC) $(CFLAGS) -x c - -c -o /dev/null 2>/dev/null && echo 1) # Require wolfSSL unless the requested goals are wolfSSL-independent (unit/cppcheck/clean). @@ -115,7 +118,8 @@ endif EXE=build/tcpecho build/tcp_netcat_poll build/tcp_netcat_select \ build/test-evloop build/test-dns build/test-wolfssl-forwarding \ - build/test-ttl-expired build/test-wolfssl build/test-httpd + build/test-ttl-expired build/test-wolfssl build/test-httpd \ + build/ipfilter-logger LIB=libwolfip.so PREFIX=/usr/local @@ -192,6 +196,17 @@ build/test-wolfssl: $(OBJ) build/test/test_native_wolfssl.o build/port/wolfssl_i @echo "[LD] $@" @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(BEGIN_GROUP) $(^) -lwolfssl $(END_GROUP) +build/ipfilter-logger: $(IPFILTER_OBJ) build/test/ipfilter_logger.o build/port/wolfssl_io.o build/certs/server_key.o build/certs/ca_cert.o build/certs/server_cert.o + @echo "[LD] $@" + @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(BEGIN_GROUP) $(^) -lwolfssl $(END_GROUP) + +build/ipfilter/wolfip.o: src/wolfip.c + @mkdir -p `dirname $@` || true + @echo "[CC] $< (ipfilter)" + @$(CC) $(CFLAGS) -DCONFIG_IPFILTER=1 -c $< -o $@ + +build/test/ipfilter_logger.o: CFLAGS+=-DCONFIG_IPFILTER=1 + build/test-wolfssl-forwarding: build/test/test_wolfssl_forwarding.o build/test/wolfip_forwarding.o $(TAP_OBJ) build/port/wolfssl_io.o build/certs/server_key.o build/certs/ca_cert.o build/certs/server_cert.o @echo "[LD] $@" @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(BEGIN_GROUP) $(^) -lwolfssl $(END_GROUP) diff --git a/config.h b/config.h index c08cb14..bda8ff8 100644 --- a/config.h +++ b/config.h @@ -1,6 +1,10 @@ #ifndef WOLF_CONFIG_H #define WOLF_CONFIG_H +#ifndef CONFIG_IPFILTER +#define CONFIG_IPFILTER 0 +#endif + #define ETHERNET #define LINK_MTU 1536 diff --git a/src/test/ipfilter_logger.c b/src/test/ipfilter_logger.c new file mode 100644 index 0000000..06ceba1 --- /dev/null +++ b/src/test/ipfilter_logger.c @@ -0,0 +1,393 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "wolfip.h" +#include +#include +#include + +#if !CONFIG_IPFILTER +#error "ipfilter_logger requires CONFIG_IPFILTER=1" +#endif + +#define TEST_SIZE (8 * 1024) +#define BUFFER_SIZE TEST_SIZE + +#define WI_IPPROTO_ICMP 0x01 +#define WI_IPPROTO_TCP 0x06 +#define WI_IPPROTO_UDP 0x11 + +static int listen_fd = -1, client_fd = -1; +static int exit_ok = 0, exit_count = 0; +static uint8_t buf[TEST_SIZE]; +static int tot_sent = 0; +static int tot_recv = 0; +static int wolfIP_closing = 0; +static int closed = 0; +static const uint8_t test_pattern[16] = "Test pattern - -"; + +static WOLFSSL_CTX *server_ctx = NULL; /* Used by wolfIP */ +static WOLFSSL_CTX *client_ctx = NULL; /* Used by Linux */ +static WOLFSSL *client_ssl = NULL; +static WOLFSSL *server_ssl = NULL; + +extern int wolfSSL_SetIO_wolfIP(WOLFSSL* ssl, int fd); +extern int wolfSSL_SetIO_wolfIP_CTX(WOLFSSL_CTX *ctx, struct wolfIP *s); + +extern const unsigned char ca_der[]; +extern const unsigned long ca_der_len; +extern const unsigned char server_der[]; +extern const unsigned long server_der_len; +extern const unsigned char server_key_der[]; +extern const unsigned long server_key_der_len; + +extern int tap_init(struct wolfIP_ll_dev *dev, const char *name, uint32_t host_ip); + +static const char *filter_reason_str(enum wolfIP_filter_reason reason) +{ + static const char *names[] = { + "BINDING", "DISSOCIATE", "LISTENING", "STOP_LISTENING", + "CONNECTING", "ACCEPTING", "CLOSED", "REMOTE_RESET", + "RECEIVING", "SENDING", "ADDR_UNREACHABLE", "PORT_UNREACHABLE", + "INBOUND_ERR", "OUTBOUND_ERR", "CLOSE_WAIT" + }; + if ((unsigned)reason < (sizeof(names) / sizeof(names[0]))) + return names[reason]; + return "UNKNOWN"; +} + +static void mac_to_str(const uint8_t mac[6], char *buf, size_t len) +{ + snprintf(buf, len, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + +static void ip_to_str(uint32_t net_ip, char *buf, size_t len) +{ + ip4 host_ip = ee32(net_ip); + iptoa(host_ip, buf); + buf[len - 1] = '\0'; +} + +static void log_ports(uint8_t proto, const struct wolfIP_filter_metadata *meta) +{ + if (proto == 0) + return; + if (proto == WI_IPPROTO_TCP) { + printf(" tcp=%u->%u flags=0x%02x", + ee16(meta->l4.tcp.src_port), + ee16(meta->l4.tcp.dst_port), + meta->l4.tcp.flags); + } else if (proto == WI_IPPROTO_UDP) { + printf(" udp=%u->%u", + ee16(meta->l4.udp.src_port), + ee16(meta->l4.udp.dst_port)); + } else if (proto == WI_IPPROTO_ICMP) { + printf(" icmp type=%u code=%u", + meta->l4.icmp.type, + meta->l4.icmp.code); + } +} + +static int filter_logger_cb(void *arg, const struct wolfIP_filter_event *event) +{ + char src_ip[16], dst_ip[16], src_mac[18], dst_mac[18]; + (void)arg; + ip_to_str(event->meta.src_ip, src_ip, sizeof(src_ip)); + ip_to_str(event->meta.dst_ip, dst_ip, sizeof(dst_ip)); + mac_to_str(event->meta.src_mac, src_mac, sizeof(src_mac)); + mac_to_str(event->meta.dst_mac, dst_mac, sizeof(dst_mac)); + + printf("[ipfilter] reason=%s if=%u len=%" PRIu32 + " ip=%s->%s mac=%s->%s proto=%u", + filter_reason_str(event->reason), + event->if_idx, + event->length, + src_ip, + dst_ip, + src_mac, + dst_mac, + event->meta.ip_proto); + log_ports(event->meta.ip_proto, &event->meta); + printf("\n"); + + fflush(stdout); + return 0; +} + +static void register_filter_logger(void) +{ + wolfIP_filter_set_callback(filter_logger_cb, NULL); + wolfIP_filter_set_mask(~0U); +} + +static void server_cb(int fd, uint16_t event, void *arg) +{ + int ret = 0; + if ((fd == listen_fd) && (event & CB_EVENT_READABLE) && (client_fd == -1)) { + client_fd = wolfIP_sock_accept((struct wolfIP *)arg, listen_fd, NULL, NULL); + if (client_fd > 0) { + printf("accept: Client FD is 0x%04x\n", client_fd); + server_ssl = wolfSSL_new(server_ctx); + if (!server_ssl) { + printf("Failed to create server SSL object\n"); + return; + } + wolfSSL_SetIO_wolfIP(server_ssl, client_fd); + printf("Server: TCP connection established\n"); + } + } else if ((fd == client_fd) && (event & CB_EVENT_READABLE)) { + ret = wolfSSL_read(server_ssl, buf, sizeof(buf)); + if (ret < 0) { + ret = wolfSSL_get_error(server_ssl, 0); + if (ret != WOLFSSL_ERROR_WANT_READ) { + printf("Recv error: %d\n", ret); + wolfIP_sock_close((struct wolfIP *)arg, client_fd); + } + } else if (ret == 0) { + printf("Client side closed the connection.\n"); + wolfIP_sock_close((struct wolfIP *)arg, client_fd); + printf("Server: Exiting.\n"); + exit_ok = 1; + } else { + printf("recv: %d, echoing back\n", ret); + tot_recv += ret; + } + } + if ((event & CB_EVENT_WRITABLE) || ((ret > 0) && !closed)) { + int snd_ret; + if ((tot_sent >= 4096) && wolfIP_closing) { + wolfIP_sock_close((struct wolfIP *)arg, client_fd); + printf("Server: I closed the connection.\n"); + closed = 1; + exit_ok = 1; + } + if ((!closed) && (tot_sent < tot_recv)) { + snd_ret = wolfSSL_write(server_ssl, buf + tot_sent, tot_recv - tot_sent); + if (snd_ret != WANT_WRITE) { + if (snd_ret < 0) { + printf("Send error: %d\n", snd_ret); + wolfSSL_free(server_ssl); + wolfIP_sock_close((struct wolfIP *)arg, client_fd); + } else { + tot_sent += snd_ret; + printf("sent %d bytes\n", snd_ret); + if (tot_recv == tot_sent) { + tot_sent = 0; + tot_recv = 0; + } + } + } + } + } + if (event & CB_EVENT_CLOSED) { + printf("Closing %d, client fd: %d\n", fd, client_fd); + wolfSSL_free(server_ssl); + server_ssl = NULL; + } + if ((fd == client_fd) && (event & CB_EVENT_CLOSED)) { + printf("Client side closed the connection (EVENT_CLOSED)\n"); + wolfSSL_free(server_ssl); + wolfIP_sock_close((struct wolfIP *)arg, client_fd); + client_fd = -1; + printf("Server: Exiting.\n"); + exit_ok = 1; + } +} + +static int test_loop(struct wolfIP *s, int active_close) +{ + exit_ok = 0; + exit_count = 0; + tot_sent = 0; + wolfIP_closing = active_close; + closed = 0; + + while (1) { + uint32_t ms_next; + struct timeval tv; + gettimeofday(&tv, NULL); + ms_next = wolfIP_poll(s, tv.tv_sec * 1000 + tv.tv_usec / 1000); + usleep(ms_next * 1000); + if (exit_ok > 0) { + if (exit_count++ < 10) + continue; + else + break; + } + } + return 0; +} + +static void *pt_echoclient(void *arg) +{ + int fd, ret; + unsigned total_r = 0; + unsigned i; + uint8_t local_buf[BUFFER_SIZE]; + uint32_t *srv_addr = (uint32_t *)arg; + struct sockaddr_in remote_sock = { + .sin_family = AF_INET, + .sin_port = ntohs(8), /* Echo */ + }; + + client_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + if (!client_ctx) { + printf("Failed to create client context\n"); + return (void *)-1; + } + + client_ssl = wolfSSL_new(client_ctx); + if (!client_ssl) { + printf("Failed to create client SSL object\n"); + return (void *)-1; + } + + wolfSSL_CTX_load_verify_buffer(client_ctx, ca_der, ca_der_len, SSL_FILETYPE_ASN1); + + remote_sock.sin_addr.s_addr = *srv_addr; + fd = socket(AF_INET, IPSTACK_SOCK_STREAM, 0); + if (fd < 0) { + perror("test client socket"); + return (void *)-1; + } + wolfSSL_set_fd(client_ssl, fd); + sleep(1); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); + printf("Connecting to echo server\n"); + ret = connect(fd, (struct sockaddr *)&remote_sock, sizeof(remote_sock)); + if (ret < 0) { + perror("test client connect"); + return (void *)-1; + } + printf("Linux client: TCP connection established\n"); + ret = wolfSSL_connect(client_ssl); + if (ret != SSL_SUCCESS) { + printf("Linux client: Failed to connect to TLS server, err: %d\n", ret); + return (void *)-1; + } + for (i = 0; i < sizeof(local_buf); i += sizeof(test_pattern)) { + memcpy(local_buf + i, test_pattern, sizeof(test_pattern)); + } + ret = wolfSSL_write(client_ssl, local_buf, sizeof(local_buf)); + if (ret < 0) { + printf("test client write: %d\n", ret); + return (void *)-1; + } + while (total_r < sizeof(local_buf)) { + ret = wolfSSL_read(client_ssl, local_buf + total_r, sizeof(local_buf) - total_r); + if (ret <= 0) { + printf("test client read error: %d\n", ret); + return (void *)-1; + } + total_r += ret; + } + for (i = 0; i < sizeof(local_buf); i += sizeof(test_pattern)) { + if (memcmp(local_buf + i, test_pattern, sizeof(test_pattern))) { + printf("test client: pattern mismatch at %u\n", i); + return (void *)-1; + } + } + client_ssl = NULL; + close(fd); + printf("Test client: success\n"); + wolfSSL_free(client_ssl); + return (void *)0; +} + +static void run_ipfilter_logger(struct wolfIP *s, uint32_t srv_ip) +{ + int ret, test_ret = 0; + pthread_t pt; + struct wolfIP_sockaddr_in local_sock = { + .sin_family = AF_INET, + .sin_port = ee16(8), /* Echo */ + .sin_addr.s_addr = 0 + }; + printf("Starting TLS echo server with filter logger\n"); + + server_ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); + if (!server_ctx) { + printf("Failed to create server context\n"); + return; + } + wolfSSL_SetIO_wolfIP_CTX(server_ctx, s); + + wolfSSL_CTX_use_certificate_buffer(server_ctx, server_der, server_der_len, SSL_FILETYPE_ASN1); + wolfSSL_CTX_use_PrivateKey_buffer(server_ctx, server_key_der, server_key_der_len, SSL_FILETYPE_ASN1); + + listen_fd = wolfIP_sock_socket(s, AF_INET, IPSTACK_SOCK_STREAM, 0); + wolfIP_register_callback(s, listen_fd, server_cb, s); + + ret = wolfIP_sock_bind(s, listen_fd, (struct wolfIP_sockaddr *)&local_sock, sizeof(local_sock)); + printf("bind: %d\n", ret); + ret = wolfIP_sock_listen(s, listen_fd, 1); + printf("listen: %d\n", ret); + + pthread_create(&pt, NULL, pt_echoclient, &srv_ip); + ret = test_loop(s, 0); + pthread_join(pt, (void **)&test_ret); + printf("ipfilter logger server ret=%d client=%d\n", ret, test_ret); + + wolfIP_sock_close(s, listen_fd); +} + +int main(int argc, char **argv) +{ + struct wolfIP *s; + struct wolfIP_ll_dev *tapdev; + struct in_addr host_stack_ip; + uint32_t srv_ip; +#ifdef DHCP + ip4 ip = 0, nm = 0, gw = 0; + struct timeval tv = {0, 0}; +#endif + + (void)argc; + (void)argv; + wolfSSL_Init(); + wolfSSL_Debugging_OFF(); + + wolfIP_init_static(&s); + register_filter_logger(); + + tapdev = wolfIP_getdev(s); + if (!tapdev) + return 1; + inet_aton(HOST_STACK_IP, &host_stack_ip); + if (tap_init(tapdev, "wtcp0", host_stack_ip.s_addr) < 0) { + perror("tap init"); + return 2; + } + +#ifdef DHCP + gettimeofday(&tv, NULL); + wolfIP_poll(s, tv.tv_sec * 1000 + tv.tv_usec / 1000); + dhcp_client_init(s); + do { + gettimeofday(&tv, NULL); + wolfIP_poll(s, tv.tv_sec * 1000 + tv.tv_usec / 1000); + usleep(1000); + wolfIP_ipconfig_get(s, &ip, &nm, &gw); + } while (!dhcp_bound(s)); + wolfIP_ipconfig_get(s, &ip, &nm, &gw); + srv_ip = htonl(ip); +#else + wolfIP_ipconfig_set(s, atoip4(WOLFIP_IP), atoip4("255.255.255.0"), + atoip4(HOST_STACK_IP)); + inet_pton(AF_INET, WOLFIP_IP, &srv_ip); +#endif + + run_ipfilter_logger(s, srv_ip); + sleep(1); + return 0; +} diff --git a/src/wolfip.c b/src/wolfip.c index 3a1277c..f419faa 100644 --- a/src/wolfip.c +++ b/src/wolfip.c @@ -52,6 +52,12 @@ static int wolfIP_loopback_send(struct wolfIP_ll_dev *ll, void *buf, uint32_t le #endif static void wolfIP_recv_on(struct wolfIP *s, unsigned int if_idx, void *buf, uint32_t len); +struct wolfIP_eth_frame; +struct wolfIP_ip_packet; +struct wolfIP_tcp_seg; +struct wolfIP_udp_datagram; +struct wolfIP_icmp_packet; + /* Fixed size binary heap: each element is a timer. */ #define MAX_TIMERS MAX_TCPSOCKETS * 3 @@ -433,6 +439,147 @@ struct PACKED wolfIP_icmp_ttl_exceeded_packet { uint8_t orig_packet[TTL_EXCEEDED_ORIG_PACKET_SIZE]; }; +#if CONFIG_IPFILTER +static wolfIP_filter_cb wolfip_filter_cb; +static void *wolfip_filter_arg; +static uint32_t wolfip_filter_mask; +static int wolfip_filter_lock; + +void wolfIP_filter_set_callback(wolfIP_filter_cb cb, void *arg) +{ + wolfip_filter_cb = cb; + wolfip_filter_arg = arg; +} + +void wolfIP_filter_set_mask(uint32_t mask) +{ + wolfip_filter_mask = mask; +} + +uint32_t wolfIP_filter_get_mask(void) +{ + return wolfip_filter_mask; +} + +static void wolfIP_filter_init_metadata(struct wolfIP_filter_metadata *meta) +{ + memset(meta, 0, sizeof(*meta)); +} + +static int wolfIP_filter_dispatch(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const void *buffer, uint32_t length, const struct wolfIP_filter_metadata *meta) +{ + struct wolfIP_filter_event event; + int ret; + + if (!wolfip_filter_cb) + return 0; + if ((wolfip_filter_mask & (1U << reason)) == 0) + return 0; + if (wolfip_filter_lock) + return 0; + + event.reason = reason; + event.stack = s; + event.if_idx = if_idx; + event.length = length; + event.buffer = buffer; + if (meta) + event.meta = *meta; + else + wolfIP_filter_init_metadata(&event.meta); + + wolfip_filter_lock = 1; + ret = wolfip_filter_cb(wolfip_filter_arg, &event); + wolfip_filter_lock = 0; + + return ret; +} + +#ifdef ETHERNET +static int wolfIP_filter_notify_eth(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const struct wolfIP_eth_frame *eth, uint32_t len) +{ + struct wolfIP_filter_metadata meta; + + wolfIP_filter_init_metadata(&meta); + memcpy(meta.src_mac, eth->src, sizeof(meta.src_mac)); + memcpy(meta.dst_mac, eth->dst, sizeof(meta.dst_mac)); + meta.eth_type = eth->type; + + return wolfIP_filter_dispatch(reason, s, if_idx, eth, len, &meta); +} +#else +#define wolfIP_filter_notify_eth(...) (0) +#endif + +static void wolfIP_filter_fill_ip_metadata(struct wolfIP_filter_metadata *meta, const struct wolfIP_ip_packet *ip) +{ + meta->src_ip = ip->src; + meta->dst_ip = ip->dst; + meta->ip_proto = ip->proto; +#ifdef ETHERNET + memcpy(meta->src_mac, ip->eth.src, sizeof(meta->src_mac)); + memcpy(meta->dst_mac, ip->eth.dst, sizeof(meta->dst_mac)); + meta->eth_type = ip->eth.type; +#endif +} + +static int wolfIP_filter_notify_ip(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const struct wolfIP_ip_packet *ip, uint32_t len) +{ + struct wolfIP_filter_metadata meta; + + wolfIP_filter_init_metadata(&meta); + wolfIP_filter_fill_ip_metadata(&meta, ip); + + return wolfIP_filter_dispatch(reason, s, if_idx, ip, len, &meta); +} + +static int wolfIP_filter_notify_tcp(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const struct wolfIP_tcp_seg *tcp, uint32_t len) +{ + struct wolfIP_filter_metadata meta; + + wolfIP_filter_init_metadata(&meta); + wolfIP_filter_fill_ip_metadata(&meta, &tcp->ip); + meta.l4.tcp.src_port = tcp->src_port; + meta.l4.tcp.dst_port = tcp->dst_port; + meta.l4.tcp.flags = tcp->flags; + + return wolfIP_filter_dispatch(reason, s, if_idx, tcp, len, &meta); +} + +static int wolfIP_filter_notify_udp(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const struct wolfIP_udp_datagram *udp, uint32_t len) +{ + struct wolfIP_filter_metadata meta; + + wolfIP_filter_init_metadata(&meta); + wolfIP_filter_fill_ip_metadata(&meta, &udp->ip); + meta.l4.udp.src_port = udp->src_port; + meta.l4.udp.dst_port = udp->dst_port; + + return wolfIP_filter_dispatch(reason, s, if_idx, udp, len, &meta); +} + +static int wolfIP_filter_notify_icmp(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const struct wolfIP_icmp_packet *icmp, uint32_t len) +{ + struct wolfIP_filter_metadata meta; + + wolfIP_filter_init_metadata(&meta); + wolfIP_filter_fill_ip_metadata(&meta, &icmp->ip); + meta.l4.icmp.type = icmp->type; + meta.l4.icmp.code = icmp->code; + + return wolfIP_filter_dispatch(reason, s, if_idx, icmp, len, &meta); +} + +#else + +#define wolfIP_filter_notify_eth(...) (0) +#define wolfIP_filter_notify_ip(...) (0) +#define wolfIP_filter_notify_tcp(...) (0) +#define wolfIP_filter_notify_udp(...) (0) +#define wolfIP_filter_notify_icmp(...) (0) + +#endif /* CONFIG_IPFILTER */ + /* DHCP */ #define BOOT_REQUEST 1 #define BOOT_REPLY 2 @@ -752,6 +899,39 @@ static inline unsigned int wolfIP_socket_if_idx(const struct tsocket *t) return t->if_idx; } +#if CONFIG_IPFILTER +static int wolfIP_filter_notify_socket_event( + enum wolfIP_filter_reason reason, + struct wolfIP *s, + struct tsocket *ts, + ip4 local_ip, + uint16_t local_port, + ip4 remote_ip, + uint16_t remote_port) +{ + struct wolfIP_filter_metadata meta; + unsigned int if_idx = ts ? wolfIP_socket_if_idx(ts) : WOLFIP_PRIMARY_IF_IDX; + + wolfIP_filter_init_metadata(&meta); + meta.src_ip = ee32(local_ip); + meta.dst_ip = ee32(remote_ip); + if (ts) { + meta.ip_proto = (uint8_t)ts->proto; + if (ts->proto == WI_IPPROTO_TCP) { + meta.l4.tcp.src_port = ee16(local_port); + meta.l4.tcp.dst_port = ee16(remote_port); + } else if (ts->proto == WI_IPPROTO_UDP) { + meta.l4.udp.src_port = ee16(local_port); + meta.l4.udp.dst_port = ee16(remote_port); + } + } + + return wolfIP_filter_dispatch(reason, s, if_idx, NULL, 0, &meta); +} +#else +#define wolfIP_filter_notify_socket_event(...) (0) +#endif + static unsigned int wolfIP_if_for_local_ip(struct wolfIP *s, ip4 local_ip, int *found) { unsigned int primary = 0; @@ -791,6 +971,10 @@ static void wolfIP_send_ttl_exceeded(struct wolfIP *s, unsigned int if_idx, stru { struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, if_idx); struct wolfIP_icmp_ttl_exceeded_packet icmp; + struct wolfIP_icmp_packet *icmp_pkt = (struct wolfIP_icmp_packet *)&icmp; +#if !CONFIG_IPFILTER + (void)icmp_pkt; +#endif if (!ll || !ll->send) return; memset(&icmp, 0, sizeof(icmp)); @@ -809,6 +993,12 @@ static void wolfIP_send_ttl_exceeded(struct wolfIP *s, unsigned int if_idx, stru icmp.ip.csum = 0; iphdr_set_checksum(&icmp.ip); eth_output_add_header(s, if_idx, orig->eth.src, &icmp.ip.eth, ETH_TYPE_IP); + if (wolfIP_filter_notify_icmp(WOLFIP_FILT_SENDING, s, if_idx, icmp_pkt, sizeof(icmp)) != 0) + return; + if (wolfIP_filter_notify_ip(WOLFIP_FILT_SENDING, s, if_idx, &icmp.ip, sizeof(icmp)) != 0) + return; + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, if_idx, &icmp.ip.eth, sizeof(icmp)) != 0) + return; ll->send(ll, &icmp, sizeof(icmp)); } #else @@ -939,6 +1129,8 @@ static void udp_try_recv(struct wolfIP *s, unsigned int if_idx, struct wolfIP_ud int i; ip4 local_ip = conf ? conf->ip : IPADDR_ANY; ip4 dst_ip = ee32(udp->ip.dst); + if (wolfIP_filter_notify_udp(WOLFIP_FILT_RECEIVING, s, if_idx, udp, frame_len) != 0) + return; for (i = 0; i < MAX_UDPSOCKETS; i++) { struct tsocket *t = &s->udpsockets[i]; if (t->src_port == ee16(udp->dst_port) && t->dst_port == ee16(udp->src_port) && @@ -1192,12 +1384,25 @@ static void wolfIP_forward_packet(struct wolfIP *s, unsigned int out_if, struct { #ifdef ETHERNET struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, out_if); + int drop = 0; if (!ll || !ll->send) return; if (broadcast) eth_output_add_header(s, out_if, NULL, &ip->eth, ETH_TYPE_IP); else eth_output_add_header(s, out_if, mac, &ip->eth, ETH_TYPE_IP); + if (ip->proto == WI_IPPROTO_TCP) + drop = wolfIP_filter_notify_tcp(WOLFIP_FILT_SENDING, s, out_if, (struct wolfIP_tcp_seg *)ip, len); + else if (ip->proto == WI_IPPROTO_UDP) + drop = wolfIP_filter_notify_udp(WOLFIP_FILT_SENDING, s, out_if, (struct wolfIP_udp_datagram *)ip, len); + else if (ip->proto == WI_IPPROTO_ICMP) + drop = wolfIP_filter_notify_icmp(WOLFIP_FILT_SENDING, s, out_if, (struct wolfIP_icmp_packet *)ip, len); + if (drop != 0) + return; + if (wolfIP_filter_notify_ip(WOLFIP_FILT_SENDING, s, out_if, ip, len) != 0) + return; + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, out_if, &ip->eth, len) != 0) + return; ll->send(ll, ip, len); #else (void)s; @@ -1384,6 +1589,8 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx, struct wolfIP_tcp_s struct ipconf *conf = wolfIP_ipconf_at(S, if_idx); ip4 local_ip = conf ? conf->ip : IPADDR_ANY; int i; + if (wolfIP_filter_notify_tcp(WOLFIP_FILT_RECEIVING, S, if_idx, tcp, frame_len) != 0) + return; for (i = 0; i < MAX_TCPSOCKETS; i++) { uint32_t tcplen; uint32_t iplen; @@ -1409,9 +1616,13 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx, struct wolfIP_tcp_s return; } tcplen = iplen - (IP_HEADER_LEN + (tcp->hlen >> 2)); - /* Check if RST, close socket only if in SYN_SENT */ - if ((tcp->flags & 0x04) && (t->sock.tcp.state == TCP_SYN_SENT)) { + /* Check if RST */ + if (tcp->flags & 0x04) { + (void)wolfIP_filter_notify_socket_event( + WOLFIP_FILT_REMOTE_RESET, S, t, + t->local_ip, t->src_port, t->remote_ip, t->dst_port); close_socket(t); + continue; } /* Check if FIN */ @@ -1421,6 +1632,9 @@ static void tcp_input(struct wolfIP *S, unsigned int if_idx, struct wolfIP_tcp_s t->sock.tcp.ack = ee32(tcp->seq) + 1; tcp_send_ack(t); t->events |= CB_EVENT_CLOSED | CB_EVENT_READABLE; + (void)wolfIP_filter_notify_socket_event( + WOLFIP_FILT_CLOSE_WAIT, S, t, + t->local_ip, t->src_port, t->remote_ip, t->dst_port); } else if (t->sock.tcp.state == TCP_FIN_WAIT_1) { t->sock.tcp.state = TCP_CLOSING; @@ -1618,6 +1832,12 @@ int wolfIP_sock_connect(struct wolfIP *s, int sockfd, const struct wolfIP_sockad if (ts->src_port < 1024) ts->src_port += 1024; ts->dst_port = ee16(sin->sin_port); + if (wolfIP_filter_notify_socket_event( + WOLFIP_FILT_CONNECTING, s, ts, + ts->local_ip, ts->src_port, ts->remote_ip, ts->dst_port) != 0) { + ts->sock.tcp.state = TCP_CLOSED; + return -1; + } tcp_send_syn(ts, 0x02); return -WOLFIP_EAGAIN; } @@ -1670,6 +1890,12 @@ int wolfIP_sock_accept(struct wolfIP *s, int sockfd, struct wolfIP_sockaddr *add } ts->sock.tcp.state = TCP_LISTEN; ts->sock.tcp.seq = wolfIP_getrandom(); + if (wolfIP_filter_notify_socket_event( + WOLFIP_FILT_ACCEPTING, s, newts, + newts->local_ip, newts->src_port, newts->remote_ip, newts->dst_port) != 0) { + close_socket(newts); + return -1; + } return (newts - s->tcpsockets) | MARK_TCP_SOCKET; } else if (ts->sock.tcp.state == TCP_LISTEN) { return -WOLFIP_EAGAIN; @@ -1878,6 +2104,13 @@ int wolfIP_sock_close(struct wolfIP *s, int sockfd) ts->sock.tcp.state = TCP_FIN_WAIT_1; tcp_send_finack(ts); return -WOLFIP_EAGAIN; + } else if (ts->sock.tcp.state == TCP_LISTEN) { + ts->sock.tcp.state = TCP_CLOSED; + (void)wolfIP_filter_notify_socket_event( + WOLFIP_FILT_STOP_LISTENING, s, ts, + ts->local_ip, ts->src_port, IPADDR_ANY, 0); + close_socket(ts); + return 0; } else if (ts->sock.tcp.state == TCP_CLOSE_WAIT) { ts->sock.tcp.state = TCP_LAST_ACK; tcp_send_finack(ts); @@ -1893,6 +2126,9 @@ int wolfIP_sock_close(struct wolfIP *s, int sockfd) return -WOLFIP_EAGAIN; } else if (ts->sock.tcp.state != TCP_CLOSED) { ts->sock.tcp.state = TCP_CLOSED; + (void)wolfIP_filter_notify_socket_event( + WOLFIP_FILT_CLOSED, s, ts, + ts->local_ip, ts->src_port, ts->remote_ip, ts->dst_port); close_socket(ts); return 0; } else return -1; @@ -1900,7 +2136,10 @@ int wolfIP_sock_close(struct wolfIP *s, int sockfd) struct tsocket *ts; if ((sockfd & ~MARK_UDP_SOCKET) >= MAX_UDPSOCKETS) return -WOLFIP_EINVAL; - ts = &s->tcpsockets[sockfd & ~MARK_UDP_SOCKET]; + ts = &s->udpsockets[sockfd & ~MARK_UDP_SOCKET]; + (void)wolfIP_filter_notify_socket_event( + WOLFIP_FILT_DISSOCIATE, s, ts, + ts->local_ip, ts->src_port, ts->remote_ip, ts->dst_port); close_socket(ts); return 0; } else return -1; @@ -1959,17 +2198,29 @@ int wolfIP_sock_bind(struct wolfIP *s, int sockfd, const struct wolfIP_sockaddr return -1; if ((sin->sin_family != AF_INET) || (addrlen < sizeof(struct wolfIP_sockaddr_in))) return -1; - ts->if_idx = (uint8_t)if_idx; - if (bind_ip != IPADDR_ANY) - ts->local_ip = bind_ip; - else if (conf && conf->ip != IPADDR_ANY) - ts->local_ip = conf->ip; - else { - struct ipconf *primary = wolfIP_primary_ipconf(s); - if (primary && primary->ip != IPADDR_ANY) - ts->local_ip = primary->ip; + { + ip4 prev_ip = ts->local_ip; + uint16_t prev_port = ts->src_port; + uint16_t new_port = ee16(sin->sin_port); + ts->if_idx = (uint8_t)if_idx; + if (bind_ip != IPADDR_ANY) + ts->local_ip = bind_ip; + else if (conf && conf->ip != IPADDR_ANY) + ts->local_ip = conf->ip; + else { + struct ipconf *primary = wolfIP_primary_ipconf(s); + if (primary && primary->ip != IPADDR_ANY) + ts->local_ip = primary->ip; + } + if (wolfIP_filter_notify_socket_event( + WOLFIP_FILT_BINDING, s, ts, + ts->local_ip, new_port, IPADDR_ANY, 0) != 0) { + ts->local_ip = prev_ip; + ts->src_port = prev_port; + return -1; + } + ts->src_port = new_port; } - ts->src_port = ee16(sin->sin_port); return 0; } else if (sockfd & MARK_UDP_SOCKET) { if ((sockfd & ~MARK_UDP_SOCKET) >= MAX_UDPSOCKETS) @@ -1979,17 +2230,29 @@ int wolfIP_sock_bind(struct wolfIP *s, int sockfd, const struct wolfIP_sockaddr return -1; if ((sin->sin_family != AF_INET) || (addrlen < sizeof(struct wolfIP_sockaddr_in))) return -1; - ts->if_idx = (uint8_t)if_idx; - if (bind_ip != IPADDR_ANY) - ts->local_ip = bind_ip; - else if (conf && conf->ip != IPADDR_ANY) - ts->local_ip = conf->ip; - else { - struct ipconf *primary = wolfIP_primary_ipconf(s); - if (primary && primary->ip != IPADDR_ANY) - ts->local_ip = primary->ip; + { + ip4 prev_ip = ts->local_ip; + uint16_t prev_port = ts->src_port; + uint16_t new_port = ee16(sin->sin_port); + ts->if_idx = (uint8_t)if_idx; + if (bind_ip != IPADDR_ANY) + ts->local_ip = bind_ip; + else if (conf && conf->ip != IPADDR_ANY) + ts->local_ip = conf->ip; + else { + struct ipconf *primary = wolfIP_primary_ipconf(s); + if (primary && primary->ip != IPADDR_ANY) + ts->local_ip = primary->ip; + } + ts->src_port = new_port; + if (wolfIP_filter_notify_socket_event( + WOLFIP_FILT_BINDING, s, ts, + ts->local_ip, new_port, IPADDR_ANY, 0) != 0) { + ts->local_ip = prev_ip; + ts->src_port = prev_port; + return -1; + } } - ts->src_port = ee16(sin->sin_port); return 0; } else return -1; @@ -2011,6 +2274,12 @@ int wolfIP_sock_listen(struct wolfIP *s, int sockfd, int backlog) if (ts->sock.tcp.state != TCP_CLOSED) return -1; ts->sock.tcp.state = TCP_LISTEN; + if (wolfIP_filter_notify_socket_event( + WOLFIP_FILT_LISTENING, s, ts, + ts->local_ip, ts->src_port, IPADDR_ANY, 0) != 0) { + ts->sock.tcp.state = TCP_CLOSED; + return -1; + } return 0; } @@ -2042,6 +2311,8 @@ static void icmp_input(struct wolfIP *s, unsigned int if_idx, struct wolfIP_ip_p struct wolfIP_icmp_packet *icmp = (struct wolfIP_icmp_packet *)ip; uint32_t tmp; struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, if_idx); + if (wolfIP_filter_notify_icmp(WOLFIP_FILT_RECEIVING, s, if_idx, icmp, len) != 0) + return; if (!DHCP_IS_RUNNING(s) && (icmp->type == ICMP_ECHO_REQUEST)) { icmp->type = ICMP_ECHO_REPLY; icmp->csum += 8; @@ -2052,6 +2323,12 @@ static void icmp_input(struct wolfIP *s, unsigned int if_idx, struct wolfIP_ip_p ip->csum = 0; iphdr_set_checksum(ip); eth_output_add_header(s, if_idx, ip->eth.src, &ip->eth, ETH_TYPE_IP); + if (wolfIP_filter_notify_icmp(WOLFIP_FILT_SENDING, s, if_idx, icmp, len) != 0) + return; + if (wolfIP_filter_notify_ip(WOLFIP_FILT_SENDING, s, if_idx, ip, len) != 0) + return; + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, if_idx, &ip->eth, len) != 0) + return; if (ll && ll->send) ll->send(ll, ip, len); } @@ -2486,8 +2763,11 @@ static void arp_request(struct wolfIP *s, unsigned int if_idx, ip4 tip) arp.sip = ee32(conf->ip); memset(arp.tma, 0, 6); arp.tip = ee32(tip); - if (ll->send) + if (ll->send) { + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, if_idx, &arp.eth, sizeof(struct arp_packet)) != 0) + return; ll->send(ll, &arp, sizeof(struct arp_packet)); + } } static void arp_recv(struct wolfIP *s, unsigned int if_idx, void *buf, int len) @@ -2507,8 +2787,11 @@ static void arp_recv(struct wolfIP *s, unsigned int if_idx, void *buf, int len) arp->sip = ee32(conf->ip); arp_store_neighbor(s, if_idx, ee32(arp->sip), arp->sma); eth_output_add_header(s, if_idx, arp->tma, &arp->eth, ETH_TYPE_ARP); - if (ll->send) + if (ll->send) { + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, if_idx, &arp->eth, len) != 0) + return; ll->send(ll, buf, len); + } } if (arp->opcode == ee16(ARP_REPLY)) { arp_store_neighbor(s, if_idx, ee32(arp->sip), arp->sma); @@ -2601,6 +2884,8 @@ static inline void ip_recv(struct wolfIP *s, unsigned int if_idx, struct wolfIP_ } } #endif + if (wolfIP_filter_notify_ip(WOLFIP_FILT_RECEIVING, s, if_idx, ip, len) != 0) + return; #if WOLFIP_ENABLE_FORWARDING if (ip->ver_ihl == 0x45) { ip4 dest = ee32(ip->dst); @@ -2669,6 +2954,8 @@ static void wolfIP_recv_on(struct wolfIP *s, unsigned int if_idx, void *buf, uin if (!ll) return; eth = (struct wolfIP_eth_frame *)buf; + if (wolfIP_filter_notify_eth(WOLFIP_FILT_RECEIVING, s, if_idx, eth, len) != 0) + return; if (eth->type == ee16(ETH_TYPE_IP)) { struct wolfIP_ip_packet *ip = (struct wolfIP_ip_packet *)eth; if ((memcmp(eth->dst, ll->mac, 6) != 0) && (memcmp(eth->dst, "\xff\xff\xff\xff\xff\xff", 6) != 0)) { @@ -2884,6 +3171,7 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now) struct wolfIP_tcp_seg *tcp; desc = fifo_peek(&ts->sock.tcp.txbuf); while (desc) { + unsigned int tx_if = wolfIP_socket_if_idx(ts); tcp = (struct wolfIP_tcp_seg *)(ts->txmem + desc->pos + sizeof(*desc)); if (desc->flags & PKT_FLAG_SENT) { in_flight += ee16(tcp->ip.len) - (IP_HEADER_LEN + (tcp->hlen >> 2)); @@ -2891,16 +3179,15 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now) continue; } else { #ifdef ETHERNET - unsigned int if_idx = wolfIP_socket_if_idx(ts); - struct ipconf *conf = wolfIP_ipconf_at(s, if_idx); + struct ipconf *conf = wolfIP_ipconf_at(s, tx_if); ip4 nexthop = wolfIP_select_nexthop(conf, ts->remote_ip); - if (wolfIP_is_loopback_if(if_idx)) { - struct wolfIP_ll_dev *loop = wolfIP_ll_at(s, if_idx); + if (wolfIP_is_loopback_if(tx_if)) { + struct wolfIP_ll_dev *loop = wolfIP_ll_at(s, tx_if); if (loop) memcpy(ts->nexthop_mac, loop->mac, 6); - } else if (arp_lookup(s, if_idx, nexthop, ts->nexthop_mac) < 0) { + } else if (arp_lookup(s, tx_if, nexthop, ts->nexthop_mac) < 0) { /* Send ARP request */ - arp_request(s, if_idx, nexthop); + arp_request(s, tx_if, nexthop); break; } #endif @@ -2921,8 +3208,16 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now) tcp->ack = ee32(ts->sock.tcp.ack); tcp->win = ee16(queue_space(&ts->sock.tcp.rxbuf)); ip_output_add_header(ts, (struct wolfIP_ip_packet *)tcp, WI_IPPROTO_TCP, size); + if (wolfIP_filter_notify_tcp(WOLFIP_FILT_SENDING, ts->S, tx_if, tcp, desc->len) != 0) + break; + if (wolfIP_filter_notify_ip(WOLFIP_FILT_SENDING, ts->S, tx_if, &tcp->ip, desc->len) != 0) + break; +#ifdef ETHERNET + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, ts->S, tx_if, &tcp->ip.eth, desc->len) != 0) + break; +#endif { - struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, wolfIP_socket_if_idx(ts)); + struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, tx_if); if (ll && ll->send) ll->send(ll, tcp, desc->len); } @@ -2954,18 +3249,18 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now) struct pkt_desc *desc = fifo_peek(&t->sock.udp.txbuf); while (desc) { struct wolfIP_udp_datagram *udp = (struct wolfIP_udp_datagram *)(t->txmem + desc->pos + sizeof(*desc)); + unsigned int tx_if = wolfIP_socket_if_idx(t); #ifdef ETHERNET - unsigned int if_idx = wolfIP_socket_if_idx(t); - struct ipconf *conf = wolfIP_ipconf_at(s, if_idx); + struct ipconf *conf = wolfIP_ipconf_at(s, tx_if); ip4 nexthop = wolfIP_select_nexthop(conf, t->remote_ip); - if (wolfIP_is_loopback_if(if_idx)) { - struct wolfIP_ll_dev *loop = wolfIP_ll_at(s, if_idx); + if (wolfIP_is_loopback_if(tx_if)) { + struct wolfIP_ll_dev *loop = wolfIP_ll_at(s, tx_if); if (loop) memcpy(t->nexthop_mac, loop->mac, 6); } else { - if ((!IS_IP_BCAST(nexthop) && (arp_lookup(s, if_idx, nexthop, t->nexthop_mac) < 0))) { + if ((!IS_IP_BCAST(nexthop) && (arp_lookup(s, tx_if, nexthop, t->nexthop_mac) < 0))) { /* Send ARP request */ - arp_request(s, if_idx, nexthop); + arp_request(s, tx_if, nexthop); break; } if (IS_IP_BCAST(nexthop)) memset(t->nexthop_mac, 0xFF, 6); @@ -2973,8 +3268,16 @@ int wolfIP_poll(struct wolfIP *s, uint64_t now) #endif len = desc->len - ETH_HEADER_LEN; ip_output_add_header(t, (struct wolfIP_ip_packet *)udp, WI_IPPROTO_UDP, len); + if (wolfIP_filter_notify_udp(WOLFIP_FILT_SENDING, t->S, tx_if, udp, desc->len) != 0) + break; + if (wolfIP_filter_notify_ip(WOLFIP_FILT_SENDING, t->S, tx_if, &udp->ip, desc->len) != 0) + break; +#ifdef ETHERNET + if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, t->S, tx_if, &udp->ip.eth, desc->len) != 0) + break; +#endif { - struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, wolfIP_socket_if_idx(t)); + struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, tx_if); if (ll && ll->send) ll->send(ll, udp, desc->len); } diff --git a/wolfip-filter.h b/wolfip-filter.h new file mode 100644 index 0000000..092ff99 --- /dev/null +++ b/wolfip-filter.h @@ -0,0 +1,67 @@ +#ifndef WOLFIP_FILTER_H +#define WOLFIP_FILTER_H + +#include + +struct wolfIP; + +enum wolfIP_filter_reason { + WOLFIP_FILT_BINDING = 0, + WOLFIP_FILT_DISSOCIATE = 1, + WOLFIP_FILT_LISTENING = 2, + WOLFIP_FILT_STOP_LISTENING = 3, + WOLFIP_FILT_CONNECTING = 4, + WOLFIP_FILT_ACCEPTING = 5, + WOLFIP_FILT_CLOSED = 6, + WOLFIP_FILT_REMOTE_RESET = 7, + WOLFIP_FILT_RECEIVING = 8, + WOLFIP_FILT_SENDING = 9, + WOLFIP_FILT_ADDR_UNREACHABLE = 10, + WOLFIP_FILT_PORT_UNREACHABLE = 11, + WOLFIP_FILT_INBOUND_ERR = 12, + WOLFIP_FILT_OUTBOUND_ERR = 13, + WOLFIP_FILT_CLOSE_WAIT = 14 +}; + +#define WOLFIP_FILT_MASK(reason) (1U << (reason)) + +struct wolfIP_filter_metadata { + uint8_t src_mac[6]; + uint8_t dst_mac[6]; + uint16_t eth_type; + uint32_t src_ip; + uint32_t dst_ip; + uint8_t ip_proto; + union { + struct { + uint16_t src_port; + uint16_t dst_port; + uint8_t flags; + } tcp; + struct { + uint16_t src_port; + uint16_t dst_port; + } udp; + struct { + uint8_t type; + uint8_t code; + } icmp; + } l4; +}; + +struct wolfIP_filter_event { + enum wolfIP_filter_reason reason; + struct wolfIP *stack; + unsigned int if_idx; + uint32_t length; + const void *buffer; + struct wolfIP_filter_metadata meta; +}; + +typedef int (*wolfIP_filter_cb)(void *arg, const struct wolfIP_filter_event *event); + +void wolfIP_filter_set_callback(wolfIP_filter_cb cb, void *arg); +void wolfIP_filter_set_mask(uint32_t mask); +uint32_t wolfIP_filter_get_mask(void); + +#endif /* WOLFIP_FILTER_H */ diff --git a/wolfip.h b/wolfip.h index 3109da9..355f40a 100644 --- a/wolfip.h +++ b/wolfip.h @@ -12,11 +12,28 @@ typedef uint32_t ip4; #define ee32(x) __builtin_bswap32(x) #define DEBUG +#ifndef WOLFIP_EAGAIN +#ifdef EAGAIN +#define WOLFIP_EAGAIN EAGAIN +#else +#define WOLFIP_EAGAIN (11) +#endif +#endif + #ifndef WOLFIP_EINVAL +#ifdef EINVAL +#define WOLFIP_EINVAL EINVAL +#else #define WOLFIP_EINVAL (22) #endif -#ifndef WOLFIP_EAGAIN -#define WOLFIP_EAGAIN (11) +#endif + +#ifndef WOLFIP_EACCES +#ifdef EACCES +#define WOLFIP_EACCES EACCES +#else +#define WOLFIP_EACCES (13) +#endif #endif @@ -114,6 +131,10 @@ int dhcp_bound(struct wolfIP *s); int nslookup(struct wolfIP *s, const char *name, uint16_t *id, void (*lookup_cb)(uint32_t ip)); +#if CONFIG_IPFILTER +#include "wolfip-filter.h" +#endif + /* IP stack interface */ void wolfIP_init(struct wolfIP *s); void wolfIP_init_static(struct wolfIP **s); From 66279675512de94ca82ac4afeb0e027e459aba9e Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Thu, 13 Nov 2025 02:07:09 +0100 Subject: [PATCH 2/3] Add per-protocol mask. Improve logging in test. --- src/test/ipfilter_logger.c | 42 ++++++++++++++++------- src/wolfip.c | 68 ++++++++++++++++++++++++++++++++++++-- wolfip-filter.h | 13 +++++++- 3 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/test/ipfilter_logger.c b/src/test/ipfilter_logger.c index 06ceba1..1ba5c6e 100644 --- a/src/test/ipfilter_logger.c +++ b/src/test/ipfilter_logger.c @@ -78,20 +78,38 @@ static void ip_to_str(uint32_t net_ip, char *buf, size_t len) buf[len - 1] = '\0'; } -static void log_ports(uint8_t proto, const struct wolfIP_filter_metadata *meta) +static const char *proto_to_name(uint16_t proto) +{ + switch (proto) { + case WOLFIP_FILTER_PROTO_ETH: + return "ETH"; + case WOLFIP_FILTER_PROTO_IP: + return "IP"; + case WOLFIP_FILTER_PROTO_TCP: + return "TCP"; + case WOLFIP_FILTER_PROTO_UDP: + return "UDP"; + case WOLFIP_FILTER_PROTO_ICMP: + return "ICMP"; + default: + return "UNKNOWN"; + } +} + +static void log_ports(uint16_t proto, const struct wolfIP_filter_metadata *meta) { if (proto == 0) return; - if (proto == WI_IPPROTO_TCP) { + if (proto == WOLFIP_FILTER_PROTO_TCP) { printf(" tcp=%u->%u flags=0x%02x", - ee16(meta->l4.tcp.src_port), - ee16(meta->l4.tcp.dst_port), + ntohs(meta->l4.tcp.src_port), + ntohs(meta->l4.tcp.dst_port), meta->l4.tcp.flags); - } else if (proto == WI_IPPROTO_UDP) { + } else if (proto == WOLFIP_FILTER_PROTO_UDP) { printf(" udp=%u->%u", - ee16(meta->l4.udp.src_port), - ee16(meta->l4.udp.dst_port)); - } else if (proto == WI_IPPROTO_ICMP) { + ntohs(meta->l4.udp.src_port), + ntohs(meta->l4.udp.dst_port)); + } else if (proto == WOLFIP_FILTER_PROTO_ICMP) { printf(" icmp type=%u code=%u", meta->l4.icmp.type, meta->l4.icmp.code); @@ -107,16 +125,16 @@ static int filter_logger_cb(void *arg, const struct wolfIP_filter_event *event) mac_to_str(event->meta.src_mac, src_mac, sizeof(src_mac)); mac_to_str(event->meta.dst_mac, dst_mac, sizeof(dst_mac)); - printf("[ipfilter] reason=%s if=%u len=%" PRIu32 - " ip=%s->%s mac=%s->%s proto=%u", + printf("[ipfilter] %s reason=%s if=%u len=%" PRIu32 + " ip=%s->%s mac=%s->%s", + proto_to_name(event->meta.ip_proto), filter_reason_str(event->reason), event->if_idx, event->length, src_ip, dst_ip, src_mac, - dst_mac, - event->meta.ip_proto); + dst_mac); log_ports(event->meta.ip_proto, &event->meta); printf("\n"); diff --git a/src/wolfip.c b/src/wolfip.c index f419faa..75568fb 100644 --- a/src/wolfip.c +++ b/src/wolfip.c @@ -443,6 +443,11 @@ struct PACKED wolfIP_icmp_ttl_exceeded_packet { static wolfIP_filter_cb wolfip_filter_cb; static void *wolfip_filter_arg; static uint32_t wolfip_filter_mask; +static uint32_t wolfip_filter_mask_eth; +static uint32_t wolfip_filter_mask_ip; +static uint32_t wolfip_filter_mask_tcp; +static uint32_t wolfip_filter_mask_udp; +static uint32_t wolfip_filter_mask_icmp; static int wolfip_filter_lock; void wolfIP_filter_set_callback(wolfIP_filter_cb cb, void *arg) @@ -456,6 +461,31 @@ void wolfIP_filter_set_mask(uint32_t mask) wolfip_filter_mask = mask; } +void wolfIP_filter_set_eth_mask(uint32_t mask) +{ + wolfip_filter_mask_eth = mask; +} + +void wolfIP_filter_set_ip_mask(uint32_t mask) +{ + wolfip_filter_mask_ip = mask; +} + +void wolfIP_filter_set_tcp_mask(uint32_t mask) +{ + wolfip_filter_mask_tcp = mask; +} + +void wolfIP_filter_set_udp_mask(uint32_t mask) +{ + wolfip_filter_mask_udp = mask; +} + +void wolfIP_filter_set_icmp_mask(uint32_t mask) +{ + wolfip_filter_mask_icmp = mask; +} + uint32_t wolfIP_filter_get_mask(void) { return wolfip_filter_mask; @@ -466,14 +496,37 @@ static void wolfIP_filter_init_metadata(struct wolfIP_filter_metadata *meta) memset(meta, 0, sizeof(*meta)); } +static uint32_t wolfIP_filter_mask_for_proto(uint16_t proto) +{ + switch (proto) { + case WOLFIP_FILTER_PROTO_ETH: + return wolfip_filter_mask_eth ? wolfip_filter_mask_eth : wolfip_filter_mask; + case WOLFIP_FILTER_PROTO_IP: + return wolfip_filter_mask_ip ? wolfip_filter_mask_ip : wolfip_filter_mask; + case WOLFIP_FILTER_PROTO_TCP: + return wolfip_filter_mask_tcp ? wolfip_filter_mask_tcp : wolfip_filter_mask; + case WOLFIP_FILTER_PROTO_UDP: + return wolfip_filter_mask_udp ? wolfip_filter_mask_udp : wolfip_filter_mask; + case WOLFIP_FILTER_PROTO_ICMP: + return wolfip_filter_mask_icmp ? wolfip_filter_mask_icmp : wolfip_filter_mask; + default: + return wolfip_filter_mask; + } +} + static int wolfIP_filter_dispatch(enum wolfIP_filter_reason reason, struct wolfIP *s, unsigned int if_idx, const void *buffer, uint32_t length, const struct wolfIP_filter_metadata *meta) { struct wolfIP_filter_event event; int ret; + uint32_t mask; if (!wolfip_filter_cb) return 0; - if ((wolfip_filter_mask & (1U << reason)) == 0) + if (!meta) + mask = wolfip_filter_mask; + else + mask = wolfIP_filter_mask_for_proto(meta->ip_proto); + if ((mask & (1U << reason)) == 0) return 0; if (wolfip_filter_lock) return 0; @@ -504,6 +557,7 @@ static int wolfIP_filter_notify_eth(enum wolfIP_filter_reason reason, struct wol memcpy(meta.src_mac, eth->src, sizeof(meta.src_mac)); memcpy(meta.dst_mac, eth->dst, sizeof(meta.dst_mac)); meta.eth_type = eth->type; + meta.ip_proto = WOLFIP_FILTER_PROTO_ETH; return wolfIP_filter_dispatch(reason, s, if_idx, eth, len, &meta); } @@ -515,7 +569,10 @@ static void wolfIP_filter_fill_ip_metadata(struct wolfIP_filter_metadata *meta, { meta->src_ip = ip->src; meta->dst_ip = ip->dst; - meta->ip_proto = ip->proto; + meta->ip_proto = (ip->proto == WI_IPPROTO_TCP) ? WOLFIP_FILTER_PROTO_TCP : + (ip->proto == WI_IPPROTO_UDP) ? WOLFIP_FILTER_PROTO_UDP : + (ip->proto == WI_IPPROTO_ICMP) ? WOLFIP_FILTER_PROTO_ICMP : + WOLFIP_FILTER_PROTO_IP; #ifdef ETHERNET memcpy(meta->src_mac, ip->eth.src, sizeof(meta->src_mac)); memcpy(meta->dst_mac, ip->eth.dst, sizeof(meta->dst_mac)); @@ -529,6 +586,10 @@ static int wolfIP_filter_notify_ip(enum wolfIP_filter_reason reason, struct wolf wolfIP_filter_init_metadata(&meta); wolfIP_filter_fill_ip_metadata(&meta, ip); + if (meta.ip_proto == WOLFIP_FILTER_PROTO_TCP || + meta.ip_proto == WOLFIP_FILTER_PROTO_UDP || + meta.ip_proto == WOLFIP_FILTER_PROTO_ICMP) + meta.ip_proto = WOLFIP_FILTER_PROTO_IP; return wolfIP_filter_dispatch(reason, s, if_idx, ip, len, &meta); } @@ -539,6 +600,7 @@ static int wolfIP_filter_notify_tcp(enum wolfIP_filter_reason reason, struct wol wolfIP_filter_init_metadata(&meta); wolfIP_filter_fill_ip_metadata(&meta, &tcp->ip); + meta.ip_proto = WOLFIP_FILTER_PROTO_TCP; meta.l4.tcp.src_port = tcp->src_port; meta.l4.tcp.dst_port = tcp->dst_port; meta.l4.tcp.flags = tcp->flags; @@ -552,6 +614,7 @@ static int wolfIP_filter_notify_udp(enum wolfIP_filter_reason reason, struct wol wolfIP_filter_init_metadata(&meta); wolfIP_filter_fill_ip_metadata(&meta, &udp->ip); + meta.ip_proto = WOLFIP_FILTER_PROTO_UDP; meta.l4.udp.src_port = udp->src_port; meta.l4.udp.dst_port = udp->dst_port; @@ -564,6 +627,7 @@ static int wolfIP_filter_notify_icmp(enum wolfIP_filter_reason reason, struct wo wolfIP_filter_init_metadata(&meta); wolfIP_filter_fill_ip_metadata(&meta, &icmp->ip); + meta.ip_proto = WOLFIP_FILTER_PROTO_ICMP; meta.l4.icmp.type = icmp->type; meta.l4.icmp.code = icmp->code; diff --git a/wolfip-filter.h b/wolfip-filter.h index 092ff99..64d0a51 100644 --- a/wolfip-filter.h +++ b/wolfip-filter.h @@ -25,13 +25,19 @@ enum wolfIP_filter_reason { #define WOLFIP_FILT_MASK(reason) (1U << (reason)) +#define WOLFIP_FILTER_PROTO_ETH 0x008f +#define WOLFIP_FILTER_PROTO_IP 0x0800 +#define WOLFIP_FILTER_PROTO_TCP 0x0006 +#define WOLFIP_FILTER_PROTO_UDP 0x0011 +#define WOLFIP_FILTER_PROTO_ICMP 0x0001 + struct wolfIP_filter_metadata { uint8_t src_mac[6]; uint8_t dst_mac[6]; uint16_t eth_type; uint32_t src_ip; uint32_t dst_ip; - uint8_t ip_proto; + uint16_t ip_proto; union { struct { uint16_t src_port; @@ -62,6 +68,11 @@ typedef int (*wolfIP_filter_cb)(void *arg, const struct wolfIP_filter_event *eve void wolfIP_filter_set_callback(wolfIP_filter_cb cb, void *arg); void wolfIP_filter_set_mask(uint32_t mask); +void wolfIP_filter_set_eth_mask(uint32_t mask); +void wolfIP_filter_set_ip_mask(uint32_t mask); +void wolfIP_filter_set_tcp_mask(uint32_t mask); +void wolfIP_filter_set_udp_mask(uint32_t mask); +void wolfIP_filter_set_icmp_mask(uint32_t mask); uint32_t wolfIP_filter_get_mask(void); #endif /* WOLFIP_FILTER_H */ From 1292ce024a6a11af89cb8d644fa1f65b9c6788f0 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Thu, 13 Nov 2025 10:48:14 +0100 Subject: [PATCH 3/3] minor fixes for wolfSentry integration --- src/wolfip.c | 6 ++++-- wolfip.h | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/wolfip.c b/src/wolfip.c index 75568fb..abd8c5d 100644 --- a/src/wolfip.c +++ b/src/wolfip.c @@ -980,14 +980,16 @@ static int wolfIP_filter_notify_socket_event( meta.src_ip = ee32(local_ip); meta.dst_ip = ee32(remote_ip); if (ts) { - meta.ip_proto = (uint8_t)ts->proto; if (ts->proto == WI_IPPROTO_TCP) { + meta.ip_proto = WOLFIP_FILTER_PROTO_TCP; meta.l4.tcp.src_port = ee16(local_port); meta.l4.tcp.dst_port = ee16(remote_port); } else if (ts->proto == WI_IPPROTO_UDP) { + meta.ip_proto = WOLFIP_FILTER_PROTO_UDP; meta.l4.udp.src_port = ee16(local_port); meta.l4.udp.dst_port = ee16(remote_port); - } + } else + meta.ip_proto = 0; } return wolfIP_filter_dispatch(reason, s, if_idx, NULL, 0, &meta); diff --git a/wolfip.h b/wolfip.h index 355f40a..f0190f9 100644 --- a/wolfip.h +++ b/wolfip.h @@ -165,7 +165,7 @@ static inline uint32_t atou(const char *s) { uint32_t ret = 0; while (*s >= '0' && *s <= '9') { - ret = ret * 10 + (*s - '0'); + ret = (ret * 10u) + (uint32_t)(*s - '0'); s++; } return ret; @@ -191,9 +191,9 @@ static inline void iptoa(ip4 ip, char *buf) buf[0] = 0; for (i = 0; i < 4; i++) { uint8_t x = (ip >> (24 - i * 8)) & 0xFF; - if (x > 99) buf[j++] = x / 100 + '0'; - if (x > 9) buf[j++] = (x / 10) % 10 + '0'; - buf[j++] = x % 10 + '0'; + if (x > 99) buf[j++] = (char)(x / 100 + '0'); + if (x > 9) buf[j++] = (char)(((x / 10) % 10) + '0'); + buf[j++] = (char)((x % 10) + '0'); if (i < 3) buf[j++] = '.'; } buf[j] = 0;