Add NFQUEUE target
authorMateusz Majewski <m.majewski2@samsung.com>
Thu, 24 Dec 2020 10:48:46 +0000 (11:48 +0100)
committerMateusz Majewski <m.majewski2@samsung.com>
Thu, 14 Jan 2021 12:17:51 +0000 (13:17 +0100)
Change-Id: I07e5aa19230de4736c380a1953bd5ed656ef5197

src/helper/helper-ip6tables.c
src/helper/helper-ip6tables.h
src/helper/helper-iptables.c
src/helper/helper-iptables.h
src/stc-iptables-util.c

index 6f81345b247c436296b5b1e765eef9c3f5c02dbe..edd06bb210d66e625431cc7af92fbcedbbce230d 100755 (executable)
@@ -26,6 +26,7 @@
 #include <linux/netfilter/xt_cgroup.h>
 #include <linux/netfilter/xt_nfacct.h>
 #include <linux/netfilter/xt_iprange.h>
+#include <linux/netfilter/xt_NFQUEUE.h>
 #include <linux/netfilter/xt_NFLOG.h>
 #include <linux/netfilter_ipv6/ip6t_LOG.h>
 
@@ -42,6 +43,7 @@
 #define IP6TC_IPRANGE "iprange"
 #define IP6TC_LOG     "LOG"
 #define IP6TC_NFLOG   "NFLOG"
+#define IP6TC_NFQUEUE "NFQUEUE"
 
 #define IP6TC_MASK   "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
 
@@ -65,6 +67,7 @@ typedef struct xt_iprange_mtinfo     ip6t_iprange_info_t;
 /* target */
 typedef struct ip6t_log_info         ip6t_log_info_t;
 typedef struct xt_nflog_info         ip6t_nflog_info_t;
+typedef struct xt_NFQ_info_v3        ip6t_nfqueue_info_t;
 
 #define SIZE_ENTRY IP6T_ALIGN(sizeof(ip6t_entry_t))
 #define SIZE_TCP_MATCH IP6T_ALIGN(sizeof(ip6t_entry_match_t)) + IP6T_ALIGN(sizeof(ip6t_tcp_info_t))
@@ -75,9 +78,10 @@ typedef struct xt_nflog_info         ip6t_nflog_info_t;
 #define SIZE_TARGET IP6T_ALIGN(sizeof(ip6t_entry_target_t)) + IP6T_ALIGN(sizeof(int))
 #define SIZE_TARGET_LOG IP6T_ALIGN(sizeof(ip6t_log_info_t))
 #define SIZE_TARGET_NFLOG IP6T_ALIGN(sizeof(ip6t_nflog_info_t))
+#define SIZE_TARGET_NFQUEUE IP6T_ALIGN(sizeof(ip6t_nfqueue_info_t))
 #define SIZE_TOTAL SIZE_ENTRY + SIZE_TCP_MATCH + SIZE_UDP_MATCH + SIZE_CGROUP_MATCH \
                                        + SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET \
-                                       + SIZE_TARGET_LOG + SIZE_TARGET_NFLOG
+                                       + SIZE_TARGET_LOG + SIZE_TARGET_NFLOG + SIZE_TARGET_NFQUEUE
 
 static unsigned int __add_match(const char *name, ip6t_entry_match_t *start,
                                                                                int revision, size_t size, void *data)
@@ -305,6 +309,18 @@ static unsigned int __add_nflog_target(unsigned int group, const char *prefix,
        return __add_target(IP6TC_NFLOG, start, 0, sizeof(ip6t_nflog_info_t), &nflog);
 }
 
