tests: Use the new DO_TEST_CAPS_*() macros
[libvirt/ericb.git] / tests / nwfilterxml2firewalltest.c
blobbea267f0fc76f557b7117fad5db7cdc7f909a966
1 /*
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/>.
22 #include <config.h>
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
38 # ifdef __linux__
39 # define RULESTYPE "linux"
40 # else
41 # error "test case not ported to this platform"
42 # endif
44 typedef struct _virNWFilterInst virNWFilterInst;
45 typedef virNWFilterInst *virNWFilterInstPtr;
46 struct _virNWFilterInst {
47 virNWFilterDefPtr *filters;
48 size_t nfilters;
49 virNWFilterRuleInstPtr *rules;
50 size_t nrules;
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);
153 if (!res)
154 return NULL;
156 if (virNWFilterHashTablePutAll(vars1, res) < 0)
157 goto err_exit;
159 if (virNWFilterHashTablePutAll(vars2, res) < 0)
160 goto err_exit;
162 return res;
164 err_exit:
165 virHashFree(res);
166 return NULL;
170 static void
171 virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst)
173 if (!inst)
174 return;
176 virHashFree(inst->vars);
177 VIR_FREE(inst);
181 static void
182 virNWFilterInstReset(virNWFilterInstPtr inst)
184 size_t i;
186 for (i = 0; i < inst->nfilters; i++)
187 virNWFilterDefFree(inst->filters[i]);
188 VIR_FREE(inst->filters);
189 inst->nfilters = 0;
191 for (i = 0; i < inst->nrules; i++)
192 virNWFilterRuleInstFree(inst->rules[i]);
193 VIR_FREE(inst->rules);
194 inst->nrules = 0;
198 static int
199 virNWFilterDefToInst(const char *xml,
200 virHashTablePtr vars,
201 virNWFilterInstPtr inst);
203 static int
204 virNWFilterRuleDefToRuleInst(virNWFilterDefPtr def,
205 virNWFilterRuleDefPtr rule,
206 virHashTablePtr vars,
207 virNWFilterInstPtr inst)
209 virNWFilterRuleInstPtr ruleinst;
210 int ret = -1;
212 if (VIR_ALLOC(ruleinst) < 0)
213 goto cleanup;
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)))
220 goto cleanup;
221 if (virNWFilterHashTablePutAll(vars, ruleinst->vars) < 0)
222 goto cleanup;
224 if (VIR_APPEND_ELEMENT(inst->rules,
225 inst->nrules,
226 ruleinst) < 0)
227 goto cleanup;
228 ruleinst = NULL;
230 ret = 0;
231 cleanup:
232 virNWFilterRuleInstFree(ruleinst);
233 return ret;
237 static int
238 virNWFilterIncludeDefToRuleInst(virNWFilterIncludeDefPtr inc,
239 virHashTablePtr vars,
240 virNWFilterInstPtr inst)
242 virHashTablePtr tmpvars = NULL;
243 int ret = -1;
244 char *xml;
246 if (virAsprintf(&xml, "%s/nwfilterxml2firewalldata/%s.xml",
247 abs_srcdir, inc->filterref) < 0)
248 return -1;
250 /* create a temporary hashmap for depth-first tree traversal */
251 if (!(tmpvars = virNWFilterCreateVarsFrom(inc->params,
252 vars)))
253 goto cleanup;
255 if (virNWFilterDefToInst(xml,
256 tmpvars,
257 inst) < 0)
258 goto cleanup;
260 ret = 0;
261 cleanup:
262 if (ret < 0)
263 virNWFilterInstReset(inst);
264 virHashFree(tmpvars);
265 VIR_FREE(xml);
266 return ret;
269 static int
270 virNWFilterDefToInst(const char *xml,
271 virHashTablePtr vars,
272 virNWFilterInstPtr inst)
274 size_t i;
275 int ret = -1;
276 virNWFilterDefPtr def = virNWFilterDefParseFile(xml);
278 if (!def)
279 return -1;
281 if (VIR_APPEND_ELEMENT_COPY(inst->filters,
282 inst->nfilters,
283 def) < 0) {
284 virNWFilterDefFree(def);
285 goto cleanup;
288 for (i = 0; i < def->nentries; i++) {
289 if (def->filterEntries[i]->rule) {
290 if (virNWFilterRuleDefToRuleInst(def,
291 def->filterEntries[i]->rule,
292 vars,
293 inst) < 0)
294 goto cleanup;
295 } else if (def->filterEntries[i]->include) {
296 if (virNWFilterIncludeDefToRuleInst(def->filterEntries[i]->include,
297 vars,
298 inst) < 0)
299 goto cleanup;
303 ret = 0;
304 cleanup:
305 if (ret < 0)
306 virNWFilterInstReset(inst);
307 return ret;
311 static void testRemoveCommonRules(char *rules)
313 size_t i;
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]);
319 if (tmp) {
320 memmove(tmp, tmp + len, (strlen(tmp) + 1) - len);
321 offset = tmp;
327 static int testSetOneParameter(virHashTablePtr vars,
328 const char *name,
329 const char *value)
331 int ret = -1;
332 virNWFilterVarValuePtr val;
334 if ((val = virHashLookup(vars, name)) == NULL) {
335 val = virNWFilterVarValueCreateSimpleCopyValue(value);
336 if (!val)
337 goto cleanup;
338 if (virHashUpdateEntry(vars, name, val) < 0) {
339 virNWFilterVarValueFree(val);
340 goto cleanup;
342 } else {
343 if (virNWFilterVarValueAddValueCopy(val, value) < 0)
344 goto cleanup;
346 ret = 0;
347 cleanup:
348 return ret;
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"))
366 return -1;
367 return 0;
370 static int testCompareXMLToArgvFiles(const char *xml,
371 const char *cmdline)
373 char *actualargv = NULL;
374 virBuffer buf = VIR_BUFFER_INITIALIZER;
375 virHashTablePtr vars = virNWFilterHashTableCreate(0);
376 virNWFilterInst inst;
377 int ret = -1;
379 memset(&inst, 0, sizeof(inst));
381 virCommandSetDryRun(&buf, NULL, NULL);
383 if (!vars)
384 goto cleanup;
386 if (testSetDefaultParameters(vars) < 0)
387 goto cleanup;
389 if (virNWFilterDefToInst(xml,
390 vars,
391 &inst) < 0)
392 goto cleanup;
394 if (ebiptables_driver.applyNewRules("vnet0", inst.rules, inst.nrules) < 0)
395 goto cleanup;
397 if (virBufferError(&buf))
398 goto cleanup;
400 actualargv = virBufferContentAndReset(&buf);
401 virTestClearCommandPath(actualargv);
402 virCommandSetDryRun(NULL, NULL, NULL);
404 testRemoveCommonRules(actualargv);
406 if (virTestCompareToFile(actualargv, cmdline) < 0)
407 goto cleanup;
409 ret = 0;
411 cleanup:
412 virBufferFreeAndReset(&buf);
413 VIR_FREE(actualargv);
414 virNWFilterInstReset(&inst);
415 virHashFree(vars);
416 return ret;
419 struct testInfo {
420 const char *name;
424 static int
425 testCompareXMLToIPTablesHelper(const void *data)
427 int result = -1;
428 const struct testInfo *info = data;
429 char *xml = NULL;
430 char *args = NULL;
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)
436 goto cleanup;
438 result = testCompareXMLToArgvFiles(xml, args);
440 cleanup:
441 VIR_FREE(xml);
442 VIR_FREE(args);
443 return result;
446 static bool
447 hasNetfilterTools(void)
449 return virFileIsExecutable(IPTABLES_PATH) &&
450 virFileIsExecutable(IP6TABLES_PATH) &&
451 virFileIsExecutable(EBTABLES_PATH);
455 static int
456 mymain(void)
458 int ret = 0;
460 # define DO_TEST(name) \
461 do { \
462 static struct testInfo info = { \
463 name, \
464 }; \
465 if (virTestRun("NWFilter XML-2-firewall " name, \
466 testCompareXMLToIPTablesHelper, &info) < 0) \
467 ret = -1; \
468 } while (0)
470 virFirewallSetLockOverride(true);
472 if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) {
473 if (!hasNetfilterTools()) {
474 fprintf(stderr, "iptables/ip6tables/ebtables tools not present");
475 return EXIT_AM_SKIP;
477 ret = -1;
478 goto cleanup;
481 DO_TEST("ah");
482 DO_TEST("ah-ipv6");
483 DO_TEST("all");
484 DO_TEST("all-ipv6");
485 DO_TEST("arp");
486 DO_TEST("comment");
487 DO_TEST("conntrack");
488 DO_TEST("esp");
489 DO_TEST("esp-ipv6");
490 DO_TEST("example-1");
491 DO_TEST("example-2");
492 DO_TEST("hex-data");
493 DO_TEST("icmp-direction2");
494 DO_TEST("icmp-direction3");
495 DO_TEST("icmp-direction");
496 DO_TEST("icmp");
497 DO_TEST("icmpv6");
498 DO_TEST("igmp");
499 DO_TEST("ip");
500 DO_TEST("ipset");
501 DO_TEST("ipt-no-macspoof");
502 DO_TEST("ipv6");
503 DO_TEST("iter1");
504 DO_TEST("iter2");
505 DO_TEST("iter3");
506 DO_TEST("mac");
507 DO_TEST("rarp");
508 DO_TEST("sctp");
509 DO_TEST("sctp-ipv6");
510 DO_TEST("stp");
511 DO_TEST("target2");
512 DO_TEST("target");
513 DO_TEST("tcp");
514 DO_TEST("tcp-ipv6");
515 DO_TEST("udp");
516 DO_TEST("udp-ipv6");
517 DO_TEST("udplite");
518 DO_TEST("udplite-ipv6");
519 DO_TEST("vlan");
521 cleanup:
522 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
525 VIR_TEST_MAIN(mymain)
527 #else /* ! defined (__linux__) */
529 int main(void)
531 return EXIT_AM_SKIP;
534 #endif /* ! defined (__linux__) */