Commit 38f3e5ca authored by Mu Qiao's avatar Mu Qiao Committed by Dan Williams
Browse files

ifnet: add Gentoo system settings plugin

parent 3f2d741b
......@@ -512,6 +512,8 @@ system-settings/Makefile
system-settings/plugins/Makefile
system-settings/plugins/ifupdown/Makefile
system-settings/plugins/ifupdown/tests/Makefile
system-settings/plugins/ifnet/Makefile
system-settings/plugins/ifnet/tests/Makefile
system-settings/plugins/ifcfg-rh/Makefile
system-settings/plugins/ifcfg-rh/tests/Makefile
system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile
......
......@@ -21,4 +21,5 @@ src/logging/nm-logging.c
src/named-manager/nm-named-manager.c
src/system-settings/nm-default-wired-connection.c
system-settings/plugins/ifcfg-rh/reader.c
system-settings/plugins/ifnet/connection_parser.c
......@@ -15,3 +15,7 @@ endif
if TARGET_DEBIAN
SUBDIRS+=ifupdown
endif
if TARGET_GENTOO
SUBDIRS+=ifnet
endif
SUBDIRS = . tests
INCLUDES = \
-I$(top_srcdir)/src/system-settings \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libnm-glib \
-I$(top_srcdir)/libnm-util
pkglib_LTLIBRARIES = libnm-settings-plugin-ifnet.la
noinst_LTLIBRARIES = lib-ifnet-io.la
libnm_settings_plugin_ifnet_la_SOURCES = \
nm-ifnet-connection.c \
nm-ifnet-connection.h \
plugin.c \
plugin.h
libnm_settings_plugin_ifnet_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(GMODULE_CFLAGS) \
$(DBUS_CFLAGS) \
$(GUDEV_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DSYSCONFDIR=\"$(sysconfdir)\"\
-g
libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version
libnm_settings_plugin_ifnet_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(top_builddir)/libnm-glib/libnm-glib.la \
lib-ifnet-io.la\
$(GLIB_LIBS) \
$(GMODULE_LIBS) \
$(GUDEV_LIBS) \
$(GIO_LIBS)
lib_ifnet_io_la_SOURCES = \
net_parser.c\
net_parser.h\
connection_parser.c \
connection_parser.h \
net_utils.h\
net_utils.c\
wpa_parser.h\
wpa_parser.c
lib_ifnet_io_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(DBUS_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DSBINDIR=\"$(sbindir)\"\
-g
lib_ifnet_io_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(GLIB_LIBS)\
$(GIO_LIBS)
This diff is collapsed.
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Mu Qiao <qiaomuf@gmail.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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 1999-2010 Gentoo Foundation, Inc.
*/
#ifndef _CONNECTION_PARSER_H
#define _CONNECTION_PARSER_H
#include <nm-connection.h>
#include "net_parser.h"
NMConnection *ifnet_update_connection_from_config_block (gchar * conn_name,
GError ** error);
/* nm_conn_name is used to update nm_ifnet_connection's priv data */
gboolean ifnet_update_parsers_by_connection (NMConnection * connection,
gchar * conn_name,
gchar ** nm_conn_name,
gchar * config_file,
gchar * wpa_file, GError ** error);
gboolean ifnet_delete_connection_in_parsers (gchar * conn_name,
gchar * config_file,
gchar * wpa_file);
gboolean ifnet_add_new_connection (NMConnection * connection,
gchar * config_file, gchar * wpa_file,
GError ** error);
#endif
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* Mu Qiao <qiaomuf@gmail.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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 1999-2010 Gentoo Foundation, Inc.
*/
#include <string.h>
#include <nm-system-config-interface.h>
#include <stdio.h>
#include "net_parser.h"
#include "net_utils.h"
/* Save all the connection information */
static GHashTable *conn_table;
/* Save global settings which are used for writing*/
static GHashTable *global_settings_table;
/* Save functions */
static GList *functions_list;
/* Used to decide whether to write changes to file*/
static gboolean net_parser_data_changed = FALSE;
static GHashTable *
add_new_connection_config (const gchar * type, const gchar * name)
{
GHashTable *new_conn;
gchar *new_name;
if (!name)
return NULL;
/* Return existing connection */
if ((new_conn = g_hash_table_lookup (conn_table, name)) != NULL)
return new_conn;
new_conn = g_hash_table_new (g_str_hash, g_str_equal);
new_name = g_strdup (name);
g_hash_table_insert (new_conn, g_strdup ("name"), new_name);
g_hash_table_insert (new_conn, g_strdup ("type"), g_strdup (type));
g_hash_table_insert (conn_table, new_name, new_conn);
return new_conn;
}
gboolean
ifnet_add_connection (gchar * name, gchar * type)
{
if (add_new_connection_config (type, name)) {
PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding network for %s", name);
net_parser_data_changed = TRUE;
return TRUE;
} else
return FALSE;
}
gboolean
ifnet_has_connection (gchar * conn_name)
{
return g_hash_table_lookup (conn_table, conn_name) != NULL;
}
static GHashTable *
get_connection_config (gchar * name)
{
return g_hash_table_lookup (conn_table, name);
}
/* Ignored name won't be treated as wireless ssid */
static gchar *ignore_name[] = {
"vlan", "bond", "atm", "ath", "ippp", "vpn", "tap", "tun", "1",
"br", "nas", "6to4", "timeout", "kvm", "force", NULL
};
static gboolean
ignore_connection_name (gchar * name)
{
gboolean result = FALSE;
guint i = 0;
/* check ignore_name list */
while (ignore_name[i] != NULL) {
if (g_ascii_strncasecmp
(name, ignore_name[i], strlen (ignore_name[i])) == 0) {
return TRUE;
}
i++;
}
/* Ignore mac address based configuration */
if (strlen (name) == 12 && is_hex (name))
result = TRUE;
return result;
}
static gboolean
is_global_setting (char *key)
{
static gchar *global_settings[] = { "wpa_supplicant_", NULL };
int i;
for (i = 0; global_settings[i] != NULL; i++) {
if (strstr (key, global_settings[i]))
return 1;
}
return 0;
}
/* Parse a complete line */
/* Connection type is determined here */
static void
init_block_by_line (gchar * buf)
{
gchar **key_value;
gchar *pos;
gchar *data;
gchar *tmp;
GHashTable *conn;
key_value = g_strsplit (buf, "=", 2);
if (g_strv_length (key_value) != 2) {
PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle this line: %s\n",
buf);
g_strfreev (key_value);
return;
}
pos = g_strrstr (key_value[0], "_");
if (pos == NULL || is_global_setting (key_value[0])) {
/* global data */
PLUGIN_PRINT (IFNET_PLUGIN_NAME, "global:%s-%s\n", key_value[0],
key_value[1]);
g_hash_table_insert (global_settings_table,
g_strdup (key_value[0]),
g_strdup (key_value[1]));
g_strfreev (key_value);
return;
}
*pos++ = '\0';
if ((conn = get_connection_config (pos)) == NULL) {
if (g_ascii_strncasecmp (pos, "eth", 3) == 0
&& strlen (pos) == 4)
/* wired connection */
conn = add_new_connection_config ("wired", pos);
else if (g_ascii_strncasecmp (pos, "ppp", 3) == 0
&& strlen (pos) == 4)
/* pppoe connection */
conn = add_new_connection_config ("ppp", pos);
else if (ignore_connection_name (pos)) {
/* ignored connection */
conn = add_new_connection_config ("ignore", pos);
} else
/* wireless connection */
conn = add_new_connection_config ("wireless", pos);
}
data = g_strdup (key_value[1]);
tmp = strip_string (data, '(');
tmp = strip_string (tmp, ')');
strip_string (tmp, '"');
strip_string (tmp, '\'');
if (conn)
g_hash_table_insert (conn, g_strdup (key_value[0]),
g_strdup (tmp));
g_free (data);
g_strfreev (key_value);
}
static void
destroy_connection_config (GHashTable * conn)
{
gpointer key, value;
GHashTableIter iter;
g_hash_table_iter_init (&iter, conn);
while (g_hash_table_iter_next (&iter, &key, &value)) {
g_free (key);
g_free (value);
}
g_hash_table_destroy (conn);
}
// read settings from /etc/NetworkManager/nm-system-settings.conf
gchar *
ifnet_get_global_setting (gchar * group, gchar * key)
{
GError *error = NULL;
GKeyFile *keyfile = g_key_file_new ();
gchar *result = NULL;
if (!g_key_file_load_from_file (keyfile,
IFNET_SYSTEM_SETTINGS_KEY_FILE,
G_KEY_FILE_NONE, &error)) {
PLUGIN_WARN (IFNET_PLUGIN_NAME,
"loading system config file (%s) caused error: (%d) %s",
IFNET_SYSTEM_SETTINGS_KEY_FILE,
error ? error->code : -1, error
&& error->message ? error->message : "(unknown)");
} else {
result = g_key_file_get_string (keyfile, group, key, &error);
}
g_key_file_free (keyfile);
return result;
}
static void
strip_function (GIOChannel * channel, gchar * line)
{
int counter = 0;
gchar *p, *tmp;
gboolean begin = FALSE;
GString *function_str = g_string_new (line);
g_string_append (function_str, "\n");
while (1) {
p = line;
while (*p != '\0') {
if (*p == '{') {
counter++;
begin = TRUE;
} else if (*p == '}')
counter--;
p++;
}
if (begin && counter == 0) {
g_free (line);
goto done;
}
while (1) {
g_free (line);
if (g_io_channel_read_line
(channel, &line, NULL, NULL,
NULL) == G_IO_STATUS_EOF)
goto done;
g_string_append (function_str, line);
tmp = g_strdup (line);
g_strstrip (tmp);
if (tmp[0] != '#' && tmp[0] != '\0') {
g_free (tmp);
break;
} else
g_free (tmp);
}
}
done:
functions_list =
g_list_append (functions_list, g_strdup (function_str->str));
g_string_free (function_str, TRUE);
}
static gboolean
is_function (gchar * line)
{
static gchar *func_names[] =
{ "preup", "predown", "postup", "postdown", "failup", "faildown",
NULL,
};
int i;
for (i = 0; func_names[i]; i++) {
if (g_str_has_prefix (line, func_names[i])) {
PLUGIN_PRINT (IFNET_PLUGIN_NAME,
"Ignoring function: %s", func_names[i]);
return TRUE;
}
}
return FALSE;
}
gboolean
ifnet_init (gchar * config_file)
{
GIOChannel *channel = NULL;
gchar *line;
/* Handle multiple lines with brackets */
gboolean complete = TRUE;
/* line buffer */
GString *buf;
net_parser_data_changed = FALSE;
conn_table = g_hash_table_new (g_str_hash, g_str_equal);
global_settings_table = g_hash_table_new (g_str_hash, g_str_equal);
functions_list = NULL;
if (g_file_test (config_file, G_FILE_TEST_IS_REGULAR))
channel = g_io_channel_new_file (config_file, "r", NULL);
if (channel == NULL) {
PLUGIN_WARN (IFNET_PLUGIN_NAME,
"Error: Can't open %s\n", config_file);
return FALSE;
}
buf = g_string_new (NULL);
while (g_io_channel_read_line
(channel, &line, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
g_strstrip (line);
/* convert multiple lines to a complete line and
* pass it to init_block_by_line() */
if (is_function (line)) {
strip_function (channel, line);
continue;
}
if (line[0] != '#' && line[0] != '\0') {
gchar *pos = NULL;
if (!complete) {
complete =
g_strrstr (line,
")") == NULL ? FALSE : TRUE;
if ((pos = strchr (line, '#')) != NULL)
*pos = '\0';
g_strstrip (line);
if (line[0] != '\0') {
g_string_append_printf (buf,
" %s", line);
}
g_free (line);
if (!complete)
continue;
} else {
complete =
(g_strrstr (line, "(") != NULL
&& g_strrstr (line, ")") != NULL)
|| g_strrstr (line, "(") == NULL;
if ((pos = strchr (line, '#')) != NULL)
*pos = '\0';
g_strstrip (line);
if (line[0] != '\0')
g_string_append (buf, line);
g_free (line);
if (!complete)
continue;
}
init_block_by_line (buf->str);
g_string_free (buf, TRUE);
buf = g_string_new (NULL);
} else
/* Blank line or comment line */
g_free (line);
}
g_string_free (buf, TRUE);
g_io_channel_shutdown (channel, FALSE, NULL);
g_io_channel_unref (channel);
return TRUE;
}
gchar *
ifnet_get_data (gchar * conn_name, const gchar * key)
{
GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
if (conn)
return g_hash_table_lookup (conn, key);
return NULL;
}
void
ifnet_set_data (gchar * conn_name, gchar * key, gchar * value)
{
gpointer orin_key = NULL, orin_value = NULL;
GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
if (!conn) {
PLUGIN_WARN (IFNET_PLUGIN_NAME,
"%s does not exsit!", conn_name);
return;
}
/* Remove existing key value pair */
if (g_hash_table_lookup_extended (conn, key, &orin_key, &orin_value)) {
g_hash_table_remove (conn, orin_key);
g_free (orin_key);
g_free (orin_value);
}
if (value)
g_hash_table_insert (conn, g_strdup (key),
strip_string (g_strdup (value), '"'));
net_parser_data_changed = TRUE;
}
// Remember to free return value
gchar *
ifnet_get_global_data (const gchar * key)
{
gchar *result = g_hash_table_lookup (global_settings_table, key);
if (result)
result = g_strdup (result);
else
return NULL;
strip_string (result, '"');
return result;
}
// Return names of legal connections
GList *
ifnet_get_connection_names ()
{
GList *names = g_hash_table_get_keys (conn_table);
GList *result = NULL;
while (names) {
if (!ignore_connection_name (names->data))
result = g_list_append (result, names->data);
names = names->next;
}
return result;
}
/* format IP and route for writing */
static void
format_ips (gchar * value, gchar ** out_line, gchar * key, gchar * name)
{
gchar **ipset;
guint length, i;
GString *formated_string = g_string_new (NULL);
strip_string (value, '"');
ipset = g_strsplit (value, "\" \"", 0);
length = g_strv_length (ipset);
//only one line
if (length < 2) {
*out_line =
g_strdup_printf ("%s_%s=( \"%s\" )\n", key, name, value);
goto done;
}
// Multiple lines
g_string_append_printf (formated_string, "%s_%s=(\n", key, name);
for (i = 0; i < length; i++)
g_string_append_printf (formated_string,
"\t\"%s\"\n", ipset[i]);
g_string_append (formated_string, ")\n");
*out_line = g_strdup (formated_string->str);
done:
g_string_free (formated_string, TRUE);
g_strfreev (ipset);
}
gboolean
ifnet_flush_to_file (gchar * config_file)
{
GIOChannel *channel;
GError **error = NULL;
gpointer key, value, name, network;
GHashTableIter iter, iter_network;
GList *list_iter;
gchar *out_line;
gsize bytes_written;
gboolean result = FALSE;
if (!net_parser_data_changed)