From 528d926b04ac5015773bcb946dc5e1b3269d5510 Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Tue, 13 Dec 2022 16:08:24 +0800 Subject: [PATCH] net: Add set/getsockopt options compatible with iptables. Signed-off-by: Zhe Weng --- include/nuttx/net/netfilter/ip_tables.h | 12 + include/nuttx/net/netfilter/nf_nat.h | 6 + net/Kconfig | 1 + net/Makefile | 1 + net/inet/Make.defs | 2 +- net/inet/inet.h | 32 ++ net/inet/inet_sockif.c | 24 +- net/inet/ipv4_getsockopt.c | 97 ++++++ net/inet/ipv4_setsockopt.c | 7 + net/netfilter/Kconfig | 13 + net/netfilter/Make.defs | 36 ++ net/netfilter/ipt_nat.c | 126 +++++++ net/netfilter/ipt_sockopt.c | 440 ++++++++++++++++++++++++ net/netfilter/iptables.h | 109 ++++++ 14 files changed, 895 insertions(+), 11 deletions(-) create mode 100644 net/inet/ipv4_getsockopt.c create mode 100644 net/netfilter/Kconfig create mode 100644 net/netfilter/Make.defs create mode 100644 net/netfilter/ipt_nat.c create mode 100644 net/netfilter/ipt_sockopt.c create mode 100644 net/netfilter/iptables.h diff --git a/include/nuttx/net/netfilter/ip_tables.h b/include/nuttx/net/netfilter/ip_tables.h index 4b7bb610e6ed4..0ac092fce0182 100644 --- a/include/nuttx/net/netfilter/ip_tables.h +++ b/include/nuttx/net/netfilter/ip_tables.h @@ -60,6 +60,18 @@ #define IPT_TARGET(e) \ ((FAR struct xt_entry_target *)((FAR uint8_t *)(e) + (e)->target_offset)) +/* Auto fill common fields of entry and target. */ + +#define IPT_FILL_ENTRY(e, target_name) \ + do \ + { \ + (e)->entry.target_offset = sizeof((e)->entry); \ + (e)->entry.next_offset = sizeof(*(e)); \ + (e)->target.target.u.target_size = sizeof(*(e)) - sizeof((e)->entry); \ + strcpy((e)->target.target.u.user.name, (target_name)); \ + } \ + while(0) + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/include/nuttx/net/netfilter/nf_nat.h b/include/nuttx/net/netfilter/nf_nat.h index 9d59d273bbfb5..8844885d764e6 100644 --- a/include/nuttx/net/netfilter/nf_nat.h +++ b/include/nuttx/net/netfilter/nf_nat.h @@ -27,6 +27,12 @@ #include +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define TABLE_NAME_NAT "nat" + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/net/Kconfig b/net/Kconfig index 5a8f0c0e2d5b9..53134fd980371 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -330,6 +330,7 @@ menuconfig NET_6LOWPAN source "net/sixlowpan/Kconfig" source "net/ipforward/Kconfig" source "net/nat/Kconfig" +source "net/netfilter/Kconfig" endmenu # Internet Protocol Selection diff --git a/net/Makefile b/net/Makefile index e9e80904db17b..7d81a4db4a30f 100644 --- a/net/Makefile +++ b/net/Makefile @@ -48,6 +48,7 @@ include ieee802154/Make.defs include devif/Make.defs include ipforward/Make.defs include nat/Make.defs +include netfilter/Make.defs include route/Make.defs include procfs/Make.defs include usrsock/Make.defs diff --git a/net/inet/Make.defs b/net/inet/Make.defs index 0fcbf4f2bc55d..498d15e679efb 100644 --- a/net/inet/Make.defs +++ b/net/inet/Make.defs @@ -31,7 +31,7 @@ SOCK_CSRCS += inet_globals.c endif ifeq ($(CONFIG_NET_IPv4),y) -SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockname.c ipv4_getpeername.c ipv4_build_header.c +SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockopt.c ipv4_getsockname.c ipv4_getpeername.c ipv4_build_header.c endif ifeq ($(CONFIG_NET_IPv6),y) diff --git a/net/inet/inet.h b/net/inet/inet.h index 2eaf1d8a07045..6dc2fdf4a6e8e 100644 --- a/net/inet/inet.h +++ b/net/inet/inet.h @@ -161,6 +161,38 @@ int ipv6_setsockopt(FAR struct socket *psock, int option, FAR const void *value, socklen_t value_len); #endif +/**************************************************************************** + * Name: ipv4_getsockopt + * + * Description: + * ipv4_getsockopt() retrieve the value for the option specified by the + * 'option' argument for the socket specified by the 'psock' argument. If + * the size of the option value is greater than 'value_len', the value + * stored in the object pointed to by the 'value' argument will be silently + * truncated. Otherwise, the length pointed to by the 'value_len' argument + * will be modified to indicate the actual length of the 'value'. + * + * See for the a complete list of values of IPv4 protocol + * socket options. + * + * Input Parameters: + * psock Socket structure of the socket to query + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * Returns zero (OK) on success. On failure, it returns a negated errno + * value to indicate the nature of the error. See psock_getsockopt() for + * the list of possible error values. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +int ipv4_getsockopt(FAR struct socket *psock, int option, + FAR void *value, FAR socklen_t *value_len); +#endif + /**************************************************************************** * Name: ipv4_getsockname and ipv6_sockname * diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index a7b1030a80aaa..85f12a0521264 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -739,19 +739,23 @@ static int inet_get_socketlevel_option(FAR struct socket *psock, int option, static int inet_getsockopt(FAR struct socket *psock, int level, int option, FAR void *value, FAR socklen_t *value_len) { - if (level == SOL_SOCKET) + switch (level) { - return inet_get_socketlevel_option(psock, option, value, value_len); - } + case SOL_SOCKET: + return inet_get_socketlevel_option(psock, option, value, value_len); + #ifdef CONFIG_NET_TCPPROTO_OPTIONS - else if (level == IPPROTO_TCP) - { - return tcp_getsockopt(psock, option, value, value_len); - } + case IPPROTO_TCP: + return tcp_getsockopt(psock, option, value, value_len); #endif - else - { - return -ENOPROTOOPT; + +#ifdef CONFIG_NET_IPv4 + case IPPROTO_IP: + return ipv4_getsockopt(psock, option, value, value_len); +#endif + + default: + return -ENOPROTOOPT; } } diff --git a/net/inet/ipv4_getsockopt.c b/net/inet/ipv4_getsockopt.c new file mode 100644 index 0000000000000..36ef1f070877e --- /dev/null +++ b/net/inet/ipv4_getsockopt.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * net/inet/ipv4_getsockopt.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +#include "netfilter/iptables.h" + +#ifdef CONFIG_NET_IPv4 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv4_getsockopt + * + * Description: + * ipv4_getsockopt() retrieve the value for the option specified by the + * 'option' argument for the socket specified by the 'psock' argument. If + * the size of the option value is greater than 'value_len', the value + * stored in the object pointed to by the 'value' argument will be silently + * truncated. Otherwise, the length pointed to by the 'value_len' argument + * will be modified to indicate the actual length of the 'value'. + * + * See for the a complete list of values of IPv4 protocol + * socket options. + * + * Input Parameters: + * psock Socket structure of the socket to query + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + * Returned Value: + * Returns zero (OK) on success. On failure, it returns a negated errno + * value to indicate the nature of the error. See psock_getsockopt() for + * the list of possible error values. + * + ****************************************************************************/ + +int ipv4_getsockopt(FAR struct socket *psock, int option, + FAR void *value, FAR socklen_t *value_len) +{ + int ret; + + ninfo("option: %d\n", option); + + net_lock(); + switch (option) + { +#ifdef CONFIG_NET_IPTABLES + case IPT_SO_GET_INFO: + case IPT_SO_GET_ENTRIES: + ret = ipt_getsockopt(psock, option, value, value_len); + break; +#endif + + default: + nerr("ERROR: Unrecognized IPv4 option: %d\n", option); + ret = -ENOPROTOOPT; + break; + } + + net_unlock(); + return ret; +} + +#endif /* CONFIG_NET_IPv4 */ diff --git a/net/inet/ipv4_setsockopt.c b/net/inet/ipv4_setsockopt.c index 9cf43b508b615..2e97fbec5a82e 100644 --- a/net/inet/ipv4_setsockopt.c +++ b/net/inet/ipv4_setsockopt.c @@ -34,6 +34,7 @@ #include #include "netdev/netdev.h" +#include "netfilter/iptables.h" #include "igmp/igmp.h" #include "inet/inet.h" #include "udp/udp.h" @@ -261,6 +262,12 @@ int ipv4_setsockopt(FAR struct socket *psock, int option, break; #endif +#ifdef CONFIG_NET_IPTABLES + case IPT_SO_SET_REPLACE: + ret = ipt_setsockopt(psock, option, value, value_len); + break; +#endif + default: nerr("ERROR: Unrecognized IPv4 option: %d\n", option); ret = -ENOPROTOOPT; diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig new file mode 100644 index 0000000000000..c0a907f77a953 --- /dev/null +++ b/net/netfilter/Kconfig @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config NET_IPTABLES + bool "Iptables Interface" + default y + depends on NET_IPv4 + depends on NET_SOCKOPTS + depends on NET_NAT # May change dependency if we have firewall later. + ---help--- + Enable or disable iptables compatible interface (for NAT). diff --git a/net/netfilter/Make.defs b/net/netfilter/Make.defs new file mode 100644 index 0000000000000..02d250a4b826f --- /dev/null +++ b/net/netfilter/Make.defs @@ -0,0 +1,36 @@ +############################################################################ +# net/netfilter/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# Netfilter source files + +ifeq ($(CONFIG_NET_IPTABLES),y) + +NET_CSRCS += ipt_sockopt.c + +ifeq ($(CONFIG_NET_NAT),y) +NET_CSRCS += ipt_nat.c +endif + +# Include Netfilter build support + +DEPPATH += --dep-path netfilter +VPATH += :netfilter + +endif diff --git a/net/netfilter/ipt_nat.c b/net/netfilter/ipt_nat.c new file mode 100644 index 0000000000000..914845fff4624 --- /dev/null +++ b/net/netfilter/ipt_nat.c @@ -0,0 +1,126 @@ +/**************************************************************************** + * net/netfilter/ipt_nat.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include + +#include "nat/nat.h" +#include "netdev/netdev.h" +#include "netfilter/iptables.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: adjust_nat + * + * Description: + * Callback for netdev_foreach, enable/disable NAT on dev. + * + * Input Parameters: + * dev - Device to adjust NAT. + * arg - The input ipt_replace config of NAT. + * + ****************************************************************************/ + +static int adjust_nat(FAR struct net_driver_s *dev, FAR void *arg) +{ + FAR const struct ipt_replace *repl = arg; + FAR struct ipt_entry *entry; + FAR struct xt_entry_target *target; + + ipt_entry_for_every(entry, repl->entries, repl->size) + { + target = IPT_TARGET(entry); + if (strcmp(target->u.user.name, XT_MASQUERADE_TARGET) == 0 && + strcmp(dev->d_ifname, entry->ip.outiface) == 0) + { + ipv4_nat_enable(dev); + return 0; + } + } + + ipv4_nat_disable(dev); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipt_nat_init + * + * Description: + * Init NAT table data. + * + ****************************************************************************/ + +FAR struct ipt_replace *ipt_nat_init(void) +{ + return ipt_alloc_table(TABLE_NAME_NAT, 1 << NF_INET_POST_ROUTING); +} + +/**************************************************************************** + * Name: ipt_nat_apply + * + * Description: + * Try to apply NAT rules, will do nothing if failed. + * + * Input Parameters: + * repl - The config got from user space to control NAT table. + * + ****************************************************************************/ + +int ipt_nat_apply(FAR const struct ipt_replace *repl) +{ + FAR struct ipt_entry *entry; + FAR struct xt_entry_target *target; + + /* Check config first. */ + + ipt_entry_for_every(entry, repl->entries, repl->size) + { + target = IPT_TARGET(entry); + if (strcmp(target->u.user.name, XT_MASQUERADE_TARGET) == 0 && + netdev_findbyname(entry->ip.outiface) == NULL) + { + /* MASQUERADE specified but no WAN device, don't apply. */ + + nwarn("WARNING: Trying to apply nat on nonexistent dev: %s", + entry->ip.outiface); + return -EINVAL; + } + } + + /* Do actual work. */ + + netdev_foreach(adjust_nat, (FAR void *)repl); + + return OK; +} diff --git a/net/netfilter/ipt_sockopt.c b/net/netfilter/ipt_sockopt.c new file mode 100644 index 0000000000000..3f9dc3612fa80 --- /dev/null +++ b/net/netfilter/ipt_sockopt.c @@ -0,0 +1,440 @@ +/**************************************************************************** + * net/netfilter/ipt_sockopt.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include + +#include "netfilter/iptables.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SWAP(a,b,t) do { t = a; a = b; b = t; } while (0) + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Structure to store all info we need, including table data and + * init/apply functions. + */ + +struct ipt_table_s +{ + FAR struct ipt_replace *repl; + FAR struct ipt_replace *(*init_func)(void); + FAR int (*apply_func)(FAR const struct ipt_replace *); +}; + +/* Following structs represent the layout of an entry with standard/error + * target (without matches). Mainly used to simplify initialization (entry + * creation), not suggested to use under other situations, because there + * might be matches between entry and target in data from user space. + */ + +struct ipt_standard_entry_s +{ + struct ipt_entry entry; + struct xt_standard_target target; +}; + +struct ipt_error_entry_s +{ + struct ipt_entry entry; + struct xt_error_target target; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct ipt_table_s g_tables[] = +{ +#ifdef CONFIG_NET_NAT + {NULL, ipt_nat_init, ipt_nat_apply}, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipt_table_init + * + * Description: + * Try initialize the table data if not initialized. + * + ****************************************************************************/ + +static void ipt_table_init(FAR struct ipt_table_s *table) +{ + if (table->repl == NULL && table->init_func != NULL) + { + table->repl = table->init_func(); + } +} + +/**************************************************************************** + * Name: ipt_table + * + * Description: + * Find table data by table name. + * + ****************************************************************************/ + +static FAR struct ipt_table_s *ipt_table(FAR const char *name) +{ + int i; + for (i = 0; i < ARRAY_SIZE(g_tables); i++) + { + ipt_table_init(&g_tables[i]); + if (g_tables[i].repl != NULL && + strcmp(g_tables[i].repl->name, name) == 0) + { + return &g_tables[i]; + } + } + + return NULL; +} + +/**************************************************************************** + * Name: ipt_table_repl + * + * Description: + * Find table data by table name. + * + ****************************************************************************/ + +static FAR struct ipt_replace *ipt_table_repl(FAR const char *name) +{ + FAR struct ipt_table_s *table = ipt_table(name); + if (table) + { + return table->repl; + } + + return NULL; +} + +/**************************************************************************** + * Name: get_info + * + * Description: + * Fill table info into ipt_getinfo structure. + * + * Input Parameters: + * get, len - The parameters from getsockopt. + * + ****************************************************************************/ + +static int get_info(FAR struct ipt_getinfo *get, FAR socklen_t *len) +{ + FAR struct ipt_replace *repl; + + if (*len != sizeof(*get)) + { + return -EINVAL; + } + + repl = ipt_table_repl(get->name); + if (repl == NULL) + { + return -ENOENT; + } + + get->valid_hooks = repl->valid_hooks; + memcpy(get->hook_entry, repl->hook_entry, sizeof(get->hook_entry)); + memcpy(get->underflow, repl->underflow, sizeof(get->underflow)); + get->num_entries = repl->num_entries; + get->size = repl->size; + + return OK; +} + +/**************************************************************************** + * Name: get_entries + * + * Description: + * Fill entry info into ipt_get_entries structure. + * + * Input Parameters: + * get, len - The parameters from getsockopt. + * + ****************************************************************************/ + +static int get_entries(FAR struct ipt_get_entries *get, FAR socklen_t *len) +{ + FAR struct ipt_replace *repl; + + if (*len < sizeof(*get) || *len != sizeof(*get) + get->size) + { + return -EINVAL; + } + + repl = ipt_table_repl(get->name); + if (repl == NULL) + { + return -ENOENT; + } + + if (get->size != repl->size) + { + return -EAGAIN; + } + + memcpy(get->entrytable, repl->entries, get->size); + + return OK; +} + +/**************************************************************************** + * Name: check_replace + * + * Description: + * Check whether an ipt_replace structure from user space is valid. + * + * Input Parameters: + * repl - The ipt_replace structure to check. + * + * Returned Value: + * OK if repl is valid, otherwise -EINVAL. + * + ****************************************************************************/ + +static int check_replace(FAR const struct ipt_replace *repl) +{ + FAR struct ipt_entry *entry; + unsigned int entry_count = 0; + + ipt_entry_for_every(entry, repl->entries, repl->size) + { + entry_count++; + } + + if (entry_count != repl->num_entries) + { + return -EINVAL; + } + + /* May add more checks later. */ + + return OK; +} + +/**************************************************************************** + * Name: replace_entries + * + * Description: + * Apply replace data to kernel tables. + * + * Input Parameters: + * repl, len - The parameters from setsockopt. + * + ****************************************************************************/ + +static int replace_entries(FAR const struct ipt_replace *repl, socklen_t len) +{ + int ret; + FAR struct ipt_replace *new_repl; + FAR struct ipt_table_s *table = ipt_table(repl->name); + + if (table == NULL || table->repl == NULL) + { + return -ENOENT; + } + + if (len < sizeof(*repl) || len != sizeof(*repl) + repl->size || + repl->valid_hooks != table->repl->valid_hooks) + { + return -EINVAL; + } + + /* Check replace struct before applying it. */ + + ret = check_replace(repl); + if (ret != OK) + { + return ret; + } + + new_repl = kmm_malloc(sizeof(*new_repl) + repl->size); + if (new_repl == NULL) + { + return -ENOMEM; + } + + /* Try to apply the config in replace data. */ + + ret = table->apply_func(repl); + + /* If successfully applied, save data into kernel space. */ + + if (ret == OK) + { + FAR struct ipt_replace *tmp; + memcpy(new_repl, repl, sizeof(*repl) + repl->size); + SWAP(table->repl, new_repl, tmp); + } + + kmm_free(new_repl); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipt_alloc_table + * + * Description: + * Allocate an initial table info with valid_hooks specified. + * Will generate a default entry with standard target for each valid hook, + * and an entry with error target at the end of entry table. + * + * Input Parameters: + * table - The name of the table. + * valid_hooks - The valid_hooks of the table, it's a bitmask. + * + * Returned Value: + * Newly generated ipt_replace structure. + * + ****************************************************************************/ + +FAR struct ipt_replace *ipt_alloc_table(FAR const char *table, + unsigned int valid_hooks) +{ + FAR struct ipt_replace *repl; + FAR struct ipt_standard_entry_s *entry; + FAR struct ipt_error_entry_s *error_entry; + size_t entry_size; + unsigned int hook; + unsigned int num_hooks; + + if (valid_hooks == 0 || valid_hooks > (1 << NF_INET_NUMHOOKS)) + { + return NULL; + } + + num_hooks = popcount(valid_hooks); + + /* There will be num_hooks entries with standard target (ACCEPT). */ + + entry_size = num_hooks * sizeof(struct ipt_standard_entry_s); + + /* An error target as final entry. */ + + entry_size += sizeof(struct ipt_error_entry_s); + + repl = kmm_zalloc(sizeof(*repl) + entry_size); + if (repl == NULL) + { + return NULL; + } + + strcpy(repl->name, table); + repl->valid_hooks = valid_hooks; + repl->num_entries = num_hooks + 1; + repl->size = entry_size; + + entry = (FAR struct ipt_standard_entry_s *)(repl + 1); + + for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) + { + if ((valid_hooks >> hook & 0x01) == 0) + { + continue; + } + + repl->hook_entry[hook] = (uintptr_t)entry - (uintptr_t)(repl + 1); + repl->underflow[hook] = repl->hook_entry[hook]; + + entry->target.verdict = -NF_ACCEPT - 1; + IPT_FILL_ENTRY(entry, XT_STANDARD_TARGET); + + entry++; + } + + error_entry = (FAR struct ipt_error_entry_s *)entry; + strcpy(error_entry->target.errorname, XT_ERROR_TARGET); + IPT_FILL_ENTRY(error_entry, XT_ERROR_TARGET); + + return repl; +} + +/**************************************************************************** + * Name: ipt_setsockopt + * + * Description: + * setsockopt function of iptables. + * + ****************************************************************************/ + +int ipt_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len) +{ + switch (option) + { + case IPT_SO_SET_REPLACE: + return replace_entries(value, value_len); + + default: + return -ENOPROTOOPT; + } +} + +/**************************************************************************** + * Name: ipt_getsockopt + * + * Description: + * getsockopt function of iptables. + * + ****************************************************************************/ + +int ipt_getsockopt(FAR struct socket *psock, int option, + FAR void *value, FAR socklen_t *value_len) +{ + switch (option) + { + case IPT_SO_GET_INFO: + return get_info(value, value_len); + + case IPT_SO_GET_ENTRIES: + return get_entries(value, value_len); + + default: + return -ENOPROTOOPT; + } +} diff --git a/net/netfilter/iptables.h b/net/netfilter/iptables.h new file mode 100644 index 0000000000000..de6d945f624f0 --- /dev/null +++ b/net/netfilter/iptables.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * net/netfilter/iptables.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __NET_NETFILTER_IPTABLES_H +#define __NET_NETFILTER_IPTABLES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#ifdef CONFIG_NET_IPTABLES + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: ipt_setsockopt + * + * Description: + * setsockopt function of iptables. + * + ****************************************************************************/ + +int ipt_setsockopt(FAR struct socket *psock, int option, + FAR const void *value, socklen_t value_len); + +/**************************************************************************** + * Name: ipt_getsockopt + * + * Description: + * getsockopt function of iptables. + * + ****************************************************************************/ + +int ipt_getsockopt(FAR struct socket *psock, int option, + FAR void *value, FAR socklen_t *value_len); + +/**************************************************************************** + * Name: ipt_alloc_table + * + * Description: + * Allocate an initial table info with valid_hooks specified. + * Will generate a default entry with standard target for each valid hook, + * and an entry with error target at the end of entry table. + * + * Input Parameters: + * table - The name of the table. + * valid_hooks - The valid_hooks of the table, it's a bitmap of hooks. + * + * Returned Value: + * Newly generated ipt_replace structure. + * + ****************************************************************************/ + +FAR struct ipt_replace *ipt_alloc_table(FAR const char *table, + unsigned int valid_hooks); + +/**************************************************************************** + * Name: ipt_nat_init + * + * Description: + * Init NAT table data. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NAT +FAR struct ipt_replace *ipt_nat_init(void); +#endif + +/**************************************************************************** + * Name: ipt_nat_apply + * + * Description: + * Try to apply NAT rules, will do nothing if failed. + * + * Input Parameters: + * repl - The config got from user space to control NAT table. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_NAT +int ipt_nat_apply(FAR const struct ipt_replace *repl); +#endif + +#endif /* CONFIG_NET_IPTABLES */ +#endif /* __NET_NETFILTER_IPTABLES_H */