5 * Copyright (C) 2013-2014 BMW Car IT GmbH.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "../src/connman.h"
31 static bool assert_rule(int type, const char *table_name, const char *rule)
33 char *cmd, *output, **lines;
34 GError **error = NULL;
40 cmd = g_strdup_printf(IPTABLES_SAVE " -t %s", table_name);
43 cmd = g_strdup_printf(IP6TABLES_SAVE " -t %s", table_name);
49 g_spawn_command_line_sync(cmd, &output, NULL, NULL, error);
52 lines = g_strsplit(output, "\n", 0);
57 for (i = 0; lines[i]; i++) {
58 DBG("lines[%02d]: %s\n", i, lines[i]);
59 if (g_strcmp0(lines[i], rule) == 0)
70 static void assert_rule_exists(int type, const char *table_name,
73 if (type == AF_INET) {
74 if (g_strcmp0(IPTABLES_SAVE, "") == 0) {
75 DBG("iptables-save is missing, no assertion possible");
80 if (type == AF_INET6) {
81 if (g_strcmp0(IP6TABLES_SAVE, "") == 0) {
82 DBG("ip6tables-save is missing, no assertion possible");
87 g_assert(assert_rule(type, table_name, rule));
90 static void assert_rule_not_exists(int type, const char *table_name,
93 if (type == AF_INET) {
94 if (g_strcmp0(IPTABLES_SAVE, "") == 0) {
95 DBG("iptables-save is missing, no assertion possible");
100 if (type == AF_INET6) {
101 if (g_strcmp0(IP6TABLES_SAVE, "") == 0) {
102 DBG("ip6tables-save is missing, no assertion possible");
107 g_assert(!assert_rule(type, table_name, rule));
110 static void test_iptables_chain0(void)
114 err = __connman_iptables_new_chain(AF_INET, "filter", "foo");
117 err = __connman_iptables_commit(AF_INET, "filter");
120 assert_rule_exists(AF_INET, "filter", ":foo - [0:0]");
122 err = __connman_iptables_delete_chain(AF_INET, "filter", "foo");
125 err = __connman_iptables_commit(AF_INET, "filter");
128 assert_rule_not_exists(AF_INET, "filter", ":foo - [0:0]");
131 static void test_iptables_chain1(void)
135 err = __connman_iptables_new_chain(AF_INET, "filter", "foo");
138 err = __connman_iptables_commit(AF_INET, "filter");
141 err = __connman_iptables_flush_chain(AF_INET, "filter", "foo");
144 err = __connman_iptables_commit(AF_INET, "filter");
147 err = __connman_iptables_delete_chain(AF_INET, "filter", "foo");
150 err = __connman_iptables_commit(AF_INET, "filter");
154 static void test_iptables_chain2(void)
158 err = __connman_iptables_change_policy(AF_INET, "filter", "INPUT", "DROP");
161 err = __connman_iptables_commit(AF_INET, "filter");
164 err = __connman_iptables_change_policy(AF_INET, "filter", "INPUT", "ACCEPT");
167 err = __connman_iptables_commit(AF_INET, "filter");
171 static void test_iptables_chain3(void)
175 err = __connman_iptables_new_chain(AF_INET, "filter", "user-chain-0");
178 err = __connman_iptables_commit(AF_INET, "filter");
181 assert_rule_exists(AF_INET, "filter", ":user-chain-0 - [0:0]");
183 err = __connman_iptables_new_chain(AF_INET, "filter", "user-chain-1");
186 err = __connman_iptables_commit(AF_INET, "filter");
189 assert_rule_exists(AF_INET, "filter", ":user-chain-0 - [0:0]");
190 assert_rule_exists(AF_INET, "filter", ":user-chain-1 - [0:0]");
192 err = __connman_iptables_delete_chain(AF_INET, "filter", "user-chain-1");
195 err = __connman_iptables_commit(AF_INET, "filter");
198 assert_rule_exists(AF_INET, "filter", ":user-chain-0 - [0:0]");
199 assert_rule_not_exists(AF_INET, "filter", ":user-chain-1 - [0:0]");
201 err = __connman_iptables_delete_chain(AF_INET, "filter", "user-chain-0");
204 err = __connman_iptables_commit(AF_INET, "filter");
207 assert_rule_not_exists(AF_INET, "filter", ":user-chain-0 - [0:0]");
210 static void test_iptables_rule0(void)
214 /* Test simple appending and removing a rule */
216 err = __connman_iptables_append(AF_INET, "filter", "INPUT",
217 "-m mark --mark 1 -j LOG");
220 err = __connman_iptables_commit(AF_INET, "filter");
223 assert_rule_exists(AF_INET, "filter",
224 "-A INPUT -m mark --mark 0x1 -j LOG");
226 err = __connman_iptables_delete(AF_INET, "filter", "INPUT",
227 "-m mark --mark 1 -j LOG");
230 err = __connman_iptables_commit(AF_INET, "filter");
233 assert_rule_not_exists(AF_INET, "filter",
234 "-A INPUT -m mark --mark 0x1 -j LOG");
237 static void test_iptables_rule1(void)
241 /* Test if we can do NAT stuff */
243 err = __connman_iptables_append(AF_INET, "nat", "POSTROUTING",
244 "-s 10.10.1.0/24 -o eth0 -j MASQUERADE");
246 err = __connman_iptables_commit(AF_INET, "nat");
249 assert_rule_exists(AF_INET, "nat",
250 "-A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE");
252 err = __connman_iptables_delete(AF_INET, "nat", "POSTROUTING",
253 "-s 10.10.1.0/24 -o eth0 -j MASQUERADE");
255 err = __connman_iptables_commit(AF_INET, "nat");
258 assert_rule_not_exists(AF_INET, "nat",
259 "-A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE");
262 static void test_iptables_rule2(void)
266 /* Test if the right rule is removed */
268 err = __connman_iptables_append(AF_INET, "filter", "INPUT",
269 "-m mark --mark 1 -j LOG");
272 err = __connman_iptables_commit(AF_INET, "filter");
275 assert_rule_exists(AF_INET, "filter",
276 "-A INPUT -m mark --mark 0x1 -j LOG");
278 err = __connman_iptables_append(AF_INET, "filter", "INPUT",
279 "-m mark --mark 2 -j LOG");
282 err = __connman_iptables_commit(AF_INET, "filter");
285 assert_rule_exists(AF_INET, "filter",
286 "-A INPUT -m mark --mark 0x1 -j LOG");
287 assert_rule_exists(AF_INET, "filter",
288 "-A INPUT -m mark --mark 0x2 -j LOG");
290 err = __connman_iptables_delete(AF_INET, "filter", "INPUT",
291 "-m mark --mark 2 -j LOG");
294 err = __connman_iptables_commit(AF_INET, "filter");
297 assert_rule_exists(AF_INET, "filter",
298 "-A INPUT -m mark --mark 0x1 -j LOG");
299 assert_rule_not_exists(AF_INET, "filter",
300 "-A INPUT -m mark --mark 0x2 -j LOG");
302 err = __connman_iptables_delete(AF_INET, "filter", "INPUT",
303 "-m mark --mark 1 -j LOG");
306 err = __connman_iptables_commit(AF_INET, "filter");
309 assert_rule_not_exists(AF_INET, "filter",
310 "-A INPUT -m mark --mark 0x1 -j LOG");
313 static void test_iptables_target0(void)
317 /* Test if 'fallthrough' targets work */
319 err = __connman_iptables_append(AF_INET, "filter", "INPUT",
323 err = __connman_iptables_append(AF_INET, "filter", "INPUT",
327 err = __connman_iptables_commit(AF_INET, "filter");
330 assert_rule_exists(AF_INET, "filter", "-A INPUT -m mark --mark 0x1");
331 assert_rule_exists(AF_INET, "filter", "-A INPUT -m mark --mark 0x2");
333 err = __connman_iptables_delete(AF_INET, "filter", "INPUT",
337 err = __connman_iptables_commit(AF_INET, "filter");
340 err = __connman_iptables_delete(AF_INET, "filter", "INPUT",
344 err = __connman_iptables_commit(AF_INET, "filter");
347 assert_rule_not_exists(AF_INET, "filter",
348 "-A INPUT -m mark --mark 0x1");
349 assert_rule_not_exists(AF_INET, "filter",
350 "-A INPUT -m mark --mark 0x2");
353 static void test_ip6tables_chain0(void)
357 err = __connman_iptables_new_chain(AF_INET6, "filter", "foo");
360 err = __connman_iptables_commit(AF_INET6, "filter");
363 assert_rule_exists(AF_INET6, "filter", ":foo - [0:0]");
365 err = __connman_iptables_delete_chain(AF_INET6, "filter", "foo");
368 err = __connman_iptables_commit(AF_INET6, "filter");
371 assert_rule_not_exists(AF_INET6, "filter", ":foo - [0:0]");
374 static void test_ip6tables_chain1(void)
378 err = __connman_iptables_new_chain(AF_INET6, "filter", "foo");
381 err = __connman_iptables_commit(AF_INET6, "filter");
384 err = __connman_iptables_flush_chain(AF_INET6, "filter", "foo");
387 err = __connman_iptables_commit(AF_INET6, "filter");
390 err = __connman_iptables_delete_chain(AF_INET6, "filter", "foo");
393 err = __connman_iptables_commit(AF_INET6, "filter");
397 static void test_ip6tables_chain2(void)
401 err = __connman_iptables_change_policy(AF_INET6, "filter", "INPUT",
405 err = __connman_iptables_commit(AF_INET6, "filter");
408 err = __connman_iptables_change_policy(AF_INET6, "filter", "INPUT",
412 err = __connman_iptables_commit(AF_INET6, "filter");
416 static void test_ip6tables_chain3(void)
420 err = __connman_iptables_new_chain(AF_INET6, "filter", "user-chain-0");
423 err = __connman_iptables_commit(AF_INET6, "filter");
426 assert_rule_exists(AF_INET6, "filter", ":user-chain-0 - [0:0]");
428 err = __connman_iptables_new_chain(AF_INET6, "filter", "user-chain-1");
431 err = __connman_iptables_commit(AF_INET6, "filter");
434 assert_rule_exists(AF_INET6, "filter", ":user-chain-0 - [0:0]");
435 assert_rule_exists(AF_INET6, "filter", ":user-chain-1 - [0:0]");
437 err = __connman_iptables_delete_chain(AF_INET6, "filter",
441 err = __connman_iptables_commit(AF_INET6, "filter");
444 assert_rule_exists(AF_INET6, "filter", ":user-chain-0 - [0:0]");
445 assert_rule_not_exists(AF_INET6, "filter", ":user-chain-1 - [0:0]");
447 err = __connman_iptables_delete_chain(AF_INET6, "filter",
451 err = __connman_iptables_commit(AF_INET6, "filter");
454 assert_rule_not_exists(AF_INET6, "filter", ":user-chain-0 - [0:0]");
457 static void test_ip6tables_rule0(void)
461 /* Test simple appending and removing a rule */
463 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
464 "-m mark --mark 1 -j LOG");
467 err = __connman_iptables_commit(AF_INET6, "filter");
470 assert_rule_exists(AF_INET6, "filter",
471 "-A INPUT -m mark --mark 0x1 -j LOG");
473 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
474 "-m mark --mark 1 -j LOG");
477 err = __connman_iptables_commit(AF_INET6, "filter");
480 assert_rule_not_exists(AF_INET6, "filter",
481 "-A INPUT -m mark --mark 0x1 -j LOG");
484 static void test_ip6tables_rule1(void)
488 /* Test if the right rule is removed */
490 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
491 "-m mark --mark 1 -j LOG");
494 err = __connman_iptables_commit(AF_INET6, "filter");
497 assert_rule_exists(AF_INET6, "filter",
498 "-A INPUT -m mark --mark 0x1 -j LOG");
500 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
501 "-m mark --mark 2 -j LOG");
504 err = __connman_iptables_commit(AF_INET6, "filter");
507 assert_rule_exists(AF_INET6, "filter",
508 "-A INPUT -m mark --mark 0x1 -j LOG");
509 assert_rule_exists(AF_INET6, "filter",
510 "-A INPUT -m mark --mark 0x2 -j LOG");
512 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
513 "-m mark --mark 2 -j LOG");
516 err = __connman_iptables_commit(AF_INET6, "filter");
519 assert_rule_exists(AF_INET6, "filter",
520 "-A INPUT -m mark --mark 0x1 -j LOG");
521 assert_rule_not_exists(AF_INET6, "filter",
522 "-A INPUT -m mark --mark 0x2 -j LOG");
524 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
525 "-m mark --mark 1 -j LOG");
528 err = __connman_iptables_commit(AF_INET6, "filter");
531 assert_rule_not_exists(AF_INET6, "filter",
532 "-A INPUT -m mark --mark 0x1 -j LOG");
535 static void test_ip6tables_rule2(void)
539 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
540 "-p icmpv6 -m icmpv6 "
541 "--icmpv6-type 128/0 -j DROP");
544 err = __connman_iptables_commit(AF_INET6, "filter");
548 assert_rule_exists(AF_INET6, "filter", "-A INPUT -p ipv6-icmp "
549 "-m icmp6 --icmpv6-type 128/0 -j DROP");
551 err = __connman_iptables_append(AF_INET6, "filter", "OUTPUT",
552 "-p icmpv6 -m icmpv6 "
553 "--icmpv6-type 129/0 -j DROP");
556 err = __connman_iptables_commit(AF_INET6, "filter");
560 assert_rule_exists(AF_INET6, "filter", "-A OUTPUT -p ipv6-icmp "
561 "-m icmp6 --icmpv6-type 129/0 -j DROP");
563 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
564 "-p icmpv6 -m icmpv6 "
565 "--icmpv6-type 128/0 -j DROP");
569 err = __connman_iptables_delete(AF_INET6, "filter", "OUTPUT",
570 "-p icmpv6 -m icmpv6 "
571 "--icmpv6-type 129/0 -j DROP");
575 err = __connman_iptables_commit(AF_INET6, "filter");
581 static void test_ip6tables_target0(void)
585 /* Test if 'fallthrough' targets work */
587 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
591 err = __connman_iptables_append(AF_INET6, "filter", "INPUT",
595 err = __connman_iptables_commit(AF_INET6, "filter");
598 assert_rule_exists(AF_INET6, "filter", "-A INPUT -m mark --mark 0x1");
599 assert_rule_exists(AF_INET6, "filter", "-A INPUT -m mark --mark 0x2");
601 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
605 err = __connman_iptables_commit(AF_INET6, "filter");
608 err = __connman_iptables_delete(AF_INET6, "filter", "INPUT",
612 err = __connman_iptables_commit(AF_INET6, "filter");
615 assert_rule_not_exists(AF_INET6, "filter", "-A INPUT "
616 "-m mark --mark 0x1");
617 assert_rule_not_exists(AF_INET6, "filter", "-A INPUT "
618 "-m mark --mark 0x2");
621 const struct connman_notifier *nat_notifier;
623 struct connman_service {
627 char *connman_service_get_interface(struct connman_service *service)
632 int connman_notifier_register(const struct connman_notifier *notifier)
634 nat_notifier = notifier;
639 void connman_notifier_unregister(const struct connman_notifier *notifier)
644 static void test_nat_basic0(void)
648 err = __connman_nat_enable("bridge", "192.168.2.1", 24);
651 /* test that table is empty */
652 err = __connman_iptables_append(AF_INET, "nat", "POSTROUTING",
653 "-s 192.168.2.1/24 -o eth0 -j MASQUERADE");
656 err = __connman_iptables_commit(AF_INET, "nat");
659 assert_rule_exists(AF_INET, "nat",
660 "-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE");
662 err = __connman_iptables_delete(AF_INET, "nat", "POSTROUTING",
663 "-s 192.168.2.1/24 -o eth0 -j MASQUERADE");
666 err = __connman_iptables_commit(AF_INET, "nat");
669 assert_rule_not_exists(AF_INET, "nat",
670 "-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE");
672 __connman_nat_disable("bridge");
675 static void test_nat_basic1(void)
677 struct connman_service *service;
680 service = g_try_new0(struct connman_service, 1);
683 nat_notifier->default_changed(service);
685 err = __connman_nat_enable("bridge", "192.168.2.1", 24);
688 /* test that table is not empty */
689 err = __connman_iptables_append(AF_INET, "nat", "POSTROUTING",
690 "-s 192.168.2.1/24 -o eth0 -j MASQUERADE");
693 err = __connman_iptables_commit(AF_INET, "nat");
696 __connman_nat_disable("bridge");
698 /* test that table is empty again */
699 err = __connman_iptables_delete(AF_INET, "nat", "POSTROUTING",
700 "-s 192.168.2.1/24 -o eth0 -j MASQUERADE");
703 err = __connman_iptables_commit(AF_INET, "nat");
709 static gchar *option_debug = NULL;
711 static bool parse_debug(const char *key, const char *value,
712 gpointer user_data, GError **error)
715 option_debug = g_strdup(value);
717 option_debug = g_strdup("*");
722 static GOptionEntry options[] = {
723 { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG,
724 G_OPTION_ARG_CALLBACK, parse_debug,
725 "Specify debug options to enable", "DEBUG" },
729 int main(int argc, char *argv[])
731 GOptionContext *context;
732 GError *error = NULL;
735 g_test_init(&argc, &argv, NULL);
737 context = g_option_context_new(NULL);
738 g_option_context_add_main_entries(context, options, NULL);
740 if (!g_option_context_parse(context, &argc, &argv, &error)) {
742 g_printerr("%s\n", error->message);
745 g_printerr("An unknown error occurred\n");
749 g_option_context_free(context);
751 __connman_log_init(argv[0], option_debug, false, false,
752 "Unit Tests Connection Manager", VERSION);
754 __connman_iptables_init();
755 __connman_nat_init();
757 g_test_add_func("/iptables/chain0", test_iptables_chain0);
758 g_test_add_func("/iptables/chain1", test_iptables_chain1);
759 g_test_add_func("/iptables/chain2", test_iptables_chain2);
760 g_test_add_func("/iptables/chain3", test_iptables_chain3);
761 g_test_add_func("/iptables/rule0", test_iptables_rule0);
762 g_test_add_func("/iptables/rule1", test_iptables_rule1);
763 g_test_add_func("/iptables/rule2", test_iptables_rule2);
764 g_test_add_func("/iptables/target0", test_iptables_target0);
765 g_test_add_func("/ip6tables/chain0", test_ip6tables_chain0);
766 g_test_add_func("/ip6tables/chain1", test_ip6tables_chain1);
767 g_test_add_func("/ip6tables/chain2", test_ip6tables_chain2);
768 g_test_add_func("/ip6tables/chain3", test_ip6tables_chain3);
769 g_test_add_func("/ip6tables/rule0", test_ip6tables_rule0);
770 g_test_add_func("/ip6tables/rule1", test_ip6tables_rule1);
771 g_test_add_func("/ip6tables/rule2", test_ip6tables_rule2);
772 g_test_add_func("/ip6tables/target0", test_ip6tables_target0);
773 g_test_add_func("/nat/basic0", test_nat_basic0);
774 g_test_add_func("/nat/basic1", test_nat_basic1);
778 __connman_nat_cleanup();
779 __connman_iptables_cleanup();
781 g_free(option_debug);