+static unsigned int __add_nfqueue_target(unsigned int queue_id, bool queue_bypass, ip6t_entry_target_t *start)
+{
+       /* nfqueue => "--queue-num --queue-bypass" */
+       ip6t_nfqueue_info_t nfqueue;
+       memset(&nfqueue, 0, sizeof(ip6t_nfqueue_info_t));
+       nfqueue.queuenum = queue_id;
+       nfqueue.flags = queue_bypass ? NFQ_FLAG_BYPASS : 0;
+       nfqueue.queues_total = 1;
+       /* target_nfqueue */
+       return __add_target(IP6TC_NFQUEUE, start, 3, sizeof(ip6t_nfqueue_info_t), &nfqueue);
+ }
+
 static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                               ip6tables_rule_s *rule)
 {
@@ -451,6 +467,9 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                e->next_offset += __add_nflog_target(rule->nflog_group,
                        rule->nflog_prefix, rule->nflog_range, rule->nflog_threshold, target);
                break;
+       case IP6TABLES_ACTION_NFQUEUE:
+               e->next_offset += __add_nfqueue_target(rule->nfqueue_id, rule->nfqueue_bypass, target);
+               break;
        default:
                target->u.target_size = SIZE_TARGET;
                if (rule->target && rule->target[0] != '\0')
index 2b2baddffcc68438afbeb2cf78d1bda5400bcf0c..b6177bd14257a554d0d7c29f7828c13373fa9f9e 100755 (executable)
@@ -21,6 +21,7 @@
 #ifndef __STC_HELPER_IP6TABLES_H__
 #define __STC_HELPER_IP6TABLES_H__
 
+#include <stdbool.h>
 #include <libiptc/libip6tc.h>
 
 #define RULE_SIZE     64
@@ -67,6 +68,7 @@ typedef enum {
        IP6TABLES_ACTION_DROP,
        IP6TABLES_ACTION_LOG,
        IP6TABLES_ACTION_NFLOG,
+       IP6TABLES_ACTION_NFQUEUE,
 } ip6tables_target_action_e;
 
 typedef struct {
@@ -98,6 +100,8 @@ typedef struct {
        char *nflog_prefix;
        unsigned int nflog_range;
        unsigned int nflog_threshold;
+       unsigned int nfqueue_id;
+       bool nfqueue_bypass;
 } ip6tables_rule_s;
 
 /**
index 9b10a02853de82a3895c9867991741f0e64a0767..e0318c88585a955b37303b7df422dbac8328da41 100755 (executable)
@@ -17,6 +17,7 @@
 
 #include <errno.h>
 #include <string.h>
+#include <stdbool.h>
 #include <stdlib.h>
 #include <glib.h>
 #include <arpa/inet.h>
@@ -25,6 +26,7 @@
 #include <linux/netfilter/xt_cgroup.h>
 #include <linux/netfilter/xt_nfacct.h>
 #include <linux/netfilter/xt_iprange.h>
+#include <linux/netfilter/xt_NFQUEUE.h>
 #include <linux/netfilter/xt_NFLOG.h>
 #include <linux/netfilter_ipv4/ipt_LOG.h>
 
@@ -41,6 +43,7 @@
 #define IPTC_IPRANGE "iprange"
 #define IPTC_LOG     "LOG"
 #define IPTC_NFLOG   "NFLOG"
+#define IPTC_NFQUEUE "NFQUEUE"
 
 #define IPTC_MASK    "255.255.255.255"
 
@@ -64,6 +67,7 @@ typedef struct xt_iprange_mtinfo     ipt_iprange_info_t;
 /* target */
 typedef struct ipt_log_info          ipt_log_info_t;
 typedef struct xt_nflog_info         ipt_nflog_info_t;
+typedef struct xt_NFQ_info_v3        ipt_nfqueue_info_t;
 
 #define SIZE_ENTRY IPT_ALIGN(sizeof(ipt_entry_t))
 #define SIZE_TCP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_tcp_info_t))
@@ -74,9 +78,10 @@ typedef struct xt_nflog_info         ipt_nflog_info_t;
 #define SIZE_TARGET IPT_ALIGN(sizeof(ipt_entry_target_t)) + IPT_ALIGN(sizeof(int))
 #define SIZE_TARGET_LOG IPT_ALIGN(sizeof(ipt_log_info_t))
 #define SIZE_TARGET_NFLOG IPT_ALIGN(sizeof(ipt_nflog_info_t))
+#define SIZE_TARGET_NFQUEUE IPT_ALIGN(sizeof(ipt_nfqueue_info_t))
 #define SIZE_TOTAL SIZE_ENTRY + SIZE_TCP_MATCH + SIZE_UDP_MATCH + SIZE_CGROUP_MATCH \
                                        + SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET \
-                                       + SIZE_TARGET_LOG + SIZE_TARGET_NFLOG
+                                       + SIZE_TARGET_LOG + SIZE_TARGET_NFLOG + SIZE_TARGET_NFQUEUE
 
 static unsigned int __add_match(const char *name, ipt_entry_match_t *start,
                                                                                int revision, size_t size, void *data)
@@ -304,6 +309,18 @@ static unsigned int __add_nflog_target(unsigned int group, const char *prefix,
        return __add_target(IPTC_NFLOG, start, 0, sizeof(ipt_nflog_info_t), &nflog);
 }
 
+static unsigned int __add_nfqueue_target(unsigned int queue_id, bool queue_bypass, ipt_entry_target_t *start)
+{
+       /* nfqueue => "--queue-num --queue-bypass" */
+       ipt_nfqueue_info_t nfqueue;
+       memset(&nfqueue, 0, sizeof(ipt_nfqueue_info_t));
+       nfqueue.queuenum = queue_id;
+       nfqueue.flags = queue_bypass ? NFQ_FLAG_BYPASS : 0;
+       nfqueue.queues_total = 1;
+       /* target_nfqueue */
+       return __add_target(IPTC_NFQUEUE, start, 3, sizeof(ipt_nfqueue_info_t), &nfqueue);
+}
+
 static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                               iptables_rule_s *rule)
 {
@@ -433,6 +450,9 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                e->next_offset += __add_nflog_target(rule->nflog_group,
                        rule->nflog_prefix, rule->nflog_range, rule->nflog_threshold, target);
                break;
+       case IPTABLES_ACTION_NFQUEUE:
+               e->next_offset += __add_nfqueue_target(rule->nfqueue_id, rule->nfqueue_bypass, target);
+               break;
        default:
                target->u.target_size = SIZE_TARGET;
                if (rule->target && rule->target[0] != '\0')
index 9a1f236761b2494d10bca7dae4529fdda6ccd5f0..564a4f687e3d75a6c8291eeaf5e8388f09d305e5 100755 (executable)
@@ -21,6 +21,7 @@
 #ifndef __STC_HELPER_IPTABLES_H__
 #define __STC_HELPER_IPTABLES_H__
 
+#include <stdbool.h>
 #include <libiptc/libiptc.h>
 
 #define RULE_SIZE     64
@@ -67,6 +68,7 @@ typedef enum {
        IPTABLES_ACTION_DROP,
        IPTABLES_ACTION_LOG,
        IPTABLES_ACTION_NFLOG,
+       IPTABLES_ACTION_NFQUEUE,
 } iptables_target_action_e;
 
 typedef struct {
@@ -98,6 +100,8 @@ typedef struct {
        char *nflog_prefix;
        unsigned int nflog_range;
        unsigned int nflog_threshold;
+       unsigned int nfqueue_id;
+       bool nfqueue_bypass;
 } iptables_rule_s;
 
 /**
index 91574af2c837f784a924edbc5a8c88ba6b86310a..48beeeec6c0fd649d1ecf5b073e97ec4ab34e73f 100755 (executable)
@@ -56,6 +56,8 @@
 #define RULE_NFLOG_PREFIX    "nflog_prefix"
 #define RULE_NFLOG_RANGE     "nflog_range"
 #define RULE_NFLOG_THRESHOLD "nflog_threshold"
+#define RULE_NFQUEUE_ID      "nfqueue_id"
+#define RULE_NFQUEUE_BYPASS  "nfqueue_bypass"
 
 #define STC_IPTABLES_DBUS_ERROR_NAME "net.stc.iptables.Error.Failed"
 
@@ -236,6 +238,18 @@ void __stc_extract_rule(const char *key, GVariant *value,
                        STC_LOGD("%s: [%u]", RULE_NFLOG_THRESHOLD, rule->nflog_threshold);
                }
 
+       } else if (!g_strcmp0(key, RULE_NFQUEUE_ID)) {
+               if (rule->target_type == IPTABLES_ACTION_NFQUEUE) {
+                       rule->nfqueue_id = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_NFQUEUE_ID, rule->nfqueue_id);
+               }
+
+       } else if (!g_strcmp0(key, RULE_NFQUEUE_BYPASS)) {
+               if (rule->target_type == IPTABLES_ACTION_NFQUEUE) {
+                       rule->nfqueue_bypass = g_variant_get_boolean(value);
+                       STC_LOGD("%s: [%u]", RULE_NFQUEUE_BYPASS, rule->nfqueue_bypass);
+               }
+
        } else {
                STC_LOGD("Unknown rule [%s]", key); //LCOV_EXCL_LINE
        }
@@ -428,6 +442,17 @@ void __stc_extract_6_rule(const char *key, GVariant *value,
                        STC_LOGD("%s: [%u]", RULE_NFLOG_THRESHOLD, rule->nflog_threshold);
                }
 
+       } else if (!g_strcmp0(key, RULE_NFQUEUE_ID)) {
+               if (rule->target_type == IP6TABLES_ACTION_NFQUEUE) {
+                       rule->nfqueue_id = g_variant_get_uint16(value);
+                       STC_LOGD("%s: [%u]", RULE_NFQUEUE_ID, rule->nfqueue_id);
+               }
+
+       } else if (!g_strcmp0(key, RULE_NFQUEUE_BYPASS)) {
+               if (rule->target_type == IP6TABLES_ACTION_NFQUEUE) {
+                       rule->nfqueue_bypass = g_variant_get_boolean(value);
+                       STC_LOGD("%s: [%u]", RULE_NFQUEUE_BYPASS, rule->nfqueue_bypass);
+               }
        } else {
                STC_LOGD("Unknown rule [%s]", key); //LCOV_EXCL_LINE
        }