From: Daniel Wagner <[email protected]>

This helpers allow to add a bunch of iptables rules together into
a set and then apply them in a 'atomic' way. Unfortunatly, it is
not garanteed to be completely automic but way better then having
several places trying to get this right.
---
 Makefile.am   |   2 +-
 src/connman.h |  11 ++++
 src/iptctx.c  | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 203 insertions(+), 1 deletion(-)
 create mode 100644 src/iptctx.c

diff --git a/Makefile.am b/Makefile.am
index cd69b56..e9aa95a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -97,7 +97,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) 
$(gweb_sources) \
                        src/session.c src/tethering.c src/wpad.c src/wispr.c \
                        src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c \
                        src/ippool.c src/bridge.c src/nat.c src/ipaddress.c \
-                       src/inotify.c
+                       src/inotify.c src/iptctx.c
 
 src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \
                                @XTABLES_LIBS@ @GNUTLS_LIBS@ -lresolv -ldl -lrt
diff --git a/src/connman.h b/src/connman.h
index 6c3c22c..df24f1e 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -790,6 +790,17 @@ int __connman_stats_get(struct connman_service *service,
                                connman_bool_t roaming,
                                struct connman_stats_data *data);
 
+struct iptables_context;
+
+struct iptables_context *__connman_iptctx_create(void);
+void __connman_iptctx_destroy(struct iptables_context *ctx);
+int __connman_iptctx_add_rule(struct iptables_context *ctx,
+                               const char *table,
+                               const char *chain,
+                               const char *rule_fmt, ...);
+int __connman_iptctx_enable(struct iptables_context *ctx);
+int __connman_iptctx_disable(struct iptables_context *ctx);
+
 int __connman_iptables_new_chain(const char *table_name,
                                        const char *chain);
 int __connman_iptables_delete_chain(const char *table_name,
diff --git a/src/iptctx.c b/src/iptctx.c
new file mode 100644
index 0000000..903deb7
--- /dev/null
+++ b/src/iptctx.c
@@ -0,0 +1,191 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2013  BMW Car IT GmbH. All rights reserved.
+ *
+ *  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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+
+#include "connman.h"
+
+struct xt_rule {
+       char *table;
+       char *chain;
+       char *rule_spec;
+};
+
+struct iptables_context {
+       GList *rules;
+};
+
+static void cleanup_xt_rule(gpointer user_data)
+{
+       struct xt_rule *rule = user_data;
+
+       g_free(rule->rule_spec);
+       g_free(rule->chain);
+       g_free(rule->table);
+       g_free(rule);
+}
+
+struct iptables_context *__connman_iptctx_create(void)
+{
+       struct iptables_context *ctx;
+
+       ctx = g_try_new0(struct iptables_context, 1);
+       if (ctx == NULL)
+               return NULL;
+
+       return ctx;
+}
+
+void __connman_iptctx_destroy(struct iptables_context *ctx)
+{
+       g_list_free_full(ctx->rules, cleanup_xt_rule);
+       g_free(ctx);
+}
+
+int __connman_iptctx_add_rule(struct iptables_context *ctx,
+                               const char *table,
+                               const char *chain,
+                               const char *rule_fmt, ...)
+{
+       va_list args;
+       char *rule_spec;
+       struct xt_rule *rule;
+
+       va_start(args, rule_fmt);
+
+       rule_spec = g_strdup_vprintf(rule_fmt, args);
+
+       va_end(args);
+
+       if (rule_spec == NULL)
+               return -ENOMEM;
+
+       rule = g_try_new0(struct xt_rule, 1);
+       if (rule == NULL) {
+               g_free(rule_spec);
+               return -ENOMEM;
+       }
+
+       rule->table = g_strdup(table);
+       rule->chain = g_strdup(chain);
+       rule->rule_spec = rule_spec;
+
+       ctx->rules = g_list_append(ctx->rules, rule);
+
+       return 0;
+}
+
+int __connman_iptctx_enable(struct iptables_context *ctx)
+{
+       struct xt_rule *rule;
+       GList *list;
+       int err, err1;
+
+       for (list = g_list_first(ctx->rules); list != NULL;
+                       list = g_list_next(list)) {
+               rule = list->data;
+
+               DBG("%s %s %s", rule->table, rule->chain, rule->rule_spec);
+
+               err = __connman_iptables_managed_append(rule->table,
+                                       rule->chain,
+                                       rule->rule_spec);
+               if (err < 0)
+                       goto err;
+
+               err = __connman_iptables_commit(rule->table);
+               if (err < 0)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       connman_warn("Failed to install iptables rules: %s", strerror(-err));
+
+       for (list = g_list_previous(list); list != NULL;
+                       list = g_list_previous(list)) {
+               rule = list->data;
+
+               err1 = __connman_iptables_managed_delete(rule->table,
+                                               rule->chain,
+                                               rule->rule_spec);
+               if (err1 < 0) {
+                       /* Now what shall we do? */
+                       connman_error("Cannot remove previously installed "
+                               "iptables rules: %s", strerror(-err1));
+               }
+
+
+               err1 = __connman_iptables_commit(rule->table);
+               if (err1 < 0) {
+                       /* Now what shall we do? */
+                       connman_error("Cannot remove previously installed "
+                               "iptables rules: %s", strerror(-err1));
+               }
+       }
+
+       return err;
+}
+
+int __connman_iptctx_disable(struct iptables_context *ctx)
+{
+       struct xt_rule *rule;
+       GList *list;
+       int err = 0;
+
+       for (list = g_list_last(ctx->rules); list != NULL;
+                       list = g_list_previous(list)) {
+               rule = list->data;
+
+               DBG("%s %s %s", rule->table, rule->chain, rule->rule_spec);
+
+               err = __connman_iptables_managed_delete(rule->table,
+                                       rule->chain,
+                                       rule->rule_spec);
+               if (err < 0) {
+                       /* Now what shall we do? */
+                       connman_error("Cannot remove previously installed "
+                               "iptables rules: %s", strerror(-err));
+                       break;
+               }
+
+
+               err = __connman_iptables_commit(rule->table);
+               if (err < 0) {
+                       /* Now what shall we do? */
+                       connman_error("Cannot remove previously installed "
+                               "iptables rules: %s", strerror(-err));
+                       break;
+               }
+       }
+
+       return err;
+}
-- 
1.8.1.3.566.gaa39828

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to