dispatcher: enhance dispatcher script environment (bgo #648382)

For VPN connections, the interface name would be that of the VPN's
IP interface, but the script environment would be the that of the
VPN's parent device.  Enhance the environment by adding any VPN
specific details as additional environment variables prefixed by
"VPN_".  Leave the existing environment setup intact for backwards
compatiblity.

Additionally, the dispatcher never got updated for IPv6 support,
so push IPv6 configuration and DHCPv6 configuration into the
environment too.

Even better, push everything the dispatcher needs to it instead
of making the dispatcher make D-Bus requests back to NM, which
sometimes fails if NM has already torn down the device or the
connection which the device was using.

And add some testcases to ensure that we don't break backwards compat,
the testcases here were grabbed from a 0.8.4 machine with a hacked up
dispatcher to dump everything it was given from NM.
This commit is contained in:
Dan Williams
2011-05-02 22:38:51 -05:00
parent a2fc80b0ea
commit f898dbf1a9
18 changed files with 1646 additions and 320 deletions

1
.gitignore vendored
View File

@@ -141,6 +141,7 @@ initscript/*/[Nn]etwork[Mm]anager
*-glue.h
*-bindings.h
nm-marshal.[ch]
callouts/tests/test-dispatcher-envp
libnm-glib/libnm-glib-test
src/NetworkManager
src/nm-crash-logger

View File

@@ -1,3 +1,13 @@
SUBDIRS=. tests
###########################################
# Test libraries
###########################################
noinst_LTLIBRARIES = \
libtest-dispatcher-envp.la
dbusservicedir = $(DBUS_SYS_DIR)
dbusservice_DATA = \
nm-dhcp-client.conf \
@@ -41,7 +51,9 @@ nm_avahi_autoipd_action_LDADD = \
nm_dispatcher_action_SOURCES = \
nm-dispatcher-action.c \
nm-dispatcher-action.h
nm-dispatcher-action.h \
nm-dispatcher-utils.c \
nm-dispatcher-utils.h
nm_dispatcher_action_CPPFLAGS = \
-I${top_srcdir} \
@@ -54,7 +66,6 @@ nm_dispatcher_action_CPPFLAGS = \
-DLIBEXECDIR=\"$(libexecdir)\"
nm_dispatcher_action_LDADD = \
$(top_builddir)/libnm-glib/libnm-glib.la \
$(top_builddir)/libnm-util/libnm-util.la \
$(DBUS_LIBS) \
$(GLIB_LIBS)
@@ -62,6 +73,26 @@ nm_dispatcher_action_LDADD = \
nm-dispatcher-glue.h: nm-dispatcher.xml
$(AM_V_GEN) dbus-binding-tool --prefix=nm_dispatcher --mode=glib-server --output=$@ $<
###########################################
# dispatcher envp
###########################################
libtest_dispatcher_envp_la_SOURCES = \
nm-dispatcher-utils.c \
nm-dispatcher-utils.h
libtest_dispatcher_envp_la_CPPFLAGS = \
-I${top_srcdir}/include \
-I${top_srcdir}/libnm-util \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS)
libtest_dispatcher_envp_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(GLIB_LIBS) \
$(DBUS_LIBS)
udevrulesdir = $(UDEV_BASE_DIR)/rules.d
udevrules_DATA = 77-nm-olpc-mesh.rules

View File

@@ -35,15 +35,9 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus-glib.h>
#include <NetworkManager.h>
#include "nm-glib-compat.h"
#include <libnm-util/nm-connection.h>
#include <libnm-util/nm-setting-ip4-config.h>
#include <libnm-util/nm-setting-connection.h>
#include <libnm-glib/nm-dhcp4-config.h>
#include <libnm-glib/nm-device.h>
#include "nm-dispatcher-action.h"
#include "nm-dispatcher-utils.h"
#define NMD_SCRIPT_DIR SYSCONFDIR "/NetworkManager/dispatcher.d"
@@ -84,11 +78,18 @@ typedef struct {
} Dispatcher;
static gboolean
nm_dispatcher_action (Handler *obj,
nm_dispatcher_action (Handler *h,
const char *action,
GHashTable *connection,
GHashTable *connection_hash,
GHashTable *connection_props,
GHashTable *device_props,
GHashTable *device_ip4_props,
GHashTable *device_ip6_props,
GHashTable *device_dhcp4_props,
GHashTable *device_dhcp6_props,
const char *vpn_ip_iface,
GHashTable *vpn_ip4_props,
GHashTable *vpn_ip6_props,
GError **error);
#include "nm-dispatcher-glue.h"
@@ -220,207 +221,13 @@ child_setup (gpointer user_data G_GNUC_UNUSED)
setpgid (pid, pid);
}
typedef struct {
char **envp;
guint32 i;
} EnvAddInfo;
static void
add_one_option_to_envp (gpointer key, gpointer value, gpointer user_data)
{
EnvAddInfo *info = (EnvAddInfo *) user_data;
char *ucased;
ucased = g_ascii_strup (key, -1);
info->envp[info->i++] = g_strdup_printf ("DHCP4_%s=%s", ucased, (char *) value);
g_free (ucased);
}
static char **
construct_envp (const char *uuid,
const char *id,
NMIP4Config *ip4_config,
NMDHCP4Config *dhcp4_config)
{
guint32 env_size = 0;
char **envp;
guint32 envp_idx = 0;
GHashTable *options = NULL;
GSList *addresses, *routes, *iter;
GArray *nameservers, *wins;
GPtrArray *domains;
guint32 num, i;
GString *tmp;
if (!ip4_config)
return g_new0 (char *, 1);
addresses = (GSList *) nm_ip4_config_get_addresses (ip4_config);
nameservers = (GArray *) nm_ip4_config_get_nameservers (ip4_config);
domains = (GPtrArray *) nm_ip4_config_get_domains (ip4_config);
wins = (GArray *) nm_ip4_config_get_wins_servers (ip4_config);
routes = (GSList *) nm_ip4_config_get_routes (ip4_config);
env_size = g_slist_length (addresses)
+ 1 /* addresses length */
+ 1 /* nameservers */
+ 1 /* domains */
+ 1 /* WINS servers */
+ g_slist_length (routes)
+ 1 /* routes length */
+ 1 /* connection UUID */
+ 1 /* connection ID */;
if (dhcp4_config) {
options = nm_dhcp4_config_get_options (dhcp4_config);
env_size += g_hash_table_size (options);
}
envp = g_new0 (char *, env_size + 1);
if (uuid)
envp[envp_idx++] = g_strdup_printf ("CONNECTION_UUID=%s", uuid);
if (id)
envp[envp_idx++] = g_strdup_printf ("CONNECTION_ID=%s", id);
/* IP4 config stuff */
for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
NMIP4Address *addr = (NMIP4Address *) iter->data;
char str_addr[INET_ADDRSTRLEN + 1];
char str_gw[INET_ADDRSTRLEN + 1];
struct in_addr tmp_addr;
guint32 prefix = nm_ip4_address_get_prefix (addr);
memset (str_addr, 0, sizeof (str_addr));
tmp_addr.s_addr = nm_ip4_address_get_address (addr);
if (!inet_ntop (AF_INET, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_gw, 0, sizeof (str_gw));
tmp_addr.s_addr = nm_ip4_address_get_gateway (addr);
inet_ntop (AF_INET, &tmp_addr, str_gw, sizeof (str_gw));
tmp = g_string_sized_new (25 + strlen (str_addr) + strlen (str_gw));
g_string_append_printf (tmp, "IP4_ADDRESS_%d=%s/%d %s", num++, str_addr, prefix, str_gw);
envp[envp_idx++] = tmp->str;
g_string_free (tmp, FALSE);
}
if (num)
envp[envp_idx++] = g_strdup_printf ("IP4_NUM_ADDRESSES=%d", num);
if (nameservers && nameservers->len) {
gboolean first = TRUE;
tmp = g_string_new ("IP4_NAMESERVERS=");
for (i = 0; i < nameservers->len; i++) {
struct in_addr addr;
char buf[INET_ADDRSTRLEN + 1];
addr.s_addr = g_array_index (nameservers, guint32, i);
memset (buf, 0, sizeof (buf));
if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
if (!first)
g_string_append_c (tmp, ' ');
g_string_append (tmp, buf);
first = FALSE;
}
}
envp[envp_idx++] = tmp->str;
g_string_free (tmp, FALSE);
}
if (domains && domains->len) {
tmp = g_string_new ("IP4_DOMAINS=");
for (i = 0; i < domains->len; i++) {
if (i > 0)
g_string_append_c (tmp, ' ');
g_string_append (tmp, (char *) g_ptr_array_index (domains, i));
}
envp[envp_idx++] = tmp->str;
g_string_free (tmp, FALSE);
}
if (wins && wins->len) {
gboolean first = TRUE;
tmp = g_string_new ("IP4_WINS_SERVERS=");
for (i = 0; i < wins->len; i++) {
struct in_addr addr;
char buf[INET_ADDRSTRLEN + 1];
addr.s_addr = g_array_index (wins, guint32, i);
memset (buf, 0, sizeof (buf));
if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
if (!first)
g_string_append_c (tmp, ' ');
g_string_append (tmp, buf);
first = FALSE;
}
}
envp[envp_idx++] = tmp->str;
g_string_free (tmp, FALSE);
}
for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
NMIP4Route *route = (NMIP4Route *) iter->data;
char str_addr[INET_ADDRSTRLEN + 1];
char str_nh[INET_ADDRSTRLEN + 1];
struct in_addr tmp_addr;
guint32 prefix = nm_ip4_route_get_prefix (route);
guint32 metric = nm_ip4_route_get_metric (route);
memset (str_addr, 0, sizeof (str_addr));
tmp_addr.s_addr = nm_ip4_route_get_dest (route);
if (!inet_ntop (AF_INET, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_nh, 0, sizeof (str_nh));
tmp_addr.s_addr = nm_ip4_route_get_next_hop (route);
inet_ntop (AF_INET, &tmp_addr, str_nh, sizeof (str_nh));
tmp = g_string_sized_new (30 + strlen (str_addr) + strlen (str_nh));
g_string_append_printf (tmp, "IP4_ROUTE_%d=%s/%d %s %d", num++, str_addr, prefix, str_nh, metric);
envp[envp_idx++] = tmp->str;
g_string_free (tmp, FALSE);
}
envp[envp_idx++] = g_strdup_printf ("IP4_NUM_ROUTES=%d", num);
/* DHCP stuff */
if (dhcp4_config && options) {
EnvAddInfo info;
info.envp = envp;
info.i = envp_idx;
g_hash_table_foreach (options, add_one_option_to_envp, &info);
}
if (debug) {
char **p;
g_message ("------------ Script Environment ------------");
for (p = envp; *p; p++)
g_message (" %s", *p);
g_message ("\n");
}
return envp;
}
static void
dispatch_scripts (const char *action,
const char *iface,
const char *parent_iface,
NMDeviceType type,
const char *uuid,
const char *id,
NMIP4Config *ip4_config,
NMDHCP4Config *dhcp4_config)
dispatch_scripts (const char *action, const char *iface, char **envp)
{
GDir *dir;
const char *filename;
GSList *scripts = NULL, *iter;
GError *error = NULL;
char **envp = NULL;
if (!(dir = g_dir_open (NMD_SCRIPT_DIR, 0, &error))) {
g_warning ("g_dir_open() could not open '" NMD_SCRIPT_DIR "'. '%s'",
@@ -458,8 +265,6 @@ dispatch_scripts (const char *action,
}
g_dir_close (dir);
envp = construct_envp (uuid, id, ip4_config, dhcp4_config);
for (iter = scripts; iter; iter = g_slist_next (iter)) {
gchar *argv[4];
gint status = -1;
@@ -487,8 +292,6 @@ dispatch_scripts (const char *action,
}
}
g_strfreev (envp);
g_slist_foreach (scripts, (GFunc) g_free, NULL);
g_slist_free (scripts);
}
@@ -499,18 +302,18 @@ nm_dispatcher_action (Handler *h,
GHashTable *connection_hash,
GHashTable *connection_props,
GHashTable *device_props,
GHashTable *device_ip4_props,
GHashTable *device_ip6_props,
GHashTable *device_dhcp4_props,
GHashTable *device_dhcp6_props,
const char *vpn_ip_iface,
GHashTable *vpn_ip4_props,
GHashTable *vpn_ip6_props,
GError **error)
{
Dispatcher *d = g_object_get_data (G_OBJECT (h), "dispatcher");
NMConnection *connection;
char *iface = NULL, *parent_iface = NULL;
const char *uuid = NULL, *id = NULL;
NMDeviceType type = NM_DEVICE_TYPE_UNKNOWN;
NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
NMDevice *device = NULL;
NMDHCP4Config *dhcp4_config = NULL;
NMIP4Config *ip4_config = NULL;
GValue *value;
char **envp, **p;
char *iface = NULL;
/* Back off the quit timeout */
if (d->quit_timeout)
@@ -518,80 +321,30 @@ nm_dispatcher_action (Handler *h,
if (!d->persist)
d->quit_timeout = g_timeout_add_seconds (10, quit_timeout_cb, NULL);
/* Hostname changes don't require a device nor contain a connection */
if (!strcmp (action, "hostname"))
goto dispatch;
envp = nm_dispatcher_utils_construct_envp (action,
connection_hash,
connection_props,
device_props,
device_ip4_props,
device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
vpn_ip_iface,
vpn_ip4_props,
vpn_ip6_props,
&iface);
connection = nm_connection_new_from_hash (connection_hash, error);
if (connection) {
uuid = nm_connection_get_uuid (connection);
id = nm_connection_get_id (connection);
} else {
g_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d",
__func__,
g_type_name (nm_connection_lookup_setting_type_by_quark ((*error)->domain)),
(*error)->message, (*error)->code);
/* Don't fail on this error yet */
g_error_free (*error);
*error = NULL;
if (debug) {
g_message ("------------ Script Environment ------------");
for (p = envp; *p; p++)
g_message (" %s", *p);
g_message ("\n");
}
/* interface name */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_INTERFACE);
if (!value || !G_VALUE_HOLDS_STRING (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!");
goto out;
}
iface = (char *) g_value_get_string (value);
dispatch_scripts (action, iface, envp);
g_strfreev (envp);
g_free (iface);
/* IP interface name */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_IP_INTERFACE);
if (value) {
if (!G_VALUE_HOLDS_STRING (value)) {
g_warning ("Invalid required value " NMD_DEVICE_PROPS_IP_INTERFACE "!");
goto out;
}
parent_iface = iface;
iface = (char *) g_value_get_string (value);
}
/* Device type */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_TYPE);
if (!value || !G_VALUE_HOLDS_UINT (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!");
goto out;
}
type = g_value_get_uint (value);
/* Device state */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_STATE);
if (!value || !G_VALUE_HOLDS_UINT (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!");
goto out;
}
dev_state = g_value_get_uint (value);
/* device itself */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_PATH);
if (!value || (G_VALUE_TYPE (value) != DBUS_TYPE_G_OBJECT_PATH)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!");
goto out;
}
device = NM_DEVICE (nm_device_new (d->g_connection, (const char *) g_value_get_boxed (value)));
/* Get the DHCP4 config */
if (device && (dev_state == NM_DEVICE_STATE_ACTIVATED)) {
dhcp4_config = nm_device_get_dhcp4_config (device);
ip4_config = nm_device_get_ip4_config (device);
}
dispatch:
dispatch_scripts (action, iface, parent_iface, type, uuid, id, ip4_config, dhcp4_config);
if (device)
g_object_unref (device);
out:
return TRUE;
}

View File

@@ -0,0 +1,509 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2011 Red Hat, Inc.
*/
#include <config.h>
#include <string.h>
#include <glib-object.h>
#include <NetworkManager.h>
#include <nm-dbus-glib-types.h>
#include <nm-connection.h>
#include <nm-setting-ip4-config.h>
#include <nm-setting-ip6-config.h>
#include <nm-setting-connection.h>
#include "nm-dispatcher-action.h"
#include "nm-utils.h"
#include "nm-dispatcher-utils.h"
static GSList *
construct_basic_items (GSList *list,
const char *uuid,
const char *id,
const char *iface,
const char *ip_iface)
{
if (uuid)
list = g_slist_prepend (list, g_strdup_printf ("CONNECTION_UUID=%s", uuid));
if (id)
list = g_slist_prepend (list, g_strdup_printf ("CONNECTION_ID=%s", id));
if (iface)
list = g_slist_prepend (list, g_strdup_printf ("DEVICE_IFACE=%s", iface));
if (ip_iface)
list = g_slist_prepend (list, g_strdup_printf ("DEVICE_IP_IFACE=%s", ip_iface));
return list;
}
static GSList *
add_domains (GSList *items,
GHashTable *hash,
const char *prefix,
const char four_or_six)
{
GValue *val;
GPtrArray *domains = NULL;
GString *tmp;
guint i;
/* Search domains */
val = g_hash_table_lookup (hash, "domains");
if (!val || !G_VALUE_HOLDS (val, DBUS_TYPE_G_ARRAY_OF_STRING))
return items;
domains = (GPtrArray *) g_value_get_boxed (val);
if (!domains || (domains->len == 0))
return items;
tmp = g_string_new (NULL);
g_string_append_printf (tmp, "%sIP%c_DOMAINS=", prefix, four_or_six);
for (i = 0; i < domains->len; i++) {
if (i > 0)
g_string_append_c (tmp, ' ');
g_string_append (tmp, (char *) g_ptr_array_index (domains, i));
}
items = g_slist_prepend (items, tmp->str);
g_string_free (tmp, FALSE);
return items;
}
static GSList *
construct_ip4_items (GSList *items, GHashTable *ip4_config, const char *prefix)
{
GSList *addresses = NULL, *routes = NULL, *iter;
GArray *dns = NULL, *wins = NULL;
guint32 num, i;
GString *tmp;
GValue *val;
if (ip4_config == NULL)
return items;
if (prefix == NULL)
prefix = "";
/* IP addresses */
val = g_hash_table_lookup (ip4_config, "addresses");
if (val)
addresses = nm_utils_ip4_addresses_from_gvalue (val);
for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
NMIP4Address *addr = (NMIP4Address *) iter->data;
char str_addr[INET_ADDRSTRLEN + 1];
char str_gw[INET_ADDRSTRLEN + 1];
struct in_addr tmp_addr;
guint32 ip_prefix = nm_ip4_address_get_prefix (addr);
char *addrtmp;
memset (str_addr, 0, sizeof (str_addr));
tmp_addr.s_addr = nm_ip4_address_get_address (addr);
if (!inet_ntop (AF_INET, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_gw, 0, sizeof (str_gw));
tmp_addr.s_addr = nm_ip4_address_get_gateway (addr);
inet_ntop (AF_INET, &tmp_addr, str_gw, sizeof (str_gw));
addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
items = g_slist_prepend (items, addrtmp);
}
if (num)
items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, num));
if (addresses) {
g_slist_foreach (addresses, (GFunc) nm_ip4_address_unref, NULL);
g_slist_free (addresses);
}
/* DNS servers */
val = g_hash_table_lookup (ip4_config, "nameservers");
if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_UINT_ARRAY))
dns = (GArray *) g_value_get_boxed (val);
if (dns && (dns->len > 0)) {
gboolean first = TRUE;
tmp = g_string_new (NULL);
g_string_append_printf (tmp, "%sIP4_NAMESERVERS=", prefix);
for (i = 0; i < dns->len; i++) {
struct in_addr addr;
char buf[INET_ADDRSTRLEN + 1];
addr.s_addr = g_array_index (dns, guint32, i);
memset (buf, 0, sizeof (buf));
if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
if (!first)
g_string_append_c (tmp, ' ');
g_string_append (tmp, buf);
first = FALSE;
}
}
items = g_slist_prepend (items, tmp->str);
g_string_free (tmp, FALSE);
}
/* Search domains */
items = add_domains (items, ip4_config, prefix, '4');
/* WINS servers */
val = g_hash_table_lookup (ip4_config, "wins-servers");
if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_UINT_ARRAY))
wins = (GArray *) g_value_get_boxed (val);
if (wins && wins->len) {
gboolean first = TRUE;
tmp = g_string_new (NULL);
g_string_append_printf (tmp, "%sIP4_WINS_SERVERS=", prefix);
for (i = 0; i < wins->len; i++) {
struct in_addr addr;
char buf[INET_ADDRSTRLEN + 1];
addr.s_addr = g_array_index (wins, guint32, i);
memset (buf, 0, sizeof (buf));
if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
if (!first)
g_string_append_c (tmp, ' ');
g_string_append (tmp, buf);
first = FALSE;
}
}
items = g_slist_prepend (items, tmp->str);
g_string_free (tmp, FALSE);
}
/* Static routes */
val = g_hash_table_lookup (ip4_config, "routes");
if (val)
routes = nm_utils_ip4_routes_from_gvalue (val);
for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
NMIP4Route *route = (NMIP4Route *) iter->data;
char str_addr[INET_ADDRSTRLEN + 1];
char str_nh[INET_ADDRSTRLEN + 1];
struct in_addr tmp_addr;
guint32 ip_prefix = nm_ip4_route_get_prefix (route);
guint32 metric = nm_ip4_route_get_metric (route);
char *routetmp;
memset (str_addr, 0, sizeof (str_addr));
tmp_addr.s_addr = nm_ip4_route_get_dest (route);
if (!inet_ntop (AF_INET, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_nh, 0, sizeof (str_nh));
tmp_addr.s_addr = nm_ip4_route_get_next_hop (route);
inet_ntop (AF_INET, &tmp_addr, str_nh, sizeof (str_nh));
routetmp = g_strdup_printf ("%sIP4_ROUTE_%d=%s/%d %s %d", prefix, num++, str_addr, ip_prefix, str_nh, metric);
items = g_slist_prepend (items, routetmp);
}
items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ROUTES=%d", prefix, num));
if (routes) {
g_slist_foreach (routes, (GFunc) nm_ip4_route_unref, NULL);
g_slist_free (routes);
}
return items;
}
static GSList *
construct_device_dhcp4_items (GSList *items, GHashTable *dhcp4_config)
{
GHashTableIter iter;
const char *key, *tmp;
GValue *val;
char *ucased;
if (dhcp4_config == NULL)
return items;
g_hash_table_iter_init (&iter, dhcp4_config);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
ucased = g_ascii_strup (key, -1);
tmp = g_value_get_string (val);
items = g_slist_prepend (items, g_strdup_printf ("DHCP4_%s=%s", ucased, tmp));
g_free (ucased);
}
return items;
}
static GSList *
construct_ip6_items (GSList *items, GHashTable *ip6_config, const char *prefix)
{
GSList *addresses = NULL, *routes = NULL, *dns = NULL, *iter;
guint32 num;
GString *tmp;
GValue *val;
if (ip6_config == NULL)
return items;
if (prefix == NULL)
prefix = "";
/* IP addresses */
val = g_hash_table_lookup (ip6_config, "addresses");
if (val)
addresses = nm_utils_ip6_addresses_from_gvalue (val);
for (iter = addresses, num = 0; iter; iter = g_slist_next (iter)) {
NMIP6Address *addr = (NMIP6Address *) iter->data;
char str_addr[INET6_ADDRSTRLEN + 1];
char str_gw[INET6_ADDRSTRLEN + 1];
const struct in6_addr *tmp_addr;
guint32 ip_prefix = nm_ip6_address_get_prefix (addr);
char *addrtmp;
memset (str_addr, 0, sizeof (str_addr));
tmp_addr = nm_ip6_address_get_address (addr);
if (!inet_ntop (AF_INET6, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_gw, 0, sizeof (str_gw));
tmp_addr = nm_ip6_address_get_gateway (addr);
inet_ntop (AF_INET6, &tmp_addr, str_gw, sizeof (str_gw));
addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, num++, str_addr, ip_prefix, str_gw);
items = g_slist_prepend (items, addrtmp);
}
if (num)
items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, num));
if (addresses) {
g_slist_foreach (addresses, (GFunc) nm_ip6_address_unref, NULL);
g_slist_free (addresses);
}
/* DNS servers */
val = g_hash_table_lookup (ip6_config, "nameservers");
if (val)
dns = nm_utils_ip6_dns_from_gvalue (val);
if (g_slist_length (dns)) {
tmp = g_string_new (NULL);
g_string_append_printf (tmp, "%sIP6_NAMESERVERS=", prefix);
for (iter = dns; iter; iter = g_slist_next (iter)) {
const struct in6_addr *addr = iter->data;
gboolean first = TRUE;
char buf[INET6_ADDRSTRLEN + 1];
memset (buf, 0, sizeof (buf));
if (inet_ntop (AF_INET6, addr, buf, sizeof (buf))) {
if (!first)
g_string_append_c (tmp, ' ');
g_string_append (tmp, buf);
first = FALSE;
}
}
items = g_slist_prepend (items, tmp->str);
g_string_free (tmp, FALSE);
}
/* Search domains */
items = add_domains (items, ip6_config, prefix, '6');
/* Static routes */
val = g_hash_table_lookup (ip6_config, "routes");
if (val)
routes = nm_utils_ip6_routes_from_gvalue (val);
for (iter = routes, num = 0; iter; iter = g_slist_next (iter)) {
NMIP6Route *route = (NMIP6Route *) iter->data;
char str_addr[INET6_ADDRSTRLEN + 1];
char str_nh[INET6_ADDRSTRLEN + 1];
const struct in6_addr *tmp_addr;
guint32 ip_prefix = nm_ip6_route_get_prefix (route);
guint32 metric = nm_ip6_route_get_metric (route);
char *routetmp;
memset (str_addr, 0, sizeof (str_addr));
tmp_addr = nm_ip6_route_get_dest (route);
if (!inet_ntop (AF_INET6, &tmp_addr, str_addr, sizeof (str_addr)))
continue;
memset (str_nh, 0, sizeof (str_nh));
tmp_addr = nm_ip6_route_get_next_hop (route);
inet_ntop (AF_INET6, &tmp_addr, str_nh, sizeof (str_nh));
routetmp = g_strdup_printf ("%sIP6_ROUTE_%d=%s/%d %s %d", prefix, num++, str_addr, ip_prefix, str_nh, metric);
items = g_slist_prepend (items, routetmp);
}
if (num)
items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ROUTES=%d", prefix, num));
if (routes) {
g_slist_foreach (routes, (GFunc) nm_ip6_route_unref, NULL);
g_slist_free (routes);
}
return items;
}
static GSList *
construct_device_dhcp6_items (GSList *items, GHashTable *dhcp6_config)
{
GHashTableIter iter;
const char *key, *tmp;
GValue *val;
char *ucased;
if (dhcp6_config == NULL)
return items;
g_hash_table_iter_init (&iter, dhcp6_config);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
ucased = g_ascii_strup (key, -1);
tmp = g_value_get_string (val);
items = g_slist_prepend (items, g_strdup_printf ("DHCP6_%s=%s", ucased, tmp));
g_free (ucased);
}
return items;
}
char **
nm_dispatcher_utils_construct_envp (const char *action,
GHashTable *connection_hash,
GHashTable *connection_props,
GHashTable *device_props,
GHashTable *device_ip4_props,
GHashTable *device_ip6_props,
GHashTable *device_dhcp4_props,
GHashTable *device_dhcp6_props,
const char *vpn_ip_iface,
GHashTable *vpn_ip4_props,
GHashTable *vpn_ip6_props,
char **out_iface)
{
const char *iface = NULL, *ip_iface = NULL;
const char *uuid = NULL, *id = NULL;
NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN;
GValue *value;
char **envp = NULL;
GSList *items = NULL, *iter;
guint i;
GHashTable *con_setting_hash;
g_return_val_if_fail (action != NULL, NULL);
g_return_val_if_fail (out_iface != NULL, NULL);
g_return_val_if_fail (*out_iface == NULL, NULL);
/* Hostname changes don't require a device nor contain a connection */
if (!strcmp (action, "hostname"))
return g_new0 (char *, 1);
con_setting_hash = g_hash_table_lookup (connection_hash, NM_SETTING_CONNECTION_SETTING_NAME);
if (!con_setting_hash) {
g_warning ("Failed to read connection setting");
return NULL;
}
value = g_hash_table_lookup (con_setting_hash, NM_SETTING_CONNECTION_UUID);
if (!value || !G_VALUE_HOLDS (value, G_TYPE_STRING)) {
g_warning ("Connection hash did not contain the UUID");
return NULL;
}
uuid = g_value_get_string (value);
value = g_hash_table_lookup (con_setting_hash, NM_SETTING_CONNECTION_ID);
if (!value || !G_VALUE_HOLDS (value, G_TYPE_STRING)) {
g_warning ("Connection hash did not contain the ID");
return NULL;
}
id = g_value_get_string (value);
/* interface name */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_INTERFACE);
if (!value || !G_VALUE_HOLDS_STRING (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!");
return NULL;
}
iface = g_value_get_string (value);
/* IP interface name */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_IP_INTERFACE);
if (value) {
if (!G_VALUE_HOLDS_STRING (value)) {
g_warning ("Invalid required value " NMD_DEVICE_PROPS_IP_INTERFACE "!");
return NULL;
}
ip_iface = g_value_get_string (value);
}
/* Device type */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_TYPE);
if (!value || !G_VALUE_HOLDS_UINT (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!");
return NULL;
}
/* Device state */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_STATE);
if (!value || !G_VALUE_HOLDS_UINT (value)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!");
return NULL;
}
dev_state = g_value_get_uint (value);
/* device itself */
value = g_hash_table_lookup (device_props, NMD_DEVICE_PROPS_PATH);
if (!value || (G_VALUE_TYPE (value) != DBUS_TYPE_G_OBJECT_PATH)) {
g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!");
return NULL;
}
items = construct_basic_items (items, uuid, id, iface, ip_iface);
/* Device it's aren't valid if the device isn't activated */
if (iface && (dev_state == NM_DEVICE_STATE_ACTIVATED)) {
items = construct_ip4_items (items, device_ip4_props, NULL);
items = construct_ip6_items (items, device_ip6_props, NULL);
items = construct_device_dhcp4_items (items, device_dhcp4_props);
items = construct_device_dhcp6_items (items, device_dhcp6_props);
}
if (vpn_ip_iface) {
items = g_slist_prepend (items, g_strdup_printf ("VPN_IP_IFACE=%s", vpn_ip_iface));
items = construct_ip4_items (items, vpn_ip4_props, "VPN_");
items = construct_ip6_items (items, vpn_ip6_props, "VPN_");
}
/* Convert the list to an environment pointer */
envp = g_new0 (char *, g_slist_length (items) + 1);
for (iter = items, i = 0; iter; iter = g_slist_next (iter), i++)
envp[i] = (char *) iter->data;
g_slist_free (items);
/* Backwards compat: 'iface' is set in this order:
* 1) VPN interface name
* 2) Device IP interface name
* 3) Device interface anme
*/
if (vpn_ip_iface)
*out_iface = g_strdup (vpn_ip_iface);
else if (ip_iface)
*out_iface = g_strdup (ip_iface);
else
*out_iface = g_strdup (iface);
return envp;
}

