Added firewall features 28/171028/4
authorhyunuktak <hyunuk.tak@samsung.com>
Mon, 26 Feb 2018 04:34:38 +0000 (13:34 +0900)
committerhyunuktak <hyunuk.tak@samsung.com>
Thu, 5 Apr 2018 06:23:36 +0000 (15:23 +0900)
It's supported some rules using iptables and extension.
Specific IP(and IP range), Protocol, Port.

Change-Id: If4a79d86e771bac586de7fad02a4f27d5a1284cd
Signed-off-by: hyunuktak <hyunuk.tak@samsung.com>
13 files changed:
include/linux/netfilter/xt_iprange.h [new file with mode: 0755]
include/stc-iptables-log.h
include/stc-iptables-util.h
src/helper/helper-ip6tables.c
src/helper/helper-ip6tables.h
src/helper/helper-iptables.c
src/helper/helper-iptables.h
src/stc-iptables-log.c
src/stc-iptables-util.c
test/stc_ipt_rule.c
unittest/rule.cpp
unittest/rule.h
unittest/unittest.cpp

diff --git a/include/linux/netfilter/xt_iprange.h b/include/linux/netfilter/xt_iprange.h
new file mode 100755 (executable)
index 0000000..c1f21a7
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _LINUX_NETFILTER_XT_IPRANGE_H
+#define _LINUX_NETFILTER_XT_IPRANGE_H 1
+
+#include <linux/types.h>
+
+enum {
+       IPRANGE_SRC     = 1 << 0,       /* match source IP address */
+       IPRANGE_DST     = 1 << 1,       /* match destination IP address */
+       IPRANGE_SRC_INV = 1 << 4,       /* negate the condition */
+       IPRANGE_DST_INV = 1 << 5,       /* -"- */
+};
+
+struct xt_iprange_mtinfo {
+       union nf_inet_addr src_min, src_max;
+       union nf_inet_addr dst_min, dst_max;
+       __u8 flags;
+};
+
+#endif /* _LINUX_NETFILTER_XT_IPRANGE_H */
index c2db213..80f3866 100755 (executable)
@@ -39,7 +39,7 @@ void stc_iptables_log_cleanup(void);
 #define STC_LOGI(format, args...) __LOG(LOG_INFO, format, ##args)
 #define STC_LOGW(format, args...) __LOG(LOG_WARN, format, ##args)
 #define STC_LOGE(format, args...) __LOG(LOG_ERROR, format, ##args)
-       
+
 #define __STC_LOG_FUNC_ENTER__ /* __LOG(LOG_DEBUG, "Enter") */
 #define __STC_LOG_FUNC_EXIT__ /* __LOG(LOG_DEBUG, "Quit") */
 
index fc19907..16506ef 100755 (executable)
@@ -20,6 +20,7 @@
 
 #include <glib.h>
 #include <gio/gio.h>
+#include <stdio.h>
 
 #include "stc-iptables-log.h"
 #include "stc-iptables-gdbus.h"
index 064adb5..aa54d84 100755 (executable)
 #include <string.h>
 #include <stdlib.h>
 #include <arpa/inet.h>
+#include <xtables.h>
 
 #include <linux/netfilter/xt_cgroup.h>
 #include <linux/netfilter/xt_nfacct.h>
+//#include <linux/netfilter/xt_iprange.h>
 
 #include "helper-ip6tables.h"
 #include "stc-iptables-util.h"
 
 #define IP6T_ALIGN   XT_ALIGN
 #define IP6TC_TABLE  "filter"
+#define IP6TC_TCP    "tcp"
+#define IP6TC_UDP    "udp"
 #define IP6TC_CGROUP "cgroup"
 #define IP6TC_NFACCT "nfacct"
 
+#define IP6TC_MASK   "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF"
+
 /* handle */
 typedef struct xtc_handle            ip6t_handle_t;
 
@@ -40,14 +46,22 @@ typedef struct ip6t_entry_match      ip6t_entry_match_t;
 typedef struct ip6t_entry_target     ip6t_entry_target_t;
 
 /* matches */
+typedef struct xt_tcp                ip6t_tcp_info_t;
+typedef struct xt_udp                ip6t_udp_info_t;
 typedef struct xt_cgroup_info_v0     ip6t_cgroup_info_t;
 typedef struct xt_nfacct_match_info  ip6t_nfacct_info_t;
+typedef struct xt_iprange_mtinfo     ip6t_iprange_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))
+#define SIZE_UDP_MATCH IP6T_ALIGN(sizeof(ip6t_entry_match_t)) + IP6T_ALIGN(sizeof(ip6t_udp_info_t))
 #define SIZE_CGROUP_MATCH IP6T_ALIGN(sizeof(ip6t_entry_match_t)) + IP6T_ALIGN(sizeof(ip6t_cgroup_info_t))
 #define SIZE_NFACCT_MATCH IP6T_ALIGN(sizeof(ip6t_entry_match_t)) + IP6T_ALIGN(sizeof(ip6t_nfacct_info_t))
+//#define SIZE_IPRANGE_MATCH IP6T_ALIGN(sizeof(ip6t_entry_match_t)) + IP6T_ALIGN(sizeof(ip6t_iprange_info_t))
 #define SIZE_TARGET IP6T_ALIGN(sizeof(ip6t_entry_target_t)) + IP6T_ALIGN(sizeof(int))
