2 * nwfilterxml2firewalltest.c: Test iptables rule generation
4 * Copyright (C) 2014 Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see
18 * <http://www.gnu.org/licenses/>.
24 #if defined (__linux__)
26 # include "testutils.h"
27 # include "nwfilter/nwfilter_ebiptables_driver.h"
28 # include "virbuffer.h"
30 # define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
31 # include "vircommandpriv.h"
33 # define VIR_FROM_THIS VIR_FROM_NONE
36 # define RULESTYPE "linux"
38 # error "test case not ported to this platform"
41 typedef struct _virNWFilterInst virNWFilterInst
;
42 struct _virNWFilterInst
{
43 virNWFilterDef
**filters
;
45 virNWFilterRuleInst
**rules
;
50 * Some sets of rules that will be common to all test files,
51 * so we don't bother including them in the test data files
52 * as that would just bloat them
55 static const char *commonRules
[] = {
56 /* Dropping ebtables rules */
57 "ebtables \\\n--concurrent \\\n-t nat \\\n-D PREROUTING \\\n-i vnet0 \\\n-j libvirt-J-vnet0\n"
58 "ebtables \\\n--concurrent \\\n-t nat \\\n-D POSTROUTING \\\n-o vnet0 \\\n-j libvirt-P-vnet0\n"
59 "ebtables \\\n--concurrent \\\n-t nat \\\n-L libvirt-J-vnet0\n"
60 "ebtables \\\n--concurrent \\\n-t nat \\\n-L libvirt-P-vnet0\n"
61 "ebtables \\\n--concurrent \\\n-t nat \\\n-F libvirt-J-vnet0\n"
62 "ebtables \\\n--concurrent \\\n-t nat \\\n-X libvirt-J-vnet0\n"
63 "ebtables \\\n--concurrent \\\n-t nat \\\n-F libvirt-P-vnet0\n"
64 "ebtables \\\n--concurrent \\\n-t nat \\\n-X libvirt-P-vnet0\n",
66 /* Creating ebtables chains */
67 "ebtables \\\n--concurrent \\\n-t nat \\\n-N libvirt-J-vnet0\n"
68 "ebtables \\\n--concurrent \\\n-t nat \\\n-N libvirt-P-vnet0\n",
70 /* Dropping iptables rules */
71 "iptables \\\n-w \\\n-D libvirt-out \\\n-m physdev \\\n--physdev-is-bridged \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
72 "iptables \\\n-w \\\n-D libvirt-out \\\n-m physdev \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
73 "iptables \\\n-w \\\n-D libvirt-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g FJ-vnet0\n"
74 "iptables \\\n-w \\\n-D libvirt-host-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g HJ-vnet0\n"
75 "iptables \\\n-w \\\n-F FP-vnet0\n"
76 "iptables \\\n-w \\\n-X FP-vnet0\n"
77 "iptables \\\n-w \\\n-F FJ-vnet0\n"
78 "iptables \\\n-w \\\n-X FJ-vnet0\n"
79 "iptables \\\n-w \\\n-F HJ-vnet0\n"
80 "iptables \\\n-w \\\n-X HJ-vnet0\n",
82 /* Creating iptables chains */
83 "iptables \\\n-w \\\n-N libvirt-in\n"
84 "iptables \\\n-w \\\n-N libvirt-out\n"
85 "iptables \\\n-w \\\n-N libvirt-in-post\n"
86 "iptables \\\n-w \\\n-N libvirt-host-in\n"
87 "iptables \\\n-w \\\n-D FORWARD \\\n-j libvirt-in\n"
88 "iptables \\\n-w \\\n-D FORWARD \\\n-j libvirt-out\n"
89 "iptables \\\n-w \\\n-D FORWARD \\\n-j libvirt-in-post\n"
90 "iptables \\\n-w \\\n-D INPUT \\\n-j libvirt-host-in\n"
91 "iptables \\\n-w \\\n-I FORWARD 1 \\\n-j libvirt-in\n"
92 "iptables \\\n-w \\\n-I FORWARD 2 \\\n-j libvirt-out\n"
93 "iptables \\\n-w \\\n-I FORWARD 3 \\\n-j libvirt-in-post\n"
94 "iptables \\\n-w \\\n-I INPUT 1 \\\n-j libvirt-host-in\n"
95 "iptables \\\n-w \\\n-N FP-vnet0\n"
96 "iptables \\\n-w \\\n-N FJ-vnet0\n"
97 "iptables \\\n-w \\\n-N HJ-vnet0\n"
98 "iptables \\\n-w \\\n-A libvirt-out \\\n-m physdev \\\n--physdev-is-bridged \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
99 "iptables \\\n-w \\\n-A libvirt-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g FJ-vnet0\n"
100 "iptables \\\n-w \\\n-A libvirt-host-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g HJ-vnet0\n"
101 "iptables \\\n-w \\\n-D libvirt-in-post \\\n-m physdev \\\n--physdev-in vnet0 \\\n-j ACCEPT\n"
102 "iptables \\\n-w \\\n-A libvirt-in-post \\\n-m physdev \\\n--physdev-in vnet0 \\\n-j ACCEPT\n",
104 /* Dropping ip6tables rules */
105 "ip6tables \\\n-w \\\n-D libvirt-out \\\n-m physdev \\\n--physdev-is-bridged \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
106 "ip6tables \\\n-w \\\n-D libvirt-out \\\n-m physdev \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
107 "ip6tables \\\n-w \\\n-D libvirt-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g FJ-vnet0\n"
108 "ip6tables \\\n-w \\\n-D libvirt-host-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g HJ-vnet0\n"
109 "ip6tables \\\n-w \\\n-F FP-vnet0\n"
110 "ip6tables \\\n-w \\\n-X FP-vnet0\n"
111 "ip6tables \\\n-w \\\n-F FJ-vnet0\n"
112 "ip6tables \\\n-w \\\n-X FJ-vnet0\n"
113 "ip6tables \\\n-w \\\n-F HJ-vnet0\n"
114 "ip6tables \\\n-w \\\n-X HJ-vnet0\n",
116 /* Creating ip6tables chains */
117 "ip6tables \\\n-w \\\n-N libvirt-in\n"
118 "ip6tables \\\n-w \\\n-N libvirt-out\n"
119 "ip6tables \\\n-w \\\n-N libvirt-in-post\n"
120 "ip6tables \\\n-w \\\n-N libvirt-host-in\n"
121 "ip6tables \\\n-w \\\n-D FORWARD \\\n-j libvirt-in\n"
122 "ip6tables \\\n-w \\\n-D FORWARD \\\n-j libvirt-out\n"
123 "ip6tables \\\n-w \\\n-D FORWARD \\\n-j libvirt-in-post\n"
124 "ip6tables \\\n-w \\\n-D INPUT \\\n-j libvirt-host-in\n"
125 "ip6tables \\\n-w \\\n-I FORWARD 1 \\\n-j libvirt-in\n"
126 "ip6tables \\\n-w \\\n-I FORWARD 2 \\\n-j libvirt-out\n"
127 "ip6tables \\\n-w \\\n-I FORWARD 3 \\\n-j libvirt-in-post\n"
128 "ip6tables \\\n-w \\\n-I INPUT 1 \\\n-j libvirt-host-in\n"
129 "ip6tables \\\n-w \\\n-N FP-vnet0\n"
130 "ip6tables \\\n-w \\\n-N FJ-vnet0\n"
131 "ip6tables \\\n-w \\\n-N HJ-vnet0\n"
132 "ip6tables \\\n-w \\\n-A libvirt-out \\\n-m physdev \\\n--physdev-is-bridged \\\n--physdev-out vnet0 \\\n-g FP-vnet0\n"
133 "ip6tables \\\n-w \\\n-A libvirt-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g FJ-vnet0\n"
134 "ip6tables \\\n-w \\\n-A libvirt-host-in \\\n-m physdev \\\n--physdev-in vnet0 \\\n-g HJ-vnet0\n"
135 "ip6tables \\\n-w \\\n-D libvirt-in-post \\\n-m physdev \\\n--physdev-in vnet0 \\\n-j ACCEPT\n"
136 "ip6tables \\\n-w \\\n-A libvirt-in-post \\\n-m physdev \\\n--physdev-in vnet0 \\\n-j ACCEPT\n",
138 /* Inserting ebtables rules */
139 "ebtables \\\n--concurrent \\\n-t nat \\\n-A PREROUTING \\\n-i vnet0 \\\n-j libvirt-J-vnet0\n"
140 "ebtables \\\n--concurrent \\\n-t nat \\\n-A POSTROUTING \\\n-o vnet0 \\\n-j libvirt-P-vnet0\n",
145 virNWFilterCreateVarsFrom(GHashTable
*vars1
,
148 g_autoptr(GHashTable
) res
= virHashNew(virNWFilterVarValueHashFree
);
150 if (virNWFilterHashTablePutAll(vars1
, res
) < 0)
153 if (virNWFilterHashTablePutAll(vars2
, res
) < 0)
156 return g_steal_pointer(&res
);
161 virNWFilterRuleInstFree(virNWFilterRuleInst
*inst
)
166 g_clear_pointer(&inst
->vars
, g_hash_table_unref
);
172 virNWFilterInstReset(virNWFilterInst
*inst
)
176 for (i
= 0; i
< inst
->nfilters
; i
++)
177 virNWFilterDefFree(inst
->filters
[i
]);
178 VIR_FREE(inst
->filters
);
181 for (i
= 0; i
< inst
->nrules
; i
++)
182 virNWFilterRuleInstFree(inst
->rules
[i
]);
183 VIR_FREE(inst
->rules
);
189 virNWFilterDefToInst(const char *xml
,
191 virNWFilterInst
*inst
);
194 virNWFilterRuleDefToRuleInst(virNWFilterDef
*def
,
195 virNWFilterRuleDef
*rule
,
197 virNWFilterInst
*inst
)
199 virNWFilterRuleInst
*ruleinst
;
202 ruleinst
= g_new0(virNWFilterRuleInst
, 1);
204 ruleinst
->chainSuffix
= def
->chainsuffix
;
205 ruleinst
->chainPriority
= def
->chainPriority
;
206 ruleinst
->def
= rule
;
207 ruleinst
->priority
= rule
->priority
;
208 ruleinst
->vars
= virHashNew(virNWFilterVarValueHashFree
);
210 if (virNWFilterHashTablePutAll(vars
, ruleinst
->vars
) < 0)
213 VIR_APPEND_ELEMENT(inst
->rules
, inst
->nrules
, ruleinst
);
217 virNWFilterRuleInstFree(ruleinst
);
223 virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDef
*inc
,
225 virNWFilterInst
*inst
)
227 g_autoptr(GHashTable
) tmpvars
= NULL
;
229 g_autofree
char *xml
= NULL
;
231 xml
= g_strdup_printf("%s/nwfilterxml2firewalldata/%s.xml", abs_srcdir
,
234 /* create a temporary hashmap for depth-first tree traversal */
235 if (!(tmpvars
= virNWFilterCreateVarsFrom(inc
->params
,
239 if (virNWFilterDefToInst(xml
,
247 virNWFilterInstReset(inst
);
252 virNWFilterDefToInst(const char *xml
,
254 virNWFilterInst
*inst
)
258 virNWFilterDef
*def
= virNWFilterDefParse(NULL
, xml
, 0);
263 VIR_APPEND_ELEMENT_COPY(inst
->filters
, inst
->nfilters
, def
);
265 for (i
= 0; i
< def
->nentries
; i
++) {
266 if (def
->filterEntries
[i
]->rule
) {
267 if (virNWFilterRuleDefToRuleInst(def
,
268 def
->filterEntries
[i
]->rule
,
272 } else if (def
->filterEntries
[i
]->include
) {
273 if (virNWFilterIncludeDefToRuleInst(def
->filterEntries
[i
]->include
,
283 virNWFilterInstReset(inst
);
288 static void testRemoveCommonRules(char *rules
)
291 char *offset
= rules
;
293 for (i
= 0; i
< G_N_ELEMENTS(commonRules
); i
++) {
294 char *tmp
= strstr(offset
, commonRules
[i
]);
295 size_t len
= strlen(commonRules
[i
]);
297 memmove(tmp
, tmp
+ len
, (strlen(tmp
) + 1) - len
);
304 static int testSetOneParameter(GHashTable
*vars
,
308 virNWFilterVarValue
*val
;
310 if ((val
= virHashLookup(vars
, name
)) == NULL
) {
311 val
= virNWFilterVarValueCreateSimpleCopyValue(value
);
314 if (virHashUpdateEntry(vars
, name
, val
) < 0) {
315 virNWFilterVarValueFree(val
);
319 if (virNWFilterVarValueAddValueCopy(val
, value
) < 0)
326 static int testSetDefaultParameters(GHashTable
*vars
)
328 if (testSetOneParameter(vars
, "IPSETNAME", "tck_test") < 0 ||
329 testSetOneParameter(vars
, "A", "1.1.1.1") ||
330 testSetOneParameter(vars
, "A", "2.2.2.2") ||
331 testSetOneParameter(vars
, "A", "3.3.3.3") ||
332 testSetOneParameter(vars
, "A", "3.3.3.3") ||
333 testSetOneParameter(vars
, "B", "80") ||
334 testSetOneParameter(vars
, "B", "90") ||
335 testSetOneParameter(vars
, "B", "80") ||
336 testSetOneParameter(vars
, "B", "80") ||
337 testSetOneParameter(vars
, "C", "1080") ||
338 testSetOneParameter(vars
, "C", "1090") ||
339 testSetOneParameter(vars
, "C", "1100") ||
340 testSetOneParameter(vars
, "C", "1110"))
345 static int testCompareXMLToArgvFiles(const char *xml
,
348 g_autofree
char *actualargv
= NULL
;
349 g_auto(virBuffer
) buf
= VIR_BUFFER_INITIALIZER
;
350 g_autoptr(GHashTable
) vars
= virHashNew(virNWFilterVarValueHashFree
);
351 virNWFilterInst inst
= { 0 };
353 g_autoptr(virCommandDryRunToken
) dryRunToken
= virCommandDryRunTokenNew();
355 virCommandSetDryRun(dryRunToken
, &buf
, true, true, NULL
, NULL
);
357 if (testSetDefaultParameters(vars
) < 0)
360 if (virNWFilterDefToInst(xml
,
365 if (ebiptables_driver
.applyNewRules("vnet0", inst
.rules
, inst
.nrules
) < 0)
368 actualargv
= virBufferContentAndReset(&buf
);
370 testRemoveCommonRules(actualargv
);
372 if (virTestCompareToFileFull(actualargv
, cmdline
, false) < 0)
378 virNWFilterInstReset(&inst
);
388 testCompareXMLToIPTablesHelper(const void *data
)
391 const struct testInfo
*info
= data
;
392 g_autofree
char *xml
= NULL
;
393 g_autofree
char *args
= NULL
;
395 xml
= g_strdup_printf("%s/nwfilterxml2firewalldata/%s.xml",
396 abs_srcdir
, info
->name
);
397 args
= g_strdup_printf("%s/nwfilterxml2firewalldata/%s-%s.args",
398 abs_srcdir
, info
->name
, RULESTYPE
);
400 result
= testCompareXMLToArgvFiles(xml
, args
);
411 # define DO_TEST(name) \
413 static struct testInfo info = { \
416 if (virTestRun("NWFilter XML-2-firewall " name, \
417 testCompareXMLToIPTablesHelper, &info) < 0) \
427 DO_TEST("conntrack");
430 DO_TEST("example-1");
431 DO_TEST("example-2");
433 DO_TEST("icmp-direction2");
434 DO_TEST("icmp-direction3");
435 DO_TEST("icmp-direction");
441 DO_TEST("ipt-no-macspoof");
449 DO_TEST("sctp-ipv6");
458 DO_TEST("udplite-ipv6");
461 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
464 VIR_TEST_MAIN_PRELOAD(mymain
, VIR_TEST_MOCK("virfirewall"))
466 #else /* ! defined (__linux__) */
473 #endif /* ! defined (__linux__) */