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_VIRFIREWALLPRIV_H_ALLOW
31 # include "virfirewallpriv.h"
33 # define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
34 # include "vircommandpriv.h"
36 # define VIR_FROM_THIS VIR_FROM_NONE
39 # define RULESTYPE "linux"
41 # error "test case not ported to this platform"
44 typedef struct _virNWFilterInst virNWFilterInst
;
45 typedef virNWFilterInst
*virNWFilterInstPtr
;
46 struct _virNWFilterInst
{
47 virNWFilterDefPtr
*filters
;
49 virNWFilterRuleInstPtr
*rules
;
54 * Some sets of rules that will be common to all test files,
55 * so we don't bother including them in the test data files
56 * as that would just bloat them
59 static const char *commonRules
[] = {
60 /* Dropping ebtables rules */
61 "ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-J-vnet0\n"
62 "ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-P-vnet0\n"
63 "ebtables -t nat -L libvirt-J-vnet0\n"
64 "ebtables -t nat -L libvirt-P-vnet0\n"
65 "ebtables -t nat -F libvirt-J-vnet0\n"
66 "ebtables -t nat -X libvirt-J-vnet0\n"
67 "ebtables -t nat -F libvirt-P-vnet0\n"
68 "ebtables -t nat -X libvirt-P-vnet0\n",
70 /* Creating ebtables chains */
71 "ebtables -t nat -N libvirt-J-vnet0\n"
72 "ebtables -t nat -N libvirt-P-vnet0\n",
74 /* Dropping iptables rules */
75 "iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
76 "iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n"
77 "iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
78 "iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
79 "iptables -F FP-vnet0\n"
80 "iptables -X FP-vnet0\n"
81 "iptables -F FJ-vnet0\n"
82 "iptables -X FJ-vnet0\n"
83 "iptables -F HJ-vnet0\n"
84 "iptables -X HJ-vnet0\n",
86 /* Creating iptables chains */
87 "iptables -N libvirt-in\n"
88 "iptables -N libvirt-out\n"
89 "iptables -N libvirt-in-post\n"
90 "iptables -N libvirt-host-in\n"
91 "iptables -D FORWARD -j libvirt-in\n"
92 "iptables -D FORWARD -j libvirt-out\n"
93 "iptables -D FORWARD -j libvirt-in-post\n"
94 "iptables -D INPUT -j libvirt-host-in\n"
95 "iptables -I FORWARD 1 -j libvirt-in\n"
96 "iptables -I FORWARD 2 -j libvirt-out\n"
97 "iptables -I FORWARD 3 -j libvirt-in-post\n"
98 "iptables -I INPUT 1 -j libvirt-host-in\n"
99 "iptables -N FP-vnet0\n"
100 "iptables -N FJ-vnet0\n"
101 "iptables -N HJ-vnet0\n"
102 "iptables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
103 "iptables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
104 "iptables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
105 "iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n"
106 "iptables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n",
108 /* Dropping ip6tables rules */
109 "ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
110 "ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n"
111 "ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
112 "ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
113 "ip6tables -F FP-vnet0\n"
114 "ip6tables -X FP-vnet0\n"
115 "ip6tables -F FJ-vnet0\n"
116 "ip6tables -X FJ-vnet0\n"
117 "ip6tables -F HJ-vnet0\n"
118 "ip6tables -X HJ-vnet0\n",
120 /* Creating ip6tables chains */
121 "ip6tables -N libvirt-in\n"
122 "ip6tables -N libvirt-out\n"
123 "ip6tables -N libvirt-in-post\n"
124 "ip6tables -N libvirt-host-in\n"
125 "ip6tables -D FORWARD -j libvirt-in\n"
126 "ip6tables -D FORWARD -j libvirt-out\n"
127 "ip6tables -D FORWARD -j libvirt-in-post\n"
128 "ip6tables -D INPUT -j libvirt-host-in\n"
129 "ip6tables -I FORWARD 1 -j libvirt-in\n"
130 "ip6tables -I FORWARD 2 -j libvirt-out\n"
131 "ip6tables -I FORWARD 3 -j libvirt-in-post\n"
132 "ip6tables -I INPUT 1 -j libvirt-host-in\n"
133 "ip6tables -N FP-vnet0\n"
134 "ip6tables -N FJ-vnet0\n"
135 "ip6tables -N HJ-vnet0\n"
136 "ip6tables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
137 "ip6tables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
138 "ip6tables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
139 "ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n"
140 "ip6tables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n",
142 /* Inserting ebtables rules */
143 "ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n"
144 "ebtables -t nat -A POSTROUTING -o vnet0 -j libvirt-P-vnet0\n",
148 static virHashTablePtr
149 virNWFilterCreateVarsFrom(virHashTablePtr vars1
,
150 virHashTablePtr vars2
)
152 virHashTablePtr res
= virNWFilterHashTableCreate(0);
156 if (virNWFilterHashTablePutAll(vars1
, res
) < 0)
159 if (virNWFilterHashTablePutAll(vars2
, res
) < 0)
171 virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst
)
176 virHashFree(inst
->vars
);
182 virNWFilterInstReset(virNWFilterInstPtr inst
)
186 for (i
= 0; i
< inst
->nfilters
; i
++)
187 virNWFilterDefFree(inst
->filters
[i
]);
188 VIR_FREE(inst
->filters
);
191 for (i
= 0; i
< inst
->nrules
; i
++)
192 virNWFilterRuleInstFree(inst
->rules
[i
]);
193 VIR_FREE(inst
->rules
);
199 virNWFilterDefToInst(const char *xml
,
200 virHashTablePtr vars
,
201 virNWFilterInstPtr inst
);
204 virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def
,
205 virNWFilterRuleDefPtr rule
,
206 virHashTablePtr vars
,
207 virNWFilterInstPtr inst
)
209 virNWFilterRuleInstPtr ruleinst
;
212 if (VIR_ALLOC(ruleinst
) < 0)
215 ruleinst
->chainSuffix
= def
->chainsuffix
;
216 ruleinst
->chainPriority
= def
->chainPriority
;
217 ruleinst
->def
= rule
;
218 ruleinst
->priority
= rule
->priority
;
219 if (!(ruleinst
->vars
= virNWFilterHashTableCreate(0)))
221 if (virNWFilterHashTablePutAll(vars
, ruleinst
->vars
) < 0)
224 if (VIR_APPEND_ELEMENT(inst
->rules
,
232 virNWFilterRuleInstFree(ruleinst
);
238 virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc
,
239 virHashTablePtr vars
,
240 virNWFilterInstPtr inst
)
242 virHashTablePtr tmpvars
= NULL
;
246 if (virAsprintf(&xml
, "%s/nwfilterxml2firewalldata/%s.xml",
247 abs_srcdir
, inc
->filterref
) < 0)
250 /* create a temporary hashmap for depth-first tree traversal */
251 if (!(tmpvars
= virNWFilterCreateVarsFrom(inc
->params
,
255 if (virNWFilterDefToInst(xml
,
263 virNWFilterInstReset(inst
);
264 virHashFree(tmpvars
);
270 virNWFilterDefToInst(const char *xml
,
271 virHashTablePtr vars
,
272 virNWFilterInstPtr inst
)
276 virNWFilterDefPtr def
= virNWFilterDefParseFile(xml
);
281 if (VIR_APPEND_ELEMENT_COPY(inst
->filters
,
284 virNWFilterDefFree(def
);
288 for (i
= 0; i
< def
->nentries
; i
++) {
289 if (def
->filterEntries
[i
]->rule
) {
290 if (virNWFilterRuleDefToRuleInst(def
,
291 def
->filterEntries
[i
]->rule
,
295 } else if (def
->filterEntries
[i
]->include
) {
296 if (virNWFilterIncludeDefToRuleInst(def
->filterEntries
[i
]->include
,
306 virNWFilterInstReset(inst
);
311 static void testRemoveCommonRules(char *rules
)
314 char *offset
= rules
;
316 for (i
= 0; i
< ARRAY_CARDINALITY(commonRules
); i
++) {
317 char *tmp
= strstr(offset
, commonRules
[i
]);
318 size_t len
= strlen(commonRules
[i
]);
320 memmove(tmp
, tmp
+ len
, (strlen(tmp
) + 1) - len
);
327 static int testSetOneParameter(virHashTablePtr vars
,
332 virNWFilterVarValuePtr val
;
334 if ((val
= virHashLookup(vars
, name
)) == NULL
) {
335 val
= virNWFilterVarValueCreateSimpleCopyValue(value
);
338 if (virHashUpdateEntry(vars
, name
, val
) < 0) {
339 virNWFilterVarValueFree(val
);
343 if (virNWFilterVarValueAddValueCopy(val
, value
) < 0)
351 static int testSetDefaultParameters(virHashTablePtr vars
)
353 if (testSetOneParameter(vars
, "IPSETNAME", "tck_test") < 0 ||
354 testSetOneParameter(vars
, "A", "1.1.1.1") ||
355 testSetOneParameter(vars
, "A", "2.2.2.2") ||
356 testSetOneParameter(vars
, "A", "3.3.3.3") ||
357 testSetOneParameter(vars
, "A", "3.3.3.3") ||
358 testSetOneParameter(vars
, "B", "80") ||
359 testSetOneParameter(vars
, "B", "90") ||
360 testSetOneParameter(vars
, "B", "80") ||
361 testSetOneParameter(vars
, "B", "80") ||
362 testSetOneParameter(vars
, "C", "1080") ||
363 testSetOneParameter(vars
, "C", "1090") ||
364 testSetOneParameter(vars
, "C", "1100") ||
365 testSetOneParameter(vars
, "C", "1110"))
370 static int testCompareXMLToArgvFiles(const char *xml
,
373 char *actualargv
= NULL
;
374 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
375 virHashTablePtr vars
= virNWFilterHashTableCreate(0);
376 virNWFilterInst inst
;
379 memset(&inst
, 0, sizeof(inst
));
381 virCommandSetDryRun(&buf
, NULL
, NULL
);
386 if (testSetDefaultParameters(vars
) < 0)
389 if (virNWFilterDefToInst(xml
,
394 if (ebiptables_driver
.applyNewRules("vnet0", inst
.rules
, inst
.nrules
) < 0)
397 if (virBufferError(&buf
))
400 actualargv
= virBufferContentAndReset(&buf
);
401 virTestClearCommandPath(actualargv
);
402 virCommandSetDryRun(NULL
, NULL
, NULL
);
404 testRemoveCommonRules(actualargv
);
406 if (virTestCompareToFile(actualargv
, cmdline
) < 0)
412 virBufferFreeAndReset(&buf
);
413 VIR_FREE(actualargv
);
414 virNWFilterInstReset(&inst
);
425 testCompareXMLToIPTablesHelper(const void *data
)
428 const struct testInfo
*info
= data
;
432 if (virAsprintf(&xml
, "%s/nwfilterxml2firewalldata/%s.xml",
433 abs_srcdir
, info
->name
) < 0 ||
434 virAsprintf(&args
, "%s/nwfilterxml2firewalldata/%s-%s.args",
435 abs_srcdir
, info
->name
, RULESTYPE
) < 0)
438 result
= testCompareXMLToArgvFiles(xml
, args
);
447 hasNetfilterTools(void)
449 return virFileIsExecutable(IPTABLES_PATH
) &&
450 virFileIsExecutable(IP6TABLES_PATH
) &&
451 virFileIsExecutable(EBTABLES_PATH
);
460 # define DO_TEST(name) \
462 static struct testInfo info = { \
465 if (virTestRun("NWFilter XML-2-firewall " name, \
466 testCompareXMLToIPTablesHelper, &info) < 0) \
470 virFirewallSetLockOverride(true);
472 if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT
) < 0) {
473 if (!hasNetfilterTools()) {
474 fprintf(stderr
, "iptables/ip6tables/ebtables tools not present");
487 DO_TEST("conntrack");
490 DO_TEST("example-1");
491 DO_TEST("example-2");
493 DO_TEST("icmp-direction2");
494 DO_TEST("icmp-direction3");
495 DO_TEST("icmp-direction");
501 DO_TEST("ipt-no-macspoof");
509 DO_TEST("sctp-ipv6");
518 DO_TEST("udplite-ipv6");
522 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
525 VIR_TEST_MAIN(mymain
)
527 #else /* ! defined (__linux__) */
534 #endif /* ! defined (__linux__) */