From 8d19530da2942d0cd8cdbdf4055e26cf61d51cee Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 18 Sep 2008 15:29:59 +0000 Subject: [PATCH] 2008-09-18 Dan Williams Patch from Alexander Sack * configure.in system-settings/plugins/Makefile.am system-settings/plugins/ifupdown/Makefile.am system-settings/plugins/ifupdown/interface_parser.c system-settings/plugins/ifupdown/interface_parser.h system-settings/plugins/ifupdown/nm-ifupdown-connection.c system-settings/plugins/ifupdown/nm-ifupdown-connection.h system-settings/plugins/ifupdown/parser.c system-settings/plugins/ifupdown/parser.h system-settings/plugins/ifupdown/plugin.c system-settings/plugins/ifupdown/plugin.h - Implement a Debian/Ubuntu legacy network configuration plugin (gnome.org #551941) git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4078 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 18 + configure.in | 1 + system-settings/plugins/Makefile.am | 4 + system-settings/plugins/ifupdown/Makefile.am | 31 + .../plugins/ifupdown/interface_parser.c | 214 +++++++ .../plugins/ifupdown/interface_parser.h | 57 ++ .../plugins/ifupdown/nm-ifupdown-connection.c | 263 +++++++++ .../plugins/ifupdown/nm-ifupdown-connection.h | 55 ++ system-settings/plugins/ifupdown/parser.c | 529 ++++++++++++++++++ system-settings/plugins/ifupdown/parser.h | 33 ++ system-settings/plugins/ifupdown/plugin.c | 333 +++++++++++ system-settings/plugins/ifupdown/plugin.h | 53 ++ 12 files changed, 1591 insertions(+) create mode 100644 system-settings/plugins/ifupdown/Makefile.am create mode 100644 system-settings/plugins/ifupdown/interface_parser.c create mode 100644 system-settings/plugins/ifupdown/interface_parser.h create mode 100644 system-settings/plugins/ifupdown/nm-ifupdown-connection.c create mode 100644 system-settings/plugins/ifupdown/nm-ifupdown-connection.h create mode 100644 system-settings/plugins/ifupdown/parser.c create mode 100644 system-settings/plugins/ifupdown/parser.h create mode 100644 system-settings/plugins/ifupdown/plugin.c create mode 100644 system-settings/plugins/ifupdown/plugin.h diff --git a/ChangeLog b/ChangeLog index 131a4d88c7..28dd923a2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-09-18 Dan Williams + + Patch from Alexander Sack + + * configure.in + system-settings/plugins/Makefile.am + system-settings/plugins/ifupdown/Makefile.am + system-settings/plugins/ifupdown/interface_parser.c + system-settings/plugins/ifupdown/interface_parser.h + system-settings/plugins/ifupdown/nm-ifupdown-connection.c + system-settings/plugins/ifupdown/nm-ifupdown-connection.h + system-settings/plugins/ifupdown/parser.c + system-settings/plugins/ifupdown/parser.h + system-settings/plugins/ifupdown/plugin.c + system-settings/plugins/ifupdown/plugin.h + - Implement a Debian/Ubuntu legacy network configuration plugin + (gnome.org #551941) + 2008-09-18 Dan Williams Implement support for honoring configured and automatic hostnames, and for diff --git a/configure.in b/configure.in index bd86fc229d..e63b313ccf 100644 --- a/configure.in +++ b/configure.in @@ -489,6 +489,7 @@ tools/Makefile system-settings/Makefile system-settings/src/Makefile system-settings/plugins/Makefile +system-settings/plugins/ifupdown/Makefile system-settings/plugins/ifcfg-fedora/Makefile system-settings/plugins/ifcfg-suse/Makefile system-settings/plugins/keyfile/Makefile diff --git a/system-settings/plugins/Makefile.am b/system-settings/plugins/Makefile.am index 9beea07a95..84a982570f 100644 --- a/system-settings/plugins/Makefile.am +++ b/system-settings/plugins/Makefile.am @@ -11,3 +11,7 @@ endif if TARGET_MANDRIVA SUBDIRS+=ifcfg-fedora endif + +if TARGET_DEBIAN +SUBDIRS+=ifupdown +endif diff --git a/system-settings/plugins/ifupdown/Makefile.am b/system-settings/plugins/ifupdown/Makefile.am new file mode 100644 index 0000000000..c6948ada47 --- /dev/null +++ b/system-settings/plugins/ifupdown/Makefile.am @@ -0,0 +1,31 @@ + +INCLUDES = \ + -I${top_srcdir}/src \ + $(NULL) + +pkglib_LTLIBRARIES = libnm-settings-plugin-ifupdown.la + +libnm_settings_plugin_ifupdown_la_SOURCES = \ + interface_parser.c interface_parser.h \ + nm-ifupdown-connection.c nm-ifupdown-connection.h \ + parser.c parser.h \ + plugin.c plugin.h \ + $(NULL) + +libnm_settings_plugin_ifupdown_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ + $(DBUS_CFLAGS) \ + -DG_DISABLE_DEPRECATED \ + -I${top_srcdir}/system-settings/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm-glib \ + -I$(top_srcdir)/libnm-util \ + -DSYSCONFDIR=\"$(sysconfdir)\" + +libnm_settings_plugin_ifupdown_la_LDFLAGS = -module -avoid-version +libnm_settings_plugin_ifupdown_la_LIBADD = \ + $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ + $(top_builddir)/libnm-util/libnm-util.la + diff --git a/system-settings/plugins/ifupdown/interface_parser.c b/system-settings/plugins/ifupdown/interface_parser.c new file mode 100644 index 0000000000..941c314599 --- /dev/null +++ b/system-settings/plugins/ifupdown/interface_parser.c @@ -0,0 +1,214 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* NetworkManager -- Network link manager + * + * Tom Parker + * + * 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 2004 Tom Parker + */ + + +#include "interface_parser.h" +#include "NetworkManagerUtils.h" +#include +#include +#include +#include "nm-utils.h" + +if_block* first; +if_block* last; + +if_data* last_data; + +void add_block(const char *type, const char* name) +{ + if_block *ret = (if_block*)calloc(1,sizeof(struct _if_block)); + ret->name = g_strdup(name); + ret->type = g_strdup(type); + if (first == NULL) + first = last = ret; + else + { + last->next = ret; + last = ret; + } + last_data = NULL; + //printf("added block '%s' with type '%s'\n",name,type); +} + +void add_data(const char *key,const char *data) +{ + if_data *ret; + + // Check if there is a block where we can attach our data + if (first == NULL) + return; + + ret = (if_data*) calloc(1,sizeof(struct _if_data)); + ret->key = g_strdup(key); + ret->data = g_strdup(data); + + if (last->info == NULL) + { + last->info = ret; + last_data = ret; + } + else + { + last_data->next = ret; + last_data = last_data->next; + } + //printf("added data '%s' with key '%s'\n",data,key); +} + +#define SPACE_OR_TAB(string,ret) {ret = strchr(string,' ');ret=(ret == NULL?strchr(string,'\t'):ret);} + +void ifparser_init(void) +{ + FILE *inp = fopen(ENI_INTERFACES_FILE, "r"); + int ret = 0; + char *line; + char *space; + char rline[255]; + + if (inp == NULL) + { + nm_warning ("Error: Can't open %s\n", ENI_INTERFACES_FILE); + return; + } + first = last = NULL; + while(1) + { + line = space = NULL; + ret = fscanf(inp,"%255[^\n]\n",rline); + if (ret == EOF) + break; + // If the line did not match, skip it + if (ret == 0) { + fgets(rline, 255, inp); + continue; + } + + line = rline; + while(line[0] == ' ') + line++; + if (line[0]=='#' || line[0]=='\0') + continue; + + SPACE_OR_TAB(line,space) + if (space == NULL) + { + nm_warning ("Error: Can't parse interface line '%s'\n",line); + continue; + } + space[0] = '\0'; + + // There are four different stanzas: + // iface, mapping, auto and allow-*. Create a block for each of them. + if (strcmp(line,"iface")==0) + { + char *space2 = strchr(space+1,' '); + if (space2 == NULL) + { + nm_warning ("Error: Can't parse iface line '%s'\n",space+1); + continue; + } + space2[0]='\0'; + add_block(line,space+1); + + if (space2[1]!='\0') + { + space = strchr(space2+1,' '); + if (space == NULL) + { + nm_warning ("Error: Can't parse data '%s'\n",space2+1); + continue; + } + space[0] = '\0'; + add_data(space2+1,space+1); + } + } + else if (strcmp(line,"auto")==0) + add_block(line,space+1); + else if (strcmp(line,"mapping")==0) + add_block(line,space+1); + else if (strncmp(line,"allow-",6)==0) + add_block(line,space+1); + else + add_data(line,space+1); + + //printf("line: '%s' ret=%d\n",rline,ret); + } + fclose(inp); +} + +void _destroy_data(if_data *ifd) +{ + if (ifd == NULL) + return; + _destroy_data(ifd->next); + free(ifd->key); + free(ifd->data); + free(ifd); + return; +} + +void _destroy_block(if_block* ifb) +{ + if (ifb == NULL) + return; + _destroy_block(ifb->next); + _destroy_data(ifb->info); + free(ifb->name); + free(ifb->type); + free(ifb); + return; +} + +void ifparser_destroy(void) +{ + _destroy_block(first); + first = last = NULL; +} + +if_block *ifparser_getfirst(void) +{ + return first; +} + +if_block *ifparser_getif(const char* iface) +{ + if_block *curr = first; + while(curr!=NULL) + { + if (strcmp(curr->type,"iface")==0 && strcmp(curr->name,iface)==0) + return curr; + curr = curr->next; + } + return NULL; +} + +const char *ifparser_getkey(if_block* iface, const char *key) +{ + if_data *curr = iface->info; + while(curr!=NULL) + { + if (strcmp(curr->key,key)==0) + return curr->data; + curr = curr->next; + } + return NULL; +} diff --git a/system-settings/plugins/ifupdown/interface_parser.h b/system-settings/plugins/ifupdown/interface_parser.h new file mode 100644 index 0000000000..43ad532162 --- /dev/null +++ b/system-settings/plugins/ifupdown/interface_parser.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ +/* NetworkManager -- Network link manager + * + * Tom Parker + * + * 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 2004 Tom Parker + */ + + +#ifndef _INTERFACE_PARSER_H +#define _INTERFACE_PARSER_H + +#include "config.h" + +#define ENI_INTERFACES_FILE "/etc/network/interfaces" + +typedef struct _if_data +{ + char *key; + char *data; + struct _if_data *next; +} if_data; + +typedef struct _if_block +{ + char *type; + char *name; + if_data *info; + struct _if_block *next; +} if_block; + +void ifparser_init(void); +void ifparser_destroy(void); + +if_block *ifparser_getif(const char* iface); +if_block *ifparser_getfirst(void); +const char *ifparser_getkey(if_block* iface, const char *key); + +void add_block(const char *type, const char* name); +void add_data(const char *key,const char *data); +void _destroy_data(if_data *ifd); +void _destroy_block(if_block* ifb); +#endif diff --git a/system-settings/plugins/ifupdown/nm-ifupdown-connection.c b/system-settings/plugins/ifupdown/nm-ifupdown-connection.c new file mode 100644 index 0000000000..08b0d3625a --- /dev/null +++ b/system-settings/plugins/ifupdown/nm-ifupdown-connection.c @@ -0,0 +1,263 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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,2008 Canonical Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "nm-ifupdown-connection.h" +#include "parser.h" + +G_DEFINE_TYPE (NMIfupdownConnection, + nm_ifupdown_connection, + NM_TYPE_EXPORTED_CONNECTION) + +#define NM_IFUPDOWN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionPrivate)) + +typedef struct { + if_block *ifblock; +} NMIfupdownConnectionPrivate; + +enum { + PROP_ZERO, + PROP_IFBLOCK, + _PROP_END, +}; + + +static void +get_secrets (NMExportedConnection *exported, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context); + + +NMIfupdownConnection* +nm_ifupdown_connection_new (if_block *block) +{ + g_return_val_if_fail (block != NULL, NULL); + + return (NMIfupdownConnection *) g_object_new (NM_TYPE_IFUPDOWN_CONNECTION, + NM_IFUPDOWN_CONNECTION_IFBLOCK, block, + NULL); +} + +static GHashTable * +get_settings (NMExportedConnection *exported) +{ + return nm_connection_to_hash (nm_exported_connection_get_connection (exported)); +} + +static gboolean +update (NMExportedConnection *exported, + GHashTable *new_settings, + GError **err) +{ + g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, + "%s.%d - %s", __FILE__, __LINE__, "connection update not supported (read-only)."); + return FALSE; +} + +static gboolean +delete (NMExportedConnection *exported, GError **err) +{ + g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, + "%s", "ifupdown - connection delete not supported (read-only)."); + return FALSE; +} + +/* GObject */ +static void +nm_ifupdown_connection_init (NMIfupdownConnection *connection) +{ +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMIfupdownConnectionPrivate *priv; + NMConnection *wrapped = nm_connection_new(); + + object = G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->constructor (type, n_construct_params, construct_params); + g_return_val_if_fail (object, NULL); + + priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); + if (!priv) { + nm_warning ("%s.%d - no private instance.", __FILE__, __LINE__); + goto err; + } + if (!priv->ifblock) { + nm_warning ("(ifupdown) ifblock not provided to constructor."); + goto err; + } + + g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); + g_object_unref (wrapped); + + return object; + + err: + g_object_unref (object); + return NULL; +} + +static void +finalize (GObject *object) +{ + G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMIfupdownConnectionPrivate *priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); + g_return_if_fail (priv); + + switch (prop_id) { + case PROP_IFBLOCK: + priv->ifblock = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMIfupdownConnectionPrivate *priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); + g_return_if_fail (priv); + + switch (prop_id) { + case PROP_IFBLOCK: + g_value_set_pointer (value, priv->ifblock); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_ifupdown_connection_class_init (NMIfupdownConnectionClass *ifupdown_connection_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ifupdown_connection_class); + NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (ifupdown_connection_class); + + g_type_class_add_private (ifupdown_connection_class, sizeof (NMIfupdownConnectionPrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + connection_class->get_settings = get_settings; + connection_class->update = update; + connection_class->delete = delete; + connection_class->get_secrets = get_secrets; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_IFBLOCK, + g_param_spec_pointer (NM_IFUPDOWN_CONNECTION_IFBLOCK, + "ifblock", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +get_secrets (NMExportedConnection *exported, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context) +{ + NMConnection *connection; + GError *error = NULL; + GHashTable *settings = NULL; + GHashTable *secrets = NULL; + NMSetting *setting; + + PLUGIN_PRINT ("SCPlugin-Ifupdown", "get_secrets for setting_name:'%s')", setting_name); + + connection = nm_exported_connection_get_connection (exported); + setting = nm_connection_get_setting_by_name (connection, setting_name); + + if (!setting) { + g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_INVALID_CONNECTION, + "%s.%d - Connection didn't have requested setting '%s'.", + __FILE__, __LINE__, setting_name); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "%s", error->message); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + settings = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) g_hash_table_destroy); + + if (!settings) { + g_set_error (&error, NM_SETTINGS_ERROR, 0, + "%s.%d - failed to hash setting (OOM?)", + __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + if (!strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME)) { + secrets = nm_setting_to_hash (setting); + if (secrets) { + g_hash_table_insert(settings, g_strdup(setting_name), secrets); + dbus_g_method_return (context, settings); + } else { + g_set_error (&error, NM_SETTINGS_ERROR, 0, + "%s.%d - nm_setting_to_hash failed (OOM?)", + __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + g_hash_table_destroy (settings); + } + } else { + g_set_error (&error, NM_SETTING_WIRELESS_SECURITY_ERROR, 1, + "%s.%d - security setting name not supported '%s'.", + __FILE__, __LINE__, setting_name); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "%s", error->message); + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} diff --git a/system-settings/plugins/ifupdown/nm-ifupdown-connection.h b/system-settings/plugins/ifupdown/nm-ifupdown-connection.h new file mode 100644 index 0000000000..96dc233781 --- /dev/null +++ b/system-settings/plugins/ifupdown/nm-ifupdown-connection.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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 2008 Canonical Ltd. + */ + +#ifndef NM_IFUPDOWN_CONNECTION_H +#define NM_IFUPDOWN_CONNECTION_H + +#include +#include "interface_parser.h" + +G_BEGIN_DECLS + +#define NM_TYPE_IFUPDOWN_CONNECTION (nm_ifupdown_connection_get_type ()) +#define NM_IFUPDOWN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnection)) +#define NM_IFUPDOWN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionClass)) +#define NM_IS_IFUPDOWN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFUPDOWN_CONNECTION)) +#define NM_IS_IFUPDOWN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IFUPDOWN_CONNECTION)) +#define NM_IFUPDOWN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionClass)) + +#define NM_IFUPDOWN_CONNECTION_IFBLOCK "ifblock" + +typedef struct { + NMExportedConnection parent; +} NMIfupdownConnection; + +typedef struct { + NMExportedConnectionClass parent; +} NMIfupdownConnectionClass; + +GType nm_ifupdown_connection_get_type (void); + +NMIfupdownConnection *nm_ifupdown_connection_new (if_block *block); + +G_END_DECLS + +#endif /* NM_IFUPDOWN_CONNECTION_H */ diff --git a/system-settings/plugins/ifupdown/parser.c b/system-settings/plugins/ifupdown/parser.c new file mode 100644 index 0000000000..159bf05d2f --- /dev/null +++ b/system-settings/plugins/ifupdown/parser.c @@ -0,0 +1,529 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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 2008 Canonical Ltd. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parser.h" +#include "plugin.h" +#include "sha1.h" + + +#define WPA_PMK_LEN 32 + +#include "parser.h" + +static const gchar* +_ifupdownplugin_guess_connection_type (if_block *block) +{ + if_data *curr = block->info; + const gchar* ret_type = NULL; + const gchar* value = ifparser_getkey(block, "inet"); + if(value && !strcmp("ppp", value)) { + ret_type = NM_SETTING_PPP_SETTING_NAME; + } + + while(!ret_type && curr) { + if(!strncmp("wireless-", curr->key, strlen("wireless-")) || + !strncmp("wpa-", curr->key, strlen("wpa-"))) { + ret_type = NM_SETTING_WIRELESS_SETTING_NAME; + } + curr = curr->next; + } + + if(!ret_type) + ret_type = NM_SETTING_WIRED_SETTING_NAME; + + PLUGIN_PRINT("SCPluginIfupdown", + "guessed connection type (%s) = %s", + block->name, ret_type); + return ret_type; +} + +/* + * utils_bin2hexstr + * + * Convert a byte-array into a hexadecimal string. + * + * Code originally by Alex Larsson and + * copyright Red Hat, Inc. under terms of the LGPL. + * + */ +static char * +utils_bin2hexstr (const char *bytes, int len, int final_len) +{ + static char hex_digits[] = "0123456789abcdef"; + char * result; + int i; + + g_return_val_if_fail (bytes != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len < 256, NULL); /* Arbitrary limit */ + + result = g_malloc0 (len * 2 + 1); + for (i = 0; i < len; i++) + { + result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; + result[2*i+1] = hex_digits[bytes[i] & 0xf]; + } + /* Cut converted key off at the correct length for this cipher type */ + if (final_len > -1) + result[final_len] = '\0'; + + return result; +} + + +struct _Mapping { + const gchar *domain; + const gpointer target; +}; + +static gpointer +map_by_mapping(struct _Mapping *mapping, const gchar *key) +{ + struct _Mapping *curr = mapping; + while(curr->domain) { + if(!strcmp(curr->domain, key)) + return curr->target; + curr++; + } + return NULL; +} + +static void +update_wireless_setting_from_if_block(NMConnection *connection, + if_block *block) +{ + gint wpa_l= strlen("wpa-"); + gint wireless_l= strlen("wireless-"); + + if_data *curr = block->info; + const gchar* value = ifparser_getkey (block, "inet"); + struct _Mapping mapping[] = { + {"ssid", "ssid"}, + { NULL, NULL} + }; + + NMSettingWireless *wireless_setting = NULL; + + if(value && !strcmp("ppp", value)) { + return; + } + + PLUGIN_PRINT ("SCPlugin-Ifupdown", "update wireless settings (%s).", block->name); + wireless_setting = NM_SETTING_WIRELESS(nm_setting_wireless_new()); + + while(curr) { + if(strlen(curr->key) > wireless_l && + !strncmp("wireless-", curr->key, wireless_l)) { + const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "wireless setting key: %s='%s'", + newkey, curr->data); + g_object_set(wireless_setting, + newkey, curr->data, + NULL); + } else if(strlen(curr->key) > wpa_l && + !strncmp("wpa-", curr->key, wpa_l)) { + const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l); + + if(newkey && !strcmp("ssid", newkey)) { + gint len = strlen(curr->data); + wireless_setting->ssid = g_byte_array_sized_new (len); + g_byte_array_append (wireless_setting->ssid, (const guint8 *) curr->data, len); + PLUGIN_PRINT("SCPlugin-Ifupdown", "setting wpa ssid = %d", wireless_setting->ssid->len); + } else if(newkey) { + + g_object_set(wireless_setting, + newkey, curr->data, + NULL); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "setting wpa newkey(%s)=data(%s)", newkey, curr->data); + } + } + curr = curr->next; + } + nm_connection_add_setting(connection, (NMSetting*) wireless_setting); +} + +typedef gchar* (*IfupdownStrDupeFunc) (gpointer value, gpointer data); +typedef gpointer (*IfupdownStrToTypeFunc) (const gchar* value); + +static char* +normalize_dupe (gpointer value, gpointer data) { + return g_strdup(value); +} + +static char* +normalize_tolower (gpointer value, gpointer data) { + return g_ascii_strdown(value, -1); +} + +static char *normalize_psk (gpointer value, gpointer data) { + NMConnection *connection = data; + NMSettingWireless *s_wireless = + NM_SETTING_WIRELESS(nm_connection_get_setting(connection, NM_TYPE_SETTING_WIRELESS)); + gchar *normalized; + if (strlen (value) == 64) { + normalized = g_strdup (value); + } else { + /* passphrase */ + unsigned char *buf = g_malloc0 (WPA_PMK_LEN * 2); + pbkdf2_sha1 (value, (char *) s_wireless->ssid->data, s_wireless->ssid->len, 4096, buf, WPA_PMK_LEN); + normalized = utils_bin2hexstr ((const char *) buf, WPA_PMK_LEN, WPA_PMK_LEN * 2); + g_free (buf); + } + return normalized; +} + +static gpointer +string_to_glist_of_strings(const gchar* data) +{ + GSList *ret = NULL; + gchar *string = (gchar*) data; + while(string) { + gchar* next = NULL; + if( (next = strchr(string, ' ')) || + (next = strchr(string, '\t')) || + (next = strchr(string, '\0')) ) { + + gchar *part = g_strndup(string, (next - string)); + ret = g_slist_append(ret, part); + if (*next) + string = next+1; + else + string = NULL; + } else { + string = NULL; + } + } + return ret; +} + +static void +update_wireless_security_setting_from_if_block(NMConnection *connection, + if_block *block) +{ + gint wpa_l= strlen("wpa-"); + gint wireless_l= strlen("wireless-"); + if_data *curr = block->info; + const gchar* value = ifparser_getkey (block, "inet"); + struct _Mapping mapping[] = { + {"psk", "psk"}, + {"identity", "identity"}, + {"password", "password"}, + {"key", "key"}, + {"key-mgmt", "key-mgmt"}, + {"group", "group"}, + {"pairwise", "pairwise"}, + {"proto", "proto"}, + {"pin", "pin"}, + {"wep-key0", "wep-key0"}, + {"wep-key1", "wep-key1"}, + {"wep-key2", "wep-key2"}, + {"wep-key3", "wep-key3"}, + { NULL, NULL} + }; + + struct _Mapping dupe_mapping[] = { + {"psk", normalize_psk}, + {"identity", normalize_dupe}, + {"password", normalize_dupe}, + {"key", normalize_dupe}, + {"key-mgmt", normalize_tolower}, + {"group", normalize_tolower}, + {"pairwise", normalize_tolower}, + {"proto", normalize_tolower}, + {"pin", normalize_dupe}, + {"wep-key0", normalize_dupe}, + {"wep-key1", normalize_dupe}, + {"wep-key2", normalize_dupe}, + {"wep-key3", normalize_dupe}, + { NULL, NULL} + }; + + struct _Mapping type_mapping[] = { + {"group", string_to_glist_of_strings}, + {"pairwise", string_to_glist_of_strings}, + {"proto", string_to_glist_of_strings}, + { NULL, NULL} + }; + + + NMSettingWirelessSecurity *wireless_security_setting; + NMSettingWireless *s_wireless; + gboolean security = FALSE; + + if(value && !strcmp("ppp", value)) { + return; + } + + s_wireless = NM_SETTING_WIRELESS(nm_connection_get_setting(connection, + NM_TYPE_SETTING_WIRELESS)); + g_return_if_fail(s_wireless); + + PLUGIN_PRINT ("SCPlugin-Ifupdown","update wireless security settings (%s).", block->name); + wireless_security_setting = + NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new()); + + while(curr) { + if(strlen(curr->key) > wireless_l && + !strncmp("wireless-", curr->key, wireless_l)) { + + gchar *property_value = NULL; + gpointer property_value2 = NULL; + const gchar* newkey = map_by_mapping(mapping, curr->key+wireless_l); + IfupdownStrDupeFunc func = map_by_mapping (dupe_mapping, curr->key+wireless_l); + IfupdownStrToTypeFunc func1 = map_by_mapping (type_mapping, curr->key+wireless_l); + if(!newkey || !func) { + g_warning("no (wireless) mapping found for key: %s", curr->key); + goto next; + } + property_value = (*func) (curr->data, connection); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "setting wireless security key: %s=%s", + newkey, property_value); + if(func1) + property_value2 = (*func1) (property_value); + + g_object_set(wireless_security_setting, + newkey, property_value2 ? property_value2 : property_value, + NULL); + security = TRUE; + g_free(property_value); + if(property_value) + g_free(property_value2); + } else if(strlen(curr->key) > wpa_l && + !strncmp("wpa-", curr->key, wpa_l)) { + + gchar *property_value = NULL; + gpointer property_value2 = NULL; + const gchar* newkey = map_by_mapping(mapping, curr->key+wpa_l); + IfupdownStrDupeFunc func = map_by_mapping (dupe_mapping, curr->key+wpa_l); + IfupdownStrToTypeFunc func1 = map_by_mapping (type_mapping, curr->key+wpa_l); + if(!newkey || !func) { + goto next; + } + property_value = (*func) (curr->data, connection); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "setting wpa security key: %s=%s", + newkey, +#ifdef DEBUG_SECRETS + property_value +#else // DEBUG_SECRETS + !strcmp("key", newkey) || + !strcmp("password", newkey) || + !strcmp("pin", newkey) || + !strcmp("psk", newkey) || + !strcmp("wep-key0", newkey) || + !strcmp("wep-key1", newkey) || + !strcmp("wep-key2", newkey) || + !strcmp("wep-key3", newkey) || + NULL ? + "" : property_value +#endif // DEBUG_SECRETS + ); + + if(func1) + property_value2 = (*func1) (property_value); + + g_object_set(wireless_security_setting, + newkey, property_value2 ? property_value2 : property_value, + NULL); + security = TRUE; + g_free(property_value); + } + next: + curr = curr->next; + } + + + if(security) { + nm_connection_add_setting(connection, NM_SETTING(wireless_security_setting)); + g_object_set(s_wireless, NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NULL); + } + +} + +static void +update_wired_setting_from_if_block(NMConnection *connection, + if_block *block) +{ + NMSettingWired *s_wired = NULL; + s_wired = NM_SETTING_WIRED(nm_setting_wired_new()); + nm_connection_add_setting(connection, NM_SETTING(s_wired)); +} + +static GQuark +eni_plugin_error_quark() { + static GQuark error_quark = 0; + + if(!error_quark) { + error_quark = g_quark_from_static_string ("eni-plugin-error-quark"); + } + + return error_quark; +} + + +static void +update_ip4_setting_from_if_block(NMConnection *connection, + if_block *block) +{ + + NMSettingIP4Config *ip4_setting = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new()); + const char *type = ifparser_getkey(block, "inet"); + gboolean is_static = type && !strcmp("static", type); + + if(!is_static) { + g_object_set(ip4_setting, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + } else { + struct in_addr tmp_ip4_addr; + NMSettingIP4Address *ip4config = g_new0(NMSettingIP4Address, 1); + GSList *ip4_addresses = NULL; + GArray *nameserver = g_array_new (TRUE, TRUE, sizeof(guint32)); + + const char *address_v = ifparser_getkey(block, "address"); + const char *netmask_v = ifparser_getkey(block, "netmask"); + const char *gateway_v = ifparser_getkey(block, "gateway"); + const char *nameserver_v = ifparser_getkey(block, "dns-nameserver"); + const char *nameservers_v = ifparser_getkey(block, "dns-nameservers"); + GSList* nameservers_list = NULL; + GSList* nameservers_list_i = NULL; + GError *error = NULL; + + if(nameservers_v) + nameservers_list_i = nameservers_list = string_to_glist_of_strings (nameservers_v); + if(nameserver_v) + nameservers_list_i = nameservers_list = g_slist_append(nameservers_list, g_strdup(nameserver_v)); + + if (inet_pton (AF_INET, address_v, &tmp_ip4_addr)) + ip4config->address = tmp_ip4_addr.s_addr; + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP4 address '%s'", "address", address_v); + if (inet_pton (AF_INET, netmask_v, &tmp_ip4_addr)) + ip4config->prefix = nm_utils_ip4_netmask_to_prefix(tmp_ip4_addr.s_addr); + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP4 address '%s'", "netmask", netmask_v); + if (inet_pton (AF_INET, gateway_v, &tmp_ip4_addr)) + ip4config->gateway = tmp_ip4_addr.s_addr; + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP4 address '%s'", "gateway", gateway_v); + + ip4_addresses = g_slist_append(ip4_addresses, ip4config); + + PLUGIN_PRINT("SCPlugin-Ifupdown", "addresses count: %d", g_slist_length(ip4_addresses)); + + while(nameservers_list_i) { + gchar *dns = nameservers_list_i->data; + nameservers_list_i = nameservers_list_i -> next; + if(!dns) + continue; + if (inet_pton (AF_INET, dns, &tmp_ip4_addr)) + g_array_append_vals(nameserver, &tmp_ip4_addr.s_addr, 1); + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP4 address nameserver '%s'", "nameserver", dns); + } + if (!nameserver->len) + PLUGIN_PRINT("SCPlugin-Ifupdown", "No dns-nameserver configured in /etc/network/interfaces"); + + ip4_setting->addresses = ip4_addresses; + ip4_setting->dns = nameserver; + + g_object_set(ip4_setting, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + g_slist_foreach (nameservers_list, (GFunc) g_free, NULL); + g_slist_free (nameservers_list); + } + + nm_connection_add_setting(connection, NM_SETTING(ip4_setting)); +} + +void +ifupdown_update_connection_from_if_block(NMConnection *connection, + if_block *block) +{ + const char *type = NULL; + char *idstr = NULL; + char *uuid_base = NULL; + GError *verify_error =NULL; + + NMSettingConnection *connection_setting = + NM_SETTING_CONNECTION(nm_connection_get_setting + (connection, NM_TYPE_SETTING_CONNECTION)); + + if(!connection_setting) { + connection_setting = NM_SETTING_CONNECTION(nm_setting_connection_new()); + nm_connection_add_setting(connection, NM_SETTING(connection_setting)); + } + + type = _ifupdownplugin_guess_connection_type (block); + idstr = g_strconcat("Ifupdown (", block->name,")", NULL); + uuid_base = idstr; + + g_object_set (connection_setting, + "type", type, + "id", idstr, + NULL); + connection_setting->uuid = + nm_utils_uuid_generate_from_string(uuid_base); + + PLUGIN_PRINT("SCPlugin-Ifupdown", "update_connection_setting_from_if_block: name:%s, type:%s, autoconnect:%d, id:%s, uuid: %s", + block->name, type, + ((gboolean) strcmp("dhcp", type) == 0), + idstr, + connection_setting->uuid); + + if(!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) { + update_wired_setting_from_if_block (connection, block); + } + else if(!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { + update_wireless_setting_from_if_block (connection, block); + update_wireless_security_setting_from_if_block (connection, block); + } + + update_ip4_setting_from_if_block(connection, block); + + if(!nm_connection_verify(connection, &verify_error)) { + nm_warning("connection broken: %s (%d)", + verify_error->message, verify_error->code); + } + + g_free(idstr); +} diff --git a/system-settings/plugins/ifupdown/parser.h b/system-settings/plugins/ifupdown/parser.h new file mode 100644 index 0000000000..8e3a222f71 --- /dev/null +++ b/system-settings/plugins/ifupdown/parser.h @@ -0,0 +1,33 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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 2008 Canonical Ltd. + */ + +#include +#include "interface_parser.h" + +G_BEGIN_DECLS + +void +ifupdown_update_connection_from_if_block(NMConnection *connection, + if_block *block); + +G_END_DECLS diff --git a/system-settings/plugins/ifupdown/plugin.c b/system-settings/plugins/ifupdown/plugin.c new file mode 100644 index 0000000000..869eb46153 --- /dev/null +++ b/system-settings/plugins/ifupdown/plugin.c @@ -0,0 +1,333 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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,2008 Canonical Ltd. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "interface_parser.h" + +#include "nm-system-config-interface.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-wireless.h" +#include "nm-setting-wired.h" +#include "nm-setting-ppp.h" + +#include "nm-ifupdown-connection.h" +#include "plugin.h" +#include "parser.h" + +#include +#include + +#include + +#define IFUPDOWN_PLUGIN_NAME "ifupdown" +#define IFUPDOWN_PLUGIN_INFO "(C) 2008 Canonical Ltd. To report bugs please use the NetworkManager mailing list." + +typedef struct { + + DBusGConnection *g_connection; + NMSystemConfigHalManager *hal_mgr; + + GHashTable *iface_connections; + +} SCPluginIfupdownPrivate; + +static void +system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); + +G_DEFINE_TYPE_EXTENDED (SCPluginIfupdown, sc_plugin_ifupdown, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, + system_config_interface_init)) + +#define SC_PLUGIN_IFUPDOWN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdownPrivate)) + +static void +sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class); + +static void +SCPluginIfupdown_init (NMSystemConfigInterface *config, + NMSystemConfigHalManager *hal_manager); + +/* Returns the plugins currently known list of connections. The returned + * list is freed by the system settings service. + */ +static GSList* +SCPluginIfupdown_get_connections (NMSystemConfigInterface *config); + +/* + * Return a list of HAL UDIs of devices which NetworkManager should not + * manage. Returned list will be freed by the system settings service, and + * each element must be allocated using g_malloc() or its variants. + */ +static GSList* +SCPluginIfupdown_get_unmanaged_devices (NMSystemConfigInterface *config); + +/* Signals */ + +/* Emitted when a new connection has been found by the plugin */ +static void +SCPluginIfupdown_connection_added (NMSystemConfigInterface *config, + NMExportedConnection *connection); + +/* Emitted when the list of unmanaged devices changes */ +static void +SCPluginIfupdown_unmanaged_devices_changed (NMSystemConfigInterface *config); + +static void +GObject__get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); + +static void +GObject__dispose (GObject *object); + +static void +GObject__finalize (GObject *object); + + +static void +system_config_interface_init (NMSystemConfigInterface *system_config_interface_class) +{ + system_config_interface_class->init = SCPluginIfupdown_init; + system_config_interface_class->get_connections = SCPluginIfupdown_get_connections; + system_config_interface_class->get_unmanaged_devices = SCPluginIfupdown_get_unmanaged_devices; + system_config_interface_class->connection_added = SCPluginIfupdown_connection_added; + system_config_interface_class->unmanaged_devices_changed = SCPluginIfupdown_unmanaged_devices_changed; +} + +static void +sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (req_class); + + g_type_class_add_private (req_class, sizeof (SCPluginIfupdownPrivate)); + + object_class->dispose = GObject__dispose; + object_class->finalize = GObject__finalize; + object_class->get_property = GObject__get_property; + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, + NM_SYSTEM_CONFIG_INTERFACE_NAME); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, + NM_SYSTEM_CONFIG_INTERFACE_INFO); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES, + NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME, + NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); +} + +static void +SCPluginIfupdown_init (NMSystemConfigInterface *config, + NMSystemConfigHalManager *hal_manager) +{ + SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config); + GHashTable *auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal); + if_block *block = NULL; + + if(!priv->iface_connections) + priv->iface_connections = g_hash_table_new (g_str_hash, g_str_equal); + + PLUGIN_PRINT("SCPlugin-Ifupdown", "init!"); + priv->hal_mgr = g_object_ref (hal_manager); + + ifparser_init(); + block = ifparser_getfirst(); + + while(block) { + if(!strcmp("auto", block->type)) { + g_hash_table_insert (auto_ifaces, block->name, "auto"); + } else if (!strcmp ("iface", block->type) && strcmp ("lo", block->name)) { + NMExportedConnection *connection = g_hash_table_lookup(priv->iface_connections, block->name); + g_hash_table_remove (priv->iface_connections, block->name); + + connection = NM_EXPORTED_CONNECTION(nm_ifupdown_connection_new(block)); + ifupdown_update_connection_from_if_block (nm_exported_connection_get_connection(connection), + block); + + g_hash_table_insert (priv->iface_connections, block->name, connection); + } + block = block -> next; + } + + { + GList *keys = g_hash_table_get_keys (priv->iface_connections); + GList *key_it = keys; + while(key_it) { + gpointer val = g_hash_table_lookup(auto_ifaces, key_it->data); + if(val) { + NMExportedConnection *connection = + g_hash_table_lookup(priv->iface_connections, key_it->data); + NMConnection *wrapped = NULL; + NMSetting *setting; + g_object_get(connection, + NM_EXPORTED_CONNECTION_CONNECTION, &wrapped, NULL); + setting = NM_SETTING(nm_connection_get_setting + (wrapped, NM_TYPE_SETTING_CONNECTION)); + g_object_set (setting, + "autoconnect", TRUE, + NULL); + PLUGIN_PRINT("SCPlugin-Ifupdown", "autoconnect"); + } + key_it = key_it -> next; + } + } + g_hash_table_unref(auto_ifaces); + PLUGIN_PRINT("SCPlugin-Ifupdown", "end _init."); +} + + +/* Returns the plugins currently known list of connections. The returned + * list is freed by the system settings service. + */ +static GSList* +SCPluginIfupdown_get_connections (NMSystemConfigInterface *config) +{ + SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config); + GSList *connections = NULL; + GList *priv_list = g_hash_table_get_values(priv->iface_connections); + GList *it = priv_list; + PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) ... get_connections.", GPOINTER_TO_UINT(config)); + + while(it) { + NMExportedConnection *conn = it->data; + connections = g_slist_append(connections, conn); + it = it->next; + } + PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) connections count: %d", GPOINTER_TO_UINT(config), g_slist_length(connections)); + return connections; +} + +/* + * Return a list of HAL UDIs of devices which NetworkManager should not + * manage. Returned list will be freed by the system settings service, and + * each element must be allocated using g_malloc() or its variants. + */ +static GSList* +SCPluginIfupdown_get_unmanaged_devices (NMSystemConfigInterface *config) +{ + // XXX implement this. + return NULL; +} + +/* Signals */ + +/* Emitted when a new connection has been found by the plugin */ +static void +SCPluginIfupdown_connection_added (NMSystemConfigInterface *config, + NMExportedConnection *connection) +{ + PLUGIN_PRINT("SCPlugin-Ifdown", "connection_added ... started"); + g_return_if_fail (config != NULL); + g_return_if_fail (NM_IS_CONNECTION (connection)); + PLUGIN_PRINT("SCPlugin-Ifdown", "connection_added ... ended"); +} + +/* Emitted when the list of unmanaged devices changes */ +static void +SCPluginIfupdown_unmanaged_devices_changed (NMSystemConfigInterface *config) +{ + PLUGIN_PRINT("SCPlugin-Ifdown", "unmanaged_devices_changed ... started"); + g_return_if_fail (config != NULL); + + PLUGIN_PRINT("SCPlugin-Ifdown", "unmanaged_devices_changed ... ended"); +} + +static void +sc_plugin_ifupdown_init (SCPluginIfupdown *plugin) +{ + SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin); + GError *error = NULL; + + priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (!priv->g_connection) { + PLUGIN_PRINT (IFUPDOWN_PLUGIN_NAME, " dbus-glib error: %s", + error->message ? error->message : "(unknown)"); + g_error_free (error); + } +} + +static void +GObject__get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME: + g_value_set_string (value, IFUPDOWN_PLUGIN_NAME); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO: + g_value_set_string (value, IFUPDOWN_PLUGIN_INFO); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: + g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: + g_value_set_string (value, ""); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +GObject__dispose (GObject *object) +{ + SCPluginIfupdown *plugin = SC_PLUGIN_IFUPDOWN (object); + SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin); + + g_object_unref (priv->hal_mgr); + G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->dispose (object); +} + +static void +GObject__finalize (GObject *object) +{ + G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->finalize (object); +} + +G_MODULE_EXPORT GObject * +nm_system_config_factory (void) +{ + static SCPluginIfupdown *singleton = NULL; + + if (!singleton) + singleton = SC_PLUGIN_IFUPDOWN (g_object_new (SC_TYPE_PLUGIN_IFUPDOWN, NULL)); + else + g_object_ref (singleton); + + return G_OBJECT (singleton); +} + diff --git a/system-settings/plugins/ifupdown/plugin.h b/system-settings/plugins/ifupdown/plugin.h new file mode 100644 index 0000000000..aad20ef633 --- /dev/null +++ b/system-settings/plugins/ifupdown/plugin.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +/* NetworkManager system settings service (ifupdown) + * + * Alexander Sack + * + * 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 2008 Canonical Ltd. + */ + +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +#include + +#define PLUGIN_NAME "ifupdown" + +#define SC_TYPE_PLUGIN_IFUPDOWN (sc_plugin_ifupdown_get_type ()) +#define SC_PLUGIN_IFUPDOWN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdown)) +#define SC_PLUGIN_IFUPDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdownClass)) +#define SC_IS_PLUGIN_IFUPDOWN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_PLUGIN_IFUPDOWN)) +#define SC_IS_PLUGIN_IFUPDOWN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SC_TYPE_PLUGIN_IFUPDOWN)) +#define SC_PLUGIN_IFUPDOWN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdownClass)) + +typedef struct _SCPluginIfupdown SCPluginIfupdown; +typedef struct _SCPluginIfupdownClass SCPluginIfupdownClass; + +struct _SCPluginIfupdown { + GObject parent; +}; + +struct _SCPluginIfupdownClass { + GObjectClass parent; +}; + +GType sc_plugin_ifupdown_get_type (void); + +GQuark ifupdown_plugin_error_quark (void); + +#endif /* _PLUGIN_H_ */