| /* |
| * |
| * Connection Manager |
| * |
| * Copyright (C) 2013-2014 BMW Car IT GmbH. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <glib.h> |
| |
| #include "../src/connman.h" |
| |
| static bool assert_rule(const char *table_name, const char *rule) |
| { |
| char *cmd, *output, **lines; |
| GError **error = NULL; |
| int i; |
| |
| cmd = g_strdup_printf(IPTABLES_SAVE " -t %s", table_name); |
| g_spawn_command_line_sync(cmd, &output, NULL, NULL, error); |
| g_free(cmd); |
| |
| lines = g_strsplit(output, "\n", 0); |
| g_free(output); |
| |
| for (i = 0; lines[i]; i++) { |
| DBG("lines[%02d]: %s\n", i, lines[i]); |
| if (g_strcmp0(lines[i], rule) == 0) |
| break; |
| } |
| g_strfreev(lines); |
| |
| if (!lines[i]) |
| return false; |
| |
| return true; |
| } |
| |
| static void assert_rule_exists(const char *table_name, const char *rule) |
| { |
| if (g_strcmp0(IPTABLES_SAVE, "") == 0) { |
| DBG("iptables-save is missing, no assertion possible"); |
| return; |
| } |
| |
| g_assert(assert_rule(table_name, rule)); |
| } |
| |
| static void assert_rule_not_exists(const char *table_name, const char *rule) |
| { |
| if (g_strcmp0(IPTABLES_SAVE, "") == 0) { |
| DBG("iptables-save is missing, no assertion possible"); |
| return; |
| } |
| |
| g_assert(!assert_rule(table_name, rule)); |
| } |
| |
| static void test_iptables_chain0(void) |
| { |
| int err; |
| |
| err = __connman_iptables_new_chain("filter", "foo"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", ":foo - [0:0]"); |
| |
| err = __connman_iptables_delete_chain("filter", "foo"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", ":foo - [0:0]"); |
| } |
| |
| static void test_iptables_chain1(void) |
| { |
| int err; |
| |
| err = __connman_iptables_new_chain("filter", "foo"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_flush_chain("filter", "foo"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_delete_chain("filter", "foo"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| } |
| |
| static void test_iptables_chain2(void) |
| { |
| int err; |
| |
| err = __connman_iptables_change_policy("filter", "INPUT", "DROP"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_change_policy("filter", "INPUT", "ACCEPT"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| } |
| |
| static void test_iptables_chain3(void) |
| { |
| int err; |
| |
| err = __connman_iptables_new_chain("filter", "user-chain-0"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", ":user-chain-0 - [0:0]"); |
| |
| err = __connman_iptables_new_chain("filter", "user-chain-1"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", ":user-chain-0 - [0:0]"); |
| assert_rule_exists("filter", ":user-chain-1 - [0:0]"); |
| |
| err = __connman_iptables_delete_chain("filter", "user-chain-1"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", ":user-chain-0 - [0:0]"); |
| assert_rule_not_exists("filter", ":user-chain-1 - [0:0]"); |
| |
| err = __connman_iptables_delete_chain("filter", "user-chain-0"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", ":user-chain-0 - [0:0]"); |
| } |
| |
| static void test_iptables_rule0(void) |
| { |
| int err; |
| |
| /* Test simple appending and removing a rule */ |
| |
| err = __connman_iptables_append("filter", "INPUT", |
| "-m mark --mark 1 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| |
| err = __connman_iptables_delete("filter", "INPUT", |
| "-m mark --mark 1 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| } |
| |
| static void test_iptables_rule1(void) |
| { |
| int err; |
| |
| /* Test if we can do NAT stuff */ |
| |
| err = __connman_iptables_append("nat", "POSTROUTING", |
| "-s 10.10.1.0/24 -o eth0 -j MASQUERADE"); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("nat", |
| "-A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE"); |
| |
| err = __connman_iptables_delete("nat", "POSTROUTING", |
| "-s 10.10.1.0/24 -o eth0 -j MASQUERADE"); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("nat", |
| "-A POSTROUTING -s 10.10.1.0/24 -o eth0 -j MASQUERADE"); |
| } |
| |
| static void test_iptables_rule2(void) |
| { |
| int err; |
| |
| /* Test if the right rule is removed */ |
| |
| err = __connman_iptables_append("filter", "INPUT", |
| "-m mark --mark 1 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| |
| err = __connman_iptables_append("filter", "INPUT", |
| "-m mark --mark 2 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| assert_rule_exists("filter", |
| "-A INPUT -m mark --mark 0x2 -j LOG"); |
| |
| err = __connman_iptables_delete("filter", "INPUT", |
| "-m mark --mark 2 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| assert_rule_not_exists("filter", |
| "-A INPUT -m mark --mark 0x2 -j LOG"); |
| |
| err = __connman_iptables_delete("filter", "INPUT", |
| "-m mark --mark 1 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", |
| "-A INPUT -m mark --mark 0x1 -j LOG"); |
| } |
| |
| static void test_iptables_target0(void) |
| { |
| int err; |
| |
| /* Test if 'fallthrough' targets work */ |
| |
| err = __connman_iptables_append("filter", "INPUT", |
| "-m mark --mark 1"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_append("filter", "INPUT", |
| "-m mark --mark 2"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", "-A INPUT -m mark --mark 0x1"); |
| assert_rule_exists("filter", "-A INPUT -m mark --mark 0x2"); |
| |
| err = __connman_iptables_delete("filter", "INPUT", |
| "-m mark --mark 1"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_delete("filter", "INPUT", |
| "-m mark --mark 2"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("filter"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", "-A INPUT -m mark --mark 0x1"); |
| assert_rule_not_exists("filter", "-A INPUT -m mark --mark 0x2"); |
| } |
| |
| struct connman_notifier *nat_notifier; |
| |
| struct connman_service { |
| char *dummy; |
| }; |
| |
| char *connman_service_get_interface(struct connman_service *service) |
| { |
| return "eth0"; |
| } |
| |
| int connman_notifier_register(struct connman_notifier *notifier) |
| { |
| nat_notifier = notifier; |
| |
| return 0; |
| } |
| |
| void connman_notifier_unregister(struct connman_notifier *notifier) |
| { |
| nat_notifier = NULL; |
| } |
| |
| static void test_nat_basic0(void) |
| { |
| int err; |
| |
| err = __connman_nat_enable("bridge", "192.168.2.1", 24); |
| g_assert(err == 0); |
| |
| /* test that table is empty */ |
| err = __connman_iptables_append("nat", "POSTROUTING", |
| "-s 192.168.2.1/24 -o eth0 -j MASQUERADE"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| assert_rule_exists("nat", |
| "-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE"); |
| |
| err = __connman_iptables_delete("nat", "POSTROUTING", |
| "-s 192.168.2.1/24 -o eth0 -j MASQUERADE"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("nat", |
| "-A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE"); |
| |
| __connman_nat_disable("bridge"); |
| } |
| |
| static void test_nat_basic1(void) |
| { |
| struct connman_service *service; |
| int err; |
| |
| service = g_try_new0(struct connman_service, 1); |
| g_assert(service); |
| |
| nat_notifier->default_changed(service); |
| |
| err = __connman_nat_enable("bridge", "192.168.2.1", 24); |
| g_assert(err == 0); |
| |
| /* test that table is not empty */ |
| err = __connman_iptables_append("nat", "POSTROUTING", |
| "-s 192.168.2.1/24 -o eth0 -j MASQUERADE"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| __connman_nat_disable("bridge"); |
| |
| /* test that table is empty again */ |
| err = __connman_iptables_delete("nat", "POSTROUTING", |
| "-s 192.168.2.1/24 -o eth0 -j MASQUERADE"); |
| g_assert(err == 0); |
| |
| err = __connman_iptables_commit("nat"); |
| g_assert(err == 0); |
| |
| g_free(service); |
| } |
| |
| static void test_firewall_basic0(void) |
| { |
| struct firewall_context *ctx; |
| int err; |
| |
| ctx = __connman_firewall_create(); |
| g_assert(ctx); |
| |
| err = __connman_firewall_add_rule(ctx, "filter", "INPUT", |
| "-m mark --mark 999 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_enable(ctx); |
| g_assert(err == 0); |
| |
| assert_rule_exists("filter", ":connman-INPUT - [0:0]"); |
| assert_rule_exists("filter", "-A INPUT -j connman-INPUT"); |
| assert_rule_exists("filter", "-A connman-INPUT -m mark --mark 0x3e7 -j LOG"); |
| |
| err = __connman_firewall_disable(ctx); |
| g_assert(err == 0); |
| |
| assert_rule_not_exists("filter", ":connman-INPUT - [0:0]"); |
| assert_rule_not_exists("filter", "-A INPUT -j connman-INPUT"); |
| assert_rule_not_exists("filter", "-A connman-INPUT -m mark --mark 0x3e7 -j LOG"); |
| |
| __connman_firewall_destroy(ctx); |
| } |
| |
| static void test_firewall_basic1(void) |
| { |
| struct firewall_context *ctx; |
| int err; |
| |
| ctx = __connman_firewall_create(); |
| g_assert(ctx); |
| |
| err = __connman_firewall_add_rule(ctx, "filter", "INPUT", |
| "-m mark --mark 999 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_add_rule(ctx, "filter", "OUTPUT", |
| "-m mark --mark 999 -j LOG"); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_enable(ctx); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_disable(ctx); |
| g_assert(err == 0); |
| |
| __connman_firewall_destroy(ctx); |
| } |
| |
| static void test_firewall_basic2(void) |
| { |
| struct firewall_context *ctx; |
| int err; |
| |
| ctx = __connman_firewall_create(); |
| g_assert(ctx); |
| |
| err = __connman_firewall_add_rule(ctx, "mangle", "INPUT", |
| "-j CONNMARK --restore-mark"); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_add_rule(ctx, "mangle", "POSTROUTING", |
| "-j CONNMARK --save-mark"); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_enable(ctx); |
| g_assert(err == 0); |
| |
| err = __connman_firewall_disable(ctx); |
| g_assert(err == 0); |
| |
| __connman_firewall_destroy(ctx); |
| } |
| |
| static gchar *option_debug = NULL; |
| |
| static bool parse_debug(const char *key, const char *value, |
| gpointer user_data, GError **error) |
| { |
| if (value) |
| option_debug = g_strdup(value); |
| else |
| option_debug = g_strdup("*"); |
| |
| return true; |
| } |
| |
| static GOptionEntry options[] = { |
| { "debug", 'd', G_OPTION_FLAG_OPTIONAL_ARG, |
| G_OPTION_ARG_CALLBACK, parse_debug, |
| "Specify debug options to enable", "DEBUG" }, |
| { NULL }, |
| }; |
| |
| int main(int argc, char *argv[]) |
| { |
| GOptionContext *context; |
| GError *error = NULL; |
| int err; |
| |
| g_test_init(&argc, &argv, NULL); |
| |
| context = g_option_context_new(NULL); |
| g_option_context_add_main_entries(context, options, NULL); |
| |
| if (!g_option_context_parse(context, &argc, &argv, &error)) { |
| if (error) { |
| g_printerr("%s\n", error->message); |
| g_error_free(error); |
| } else |
| g_printerr("An unknown error occurred\n"); |
| return 1; |
| } |
| |
| g_option_context_free(context); |
| |
| __connman_log_init(argv[0], option_debug, false, false, |
| "Unit Tests Connection Manager", VERSION); |
| |
| __connman_iptables_init(); |
| __connman_firewall_init(); |
| __connman_nat_init(); |
| |
| g_test_add_func("/iptables/chain0", test_iptables_chain0); |
| g_test_add_func("/iptables/chain1", test_iptables_chain1); |
| g_test_add_func("/iptables/chain2", test_iptables_chain2); |
| g_test_add_func("/iptables/chain3", test_iptables_chain3); |
| g_test_add_func("/iptables/rule0", test_iptables_rule0); |
| g_test_add_func("/iptables/rule1", test_iptables_rule1); |
| g_test_add_func("/iptables/rule2", test_iptables_rule2); |
| g_test_add_func("/iptables/target0", test_iptables_target0); |
| g_test_add_func("/nat/basic0", test_nat_basic0); |
| g_test_add_func("/nat/basic1", test_nat_basic1); |
| g_test_add_func("/firewall/basic0", test_firewall_basic0); |
| g_test_add_func("/firewall/basic1", test_firewall_basic1); |
| g_test_add_func("/firewall/basic2", test_firewall_basic2); |
| |
| err = g_test_run(); |
| |
| __connman_nat_cleanup(); |
| __connman_firewall_cleanup(); |
| __connman_iptables_cleanup(); |
| |
| g_free(option_debug); |
| |
| return err; |
| } |