View File

@@ -0,0 +1,41 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 - 2011 Red Hat, Inc.
*/
#ifndef NM_DISPATCHER_UTILS_H
#define NM_DISPATCHER_UTILS_H
#include <glib.h>
char **
nm_dispatcher_utils_construct_envp (const char *action,
GHashTable *connection_hash,
GHashTable *connection_props,
GHashTable *device_props,
GHashTable *device_ip4_props,
GHashTable *device_ip6_props,
GHashTable *device_dhcp4_props,
GHashTable *device_dhcp6_props,
const char *vpn_ip_iface,
GHashTable *vpn_ip4_props,
GHashTable *vpn_ip6_props,
char **out_iface);
#endif /* NM_DISPATCHER_UTILS_H */

View File

@@ -32,6 +32,46 @@
</tp:docstring>
</arg>
<arg name="device_ip4_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the device's IPv4 configuration.
</tp:docstring>
</arg>
<arg name="device_ip6_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the device's IPv6 configuration.
</tp:docstring>
</arg>
<arg name="device_dhcp4_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the device's DHCPv4 configuration.
</tp:docstring>
</arg>
<arg name="device_dhcp6_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the device's DHCPv6 configuration.
</tp:docstring>
</arg>
<arg name="vpn_ip_iface" type="s" direction="in">
<tp:docstring>VPN interface name.</tp:docstring>
</arg>
<arg name="vpn_ip4_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the VPN's IPv4 configuration.
</tp:docstring>
</arg>
<arg name="vpn_ip6_config" type="a{sv}" direction="in">
<tp:docstring>
Properties of the VPN's IPv6 configuration.
</tp:docstring>
</arg>
</method>
</interface>
</node>

View File

@@ -0,0 +1,38 @@
INCLUDES = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libnm-util \
-I$(top_srcdir)/callouts
noinst_PROGRAMS = \
test-dispatcher-envp
####### dispatcher envp #######
test_dispatcher_envp_SOURCES = \
test-dispatcher-envp.c
test_dispatcher_envp_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS)
test_dispatcher_envp_LDADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(top_builddir)/callouts/libtest-dispatcher-envp.la \
$(GLIB_LIBS) \
$(DBUS_LIBS)
###########################################
if WITH_TESTS
check-local: test-dispatcher-envp
$(abs_builddir)/test-dispatcher-envp $(abs_srcdir)
endif
EXTRA_DIST= \
dispatcher-old-down \
dispatcher-old-up \
dispatcher-old-vpn-down \
dispatcher-old-vpn-up

View File

@@ -0,0 +1,19 @@
[main]
action=down
iface=wlan0
uuid=3fd2a33a-d81b-423f-ae99-e6baba742311
id=Random Connection
[device]
state=30
ip-interface=wlan0
type=2
interface=wlan0
path=/org/freedesktop/NetworkManager/Devices/0
[env]
CONNECTION_UUID=3fd2a33a-d81b-423f-ae99-e6baba742311
CONNECTION_ID=Random Connection
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=wlan0

View File

@@ -0,0 +1,55 @@
[main]
action=up
iface=wlan0
uuid=3fd2a33a-d81b-423f-ae99-e6baba742311
id=Random Connection
[device]
state=100
ip-interface=wlan0
type=2
interface=wlan0
path=/org/freedesktop/NetworkManager/Devices/0
[dhcp4]
netbios_name_servers=0.0.0.0
domain_name_servers=68.87.77.134 68.87.72.134 192.168.1.1
dhcp_lease_time=86400
network_number=192.168.1.0
domain_name=hsd1.mn.comcast.net.
ip_address=192.168.1.119
dhcp_message_type=5
dhcp_server_identifier=192.168.1.1
routers=192.168.1.1
broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304300446
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
domains=hsd1.mn.comcast.net.
[env]
CONNECTION_UUID=3fd2a33a-d81b-423f-ae99-e6baba742311
CONNECTION_ID=Random Connection
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=wlan0
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
IP4_DOMAINS=hsd1.mn.comcast.net.
IP4_NUM_ROUTES=0
DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
DHCP4_DOMAIN_NAME_SERVERS=68.87.77.134 68.87.72.134 192.168.1.1
DHCP4_DHCP_LEASE_TIME=86400
DHCP4_NETWORK_NUMBER=192.168.1.0
DHCP4_DOMAIN_NAME=hsd1.mn.comcast.net.
DHCP4_IP_ADDRESS=192.168.1.119
DHCP4_DHCP_MESSAGE_TYPE=5
DHCP4_DHCP_SERVER_IDENTIFIER=192.168.1.1
DHCP4_ROUTERS=192.168.1.1
DHCP4_BROADCAST_ADDRESS=192.168.1.255
DHCP4_SUBNET_MASK=255.255.255.0
DHCP4_EXPIRY=1304300446

View File

@@ -0,0 +1,54 @@
[main]
action=vpn-down
iface=tun0
uuid=355653c0-34d3-4777-ad25-f9a498b7ef8e
id=Random Connection
[device]
state=100
ip-interface=tun0
type=2
interface=wlan0
path=/org/freedesktop/NetworkManager/Devices/0
[dhcp4]
netbios_name_servers=0.0.0.0
domain_name_servers=68.87.77.134 68.87.72.134 192.168.1.1
dhcp_lease_time=86400
network_number=192.168.1.0
domain_name=hsd1.mn.comcast.net.
ip_address=192.168.1.119
dhcp_message_type=5
dhcp_server_identifier=192.168.1.1
routers=192.168.1.1
broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304349405
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
domains=hsd1.mn.comcast.net.
[env]
CONNECTION_UUID=355653c0-34d3-4777-ad25-f9a498b7ef8e
CONNECTION_ID=Random Connection
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=tun0
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
IP4_DOMAINS=hsd1.mn.comcast.net.
IP4_NUM_ROUTES=0
DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
DHCP4_DOMAIN_NAME_SERVERS=68.87.77.134 68.87.72.134 192.168.1.1
DHCP4_DHCP_LEASE_TIME=86400
DHCP4_NETWORK_NUMBER=192.168.1.0
DHCP4_DOMAIN_NAME=hsd1.mn.comcast.net.
DHCP4_IP_ADDRESS=192.168.1.119
DHCP4_DHCP_MESSAGE_TYPE=5
DHCP4_DHCP_SERVER_IDENTIFIER=192.168.1.1
DHCP4_ROUTERS=192.168.1.1
DHCP4_BROADCAST_ADDRESS=192.168.1.255
DHCP4_SUBNET_MASK=255.255.255.0
DHCP4_EXPIRY=1304349405

View File

@@ -0,0 +1,54 @@
[main]
action=vpn-up
iface=tun0
uuid=355653c0-34d3-4777-ad25-f9a498b7ef8e
id=Random Connection
[device]
state=100
ip-interface=tun0
type=2
interface=wlan0
path=/org/freedesktop/NetworkManager/Devices/0
[dhcp4]
netbios_name_servers=0.0.0.0
domain_name_servers=68.87.77.134 68.87.72.134 192.168.1.1
dhcp_lease_time=86400
network_number=192.168.1.0
domain_name=hsd1.mn.comcast.net.
ip_address=192.168.1.119
dhcp_message_type=5
dhcp_server_identifier=192.168.1.1
routers=192.168.1.1
broadcast_address=192.168.1.255
subnet_mask=255.255.255.0
expiry=1304349405
[ip4]
addresses=192.168.1.119/24 192.168.1.1
nameservers=68.87.77.134 68.87.72.134 192.168.1.1
domains=hsd1.mn.comcast.net.
[env]
CONNECTION_UUID=355653c0-34d3-4777-ad25-f9a498b7ef8e
CONNECTION_ID=Random Connection
DEVICE_IFACE=wlan0
DEVICE_IP_IFACE=tun0
IP4_ADDRESS_0=192.168.1.119/24 192.168.1.1
IP4_NUM_ADDRESSES=1
IP4_NAMESERVERS=68.87.77.134 68.87.72.134 192.168.1.1
IP4_DOMAINS=hsd1.mn.comcast.net.
IP4_NUM_ROUTES=0
DHCP4_NETBIOS_NAME_SERVERS=0.0.0.0
DHCP4_DOMAIN_NAME_SERVERS=68.87.77.134 68.87.72.134 192.168.1.1
DHCP4_DHCP_LEASE_TIME=86400
DHCP4_NETWORK_NUMBER=192.168.1.0
DHCP4_DOMAIN_NAME=hsd1.mn.comcast.net.
DHCP4_IP_ADDRESS=192.168.1.119
DHCP4_DHCP_MESSAGE_TYPE=5
DHCP4_DHCP_SERVER_IDENTIFIER=192.168.1.1
DHCP4_ROUTERS=192.168.1.1
DHCP4_BROADCAST_ADDRESS=192.168.1.255
DHCP4_SUBNET_MASK=255.255.255.0
DHCP4_EXPIRY=1304349405

View File

@@ -0,0 +1,615 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2011 Red Hat, Inc.
*
*/
#include <config.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <glib.h>
#include <glib-object.h>
#include "nm-connection.h"
#include "nm-setting-connection.h"
#include "nm-dispatcher-utils.h"
#include "nm-dbus-glib-types.h"
#include "nm-dispatcher-action.h"
#include "nm-utils.h"
/*******************************************/
static void
value_destroy (gpointer data)
{
GValue *value = (GValue *) data;
g_value_unset (value);
g_slice_free (GValue, value);
}
static GHashTable *
value_hash_create (void)
{
return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, value_destroy);
}
static void
value_hash_add (GHashTable *hash,
const char *key,
GValue *value)
{
g_hash_table_insert (hash, g_strdup (key), value);
}
static void
value_hash_add_string (GHashTable *hash,
const char *key,
const char *str)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, str);
value_hash_add (hash, key, value);
}
static void
value_hash_add_object_path (GHashTable *hash,
const char *key,
const char *op)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, DBUS_TYPE_G_OBJECT_PATH);
g_value_set_boxed (value, op);
value_hash_add (hash, key, value);
}
static void
value_hash_add_uint (GHashTable *hash,
const char *key,
guint32 val)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, val);
value_hash_add (hash, key, value);
}
static void
value_hash_add_strv (GHashTable *hash,
const char *key,
GPtrArray *array)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, DBUS_TYPE_G_ARRAY_OF_STRING);
g_value_take_boxed (value, array);
value_hash_add (hash, key, value);
}
static void
value_hash_add_uint_array (GHashTable *hash,
const char *key,
GArray *array)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, DBUS_TYPE_G_UINT_ARRAY);
g_value_take_boxed (value, array);
value_hash_add (hash, key, value);
}
static gboolean
parse_main (GKeyFile *kf,
GHashTable **out_con_hash,
GHashTable **out_con_props,
char **out_iface,
char **out_action,
GError **error)
{
char *uuid, *id;
NMConnection *connection;
NMSettingConnection *s_con;
*out_iface = g_key_file_get_string (kf, "main", "iface", error);
if (*out_iface == NULL)
return FALSE;
*out_action = g_key_file_get_string (kf, "main", "action", error);
if (*out_action == NULL)
return FALSE;
uuid = g_key_file_get_string (kf, "main", "uuid", error);
if (uuid == NULL)
return FALSE;
id = g_key_file_get_string (kf, "main", "id", error);
if (id == NULL)
return FALSE;
connection = nm_connection_new ();
g_assert (connection);
s_con = (NMSettingConnection *) nm_setting_connection_new ();
g_assert (s_con);
g_object_set (s_con,
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_ID, id,
NULL);
g_free (uuid);
g_free (id);
nm_connection_add_setting (connection, NM_SETTING (s_con));
*out_con_hash = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
g_object_unref (connection);
*out_con_props = value_hash_create ();
value_hash_add_object_path (*out_con_props, "connection-path", "/org/freedesktop/NetworkManager/Connections/5");
return TRUE;
}
static gboolean
parse_device (GKeyFile *kf, GHashTable **out_device_props, GError **error)
{
char *tmp;
gint i;
*out_device_props = value_hash_create ();
i = g_key_file_get_integer (kf, "device", "state", error);
if (i == 0)
return FALSE;
value_hash_add_uint (*out_device_props, NMD_DEVICE_PROPS_STATE, (guint) i);
i = g_key_file_get_integer (kf, "device", "type", error);
if (i == 0)
return FALSE;
value_hash_add_uint (*out_device_props, NMD_DEVICE_PROPS_TYPE, (guint) i);
tmp = g_key_file_get_string (kf, "device", "interface", error);
if (tmp == NULL)
return FALSE;
value_hash_add_string (*out_device_props, NMD_DEVICE_PROPS_INTERFACE, tmp);
g_free (tmp);
tmp = g_key_file_get_string (kf, "device", "ip-interface", error);
if (tmp == NULL)
return FALSE;
value_hash_add_string (*out_device_props, NMD_DEVICE_PROPS_IP_INTERFACE, tmp);
g_free (tmp);
tmp = g_key_file_get_string (kf, "device", "path", error);
if (tmp == NULL)
return FALSE;
value_hash_add_object_path (*out_device_props, NMD_DEVICE_PROPS_PATH, tmp);
g_free (tmp);
return TRUE;
}
static gboolean
add_uint_array (GKeyFile *kf,
GHashTable *props,
const char *section,
const char *key,
GError **error)
{
char *tmp;
char **split, **iter;
GArray *items;
tmp = g_key_file_get_string (kf, section, key, error);
if (tmp == NULL) {
g_clear_error (error);
return TRUE;
}
split = g_strsplit_set (tmp, " ", -1);
g_free (tmp);
if (g_strv_length (split) > 0) {
items = g_array_sized_new (FALSE, TRUE, sizeof (guint32), g_strv_length (split));
for (iter = split; iter && *iter; iter++) {
if (strlen (g_strstrip (*iter))) {
struct in_addr addr;
g_assert_cmpint (inet_pton (AF_INET, *iter, &addr), ==, 1);
g_array_append_val (items, addr.s_addr);
}
}
value_hash_add_uint_array (props, key, items);
}
g_strfreev (split);
return TRUE;
}
static gboolean
parse_ip4 (GKeyFile *kf, GHashTable **out_props, const char *section, GError **error)
{
char *tmp;
char **split, **iter;
GPtrArray *domains;
GSList *list;
GValue *val;
*out_props = value_hash_create ();
/* search domains */
tmp = g_key_file_get_string (kf, section, "domains", error);
if (tmp == NULL)
return FALSE;
split = g_strsplit_set (tmp, " ", -1);
g_free (tmp);
if (g_strv_length (split) > 0) {
domains = g_ptr_array_sized_new (g_strv_length (split));
for (iter = split; iter && *iter; iter++) {
if (strlen (g_strstrip (*iter)))
g_ptr_array_add (domains, g_strdup (*iter));
}
value_hash_add_strv (*out_props, "domains", domains);
}
g_strfreev (split);
/* nameservers */
if (!add_uint_array (kf, *out_props, "ip4", "nameservers", error))
return FALSE;
/* wins-servers */
if (!add_uint_array (kf, *out_props, "ip4", "wins-servers", error))
return FALSE;
/* Addresses */
tmp = g_key_file_get_string (kf, section, "addresses", error);
if (tmp == NULL)
return FALSE;
split = g_strsplit_set (tmp, ",", -1);
g_free (tmp);
if (g_strv_length (split) > 0) {
list = NULL;
for (iter = split; iter && *iter; iter++) {
NMIP4Address *addr;
struct in_addr a;
char *p;
if (strlen (g_strstrip (*iter)) == 0)
continue;
addr = nm_ip4_address_new ();
p = strchr (*iter, '/');
g_assert (p);
*p++ = '\0';
g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
nm_ip4_address_set_address (addr, a.s_addr);
nm_ip4_address_set_prefix (addr, (guint) atoi (p));
p = strchr (p, ' ');
g_assert (p);
p++;
g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
nm_ip4_address_set_gateway (addr, a.s_addr);
list = g_slist_append (list, addr);
}
val = g_slice_new0 (GValue);
g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT);
nm_utils_ip4_addresses_to_gvalue (list, val);
value_hash_add (*out_props, "addresses", val);
}
g_strfreev (split);
/* Routes */
tmp = g_key_file_get_string (kf, section, "routes", error);
g_clear_error (error);
if (tmp) {
split = g_strsplit_set (tmp, ",", -1);
g_free (tmp);
if (g_strv_length (split) > 0) {
list = NULL;
for (iter = split; iter && *iter; iter++) {
NMIP4Route *route;
struct in_addr a;
char *p;
if (strlen (g_strstrip (*iter)) == 0)
continue;
route = nm_ip4_route_new ();
p = strchr (*iter, '/');
g_assert (p);
*p++ = '\0';
g_assert_cmpint (inet_pton (AF_INET, *iter, &a), ==, 1);
nm_ip4_route_set_dest (route, a.s_addr);
nm_ip4_route_set_prefix (route, (guint) atoi (p));
p = strchr (p, ' ');
g_assert (p);
p++;
g_assert_cmpint (inet_pton (AF_INET, p, &a), ==, 1);
nm_ip4_route_set_next_hop (route, a.s_addr);
p = strchr (p, ' ');
g_assert (p);
p++;
nm_ip4_route_set_metric (route, (guint) atoi (p));
list = g_slist_append (list, route);
}
val = g_slice_new0 (GValue);
g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT);
nm_utils_ip4_routes_to_gvalue (list, val);
value_hash_add (*out_props, "routes", val);
}
g_strfreev (split);
}
return TRUE;
}
static gboolean
parse_dhcp (GKeyFile *kf,
const char *group_name,
GHashTable **out_props,
GError **error)
{
char **keys, **iter, *val;
keys = g_key_file_get_keys (kf, group_name, NULL, error);
if (!keys)
return FALSE;
*out_props = value_hash_create ();
for (iter = keys; iter && *iter; iter++) {
val = g_key_file_get_string (kf, group_name, *iter, error);
if (!val)
return FALSE;
value_hash_add_string (*out_props, *iter, val);
g_free (val);
}
return TRUE;
}
static gboolean
get_dispatcher_file (const char *file,
GHashTable **out_con_hash,
GHashTable **out_con_props,
GHashTable **out_device_props,
GHashTable **out_device_ip4_props,
GHashTable **out_device_ip6_props,
GHashTable **out_device_dhcp4_props,
GHashTable **out_device_dhcp6_props,
const char **out_vpn_ip_iface,
GHashTable **out_vpn_ip4_props,
GHashTable **out_vpn_ip6_props,
char **out_expected_iface,
char **out_action,
GHashTable **out_env,
GError **error)
{
GKeyFile *kf;
gboolean success = FALSE;
char **keys, **iter, *val;
kf = g_key_file_new ();
if (!g_key_file_load_from_file (kf, file, G_KEY_FILE_NONE, error))
return FALSE;
if (!parse_main (kf, out_con_hash, out_con_props, out_expected_iface, out_action, error))
goto out;
if (!parse_device (kf, out_device_props, error))
goto out;
if (g_key_file_has_group (kf, "ip4")) {
if (!parse_ip4 (kf, out_device_ip4_props, "ip4", error))
goto out;
}
if (g_key_file_has_group (kf, "dhcp4")) {
if (!parse_dhcp (kf, "dhcp4", out_device_dhcp4_props, error))
goto out;
}
if (g_key_file_has_group (kf, "dhcp6")) {
if (!parse_dhcp (kf, "dhcp6", out_device_dhcp4_props, error))
goto out;
}
g_assert (g_key_file_has_group (kf, "env"));
keys = g_key_file_get_keys (kf, "env", NULL, error);
*out_env = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (iter = keys; iter && *iter; iter++) {
val = g_key_file_get_string (kf, "env", *iter, error);
if (!val)
goto out;
g_hash_table_insert (*out_env,
g_strdup_printf ("%s=%s", *iter, val),
GUINT_TO_POINTER (1));
g_free (val);
}
g_strfreev (keys);
success = TRUE;
out:
g_key_file_free (kf);
return success;
}
/*******************************************/
static void
test_generic (const char *path, const char *file)
{
GHashTable *con_hash = NULL;
GHashTable *con_props = NULL;
GHashTable *device_props = NULL;
GHashTable *device_ip4_props = NULL;
GHashTable *device_ip6_props = NULL;
GHashTable *device_dhcp4_props = NULL;
GHashTable *device_dhcp6_props = NULL;
const char *vpn_ip_iface = NULL;
GHashTable *vpn_ip4_props = NULL;
GHashTable *vpn_ip6_props = NULL;
char *expected_iface = NULL;
char *action = NULL;
char *out_iface = NULL;
GHashTable *expected_env = NULL;
GError *error = NULL;
gboolean success;
char *p;
char **denv, **iter;
/* Read in the test file */
p = g_strdup_printf ("%s/%s", path, file);
success = get_dispatcher_file (p,
&con_hash,
&con_props,
&device_props,
&device_ip4_props,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props,
&vpn_ip_iface,
&vpn_ip4_props,
&vpn_ip6_props,
&expected_iface,
&action,
&expected_env,
&error);
g_free (p);
g_assert_no_error (error);
g_assert (success);
/* Get the environment from the dispatcher code */
denv = nm_dispatcher_utils_construct_envp (action,
con_hash,
con_props,
device_props,
device_ip4_props,
device_ip6_props,
device_dhcp4_props,
device_dhcp6_props,
vpn_ip_iface,
vpn_ip4_props,
vpn_ip6_props,
&out_iface);
/* Print out environment for now */
g_message ("\n");
for (iter = denv; iter && *iter; iter++)
g_message (" %s", *iter);
g_assert_cmpint (g_strv_length (denv), ==, g_hash_table_size (expected_env));
{
GHashTableIter k;
const char *key;
g_hash_table_iter_init (&k, expected_env);
while (g_hash_table_iter_next (&k, (gpointer) &key, NULL))
g_message (" %s", key);
}
/* Compare dispatcher generated env and expected env */
for (iter = denv; iter && *iter; iter++) {
gpointer foo;
foo = g_hash_table_lookup (expected_env, *iter);
if (!foo)
g_warning ("Failed to find %s in environment", *iter);
g_assert (foo);
}
g_assert_cmpstr (expected_iface, ==, out_iface);
}
/*******************************************/
static void
test_old_up (const char *path)
{
test_generic (path, "dispatcher-old-up");
}
static void
test_old_down (const char *path)
{
test_generic (path, "dispatcher-old-down");
}
static void
test_old_vpn_up (const char *path)
{
test_generic (path, "dispatcher-old-vpn-up");
}
static void
test_old_vpn_down (const char *path)
{
test_generic (path, "dispatcher-old-vpn-down");
}
/*******************************************/
#if GLIB_CHECK_VERSION(2,25,12)
typedef GTestFixtureFunc TCFunc;
#else
typedef void (*TCFunc)(void);
#endif
#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL)
int main (int argc, char **argv)
{
GTestSuite *suite;
g_assert (argc > 1);
g_test_init (&argc, &argv, NULL);
g_type_init ();
suite = g_test_get_root ();
g_test_suite_add (suite, TESTCASE (test_old_up, argv[1]));
g_test_suite_add (suite, TESTCASE (test_old_down, argv[1]));
g_test_suite_add (suite, TESTCASE (test_old_vpn_up, argv[1]));
g_test_suite_add (suite, TESTCASE (test_old_vpn_down, argv[1]));
return g_test_run ();
}

View File

@@ -631,6 +631,7 @@ libnm-glib/libnm-glib-vpn.pc
libnm-glib/Makefile
libnm-glib/tests/Makefile
callouts/Makefile
callouts/tests/Makefile
tools/Makefile
cli/Makefile
cli/src/Makefile

View File

@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2004 - 2010 Red Hat, Inc.
* Copyright (C) 2004 - 2011 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
*/
@@ -373,6 +373,72 @@ nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *setting)
nm_ip6_config_set_never_default (ip6_config, TRUE);
}
static void
dump_object_to_props (GObject *object, GHashTable *hash)
{
GParamSpec **pspecs;
guint len = 0, i;
pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), &len);
for (i = 0; i < len; i++) {
value_hash_add_object_property (hash,
pspecs[i]->name,
object,
pspecs[i]->name,
pspecs[i]->value_type);
}
g_free (pspecs);
}
static void
fill_device_props (NMDevice *device,
GHashTable *dev_hash,
GHashTable *ip4_hash,
GHashTable *ip6_hash,
GHashTable *dhcp4_hash,
GHashTable *dhcp6_hash)
{
NMIP4Config *ip4_config;
NMIP6Config *ip6_config;
NMDHCP4Config *dhcp4_config;
NMDHCP6Config *dhcp6_config;
/* If the action is for a VPN, send the VPN's IP interface instead of the device's */
value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_IP_INTERFACE, nm_device_get_ip_iface (device));
value_hash_add_str (dev_hash, NMD_DEVICE_PROPS_INTERFACE, nm_device_get_iface (device));
value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_TYPE, nm_device_get_device_type (device));
value_hash_add_uint (dev_hash, NMD_DEVICE_PROPS_STATE, nm_device_get_state (device));
value_hash_add_object_path (dev_hash, NMD_DEVICE_PROPS_PATH, nm_device_get_path (device));
ip4_config = nm_device_get_ip4_config (device);
if (ip4_config)
dump_object_to_props (G_OBJECT (ip4_config), ip4_hash);
ip6_config = nm_device_get_ip6_config (device);
if (ip6_config)
dump_object_to_props (G_OBJECT (ip6_config), ip6_hash);
dhcp4_config = nm_device_get_dhcp4_config (device);
if (dhcp4_config)
dump_object_to_props (G_OBJECT (dhcp4_config), dhcp4_hash);
dhcp6_config = nm_device_get_dhcp6_config (device);
if (dhcp6_config)
dump_object_to_props (G_OBJECT (dhcp6_config), dhcp6_hash);
}
static void
fill_vpn_props (NMIP4Config *ip4_config,
NMIP6Config *ip6_config,
GHashTable *ip4_hash,
GHashTable *ip6_hash)
{
if (ip4_config)
dump_object_to_props (G_OBJECT (ip4_config), ip4_hash);
if (ip6_config)
dump_object_to_props (G_OBJECT (ip6_config), ip6_hash);
}
static void
dispatcher_done_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
@@ -384,7 +450,9 @@ void
nm_utils_call_dispatcher (const char *action,
NMConnection *connection,
NMDevice *device,
const char *vpn_iface)
const char *vpn_iface,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config)
{
NMDBusManager *dbus_mgr;
DBusGProxy *proxy;
@@ -392,12 +460,21 @@ nm_utils_call_dispatcher (const char *action,
GHashTable *connection_hash;
GHashTable *connection_props;
GHashTable *device_props;
GHashTable *device_ip4_props;
GHashTable *device_ip6_props;
GHashTable *device_dhcp4_props;
GHashTable *device_dhcp6_props;
GHashTable *vpn_ip4_props;
GHashTable *vpn_ip6_props;
g_return_if_fail (action != NULL);
/* All actions except 'hostname' require a device */
if (strcmp (action, "hostname"))
if (strcmp (action, "hostname") != 0)
g_return_if_fail (NM_IS_DEVICE (device));
/* VPN actions require at least an IPv4 config (for now) */
if (strcmp (action, "vpn-up") == 0)
g_return_if_fail (vpn_ip4_config != NULL);
dbus_mgr = nm_dbus_manager_get ();
g_connection = nm_dbus_manager_get_connection (dbus_mgr);
@@ -426,25 +503,23 @@ nm_utils_call_dispatcher (const char *action,
}
device_props = value_hash_create ();
device_ip4_props = value_hash_create ();
device_ip6_props = value_hash_create ();
device_dhcp4_props = value_hash_create ();
device_dhcp6_props = value_hash_create ();
vpn_ip4_props = value_hash_create ();
vpn_ip6_props = value_hash_create ();
/* Hostname actions do not require a device */
if (strcmp (action, "hostname")) {
/* interface */
value_hash_add_str (device_props, NMD_DEVICE_PROPS_INTERFACE, nm_device_get_iface (device));
/* IP interface */
if (vpn_iface) {
value_hash_add_str (device_props, NMD_DEVICE_PROPS_IP_INTERFACE, vpn_iface);
} else if (nm_device_get_ip_iface (device)) {
value_hash_add_str (device_props, NMD_DEVICE_PROPS_IP_INTERFACE, nm_device_get_ip_iface (device));
}
/* type */
value_hash_add_uint (device_props, NMD_DEVICE_PROPS_TYPE, nm_device_get_device_type (device));
/* state */
value_hash_add_uint (device_props, NMD_DEVICE_PROPS_STATE, nm_device_get_state (device));
value_hash_add_object_path (device_props, NMD_DEVICE_PROPS_PATH, nm_device_get_path (device));
/* hostname actions only send the hostname */
if (strcmp (action, "hostname") != 0) {
fill_device_props (device,
device_props,
device_ip4_props,
device_ip6_props,
device_dhcp4_props,
device_dhcp6_props);
if (vpn_iface)
fill_vpn_props (vpn_ip4_config, NULL, vpn_ip4_props, vpn_ip6_props);
}
/* Do a non-blocking call, but wait for the reply, because dbus-glib
@@ -455,17 +530,30 @@ nm_utils_call_dispatcher (const char *action,
*/
dbus_g_proxy_begin_call_with_timeout (proxy, "Action",
dispatcher_done_cb,
dbus_mgr,
dbus_mgr, /* automatically unref the dbus mgr when call is done */
g_object_unref,
5000,
G_TYPE_STRING, action,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, connection_hash,
DBUS_TYPE_G_MAP_OF_VARIANT, connection_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_ip6_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, device_dhcp6_props,
G_TYPE_STRING, vpn_iface ? vpn_iface : "",
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip4_props,
DBUS_TYPE_G_MAP_OF_VARIANT, vpn_ip6_props,
G_TYPE_INVALID);
g_hash_table_destroy (connection_hash);
g_hash_table_destroy (connection_props);
g_hash_table_destroy (device_props);
g_hash_table_destroy (device_ip4_props);
g_hash_table_destroy (device_ip6_props);
g_hash_table_destroy (device_dhcp4_props);
g_hash_table_destroy (device_dhcp6_props);
g_hash_table_destroy (vpn_ip4_props);
g_hash_table_destroy (vpn_ip6_props);
}
gboolean
@@ -670,6 +758,21 @@ value_hash_add_bool (GHashTable *hash,
value_hash_add (hash, key, value);
}
void
value_hash_add_object_property (GHashTable *hash,
const char *key,
GObject *object,
const char *prop,
GType val_type)
{
GValue *value;
value = g_slice_new0 (GValue);
g_value_init (value, val_type);
g_object_get_property (object, prop, value);
value_hash_add (hash, key, value);
}
gboolean
nm_utils_do_sysctl (const char *path, const char *value)
{

View File

@@ -45,7 +45,9 @@ void nm_utils_merge_ip6_config (NMIP6Config *ip6_config, NMSettingIP6Config *set
void nm_utils_call_dispatcher (const char *action,
NMConnection *connection,
NMDevice *device,
const char *vpn_iface);
const char *vpn_iface,
NMIP4Config *vpn_ip4_config,
NMIP6Config *vpn_ip6_config);
gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
gboolean nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
@@ -72,6 +74,12 @@ void value_hash_add_bool (GHashTable *hash,
const char *key,
gboolean val);
void value_hash_add_object_property (GHashTable *hash,
const char *key,
GObject *object,
const char *prop,
GType val_type);
gboolean nm_utils_do_sysctl (const char *path, const char *value);
gboolean nm_utils_get_proc_sys_net_value (const char *path,

View File

@@ -1384,7 +1384,7 @@ handle_dhcp_lease_change (NMDevice *device, gboolean ipv6)
nm_dhcp_client_foreach_option (priv->dhcp6_client,
dhcp6_add_option_cb,
priv->dhcp6_config);
nm_utils_call_dispatcher ("dhcp6-change", connection, device, NULL);
nm_utils_call_dispatcher ("dhcp6-change", connection, device, NULL, NULL, NULL);
} else {
nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.",
nm_device_get_ip_iface (device));
@@ -1409,7 +1409,7 @@ handle_dhcp_lease_change (NMDevice *device, gboolean ipv6)
nm_dhcp_client_foreach_option (priv->dhcp4_client,
dhcp4_add_option_cb,
priv->dhcp4_config);
nm_utils_call_dispatcher ("dhcp4-change", connection, device, NULL);
nm_utils_call_dispatcher ("dhcp4-change", connection, device, NULL, NULL, NULL);
} else {
nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv4 config in response to DHCP event.",
nm_device_get_ip_iface (device));
@@ -3781,7 +3781,7 @@ nm_device_state_changed (NMDevice *device,
case NM_DEVICE_STATE_ACTIVATED:
nm_log_info (LOGD_DEVICE, "Activation (%s) successful, device activated.",
nm_device_get_iface (device));
nm_utils_call_dispatcher ("up", nm_act_request_get_connection (req), device, NULL);
nm_utils_call_dispatcher ("up", nm_act_request_get_connection (req), device, NULL, NULL, NULL);
break;
case NM_DEVICE_STATE_FAILED:
nm_log_warn (LOGD_DEVICE, "Activation (%s) failed.", nm_device_get_iface (device));
@@ -3796,7 +3796,7 @@ nm_device_state_changed (NMDevice *device,
}
if (old_state == NM_DEVICE_STATE_ACTIVATED)
nm_utils_call_dispatcher ("down", nm_act_request_get_connection (req), device, NULL);
nm_utils_call_dispatcher ("down", nm_act_request_get_connection (req), device, NULL, NULL, NULL);
/* Dispose of the cached activation request */
if (req)

View File

@@ -238,7 +238,7 @@ _set_hostname (NMPolicy *policy,
}
if (nm_policy_set_system_hostname (policy->cur_hostname, msg))
nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL);
nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL, NULL, NULL);
}
static void

View File

@@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2005 - 2010 Red Hat, Inc.
* Copyright (C) 2005 - 2011 Red Hat, Inc.
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
@@ -140,7 +140,9 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
nm_utils_call_dispatcher ("vpn-up",
priv->connection,
priv->parent_dev,
ip_iface);
ip_iface,
priv->ip4_config,
NULL);
break;
case NM_VPN_CONNECTION_STATE_FAILED:
case NM_VPN_CONNECTION_STATE_DISCONNECTED:
@@ -148,7 +150,9 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection,
nm_utils_call_dispatcher ("vpn-down",
priv->connection,
priv->parent_dev,
ip_iface);
ip_iface,
NULL,
NULL);
}
break;
default: