diff --git a/.gitignore b/.gitignore index aa39c31..84ade19 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ wolfsentry/wolfsentry_options.h /examples/notification-demo/log_server/log_server /examples/notification-demo/udp_to_dbus/udp_to_dbus +/examples/Linux-wolfIP/wolfip-wolfsentry-demo /scripts/analyzer-config.sh diff --git a/Makefile b/Makefile index bc718f3..ff042fe 100644 --- a/Makefile +++ b/Makefile @@ -129,6 +129,23 @@ ifdef LWIP SRCS += lwip/packet_filter_glue.c endif +ifdef WOLFIP + ifndef WOLFIP_TOP + WOLFIP_TOP := $(SRC_TOP)/../wolfip + endif + ifndef WOLFIP_CONFIG_DIR + WOLFIP_CONFIG_DIR := $(WOLFIP_TOP) + endif + ifndef WOLFIP_ENABLE_IPFILTER + WOLFIP_ENABLE_IPFILTER := 1 + endif + WOLFIP_CFLAGS += -DWOLFSENTRY_WOLFIP -I$(WOLFIP_CONFIG_DIR) -I$(WOLFIP_TOP) + ifeq ($(WOLFIP_ENABLE_IPFILTER),1) + WOLFIP_CFLAGS += -DCONFIG_IPFILTER=1 + endif + SRCS += wolfip/packet_filter_glue.c +endif + ifdef NETXDUO ifndef NETXDUO_TOP NETXDUO_TOP=$(THREADX_TOP) @@ -166,7 +183,7 @@ ifndef C_WARNFLAGS endif endif -CFLAGS := -I$(BUILD_TOP) -I$(SRC_TOP) $(OPTIM) $(DEBUG) $(C_WARNFLAGS) $(LWIP_CFLAGS) $(RUNTIME_CFLAGS) $(EXTRA_CFLAGS) +CFLAGS := -I$(BUILD_TOP) -I$(SRC_TOP) $(OPTIM) $(DEBUG) $(C_WARNFLAGS) $(LWIP_CFLAGS) $(WOLFIP_CFLAGS) $(RUNTIME_CFLAGS) $(EXTRA_CFLAGS) LDFLAGS := $(EXTRA_LDFLAGS) VISIBILITY_CFLAGS := -fvisibility=hidden -DHAVE_VISIBILITY=1 diff --git a/examples/Linux-wolfIP/Makefile b/examples/Linux-wolfIP/Makefile new file mode 100644 index 0000000..9b2b191 --- /dev/null +++ b/examples/Linux-wolfIP/Makefile @@ -0,0 +1,62 @@ +CC ?= gcc +AR ?= ar + +WOLFSENTRY_PATH ?= ../../../wolfsentry +WOLFSENTRY_LIB ?= $(WOLFSENTRY_PATH)/libwolfsentry.a +WOLFIP_PATH ?= ../../../wolfip + +CFLAGS ?= -O2 -g +CFLAGS += -D_GNU_SOURCE +CFLAGS += -DCONFIG_IPFILTER=1 +CFLAGS += -Wall -Wextra -Wpedantic -std=c99 +CFLAGS += -std=c99 +CFLAGS += -I. +CFLAGS += -I./wolfip +CFLAGS += -I../../../wolfsentry/wolfsentry +CFLAGS += -I../../../wolfsentry +CFLAGS += -I$(WOLFIP_PATH) +CFLAGS += -I$(WOLFIP_PATH)/src +CFLAGS += -I$(WOLFIP_PATH)/src/port/posix +CFLAGS += -pthread + +LDFLAGS ?= -pthread + +TARGET := wolfip-wolfsentry-demo + +APP_SRCS := main.c +APP_OBJS := $(APP_SRCS:.c=.o) + +TAP_SRC := $(WOLFIP_PATH)/src/port/posix/tap_linux.c +TAP_OBJ := tap_linux.o + +WOLFIP_SRC := $(WOLFIP_PATH)/src/wolfip.c +WOLFIP_LIB := libwolfip.a +WOLFIP_OBJ := wolfip.o + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(APP_OBJS) $(TAP_OBJ) $(WOLFIP_LIB) $(WOLFSENTRY_LIB) + $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ + +$(APP_OBJS): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(TAP_OBJ): $(TAP_SRC) wolfip/config.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(WOLFIP_OBJ): $(WOLFIP_SRC) wolfip/config.h + $(CC) $(CFLAGS) -c $< -o $@ + +$(WOLFIP_LIB): $(WOLFIP_OBJ) + $(AR) rcs $@ $< + +$(WOLFSENTRY_LIB): + $(MAKE) -C $(WOLFSENTRY_PATH) libwolfsentry.a \ + WOLFIP=1 \ + WOLFIP_TOP=$(abspath $(WOLFIP_PATH)) \ + WOLFIP_CONFIG_DIR=$(abspath $(CURDIR)/wolfip) + +clean: + $(RM) $(APP_OBJS) $(TAP_OBJ) $(WOLFIP_OBJ) $(WOLFIP_LIB) $(TARGET) diff --git a/examples/Linux-wolfIP/README.md b/examples/Linux-wolfIP/README.md new file mode 100644 index 0000000..76f1d7d --- /dev/null +++ b/examples/Linux-wolfIP/README.md @@ -0,0 +1,77 @@ +# Linux wolfIP + wolfSentry Demo + +This example runs a single wolfIP instance on a TAP interface and forwards +wolfIP packet-filter events into wolfSentry via the wolfIP glue layer. The +installed wolfSentry actions log every inbound Ethernet frame and drop every +seventh inbound ICMP echo request while logging the drop decision. + +## Prerequisites + +* Linux host with `/dev/net/tun` access (run the demo with `sudo`). +* `libpcap` is **not** required. +* Build `wolfsentry` with wolfIP support enabled so the packet-filter glue is + present: + + ```sh + cd ../../wolfsentry + make WOLFIP=1 WOLFIP_CONFIG_DIR=examples/Linux-wolfIP/wolfip + ``` + + The example will then compile its own copy of wolfIP from `$(WOLFIP_PATH)` + using the local configuration in `wolfip/config.h`, so you do not need to + build wolfIP separately. Edit that file if you need different Ethernet/TAP + settings, such as the wolfIP and host IP addresses or the TAP interface name. + +## Build the demo + +```sh +cd wolfsentry/examples/Linux-wolfIP +make # override WOLFIP_PATH=/path/to/wolfip if needed +``` + +The Makefile first builds a local `libwolfip.a` from +`$(WOLFIP_PATH)/src/wolfip.c`, picking up the Ethernet/TAP configuration in +`wolfip/config.h`, and then links the demo against that static library plus +`../../../wolfsentry/libwolfsentry.a`. Override `WOLFIP_PATH` if your source +tree lives elsewhere. If `libwolfsentry.a` is missing or older than the +example sources, the Makefile automatically runs +`make WOLFIP=1 WOLFIP_CONFIG_DIR=examples/Linux-wolfIP/wolfip` inside +`../../wolfsentry` so the packet-filter glue is rebuilt with the local config. + +## Run the demo + +```sh +sudo ./wolfip-wolfsentry-demo +``` + +The program: + +1. Initializes wolfSentry, registers two actions (`log-event` and + `icmp-mod7`), and loads `wolfip-config.json`. +2. Installs wolfSentry as the wolfIP packet filter for Ethernet, IPv4 and + ICMP events. +3. Brings up wolfIP on a TAP interface (default host IP `10.10.10.1`, + wolfIP address `10.10.10.2`) and enters the polling loop. + +While it runs you can exercise it from the host by pinging +`10.10.10.2`. The demo now starts a background +`ping -I wolfip0 -c 100 10.10.10.2` process automatically so you immediately +get traffic; it stops after 100 packets, and you can launch your own ping if +you prefer. ICMP echo requests are accepted except when the running counter is +a multiple of 7 – only those discarded packets are logged. + +The demo links in wolfIP's POSIX TAP driver (`tap_linux.c`), so the call to +`tap_init()` inside the sample automatically creates, configures, and brings up +the TAP interface on the host (default name `wolfip0`). No manual `ip` +commands are required beyond running the binary with sufficient privileges. + +Stop the demo with `Ctrl+C`. + +## Cleaning up + +```sh +make clean +``` + +This removes the local binary and object files; it does not touch the +wolfIP/wolfSentry build outputs. diff --git a/examples/Linux-wolfIP/main.c b/examples/Linux-wolfIP/main.c new file mode 100644 index 0000000..0d9a455 --- /dev/null +++ b/examples/Linux-wolfIP/main.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WOLFSENTRY_SOURCE_ID WOLFSENTRY_SOURCE_ID_USER_BASE + +#include +#include +#include + +#include "wolfip/config.h" + +#include +#include + +extern int tap_init(struct wolfIP_ll_dev *dev, const char *name, uint32_t host_ip); + +static const char *const CONFIG_PATH = "wolfip-config.json"; +static volatile sig_atomic_t stop_flag = 0; + +static struct wolfsentry_context *sentry = NULL; +static pid_t ping_pid = -1; + +struct icmp_filter_state { + unsigned long counter; +}; + +static struct icmp_filter_state icmp_state; + +static void on_signal(int sig) +{ + (void)sig; + stop_flag = 1; +} + +static const char *reason_to_string(enum wolfIP_filter_reason reason) +{ + switch (reason) { + case WOLFIP_FILT_BINDING: return "BINDING"; + case WOLFIP_FILT_DISSOCIATE: return "DISSOCIATE"; + case WOLFIP_FILT_LISTENING: return "LISTENING"; + case WOLFIP_FILT_STOP_LISTENING: return "STOP_LISTENING"; + case WOLFIP_FILT_CONNECTING: return "CONNECTING"; + case WOLFIP_FILT_ACCEPTING: return "ACCEPTING"; + case WOLFIP_FILT_CLOSED: return "CLOSED"; + case WOLFIP_FILT_REMOTE_RESET: return "REMOTE_RESET"; + case WOLFIP_FILT_RECEIVING: return "RECEIVING"; + case WOLFIP_FILT_SENDING: return "SENDING"; + case WOLFIP_FILT_ADDR_UNREACHABLE: return "ADDR_UNREACHABLE"; + case WOLFIP_FILT_PORT_UNREACHABLE: return "PORT_UNREACHABLE"; + case WOLFIP_FILT_INBOUND_ERR: return "INBOUND_ERR"; + case WOLFIP_FILT_OUTBOUND_ERR: return "OUTBOUND_ERR"; + case WOLFIP_FILT_CLOSE_WAIT: return "CLOSE_WAIT"; + default: return "UNKNOWN"; + } +} + +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 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_event(const struct wolfIP_filter_event *event, const char *tag) +{ + char src_mac[18], dst_mac[18], src_ip[16], dst_ip[16]; + mac_to_str(event->meta.src_mac, src_mac, sizeof(src_mac)); + mac_to_str(event->meta.dst_mac, dst_mac, sizeof(dst_mac)); + ip_to_str(event->meta.src_ip, src_ip, sizeof(src_ip)); + ip_to_str(event->meta.dst_ip, dst_ip, sizeof(dst_ip)); + + printf("[%s] proto=%s reason=%s if=%u len=%u %s->%s %s->%s\n", + tag, + proto_to_name(event->meta.ip_proto), + reason_to_string(event->reason), + event->if_idx, + event->length, + src_ip, + dst_ip, + src_mac, + dst_mac); +} + +static wolfsentry_errcode_t icmp_mod7_action( + struct wolfsentry_context *wolfsentry, + struct wolfsentry_thread_context *thread, + const struct wolfsentry_action *action, + void *handler_arg, + void *caller_arg, + const struct wolfsentry_event *trigger_event, + wolfsentry_action_type_t action_type, + const struct wolfsentry_route *target_route, + struct wolfsentry_route_table *route_table, + struct wolfsentry_route *rule_route, + wolfsentry_action_res_t *action_results) +{ + struct icmp_filter_state *state = (struct icmp_filter_state *)handler_arg; + const struct wolfIP_filter_event *event = (const struct wolfIP_filter_event *)caller_arg; + (void)wolfsentry; + (void)thread; + (void)action; + (void)trigger_event; + (void)action_type; + (void)target_route; + (void)route_table; + (void)rule_route; + + if (!state || !event || (event->meta.ip_proto != WOLFIP_FILTER_PROTO_ICMP)) + return WOLFSENTRY_ERROR_ENCODE(OK); + + state->counter++; + if ((state->counter % 7) == 0) { + log_event(event, "drop-icmp-mod7"); + if (action_results) + *action_results |= WOLFSENTRY_ACTION_RES_REJECT | + WOLFSENTRY_ACTION_RES_DEROGATORY; + } + return WOLFSENTRY_ERROR_ENCODE(OK); +} + +static void stop_ping_process(void) +{ + if (ping_pid > 0) { + if (kill(ping_pid, SIGTERM) < 0 && errno != ESRCH) + perror("kill ping"); + while (waitpid(ping_pid, NULL, 0) < 0) { + if (errno == EINTR) + continue; + perror("waitpid ping"); + break; + } + ping_pid = -1; + } +} + +static void start_host_ping(void) +{ + if (ping_pid > 0) + return; + + pid_t pid = fork(); + if (pid < 0) { + perror("fork ping"); + return; + } + if (pid == 0) { + execlp("ping", "ping", "-n", "-i", "0.5", "-c", "100", + "-I", TAP_IFNAME, WOLFIP_IP, (char *)NULL); + perror("execlp ping"); + _exit(EXIT_FAILURE); + } + + ping_pid = pid; +} + +static void register_actions(void) +{ + wolfsentry_errcode_t ret; + wolfsentry_ent_id_t action_id; + + ret = wolfsentry_action_insert( + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), + "icmp-mod7", + WOLFSENTRY_LENGTH_NULL_TERMINATED, + WOLFSENTRY_ACTION_FLAG_NONE, + icmp_mod7_action, + &icmp_state, + &action_id); + if (ret < 0) { + fprintf(stderr, "wolfsentry_action_insert(icmp-mod7): " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(EXIT_FAILURE); + } +} + +static void load_config(const char *path) +{ + FILE *f = fopen(path, "r"); + if (!f) { + perror("fopen config"); + exit(EXIT_FAILURE); + } + + struct wolfsentry_json_process_state *jps; + wolfsentry_errcode_t ret = wolfsentry_config_json_init( + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), + WOLFSENTRY_CONFIG_LOAD_FLAG_NONE, + &jps); + if (ret < 0) { + fprintf(stderr, "wolfsentry_config_json_init: " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(EXIT_FAILURE); + } + + char buf[512], err_buf[512]; + while (!feof(f)) { + size_t n = fread(buf, 1, sizeof buf, f); + if (n == 0 && ferror(f)) { + perror("fread config"); + exit(EXIT_FAILURE); + } + ret = wolfsentry_config_json_feed(jps, (const unsigned char *)buf, n, err_buf, sizeof err_buf); + if (ret < 0) { + fprintf(stderr, "%.*s\n", (int)sizeof err_buf, err_buf); + exit(EXIT_FAILURE); + } + } + fclose(f); + + ret = wolfsentry_config_json_fini(&jps, err_buf, sizeof err_buf); + if (ret < 0) { + fprintf(stderr, "%.*s\n", (int)sizeof err_buf, err_buf); + exit(EXIT_FAILURE); + } +} + +static void install_filter_masks(void) +{ + wolfsentry_errcode_t ret; + uint32_t mask = WOLFIP_FILT_MASK(WOLFIP_FILT_RECEIVING); + + ret = wolfsentry_install_wolfip_filter_ethernet_callback( + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), + mask); + if (ret < 0) { + fprintf(stderr, "install ethernet callback failed: " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(EXIT_FAILURE); + } + + ret = wolfsentry_install_wolfip_filter_ip4_callbacks( + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), + mask); + if (ret < 0) { + fprintf(stderr, "install ip callback failed: " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(EXIT_FAILURE); + } + + ret = wolfsentry_install_wolfip_filter_icmp_callbacks( + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), + mask); + if (ret < 0) { + fprintf(stderr, "install icmp callback failed: " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + exit(EXIT_FAILURE); + } +} + +static struct wolfIP *start_wolfip(void) +{ + struct wolfIP *stack = NULL; + struct wolfIP_ll_dev *tapdev; + struct in_addr host_addr; + + wolfIP_init_static(&stack); + if (!stack) { + fprintf(stderr, "wolfIP_init_static failed\n"); + exit(EXIT_FAILURE); + } + + tapdev = wolfIP_getdev(stack); + if (!tapdev) { + fprintf(stderr, "wolfIP_getdev failed\n"); + exit(EXIT_FAILURE); + } + + if (inet_aton(HOST_STACK_IP, &host_addr) == 0) { + fprintf(stderr, "inet_aton failed for host stack IP\n"); + exit(EXIT_FAILURE); + } + + if (tap_init(tapdev, TAP_IFNAME, host_addr.s_addr) < 0) { + perror("tap_init"); + exit(EXIT_FAILURE); + } + + wolfIP_ipconfig_set(stack, + atoip4(WOLFIP_IP), + atoip4(WOLFIP_NETMASK), + atoip4(HOST_STACK_IP)); + + printf("wolfIP ready on %s (wolfIP=%s, host=%s)\n", + tapdev->ifname, + WOLFIP_IP, + HOST_STACK_IP); + return stack; +} + +int main(void) +{ + struct wolfIP *stack; + struct wolfsentry_eventconfig evconfig = { + .route_private_data_size = 32, + .route_private_data_alignment = 16 + }; + wolfsentry_errcode_t ret; + + signal(SIGINT, on_signal); + signal(SIGTERM, on_signal); + + ret = wolfsentry_init( + wolfsentry_build_settings, + WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(NULL /* hpi */, NULL /* thread */), + &evconfig, + &sentry); + if (ret < 0) { + fprintf(stderr, "wolfsentry_init failed: " + WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret)); + return EXIT_FAILURE; + } + + register_actions(); + load_config(CONFIG_PATH); + install_filter_masks(); + + stack = start_wolfip(); + start_host_ping(); + + while (!stop_flag) { + struct timeval tv; + gettimeofday(&tv, NULL); + uint32_t delay = wolfIP_poll(stack, tv.tv_sec * 1000 + tv.tv_usec / 1000); + usleep(delay * 1000); + } + + stop_ping_process(); + wolfsentry_cleanup_wolfip_filter_callbacks(WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(sentry, NULL), NULL); + wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX4(&sentry, NULL)); + + printf("Exiting.\n"); + return 0; +} +#include diff --git a/examples/Linux-wolfIP/wolfip-config.json b/examples/Linux-wolfIP/wolfip-config.json new file mode 100644 index 0000000..d49b332 --- /dev/null +++ b/examples/Linux-wolfIP/wolfip-config.json @@ -0,0 +1,39 @@ +{ + "wolfsentry-config-version": 1, + "events": [ + { + "label": "wolfip-ethernet", + "match-actions": [ ] + }, + { + "label": "wolfip-icmp", + "match-actions": [ "icmp-mod7" ] + } + ], + "default-policies": { + "default-policy": "accept", + "default-event": "wolfip-ethernet" + }, + "routes": [ + { + "parent-event": "wolfip-ethernet", + "family": 118, + "direction-in": true, + "direction-out": true, + "remote": { + "address": "00:00:00:00:00:00", + "prefix-bits": 0 + } + }, + { + "parent-event": "wolfip-icmp", + "family": 2, + "protocol": 1, + "direction-in": true, + "remote": { + "address": "0.0.0.0", + "prefix-bits": 0 + } + } + ] +} diff --git a/examples/Linux-wolfIP/wolfip/config.h b/examples/Linux-wolfIP/wolfip/config.h new file mode 100644 index 0000000..9019f83 --- /dev/null +++ b/examples/Linux-wolfIP/wolfip/config.h @@ -0,0 +1,33 @@ +#ifndef WOLFIP_CONFIG_H +#define WOLFIP_CONFIG_H + +#define CONFIG_IPFILTER 1 + +#define ETHERNET +#define LINK_MTU 1536 + +#define MAX_TCPSOCKETS 4 +#define MAX_UDPSOCKETS 2 +#define RXBUF_SIZE (LINK_MTU * 16) +#define TXBUF_SIZE (LINK_MTU * 16) + +#define MAX_NEIGHBORS 16 + +#ifndef WOLFIP_MAX_INTERFACES +#define WOLFIP_MAX_INTERFACES 2 +#endif + +#ifndef WOLFIP_ENABLE_FORWARDING +#define WOLFIP_ENABLE_FORWARDING 0 +#endif + +#ifndef WOLFIP_ENABLE_LOOPBACK +#define WOLFIP_ENABLE_LOOPBACK 0 +#endif + +#define WOLFIP_IP "10.10.10.2" +#define WOLFIP_NETMASK "255.255.255.0" +#define HOST_STACK_IP "10.10.10.1" +#define TAP_IFNAME "wolfip0" + +#endif /* WOLFIP_CONFIG_H */ diff --git a/src/wolfip/packet_filter_glue.c b/src/wolfip/packet_filter_glue.c new file mode 100644 index 0000000..2dcaec6 --- /dev/null +++ b/src/wolfip/packet_filter_glue.c @@ -0,0 +1,780 @@ +/* + * wolfip/packet_filter_glue.c + * + * Copyright (C) 2024-2025 wolfSSL Inc. + * + * This file is part of wolfSentry. + * + * wolfSentry is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSentry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include + +#include +#include + +#define WOLFSENTRY_SOURCE_ID WOLFSENTRY_SOURCE_ID_WOLFIP_PACKET_FILTER_GLUE_C + +#ifndef __STRICT_ANSI__ + #define __F__ __FUNCTION__ +#endif + +#ifndef WOLFIP_CONFIG_HEADER +#define WOLFIP_CONFIG_HEADER "../../../wolfip/config.h" +#endif +#include WOLFIP_CONFIG_HEADER + +#include +#include + +#if CONFIG_IPFILTER + +static struct wolfsentry_context *wolfip_filter_context; +static uint32_t wolfip_mask_eth; +static uint32_t wolfip_mask_ip; +static uint32_t wolfip_mask_icmp; +static uint32_t wolfip_mask_tcp; +static uint32_t wolfip_mask_udp; +static int wolfip_cleanup_registered; + +static int wolfip_filter_with_wolfsentry(void *arg, const struct wolfIP_filter_event *event); + +static wolfsentry_errcode_t wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_IN); + +static byte wolfip_if_idx_to_byte(unsigned int if_idx) +{ + return (if_idx > 0xffU) ? 0xffU : (byte)if_idx; +} + +static int wolfip_is_direction_out(enum wolfIP_filter_reason reason) +{ + switch (reason) { + case WOLFIP_FILT_SENDING: + case WOLFIP_FILT_CONNECTING: + case WOLFIP_FILT_DISSOCIATE: + case WOLFIP_FILT_OUTBOUND_ERR: + case WOLFIP_FILT_CLOSED: + return 1; + default: + return 0; + } +} + +static void wolfip_set_ipv4_sockaddrs( + struct wolfsentry_sockaddr *remote, + struct wolfsentry_sockaddr *local, + const struct wolfIP_filter_event *event, + int outbound) +{ + uint32_t remote_ip = outbound ? event->meta.dst_ip : event->meta.src_ip; + uint32_t local_ip = outbound ? event->meta.src_ip : event->meta.dst_ip; + + remote->sa_family = WOLFSENTRY_AF_INET; + remote->addr_len = sizeof(remote_ip) * 8; + memcpy(&remote->addr, &remote_ip, sizeof remote_ip); + remote->sa_port = 0; + remote->interface = wolfip_if_idx_to_byte(event->if_idx); + + local->sa_family = WOLFSENTRY_AF_INET; + local->addr_len = sizeof(local_ip) * 8; + memcpy(&local->addr, &local_ip, sizeof local_ip); + local->sa_port = 0; + local->interface = wolfip_if_idx_to_byte(event->if_idx); +} + +static void wolfip_set_link_sockaddrs( + struct wolfsentry_sockaddr *remote, + struct wolfsentry_sockaddr *local, + const struct wolfIP_filter_event *event, + int outbound) +{ + const uint8_t *remote_mac = outbound ? event->meta.dst_mac : event->meta.src_mac; + const uint8_t *local_mac = outbound ? event->meta.src_mac : event->meta.dst_mac; + + remote->sa_family = WOLFSENTRY_AF_LINK; + remote->addr_len = sizeof(event->meta.src_mac) * 8; + memcpy(&remote->addr, remote_mac, sizeof(event->meta.src_mac)); + remote->sa_port = 0; + remote->sa_proto = event->meta.eth_type; + remote->interface = wolfip_if_idx_to_byte(event->if_idx); + + local->sa_family = WOLFSENTRY_AF_LINK; + local->addr_len = sizeof(event->meta.src_mac) * 8; + memcpy(&local->addr, local_mac, sizeof(event->meta.src_mac)); + local->sa_port = 0; + local->sa_proto = event->meta.eth_type; + local->interface = wolfip_if_idx_to_byte(event->if_idx); +} + +static int wolfip_action_rejects(wolfsentry_action_res_t action_results) +{ + if (WOLFSENTRY_MASKIN_BITS(action_results, WOLFSENTRY_ACTION_RES_REJECT)) + return 1; + if (WOLFSENTRY_MASKIN_BITS(action_results, WOLFSENTRY_ACTION_RES_PORT_RESET)) + return 1; + return 0; +} + +static int wolfip_dispatch_event( + struct wolfsentry_context *wolfsentry, + wolfsentry_route_flags_t route_flags, + wolfsentry_action_res_t *action_results, + struct wolfsentry_sockaddr *remote, + struct wolfsentry_sockaddr *local, + const struct wolfIP_filter_event *event) +{ + wolfsentry_errcode_t ws_ret; + WOLFSENTRY_THREAD_HEADER_DECLS + + if (wolfsentry == NULL) + return 0; + + if (WOLFSENTRY_THREAD_HEADER_INIT(WOLFSENTRY_THREAD_FLAG_NONE) < 0) + return -WOLFIP_EACCES; + + ws_ret = wolfsentry_route_event_dispatch_with_inited_result( + WOLFSENTRY_CONTEXT_ARGS_OUT, + remote, + local, + route_flags, + NULL /* event_label */, + 0, + (void *)event, + NULL, + NULL, + action_results); + + WOLFSENTRY_WARN_ON_FAILURE(ws_ret); + + if (WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE) < 0) + return -WOLFIP_EACCES; + + if (wolfip_action_rejects(*action_results)) + return -WOLFIP_EACCES; + + return 0; +} + +static int wolfip_filter_ethernet( + struct wolfsentry_context *wolfsentry, + const struct wolfIP_filter_event *event) +{ + wolfsentry_route_flags_t route_flags = + WOLFSENTRY_ROUTE_FLAG_PARENT_EVENT_WILDCARD; + wolfsentry_action_res_t action_results = WOLFSENTRY_ACTION_RES_NONE; + int outbound = 0; + int ret; + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_mac), + remote); + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_mac), + local); + + switch (event->reason) { + case WOLFIP_FILT_RECEIVING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_RECEIVED; + break; + case WOLFIP_FILT_SENDING: + outbound = 1; + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SENDING; + break; + case WOLFIP_FILT_INBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_OUTBOUND_ERR: + outbound = 1; + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + default: + return 0; + } + + wolfip_set_link_sockaddrs(&remote.remote, &local.local, event, outbound); + ret = wolfip_dispatch_event(wolfsentry, route_flags, &action_results, &remote.remote, &local.local, event); + return ret; +} + +static int wolfip_filter_ipv4( + struct wolfsentry_context *wolfsentry, + const struct wolfIP_filter_event *event) +{ + wolfsentry_route_flags_t route_flags = + WOLFSENTRY_ROUTE_FLAG_PARENT_EVENT_WILDCARD; + wolfsentry_action_res_t action_results = WOLFSENTRY_ACTION_RES_NONE; + int outbound = 0; + int ret; + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + remote); + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + local); + switch (event->reason) { + case WOLFIP_FILT_RECEIVING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_RECEIVED; + break; + case WOLFIP_FILT_SENDING: + outbound = 1; + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SENDING; + break; + case WOLFIP_FILT_ADDR_UNREACHABLE: + case WOLFIP_FILT_PORT_UNREACHABLE: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_UNREACHABLE; + break; + case WOLFIP_FILT_INBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_OUTBOUND_ERR: + outbound = 1; + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + default: + return 0; + } + + wolfip_set_ipv4_sockaddrs(&remote.remote, &local.local, event, outbound); + remote.remote.sa_proto = local.local.sa_proto = 0; + ret = wolfip_dispatch_event(wolfsentry, route_flags, &action_results, &remote.remote, &local.local, event); + return ret; +} + +static int wolfip_filter_tcp( + struct wolfsentry_context *wolfsentry, + const struct wolfIP_filter_event *event) +{ + wolfsentry_route_flags_t route_flags = + WOLFSENTRY_ROUTE_FLAG_TCPLIKE_PORT_NUMBERS | + WOLFSENTRY_ROUTE_FLAG_PARENT_EVENT_WILDCARD; + wolfsentry_action_res_t action_results = WOLFSENTRY_ACTION_RES_NONE; + int outbound = wolfip_is_direction_out(event->reason); + int ret; + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + remote); + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + local); + switch (event->reason) { + case WOLFIP_FILT_ACCEPTING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_CONNECT; + break; + case WOLFIP_FILT_CONNECTING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_CONNECTING_OUT; + break; + case WOLFIP_FILT_REMOTE_RESET: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_DISCONNECT; + break; + case WOLFIP_FILT_CLOSED: + route_flags |= outbound ? WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT : + WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = outbound ? WOLFSENTRY_ACTION_RES_CLOSED : + WOLFSENTRY_ACTION_RES_DISCONNECT; + break; + case WOLFIP_FILT_CLOSE_WAIT: + route_flags |= outbound ? WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT : + WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + break; + case WOLFIP_FILT_PORT_UNREACHABLE: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_UNREACHABLE | + WOLFSENTRY_ACTION_RES_DEROGATORY; + break; + case WOLFIP_FILT_BINDING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_BINDING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + case WOLFIP_FILT_LISTENING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_LISTENING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + case WOLFIP_FILT_STOP_LISTENING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_STOPPED_LISTENING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + case WOLFIP_FILT_RECEIVING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_RECEIVED; + break; + case WOLFIP_FILT_SENDING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SENDING; + break; + case WOLFIP_FILT_INBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_OUTBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_DISSOCIATE: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_DEROGATORY; + break; + default: + return 0; + } + + wolfip_set_ipv4_sockaddrs(&remote.remote, &local.local, event, outbound); + remote.remote.sa_proto = local.local.sa_proto = IPPROTO_TCP; + + if (event->meta.ip_proto == WOLFIP_FILTER_PROTO_TCP) { + uint16_t remote_port = outbound ? ee16(event->meta.l4.tcp.dst_port) : + ee16(event->meta.l4.tcp.src_port); + uint16_t local_port = outbound ? ee16(event->meta.l4.tcp.src_port) : + ee16(event->meta.l4.tcp.dst_port); + remote.remote.sa_port = remote_port; + local.local.sa_port = local_port; + } + + ret = wolfip_dispatch_event(wolfsentry, route_flags, &action_results, &remote.remote, &local.local, event); + return ret; +} + +static int wolfip_filter_udp( + struct wolfsentry_context *wolfsentry, + const struct wolfIP_filter_event *event) +{ + wolfsentry_route_flags_t route_flags = + WOLFSENTRY_ROUTE_FLAG_PARENT_EVENT_WILDCARD; + wolfsentry_action_res_t action_results = WOLFSENTRY_ACTION_RES_NONE; + int outbound = wolfip_is_direction_out(event->reason); + int ret; + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + remote); + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + local); + switch (event->reason) { + case WOLFIP_FILT_RECEIVING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_RECEIVED; + break; + case WOLFIP_FILT_SENDING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SENDING; + break; + case WOLFIP_FILT_PORT_UNREACHABLE: + case WOLFIP_FILT_ADDR_UNREACHABLE: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_UNREACHABLE; + break; + case WOLFIP_FILT_INBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_OUTBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_BINDING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_BINDING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + case WOLFIP_FILT_LISTENING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_LISTENING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + case WOLFIP_FILT_STOP_LISTENING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_ADDR_WILDCARD | + WOLFSENTRY_ROUTE_FLAG_SA_REMOTE_PORT_WILDCARD; + action_results = WOLFSENTRY_ACTION_RES_STOPPED_LISTENING | + WOLFSENTRY_ACTION_RES_EXCLUDE_REJECT_ROUTES; + break; + default: + return 0; + } + + wolfip_set_ipv4_sockaddrs(&remote.remote, &local.local, event, outbound); + remote.remote.sa_proto = local.local.sa_proto = IPPROTO_UDP; + + if (event->meta.ip_proto == WOLFIP_FILTER_PROTO_UDP) { + uint16_t remote_port = outbound ? ee16(event->meta.l4.udp.dst_port) : + ee16(event->meta.l4.udp.src_port); + uint16_t local_port = outbound ? ee16(event->meta.l4.udp.src_port) : + ee16(event->meta.l4.udp.dst_port); + remote.remote.sa_port = remote_port; + local.local.sa_port = local_port; + } + + ret = wolfip_dispatch_event(wolfsentry, route_flags, &action_results, &remote.remote, &local.local, event); + return ret; +} + +static int wolfip_filter_icmp( + struct wolfsentry_context *wolfsentry, + const struct wolfIP_filter_event *event) +{ + wolfsentry_route_flags_t route_flags = + WOLFSENTRY_ROUTE_FLAG_PARENT_EVENT_WILDCARD; + wolfsentry_action_res_t action_results = WOLFSENTRY_ACTION_RES_NONE; + int outbound = wolfip_is_direction_out(event->reason); + int ret; + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + remote); + WOLFSENTRY_STACKBUF( + struct wolfsentry_sockaddr, + addr, + sizeof(event->meta.src_ip), + local); + + switch (event->reason) { + case WOLFIP_FILT_RECEIVING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_RECEIVED; + break; + case WOLFIP_FILT_SENDING: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SENDING; + break; + case WOLFIP_FILT_ADDR_UNREACHABLE: + case WOLFIP_FILT_PORT_UNREACHABLE: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_UNREACHABLE; + break; + case WOLFIP_FILT_INBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + case WOLFIP_FILT_OUTBOUND_ERR: + route_flags |= WOLFSENTRY_ROUTE_FLAG_DIRECTION_OUT; + action_results = WOLFSENTRY_ACTION_RES_SOCK_ERROR; + break; + default: + return 0; + } + + wolfip_set_ipv4_sockaddrs(&remote.remote, &local.local, event, outbound); + remote.remote.sa_proto = local.local.sa_proto = IPPROTO_ICMP; + + ret = wolfip_dispatch_event(wolfsentry, route_flags, &action_results, &remote.remote, &local.local, event); + return ret; +} + +static int wolfip_filter_with_wolfsentry(void *arg, const struct wolfIP_filter_event *event) +{ + struct wolfsentry_context *wolfsentry = (struct wolfsentry_context *)arg; + + if ((wolfsentry == NULL) || (event == NULL)) + return 0; + + switch (event->meta.ip_proto) { + case WOLFIP_FILTER_PROTO_ETH: + return wolfip_filter_ethernet(wolfsentry, event); + case WOLFIP_FILTER_PROTO_IP: + return wolfip_filter_ipv4(wolfsentry, event); + case WOLFIP_FILTER_PROTO_TCP: + return wolfip_filter_tcp(wolfsentry, event); + case WOLFIP_FILTER_PROTO_UDP: + return wolfip_filter_udp(wolfsentry, event); + case WOLFIP_FILTER_PROTO_ICMP: + return wolfip_filter_icmp(wolfsentry, event); + default: + return 0; + } +} + +static wolfsentry_errcode_t wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_IN) +{ + uint32_t combined = wolfip_mask_eth | wolfip_mask_ip | wolfip_mask_icmp | + wolfip_mask_tcp | wolfip_mask_udp; + wolfsentry_errcode_t ret = WOLFSENTRY_ERROR_ENCODE(OK); + + if (combined) { + if (wolfip_filter_context && (wolfip_filter_context != wolfsentry)) + return WOLFSENTRY_ERROR_ENCODE(INCOMPATIBLE_STATE); + if (!wolfip_cleanup_registered) { + ret = wolfsentry_cleanup_push(WOLFSENTRY_CONTEXT_ARGS_OUT, wolfsentry_cleanup_wolfip_filter_callbacks, NULL); + if (ret < 0) + return ret; + wolfip_cleanup_registered = 1; + } + wolfip_filter_context = wolfsentry; + wolfIP_filter_set_callback(wolfip_filter_with_wolfsentry, wolfsentry); + } else { + wolfIP_filter_set_callback(NULL, NULL); + wolfip_filter_context = NULL; + } + + wolfIP_filter_set_eth_mask(wolfip_mask_eth); + wolfIP_filter_set_ip_mask(wolfip_mask_ip); + wolfIP_filter_set_icmp_mask(wolfip_mask_icmp); + wolfIP_filter_set_tcp_mask(wolfip_mask_tcp); + wolfIP_filter_set_udp_mask(wolfip_mask_udp); + + return ret; +} + +WOLFSENTRY_API_VOID wolfsentry_cleanup_wolfip_filter_callbacks(WOLFSENTRY_CONTEXT_ARGS_IN, void *cleanup_arg) +{ + (void)wolfsentry; + (void)thread; + (void)cleanup_arg; + wolfip_mask_eth = wolfip_mask_ip = wolfip_mask_icmp = wolfip_mask_tcp = wolfip_mask_udp = 0; + wolfip_cleanup_registered = 0; + wolfIP_filter_set_callback(NULL, NULL); + wolfIP_filter_set_eth_mask(0); + wolfIP_filter_set_ip_mask(0); + wolfIP_filter_set_icmp_mask(0); + wolfIP_filter_set_tcp_mask(0); + wolfIP_filter_set_udp_mask(0); + wolfip_filter_context = NULL; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ethernet_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + wolfip_mask_eth = ethernet_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ip4_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ip_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + wolfip_mask_ip = ip_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_icmp_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t icmp_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + wolfip_mask_icmp = icmp_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_tcp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t tcp_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + if (tcp_mask & (WOLFIP_FILT_MASK(WOLFIP_FILT_ACCEPTING) | + WOLFIP_FILT_MASK(WOLFIP_FILT_CLOSED) | + WOLFIP_FILT_MASK(WOLFIP_FILT_REMOTE_RESET))) + tcp_mask |= WOLFIP_FILT_MASK(WOLFIP_FILT_ACCEPTING) | + WOLFIP_FILT_MASK(WOLFIP_FILT_CLOSED) | + WOLFIP_FILT_MASK(WOLFIP_FILT_REMOTE_RESET); + wolfip_mask_tcp = tcp_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_udp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t udp_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + wolfip_mask_udp = udp_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask, + uint32_t ip_mask, + uint32_t icmp_mask, + uint32_t tcp_mask, + uint32_t udp_mask) +{ + wolfsentry_errcode_t ret; + + WOLFSENTRY_MUTEX_OR_RETURN(); + (void)thread; + wolfip_mask_eth = ethernet_mask; + wolfip_mask_ip = ip_mask; + wolfip_mask_icmp = icmp_mask; + wolfip_mask_tcp = tcp_mask; + wolfip_mask_udp = udp_mask; + ret = wolfip_apply_masks(WOLFSENTRY_CONTEXT_ARGS_OUT); + WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret); +} + +#else /* !CONFIG_IPFILTER */ + +WOLFSENTRY_API_VOID wolfsentry_cleanup_wolfip_filter_callbacks(WOLFSENTRY_CONTEXT_ARGS_IN, void *cleanup_arg) +{ + (void)thread; + (void)cleanup_arg; + (void)wolfsentry; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ethernet_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask) +{ + (void)thread; + (void)wolfsentry; + if (ethernet_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ip4_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ip_mask) +{ + (void)thread; + (void)wolfsentry; + if (ip_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_icmp_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t icmp_mask) +{ + (void)thread; + (void)wolfsentry; + if (icmp_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_tcp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t tcp_mask) +{ + (void)thread; + (void)wolfsentry; + if (tcp_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_udp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t udp_mask) +{ + (void)thread; + (void)wolfsentry; + if (udp_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask, + uint32_t ip_mask, + uint32_t icmp_mask, + uint32_t tcp_mask, + uint32_t udp_mask) +{ + (void)thread; + (void)wolfsentry; + if (ethernet_mask || ip_mask || icmp_mask || tcp_mask || udp_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +#endif /* CONFIG_IPFILTER */ + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ip6_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ip_mask) +{ + (void)thread; + (void)wolfsentry; + if (ip_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_icmp6_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t icmp_mask) +{ + (void)thread; + (void)wolfsentry; + if (icmp_mask) + WOLFSENTRY_ERROR_RETURN(IMPLEMENTATION_MISSING); + WOLFSENTRY_RETURN_OK; +} diff --git a/src/wolfsentry_util.c b/src/wolfsentry_util.c index be01b60..c02d8e6 100644 --- a/src/wolfsentry_util.c +++ b/src/wolfsentry_util.c @@ -69,6 +69,8 @@ WOLFSENTRY_API const char *wolfsentry_errcode_source_string(wolfsentry_errcode_t return "lwip/packet_filter_glue.c"; case WOLFSENTRY_SOURCE_ID_ACTION_BUILTINS_C: return "action_builtins.c"; + case WOLFSENTRY_SOURCE_ID_WOLFIP_PACKET_FILTER_GLUE_C: + return "wolfip/packet_filter_glue.c"; case WOLFSENTRY_SOURCE_ID_USER_BASE: break; diff --git a/wolfsentry/wolfsentry.h b/wolfsentry/wolfsentry.h index a9a0ea1..b5d7529 100644 --- a/wolfsentry/wolfsentry.h +++ b/wolfsentry/wolfsentry.h @@ -3364,6 +3364,10 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_base64_decode( #include "wolfsentry/wolfsentry_lwip.h" #endif +#ifdef WOLFSENTRY_WOLFIP + #include "wolfsentry/wolfsentry_wolfip.h" +#endif + #ifdef WOLFSENTRY_NETXDUO #include "wolfsentry/wolfsentry_netxduo.h" #endif diff --git a/wolfsentry/wolfsentry_errcodes.h b/wolfsentry/wolfsentry_errcodes.h index 2eb84ef..6dda150 100644 --- a/wolfsentry/wolfsentry_errcodes.h +++ b/wolfsentry/wolfsentry_errcodes.h @@ -379,6 +379,7 @@ enum wolfsentry_source_id { WOLFSENTRY_SOURCE_ID_JSON_JSON_UTIL_C = 9, WOLFSENTRY_SOURCE_ID_LWIP_PACKET_FILTER_GLUE_C = 10, WOLFSENTRY_SOURCE_ID_ACTION_BUILTINS_C = 11, + WOLFSENTRY_SOURCE_ID_WOLFIP_PACKET_FILTER_GLUE_C = 12, WOLFSENTRY_SOURCE_ID_USER_BASE = 112 }; diff --git a/wolfsentry/wolfsentry_wolfip.h b/wolfsentry/wolfsentry_wolfip.h new file mode 100644 index 0000000..c91a1bf --- /dev/null +++ b/wolfsentry/wolfsentry_wolfip.h @@ -0,0 +1,72 @@ +/* + * wolfsentry_wolfip.h + * + * Copyright (C) 2025 wolfSSL Inc. + * + * This file is part of wolfSentry. + * + * wolfSentry is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSentry is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! @file wolfsentry_wolfip.h + * \brief Prototypes for wolfIP callback installation functions. + */ + +#ifndef WOLFSENTRY_WOLFIP_H +#define WOLFSENTRY_WOLFIP_H + +#include + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ethernet_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ip4_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ip_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_ip6_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ip_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_icmp_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t icmp_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_icmp6_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t icmp_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_tcp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t tcp_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_udp_callback( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t udp_mask); + +WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_install_wolfip_filter_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + uint32_t ethernet_mask, + uint32_t ip_mask, + uint32_t icmp_mask, + uint32_t tcp_mask, + uint32_t udp_mask); + +WOLFSENTRY_API_VOID wolfsentry_cleanup_wolfip_filter_callbacks( + WOLFSENTRY_CONTEXT_ARGS_IN, + void *cleanup_arg); + +#endif /* WOLFSENTRY_WOLFIP_H */