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 __VIR_FIREWALL_PRIV_H_ALLOW__
31 # include "virfirewallpriv.h"
33 # define __VIR_COMMAND_PRIV_H_ALLOW__
34 # include "vircommandpriv.h"
36 # define VIR_FROM_THIS VIR_FROM_NONE
38 static const char *abs_top_srcdir;
41 # define RULESTYPE "linux"
43 # error "test case not ported to this platform"
46 typedef struct _virNWFilterInst virNWFilterInst;
47 typedef virNWFilterInst *virNWFilterInstPtr;
48 struct _virNWFilterInst {
49 virNWFilterDefPtr *filters;
51 virNWFilterRuleInstPtr *rules;
56 * Some sets of rules that will be common to all test files,
57 * so we don't bother including them in the test data files
58 * as that would just bloat them
61 static const char *commonRules[] = {
62 /* Dropping ebtables rules */
63 "ebtables -t nat -D PREROUTING -i vnet0 -j libvirt-J-vnet0\n"
64 "ebtables -t nat -D POSTROUTING -o vnet0 -j libvirt-P-vnet0\n"
65 "ebtables -t nat -L libvirt-J-vnet0\n"
66 "ebtables -t nat -L libvirt-P-vnet0\n"
67 "ebtables -t nat -F libvirt-J-vnet0\n"
68 "ebtables -t nat -X libvirt-J-vnet0\n"
69 "ebtables -t nat -F libvirt-P-vnet0\n"
70 "ebtables -t nat -X libvirt-P-vnet0\n",
72 /* Creating ebtables chains */
73 "ebtables -t nat -N libvirt-J-vnet0\n"
74 "ebtables -t nat -N libvirt-P-vnet0\n",
76 /* Dropping iptables rules */
77 "iptables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
78 "iptables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n"
79 "iptables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
80 "iptables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
81 "iptables -F FP-vnet0\n"
82 "iptables -X FP-vnet0\n"
83 "iptables -F FJ-vnet0\n"
84 "iptables -X FJ-vnet0\n"
85 "iptables -F HJ-vnet0\n"
86 "iptables -X HJ-vnet0\n",
88 /* Creating iptables chains */
89 "iptables -N libvirt-in\n"
90 "iptables -N libvirt-out\n"
91 "iptables -N libvirt-in-post\n"
92 "iptables -N libvirt-host-in\n"
93 "iptables -D FORWARD -j libvirt-in\n"
94 "iptables -D FORWARD -j libvirt-out\n"
95 "iptables -D FORWARD -j libvirt-in-post\n"
96 "iptables -D INPUT -j libvirt-host-in\n"
97 "iptables -I FORWARD 1 -j libvirt-in\n"
98 "iptables -I FORWARD 2 -j libvirt-out\n"
99 "iptables -I FORWARD 3 -j libvirt-in-post\n"
100 "iptables -I INPUT 1 -j libvirt-host-in\n"
101 "iptables -N FP-vnet0\n"
102 "iptables -N FJ-vnet0\n"
103 "iptables -N HJ-vnet0\n"
104 "iptables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
105 "iptables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
106 "iptables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
107 "iptables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n"
108 "iptables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n",
110 /* Dropping ip6tables rules */
111 "ip6tables -D libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
112 "ip6tables -D libvirt-out -m physdev --physdev-out vnet0 -g FP-vnet0\n"
113 "ip6tables -D libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
114 "ip6tables -D libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
115 "ip6tables -F FP-vnet0\n"
116 "ip6tables -X FP-vnet0\n"
117 "ip6tables -F FJ-vnet0\n"
118 "ip6tables -X FJ-vnet0\n"
119 "ip6tables -F HJ-vnet0\n"
120 "ip6tables -X HJ-vnet0\n",
122 /* Creating ip6tables chains */
123 "ip6tables -N libvirt-in\n"
124 "ip6tables -N libvirt-out\n"
125 "ip6tables -N libvirt-in-post\n"
126 "ip6tables -N libvirt-host-in\n"
127 "ip6tables -D FORWARD -j libvirt-in\n"
128 "ip6tables -D FORWARD -j libvirt-out\n"
129 "ip6tables -D FORWARD -j libvirt-in-post\n"
130 "ip6tables -D INPUT -j libvirt-host-in\n"
131 "ip6tables -I FORWARD 1 -j libvirt-in\n"
132 "ip6tables -I FORWARD 2 -j libvirt-out\n"
133 "ip6tables -I FORWARD 3 -j libvirt-in-post\n"
134 "ip6tables -I INPUT 1 -j libvirt-host-in\n"
135 "ip6tables -N FP-vnet0\n"
136 "ip6tables -N FJ-vnet0\n"
137 "ip6tables -N HJ-vnet0\n"
138 "ip6tables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet0 -g FP-vnet0\n"
139 "ip6tables -A libvirt-in -m physdev --physdev-in vnet0 -g FJ-vnet0\n"
140 "ip6tables -A libvirt-host-in -m physdev --physdev-in vnet0 -g HJ-vnet0\n"
141 "ip6tables -D libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n"
142 "ip6tables -A libvirt-in-post -m physdev --physdev-in vnet0 -j ACCEPT\n",
144 /* Inserting ebtables rules */
145 "ebtables -t nat -A PREROUTING -i vnet0 -j libvirt-J-vnet0\n"
146 "ebtables -t nat -A POSTROUTING -o vnet0 -j libvirt-P-vnet0\n",
150 static virNWFilterHashTablePtr
151 virNWFilterCreateVarsFrom(virNWFilterHashTablePtr vars1,
152 virNWFilterHashTablePtr vars2)
154 virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0);
158 if (virNWFilterHashTablePutAll(vars1, res) < 0)
161 if (virNWFilterHashTablePutAll(vars2, res) < 0)
167 virNWFilterHashTableFree(res);
173 virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst)
178 virNWFilterHashTableFree(inst->vars);
184 virNWFilterInstReset(virNWFilterInstPtr inst)
188 for (i = 0; i < inst->nfilters; i++)
189 virNWFilterDefFree(inst->filters[i]);
190 VIR_FREE(inst->filters);
193 for (i = 0; i < inst->nrules; i++)
194 virNWFilterRuleInstFree(inst->rules[i]);
195 VIR_FREE(inst->rules);
201 virNWFilterDefToInst(const char *xml,
202 virNWFilterHashTablePtr vars,
203 virNWFilterInstPtr inst);
206 virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def,
207 virNWFilterRuleDefPtr rule,
208 virNWFilterHashTablePtr vars,
209 virNWFilterInstPtr inst)
211 virNWFilterRuleInstPtr ruleinst;
214 if (VIR_ALLOC(ruleinst) < 0)
217 ruleinst->chainSuffix = def->chainsuffix;
218 ruleinst->chainPriority = def->chainPriority;
219 ruleinst->def = rule;
220 ruleinst->priority = rule->priority;
221 if (!(ruleinst->vars = virNWFilterHashTableCreate(0)))
223 if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0)
226 if (VIR_APPEND_ELEMENT(inst->rules,
234 virNWFilterRuleInstFree(ruleinst);
240 virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc,
241 virNWFilterHashTablePtr vars,
242 virNWFilterInstPtr inst)
244 virNWFilterHashTablePtr tmpvars = NULL;
248 if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml",
249 abs_srcdir, inc->filterref) < 0)
252 /* create a temporary hashmap for depth-first tree traversal */
253 if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params,
257 if (virNWFilterDefToInst(xml,
265 virNWFilterInstReset(inst);
266 virNWFilterHashTableFree(tmpvars);
272 virNWFilterDefToInst(const char *xml,
273 virNWFilterHashTablePtr vars,
274 virNWFilterInstPtr inst)
278 virNWFilterDefPtr def = virNWFilterDefParseFile(xml);
283 if (VIR_APPEND_ELEMENT_COPY(inst->filters,
286 virNWFilterDefFree(def);
290 for (i = 0; i < def->nentries; i++) {
291 if (def->filterEntries[i]->rule) {
292 if (virNWFilterRuleDefToRuleInst(def,
293 def->filterEntries[i]->rule,
297 } else if (def->filterEntries[i]->include) {
298 if (virNWFilterIncludeDefToRuleInst(def->filterEntries[i]->include,
308 virNWFilterInstReset(inst);
313 static void testRemoveCommonRules(char *rules)
316 char *offset = rules;
318 for (i = 0; i < ARRAY_CARDINALITY(commonRules); i++) {
319 char *tmp = strstr(offset, commonRules[i]);
320 size_t len = strlen(commonRules[i]);
322 memmove(tmp, tmp + len, (strlen(tmp) + 1) - len);
329 static int testSetOneParameter(virNWFilterHashTablePtr vars,
334 virNWFilterVarValuePtr val;
336 if ((val = virHashLookup(vars->hashTable, name)) == NULL) {
337 val = virNWFilterVarValueCreateSimpleCopyValue(value);
340 if (virNWFilterHashTablePut(vars, name, val) < 0) {
341 virNWFilterVarValueFree(val);
345 if (virNWFilterVarValueAddValueCopy(val, value) < 0)
353 static int testSetDefaultParameters(virNWFilterHashTablePtr vars)
355 if (testSetOneParameter(vars, "IPSETNAME", "tck_test") < 0 ||
356 testSetOneParameter(vars, "A", "1.1.1.1") ||
357 testSetOneParameter(vars, "A", "2.2.2.2") ||
358 testSetOneParameter(vars, "A", "3.3.3.3") ||
359 testSetOneParameter(vars, "A", "3.3.3.3") ||
360 testSetOneParameter(vars, "B", "80") ||
361 testSetOneParameter(vars, "B", "90") ||
362 testSetOneParameter(vars, "B", "80") ||
363 testSetOneParameter(vars, "B", "80") ||
364 testSetOneParameter(vars, "C", "1080") ||
365 testSetOneParameter(vars, "C", "1090") ||
366 testSetOneParameter(vars, "C", "1100") ||
367 testSetOneParameter(vars, "C", "1110"))
372 static int testCompareXMLToArgvFiles(const char *xml,
375 char *expectargv = NULL;
377 char *actualargv = NULL;
378 virBuffer buf = VIR_BUFFER_INITIALIZER;
379 virNWFilterHashTablePtr vars = virNWFilterHashTableCreate(0);
380 virNWFilterInst inst;
383 memset(&inst, 0, sizeof(inst));
385 virCommandSetDryRun(&buf, NULL, NULL);
390 if (testSetDefaultParameters(vars) < 0)
393 if (virNWFilterDefToInst(xml,
398 if (ebiptables_driver.applyNewRules("vnet0", inst.rules, inst.nrules) < 0)
401 if (virBufferError(&buf))
404 actualargv = virBufferContentAndReset(&buf);
405 virtTestClearCommandPath(actualargv);
406 virCommandSetDryRun(NULL, NULL, NULL);
408 testRemoveCommonRules(actualargv);
410 len = virtTestLoadFile(cmdline, &expectargv);
414 if (STRNEQ(expectargv, actualargv)) {
415 virtTestDifference(stderr, expectargv, actualargv);
422 virBufferFreeAndReset(&buf);
423 VIR_FREE(expectargv);
424 VIR_FREE(actualargv);
425 virNWFilterInstReset(&inst);
426 virNWFilterHashTableFree(vars);
436 testCompareXMLToIPTablesHelper(const void *data)
439 const struct testInfo *info = data;
443 if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml",
444 abs_srcdir, info->name) < 0 ||
445 virAsprintf(&args, "%s/nwfilterxml2firewalldata/%s-%s.args",
446 abs_srcdir, info->name, RULESTYPE) < 0)
449 result = testCompareXMLToArgvFiles(xml, args);
463 abs_top_srcdir = getenv("abs_top_srcdir");
465 abs_top_srcdir = abs_srcdir "/..";
467 # define DO_TEST(name) \
469 static struct testInfo info = { \
472 if (virtTestRun("NWFilter XML-2-firewall " name, \
473 testCompareXMLToIPTablesHelper, &info) < 0) \
477 if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) {
488 DO_TEST("conntrack");
491 DO_TEST("example-1");
492 DO_TEST("example-2");
494 DO_TEST("icmp-direction2");
495 DO_TEST("icmp-direction3");
496 DO_TEST("icmp-direction");
502 DO_TEST("ipt-no-macspoof");
510 DO_TEST("sctp-ipv6");
519 DO_TEST("udplite-ipv6");
523 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
526 VIRT_TEST_MAIN(mymain)
528 #else /* ! defined (__linux__) */
535 #endif /* ! defined (__linux__) */