diff options
author | Antti Kaijanmäki <antti@kaijanmaki.net> | 2008-08-18 08:30:28 +0000 |
---|---|---|
committer | Antti Kaijanmäki <antti@kaijanmaki.net> | 2008-08-18 08:30:28 +0000 |
commit | 2c21a2fe6b0498585fba0beb003ac8aa6351803c (patch) | |
tree | 9544edfe2ed9a6c96eda933c35fb5110f1d666c6 /src/nm-activation-request.c | |
parent | e04934d93efba622123809cc767488af673b2967 (diff) | |
download | NetworkManager-mbca.tar.gz |
keep up with trunkmbca
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/branches/mbca@3981 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
Diffstat (limited to 'src/nm-activation-request.c')
-rw-r--r-- | src/nm-activation-request.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 4df9f887e9..071511792e 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -20,6 +20,9 @@ */ #include <string.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <unistd.h> #include <dbus/dbus-glib.h> #include "nm-activation-request.h" @@ -49,6 +52,10 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; +typedef struct { + char *table; + char *rule; +} ShareRule; typedef struct { gboolean disposed; @@ -63,6 +70,7 @@ typedef struct { NMActiveConnectionState state; gboolean is_default; gboolean shared; + GSList *share_rules; char *ac_path; } NMActRequestPrivate; @@ -206,12 +214,33 @@ dispose (GObject *object) cleanup_secrets_dbus_call (NM_ACT_REQUEST (object)); + /* Clear any share rules */ + nm_act_request_set_shared (NM_ACT_REQUEST (object), FALSE); + g_object_unref (priv->connection); G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object); } static void +clear_share_rules (NMActRequest *req) +{ + NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req); + GSList *iter; + + for (iter = priv->share_rules; iter; iter = g_slist_next (iter)) { + ShareRule *rule = (ShareRule *) iter->data; + + g_free (rule->table); + g_free (rule->rule); + g_free (rule); + } + + g_slist_free (priv->share_rules); + priv->share_rules = NULL; +} + +static void finalize (GObject *object) { NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object); @@ -219,6 +248,8 @@ finalize (GObject *object) g_free (priv->specific_object); g_free (priv->ac_path); + clear_share_rules (NM_ACT_REQUEST (object)); + G_OBJECT_CLASS (nm_act_request_parent_class)->finalize (object); } @@ -646,12 +677,69 @@ nm_act_request_get_default (NMActRequest *req) return NM_ACT_REQUEST_GET_PRIVATE (req)->is_default; } +static void +share_child_setup (gpointer user_data G_GNUC_UNUSED) +{ + /* We are in the child process at this point */ + pid_t pid = getpid (); + setpgid (pid, pid); +} + void nm_act_request_set_shared (NMActRequest *req, gboolean shared) { + NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req); + GSList *list, *iter; + g_return_if_fail (NM_IS_ACT_REQUEST (req)); NM_ACT_REQUEST_GET_PRIVATE (req)->shared = shared; + + /* Tear the rules down in reverse order when sharing is stopped */ + list = g_slist_copy (priv->share_rules); + if (!shared) + list = g_slist_reverse (list); + + /* Send the rules to iptables */ + for (iter = list; iter; iter = g_slist_next (iter)) { + ShareRule *rule = (ShareRule *) iter->data; + char *envp[1] = { NULL }; + char **argv; + char *cmd; + int status; + GError *error = NULL; + + if (shared) + cmd = g_strdup_printf ("/sbin/iptables --table %s --insert %s", rule->table, rule->rule); + else + cmd = g_strdup_printf ("/sbin/iptables --table %s --delete %s", rule->table, rule->rule); + + argv = g_strsplit (cmd, " ", 0); + if (!argv || !argv[0]) { + continue; + g_free (cmd); + } + + nm_info ("Executing: %s", cmd); + g_free (cmd); + + if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + share_child_setup, NULL, NULL, NULL, &status, &error)) { + nm_info ("Error executing command: (%d) %s", + error ? error->code : 0, (error && error->message) ? error->message : "unknown"); + if (error) + g_error_free (error); + } else if (WEXITSTATUS (status)) + nm_info ("** Command returned exit status %d.", WEXITSTATUS (status)); + + g_strfreev (argv); + } + + g_slist_free (list); + + /* Clear the share rule list when sharing is stopped */ + if (!shared) + clear_share_rules (req); } gboolean @@ -662,6 +750,24 @@ nm_act_request_get_shared (NMActRequest *req) return NM_ACT_REQUEST_GET_PRIVATE (req)->shared; } +void +nm_act_request_add_share_rule (NMActRequest *req, + const char *table, + const char *table_rule) +{ + NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req); + ShareRule *rule; + + g_return_if_fail (NM_IS_ACT_REQUEST (req)); + g_return_if_fail (table != NULL); + g_return_if_fail (table_rule != NULL); + + rule = g_malloc0 (sizeof (ShareRule)); + rule->table = g_strdup (table); + rule->rule = g_strdup (table_rule); + priv->share_rules = g_slist_append (priv->share_rules, rule); +} + GObject * nm_act_request_get_device (NMActRequest *req) { |