-#define SIZE_TOTAL SIZE_ENTRY + SIZE_CGROUP_MATCH + SIZE_NFACCT_MATCH + SIZE_TARGET
+#define SIZE_TOTAL SIZE_ENTRY + SIZE_TCP_MATCH + SIZE_UDP_MATCH + SIZE_CGROUP_MATCH \
+                                       + SIZE_NFACCT_MATCH + SIZE_TARGET
+//                                     + SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET
 
 static unsigned int __add_match(const char *name, ip6t_entry_match_t *start, size_t size, void *data)
 {
@@ -61,6 +75,108 @@ static unsigned int __add_match(const char *name, ip6t_entry_match_t *start, siz
        return match->u.match_size;
 }
 
+static unsigned int __add_port_match(ip6tables_protocol_type_e prot_type,
+               ip6tables_port_type_e sport_type, unsigned short sport1, unsigned short sport2,
+               ip6tables_port_type_e dport_type, unsigned short dport1, unsigned short dport2,
+               ip6t_entry_match_t *start)
+{
+       switch (prot_type) {
+       case IP6TABLES_PROTOCOL_TCP:
+               {
+                       ip6t_tcp_info_t tcp;
+                       memset(&tcp, 0, sizeof(ip6t_tcp_info_t));
+                       switch(sport_type) {
+                       /* --sport 80 */
+                       case IP6TABLES_PORT_SINGLE:
+                               tcp.spts[0] = ntohs(htons(sport1));
+                               tcp.spts[1] = ntohs(htons(sport1));
+                               break;
+                       /* --sport 0:59136 */
+                       case IP6TABLES_PORT_RANGE:
+                               tcp.spts[0] = ntohs(htons(sport1));
+                               tcp.spts[1] = ntohs(htons(sport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       switch(dport_type) {
+                       /* --dport 80 */
+                       case IP6TABLES_PORT_SINGLE:
+                               tcp.dpts[0] = ntohs(htons(dport1));
+                               tcp.dpts[1] = ntohs(htons(dport1));
+                               break;
+                       /* --dport 0:59136 */
+                       case IP6TABLES_PORT_RANGE:
+                               tcp.dpts[0] = ntohs(htons(dport1));
+                               tcp.dpts[1] = ntohs(htons(dport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       return __add_match(IP6TC_TCP, start, sizeof(ip6t_tcp_info_t), &tcp);
+               }
+       case IP6TABLES_PROTOCOL_UDP:
+               {
+                       ip6t_udp_info_t udp;
+                       memset(&udp, 0, sizeof(ip6t_udp_info_t));
+                       switch(sport_type) {
+                       /* --sport 80 */
+                       case IP6TABLES_PORT_SINGLE:
+                               udp.spts[0] = ntohs(htons(sport1));
+                               udp.spts[1] = ntohs(htons(sport1));
+                               break;
+                       /* --sport 0:59136 */
+                       case IP6TABLES_PORT_RANGE:
+                               udp.spts[0] = ntohs(htons(sport1));
+                               udp.spts[1] = ntohs(htons(sport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       switch(dport_type) {
+                       /* --dport 80 */
+                       case IP6TABLES_PORT_SINGLE:
+                               udp.dpts[0] = ntohs(htons(dport1));
+                               udp.dpts[1] = ntohs(htons(dport1));
+                               break;
+                       /* --dport 0:59136 */
+                       case IP6TABLES_PORT_RANGE:
+                               udp.dpts[0] = ntohs(htons(dport1));
+                               udp.dpts[1] = ntohs(htons(dport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       return __add_match(IP6TC_UDP, start, sizeof(ip6t_udp_info_t), &udp);
+               }
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void __add_port(unsigned char *entry, unsigned int *size_mask,
+               unsigned int *size_match, ip6tables_rule_s *rule, unsigned int match_size)
+{
+       if ((rule->s_port_type > IP6TABLES_PORT_NONE &&
+               rule->s_port_type <= IP6TABLES_PORT_RANGE) ||
+               (rule->d_port_type > IP6TABLES_PORT_NONE &&
+               rule->d_port_type <= IP6TABLES_PORT_RANGE)) {
+
+               ip6t_entry_t *e = (ip6t_entry_t *)(entry);
+
+               (*size_match) += __add_port_match(rule->protocol,
+                       rule->s_port_type, rule->s_port1, rule->s_port2,
+                       rule->d_port_type, rule->d_port1, rule->d_port2,
+                       (ip6t_entry_match_t *) (e->elems + (*size_match)));
+
+               (*size_mask) += sizeof(ip6t_entry_match_t);
+               e->target_offset += match_size;
+               e->next_offset += match_size;
+       }
+}
+
 static unsigned int __add_cgroup_match(unsigned int classid, ip6t_entry_match_t *start)
 {
        /* cgroup => "--cgroup 0" */
@@ -102,13 +218,13 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
        size_mask = sizeof(ip6t_entry_t);
 
        if (rule->ifname) {
-               switch (rule->type) {
-               case IP6TABLES_RULE_IN:
+               switch (rule->direction) {
+               case IP6TABLES_DIRECTION_IN:
                        /* entry => "-i wlan0" */
                        g_strlcpy(e->ipv6.iniface, rule->ifname, IFNAMSIZ);
                        memset(&(e->ipv6.iniface_mask), 0xFF, IFNAMSIZ);
                        break;
-               case IP6TABLES_RULE_OUT:
+               case IP6TABLES_DIRECTION_OUT:
                        /* entry => "-o wlan0" */
                        g_strlcpy(e->ipv6.outiface, rule->ifname, IFNAMSIZ);
                        memset(&(e->ipv6.outiface_mask), 0xFF, IFNAMSIZ);
@@ -119,6 +235,88 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                }
        }
 
+       switch (rule->s_ip_type) {
+       case IP6TABLES_IP_SINGLE:
+               /* -s 2001:DB8::5/128 */
+               e->ipv6.src.s6_addr32[0] = rule->s_ip1.s6_addr32[0];
+               e->ipv6.src.s6_addr32[1] = rule->s_ip1.s6_addr32[1];
+               e->ipv6.src.s6_addr32[2] = rule->s_ip1.s6_addr32[2];
+               e->ipv6.src.s6_addr32[3] = rule->s_ip1.s6_addr32[3];
+               inet_pton(AF_INET6, IP6TC_MASK, &(e->ipv6.smsk));
+               break;
+       case IP6TABLES_IP_MASK:
+               /* -s 2001:DB8::5/64 */
+               e->ipv6.src.s6_addr32[0] = rule->s_ip1.s6_addr32[0];
+               e->ipv6.src.s6_addr32[1] = rule->s_ip1.s6_addr32[1];
+               e->ipv6.src.s6_addr32[2] = rule->s_ip1.s6_addr32[2];
+               e->ipv6.src.s6_addr32[3] = rule->s_ip1.s6_addr32[3];
+               e->ipv6.smsk.s6_addr32[0] = rule->s_ip2.s6_addr32[0];
+               e->ipv6.smsk.s6_addr32[1] = rule->s_ip2.s6_addr32[1];
+               e->ipv6.smsk.s6_addr32[2] = rule->s_ip2.s6_addr32[2];
+               e->ipv6.smsk.s6_addr32[3] = rule->s_ip2.s6_addr32[3];
+               break;
+       default:
+               break;
+       }
+
+       switch (rule->d_ip_type) {
+       case IP6TABLES_IP_SINGLE:
+               /* -d 2001:DB8::5/128 */
+               e->ipv6.dst.s6_addr32[0] = rule->d_ip1.s6_addr32[0];
+               e->ipv6.dst.s6_addr32[1] = rule->d_ip1.s6_addr32[1];
+               e->ipv6.dst.s6_addr32[2] = rule->d_ip1.s6_addr32[2];
+               e->ipv6.dst.s6_addr32[3] = rule->d_ip1.s6_addr32[3];
+               inet_pton(AF_INET6, IP6TC_MASK, &(e->ipv6.dmsk));
+               break;
+       case IP6TABLES_IP_MASK:
+               /* -d 2001:DB8::5/128 */
+               e->ipv6.dst.s6_addr32[0] = rule->d_ip1.s6_addr32[0];
+               e->ipv6.dst.s6_addr32[1] = rule->d_ip1.s6_addr32[1];
+               e->ipv6.dst.s6_addr32[2] = rule->d_ip1.s6_addr32[2];
+               e->ipv6.dst.s6_addr32[3] = rule->d_ip1.s6_addr32[3];
+               e->ipv6.dmsk.s6_addr32[0] = rule->d_ip2.s6_addr32[0];
+               e->ipv6.dmsk.s6_addr32[1] = rule->d_ip2.s6_addr32[1];
+               e->ipv6.dmsk.s6_addr32[2] = rule->d_ip2.s6_addr32[2];
+               e->ipv6.dmsk.s6_addr32[3] = rule->d_ip2.s6_addr32[3];
+               break;
+       default:
+               break;
+       }
+
+       /* -p tcp */
+       switch (rule->protocol) {
+       case IP6TABLES_PROTOCOL_TCP:
+               e->ipv6.proto = IPPROTO_TCP;
+               __add_port(entry, &size_mask, &size_match, rule, SIZE_TCP_MATCH);
+               break;
+       case IP6TABLES_PROTOCOL_UDP:
+               e->ipv6.proto = IPPROTO_UDP;
+               __add_port(entry, &size_mask, &size_match, rule, SIZE_UDP_MATCH);
+               break;
+       case IP6TABLES_PROTOCOL_ICMP:
+               e->ipv6.proto = IPPROTO_ICMP;
+               break;
+       case IP6TABLES_PROTOCOL_ESP:
+               e->ipv6.proto = IPPROTO_ESP;
+               break;
+       case IP6TABLES_PROTOCOL_AH:
+               e->ipv6.proto = IPPROTO_AH;
+               break;
+       case IP6TABLES_PROTOCOL_SCTP:
+               e->ipv6.proto = IPPROTO_SCTP;
+               break;
+       case IP6TABLES_PROTOCOL_MH:
+               e->ipv6.proto = IPPROTO_MH;
+               break;
+       case IP6TABLES_PROTOCOL_ALL:
+               e->ipv6.proto = 0;
+               break;
+       default:
+               e->ipv6.proto = 0;
+               break;
+       }
+
+       /* -m cgroup --cgroup 33 */
        if (rule->classid > 0) {
                size_match += __add_cgroup_match(rule->classid, (ip6t_entry_match_t *) e->elems);
                size_mask += sizeof(ip6t_entry_match_t);
@@ -126,6 +324,7 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
                e->next_offset += SIZE_CGROUP_MATCH;
        }
 
+       /* -m nfacct --nfacct-name  c2_1_33_seth_w0 */
        if (rule->nfacct_name) {
                size_match += __add_nfacct_match(rule->nfacct_name, (ip6t_entry_match_t *) (e->elems + size_match));
                size_mask += sizeof(ip6t_entry_match_t);
index c763164..a5bc691 100755 (executable)
@@ -31,9 +31,35 @@ typedef enum {
 } ip6tables_chain_e;
 
 typedef enum {
-       IP6TABLES_RULE_IN,
-       IP6TABLES_RULE_OUT
-} ip6tables_rule_type_e;
+       IP6TABLES_DIRECTION_NONE,
+       IP6TABLES_DIRECTION_IN,
+       IP6TABLES_DIRECTION_OUT
+} ip6tables_direction_e;
+
+typedef enum {
+       IP6TABLES_IP_NONE,
+       IP6TABLES_IP_SINGLE,
+       IP6TABLES_IP_MASK,
+       IP6TABLES_IP_RANGE
+} ip6tables_ip_type_e;
+
+typedef enum {
+       IP6TABLES_PORT_NONE,
+       IP6TABLES_PORT_SINGLE,
+       IP6TABLES_PORT_RANGE
+} ip6tables_port_type_e;
+
+typedef enum {
+       IP6TABLES_PROTOCOL_NONE,
+       IP6TABLES_PROTOCOL_TCP,
+       IP6TABLES_PROTOCOL_UDP,
+       IP6TABLES_PROTOCOL_ICMP,
+       IP6TABLES_PROTOCOL_ESP,
+       IP6TABLES_PROTOCOL_AH,
+       IP6TABLES_PROTOCOL_SCTP,
+       IP6TABLES_PROTOCOL_MH,
+       IP6TABLES_PROTOCOL_ALL,
+} ip6tables_protocol_type_e;
 
 typedef enum {
        IP6TABLES_ACTION_ACCEPT,
@@ -42,7 +68,20 @@ typedef enum {
 
 typedef struct {
        char *chain;
-       ip6tables_rule_type_e type;
+       ip6tables_direction_e direction;
+       ip6tables_ip_type_e s_ip_type;
+       ip6tables_ip_type_e d_ip_type;
+       ip6tables_port_type_e s_port_type;
+       ip6tables_port_type_e d_port_type;
+       ip6tables_protocol_type_e protocol;
+       struct in6_addr s_ip1;
+       struct in6_addr s_ip2;
+       struct in6_addr d_ip1;
+       struct in6_addr d_ip2;
+       unsigned int s_port1;
+       unsigned int s_port2;
+       unsigned int d_port1;
+       unsigned int d_port2;
        char *ifname;
        int classid;
        char *nfacct_name;
index 21c2e68..a791202 100755 (executable)
 #include <stdlib.h>
 #include <arpa/inet.h>
 
+#include <linux/netfilter.h>
 #include <linux/netfilter/xt_cgroup.h>
 #include <linux/netfilter/xt_nfacct.h>
+#include <linux/netfilter/xt_iprange.h>
 
 #include "helper-iptables.h"
 #include "stc-iptables-util.h"
 
-#define IPT_ALIGN   XT_ALIGN
-#define IPTC_TABLE  "filter"
-#define IPTC_CGROUP "cgroup"
-#define IPTC_NFACCT "nfacct"
+#define IPT_ALIGN    XT_ALIGN
+#define IPTC_TABLE   "filter"
+#define IPTC_TCP     "tcp"
+#define IPTC_UDP     "udp"
+#define IPTC_CGROUP  "cgroup"
+#define IPTC_NFACCT  "nfacct"
+#define IPTC_IPRANGE "iprange"
+
+#define IPTC_MASK    "255.255.255.255"
 
 /* handle */
 typedef struct xtc_handle            ipt_handle_t;
@@ -40,14 +47,21 @@ typedef struct ipt_entry_match       ipt_entry_match_t;
 typedef struct ipt_entry_target      ipt_entry_target_t;
 
 /* matches */
+typedef struct xt_tcp                ipt_tcp_info_t;
+typedef struct xt_udp                ipt_udp_info_t;
 typedef struct xt_cgroup_info_v0     ipt_cgroup_info_t;
 typedef struct xt_nfacct_match_info  ipt_nfacct_info_t;
+typedef struct xt_iprange_mtinfo     ipt_iprange_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))
+#define SIZE_UDP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_udp_info_t))
 #define SIZE_CGROUP_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_cgroup_info_t))
 #define SIZE_NFACCT_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_nfacct_info_t))
+#define SIZE_IPRANGE_MATCH IPT_ALIGN(sizeof(ipt_entry_match_t)) + IPT_ALIGN(sizeof(ipt_iprange_info_t))
 #define SIZE_TARGET IPT_ALIGN(sizeof(ipt_entry_target_t)) + IPT_ALIGN(sizeof(int))
-#define SIZE_TOTAL SIZE_ENTRY + SIZE_CGROUP_MATCH + SIZE_NFACCT_MATCH + SIZE_TARGET
+#define SIZE_TOTAL SIZE_ENTRY + SIZE_TCP_MATCH + SIZE_UDP_MATCH + SIZE_CGROUP_MATCH \
+                                       + SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET
 
 static unsigned int __add_match(const char *name, ipt_entry_match_t *start, size_t size, void *data)
 {
@@ -61,6 +75,147 @@ static unsigned int __add_match(const char *name, ipt_entry_match_t *start, size
        return match->u.match_size;
 }
 
+static unsigned int __add_iprange_match(iptables_ip_type_e sip_type,
+               struct in_addr sip1, struct in_addr sip2, iptables_ip_type_e dip_type,
+               struct in_addr dip1, struct in_addr dip2, ipt_entry_match_t *start)
+{
+       ipt_iprange_info_t iprange;
+       memset(&iprange, 0, sizeof(ipt_iprange_info_t));
+
+       /* iprange => "--src-range " */
+       if (sip_type == IPTABLES_IP_RANGE) {
+               iprange.src_min.in.s_addr = sip1.s_addr;
+               iprange.src_max.in.s_addr = sip2.s_addr;
+               iprange.flags |= IPRANGE_SRC;
+       }
+
+       /* iprange => "--dst-range " */
+       if (dip_type == IPTABLES_IP_RANGE) {
+               iprange.dst_min.in.s_addr = dip1.s_addr;
+               iprange.dst_max.in.s_addr = dip2.s_addr;
+               iprange.flags |= IPRANGE_DST;
+       }
+
+       /* match_iprange => "-m iprange" */
+       return __add_match(IPTC_IPRANGE, start, sizeof(ipt_iprange_info_t), &iprange);
+}
+
+static void __add_iprange(unsigned char *entry, unsigned int *size_mask,
+               unsigned int *size_match, iptables_rule_s *rule)
+{
+       ipt_entry_t *e = (ipt_entry_t *)(entry);
+
+       (*size_match) += __add_iprange_match(rule->s_ip_type,
+               rule->s_ip1, rule->s_ip2, rule->d_ip_type, rule->d_ip1,
+               rule->d_ip2, (ipt_entry_match_t *)(e->elems + (*size_match)));
+
+       (*size_mask) += sizeof(ipt_entry_match_t);
+       e->target_offset += SIZE_IPRANGE_MATCH;
+       e->next_offset += SIZE_IPRANGE_MATCH;
+}
+
+static unsigned int __add_port_match(iptables_protocol_type_e prot_type,
+               iptables_port_type_e sport_type, unsigned short sport1, unsigned short sport2,
+               iptables_port_type_e dport_type, unsigned short dport1, unsigned short dport2,
+               ipt_entry_match_t *start)
+{
+       switch (prot_type) {
+       case IPTABLES_PROTOCOL_TCP:
+               {
+                       ipt_tcp_info_t tcp;
+                       memset(&tcp, 0, sizeof(ipt_tcp_info_t));
+                       switch(sport_type) {
+                       /* --sport 80 */
+                       case IPTABLES_PORT_SINGLE:
+                               tcp.spts[0] = ntohs(htons(sport1));
+                               tcp.spts[1] = ntohs(htons(sport1));
+                               break;
+                       /* --sport 0:59136 */
+                       case IPTABLES_PORT_RANGE:
+                               tcp.spts[0] = ntohs(htons(sport1));
+                               tcp.spts[1] = ntohs(htons(sport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       switch(dport_type) {
+                       /* --dport 80 */
+                       case IPTABLES_PORT_SINGLE:
+                               tcp.dpts[0] = ntohs(htons(dport1));
+                               tcp.dpts[1] = ntohs(htons(dport1));
+                               break;
+                       /* --dport 0:59136 */
+                       case IPTABLES_PORT_RANGE:
+                               tcp.dpts[0] = ntohs(htons(dport1));
+                               tcp.dpts[1] = ntohs(htons(dport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       return __add_match(IPTC_TCP, start, sizeof(ipt_tcp_info_t), &tcp);
+               }
+       case IPTABLES_PROTOCOL_UDP:
+               {
+                       ipt_udp_info_t udp;
+                       memset(&udp, 0, sizeof(ipt_udp_info_t));
+                       switch(sport_type) {
+                       /* --sport 80 */
+                       case IPTABLES_PORT_SINGLE:
+                               udp.spts[0] = ntohs(htons(sport1));
+                               udp.spts[1] = ntohs(htons(sport1));
+                               break;
+                       /* --sport 0:59136 */
+                       case IPTABLES_PORT_RANGE:
+                               udp.spts[0] = ntohs(htons(sport1));
+                               udp.spts[1] = ntohs(htons(sport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       switch(dport_type) {
+                       /* --dport 80 */
+                       case IPTABLES_PORT_SINGLE:
+                               udp.dpts[0] = ntohs(htons(dport1));
+                               udp.dpts[1] = ntohs(htons(dport1));
+                               break;
+                       /* --dport 0:59136 */
+                       case IPTABLES_PORT_RANGE:
+                               udp.dpts[0] = ntohs(htons(dport1));
+                               udp.dpts[1] = ntohs(htons(dport2));
+                               break;
+                       default:
+                               break;
+                       }
+                       return __add_match(IPTC_UDP, start, sizeof(ipt_udp_info_t), &udp);
+               }
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void __add_port(unsigned char *entry, unsigned int *size_mask,
+               unsigned int *size_match, iptables_rule_s *rule, unsigned int match_size)
+{
+       if ((rule->s_port_type > IPTABLES_PORT_NONE &&
+               rule->s_port_type <= IPTABLES_PORT_RANGE) ||
+               (rule->d_port_type > IPTABLES_PORT_NONE &&
+               rule->d_port_type <= IPTABLES_PORT_RANGE)) {
+
+               ipt_entry_t *e = (ipt_entry_t *)(entry);
+
+               (*size_match) += __add_port_match(rule->protocol,
+                       rule->s_port_type, rule->s_port1, rule->s_port2,
+                       rule->d_port_type, rule->d_port1, rule->d_port2,
+                       (ipt_entry_match_t *) (e->elems + (*size_match)));
+
+               (*size_mask) += sizeof(ipt_entry_match_t);
+               e->target_offset += match_size;
+               e->next_offset += match_size;
+       }
+}
+
 static unsigned int __add_cgroup_match(unsigned int classid, ipt_entry_match_t *start)
 {
        /* cgroup => "--cgroup 0" */
@@ -102,32 +257,103 @@ static int __create_entry_data(unsigned char *entry, unsigned char *mask,
        size_mask = sizeof(ipt_entry_t);
 
        if (rule->ifname) {
-               switch (rule->type) {
-               case IPTABLES_RULE_IN:
-                       /* entry => "-i wlan0 */
+               switch (rule->direction) {
+               case IPTABLES_DIRECTION_IN:
+                       /* -i wlan0 */
                        g_strlcpy(e->ip.iniface, rule->ifname, IFNAMSIZ);
                        memset(&(e->ip.iniface_mask), 0xFF, IFNAMSIZ);
                        break;
-               case IPTABLES_RULE_OUT:
-                       /* entry => "-o wlan0 */
+               case IPTABLES_DIRECTION_OUT:
+                       /* -o wlan0 */
                        g_strlcpy(e->ip.outiface, rule->ifname, IFNAMSIZ);
                        memset(&(e->ip.outiface_mask), 0xFF, IFNAMSIZ);
                        break;
                default:
                        STC_LOGE("Invalid parameter"); //LCOV_EXCL_LINE
-                       return STC_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
+                       break; //LCOV_EXCL_LINE
                }
        }
 
+       switch (rule->s_ip_type) {
+       case IPTABLES_IP_SINGLE:
+               /* -s 102.132.217.5/32 */
+               e->ip.src.s_addr = rule->s_ip1.s_addr;
+               inet_pton(AF_INET, IPTC_MASK, &(e->ip.smsk));
+               break;
+       case IPTABLES_IP_MASK:
+               /* -s 102.132.217.5/24 */
+               e->ip.src.s_addr = rule->s_ip1.s_addr;
+               e->ip.smsk.s_addr = rule->s_ip2.s_addr;
+               break;
+       default:
+               break;
+       }
+
+       switch (rule->d_ip_type) {
+       case IPTABLES_IP_SINGLE:
+               /* -d 102.132.217.5/32 */
+               e->ip.dst.s_addr = rule->d_ip1.s_addr;
+               inet_pton(AF_INET, IPTC_MASK, &(e->ip.dmsk));
+               break;
+       case IPTABLES_IP_MASK:
+               /* -d 102.132.217.5/24 */
+               e->ip.dst.s_addr = rule->d_ip1.s_addr;
+               e->ip.dmsk.s_addr = rule->d_ip2.s_addr;
+               break;
+       default:
+               break;
+       }
+
+       if (rule->s_ip_type == IPTABLES_IP_RANGE ||
+               rule->d_ip_type == IPTABLES_IP_RANGE)
+               __add_iprange(entry, &size_mask, &size_match, rule);
+
+       /* -p tcp */
+       switch (rule->protocol) {
+       case IPTABLES_PROTOCOL_TCP:
+               e->ip.proto = IPPROTO_TCP;
+               __add_port(entry, &size_mask, &size_match, rule, SIZE_TCP_MATCH);
+               break;
+       case IPTABLES_PROTOCOL_UDP:
+               e->ip.proto = IPPROTO_UDP;
+               __add_port(entry, &size_mask, &size_match, rule, SIZE_UDP_MATCH);
+               break;
+       case IPTABLES_PROTOCOL_ICMP:
+               e->ip.proto = IPPROTO_ICMP;
+               break;
+       case IPTABLES_PROTOCOL_ESP:
+               e->ip.proto = IPPROTO_ESP;
+               break;
+       case IPTABLES_PROTOCOL_AH:
+               e->ip.proto = IPPROTO_AH;
+               break;
+       case IPTABLES_PROTOCOL_SCTP:
+               e->ip.proto = IPPROTO_SCTP;
+               break;
+       case IPTABLES_PROTOCOL_MH:
+               e->ip.proto = IPPROTO_MH;
+               break;
+       case IPTABLES_PROTOCOL_ALL:
+               e->ip.proto = 0;
+               break;
+       default:
+               e->ip.proto = 0;
+               break;
+       }
+
+       /* -m cgroup --cgroup 33 */
        if (rule->classid > 0) {
-               size_match += __add_cgroup_match(rule->classid, (ipt_entry_match_t *) e->elems);
+               size_match += __add_cgroup_match(rule->classid,
+                       (ipt_entry_match_t *) (e->elems + size_match));
                size_mask += sizeof(ipt_entry_match_t);
                e->target_offset += SIZE_CGROUP_MATCH;
                e->next_offset += SIZE_CGROUP_MATCH;
        }
 
+       /* -m nfacct --nfacct-name c2_1_33_seth_w0 */
        if (rule->nfacct_name) {
-               size_match += __add_nfacct_match(rule->nfacct_name, (ipt_entry_match_t *) (e->elems + size_match));
+               size_match += __add_nfacct_match(rule->nfacct_name,
+                       (ipt_entry_match_t *) (e->elems + size_match));
                size_mask += sizeof(ipt_entry_match_t);
                e->target_offset += SIZE_NFACCT_MATCH;
                e->next_offset += SIZE_NFACCT_MATCH;
index c74ecb3..b7473d6 100755 (executable)
@@ -31,18 +31,59 @@ typedef enum {
 } iptables_chain_e;
 
 typedef enum {
-       IPTABLES_RULE_IN,
-       IPTABLES_RULE_OUT
-} iptables_rule_type_e;
+       IPTABLES_DIRECTION_NONE,
+       IPTABLES_DIRECTION_IN,
+       IPTABLES_DIRECTION_OUT
+} iptables_direction_e;
 
 typedef enum {
+       IPTABLES_IP_NONE,
+       IPTABLES_IP_SINGLE,
+       IPTABLES_IP_MASK,
+       IPTABLES_IP_RANGE
+} iptables_ip_type_e;
+
+typedef enum {
+       IPTABLES_PORT_NONE,
+       IPTABLES_PORT_SINGLE,
+       IPTABLES_PORT_RANGE
+} iptables_port_type_e;
+
+typedef enum {
+       IPTABLES_PROTOCOL_NONE,
+       IPTABLES_PROTOCOL_TCP,
+       IPTABLES_PROTOCOL_UDP,
+       IPTABLES_PROTOCOL_ICMP,
+       IPTABLES_PROTOCOL_ESP,
+       IPTABLES_PROTOCOL_AH,
+       IPTABLES_PROTOCOL_SCTP,
+       IPTABLES_PROTOCOL_MH,
+       IPTABLES_PROTOCOL_ALL,
+} iptables_protocol_type_e;
+
+typedef enum {
+       IPTABLES_ACTION_NONE,
        IPTABLES_ACTION_ACCEPT,
-       IPTABLES_ACTION_DROP
+       IPTABLES_ACTION_DROP,
+       IPTABLES_ACTION_LOG
 } iptables_target_action_e;
 
 typedef struct {
        char *chain;
-       iptables_rule_type_e type;
+       iptables_direction_e direction;
+       iptables_ip_type_e s_ip_type;
+       iptables_ip_type_e d_ip_type;
+       iptables_port_type_e s_port_type;
+       iptables_port_type_e d_port_type;
+       iptables_protocol_type_e protocol;
+       struct in_addr s_ip1;
+       struct in_addr s_ip2;
+       struct in_addr d_ip1;
+       struct in_addr d_ip2;
+       unsigned int s_port1;
+       unsigned int s_port2;
+       unsigned int d_port1;
+       unsigned int d_port2;
        char *ifname;
        int classid;
        char *nfacct_name;
index 6eb9646..bb07f7c 100755 (executable)
@@ -68,7 +68,7 @@ static void __stc_iptables_log_make_backup(void)
        if (rename(LOG_FILE_PATH, backup) != 0)
                remove(LOG_FILE_PATH);
 
-       g_free(backup);         
+       g_free(backup);
 }
 //LCOV_EXCL_STOP
 
index e18e600..3922fd9 100755 (executable)
 #include "helper-iptables.h"
 #include "helper-ip6tables.h"
 
+#define BUF_SIZE_FOR_IP 64
+
+#define RULE_CHAIN      "chain"
+#define RULE_DIRECTION  "type"
+#define RULE_IFNAME     "ifname"
+#define RULE_CGROUP     "cgroup"
+#define RULE_NFACCT     "nfacct"
+#define RULE_PROTOCOL   "protocol"
+#define RULE_TARGET     "target"
+
+#define RULE_FAMILY     "family"
+#define RULE_SIPTYPE    "s_ip_type"
+#define RULE_SIP1       "s_ip1"
+#define RULE_SIP2       "s_ip2"
+#define RULE_DIPTYPE    "d_ip_type"
+#define RULE_DIP1       "d_ip1"
+#define RULE_DIP2       "d_ip2"
+#define RULE_SPORTTYPE  "s_port_type"
+#define RULE_SPORT1     "s_port1"
+#define RULE_SPORT2     "s_port2"
+#define RULE_DPORTTYPE  "d_port_type"
+#define RULE_DPORT1     "d_port1"
+#define RULE_DPORT2     "d_port2"
+
 #define STC_IPTABLES_DBUS_ERROR_NAME "net.stc.iptables.Error.Failed"
-       
+
 #define STC_IPTABLES_DBUS_REPLY(invocation, parameters) \
                g_dbus_method_invocation_return_value((invocation), parameters);
-       
+
 #define STC_IPTABLES_DBUS_REPLY_ERROR(invocation, err_num) \
                g_dbus_method_invocation_return_dbus_error((invocation), \
                                                           STC_IPTABLES_DBUS_ERROR_NAME, \
@@ -49,36 +73,88 @@ void __stc_extract_rule(const char *key, GVariant *value,
        if (rule == NULL)
                return;
 
-       if (!g_strcmp0(key, "chain")) {
+       if (!g_strcmp0(key, RULE_CHAIN)) {
                gsize len = 0;
                rule->chain = g_variant_dup_string(value, &len);
-               STC_LOGD("chain: [%s]", rule->chain);
+               STC_LOGD("%s: [%s]", RULE_CHAIN, rule->chain);
+
+       } else if (!g_strcmp0(key, RULE_DIRECTION)) {
+               rule->direction = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIRECTION, rule->direction);
+
+       } else if (!g_strcmp0(key, RULE_SIPTYPE)) {
+               rule->s_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SIPTYPE, rule->s_ip_type);
+
+       } else if (!g_strcmp0(key, RULE_DIPTYPE)) {
+               rule->d_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIPTYPE, rule->d_ip_type);
+
+       } else if (!g_strcmp0(key, RULE_SPORTTYPE)) {
+               rule->s_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SPORTTYPE, rule->s_port_type);
+
+       } else if (!g_strcmp0(key, RULE_DPORTTYPE)) {
+               rule->d_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DPORTTYPE, rule->d_port_type);
+
+       } else if (!g_strcmp0(key, RULE_SIP1)) {
+               rule->s_ip1.s_addr = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%08x]", RULE_SIP1, rule->s_ip1.s_addr);
 
-       } else if (!g_strcmp0(key, "type")) {
-               rule->type = g_variant_get_uint32(value);
-               STC_LOGD("type: [%d]", rule->type);
+       } else if (!g_strcmp0(key, RULE_SIP2)) {
+               rule->s_ip2.s_addr = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%08x]", RULE_SIP2, rule->s_ip2.s_addr);
 
-       } else if (!g_strcmp0(key, "ifname")) {
+       } else if (!g_strcmp0(key, RULE_DIP1)) {
+               rule->d_ip1.s_addr = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%08x]", RULE_DIP1, rule->d_ip1.s_addr);
+
+       } else if (!g_strcmp0(key, RULE_DIP2)) {
+               rule->d_ip2.s_addr = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%08x]", RULE_DIP2, rule->d_ip2.s_addr);
+
+       } else if (!g_strcmp0(key, RULE_SPORT1)) {
+               rule->s_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT1, rule->s_port1);
+
+       } else if (!g_strcmp0(key, RULE_SPORT2)) {
+               rule->s_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT2, rule->s_port2);
+
+       } else if (!g_strcmp0(key, RULE_DPORT1)) {
+               rule->d_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT1, rule->d_port1);
+
+       } else if (!g_strcmp0(key, RULE_DPORT2)) {
+               rule->d_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT2, rule->d_port2);
+
+       } else if (!g_strcmp0(key, RULE_IFNAME)) {
                gsize len = 0;
                rule->ifname = g_variant_dup_string(value, &len);
-               STC_LOGD("ifname: [%s]", rule->ifname);
+               STC_LOGD("%s: [%s]", RULE_IFNAME, rule->ifname);
 
-       } else if (!g_strcmp0(key, "cgroup")) {
+       } else if (!g_strcmp0(key, RULE_CGROUP)) {
                rule->classid = g_variant_get_uint32(value);
-               STC_LOGD("classid: [%d]", rule->classid);
+               STC_LOGD("%s: [%u]", RULE_CGROUP, rule->classid);
 
-       } else if (!g_strcmp0(key, "nfacct")) {
+       } else if (!g_strcmp0(key, RULE_NFACCT)) {
                gsize len = 0;
                rule->nfacct_name = g_variant_dup_string(value, &len);
-               STC_LOGD("nfacct_name: [%s]", rule->nfacct_name);
+               STC_LOGD("%s: [%s]", RULE_NFACCT, rule->nfacct_name);
+
+       } else if (!g_strcmp0(key, RULE_PROTOCOL)) {
+               rule->protocol = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_PROTOCOL, rule->protocol);
 
-       } else if (!g_strcmp0(key, "target")) {
+       } else if (!g_strcmp0(key, RULE_TARGET)) {
                gsize len = 0;
                rule->target = g_variant_dup_string(value, &len);
-               STC_LOGD("target: [%s]", rule->target);
+               STC_LOGD("%s: [%s]", RULE_TARGET, rule->target);
 
        } else {
-               STC_LOGD("Unknown rule"); //LCOV_EXCL_LINE
+               STC_LOGD("Unknown rule [%s]", key); //LCOV_EXCL_LINE
        }
 }
 
@@ -89,39 +165,135 @@ void __stc_extract_6_rule(const char *key, GVariant *value,
        if (rule == NULL)
                return;
 
-       if (!g_strcmp0(key, "chain")) {
+       if (!g_strcmp0(key, RULE_CHAIN)) {
                gsize len = 0;
                rule->chain = g_variant_dup_string(value, &len);
-               STC_LOGD("chain: [%s]", rule->chain);
+               STC_LOGD("%s: [%s]", RULE_CHAIN, rule->chain);
+
+       } else if (!g_strcmp0(key, RULE_DIRECTION)) {
+               rule->direction = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIRECTION, rule->direction);
+
+       } else if (!g_strcmp0(key, RULE_SIPTYPE)) {
+               rule->s_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SIPTYPE, rule->s_ip_type);
 
-       } else if (!g_strcmp0(key, "type")) {
-               rule->type = g_variant_get_uint32(value);
-               STC_LOGD("type: [%d]", rule->type);
+       } else if (!g_strcmp0(key, RULE_DIPTYPE)) {
+               rule->d_ip_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DIPTYPE, rule->d_ip_type);
 
-       } else if (!g_strcmp0(key, "ifname")) {
+       } else if (!g_strcmp0(key, RULE_SPORTTYPE)) {
+               rule->s_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_SPORTTYPE, rule->s_port_type);
+
+       } else if (!g_strcmp0(key, RULE_DPORTTYPE)) {
+               rule->d_port_type = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_DPORTTYPE, rule->d_port_type);
+
+       } else if (!g_strcmp0(key, RULE_SIP1)) {
+               gsize len = 0;
+               char *str = g_variant_dup_string(value, &len);
+               sscanf(str, "%08x:%08x:%08x:%08x",
+                       &(rule->s_ip1.s6_addr32[0]), &(rule->s_ip1.s6_addr32[1]),
+                       &(rule->s_ip1.s6_addr32[2]), &(rule->s_ip1.s6_addr32[3]));
+               STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP1,
+                       rule->s_ip1.s6_addr32[0], rule->s_ip1.s6_addr32[1],
+                       rule->s_ip1.s6_addr32[2], rule->s_ip1.s6_addr32[3]);
+               FREE(str);
+
+       } else if (!g_strcmp0(key, RULE_SIP2)) {
+               gsize len = 0;
+               char *str = g_variant_dup_string(value, &len);
+               sscanf(str, "%08x:%08x:%08x:%08x",
+                       &(rule->s_ip2.s6_addr32[0]), &(rule->s_ip2.s6_addr32[1]),
+                       &(rule->s_ip2.s6_addr32[2]), &(rule->s_ip2.s6_addr32[3]));
+               STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_SIP2,
+                       rule->s_ip2.s6_addr32[0], rule->s_ip2.s6_addr32[1],
+                       rule->s_ip2.s6_addr32[2], rule->s_ip2.s6_addr32[3]);
+               FREE(str);
+
+       } else if (!g_strcmp0(key, RULE_DIP1)) {
+               gsize len = 0;
+               char *str = g_variant_dup_string(value, &len);
+               sscanf(str, "%08x:%08x:%08x:%08x",
+                       &(rule->d_ip1.s6_addr32[0]), &(rule->d_ip1.s6_addr32[1]),
+                       &(rule->d_ip1.s6_addr32[2]), &(rule->d_ip1.s6_addr32[3]));
+               STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP1,
+                       rule->d_ip1.s6_addr32[0], rule->d_ip1.s6_addr32[1],
+                       rule->d_ip1.s6_addr32[2], rule->d_ip1.s6_addr32[3]);
+               FREE(str);
+
+       } else if (!g_strcmp0(key, RULE_DIP2)) {
+               gsize len = 0;
+               char *str = g_variant_dup_string(value, &len);
+               sscanf(str, "%08x:%08x:%08x:%08x",
+                       &(rule->d_ip2.s6_addr32[0]), &(rule->d_ip2.s6_addr32[1]),
+                       &(rule->d_ip2.s6_addr32[2]), &(rule->d_ip2.s6_addr32[3]));
+               STC_LOGD("%s: [%08x:%08x:%08x:%08x]", RULE_DIP2,
+                       rule->d_ip2.s6_addr32[0], rule->d_ip2.s6_addr32[1],
+                       rule->d_ip2.s6_addr32[2], rule->d_ip2.s6_addr32[3]);
+               FREE(str);
+
+       } else if (!g_strcmp0(key, RULE_SPORT1)) {
+               rule->s_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT1, rule->s_port1);
+
+       } else if (!g_strcmp0(key, RULE_SPORT2)) {
+               rule->s_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_SPORT2, rule->s_port2);
+
+       } else if (!g_strcmp0(key, RULE_DPORT1)) {
+               rule->d_port1 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT1, rule->d_port1);
+
+       } else if (!g_strcmp0(key, RULE_DPORT2)) {
+               rule->d_port2 = g_variant_get_uint32(value);
+               STC_LOGD("%s: [%04x]", RULE_DPORT2, rule->d_port2);
+
+       } else if (!g_strcmp0(key, RULE_IFNAME)) {
                gsize len = 0;
                rule->ifname = g_variant_dup_string(value, &len);
-               STC_LOGD("ifname: [%s]", rule->ifname);
+               STC_LOGD("%s: [%s]", RULE_IFNAME, rule->ifname);
 
-       } else if (!g_strcmp0(key, "cgroup")) {
+       } else if (!g_strcmp0(key, RULE_CGROUP)) {
                rule->classid = g_variant_get_uint32(value);
-               STC_LOGD("classid: [%d]", rule->classid);
+               STC_LOGD("%s: [%u]", RULE_CGROUP, rule->classid);
 
-       } else if (!g_strcmp0(key, "nfacct")) {
+       } else if (!g_strcmp0(key, RULE_NFACCT)) {
                gsize len = 0;
                rule->nfacct_name = g_variant_dup_string(value, &len);
-               STC_LOGD("nfacct_name: [%s]", rule->nfacct_name);
+               STC_LOGD("%s: [%s]", RULE_NFACCT, rule->nfacct_name);
+
+       } else if (!g_strcmp0(key, RULE_PROTOCOL)) {
+               rule->protocol = g_variant_get_uint16(value);
+               STC_LOGD("%s: [%u]", RULE_PROTOCOL, rule->protocol);
 
-       } else if (!g_strcmp0(key, "target")) {
+       } else if (!g_strcmp0(key, RULE_TARGET)) {
                gsize len = 0;
                rule->target = g_variant_dup_string(value, &len);
-               STC_LOGD("target: [%s]", rule->target);
+               STC_LOGD("%s: [%s]", RULE_TARGET, rule->target);
 
        } else {
-               STC_LOGD("Unknown rule"); //LCOV_EXCL_LINE
+               STC_LOGD("Unknown rule [%s]", key); //LCOV_EXCL_LINE
        }
 }
 
+static void __free_rule(iptables_rule_s *rule)
+{
+       FREE(rule->chain);
+       FREE(rule->ifname);
+       FREE(rule->nfacct_name);
+       FREE(rule->target);
+}
+
+static void __free_6_rule(ip6tables_rule_s *rule)
+{
+       FREE(rule->chain);
+       FREE(rule->ifname);
+       FREE(rule->nfacct_name);
+       FREE(rule->target);
+}
+
 gboolean handle_iptables_stop(StcManager *object,
                                   GDBusMethodInvocation *invocation)
 {
@@ -167,19 +339,18 @@ gboolean handle_iptables_add_rule(StcRule *object,
                        if (ret != STC_ERROR_NONE) {
                                 //LCOV_EXCL_START
                                STC_LOGE("Failed add rule [%s:%d:%s:%d:%s:%s]", rule->chain,
-                                        rule->type, rule->ifname, rule->classid,
+                                        rule->direction, rule->ifname, rule->classid,
                                         rule->nfacct_name, rule->target);
 
-                               FREE(rule->chain);
-                               FREE(rule->ifname);
-                               FREE(rule->nfacct_name);
-                               FREE(rule->target);
+                               __free_rule(rule);
 
                                STC_IPTABLES_DBUS_REPLY_ERROR(invocation, ret);
                                __STC_LOG_FUNC_EXIT__;
                                return TRUE;
                                 //LCOV_EXCL_STOP
                        }
+
+                       __free_rule(rule);
                }
 
                g_variant_iter_free(iter);
@@ -224,19 +395,18 @@ gboolean handle_iptables_remove_rule(StcRule *object,
                        if (ret != STC_ERROR_NONE) {
                                 //LCOV_EXCL_START
                                STC_LOGE("Failed remove rule [%s:%d:%s:%d:%s:%s]", rule->chain,
-                                        rule->type, rule->ifname, rule->classid,
+                                        rule->direction, rule->ifname, rule->classid,
                                         rule->nfacct_name, rule->target);
 
-                               FREE(rule->chain);
-                               FREE(rule->ifname);
-                               FREE(rule->nfacct_name);
-                               FREE(rule->target);
+                               __free_rule(rule);
 
                                STC_IPTABLES_DBUS_REPLY_ERROR(invocation, ret);
                                __STC_LOG_FUNC_EXIT__;
                                return TRUE;
                                 //LCOV_EXCL_STOP
                        }
+
+                       __free_rule(rule);
                }
 
                g_variant_iter_free(iter);
@@ -357,19 +527,18 @@ gboolean handle_ip6tables_add_rule(StcRule *object,
                        if (ret != STC_ERROR_NONE) {
                                 //LCOV_EXCL_START
                                STC_LOGE("Failed add rule [%s:%d:%s:%d:%s:%s]", rule->chain,
-                                        rule->type, rule->ifname, rule->classid,
+                                        rule->direction, rule->ifname, rule->classid,
                                         rule->nfacct_name, rule->target);
 
-                               FREE(rule->chain);
-                               FREE(rule->ifname);
-                               FREE(rule->nfacct_name);
-                               FREE(rule->target);
+                               __free_6_rule(rule);
 
                                STC_IPTABLES_DBUS_REPLY_ERROR(invocation, ret);
                                __STC_LOG_FUNC_EXIT__;
                                return TRUE;
                                 //LCOV_EXCL_STOP
                        }
+
+                       __free_6_rule(rule);
                }
 
                g_variant_iter_free(iter);
@@ -414,19 +583,18 @@ gboolean handle_ip6tables_remove_rule(StcRule *object,
                        if (ret != STC_ERROR_NONE) {
                                 //LCOV_EXCL_START
                                STC_LOGE("Failed remove rule [%s:%d:%s:%d:%s:%s]", rule->chain,
-                                        rule->type, rule->ifname, rule->classid,
+                                        rule->direction, rule->ifname, rule->classid,
                                         rule->nfacct_name, rule->target);
 
-                               FREE(rule->chain);
-                               FREE(rule->ifname);
-                               FREE(rule->nfacct_name);
-                               FREE(rule->target);
+                               __free_6_rule(rule);
 
                                STC_IPTABLES_DBUS_REPLY_ERROR(invocation, ret);
                                __STC_LOG_FUNC_EXIT__;
                                return TRUE;
                                 //LCOV_EXCL_STOP
                        }
+
+                       __free_6_rule(rule);
                }
 
                g_variant_iter_free(iter);
index 27e9f71..91adcb2 100755 (executable)
 
 #define TARGET_ACCEPT "ACCEPT"
 #define TARGET_DROP   "DROP"
-
-#define RULE_CHAIN   "chain"
-#define RULE_TYPE    "type"
-#define RULE_IFNAME  "ifname"
-#define RULE_CGROUP  "cgroup"
-#define RULE_NFACCT  "nfacct"
-#define RULE_TARGET  "target"
+#define TARGET_LOG    "LOG"
+
+#define RULE_CHAIN      "chain"
+#define RULE_DIRECTION  "type"
+#define RULE_IFNAME     "ifname"
+#define RULE_CGROUP     "cgroup"
+#define RULE_NFACCT     "nfacct"
+#define RULE_PROTOCOL   "protocol"
+#define RULE_TARGET     "target"
+/* IPv4 */
+#define RULE_SIPV4TYPE  "s_ipv4_type"
+#define RULE_SIPV4      "s_ipv4"
+#define RULE_DIPV4TYPE  "d_ipv4_type"
+#define RULE_DIPV4      "d_ipv4"
+#define RULE_SPORTTYPE  "s_port_type"
+#define RULE_SPORT      "s_port"
+#define RULE_DPORTTYPE  "d_port_type"
+#define RULE_DPORT      "d_port"
+/* IPv6 */
+#define RULE_SIPV6TYPE  "s_ipv6_type"
+#define RULE_SIPV6      "s_ipv6"
+#define RULE_DIPV6TYPE  "d_ipv6_type"
+#define RULE_DIPV6      "d_ipv6"
+#define RULE_SPORT6TYPE "s_port6_type"
+#define RULE_SPORT6     "s_port6"
+#define RULE_DPORT6TYPE "d_port6_type"
+#define RULE_DPORT6     "d_port6"
 
 typedef enum {
        IPTABLES_CHAIN_INPUT,
@@ -48,19 +68,62 @@ typedef enum {
 } ipt_chain_e;
 
 typedef enum {
-       IPTABLES_RULE_IN,
-       IPTABLES_RULE_OUT
-} ipt_rule_type_e;
+       IPTABLES_DIRECTION_IN,
+       IPTABLES_DIRECTION_OUT
+} ipt_direction_e;
+
+typedef enum {
+       IPTABLES_IP_NONE,
+       IPTABLES_IP_SINGLE,
+       IPTABLES_IP_MASK,
+       IPTABLES_IP_RANGE
+} ipt_ip_type_e;
+
+typedef enum {
+       IPTABLES_PORT_NONE,
+       IPTABLES_PORT_SINGLE,
+       IPTABLES_PORT_RANGE
+} ipt_port_type_e;
+
+typedef enum {
+       IPTABLES_PROTOCOL_NONE,
+       IPTABLES_PROTOCOL_TCP,
+       IPTABLES_PROTOCOL_UDP,
+       IPTABLES_PROTOCOL_ICMP,
+       IPTABLES_PROTOCOL_ESP,
+       IPTABLES_PROTOCOL_AH,
+       IPTABLES_PROTOCOL_SCTP,
+       IPTABLES_PROTOCOL_MH,
+       IPTABLES_PROTOCOL_ALL,
+} ipt_protocol_type_e;
 
 typedef enum {
        IPTABLES_ACTION_NONE,
        IPTABLES_ACTION_ACCEPT,
-       IPTABLES_ACTION_DROP
+       IPTABLES_ACTION_DROP,
+       IPTABLES_ACTION_LOG
 } ipt_target_action_e;
 
 typedef struct {
        char *chain;
-       ipt_rule_type_e type;
+       ipt_direction_e direction;
+       ipt_ip_type_e s_ipv4_type;
+       ipt_ip_type_e d_ipv4_type;
+       ipt_port_type_e s_port_type;
+       ipt_port_type_e d_port_type;
+       ipt_ip_type_e s_ipv6_type;
+       ipt_ip_type_e d_ipv6_type;
+       ipt_port_type_e s_port6_type;
+       ipt_port_type_e d_port6_type;
+       ipt_protocol_type_e protocol;
+       char *s_ipv4;
+       char *d_ipv4;
+       char *s_port;
+       char *d_port;
+       char *s_ipv6;
+       char *d_ipv6;
+       char *s_port6;
+       char *d_port6;
        char *ifname;
        int classid;
        char *nfacct_name;
@@ -68,31 +131,127 @@ typedef struct {
 } ipt_rule_s;
 
 static char g_rule_chain[MENU_DATA_SIZE] = "STC_CHAIN";
-static char g_rule_type[MENU_DATA_SIZE] = "0";
+static char g_rule_direction[MENU_DATA_SIZE] = "0";
 static char g_rule_ifname[MENU_DATA_SIZE] = "seth_w0";
 static char g_rule_cgroup[MENU_DATA_SIZE] = "0";
 static char g_rule_nfacct[MENU_DATA_SIZE] = "";
+static char g_rule_protocol[MENU_DATA_SIZE] = "1";
 static char g_rule_target[MENU_DATA_SIZE] = "0";
+/* ipv4 */
+static char g_rule_s_ip_type[MENU_DATA_SIZE] = "2";
+static char g_rule_s_ip1[MENU_DATA_SIZE] = "102.132.217.5";
+static char g_rule_s_ip2[MENU_DATA_SIZE] = "255.255.255.0";
+static char g_rule_d_ip_type[MENU_DATA_SIZE] = "3";
+static char g_rule_d_ip1[MENU_DATA_SIZE] = "102.132.217.10";
+static char g_rule_d_ip2[MENU_DATA_SIZE] = "102.132.217.30";
+static char g_rule_s_port_type[MENU_DATA_SIZE] = "1";
+static char g_rule_s_port1[MENU_DATA_SIZE] = "80";
+static char g_rule_s_port2[MENU_DATA_SIZE] = "0";
+static char g_rule_d_port_type[MENU_DATA_SIZE] = "2";
+static char g_rule_d_port1[MENU_DATA_SIZE] = "0";
+static char g_rule_d_port2[MENU_DATA_SIZE] = "59136";
+/* ipv6 */
+static char g_rule_s_ip6_type[MENU_DATA_SIZE] = "2";
+static char g_rule_s_ip61[MENU_DATA_SIZE] = "2001:DB8::5";
+static char g_rule_s_ip62[MENU_DATA_SIZE] = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0";
+static char g_rule_d_ip6_type[MENU_DATA_SIZE] = "1";
+static char g_rule_d_ip61[MENU_DATA_SIZE] = "2001:DB8::10";
+static char g_rule_d_ip62[MENU_DATA_SIZE] = "2001:DB8::30";
+static char g_rule_s_port6_type[MENU_DATA_SIZE] = "1";
+static char g_rule_s_port61[MENU_DATA_SIZE] = "80";
+static char g_rule_s_port62[MENU_DATA_SIZE] = "0";
+static char g_rule_d_port6_type[MENU_DATA_SIZE] = "2";
+static char g_rule_d_port61[MENU_DATA_SIZE] = "0";
+static char g_rule_d_port62[MENU_DATA_SIZE] = "59136";
 
 static ipt_rule_s *g_rule = NULL;
 
+static char *__test_print_protocol_type(ipt_protocol_type_e type)
+{
+       switch (type) {
+       case IPTABLES_PROTOCOL_NONE:
+               return "None";
+       case IPTABLES_PROTOCOL_TCP:
+               return "TCP";
+       case IPTABLES_PROTOCOL_UDP:
+               return "UDP";
+       case IPTABLES_PROTOCOL_ICMP:
+               return "ICMP";
+       case IPTABLES_PROTOCOL_ESP:
+               return "ESP";
+       case IPTABLES_PROTOCOL_AH:
+               return "AH";
+       case IPTABLES_PROTOCOL_SCTP:
+               return "SCTP";
+       case IPTABLES_PROTOCOL_MH:
+               return "MH";
+       case IPTABLES_PROTOCOL_ALL:
+               return "All";
+       default:
+               return "Unknown";
+       }
+}
+
 static void __test_print_rule(ipt_rule_s *rule)
 {
        msg(HR_SINGLE);
 
-       msg("Chain  : [%s]", rule->chain);
-       if (rule->type == IPTABLES_RULE_IN)
-               msg("Type   : [IN]");
-       else if (rule->type == IPTABLES_RULE_OUT)
-               msg("Type   : [OUT]");
+       msg("Chain     : [%s]", rule->chain);
+
+       if (rule->direction == IPTABLES_DIRECTION_IN)
+               msg("Direction : [IN]");
+       else if (rule->direction == IPTABLES_DIRECTION_OUT)
+               msg("Dir       : [OUT]");
+
+       /* IPv4 */
+       if (rule->s_ipv4_type > IPTABLES_IP_NONE &&
+               rule->s_ipv4_type <= IPTABLES_IP_RANGE)
+               msg("S-IPv4    : [%s]", rule->s_ipv4);
+
+       if (rule->d_ipv4_type > IPTABLES_IP_NONE &&
+               rule->d_ipv4_type <= IPTABLES_IP_RANGE)
+               msg("D-IPv4    : [%s]", rule->d_ipv4);
+
+       if (rule->s_port_type > IPTABLES_PORT_NONE &&
+               rule->s_port_type <= IPTABLES_PORT_RANGE)
+               msg("S-Port    : [%s]", rule->s_port);
+
+       if (rule->d_port_type > IPTABLES_PORT_NONE &&
+               rule->d_port_type <= IPTABLES_PORT_RANGE)
+               msg("D-Port    : [%s]", rule->d_port);
+
+       /* IPv4 */
+       if (rule->s_ipv6_type > IPTABLES_IP_NONE &&
+               rule->s_ipv6_type <= IPTABLES_IP_RANGE)
+               msg("S-IPv6    : [%s]", rule->s_ipv6);
+
+       if (rule->d_ipv4_type > IPTABLES_IP_NONE &&
+               rule->d_ipv4_type <= IPTABLES_IP_RANGE)
+               msg("D-IPv6    : [%s]", rule->d_ipv6);
+
+       if (rule->s_port6_type > IPTABLES_PORT_NONE &&
+               rule->s_port6_type <= IPTABLES_PORT_RANGE)
+               msg("S-Port6   : [%s]", rule->s_port6);
+
+       if (rule->d_port6_type > IPTABLES_PORT_NONE &&
+               rule->d_port6_type <= IPTABLES_PORT_RANGE)
+               msg("D-Port6   : [%s]", rule->d_port6);
+
        if (rule->ifname)
-               msg("Ifname : [%s]", rule->ifname);
+               msg("Ifname    : [%s]", rule->ifname);
+
        if (rule->classid > 0)
-               msg("Cgroup : [%d]", rule->classid);
+               msg("Cgroup    : [%d]", rule->classid);
+
        if (rule->nfacct_name)
-               msg("Nfacct : [%s]", rule->nfacct_name);
+               msg("Nfacct    : [%s]", rule->nfacct_name);
+
+       if (rule->protocol > IPTABLES_PROTOCOL_NONE &&
+               rule->protocol <= IPTABLES_PROTOCOL_ALL)
+               msg("Protocol  : [%s]", __test_print_protocol_type(rule->protocol));
+
        if (rule->target)
-               msg("Target : [%s]", rule->target);
+               msg("Target    : [%s]", rule->target);
 
        msg(HR_SINGLE);
 }
@@ -109,15 +268,31 @@ static void __test_rule_free(ipt_rule_s *rule)
 
 static int __test_set_rule(void)
 {
-       int type = (int)strtol(g_rule_type, NULL, 10);
+       int direction = (int)strtol(g_rule_direction, NULL, 10);
+       int siptype = (int)strtol(g_rule_s_ip_type, NULL, 10);
+       int diptype = (int)strtol(g_rule_d_ip_type, NULL, 10);
+       int sporttype = (int)strtol(g_rule_s_port_type, NULL, 10);
+       int dporttype = (int)strtol(g_rule_d_port_type, NULL, 10);
+       int sip6type = (int)strtol(g_rule_s_ip6_type, NULL, 10);
+       int dip6type = (int)strtol(g_rule_d_ip6_type, NULL, 10);
+       int sport6type = (int)strtol(g_rule_s_port6_type, NULL, 10);
+       int dport6type = (int)strtol(g_rule_d_port6_type, NULL, 10);
        int classid = (int)strtol(g_rule_cgroup, NULL, 10);
+       int protocol = (int)strtol(g_rule_protocol, NULL, 10);
        int target = (int)strtol(g_rule_target, NULL, 10);
 
        if (g_rule_chain[0] == '\0' ||
-               type < IPTABLES_RULE_IN ||
-               type > IPTABLES_RULE_OUT ||
-               target < IPTABLES_ACTION_NONE ||
-               target > IPTABLES_ACTION_DROP) {
+               direction < IPTABLES_DIRECTION_IN || direction > IPTABLES_DIRECTION_OUT ||
+               siptype < IPTABLES_IP_NONE || siptype > IPTABLES_IP_RANGE ||
+               diptype < IPTABLES_IP_NONE || diptype > IPTABLES_IP_RANGE ||
+               sporttype < IPTABLES_PORT_NONE || sporttype > IPTABLES_PORT_RANGE ||
+               dporttype < IPTABLES_PORT_NONE || dporttype > IPTABLES_PORT_RANGE ||
+               sip6type < IPTABLES_IP_NONE || sip6type > IPTABLES_IP_RANGE ||
+               dip6type < IPTABLES_IP_NONE || dip6type > IPTABLES_IP_RANGE ||
+               sport6type < IPTABLES_PORT_NONE || sport6type > IPTABLES_PORT_RANGE ||
+               dport6type < IPTABLES_PORT_NONE || dport6type > IPTABLES_PORT_RANGE ||
+               protocol < IPTABLES_PROTOCOL_NONE || protocol > IPTABLES_PROTOCOL_ALL ||
+               target < IPTABLES_ACTION_NONE || target > IPTABLES_ACTION_LOG) {
                msg(LOG_RED "Invalid parameter" LOG_END);
                return STC_ERROR_INVALID_PARAMETER;
        }
@@ -133,11 +308,115 @@ static int __test_set_rule(void)
 
        memset(g_rule, 0, sizeof(ipt_rule_s));
        g_rule->chain = g_strdup(g_rule_chain);
-       g_rule->type = type;
+       g_rule->direction = direction;
+       g_rule->s_ipv4_type = siptype;
+       g_rule->d_ipv4_type = diptype;
+       g_rule->s_port_type = sporttype;
+       g_rule->d_port_type = dporttype;
+       g_rule->s_ipv6_type = sip6type;
+       g_rule->d_ipv6_type = dip6type;
+       g_rule->s_port6_type = sport6type;
+       g_rule->d_port6_type = dport6type;
+       g_rule->protocol = protocol;
+
+       switch (g_rule->s_ipv4_type) {
+       case IPTABLES_IP_SINGLE:
+               g_rule->s_ipv4 = g_strdup_printf("%s,", g_rule_s_ip1);
+               break;
+       case IPTABLES_IP_MASK:
+       case IPTABLES_IP_RANGE:
+               g_rule->s_ipv4 = g_strdup_printf("%s,%s", g_rule_s_ip1, g_rule_s_ip2);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->d_ipv4_type) {
+       case IPTABLES_IP_SINGLE:
+               g_rule->d_ipv4 = g_strdup_printf("%s,", g_rule_d_ip1);
+               break;
+       case IPTABLES_IP_MASK:
+       case IPTABLES_IP_RANGE:
+               g_rule->d_ipv4 = g_strdup_printf("%s,%s", g_rule_d_ip1, g_rule_d_ip2);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->s_port_type) {
+       case IPTABLES_PORT_SINGLE:
+               g_rule->s_port = g_strdup_printf("%s,", g_rule_s_port1);
+               break;
+       case IPTABLES_PORT_RANGE:
+               g_rule->s_port = g_strdup_printf("%s,%s", g_rule_s_port1, g_rule_s_port2);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->d_port_type) {
+       case IPTABLES_PORT_SINGLE:
+               g_rule->d_port = g_strdup_printf("%s,", g_rule_d_port1);
+               break;
+       case IPTABLES_PORT_RANGE:
+               g_rule->d_port = g_strdup_printf("%s,%s", g_rule_d_port1, g_rule_d_port2);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->s_ipv6_type) {
+       case IPTABLES_IP_SINGLE:
+               g_rule->s_ipv6 = g_strdup_printf("%s,", g_rule_s_ip61);
+               break;
+       case IPTABLES_IP_MASK:
+       case IPTABLES_IP_RANGE:
+               g_rule->s_ipv6 = g_strdup_printf("%s,%s", g_rule_s_ip61, g_rule_s_ip62);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->d_ipv6_type) {
+       case IPTABLES_IP_SINGLE:
+               g_rule->d_ipv6 = g_strdup_printf("%s,", g_rule_d_ip61);
+               break;
+       case IPTABLES_IP_MASK:
+       case IPTABLES_IP_RANGE:
+               g_rule->d_ipv6 = g_strdup_printf("%s,%s", g_rule_d_ip61, g_rule_d_ip62);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->s_port6_type) {
+       case IPTABLES_PORT_SINGLE:
+               g_rule->s_port6 = g_strdup_printf("%s,", g_rule_s_port61);
+               break;
+       case IPTABLES_PORT_RANGE:
+               g_rule->s_port6 = g_strdup_printf("%s,%s", g_rule_s_port61, g_rule_s_port62);
+               break;
+       default:
+               break;
+       }
+
+       switch (g_rule->d_port6_type) {
+       case IPTABLES_PORT_SINGLE:
+               g_rule->d_port6 = g_strdup_printf("%s,", g_rule_d_port1);
+               break;
+       case IPTABLES_PORT_RANGE:
+               g_rule->d_port6 = g_strdup_printf("%s,%s", g_rule_d_port61, g_rule_d_port62);
+               break;
+       default:
+               break;
+       }
+
        if (g_rule_ifname[0] != '\0')
                g_rule->ifname = g_strdup(g_rule_ifname);
+
        if (classid > 0)
                g_rule->classid = classid;
+
        if (g_rule_nfacct[0] != '\0')
                g_rule->nfacct_name = g_strdup(g_rule_nfacct);
 
@@ -148,6 +427,9 @@ static int __test_set_rule(void)
        case IPTABLES_ACTION_DROP:
                g_rule->target = g_strdup(TARGET_DROP);
                break;
+       case IPTABLES_ACTION_LOG:
+               g_rule->target = g_strdup(TARGET_LOG);
+               break;
        default:
                g_rule->target = g_strdup("");
                break;
@@ -178,8 +460,50 @@ static void __test_add_rule_info_to_builder(GVariantBuilder *builder,
        g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
                                g_variant_new_string(rule->chain));
 
-       g_variant_builder_add(builder, "{sv}", RULE_TYPE,
-                               g_variant_new_uint32(rule->type));
+       if (rule->direction == IPTABLES_DIRECTION_IN ||
+               rule->direction == IPTABLES_DIRECTION_OUT)
+               g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
+                       g_variant_new_uint32(rule->direction));
+
+       if (rule->s_ipv4_type > IPTABLES_IP_NONE &&
+               rule->s_ipv4_type <= IPTABLES_IP_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_SIPV4TYPE,
+                       g_variant_new_uint32(rule->s_ipv4_type));
+
+               if (rule->s_ipv4)
+                       g_variant_builder_add(builder, "{sv}", RULE_SIPV4,
+                               g_variant_new_string(rule->s_ipv4));
+       }
+
+       if (rule->d_ipv4_type > IPTABLES_IP_NONE &&
+               rule->d_ipv4_type <= IPTABLES_IP_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_DIPV4TYPE,
+                       g_variant_new_uint32(rule->d_ipv4_type));
+
+               if (rule->d_ipv4)
+                       g_variant_builder_add(builder, "{sv}", RULE_DIPV4,
+                               g_variant_new_string(rule->d_ipv4));
+       }
+
+       if (rule->s_port_type > IPTABLES_PORT_NONE &&
+               rule->s_port_type <= IPTABLES_PORT_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_SPORTTYPE,
+                       g_variant_new_uint32(rule->s_port_type));
+
+               if (rule->s_port)
+                       g_variant_builder_add(builder, "{sv}", RULE_SPORT,
+                               g_variant_new_string(rule->s_port));
+       }
+
+       if (rule->d_port_type > IPTABLES_PORT_NONE &&
+               rule->d_port_type <= IPTABLES_PORT_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_DPORTTYPE,
+                       g_variant_new_uint32(rule->d_port_type));
+
+               if (rule->d_port)
+                       g_variant_builder_add(builder, "{sv}", RULE_DPORT,
+                               g_variant_new_string(rule->d_port));
+       }
 
        if (rule->ifname)
                g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
@@ -193,6 +517,81 @@ static void __test_add_rule_info_to_builder(GVariantBuilder *builder,
                g_variant_builder_add(builder, "{sv}", RULE_NFACCT,
                                g_variant_new_string(rule->nfacct_name));
 
+       if (rule->protocol > IPTABLES_PROTOCOL_NONE &&
+               rule->protocol <= IPTABLES_PROTOCOL_ALL)
+               g_variant_builder_add(builder, "{sv}", RULE_PROTOCOL,
+                               g_variant_new_uint32(rule->protocol));
+
+       if (rule->target)
+               g_variant_builder_add(builder, "{sv}", RULE_TARGET,
+                               g_variant_new_string(rule->target));
+
+}
+
+static void __test_add_6rule_info_to_builder(GVariantBuilder *builder,
+                       ipt_rule_s *rule)
+{
+       g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
+                               g_variant_new_string(rule->chain));
+
+       g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
+                               g_variant_new_uint32(rule->direction));
+
+       if (rule->s_ipv6_type > IPTABLES_IP_NONE &&
+               rule->s_ipv6_type <= IPTABLES_IP_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_SIPV6TYPE,
+                       g_variant_new_uint32(rule->s_ipv6_type));
+
+               if (rule->s_ipv6)
+                       g_variant_builder_add(builder, "{sv}", RULE_SIPV6,
+                               g_variant_new_string(rule->s_ipv6));
+       }
+
+       if (rule->d_ipv6_type > IPTABLES_IP_NONE &&
+               rule->d_ipv6_type <= IPTABLES_IP_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_DIPV6TYPE,
+                       g_variant_new_uint32(rule->d_ipv6_type));
+
+               if (rule->d_ipv6)
+                       g_variant_builder_add(builder, "{sv}", RULE_DIPV6,
+                               g_variant_new_string(rule->d_ipv6));
+       }
+
+       if (rule->s_port6_type > IPTABLES_PORT_NONE &&
+               rule->s_port6_type <= IPTABLES_PORT_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_SPORT6TYPE,
+                       g_variant_new_uint32(rule->s_port6_type));
+
+               if (rule->s_port6)
+                       g_variant_builder_add(builder, "{sv}", RULE_SPORT6,
+                               g_variant_new_string(rule->s_port6));
+       }
+
+       if (rule->d_port6_type > IPTABLES_PORT_NONE &&
+               rule->d_port6_type <= IPTABLES_PORT_RANGE) {
+               g_variant_builder_add(builder, "{sv}", RULE_DPORT6TYPE,
+                       g_variant_new_uint32(rule->d_port6_type));
+
+               if (rule->d_port6)
+                       g_variant_builder_add(builder, "{sv}", RULE_DPORT6,
+                               g_variant_new_string(rule->d_port6));
+       }
+
+       if (rule->ifname)
+               g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
+                               g_variant_new_string(rule->ifname));
+
+       if (rule->classid > 0)
+               g_variant_builder_add(builder, "{sv}", RULE_CGROUP,
+                               g_variant_new_uint32(rule->classid));
+
+       if (rule->nfacct_name)
+               g_variant_builder_add(builder, "{sv}", RULE_NFACCT,
+                               g_variant_new_string(rule->nfacct_name));
+
+       g_variant_builder_add(builder, "{sv}", RULE_PROTOCOL,
+                               g_variant_new_uint32(rule->protocol));
+
        if (rule->target)
                g_variant_builder_add(builder, "{sv}", RULE_TARGET,
                                g_variant_new_string(rule->target));
@@ -241,7 +640,7 @@ static int __stc_ip6t_add_rule(void)
        GVariant *message = NULL;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
-       __test_add_rule_info_to_builder(builder, g_rule);
+       __test_add_6rule_info_to_builder(builder, g_rule);
        params = g_variant_new("(a{sv})", builder);
        g_variant_builder_unref(builder);
 
@@ -308,7 +707,7 @@ static int __stc_ip6t_remove_rule(void)
        GVariant *message = NULL;
 
        builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
-       __test_add_rule_info_to_builder(builder, g_rule);
+       __test_add_6rule_info_to_builder(builder, g_rule);
        params = g_variant_new("(a{sv})", builder);
        g_variant_builder_unref(builder);
 
@@ -369,13 +768,48 @@ void test_stc_ipt_clear_rule(void)
                __test_rule_free(g_rule);
 }
 
+static struct menu_data menu_set_ipv4[] = {
+       { "1", "source IPv4 type (0.None/1.Single/2.Mask/3.Range)", NULL, NULL, g_rule_s_ip_type},
+       { "11", "source IPv4 address 1", NULL, NULL, g_rule_s_ip1},
+       { "12", "source IPv4 address 2", NULL, NULL, g_rule_s_ip2},
+       { "2", "destination IPv4 type (0.None/1.Single/2.Mask/3.Range)", NULL, NULL, g_rule_d_ip_type},
+       { "21", "destination IPv4 address 1", NULL, NULL, g_rule_d_ip1},
+       { "22", "destination IPv4 address 2", NULL, NULL, g_rule_d_ip2},
+       { "3", "source port type (0.None/1.Single/2.Range)", NULL, NULL, g_rule_s_port_type},
+       { "31", "source port 1", NULL, NULL, g_rule_s_port1},
+       { "32", "source port 2", NULL, NULL, g_rule_s_port2},
+       { "4", "destination port type (0.None/1.Single/2.Range)", NULL, NULL, g_rule_d_port_type},
+       { "41", "destination port 1", NULL, NULL, g_rule_d_port1},
+       { "42", "destination port 2", NULL, NULL, g_rule_d_port2},
+       { NULL, NULL, },
+};
+
+static struct menu_data menu_set_ipv6[] = {
+       { "1", "source IPv6 type (0.None/1.Single/2.Mask/3.Range)", NULL, NULL, g_rule_s_ip6_type},
+       { "11", "source IPv6 address 1", NULL, NULL, g_rule_s_ip61},
+       { "12", "source IPv6 address 2", NULL, NULL, g_rule_s_ip62},
+       { "2", "destination IPv6 type (0.None/1.Single/2.Mask/3.Range)", NULL, NULL, g_rule_d_ip6_type},
+       { "21", "destination IPv6 address 1", NULL, NULL, g_rule_d_ip61},
+       { "22", "destination IPv6 address 2", NULL, NULL, g_rule_d_ip62},
+       { "3", "source port6 type (0.None/1.Single/2.Range)", NULL, NULL, g_rule_s_port6_type},
+       { "31", "source port6 1", NULL, NULL, g_rule_s_port61},
+       { "32", "source port6 2", NULL, NULL, g_rule_s_port62},
+       { "4", "destination port6 type (0.None/1.Single/2.Range)", NULL, NULL, g_rule_d_port6_type},
+       { "41", "destination port6 1", NULL, NULL, g_rule_d_port61},
+       { "42", "destination port6 2", NULL, NULL, g_rule_d_port62},
+       { NULL, NULL, },
+};
+
 static struct menu_data menu_set[] = {
        { "1", "chain name", NULL, NULL, g_rule_chain},
-       { "2", "type (0.IN/1.OUT)", NULL, NULL, g_rule_type},
+       { "2", "direction (0.IN/1.OUT)", NULL, NULL, g_rule_direction},
        { "3", "interface name", NULL, NULL, g_rule_ifname},
-       { "4", "cgroup classid", NULL, NULL, g_rule_cgroup},
-       { "5", "nfacct name", NULL, NULL, g_rule_nfacct},
-       { "6", "target (0.NONE/1.ACCEPT/2.DROP)", NULL, NULL, g_rule_target},
+       { "4", "[IPv4]", menu_set_ipv4, NULL, NULL},
+       { "6", "[IPv6]", menu_set_ipv6, NULL, NULL},
+       { "7", "cgroup classid", NULL, NULL, g_rule_cgroup},
+       { "8", "nfacct name", NULL, NULL, g_rule_nfacct},
+       { "9", "protocol (0.None/1.tcp/2.udp/3.icmp/4.esp/5.ah/6.sctp/7.mh/8.all)", NULL, NULL, g_rule_protocol},
+       { "0", "target (0.NONE/1.ACCEPT/2.DROP/3.LOG)", NULL, NULL, g_rule_target},
        { "s", LOG_LIGHTBLUE "[Set]" LOG_END " rule", NULL, test_stc_ipt_set_rule, NULL},
        { NULL, NULL, },
 };
index e451301..20172fc 100755 (executable)
@@ -32,7 +32,7 @@ Rule::~Rule()
        Destroy();
 }
 
-error_e Rule::SetRule(const char *chain, ipt_rule_type_e rule_type,
+error_e Rule::SetRule(const char *chain, ipt_direction_e direction,
                const char *iface_name, int classid, const char *nfacct_name,
                const char *target_name)
 {
@@ -41,10 +41,10 @@ error_e Rule::SetRule(const char *chain, ipt_rule_type_e rule_type,
        else
                g_strlcpy(this->m_ChainName, chain, CHAIN_NAME_LEN);
 
-       switch (rule_type) {
+       switch (direction) {
        case IPT_RULE_IN:
        case IPT_RULE_OUT:
-               this->m_RuleType = rule_type;
+               this->m_Direction = direction;
                break;
        default:
                return ERROR_INVALID_PARAMETER;
@@ -80,8 +80,8 @@ void Rule::MakeRuleParams(GVariant **params)
        g_variant_builder_add(builder, "{sv}", RULE_CHAIN,
                g_variant_new_string(this->m_ChainName));
 
-       g_variant_builder_add(builder, "{sv}", RULE_TYPE,
-               g_variant_new_uint32(this->m_RuleType));
+       g_variant_builder_add(builder, "{sv}", RULE_DIRECTION,
+               g_variant_new_uint32(this->m_Direction));
 
        g_variant_builder_add(builder, "{sv}", RULE_IFNAME,
                g_variant_new_string(this->m_IfaceName));
index d7b2ffa..d4dbd3e 100755 (executable)
 #include "stcmgr.h"
 #include "gdbus.h"
 
-#define RULE_CHAIN   "chain"
-#define RULE_TYPE    "type"
-#define RULE_IFNAME  "ifname"
-#define RULE_CGROUP  "cgroup"
-#define RULE_NFACCT  "nfacct"
-#define RULE_TARGET  "target"
+#define RULE_CHAIN      "chain"
+#define RULE_DIRECTION  "type"
+#define RULE_IFNAME     "ifname"
+#define RULE_CGROUP     "cgroup"
+#define RULE_NFACCT     "nfacct"
+#define RULE_PROTOCOL   "protocol"
+#define RULE_TARGET     "target"
+/* IPv4 */
+#define RULE_SIPV4TYPE  "s_ipv4_type"
+#define RULE_SIPV4      "s_ipv4"
+#define RULE_DIPV4TYPE  "d_ipv4_type"
+#define RULE_DIPV4      "d_ipv4"
+#define RULE_SPORTTYPE  "s_port_type"
+#define RULE_SPORT      "s_port"
+#define RULE_DPORTTYPE  "d_port_type"
+#define RULE_DPORT      "d_port"
+/* IPv6 */
+#define RULE_SIPV6TYPE  "s_ipv6_type"
+#define RULE_SIPV6      "s_ipv6"
+#define RULE_DIPV6TYPE  "d_ipv6_type"
+#define RULE_DIPV6      "d_ipv6"
+#define RULE_SPORT6TYPE "s_port6_type"
+#define RULE_SPORT6     "s_port6"
+#define RULE_DPORT6TYPE "d_port6_type"
+#define RULE_DPORT6     "d_port6"
 
 #define STC_IPT_METHOD_IPT_ADD_RULE       "IptAddRule"
 #define STC_IPT_METHOD_IPT_REMOVE_RULE    "IptRemoveRule"
 typedef enum {
        IPT_RULE_IN,
        IPT_RULE_OUT
-} ipt_rule_type_e;
+} ipt_direction_e;
 
 class Rule : public GDbus {
 private:
-       char m_ChainName[CHAIN_NAME_LEN];       
+       char m_ChainName[CHAIN_NAME_LEN];
        char m_IfaceName[IFACE_NAME_LEN];
        char m_NfacctName[NFACCT_NAME_LEN];
        char m_TargetName[TARGET_NAME_LEN];
        int m_ClassID;
-       ipt_rule_type_e m_RuleType;
+       ipt_direction_e m_Direction;
 public:
        Rule();
        ~Rule();
-       error_e SetRule(const char *chain, ipt_rule_type_e rule_type,
+       error_e SetRule(const char *chain, ipt_direction_e direction,
                const char *iface_name, int classid, const char *nfacct_name,
                const char *target_name);
        void MakeRuleParams(GVariant **params);
index a874a30..d84fffc 100755 (executable)
@@ -36,6 +36,7 @@ using ::testing::TestCase;
 
 #define TARGET_ACCEPT  "ACCEPT"
 #define TARGET_DROP    "DROP"
+#define TARGET_LOG     "LOG"
 
 typedef struct {
        int classid;