From 7f71eeda3e07536028469ec705b911d72e6698d2 Mon Sep 17 00:00:00 2001 From: P1F Date: Sun, 6 Nov 2022 23:13:03 -0300 Subject: [PATCH] Add iptlite packet filter module --- net/devif/Make.defs | 6 ++ net/devif/devif.h | 15 +++ net/devif/devif_pktfilter.c | 195 ++++++++++++++++++++++++++++++++++++ net/devif/ipv4_input.c | 7 ++ net/net_initialize.c | 6 ++ 5 files changed, 229 insertions(+) create mode 100644 net/devif/devif_pktfilter.c diff --git a/net/devif/Make.defs b/net/devif/Make.defs index 3fcfbf6135826..29fb7ca55f01b 100644 --- a/net/devif/Make.defs +++ b/net/devif/Make.defs @@ -55,6 +55,12 @@ ifeq ($(CONFIG_NET_CAN),y) NET_CSRCS += devif_cansend.c endif +# iptlite packet filter support + +ifeq ($(CONFIG_NETUTILS_IPTLITE),y) +NET_CSRCS += devif_pktfilter.c +endif + # Include network device interface build support DEPPATH += --dep-path devif diff --git a/net/devif/devif.h b/net/devif/devif.h index 4393e4be1a285..ff506d60502f3 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -284,6 +284,21 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +#ifdef CONFIG_NETUTILS_IPTLITE +#define RULE_INFO_MAX_SIZE 100 +#define RULE_MAX_SIZE 10 +#define PORTSTRLEN 6 + +void nflite_initialize(void); +bool nflite_addrule(int rule, +in_addr_t srcipaddr, in_addr_t destipaddr, \ +in_port_t srcport, in_port_t destport); +bool nflite_verify_ipv4(FAR struct net_driver_s *dev); +void nflite_flushall(void); +char** nflite_listall(void); +int nflite_get_rules_counter(void); +#endif + /**************************************************************************** * Name: devif_initialize * diff --git a/net/devif/devif_pktfilter.c b/net/devif/devif_pktfilter.c new file mode 100644 index 0000000000000..40ecfabd0a57e --- /dev/null +++ b/net/devif/devif_pktfilter.c @@ -0,0 +1,195 @@ +/**************************************************************************** + * net/devif/devif_pktfilter.c + * iptlite packet filter modules + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include "devif.h" +#include +#include +#include + +typedef enum rules +{ + DROP, + FLUSHALL, + LISTALL +} rules; + +typedef struct chain chain; + +struct chain +{ + rules rule; + in_addr_t srcipaddr; + in_addr_t destipaddr; + in_port_t srcport; + in_port_t destport; + chain *next; +}; + +chain *chain_head; +chain *last_rule; +int rules_counter; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +char *get_rule_name(rules rule) +{ + switch (rule) + { + case DROP: + return "DROP"; + case FLUSHALL: + return "FLUSHALL"; + case LISTALL: + return "LISTALL"; + } + + return "UNDEFINED"; +} + +void get_rule_info(chain *node, char **table, int idx) +{ + char srcipaddr[INET_ADDRSTRLEN]; + char destipaddr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &node->srcipaddr, srcipaddr, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &node->destipaddr, destipaddr, INET_ADDRSTRLEN); + + int srcport = ntohs(node->srcport); + int destport = ntohs(node->destport); + + char rule[RULE_MAX_SIZE]; + strcpy(rule, get_rule_name(node->rule)); + + char rule_info[RULE_INFO_MAX_SIZE]; + sprintf(rule_info, "%2d: %10s %16s %16s %9d %9d", + idx, rule, srcipaddr, destipaddr, srcport, destport); + + strcpy(table[idx], rule_info); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void nflite_initialize(void) +{ + chain_head = (chain *)malloc(sizeof(chain)); + chain_head->next = NULL; + rules_counter = 0; + + last_rule = chain_head; +} + +bool nflite_addrule(int rule, in_addr_t srcipaddr, in_addr_t destipaddr, + in_port_t srcport, in_port_t destport) +{ + chain *new_chainrule = (chain *)malloc(sizeof(chain)); + if (new_chainrule == NULL) return false; + + new_chainrule->rule = rule; + new_chainrule->srcipaddr = srcipaddr; + new_chainrule->destipaddr = destipaddr; + new_chainrule->srcport = srcport; + new_chainrule->destport = destport; + new_chainrule->next = NULL; + + last_rule->next = new_chainrule; + last_rule = last_rule->next; + rules_counter++; + + return true; +} + +bool nflite_verify_ipv4(FAR struct net_driver_s *dev) +{ + FAR struct ipv4_hdr_s *ipv4; + FAR struct tcp_hdr_s *tcp; + in_addr_t destipaddr; + in_addr_t srcipaddr; + in_port_t srcport; + in_port_t destport; + uint16_t iphdrlen; + + ipv4 = ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)]); + iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2; + tcp = (FAR struct tcp_hdr_s *)&dev->d_buf[iphdrlen + NET_LL_HDRLEN(dev)]; + + destipaddr = net_ip4addr_conv32(ipv4->destipaddr); + srcipaddr = net_ip4addr_conv32(ipv4->srcipaddr); + srcport = tcp->srcport; + destport = tcp->destport; + + chain *current_rule = chain_head->next; + while (current_rule) + { + /* Verify incoming tuple */ + + if ((current_rule->destipaddr == 0 \ + || current_rule->destipaddr == destipaddr) \ + && (current_rule->srcipaddr == 0 \ + || current_rule->srcipaddr == srcipaddr) \ + && (current_rule->destport == 0 \ + || current_rule->destport == destport) \ + && (current_rule->srcport == 0 \ + || current_rule->srcport == srcport)) return false; + + current_rule = current_rule->next; + } + + return true; +} + +void nflite_flushall(void) +{ + chain *current_rule = chain_head->next; + chain *head = chain_head->next; + while (head != NULL) + { + current_rule = head; + head = head->next; + free(current_rule); + } + + chain_head->next = NULL; + rules_counter = 0; + + last_rule = chain_head; +} + +char **nflite_listall(void) +{ + chain *head = chain_head->next; + char **table = (char **)malloc(rules_counter * sizeof(char *)); + + for (int i = 0; i < rules_counter; i++) + { + table[i] = (char *)malloc(RULE_INFO_MAX_SIZE * sizeof(char)); + } + + int idx = 0; + while (head != NULL) + { + get_rule_info(head, table, idx); + head = head->next; + idx++; + } + + return table; +} + +int nflite_get_rules_counter(void) +{ + return rules_counter; +} diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c index 338d18f36565e..2949c87fdc7a1 100644 --- a/net/devif/ipv4_input.c +++ b/net/devif/ipv4_input.c @@ -210,6 +210,13 @@ int ipv4_input(FAR struct net_driver_s *dev) destipaddr = net_ip4addr_conv32(ipv4->destipaddr); +#ifdef CONFIG_NETUTILS_IPTLITE + /* Check if packet needs to be dropped */ + + bool is_valid_packet = nflite_verify_ipv4(dev); + if (!is_valid_packet) goto drop; +#endif + #if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK) /* If IP broadcast support is configured, we check for a broadcast * UDP packet, which may be destined to us (even if there is no IP diff --git a/net/net_initialize.c b/net/net_initialize.c index 0fa2536598778..12800c2e186fd 100644 --- a/net/net_initialize.c +++ b/net/net_initialize.c @@ -168,6 +168,12 @@ void net_initialize(void) usrsock_initialize(); #endif + +#ifdef CONFIG_NETUTILS_IPTLITE + /* Initialize the iptlite packet filter modules */ + + nflite_initialize(); +#endif } #endif /* CONFIG_NET */