#include <arpa/inet.h>
#include <xtables.h>
+#include <linux/netfilter.h>
#include <linux/netfilter/xt_cgroup.h>
#include <linux/netfilter/xt_nfacct.h>
-//#include <linux/netfilter/xt_iprange.h>
+#include <linux/netfilter/xt_iprange.h>
#include <linux/netfilter/xt_NFLOG.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h>
#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_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_TARGET_LOG IP6T_ALIGN(sizeof(ip6t_log_info_t))
#define SIZE_TARGET_NFLOG IP6T_ALIGN(sizeof(ip6t_nflog_info_t))
#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 \
+ SIZE_TARGET_LOG + SIZE_TARGET_NFLOG
-// + 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)
+static unsigned int __add_match(const char *name, ip6t_entry_match_t *start,
+ int revision, size_t size, void *data)
{
ip6t_entry_match_t *match = start;
g_strlcpy(match->u.user.name, name, XT_EXTENSION_MAXNAMELEN);
memcpy(match->data, data, size);
+ match->u.user.revision = revision;
return match->u.match_size;
}
return target->u.target_size;
}
+static unsigned int __add_iprange_match(ip6tables_ip_type_e sip_type,
+ struct in6_addr sip1, struct in6_addr sip2, ip6tables_ip_type_e dip_type,
+ struct in6_addr dip1, struct in6_addr dip2, ip6t_entry_match_t *start)
+{
+ ip6t_iprange_info_t iprange;
+ memset(&iprange, 0, sizeof(ip6t_iprange_info_t));
+
+ /* iprange => "--src-range " */
+ if (sip_type == IP6TABLES_IP_RANGE) {
+ memcpy(&(iprange.src_min.in6), &sip1, sizeof(struct in6_addr));
+ memcpy(&(iprange.src_max.in6), &sip2, sizeof(struct in6_addr));
+ iprange.flags |= IPRANGE_SRC;
+ }
+
+ /* iprange => "--dst-range " */
+ if (dip_type == IP6TABLES_IP_RANGE) {
+ memcpy(&(iprange.dst_min.in6), &dip1, sizeof(struct in6_addr));
+ memcpy(&(iprange.dst_max.in6), &dip2, sizeof(struct in6_addr));
+ iprange.flags |= IPRANGE_DST;
+ }
+
+ /* match_iprange => "-m iprange" */
+ return __add_match(IP6TC_IPRANGE, start, 1, sizeof(ip6t_iprange_info_t), &iprange);
+}
+
+static void __add_iprange(unsigned char *entry, unsigned int *size_mask,
+ unsigned int *size_match, ip6tables_rule_s *rule)
+{
+ ip6t_entry_t *e = (ip6t_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, (ip6t_entry_match_t *)(e->elems + (*size_match)));
+
+ (*size_mask) += sizeof(ip6t_entry_match_t);
+ e->target_offset += SIZE_IPRANGE_MATCH;
+ e->next_offset += SIZE_IPRANGE_MATCH;
+}
+
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,
default:
break;
}
- return __add_match(IP6TC_TCP, start, sizeof(ip6t_tcp_info_t), &tcp);
+ return __add_match(IP6TC_TCP, start, 0, sizeof(ip6t_tcp_info_t), &tcp);
}
case IP6TABLES_PROTOCOL_UDP:
{
default:
break;
}
- return __add_match(IP6TC_UDP, start, sizeof(ip6t_udp_info_t), &udp);
+ return __add_match(IP6TC_UDP, start, 0, sizeof(ip6t_udp_info_t), &udp);
}
default:
break;
memset(&cgroup, 0, sizeof(ip6t_cgroup_info_t));
cgroup.id = classid;
/* match_cgroup => "-m cgroup" */
- return __add_match(IP6TC_CGROUP, start, sizeof(ip6t_cgroup_info_t), &cgroup);
+ return __add_match(IP6TC_CGROUP, start, 0, sizeof(ip6t_cgroup_info_t), &cgroup);
}
static unsigned int __add_nfacct_match(const char *nfacct_name, ip6t_entry_match_t *start)
memset(&nfacct, 0, sizeof(ip6t_nfacct_info_t));
g_strlcpy(nfacct.name, nfacct_name, NFACCT_NAME_MAX);
/* match_nfacct => "-m nfacct" */
- return __add_match(IP6TC_NFACCT, start, sizeof(ip6t_nfacct_info_t), &nfacct);
+ return __add_match(IP6TC_NFACCT, start, 0, sizeof(ip6t_nfacct_info_t), &nfacct);
}
static unsigned int __add_log_target(unsigned char level, const char *prefix,
break;
}
+ if (rule->s_ip_type == IP6TABLES_IP_RANGE ||
+ rule->d_ip_type == IP6TABLES_IP_RANGE)
+ __add_iprange(entry, &size_mask, &size_match, rule);
+
/* -p tcp */
switch (rule->protocol) {
case IP6TABLES_PROTOCOL_TCP:
+ SIZE_NFACCT_MATCH + SIZE_IPRANGE_MATCH + SIZE_TARGET \
+ SIZE_TARGET_LOG + SIZE_TARGET_NFLOG
-static unsigned int __add_match(const char *name, ipt_entry_match_t *start, size_t size, void *data)
+static unsigned int __add_match(const char *name, ipt_entry_match_t *start,
+ int revision, size_t size, void *data)
{
ipt_entry_match_t *match = start;
g_strlcpy(match->u.user.name, name, XT_EXTENSION_MAXNAMELEN);
memcpy(match->data, data, size);
+ match->u.user.revision = revision;
return match->u.match_size;
}
/* 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;
+ memcpy(&(iprange.src_min.in), &sip1, sizeof(struct in_addr));
+ memcpy(&(iprange.src_max.in), &sip2, sizeof(struct in_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;
+ memcpy(&(iprange.dst_min.in), &dip1, sizeof(struct in_addr));
+ memcpy(&(iprange.dst_max.in), &dip2, sizeof(struct in_addr));
iprange.flags |= IPRANGE_DST;
}
/* match_iprange => "-m iprange" */
- return __add_match(IPTC_IPRANGE, start, sizeof(ipt_iprange_info_t), &iprange);
+ return __add_match(IPTC_IPRANGE, start, 1, sizeof(ipt_iprange_info_t), &iprange);
}
static void __add_iprange(unsigned char *entry, unsigned int *size_mask,
default:
break;
}
- return __add_match(IPTC_TCP, start, sizeof(ipt_tcp_info_t), &tcp);
+ return __add_match(IPTC_TCP, start, 0, sizeof(ipt_tcp_info_t), &tcp);
}
case IPTABLES_PROTOCOL_UDP:
{
default:
break;
}
- return __add_match(IPTC_UDP, start, sizeof(ipt_udp_info_t), &udp);
+ return __add_match(IPTC_UDP, start, 0, sizeof(ipt_udp_info_t), &udp);
}
default:
break;
memset(&cgroup, 0, sizeof(ipt_cgroup_info_t));
cgroup.id = classid;
/* match_cgroup => "-m cgroup" */
- return __add_match(IPTC_CGROUP, start, sizeof(ipt_cgroup_info_t), &cgroup);
+ return __add_match(IPTC_CGROUP, start, 0, sizeof(ipt_cgroup_info_t), &cgroup);
}
static unsigned int __add_nfacct_match(const char *nfacct_name, ipt_entry_match_t *start)
memset(&nfacct, 0, sizeof(ipt_nfacct_info_t));
g_strlcpy(nfacct.name, nfacct_name, NFACCT_NAME_MAX);
/* match_nfacct => "-m nfacct" */
- return __add_match(IPTC_NFACCT, start, sizeof(ipt_nfacct_info_t), &nfacct);
+ return __add_match(IPTC_NFACCT, start, 0, sizeof(ipt_nfacct_info_t), &nfacct);
}
static unsigned int __add_log_target(unsigned char level, const char *prefix,