1 /*
2  * networkxml2firewalltest.c: Test iptables rule generation
3  *
4  * Copyright (C) 2014 Red Hat, Inc.
5  *
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.
10  *
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.
15  *
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/>.
19  *
20  */
21 
22 #include <config.h>
23 
24 #include "testutils.h"
25 #include "viralloc.h"
26 
27 #if defined (__linux__)
28 
29 # include <gio/gio.h>
30 
31 # include "network/bridge_driver_platform.h"
32 # include "virbuffer.h"
33 # include "virmock.h"
34 
35 # define LIBVIRT_VIRFIREWALLPRIV_H_ALLOW
36 # include "virfirewallpriv.h"
37 
38 # define LIBVIRT_VIRCOMMANDPRIV_H_ALLOW
39 # include "vircommandpriv.h"
40 
41 # define VIR_FROM_THIS VIR_FROM_NONE
42 
43 # ifdef __linux__
44 #  define RULESTYPE "linux"
45 # else
46 #  error "test case not ported to this platform"
47 # endif
48 
VIR_MOCK_WRAP_RET_ARGS(g_dbus_connection_call_sync,GVariant *,GDBusConnection *,connection,const gchar *,bus_name,const gchar *,object_path,const gchar *,interface_name,const gchar *,method_name,GVariant *,parameters,const GVariantType *,reply_type,GDBusCallFlags,flags,gint,timeout_msec,GCancellable *,cancellable,GError **,error)49 VIR_MOCK_WRAP_RET_ARGS(g_dbus_connection_call_sync,
50                        GVariant *,
51                        GDBusConnection *, connection,
52                        const gchar *, bus_name,
53                        const gchar *, object_path,
54                        const gchar *, interface_name,
55                        const gchar *, method_name,
56                        GVariant *, parameters,
57                        const GVariantType *, reply_type,
58                        GDBusCallFlags, flags,
59                        gint, timeout_msec,
60                        GCancellable *, cancellable,
61                        GError **, error)
62 {
63     if (parameters) {
64         g_variant_ref_sink(parameters);
65         g_variant_unref(parameters);
66     }
67 
68     VIR_MOCK_REAL_INIT(g_dbus_connection_call_sync);
69 
70     *error = g_dbus_error_new_for_dbus_error("org.freedesktop.error",
71                                              "dbus is disabled");
72 
73     return NULL;
74 }
75 
76 static void
testCommandDryRun(const char * const * args G_GNUC_UNUSED,const char * const * env G_GNUC_UNUSED,const char * input G_GNUC_UNUSED,char ** output,char ** error,int * status,void * opaque G_GNUC_UNUSED)77 testCommandDryRun(const char *const*args G_GNUC_UNUSED,
78                   const char *const*env G_GNUC_UNUSED,
79                   const char *input G_GNUC_UNUSED,
80                   char **output,
81                   char **error,
82                   int *status,
83                   void *opaque G_GNUC_UNUSED)
84 {
85     *status = 0;
86     *output = g_strdup("");
87     *error = g_strdup("");
88 }
89 
testCompareXMLToArgvFiles(const char * xml,const char * cmdline,const char * baseargs)90 static int testCompareXMLToArgvFiles(const char *xml,
91                                      const char *cmdline,
92                                      const char *baseargs)
93 {
94     g_autofree char *actualargv = NULL;
95     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
96     virNetworkDef *def = NULL;
97     int ret = -1;
98     char *actual;
99     g_autoptr(virCommandDryRunToken) dryRunToken = virCommandDryRunTokenNew();
100 
101     virCommandSetDryRun(dryRunToken, &buf, true, true, testCommandDryRun, NULL);
102 
103     if (!(def = virNetworkDefParseFile(xml, NULL)))
104         goto cleanup;
105 
106     if (networkAddFirewallRules(def) < 0)
107         goto cleanup;
108 
109     actual = actualargv = virBufferContentAndReset(&buf);
110 
111     /* The first network to be created populates the
112      * libvirt global chains. We must skip args for
113      * that if present
114      */
115     if (STRPREFIX(actual, baseargs))
116         actual += strlen(baseargs);
117 
118     if (virTestCompareToFileFull(actual, cmdline, false) < 0)
119         goto cleanup;
120 
121     ret = 0;
122 
123  cleanup:
124     virNetworkDefFree(def);
125     return ret;
126 }
127 
128 struct testInfo {
129     const char *name;
130     const char *baseargs;
131 };
132 
133 
134 static int
testCompareXMLToIPTablesHelper(const void * data)135 testCompareXMLToIPTablesHelper(const void *data)
136 {
137     int result = -1;
138     const struct testInfo *info = data;
139     g_autofree char *xml = NULL;
140     g_autofree char *args = NULL;
141 
142     xml = g_strdup_printf("%s/networkxml2firewalldata/%s.xml",
143                           abs_srcdir, info->name);
144     args = g_strdup_printf("%s/networkxml2firewalldata/%s-%s.args",
145                            abs_srcdir, info->name, RULESTYPE);
146 
147     result = testCompareXMLToArgvFiles(xml, args, info->baseargs);
148 
149     return result;
150 }
151 
152 
153 static int
mymain(void)154 mymain(void)
155 {
156     int ret = 0;
157     g_autofree char *basefile = NULL;
158     g_autofree char *baseargs = NULL;
159 
160 # define DO_TEST(name) \
161     do { \
162         struct testInfo info = { \
163             name, baseargs, \
164         }; \
165         if (virTestRun("Network XML-2-iptables " name, \
166                        testCompareXMLToIPTablesHelper, &info) < 0) \
167             ret = -1; \
168     } while (0)
169 
170     if (virFirewallSetBackend(VIR_FIREWALL_BACKEND_DIRECT) < 0) {
171         return EXIT_FAILURE;
172     }
173 
174     basefile = g_strdup_printf("%s/networkxml2firewalldata/base.args", abs_srcdir);
175 
176     if (virFileReadAll(basefile, INT_MAX, &baseargs) < 0)
177         return EXIT_FAILURE;
178 
179     DO_TEST("nat-default");
180     DO_TEST("nat-tftp");
181     DO_TEST("nat-many-ips");
182     DO_TEST("nat-no-dhcp");
183     DO_TEST("nat-ipv6");
184     DO_TEST("nat-ipv6-masquerade");
185     DO_TEST("route-default");
186 
187     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
188 }
189 
190 VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virgdbus"),
191                       VIR_TEST_MOCK("virfirewall"))
192 
193 #else /* ! defined (__linux__) */
194 
195 int main(void)
196 {
197     return EXIT_AM_SKIP;
198 }
199 
200 #endif /* ! defined (__linux__) */
201