Commit dd6b25de authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Merge tag 'upstream/1.6.0+snapshot20161117'

Upstream version 1.6.0+snapshot20161117
parents 8fceaf37 7b095084
...@@ -3,65 +3,182 @@ ...@@ -3,65 +3,182 @@
#include <linux/netfilter/xt_cgroup.h> #include <linux/netfilter/xt_cgroup.h>
enum { enum {
O_CGROUP = 0, O_CLASSID = 0,
O_PATH = 1,
}; };
static void cgroup_help(void) static void cgroup_help_v0(void)
{ {
printf( printf(
"cgroup match options:\n" "cgroup match options:\n"
"[!] --cgroup fwid Match cgroup fwid\n"); "[!] --cgroup classid Match cgroup classid\n");
} }
static const struct xt_option_entry cgroup_opts[] = { static void cgroup_help_v1(void)
{
printf(
"cgroup match options:\n"
"[!] --path path Recursively match path relative to cgroup2 root\n"
"[!] --cgroup classid Match cgroup classid, can't be used with --path\n");
}
static const struct xt_option_entry cgroup_opts_v0[] = {
{ {
.name = "cgroup", .name = "cgroup",
.id = O_CGROUP, .id = O_CLASSID,
.type = XTTYPE_UINT32, .type = XTTYPE_UINT32,
.flags = XTOPT_INVERT | XTOPT_MAND | XTOPT_PUT, .flags = XTOPT_INVERT | XTOPT_MAND | XTOPT_PUT,
XTOPT_POINTER(struct xt_cgroup_info, id) XTOPT_POINTER(struct xt_cgroup_info_v0, id)
},
XTOPT_TABLEEND,
};
static const struct xt_option_entry cgroup_opts_v1[] = {
{
.name = "path",
.id = O_PATH,
.type = XTTYPE_STRING,
.flags = XTOPT_INVERT | XTOPT_PUT,
XTOPT_POINTER(struct xt_cgroup_info_v1, path)
},
{
.name = "cgroup",
.id = O_CLASSID,
.type = XTTYPE_UINT32,
.flags = XTOPT_INVERT | XTOPT_PUT,
XTOPT_POINTER(struct xt_cgroup_info_v1, classid)
}, },
XTOPT_TABLEEND, XTOPT_TABLEEND,
}; };
static void cgroup_parse(struct xt_option_call *cb) static void cgroup_parse_v0(struct xt_option_call *cb)
{ {
struct xt_cgroup_info *cgroupinfo = cb->data; struct xt_cgroup_info_v0 *cgroupinfo = cb->data;
xtables_option_parse(cb); xtables_option_parse(cb);
if (cb->invert) if (cb->invert)
cgroupinfo->invert = true; cgroupinfo->invert = true;
} }
static void cgroup_parse_v1(struct xt_option_call *cb)
{
struct xt_cgroup_info_v1 *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_PATH:
info->has_path = true;
if (cb->invert)
info->invert_path = true;
break;
case O_CLASSID:
info->has_classid = true;
if (cb->invert)
info->invert_classid = true;
break;
}
}
static void static void
cgroup_print(const void *ip, const struct xt_entry_match *match, int numeric) cgroup_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
{ {
const struct xt_cgroup_info *info = (void *) match->data; const struct xt_cgroup_info_v0 *info = (void *) match->data;
printf(" cgroup %s%u", info->invert ? "! ":"", info->id); printf(" cgroup %s%u", info->invert ? "! ":"", info->id);
} }
static void cgroup_save(const void *ip, const struct xt_entry_match *match) static void cgroup_save_v0(const void *ip, const struct xt_entry_match *match)
{ {
const struct xt_cgroup_info *info = (void *) match->data; const struct xt_cgroup_info_v0 *info = (void *) match->data;
printf("%s --cgroup %u", info->invert ? " !" : "", info->id); printf("%s --cgroup %u", info->invert ? " !" : "", info->id);
} }
static struct xtables_match cgroup_match = { static void
.family = NFPROTO_UNSPEC, cgroup_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
.name = "cgroup", {
.version = XTABLES_VERSION, const struct xt_cgroup_info_v1 *info = (void *)match->data;
.size = XT_ALIGN(sizeof(struct xt_cgroup_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_cgroup_info)), printf(" cgroup");
.help = cgroup_help, if (info->has_path)
.print = cgroup_print, printf(" %s%s", info->invert_path ? "! ":"", info->path);
.save = cgroup_save, if (info->has_classid)
.x6_parse = cgroup_parse, printf(" %s%u", info->invert_classid ? "! ":"", info->classid);
.x6_options = cgroup_opts, }
static void cgroup_save_v1(const void *ip, const struct xt_entry_match *match)
{
const struct xt_cgroup_info_v1 *info = (void *)match->data;
if (info->has_path) {
printf("%s --path", info->invert_path ? " !" : "");
xtables_save_string(info->path);
}
if (info->has_classid)
printf("%s --cgroup %u", info->invert_classid ? " !" : "",
info->classid);
}
static int cgroup_xlate_v0(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_cgroup_info_v0 *info = (void *)params->match->data;
xt_xlate_add(xl, "meta cgroup %s%u", info->invert ? "!= " : "",
info->id);
return 1;
}
static int cgroup_xlate_v1(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_cgroup_info_v1 *info = (void *)params->match->data;
if (info->has_path)
return 0;
if (info->has_classid)
xt_xlate_add(xl, "meta cgroup %s%u",
info->invert_classid ? "!= " : "",
info->classid);
return 1;
}
static struct xtables_match cgroup_match[] = {
{
.family = NFPROTO_UNSPEC,
.revision = 0,
.name = "cgroup",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_cgroup_info_v0)),
.userspacesize = XT_ALIGN(sizeof(struct xt_cgroup_info_v0)),
.help = cgroup_help_v0,
.print = cgroup_print_v0,
.save = cgroup_save_v0,
.x6_parse = cgroup_parse_v0,
.x6_options = cgroup_opts_v0,
.xlate = cgroup_xlate_v0,
},
{
.family = NFPROTO_UNSPEC,
.revision = 1,
.name = "cgroup",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_cgroup_info_v1)),
.userspacesize = offsetof(struct xt_cgroup_info_v1, priv),
.help = cgroup_help_v1,
.print = cgroup_print_v1,
.save = cgroup_save_v1,
.x6_parse = cgroup_parse_v1,
.x6_options = cgroup_opts_v1,
.xlate = cgroup_xlate_v1,
},
}; };
void _init(void) void _init(void)
{ {
xtables_register_match(&cgroup_match); xtables_register_matches(cgroup_match, ARRAY_SIZE(cgroup_match));
} }
.TP .TP
[\fB!\fP] \fB\-\-cgroup\fP \fIfwid\fP [\fB!\fP] \fB\-\-path\fP \fIpath\fP
Match corresponding cgroup for this packet. Match cgroup2 membership.
Can be used in the OUTPUT chain to assign particular firewall Each socket is associated with the v2 cgroup of the creating process.
policies for aggregated task/jobs on the system. This allows This matches packets coming from or going to all sockets in the
for more fine-grained firewall policies that only match for a sub-hierarchy of the specified path. The path should be relative to
subset of the system's processes. fwid is the maker set through the root of the cgroup2 hierarchy.
the net_cls cgroup's id. .TP
[\fB!\fP] \fB\-\-cgroup\fP \fIclassid\fP
Match cgroup net_cls classid.
\fBIMPORTANT\fP: when being used in the INPUT chain, the cgroup classid is the marker set through the cgroup net_cls controller. This
matcher is currently only of limited functionality, meaning it option and \-\-path can't be used together.
will only match on packets that are processed for local sockets
through early socket demuxing. Therefore, general usage on the
INPUT chain is disadviced unless the implications are well
understood.
.PP .PP
Example: Example:
.IP .IP
iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-path service/http-server \-j DROP
.IP
iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1 iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1
\-j DROP \-j DROP
.PP .PP
\fBIMPORTANT\fP: when being used in the INPUT chain, the cgroup
matcher is currently only of limited functionality, meaning it
will only match on packets that are processed for local sockets
through early socket demuxing. Therefore, general usage on the
INPUT chain is not advised unless the implications are well
understood.
.PP
Available since Linux 3.14. Available since Linux 3.14.
:INPUT,OUTPUT,POSTROUTING
*mangle
-m cgroup --cgroup 1;=;OK
-m cgroup ! --cgroup 1;=;OK
-m cgroup --path "/";=;OK
-m cgroup ! --path "/";=;OK
-m cgroup --cgroup 1 --path "/";;FAIL
-m cgroup ;;FAIL
:PREROUTING,FORWARD,POSTROUTING
*mangle
-m cluster;;FAIL
-m cluster --cluster-total-nodes 3;;FAIL
-m cluster --cluster-total-nodes 2 --cluster-local-node 2;;FAIL
-m cluster --cluster-total-nodes 2 --cluster-local-node 3 --cluster-hash-seed;;FAIL
#
# outputs --cluster-local-nodemask instead of --cluster-local-node
#
-m cluster --cluster-total-nodes 2 --cluster-local-node 2 --cluster-hash-seed 0xfeedcafe;-m cluster --cluster-local-nodemask 0x00000002 --cluster-total-nodes 2 --cluster-hash-seed 0xfeedcafe;OK
...@@ -48,6 +48,26 @@ comment_save(const void *ip, const struct xt_entry_match *match) ...@@ -48,6 +48,26 @@ comment_save(const void *ip, const struct xt_entry_match *match)
xtables_save_string(commentinfo->comment); xtables_save_string(commentinfo->comment);
} }
static int comment_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
struct xt_comment_info *commentinfo = (void *)params->match->data;
char comment[XT_MAX_COMMENT_LEN];
commentinfo->comment[XT_MAX_COMMENT_LEN - 1] = '\0';
if (params->escape_quotes)
snprintf(comment, XT_MAX_COMMENT_LEN, "\\\"%s\\\"",
commentinfo->comment);
else
snprintf(comment, XT_MAX_COMMENT_LEN, "\"%s\"",
commentinfo->comment);
comment[XT_MAX_COMMENT_LEN - 1] = '\0';
xt_xlate_add_comment(xl, comment);
return 1;
}
static struct xtables_match comment_match = { static struct xtables_match comment_match = {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
.name = "comment", .name = "comment",
...@@ -59,6 +79,7 @@ static struct xtables_match comment_match = { ...@@ -59,6 +79,7 @@ static struct xtables_match comment_match = {
.save = comment_save, .save = comment_save,
.x6_parse = xtables_option_parse, .x6_parse = xtables_option_parse,
.x6_options = comment_opts, .x6_options = comment_opts,
.xlate = comment_xlate,
}; };
void _init(void) void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m comment;;FAIL
-m comment --comment;;FAIL
#
# it fails with 256 characters
#
# should fail: iptables -A INPUT -m comment --comment xxxxxxxxxxxxxxxxx [....]
# -m comment --comment xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;;FAIL
#
# success with 255 characters
#
-m comment --comment xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK
:INPUT,FORWARD,OUTPUT
-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir original;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir reply;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir both;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir original;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir reply;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir both;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir original;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir reply;=;OK
-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir both;=;OK
-m connbytes --connbytes -1:0 --connbytes-mode packets --connbytes-dir original;;FAIL
-m connbytes --connbytes 0:-1 --connbytes-mode packets --connbytes-dir original;;FAIL
# ERROR: cannot find: iptables -I INPUT -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both
# -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both;=;OK
-m connbytes --connbytes 0:18446744073709551616 --connbytes-mode avgpkt --connbytes-dir both;;FAIL
-m connbytes --connbytes 0:1000 --connbytes-mode wrong --connbytes-dir both;;FAIL
-m connbytes --connbytes 0:1000 --connbytes-dir original;;FAIL
-m connbytes --connbytes 0:1000 --connbytes-mode packets;;FAIL
-m connbytes --connbytes-dir original;;FAIL
-m connbytes --connbytes 0:1000;;FAIL
-m connbytes;;FAIL
...@@ -34,13 +34,23 @@ static const struct xt_option_entry connlabel_mt_opts[] = { ...@@ -34,13 +34,23 @@ static const struct xt_option_entry connlabel_mt_opts[] = {
*/ */
static void connlabel_open(void) static void connlabel_open(void)
{ {
const char *fname;
if (map) if (map)
return; return;
map = nfct_labelmap_new(NULL); map = nfct_labelmap_new(NULL);
if (!map && errno) if (map != NULL)
xtables_error(RESOURCE_PROBLEM, "cannot open connlabel.conf: %s\n", return;
strerror(errno));
fname = nfct_labels_get_path();
if (errno) {
xtables_error(RESOURCE_PROBLEM,
"cannot open %s: %s", fname, strerror(errno));
} else {
xtables_error(RESOURCE_PROBLEM,
"cannot parse %s: no labels found", fname);
}
} }
static void connlabel_mt_parse(struct xt_option_call *cb) static void connlabel_mt_parse(struct xt_option_call *cb)
...@@ -118,6 +128,27 @@ connlabel_mt_save(const void *ip, const struct xt_entry_match *match) ...@@ -118,6 +128,27 @@ connlabel_mt_save(const void *ip, const struct xt_entry_match *match)
connlabel_mt_print_op(info, "--"); connlabel_mt_print_op(info, "--");
} }
static int connlabel_mt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_connlabel_mtinfo *info =
(const void *)params->match->data;
const char *name = connlabel_get_name(info->bit);
if (name == NULL)
return 0;
if (info->options & XT_CONNLABEL_OP_SET)
xt_xlate_add(xl, "ct label set %s ", name);
xt_xlate_add(xl, "ct label ");
if (info->options & XT_CONNLABEL_OP_INVERT)
xt_xlate_add(xl, "and %s != ", name);
xt_xlate_add(xl, "%s", name);
return 1;
}
static struct xtables_match connlabel_mt_reg = { static struct xtables_match connlabel_mt_reg = {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
.name = "connlabel", .name = "connlabel",
...@@ -129,6 +160,7 @@ static struct xtables_match connlabel_mt_reg = { ...@@ -129,6 +160,7 @@ static struct xtables_match connlabel_mt_reg = {
.save = connlabel_mt_save, .save = connlabel_mt_save,
.x6_parse = connlabel_mt_parse, .x6_parse = connlabel_mt_parse,
.x6_options = connlabel_mt_opts, .x6_options = connlabel_mt_opts,
.xlate = connlabel_mt_xlate,
}; };
void _init(void) void _init(void)
......
:INPUT,FORWARD,OUTPUT
# Backup the connlabel.conf, then add some label maps for test
@[ -f /etc/xtables/connlabel.conf ] && mv /etc/xtables/connlabel.conf /tmp/connlabel.conf.bak
@mkdir -p /etc/xtables
@echo "40 bit40" > /etc/xtables/connlabel.conf
@echo "41 bit41" >> /etc/xtables/connlabel.conf
@echo "128 bit128" >> /etc/xtables/connlabel.conf
-m connlabel --label "bit40";=;OK
-m connlabel ! --label "bit40";=;OK
-m connlabel --label "bit41" --set;=;OK
-m connlabel ! --label "bit41" --set;=;OK
-m connlabel --label "bit128";;FAIL
@echo > /etc/xtables/connlabel.conf
-m connlabel --label "abc";;FAIL
@rm -f /etc/xtables/connlabel.conf
-m connlabel --label "abc";;FAIL
# Restore the original connlabel.conf
@[ -f /tmp/connlabel.conf.bak ] && mv /tmp/connlabel.conf.bak /etc/xtables/connlabel.conf
:INPUT,FORWARD,OUTPUT
-m connlimit --connlimit-upto 0;=;OK
-m connlimit --connlimit-upto 4294967295;=;OK
-m connlimit --connlimit-upto 4294967296;;FAIL
-m connlimit --connlimit-upto -1;;FAIL
-m connlimit --connlimit-above 0;=;OK
-m connlimit --connlimit-above 4294967295;=;OK
-m connlimit --connlimit-above 4294967296;;FAIL
-m connlimit --connlimit-above -1;;FAIL
-m connlimit --connlimit-upto 1 --conlimit-above 1;;FAIL
-m connlimit --connlimit-above 10 --connlimit-saddr;-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-saddr;OK
-m connlimit --connlimit-above 10 --connlimit-daddr;-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-daddr;OK
-m connlimit --connlimit-above 10 --connlimit-saddr --connlimit-daddr;;FAIL
-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-saddr;=;OK
-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-daddr;=;OK
-m connlimit;;FAIL
...@@ -89,7 +89,8 @@ connmark_print(const void *ip, const struct xt_entry_match *match, int numeric) ...@@ -89,7 +89,8 @@ connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
} }
static void static void
connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric) connmark_mt_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{ {
const struct xt_connmark_mtinfo1 *info = (const void *)match->data; const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
...@@ -122,6 +123,49 @@ connmark_mt_save(const void *ip, const struct xt_entry_match *match) ...@@ -122,6 +123,49 @@ connmark_mt_save(const void *ip, const struct xt_entry_match *match)
print_mark(info->mark, info->mask); print_mark(info->mark, info->mask);
} }
static void print_mark_xlate(unsigned int mark, unsigned int mask,
struct xt_xlate *xl, uint32_t op)
{
if (mask != 0xffffffffU)
xt_xlate_add(xl, " and 0x%x %s 0x%x", mask,
op == XT_OP_EQ ? "==" : "!=", mark);
else
xt_xlate_add(xl, " %s0x%x",
op == XT_OP_EQ ? "" : "!= ", mark);
}
static int connmark_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_connmark_info *info = (const void *)params->match->data;
enum xt_op op = XT_OP_EQ;
if (info->invert)
op = XT_OP_NEQ;
xt_xlate_add(xl, "ct mark");
print_mark_xlate(info->mark, info->mask, xl, op);
return 1;
}
static int
connmark_mt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_connmark_mtinfo1 *info =
(const void *)params->match->data;
enum xt_op op = XT_OP_EQ;
if (info->invert)
op = XT_OP_NEQ;
xt_xlate_add(xl, "ct mark");
print_mark_xlate(info->mark, info->mask, xl, op);
return 1;
}
static struct xtables_match connmark_mt_reg[] = { static struct xtables_match connmark_mt_reg[] = {
{ {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
...@@ -135,6 +179,7 @@ static struct xtables_match connmark_mt_reg[] = { ...@@ -135,6 +179,7 @@ static struct xtables_match connmark_mt_reg[] = {
.save = connmark_save, .save = connmark_save,
.x6_parse = connmark_parse, .x6_parse = connmark_parse,
.x6_options = connmark_mt_opts, .x6_options = connmark_mt_opts,
.xlate = connmark_xlate,
}, },
{ {
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
...@@ -148,6 +193,7 @@ static struct xtables_match connmark_mt_reg[] = { ...@@ -148,6 +193,7 @@ static struct xtables_match connmark_mt_reg[] = {
.save = connmark_mt_save, .save = connmark_mt_save,
.x6_parse = connmark_mt_parse, .x6_parse = connmark_mt_parse,
.x6_options = connmark_mt_opts, .x6_options = connmark_mt_opts,
.xlate = connmark_mt_xlate,
}, },
}; };
......
:PREROUTING,FORWARD,OUTPUT,POSTROUTING
*mangle
-m connmark --mark 0xffffffff;=;OK
-m connmark --mark 0xffffffff/0xffffffff;-m connmark --mark 0xffffffff;OK
-m connmark --mark 0xffffffff/0;=;OK
-m connmark --mark 0/0xffffffff;-m connmark --mark 0;OK
-m connmark --mark -1;;FAIL
-m connmark --mark 0xfffffffff;;FAIL
-m connmark;;FAIL
...@@ -1156,6 +1156,246 @@ static void state_save(const void *ip, const struct xt_entry_match *match) ...@@ -1156,6 +1156,246 @@ static void state_save(const void *ip, const struct xt_entry_match *match)
state_print_state(sinfo->statemask); state_print_state(sinfo->statemask);
} }
static void state_xlate_print(struct xt_xlate *xl, unsigned int statemask)
{
const char *sep = "";
if (statemask & XT_CONNTRACK_STATE_INVALID) {
xt_xlate_add(xl, "%s%s", sep, "invalid");
sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
xt_xlate_add(xl, "%s%s", sep, "new");
sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
xt_xlate_add(xl, "%s%s", sep, "related");
sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
xt_xlate_add(xl, "%s%s", sep, "established");
sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
xt_xlate_add(xl, "%s%s", sep, "untracked");
sep = ",";
}
}
static int state_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_conntrack_mtinfo3 *sinfo =
(const void *)params->match->data;
xt_xlate_add(xl, "ct state %s", sinfo->invert_flags & XT_CONNTRACK_STATE ?
"!= " : "");
state_xlate_print(xl, sinfo->state_mask);
xt_xlate_add(xl, " ");
return 1;
}
static void status_xlate_print(struct xt_xlate *xl, unsigned int statusmask)
{
const char *sep = "";
if (statusmask & IPS_EXPECTED) {
xt_xlate_add(xl, "%s%s", sep, "expected");
sep = ",";
}
if (statusmask & IPS_SEEN_REPLY) {
xt_xlate_add(xl, "%s%s", sep, "seen-reply");
sep = ",";
}
if (statusmask & IPS_ASSURED) {
xt_xlate_add(xl, "%s%s", sep, "assured");
sep = ",";
}
if (statusmask & IPS_CONFIRMED) {
xt_xlate_add(xl, "%s%s", sep, "confirmed");
sep = ",";
}
}
static void addr_xlate_print(struct xt_xlate *xl,
const union nf_inet_addr *addr,
const union nf_inet_addr *mask,
unsigned int family)
{
if (family == NFPROTO_IPV4) {
xt_xlate_add(xl, "%s%s", xtables_ipaddr_to_numeric(&addr->in),
xtables_ipmask_to_numeric(&mask->in));
} else if (family == NFPROTO_IPV6) {
xt_xlate_add(xl, "%s%s", xtables_ip6addr_to_numeric(&addr->in6),
xtables_ip6mask_to_numeric(&mask->in6));
}
}
static int _conntrack3_mt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params,
int family)
{
const struct xt_conntrack_mtinfo3 *sinfo =
(const void *)params->match->data;
char *space = "";
if (sinfo->match_flags & XT_CONNTRACK_DIRECTION) {
xt_xlate_add(xl, "ct direction %s",
sinfo->invert_flags & XT_CONNTRACK_DIRECTION ?
"reply" : "original");
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_PROTO) {
xt_xlate_add(xl, "%sct %s protocol %s%u", space,
sinfo->invert_flags & XT_CONNTRACK_DIRECTION ?
"reply" : "original",
sinfo->invert_flags & XT_CONNTRACK_PROTO ?
"!= " : "",
sinfo->l4proto);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_STATE) {
xt_xlate_add(xl, "%sct state %s", space,
sinfo->invert_flags & XT_CONNTRACK_STATE ?
"!= " : "");
state_xlate_print(xl, sinfo->state_mask);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_STATUS) {
if (sinfo->status_mask == 1)
return 0;
xt_xlate_add(xl, "%sct status %s", space,
sinfo->invert_flags & XT_CONNTRACK_STATUS ?
"!= " : "");
status_xlate_print(xl, sinfo->status_mask);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_EXPIRES) {
xt_xlate_add(xl, "%sct expiration %s", space,
sinfo->invert_flags & XT_CONNTRACK_EXPIRES ?
"!= " : "");
if (sinfo->expires_max == sinfo->expires_min)
xt_xlate_add(xl, "%lu", sinfo->expires_min);
else
xt_xlate_add(xl, "%lu-%lu", sinfo->expires_min,
sinfo->expires_max);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_ORIGSRC) {
if (&sinfo->origsrc_addr == 0L)
return 0;
xt_xlate_add(xl, "%sct original saddr %s", space,
sinfo->invert_flags & XT_CONNTRACK_ORIGSRC ?
"!= " : "");
addr_xlate_print(xl, &sinfo->origsrc_addr,
&sinfo->origsrc_mask, family);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_ORIGDST) {
if (&sinfo->origdst_addr == 0L)
return 0;
xt_xlate_add(xl, "%sct original daddr %s", space,
sinfo->invert_flags & XT_CONNTRACK_ORIGDST ?
"!= " : "");
addr_xlate_print(xl, &sinfo->origdst_addr,
&sinfo->origdst_mask, family);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_REPLSRC) {
if (&sinfo->replsrc_addr == 0L)
return 0;
xt_xlate_add(xl, "%sct reply saddr %s", space,
sinfo->invert_flags & XT_CONNTRACK_REPLSRC ?
"!= " : "");
addr_xlate_print(xl, &sinfo->replsrc_addr,
&sinfo->replsrc_mask, family);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_REPLDST) {
if (&sinfo->repldst_addr == 0L)
return 0;
xt_xlate_add(xl, "%sct reply daddr %s", space,
sinfo->invert_flags & XT_CONNTRACK_REPLDST ?
"!= " : "");
addr_xlate_print(xl, &sinfo->repldst_addr,
&sinfo->repldst_mask, family);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
xt_xlate_add(xl, "%sct original proto-src %s", space,
sinfo->invert_flags & XT_CONNTRACK_ORIGSRC_PORT ?
"!= " : "");
if (sinfo->origsrc_port == sinfo->origsrc_port_high)
xt_xlate_add(xl, "%u", sinfo->origsrc_port);
else
xt_xlate_add(xl, "%u-%u", sinfo->origsrc_port,
sinfo->origsrc_port_high);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
xt_xlate_add(xl, "%sct original proto-dst %s", space,
sinfo->invert_flags & XT_CONNTRACK_ORIGDST_PORT ?
"!= " : "");
if (sinfo->origdst_port == sinfo->origdst_port_high)
xt_xlate_add(xl, "%u", sinfo->origdst_port);
else
xt_xlate_add(xl, "%u-%u", sinfo->origdst_port,
sinfo->origdst_port_high);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
xt_xlate_add(xl, "%sct reply proto-src %s", space,
sinfo->invert_flags & XT_CONNTRACK_REPLSRC_PORT ?
"!= " : "");
if (sinfo->replsrc_port == sinfo->replsrc_port_high)
xt_xlate_add(xl, "%u", sinfo->replsrc_port);
else
xt_xlate_add(xl, "%u-%u", sinfo->replsrc_port,
sinfo->replsrc_port_high);
space = " ";
}
if (sinfo->match_flags & XT_CONNTRACK_REPLDST_PORT) {
xt_xlate_add(xl, "%sct reply proto-dst %s", space,
sinfo->invert_flags & XT_CONNTRACK_REPLDST_PORT ?
"!= " : "", sinfo->repldst_port);
if (sinfo->repldst_port == sinfo->repldst_port_high)
xt_xlate_add(xl, "%u", sinfo->repldst_port);
else
xt_xlate_add(xl, "%u-%u", sinfo->repldst_port,
sinfo->repldst_port_high);
}
return 1;
}
static int conntrack3_mt4_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
return _conntrack3_mt_xlate(xl, params, NFPROTO_IPV4);
}
static int conntrack3_mt6_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
return _conntrack3_mt_xlate(xl, params, NFPROTO_IPV6);
}
static struct xtables_match conntrack_mt_reg[] = { static struct xtables_match conntrack_mt_reg[] = {
{ {
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
...@@ -1246,6 +1486,7 @@ static struct xtables_match conntrack_mt_reg[] = { ...@@ -1246,6 +1486,7 @@ static struct xtables_match conntrack_mt_reg[] = {
.save = conntrack3_mt_save, .save = conntrack3_mt_save,
.alias = conntrack_print_name_alias, .alias = conntrack_print_name_alias,
.x6_options = conntrack3_mt_opts, .x6_options = conntrack3_mt_opts,
.xlate = conntrack3_mt4_xlate,
}, },
{ {
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
...@@ -1261,6 +1502,7 @@ static struct xtables_match conntrack_mt_reg[] = { ...@@ -1261,6 +1502,7 @@ static struct xtables_match conntrack_mt_reg[] = {
.save = conntrack3_mt6_save, .save = conntrack3_mt6_save,
.alias = conntrack_print_name_alias, .alias = conntrack_print_name_alias,
.x6_options = conntrack3_mt_opts, .x6_options = conntrack3_mt_opts,
.xlate = conntrack3_mt6_xlate,
}, },
{ {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
...@@ -1306,6 +1548,7 @@ static struct xtables_match conntrack_mt_reg[] = { ...@@ -1306,6 +1548,7 @@ static struct xtables_match conntrack_mt_reg[] = {
.save = state_save, .save = state_save,
.x6_parse = state_ct23_parse, .x6_parse = state_ct23_parse,
.x6_options = state_opts, .x6_options = state_opts,
.xlate = state_xlate,
}, },
{ {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
......
:INPUT,FORWARD,OUTPUT
-m conntrack --ctstate NEW;=;OK
-m conntrack --ctstate NEW,ESTABLISHED;=;OK
-m conntrack --ctstate NEW,RELATED,ESTABLISHED;=;OK
-m conntrack --ctstate INVALID;=;OK
-m conntrack --ctstate UNTRACKED;=;OK
-m conntrack --ctstate SNAT,DNAT;=;OK
-m conntrack --ctstate wrong;;FAIL
# should we convert this to output "tcp" instead of 6?
-m conntrack --ctproto tcp;-m conntrack --ctproto 6;OK
-m conntrack --ctorigsrc 1.1.1.1;=;OK
-m conntrack --ctorigdst 1.1.1.1;=;OK
-m conntrack --ctreplsrc 1.1.1.1;=;OK
-m conntrack --ctrepldst 1.1.1.1;=;OK
-m conntrack --ctexpire 0;=;OK
-m conntrack --ctexpire 4294967295;=;OK
-m conntrack --ctexpire 0:4294967295;=;OK
-m conntrack --ctexpire 42949672956;;FAIL
-m conntrack --ctexpire -1;;FAIL
-m conntrack --ctdir ORIGINAL;=;OK
-m conntrack --ctdir REPLY;=;OK
-m conntrack --ctstatus NONE;=;OK
-m conntrack --ctstatus CONFIRMED;=;OK
-m conntrack --ctstatus ASSURED;=;OK
-m conntrack --ctstatus EXPECTED;=;OK
-m conntrack --ctstatus SEEN_REPLY;=;OK
-m conntrack;;FAIL
...@@ -44,9 +44,19 @@ static void cpu_save(const void *ip, const struct xt_entry_match *match) ...@@ -44,9 +44,19 @@ static void cpu_save(const void *ip, const struct xt_entry_match *match)
printf("%s --cpu %u", info->invert ? " !" : "", info->cpu); printf("%s --cpu %u", info->invert ? " !" : "", info->cpu);
} }
static int cpu_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_cpu_info *info = (void *)params->match->data;
xt_xlate_add(xl, "cpu%s %u", info->invert ? " !=" : "", info->cpu);
return 1;
}
static struct xtables_match cpu_match = { static struct xtables_match cpu_match = {
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
.name = "cpu", .name = "cpu",
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_cpu_info)), .size = XT_ALIGN(sizeof(struct xt_cpu_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_cpu_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_cpu_info)),
...@@ -55,6 +65,7 @@ static struct xtables_match cpu_match = { ...@@ -55,6 +65,7 @@ static struct xtables_match cpu_match = {
.save = cpu_save, .save = cpu_save,
.x6_parse = cpu_parse, .x6_parse = cpu_parse,
.x6_options = cpu_opts, .x6_options = cpu_opts,
.xlate = cpu_xlate,
}; };
void _init(void) void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m cpu --cpu 0;=;OK
-m cpu ! --cpu 0;=;OK
-m cpu --cpu 4294967295;=;OK
-m cpu --cpu 4294967296;;FAIL
-m cpu;;FAIL
...@@ -277,6 +277,97 @@ static void dccp_save(const void *ip, const struct xt_entry_match *match) ...@@ -277,6 +277,97 @@ static void dccp_save(const void *ip, const struct xt_entry_match *match)
} }
} }
static const char *const dccp_pkt_types_xlate[] = {
[DCCP_PKT_REQUEST] = "request",
[DCCP_PKT_RESPONSE] = "response",
[DCCP_PKT_DATA] = "data",
[DCCP_PKT_ACK] = "ack",
[DCCP_PKT_DATAACK] = "dataack",
[DCCP_PKT_CLOSEREQ] = "closereq",
[DCCP_PKT_CLOSE] = "close",
[DCCP_PKT_RESET] = "reset",
[DCCP_PKT_SYNC] = "sync",
[DCCP_PKT_SYNCACK] = "syncack",
};
static int dccp_type_xlate(const struct xt_dccp_info *einfo,
struct xt_xlate *xl)
{
bool have_type = false, set_need = false;
uint16_t types = einfo->typemask;
if (types & (1 << DCCP_PKT_INVALID))
return 0;
xt_xlate_add(xl, " dccp type%s ", einfo->invflags ? " !=" : "");
if ((types != 0) && !(types == (types & -types))) {
xt_xlate_add(xl, "{");
set_need = true;
}
while (types) {
unsigned int i;
for (i = 0; !(types & (1 << i)); i++);
if (have_type)
xt_xlate_add(xl, ", ");
else
have_type = true;
xt_xlate_add(xl, "%s", dccp_pkt_types_xlate[i]);
types &= ~(1 << i);
}
if (set_need)
xt_xlate_add(xl, "}");
return 1;
}
static int dccp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_dccp_info *einfo =
(const struct xt_dccp_info *)params->match->data;
char *space = "";
int ret = 1;
xt_xlate_add(xl, "dccp ");
if (einfo->flags & XT_DCCP_SRC_PORTS) {
if (einfo->spts[0] != einfo->spts[1])
xt_xlate_add(xl, "sport%s %u-%u",
einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
einfo->spts[0], einfo->spts[1]);
else
xt_xlate_add(xl, "sport%s %u",
einfo->invflags & XT_DCCP_SRC_PORTS ? " !=" : "",
einfo->spts[0]);
space = " ";
}
if (einfo->flags & XT_DCCP_DEST_PORTS) {
if (einfo->dpts[0] != einfo->dpts[1])
xt_xlate_add(xl, "%sdport%s %u-%u", space,
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0], einfo->dpts[1]);
else
xt_xlate_add(xl, "%sdport%s %u", space,
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0]);
}
if (einfo->flags & XT_DCCP_TYPE)
ret = dccp_type_xlate(einfo, xl);
if (einfo->flags & XT_DCCP_OPTION)
ret = 0;
return ret;
}
static struct xtables_match dccp_match = { static struct xtables_match dccp_match = {
.name = "dccp", .name = "dccp",
.family = NFPROTO_UNSPEC, .family = NFPROTO_UNSPEC,
...@@ -288,6 +379,7 @@ static struct xtables_match dccp_match = { ...@@ -288,6 +379,7 @@ static struct xtables_match dccp_match = {
.save = dccp_save, .save = dccp_save,
.x6_parse = dccp_parse, .x6_parse = dccp_parse,
.x6_options = dccp_opts, .x6_options = dccp_opts,
.xlate = dccp_xlate,
}; };
void _init(void) void _init(void)
......
:INPUT,FORWARD,OUTPUT
-p dccp -m dccp --sport 1;=;OK
-p dccp -m dccp --sport 65535;=;OK
-p dccp -m dccp --dport 1;=;OK
-p dccp -m dccp --dport 65535;=;OK
-p dccp -m dccp --sport 1:1023;=;OK
-p dccp -m dccp --sport 1024:65535;=;OK
-p dccp -m dccp --sport 1024:;-p dccp -m dccp --sport 1024:65535;OK
-p dccp -m dccp ! --sport 1;=;OK
-p dccp -m dccp ! --sport 65535;=;OK
-p dccp -m dccp ! --dport 1;=;OK
-p dccp -m dccp ! --dport 65535;=;OK
-p dccp -m dccp --sport 1 --dport 65535;=;OK
-p dccp -m dccp --sport 65535 --dport 1;=;OK
-p dccp -m dccp ! --sport 1 --dport 65535;=;OK
-p dccp -m dccp ! --sport 65535 --dport 1;=;OK
# ERROR: should fail: iptables -A INPUT -p dccp -m dccp --sport 65536
# -p dccp -m dccp --sport 65536;;FAIL
-p dccp -m dccp --sport -1;;FAIL
-p dccp -m dccp --dport -1;;FAIL
-p dccp -m dccp --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,RESET,SYNC,SYNCACK,INVALID;=;OK
-p dccp -m dccp ! --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,RESET,SYNC,SYNCACK,INVALID;=;OK
# DCCP option 0 is valid, see http://tools.ietf.org/html/rfc4340#page-29
# ERROR: cannot load: iptables -A INPUT -p dccp -m dccp --dccp-option 0
#-p dccp -m dccp --dccp-option 0;=;OK
-p dccp -m dccp --dccp-option 255;=;OK
-p dccp -m dccp --dccp-option 256;;FAIL
-p dccp -m dccp --dccp-option -1;;FAIL
# should we accept this below?
-p dccp -m dccp;=;OK
...@@ -151,6 +151,61 @@ static void devgroup_check(struct xt_fcheck_call *cb) ...@@ -151,6 +151,61 @@ static void devgroup_check(struct xt_fcheck_call *cb)
"'--src-group' or '--dst-group'"); "'--src-group' or '--dst-group'");
} }
static void
print_devgroup_xlate(unsigned int id, uint32_t op, unsigned int mask,
struct xt_xlate *xl, int numeric)
{
const char *name = NULL;
if (mask != 0xffffffff)
xt_xlate_add(xl, "and 0x%x %s 0x%x", mask,
op == XT_OP_EQ ? "==" : "!=", id);
else {
if (numeric == 0)
name = xtables_lmap_id2name(devgroups, id);
xt_xlate_add(xl, "%s", op == XT_OP_EQ ? "" : "!= ");
if (name)
xt_xlate_add(xl, "%s", name);
else
xt_xlate_add(xl, "0x%x", id);
}
}
static void devgroup_show_xlate(const struct xt_devgroup_info *info,
struct xt_xlate *xl, int numeric)
{
enum xt_op op = XT_OP_EQ;
char *space = "";
if (info->flags & XT_DEVGROUP_MATCH_SRC) {
if (info->flags & XT_DEVGROUP_INVERT_SRC)
op = XT_OP_NEQ;
xt_xlate_add(xl, "iifgroup ");
print_devgroup_xlate(info->src_group, op,
info->src_mask, xl, numeric);
space = " ";
}
if (info->flags & XT_DEVGROUP_MATCH_DST) {
if (info->flags & XT_DEVGROUP_INVERT_DST)
op = XT_OP_NEQ;
xt_xlate_add(xl, "%soifgroup ", space);
print_devgroup_xlate(info->dst_group, op,
info->dst_mask, xl, numeric);
}
}
static int devgroup_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_devgroup_info *info = (const void *)params->match->data;
devgroup_show_xlate(info, xl, 0);
return 1;
}
static struct xtables_match devgroup_mt_reg = { static struct xtables_match devgroup_mt_reg = {
.name = "devgroup", .name = "devgroup",
.version = XTABLES_VERSION, .version = XTABLES_VERSION,
...@@ -164,6 +219,7 @@ static struct xtables_match devgroup_mt_reg = { ...@@ -164,6 +219,7 @@ static struct xtables_match devgroup_mt_reg = {
.x6_parse = devgroup_parse, .x6_parse = devgroup_parse,
.x6_fcheck = devgroup_check, .x6_fcheck = devgroup_check,
.x6_options = devgroup_opts, .x6_options = devgroup_opts,
.xlate = devgroup_xlate,
}; };
void _init(void) void _init(void)
......
...@@ -91,21 +91,66 @@ static void dscp_save(const void *ip, const struct xt_entry_match *match) ...@@ -91,21 +91,66 @@ static void dscp_save(const void *ip, const struct xt_entry_match *match)
printf("%s --dscp 0x%02x", dinfo->invert ? " !" : "", dinfo->dscp); printf("%s --dscp 0x%02x", dinfo->invert ? " !" : "", dinfo->dscp);
} }
static struct xtables_match dscp_match = { static int __dscp_xlate(struct xt_xlate *xl,
.family = NFPROTO_UNSPEC, const struct xt_xlate_mt_params *params)
.name = "dscp", {
.version = XTABLES_VERSION, const struct xt_dscp_info *dinfo =
.size = XT_ALIGN(sizeof(struct xt_dscp_info)), (const struct xt_dscp_info *)params->match->data;
.userspacesize = XT_ALIGN(sizeof(struct xt_dscp_info)),
.help = dscp_help, xt_xlate_add(xl, "dscp %s0x%02x", dinfo->invert ? "!= " : "",
.print = dscp_print, dinfo->dscp);
.save = dscp_save,
.x6_parse = dscp_parse, return 1;
.x6_fcheck = dscp_check, }
.x6_options = dscp_opts,
static int dscp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
xt_xlate_add(xl, "ip ");
return __dscp_xlate(xl, params);
}
static int dscp_xlate6(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
xt_xlate_add(xl, "ip6 ");
return __dscp_xlate(xl, params);
}
static struct xtables_match dscp_mt_reg[] = {
{
.family = NFPROTO_IPV4,
.name = "dscp",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_dscp_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_dscp_info)),
.help = dscp_help,
.print = dscp_print,
.save = dscp_save,
.x6_parse = dscp_parse,
.x6_fcheck = dscp_check,
.x6_options = dscp_opts,
.xlate = dscp_xlate,
},
{
.family = NFPROTO_IPV6,
.name = "dscp",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_dscp_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_dscp_info)),
.help = dscp_help,
.print = dscp_print,
.save = dscp_save,
.x6_parse = dscp_parse,
.x6_fcheck = dscp_check,
.x6_options = dscp_opts,
.xlate = dscp_xlate6,
},
}; };
void _init(void) void _init(void)
{ {
xtables_register_match(&dscp_match); xtables_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg));
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment