2007-08-12 Dan Williams <dcbw@redhat.com>
authorDan Williams <dcbw@redhat.com>
Sun, 12 Aug 2007 15:21:15 +0000 (15:21 +0000)
committerDan Williams <dcbw@redhat.com>
Sun, 12 Aug 2007 15:21:15 +0000 (15:21 +0000)
* Makefile.am
  configure.in
  callouts/Makefile.am
  callouts/nm-dhcp-client-action.c
  callouts/nm-dhcp-client.conf
- Add dhclient-executed callout that takes the place of dhclient-script
and dhcdbd, pushing DHCP options out to the system bus as a signal that
NM then listens for

git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2664 4912f4e0-d625-0410-9fb7-b9a5a253dbdc

ChangeLog
Makefile.am
callouts/Makefile.am [new file with mode: 0644]
callouts/nm-dhcp-client-action.c [new file with mode: 0644]
callouts/nm-dhcp-client.conf [new file with mode: 0644]
configure.in

index 02dd65f..4545832 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-08-12  Dan Williams  <dcbw@redhat.com>
+
+       * Makefile.am
+         configure.in
+         callouts/Makefile.am
+         callouts/nm-dhcp-client-action.c
+         callouts/nm-dhcp-client.conf
+               - Add dhclient-executed callout that takes the place of dhclient-script
+               and dhcdbd, pushing DHCP options out to the system bus as a signal that
+               NM then listens for
+
 2007-08-09  Tambet Ingo  <tambet@gmail.com>
 
        [Based on patch by Helmut Schaa <hschaa@suse.de>]
index 8e8996f..7a72814 100644 (file)
@@ -10,7 +10,8 @@ SUBDIRS =                             \
           po                           \
           man                          \
           include                      \
-          introspection
+          introspection        \
+          callouts
 
 EXTRA_DIST =                           \
        CONTRIBUTING                    \
diff --git a/callouts/Makefile.am b/callouts/Makefile.am
new file mode 100644 (file)
index 0000000..fbb5652
--- /dev/null
@@ -0,0 +1,22 @@
+dbusservicedir = $(DBUS_SYS_DIR)
+dbusservice_DATA = nm-dhcp-client.conf
+
+calloutdir = $(sysconfdir)/NetworkManager/callouts
+
+callout_PROGRAMS = nm-dhcp-client.action
+
+nm_dhcp_client_action_SOURCES = \
+       nm-dhcp-client-action.c
+
+nm_dhcp_client_action_CPPFLAGS =               \
+       $(DBUS_CFLAGS)                                          \
+       $(GTHREAD_CFLAGS)                                       \
+       -DDBUS_API_SUBJECT_TO_CHANGE            \
+       -DG_DISABLE_DEPRECATED                          \
+       -DSYSCONFDIR=\"$(sysconfdir)\"
+
+nm_dhcp_client_action_LDADD =  \
+                       $(DBUS_LIBS)            \
+                       $(GTHREAD_LIBS)
+
+EXTRA_DIST = $(dbusservice_DATA)
diff --git a/callouts/nm-dhcp-client-action.c b/callouts/nm-dhcp-client-action.c
new file mode 100644 (file)
index 0000000..9e36df1
--- /dev/null
@@ -0,0 +1,317 @@
+/* NetworkManager -- Network link manager
+ *
+ * Dan Williams <dcbw@redhat.com>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2007 Red Hat, Inc.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib.h>
+
+#define NM_DHCP_CLIENT_DBUS_SERVICE "org.freedesktop.nm_dhcp_client"
+#define NM_DHCP_CLIENT_DBUS_IFACE   "org.freedesktop.nm_dhcp_client"
+
+/**
+ * Start a dict in a dbus message.  Should be paired with a call to
+ * {@link wpa_dbus_dict_close_write}.
+ *
+ * @param iter A valid dbus message iterator
+ * @param iter_dict (out) A dict iterator to pass to further dict functions
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
+                                    DBusMessageIter *iter_dict)
+{
+       dbus_bool_t result;
+
+       if (!iter || !iter_dict)
+               return FALSE;
+
+       result = dbus_message_iter_open_container(
+               iter,
+               DBUS_TYPE_ARRAY,
+               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING
+               DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+               iter_dict);
+       return result;
+}
+
+/**
+ * End a dict element in a dbus message.  Should be paired with
+ * a call to {@link wpa_dbus_dict_open_write}.
+ *
+ * @param iter valid dbus message iterator, same as passed to
+ *    wpa_dbus_dict_open_write()
+ * @param iter_dict a dbus dict iterator returned from
+ *    {@link wpa_dbus_dict_open_write}
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
+                                     DBusMessageIter *iter_dict)
+{
+       if (!iter || !iter_dict)
+               return FALSE;
+
+       return dbus_message_iter_close_container(iter, iter_dict);
+}
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_start(
+       DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+       const char *key, const int value_type)
+{
+       if (!dbus_message_iter_open_container(iter_dict,
+                                             DBUS_TYPE_DICT_ENTRY, NULL,
+                                             iter_dict_entry))
+               return FALSE;
+
+       if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
+                                           &key))
+               return FALSE;
+
+       return TRUE;
+}
+
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_end(
+       DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+       DBusMessageIter *iter_dict_val)
+{
+       if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
+               return FALSE;
+       if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry))
+               return FALSE;
+
+       return TRUE;
+}
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
+       DBusMessageIter *iter_dict, const char *key,
+       const char *value, const dbus_uint32_t value_len)
+{
+       DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
+       dbus_uint32_t i;
+
+       if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
+                                           key, DBUS_TYPE_ARRAY))
+               return FALSE;
+
+       if (!dbus_message_iter_open_container(&iter_dict_entry,
+                                             DBUS_TYPE_VARIANT,
+                                             DBUS_TYPE_ARRAY_AS_STRING
+                                             DBUS_TYPE_BYTE_AS_STRING,
+                                             &iter_dict_val))
+               return FALSE;
+
+       if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
+                                             DBUS_TYPE_BYTE_AS_STRING,
+                                             &iter_array))
+               return FALSE;
+
+       for (i = 0; i < value_len; i++) {
+               if (!dbus_message_iter_append_basic(&iter_array,
+                                                   DBUS_TYPE_BYTE,
+                                                   &(value[i])))
+                       return FALSE;
+       }
+
+       if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
+               return FALSE;
+
+       if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
+                                         &iter_dict_val))
+               return FALSE;
+
+       return TRUE;
+}
+
+/**
+ * Add a byte array entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    {@link wpa_dbus_dict_open_write}
+ * @param key The key of the dict item
+ * @param value The byte array
+ * @param value_len The length of the byte array, in bytes
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
+                                           const char *key,
+                                           const char *value,
+                                           const dbus_uint32_t value_len)
+{
+       if (!key)
+               return FALSE;
+       if (!value && (value_len != 0))
+               return FALSE;
+       return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
+                                                  value_len);
+}
+
+
+dbus_bool_t
+build_message (DBusMessage * message)
+{
+       char ** env = NULL;
+       char ** item;
+       dbus_bool_t success = FALSE;
+       DBusMessageIter iter, iter_dict;
+
+       dbus_message_iter_init_append (message, &iter);
+       if (!wpa_dbus_dict_open_write (&iter, &iter_dict))
+               goto out;
+
+       /* List environment and format for dbus dict */
+       env = g_listenv ();
+       for (item = env; *item; item++) {
+               const char * val = g_getenv (*item);
+
+               /* Value passed as a byte array rather than a string, because there are
+                * no character encoding guarantees with DHCP, and D-Bus requires
+                * strings to be UTF-8.
+                */
+               if (!wpa_dbus_dict_append_byte_array (&iter_dict,
+                                                     *item,
+                                                     val ? val : "\0",
+                                                     val ? strlen (val) : 1)) {
+                       fprintf (stderr, "Error: failed to add item '%s' to signal\n",
+                                *item);
+                       goto out;
+               }
+       }
+
+       if (!wpa_dbus_dict_close_write (&iter, &iter_dict))
+               goto out;
+
+       success = TRUE;
+
+out:
+       g_strfreev (env);
+       return success;
+}
+
+DBusConnection *
+dbus_init (void)
+{
+       DBusConnection * connection;
+       DBusError error;
+       int ret, flags;
+
+       dbus_connection_set_change_sigpipe (TRUE);
+
+       dbus_error_init (&error);
+       connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+       if (dbus_error_is_set (&error)) {
+               fprintf (stderr, "Error: could not get the system bus.  Make sure "
+                           "the message bus daemon is running!  Message: (%s) %s\n",
+                           error.name,
+                           error.message);
+               goto error;
+       }
+
+       dbus_connection_set_exit_on_disconnect (connection, FALSE);
+
+#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR < 60)
+       flags = DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT;
+#else
+       flags = DBUS_NAME_FLAG_DO_NOT_QUEUE;
+#endif
+
+       dbus_error_init (&error);
+       ret = dbus_bus_request_name (connection,
+                                    NM_DHCP_CLIENT_DBUS_SERVICE,
+                                    flags,
+                                    &error);
+       if (dbus_error_is_set (&error)) {
+               fprintf (stderr, "Error: Could not acquire the NM DHCP client service. "
+                           "Message: (%s) %s\n",
+                           error.name,
+                           error.message);
+               goto error;
+       }
+
+       if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+               fprintf (stderr, "Error: Could not acquire the NM DHCP client service "
+                        "as it is already taken.  Return: %d\n",
+                        ret);
+               goto error;
+       }
+
+       return connection;
+
+error:
+       if (dbus_error_is_set (&error))
+               dbus_error_free (&error);
+       if (connection)
+               dbus_connection_unref (connection);
+       return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+       DBusConnection * connection;
+       DBusMessage * message;
+       dbus_bool_t result;
+
+       g_type_init ();
+
+       /* Get a connection to the system bus */
+       connection = dbus_init ();
+       if (connection == NULL)
+               exit (1);
+
+       message = dbus_message_new_signal ("/", NM_DHCP_CLIENT_DBUS_IFACE, "Event");
+       if (message == NULL) {
+               fprintf (stderr, "Error: Not enough memory to send DHCP Event signal.\n");
+               exit (1);
+       }
+
+       /* Dump environment variables into the message */
+       result = build_message (message);
+       if (result == FALSE) {
+               fprintf (stderr, "Error: Not enough memory to send DHCP Event signal.\n");
+               exit (1);
+       }
+
+       /* queue the message */
+       result = dbus_connection_send (connection, message, NULL);
+       if (!result) {
+               fprintf (stderr, "Error: Could not send send DHCP Event signal.\n");
+               exit (1);
+       }
+       dbus_message_unref (message);
+
+       /* Send out the message */
+       dbus_connection_flush (connection);
+
+       return 0;
+}
+
diff --git a/callouts/nm-dhcp-client.conf b/callouts/nm-dhcp-client.conf
new file mode 100644 (file)
index 0000000..515a110
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+        <policy user="root">
+                <allow own="org.freedesktop.nm_dhcp_client"/>
+               <allow send_interface="org.freedesktop.nm_dhcp_client"/>
+        </policy>
+        <policy context="default">
+                <deny own="org.freedesktop.nm_dhcp_client"/>
+               <deny send_interface="org.freedesktop.nm_dhcp_client"/>
+        </policy>
+</busconfig>
+
index 3d5d799..2d83cc5 100644 (file)
@@ -323,6 +323,7 @@ libnm-util/libnm-util.pc
 libnm-util/Makefile
 libnm-glib/libnm-glib.pc
 libnm-glib/Makefile
+callouts/Makefile
 dispatcher-daemon/Makefile
 gnome/Makefile
 gnome/libnm_glib/libnm_glib.pc