diff options
| author | Michael Biebl <biebl@debian.org> | 2017-12-12 15:53:07 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-12-12 15:53:07 +0100 |
| commit | afcd268ea7b1149fbfb66bce4eca659b675da0a2 (patch) | |
| tree | c3fca2203ad17434daf3ccf576582bd66aa41ab2 /src/settings/plugins/ifcfg-rh | |
| parent | 417f6015c3dc8c47cf27daa59f64e0e36c521b9c (diff) | |
New upstream version 1.10.2 upstream/1.10.2
Diffstat (limited to 'src/settings/plugins/ifcfg-rh')
23 files changed, 930 insertions, 507 deletions
diff --git a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c new file mode 100644 index 00000000..4c65b02d --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.c @@ -0,0 +1,214 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2008 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-inotify-helper.h" + +#include <unistd.h> +#include <string.h> +#include <sys/inotify.h> +#include <errno.h> + +#include "NetworkManagerUtils.h" + +/* NOTE: this code should be killed once we depend on a new enough glib to + * include the patches from https://bugzilla.gnome.org/show_bug.cgi?id=532815 + */ + +/*****************************************************************************/ + +enum { + EVENT, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + int ifd; + GHashTable *wd_refs; +} NMInotifyHelperPrivate; + +struct _NMInotifyHelper { + GObject parent; + NMInotifyHelperPrivate _priv; +}; + +struct _NMInotifyHelperClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE (NMInotifyHelper, nm_inotify_helper, G_TYPE_OBJECT) + +#define NM_INOTIFY_HELPER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMInotifyHelper, NM_IS_INOTIFY_HELPER) + +/*****************************************************************************/ + +NM_DEFINE_SINGLETON_GETTER (NMInotifyHelper, nm_inotify_helper_get, NM_TYPE_INOTIFY_HELPER); + +/*****************************************************************************/ + +int +nm_inotify_helper_add_watch (NMInotifyHelper *self, const char *path) +{ + NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self); + int wd; + guint refcount; + + if (priv->ifd < 0) + return -1; + + /* We only care about modifications since we're just trying to get change + * notifications on hardlinks. + */ + + wd = inotify_add_watch (priv->ifd, path, IN_CLOSE_WRITE); + if (wd < 0) + return -1; + + refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd))); + refcount++; + g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount)); + + return wd; +} + +void +nm_inotify_helper_remove_watch (NMInotifyHelper *self, int wd) +{ + NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self); + guint refcount; + + if (priv->ifd < 0) + return; + + refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd))); + if (!refcount) + return; + + refcount--; + if (!refcount) { + g_hash_table_remove (priv->wd_refs, GINT_TO_POINTER (wd)); + inotify_rm_watch (priv->ifd, wd); + } else + g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount)); +} + +static gboolean +inotify_event_handler (GIOChannel *channel, GIOCondition cond, gpointer user_data) +{ + NMInotifyHelper *self = NM_INOTIFY_HELPER (user_data); + struct inotify_event evt; + + /* read the notifications from the watch descriptor */ + while (g_io_channel_read_chars (channel, (gchar *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) { + gchar filename[PATH_MAX + 1]; + + filename[0] = '\0'; + if (evt.len > 0) { + g_io_channel_read_chars (channel, + filename, + evt.len > PATH_MAX ? PATH_MAX : evt.len, + NULL, NULL); + } + + if (!(evt.mask & IN_IGNORED)) + g_signal_emit (self, signals[EVENT], 0, &evt, &filename[0]); + } + + return TRUE; +} + +static gboolean +init_inotify (NMInotifyHelper *self) +{ + NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self); + GIOChannel *channel; + guint source_id; + + priv->ifd = inotify_init1 (IN_CLOEXEC); + if (priv->ifd == -1) { + int errsv = errno; + + nm_log_warn (LOGD_SETTINGS, "couldn't initialize inotify: %s (%d)", strerror (errsv), errsv); + return FALSE; + } + + /* Watch the inotify descriptor for file/directory change events */ + channel = g_io_channel_unix_new (priv->ifd); + g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_encoding (channel, NULL, NULL); + + source_id = g_io_add_watch (channel, + G_IO_IN | G_IO_ERR, + (GIOFunc) inotify_event_handler, + (gpointer) self); + g_io_channel_unref (channel); + return TRUE; +} + +/*****************************************************************************/ + +static void +nm_inotify_helper_init (NMInotifyHelper *self) +{ + NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self); + + priv->wd_refs = g_hash_table_new (g_direct_hash, g_direct_equal); +} + +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_inotify_helper_parent_class)->constructed (object); + + init_inotify (NM_INOTIFY_HELPER (object)); +} + +static void +finalize (GObject *object) +{ + NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE ((NMInotifyHelper *) object); + + nm_close (priv->ifd); + + g_hash_table_destroy (priv->wd_refs); + + G_OBJECT_CLASS (nm_inotify_helper_parent_class)->finalize (object); +} + +static void +nm_inotify_helper_class_init (NMInotifyHelperClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = constructed; + object_class->finalize = finalize; + + signals[EVENT] = + g_signal_new ("event", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING); +} + diff --git a/src/settings/plugins/ifcfg-rh/nm-inotify-helper.h b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.h new file mode 100644 index 00000000..b887ae37 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/nm-inotify-helper.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2008 Red Hat, Inc. + */ + +#ifndef __NM_INOTIFY_HELPER_H__ +#define __NM_INOTIFY_HELPER_H__ + +/* NOTE: this code should be killed once we depend on a new enough glib to + * include the patches from https://bugzilla.gnome.org/show_bug.cgi?id=532815 + */ + +#define NM_TYPE_INOTIFY_HELPER (nm_inotify_helper_get_type ()) +#define NM_INOTIFY_HELPER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelper)) +#define NM_INOTIFY_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass)) +#define NM_IS_INOTIFY_HELPER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_INOTIFY_HELPER)) +#define NM_IS_INOTIFY_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_INOTIFY_HELPER)) +#define NM_INOTIFY_HELPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass)) + +typedef struct _NMInotifyHelper NMInotifyHelper; +typedef struct _NMInotifyHelperClass NMInotifyHelperClass; + +GType nm_inotify_helper_get_type (void); + +NMInotifyHelper * nm_inotify_helper_get (void); + +int nm_inotify_helper_add_watch (NMInotifyHelper *helper, const char *path); + +void nm_inotify_helper_remove_watch (NMInotifyHelper *helper, int wd); + +static inline gboolean +nm_inotify_helper_clear_watch (NMInotifyHelper *helper, int *wd) +{ + int x; + + if (wd && ((x = *wd) >= 0)) { + *wd = -1; + nm_inotify_helper_remove_watch (helper, x); + return TRUE; + } + return FALSE; +} + +#endif /* __NM_INOTIFY_HELPER_H__ */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c index 4c1d02ae..3cf5c978 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-connection.c @@ -36,13 +36,13 @@ #include "nm-setting-wireless-security.h" #include "nm-setting-8021x.h" #include "platform/nm-platform.h" -#include "settings/nm-inotify-helper.h" #include "nm-config.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" #include "nms-ifcfg-rh-writer.h" #include "nms-ifcfg-rh-utils.h" +#include "nm-inotify-helper.h" /*****************************************************************************/ @@ -96,14 +96,6 @@ G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SETTINGS_CONNECTI /*****************************************************************************/ -static NMInotifyHelper * -_get_inotify_helper (NMIfcfgConnectionPrivate *priv) -{ - if (!priv->inotify_helper) - priv->inotify_helper = g_object_ref (nm_inotify_helper_get ()); - return priv->inotify_helper; -} - static gboolean devtimeout_ready (gpointer user_data) { @@ -225,37 +217,17 @@ static void path_watch_stop (NMIfcfgConnection *self) { NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self); - NMInotifyHelper *ih; - - ih = _get_inotify_helper (priv); - - nm_clear_g_signal_handler (ih, &priv->ih_event_id); - - if (priv->file_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->file_wd); - priv->file_wd = -1; - } - g_free (priv->keyfile); - priv->keyfile = NULL; - if (priv->keyfile_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->keyfile_wd); - priv->keyfile_wd = -1; - } + nm_clear_g_signal_handler (priv->inotify_helper, &priv->ih_event_id); - g_free (priv->routefile); - priv->routefile = NULL; - if (priv->routefile_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->routefile_wd); - priv->routefile_wd = -1; - } + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->file_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->keyfile_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->routefile_wd); + nm_inotify_helper_clear_watch (priv->inotify_helper, &priv->route6file_wd); - g_free (priv->route6file); - priv->route6file = NULL; - if (priv->route6file_wd >= 0) { - nm_inotify_helper_remove_watch (ih, priv->route6file_wd); - priv->route6file_wd = -1; - } + nm_clear_g_free (&priv->keyfile); + nm_clear_g_free (&priv->routefile); + nm_clear_g_free (&priv->route6file); } static void @@ -280,7 +252,9 @@ filename_changed (GObject *object, if (nm_config_get_monitor_connection_files (nm_config_get ())) { NMInotifyHelper *ih; - ih = _get_inotify_helper (priv); + if (!priv->inotify_helper) + priv->inotify_helper = g_object_ref (nm_inotify_helper_get ()); + ih = priv->inotify_helper; priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), self); priv->file_wd = nm_inotify_helper_add_watch (ih, ifcfg_path); @@ -324,7 +298,7 @@ commit_changes (NMSettingsConnection *connection, nm_assert (!out_logmsg_change || !*out_logmsg_change); filename = nm_settings_connection_get_filename (connection); - if (!nms_ifcfg_rh_writer_write_connection (new_connection ?: NM_CONNECTION (connection), + if (!nms_ifcfg_rh_writer_write_connection (new_connection, IFCFG_DIR, filename, &ifcfg_path, @@ -415,6 +389,13 @@ set_property (GObject *object, guint prop_id, static void nm_ifcfg_connection_init (NMIfcfgConnection *connection) { + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); + + priv->file_wd = -1; + priv->keyfile_wd = -1; + priv->routefile_wd = -1; + priv->route6file_wd = -1; + g_signal_connect (connection, "notify::" NM_SETTINGS_CONNECTION_FILENAME, G_CALLBACK (filename_changed), NULL); } @@ -429,18 +410,12 @@ nm_ifcfg_connection_new (NMConnection *source, NMConnection *tmp; char *unhandled_spec = NULL; const char *unmanaged_spec = NULL, *unrecognized_spec = NULL; - gboolean update_unsaved = TRUE; g_assert (source || full_path); if (out_ignore_error) *out_ignore_error = FALSE; - if (full_path) { - /* The connection already is on the disk */ - update_unsaved = FALSE; - } - /* If we're given a connection already, prefer that instead of re-reading */ if (source) tmp = g_object_ref (source); @@ -464,11 +439,14 @@ nm_ifcfg_connection_new (NMConnection *source, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, unrecognized_spec, NULL); /* Update our settings with what was read from the file */ - if (nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), - tmp, - update_unsaved, - NULL, - error)) + if (nm_settings_connection_update (NM_SETTINGS_CONNECTION (object), + tmp, + full_path + ? NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP /* connection is already on disk */ + : NM_SETTINGS_CONNECTION_PERSIST_MODE_UNSAVED, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + NULL, + error)) nm_ifcfg_connection_check_devtimeout (NM_IFCFG_CONNECTION (object)); else g_clear_object (&object); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index da0920ef..04e74bbd 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -313,11 +313,12 @@ update_connection (SettingsPluginIfcfg *self, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC, new_unrecognized, NULL); - if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (connection_by_uuid), - NM_CONNECTION (connection_new), - FALSE, /* don't set Unsaved */ - "ifcfg-update", - &local)) { + if (!nm_settings_connection_update (NM_SETTINGS_CONNECTION (connection_by_uuid), + NM_CONNECTION (connection_new), + NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, + NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, + "ifcfg-update", + &local)) { /* Shouldn't ever get here as 'connection_new' was verified by the reader already * and the UUID did not change. */ g_assert_not_reached (); @@ -1079,5 +1080,5 @@ settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) G_MODULE_EXPORT GObject * nm_settings_plugin_factory (void) { - return g_object_ref (settings_plugin_ifcfg_get ()); + return G_OBJECT (g_object_ref (settings_plugin_ifcfg_get ())); } diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 66add713..b9900eec 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -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 2008 - 2015 Red Hat, Inc. + * Copyright 2008 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -77,18 +77,6 @@ /*****************************************************************************/ -static gboolean -get_uint (const char *str, guint32 *value) -{ - gint64 tmp; - - tmp = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT32, -1); - if (tmp == -1) - return FALSE; - *value = tmp; - return TRUE; -} - static void check_if_bond_slave (shvarFile *ifcfg, NMSettingConnection *s_con) @@ -512,13 +500,13 @@ typedef struct { bool int_base_16:1; - /* the type, one of PARSE_LINE_TYPE_* */ - char type; - /* whether the command line option was found, and @v is * initialized. */ bool has:1; + /* the type, one of PARSE_LINE_TYPE_* */ + char type; + union { guint8 uint8; guint32 uint32; @@ -541,6 +529,7 @@ enum { PARSE_LINE_ATTR_ROUTE_SRC, PARSE_LINE_ATTR_ROUTE_FROM, PARSE_LINE_ATTR_ROUTE_TOS, + PARSE_LINE_ATTR_ROUTE_ONLINK, PARSE_LINE_ATTR_ROUTE_WINDOW, PARSE_LINE_ATTR_ROUTE_CWND, PARSE_LINE_ATTR_ROUTE_INITCWND, @@ -562,6 +551,7 @@ enum { #define PARSE_LINE_TYPE_ADDR 'a' #define PARSE_LINE_TYPE_ADDR_WITH_PREFIX 'p' #define PARSE_LINE_TYPE_IFNAME 'i' +#define PARSE_LINE_TYPE_FLAG 'f' /** * parse_route_line: @@ -601,42 +591,45 @@ parse_route_line (const char *line, char buf1[256]; char buf2[256]; ParseLineInfo infos[] = { - [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, - .type = PARSE_LINE_TYPE_UINT32, }, - [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, - .type = PARSE_LINE_TYPE_ADDR, }, - [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, - .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (addr_family != AF_INET6), }, - [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, - .type = PARSE_LINE_TYPE_UINT8, - .int_base_16 = TRUE, - .ignore = (addr_family != AF_INET), }, - [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU, - .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, - - [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", - .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, - .disabled = (options_route != NULL), }, - [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", - .type = PARSE_LINE_TYPE_ADDR, - .disabled = (options_route != NULL), }, - [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", - .type = PARSE_LINE_TYPE_UINT32, - .disabled = (options_route != NULL), }, - - [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", - .type = PARSE_LINE_TYPE_IFNAME, - .ignore = TRUE, - .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_TABLE] = { .key = NM_IP_ROUTE_ATTRIBUTE_TABLE, + .type = PARSE_LINE_TYPE_UINT32, }, + [PARSE_LINE_ATTR_ROUTE_SRC] = { .key = NM_IP_ROUTE_ATTRIBUTE_SRC, + .type = PARSE_LINE_TYPE_ADDR, }, + [PARSE_LINE_ATTR_ROUTE_FROM] = { .key = NM_IP_ROUTE_ATTRIBUTE_FROM, + .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, + .disabled = (addr_family != AF_INET6), }, + [PARSE_LINE_ATTR_ROUTE_TOS] = { .key = NM_IP_ROUTE_ATTRIBUTE_TOS, + .type = PARSE_LINE_TYPE_UINT8, + .int_base_16 = TRUE, + .ignore = (addr_family != AF_INET), }, + [PARSE_LINE_ATTR_ROUTE_ONLINK] = { .key = NM_IP_ROUTE_ATTRIBUTE_ONLINK, + .type = PARSE_LINE_TYPE_FLAG, + .ignore = (addr_family != AF_INET), }, + [PARSE_LINE_ATTR_ROUTE_WINDOW] = { .key = NM_IP_ROUTE_ATTRIBUTE_WINDOW, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_CWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_CWND, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_INITCWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITCWND, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_INITRWND] = { .key = NM_IP_ROUTE_ATTRIBUTE_INITRWND, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + [PARSE_LINE_ATTR_ROUTE_MTU] = { .key = NM_IP_ROUTE_ATTRIBUTE_MTU, + .type = PARSE_LINE_TYPE_UINT32_WITH_LOCK, }, + + [PARSE_LINE_ATTR_ROUTE_TO] = { .key = "to", + .type = PARSE_LINE_TYPE_ADDR_WITH_PREFIX, + .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_VIA] = { .key = "via", + .type = PARSE_LINE_TYPE_ADDR, + .disabled = (options_route != NULL), }, + [PARSE_LINE_ATTR_ROUTE_METRIC] = { .key = "metric", + .type = PARSE_LINE_TYPE_UINT32, + .disabled = (options_route != NULL), }, + + [PARSE_LINE_ATTR_ROUTE_DEV] = { .key = "dev", + .type = PARSE_LINE_TYPE_IFNAME, + .ignore = TRUE, + .disabled = (options_route != NULL), }, }; nm_assert (line); @@ -705,6 +698,9 @@ parse_route_line (const char *line, case PARSE_LINE_TYPE_IFNAME: i_words++; goto parse_line_type_ifname; + case PARSE_LINE_TYPE_FLAG: + i_words++; + goto next; default: nm_assert_not_reached (); } @@ -913,6 +909,15 @@ next: ? nm_sprintf_buf (buf2, "/%u", (unsigned) info->v.addr.plen) : "")); break; + case PARSE_LINE_TYPE_FLAG: + /* XXX: the flag (for "onlink") only allows to explictly set "TRUE". + * There is no way to express an explicit "FALSE" setting + * of this attribute, hence, the file format cannot encode + * that configuration. */ + nm_ip_route_set_attribute (route, + info->key, + g_variant_new_boolean (TRUE)); + break; default: nm_assert_not_reached (); break; @@ -1141,7 +1146,7 @@ error: } static NMSetting * -make_user_setting (shvarFile *ifcfg, GError **error) +make_user_setting (shvarFile *ifcfg) { gboolean has_user_data = FALSE; gs_unref_object NMSettingUser *s_user = NULL; @@ -1189,7 +1194,7 @@ make_user_setting (shvarFile *ifcfg, GError **error) } static NMSetting * -make_proxy_setting (shvarFile *ifcfg, GError **error) +make_proxy_setting (shvarFile *ifcfg) { NMSettingProxy *s_proxy = NULL; gs_free char *value = NULL; @@ -1239,7 +1244,7 @@ make_proxy_setting (shvarFile *ifcfg, GError **error) static NMSetting * make_ip4_setting (shvarFile *ifcfg, - const char *network_file, + shvarFile *network_ifcfg, gboolean routes_read, gboolean *out_has_defroute, GError **error) @@ -1255,7 +1260,6 @@ make_ip4_setting (shvarFile *ifcfg, int i; guint32 a; gboolean has_key; - shvarFile *network_ifcfg; shvarFile *route_ifcfg; gboolean never_default; gint64 timeout; @@ -1282,7 +1286,6 @@ make_ip4_setting (shvarFile *ifcfg, } /* Then check if GATEWAYDEV; it's global and overrides DEFROUTE */ - network_ifcfg = svOpenFile (network_file, NULL); if (network_ifcfg) { gs_free char *gatewaydev_value = NULL; const char *gatewaydev; @@ -1299,7 +1302,6 @@ make_ip4_setting (shvarFile *ifcfg, never_default = !!strcmp (v, gatewaydev); nm_clear_g_free (&value); - svCloseFile (network_ifcfg); } v = svGetValueStr (ifcfg, "BOOTPROTO", &value); @@ -1424,12 +1426,10 @@ make_ip4_setting (shvarFile *ifcfg, /* Gateway */ if (!gateway) { - network_ifcfg = svOpenFile (network_file, NULL); if (network_ifcfg) { gboolean read_success; read_success = read_ip4_address (network_ifcfg, "GATEWAY", &has_key, &a, error); - svCloseFile (network_ifcfg); if (!read_success) return NULL; if (has_key) { @@ -1665,16 +1665,15 @@ read_aliases (NMSettingIPConfig *s_ip4, gboolean read_defroute, const char *file static NMSetting * make_ip6_setting (shvarFile *ifcfg, - const char *network_file, + shvarFile *network_ifcfg, gboolean routes_read, GError **error) { NMSettingIPConfig *s_ip6 = NULL; + const char *v; char *value = NULL; char *str_value; char *route6_path = NULL; - gs_free char *dns_options_free = NULL; - const char *dns_options = NULL; gboolean ipv6init, ipv6forwarding, dhcp6 = FALSE; char *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; char *ipv6addr, *ipv6addr_secondaries; @@ -1684,7 +1683,6 @@ make_ip6_setting (shvarFile *ifcfg, int i_val; GError *local = NULL; gint priority; - shvarFile *network_ifcfg; gboolean never_default = FALSE; gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip; NMSettingIP6ConfigPrivacy ip6_privacy_val; @@ -1703,7 +1701,6 @@ make_ip6_setting (shvarFile *ifcfg, * they are global and override IPV6_DEFROUTE * When both are set, the device specified in IPV6_DEFAULTGW takes preference. */ - network_ifcfg = svOpenFile (network_file, NULL); if (network_ifcfg) { char *ipv6_defaultgw, *ipv6_defaultdev; char *default_dev = NULL; @@ -1712,7 +1709,6 @@ make_ip6_setting (shvarFile *ifcfg, value = svGetValueStr_cp (ifcfg, "DEVICE"); ipv6_defaultgw = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTGW"); ipv6_defaultdev = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTDEV"); - dns_options = svGetValue (network_ifcfg, "RES_OPTIONS", &dns_options_free); if (ipv6_defaultgw) { default_dev = strchr (ipv6_defaultgw, '%'); @@ -1731,7 +1727,6 @@ make_ip6_setting (shvarFile *ifcfg, g_free (ipv6_defaultgw); g_free (ipv6_defaultdev); g_free (value); - svCloseFile (network_ifcfg); } /* Find out method property */ @@ -1739,11 +1734,8 @@ make_ip6_setting (shvarFile *ifcfg, str_value = svGetValueStr_cp (ifcfg, "IPV6INIT"); ipv6init = svGetValueBoolean (ifcfg, "IPV6INIT", FALSE); if (!str_value) { - network_ifcfg = svOpenFile (network_file, NULL); - if (network_ifcfg) { + if (network_ifcfg) ipv6init = svGetValueBoolean (network_ifcfg, "IPV6INIT", FALSE); - svCloseFile (network_ifcfg); - } } g_free (str_value); @@ -1865,11 +1857,8 @@ make_ip6_setting (shvarFile *ifcfg, value = svGetValueStr_cp (ifcfg, "IPV6_DEFAULTGW"); if (!value) { /* If no gateway in the ifcfg, try global /etc/sysconfig/network instead */ - network_ifcfg = svOpenFile (network_file, NULL); - if (network_ifcfg) { + if (network_ifcfg) value = svGetValueStr_cp (network_ifcfg, "IPV6_DEFAULTGW"); - svCloseFile (network_ifcfg); - } } if (value) { char *ptr; @@ -1930,8 +1919,6 @@ make_ip6_setting (shvarFile *ifcfg, g_free (value); } - /* DNS searches ('DOMAIN' key) are read by make_ip4_setting() and included in NMSettingIPConfig */ - if (!routes_read) { /* NOP */ } else { @@ -1942,9 +1929,24 @@ make_ip6_setting (shvarFile *ifcfg, g_free (route6_path); } + /* DNS searches */ + nm_clear_g_free (&value); + v = svGetValueStr (ifcfg, "IPV6_DOMAIN", &value); + if (v) { + gs_free const char **searches = NULL; + + searches = nm_utils_strsplit_set (v, " "); + if (searches) { + for (iter = searches; *iter; iter++) { + if (!nm_setting_ip_config_add_dns_search (s_ip6, *iter)) + PARSE_WARNING ("duplicate DNS domain '%s'", *iter); + } + } + } + /* DNS options */ - parse_dns_options (s_ip6, svGetValue (ifcfg, "RES_OPTIONS", &value)); - parse_dns_options (s_ip6, dns_options); + nm_clear_g_free (&value); + parse_dns_options (s_ip6, svGetValue (ifcfg, "IPV6_RES_OPTIONS", &value)); g_free (value); /* DNS priority */ @@ -1962,6 +1964,59 @@ error: return NULL; } +static NMSetting * +make_tc_setting (shvarFile *ifcfg) +{ + NMSettingTCConfig *s_tc = NULL; + char tag[256]; + int i; + + s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new (); + + for (i = 1;; i++) { + NMTCQdisc *qdisc = NULL; + gs_free char *value_to_free = NULL; + const char *value = NULL; + GError *local = NULL; + + value = svGetValueStr (ifcfg, numbered_tag (tag, "QDISC", i), &value_to_free); + if (!value) + break; + + qdisc = nm_utils_tc_qdisc_from_str (value, &local); + if (!qdisc) + PARSE_WARNING ("ignoring bad qdisc: '%s': %s", value, local->message); + + if (!nm_setting_tc_config_add_qdisc (s_tc, qdisc)) + PARSE_WARNING ("duplicate qdisc"); + } + + for (i = 1;; i++) { + NMTCTfilter *tfilter = NULL; + gs_free char *value_to_free = NULL; + const char *value = NULL; + GError *local = NULL; + + value = svGetValueStr (ifcfg, numbered_tag (tag, "FILTER", i), &value_to_free); + if (!value) + break; + + tfilter = nm_utils_tc_tfilter_from_str (value, &local); + if (!tfilter) + PARSE_WARNING ("ignoring bad tfilter: '%s': %s", value, local->message); + + if (!nm_setting_tc_config_add_tfilter (s_tc, tfilter)) + PARSE_WARNING ("duplicate filter"); + } + + if ( nm_setting_tc_config_get_num_qdiscs (s_tc) > 0 + || nm_setting_tc_config_get_num_tfilters (s_tc) > 0) + return NM_SETTING (s_tc); + + g_object_unref (s_tc); + return NULL; +} + typedef struct { const char *enable_key; const char *advertise_key; @@ -2195,7 +2250,6 @@ read_dcb_percent_array (shvarFile *ifcfg, static gboolean make_dcb_setting (shvarFile *ifcfg, - const char *network_file, NMSetting **out_setting, GError **error) { @@ -2350,54 +2404,39 @@ add_one_wep_key (shvarFile *ifcfg, NMSettingWirelessSecurity *s_wsec, GError **error) { - char *key = NULL; - char *value = NULL; - gboolean success = FALSE; + gs_free char *value_free = NULL; + const char *value; + const char *key = NULL; g_return_val_if_fail (ifcfg != NULL, FALSE); g_return_val_if_fail (shvar_key != NULL, FALSE); g_return_val_if_fail (key_idx <= 3, FALSE); g_return_val_if_fail (s_wsec != NULL, FALSE); - value = svGetValueStr_cp (ifcfg, shvar_key); + value = svGetValueStr (ifcfg, shvar_key, &value_free); if (!value) return TRUE; /* Validate keys */ if (passphrase) { - if (strlen (value) && strlen (value) < 64) { - key = g_strdup (value); - g_object_set (G_OBJECT (s_wsec), - NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, - NM_WEP_KEY_TYPE_PASSPHRASE, - NULL); - } + if (value[0] && strlen (value) < 64) + key = value; } else { - if (strlen (value) == 10 || strlen (value) == 26) { + if (NM_IN_SET (strlen (value), 10, 26)) { /* Hexadecimal WEP key */ - char *p = value; - - while (*p) { - if (!g_ascii_isxdigit (*p)) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid hexadecimal WEP key."); - goto out; - } - p++; + if (NM_STRCHAR_ANY (value, ch, !g_ascii_isxdigit (ch))) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid hexadecimal WEP key."); + return FALSE; } - key = g_strdup (value); + key = value; } else if ( !strncmp (value, "s:", 2) - && (strlen (value) == 7 || strlen (value) == 15)) { + && NM_IN_SET (strlen (value), 7, 15)) { /* ASCII key */ - char *p = value + 2; - - while (*p) { - if (!g_ascii_isprint ((int) (*p))) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid ASCII WEP key."); - goto out; - } - p++; + if (NM_STRCHAR_ANY (value + 2, ch, !g_ascii_isprint (ch))) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid ASCII WEP key."); + return FALSE; } /* Remove 's:' prefix. @@ -2406,51 +2445,50 @@ add_one_wep_key (shvarFile *ifcfg, * before passing to wpa_supplicant, this prevents two unnecessary conversions. And mainly, * ASCII WEP key doesn't change to HEX WEP key in UI, which could confuse users. */ - key = g_strdup (value + 2); + key = value + 2; } } - if (key) { - nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, key); - g_free (key); - success = TRUE; - } else { + if (!key) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid WEP key length."); + return FALSE; } -out: - g_free (value); - return success; + nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, key); + return TRUE; } static gboolean read_wep_keys (shvarFile *ifcfg, + NMWepKeyType key_type, guint8 def_idx, NMSettingWirelessSecurity *s_wsec, GError **error) { - /* Try hex/ascii keys first */ - if (!add_one_wep_key (ifcfg, "KEY1", 0, FALSE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY2", 1, FALSE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY3", 2, FALSE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY4", 3, FALSE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY", def_idx, FALSE, s_wsec, error)) - return FALSE; + if (key_type != NM_WEP_KEY_TYPE_PASSPHRASE) { + if (!add_one_wep_key (ifcfg, "KEY1", 0, FALSE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY2", 1, FALSE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY3", 2, FALSE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY4", 3, FALSE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY", def_idx, FALSE, s_wsec, error)) + return FALSE; + } - /* And then passphrases */ - if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE1", 0, TRUE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE2", 1, TRUE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE3", 2, TRUE, s_wsec, error)) - return FALSE; - if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE4", 3, TRUE, s_wsec, error)) - return FALSE; + if (key_type != NM_WEP_KEY_TYPE_KEY) { + if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE1", 0, TRUE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE2", 1, TRUE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE3", 2, TRUE, s_wsec, error)) + return FALSE; + if (!add_one_wep_key (ifcfg, "KEY_PASSPHRASE4", 3, TRUE, s_wsec, error)) + return FALSE; + } return TRUE; } @@ -2515,19 +2553,40 @@ make_wep_setting (shvarFile *ifcfg, /* Read keys in the ifcfg file if they are system-owned */ if (key_flags == NM_SETTING_SECRET_FLAG_NONE) { - if (!read_wep_keys (ifcfg, default_key_idx, s_wsec, error)) + NMWepKeyType key_type; + const char *v; + gs_free char *to_free = NULL; + + v = svGetValueStr (ifcfg, "KEY_TYPE", &to_free); + if (!v) + key_type = NM_WEP_KEY_TYPE_UNKNOWN; + else if (nm_streq (v, "key")) + key_type = NM_WEP_KEY_TYPE_KEY; + else if (nm_streq (v, "passphrase")) + key_type = NM_WEP_KEY_TYPE_PASSPHRASE; + else { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid KEY_TYPE value '%s'", v); + return FALSE; + } + + if (!read_wep_keys (ifcfg, key_type, default_key_idx, s_wsec, error)) return NULL; /* Try to get keys from the "shadow" key file */ keys_ifcfg = utils_get_keys_ifcfg (file, FALSE); if (keys_ifcfg) { - if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wsec, error)) { + if (!read_wep_keys (keys_ifcfg, key_type, default_key_idx, s_wsec, error)) { svCloseFile (keys_ifcfg); return NULL; } svCloseFile (keys_ifcfg); g_assert (error == NULL || *error == NULL); } + + g_object_set (G_OBJECT (s_wsec), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, key_type, + NULL); } value = svGetValueStr_cp (ifcfg, "SECURITYMODE"); @@ -3577,25 +3636,25 @@ make_wireless_security_setting (shvarFile *ifcfg, return NULL; /* unencrypted */ } -static char ** +static const char ** transform_hwaddr_blacklist (const char *blacklist) { - char **strv, **iter; - int shift = 0; - - strv = _nm_utils_strsplit_set (blacklist, " \t", 0); - for (iter = strv; iter && *iter; iter++) { - if (shift) { - *(iter - shift) = *iter; - *iter = NULL; - } - if (!nm_utils_hwaddr_valid (*(iter - shift), ETH_ALEN)) { - PARSE_WARNING ("invalid MAC in HWADDR_BLACKLIST '%s'", *(iter - shift)); - g_free (*(iter - shift)); - *(iter - shift) = NULL; - shift++; + const char **strv; + gsize i, j; + + strv = nm_utils_strsplit_set (blacklist, " \t"); + if (!strv) + return NULL; + for (i = 0, j = 0; strv[j]; j++) { + const char *s = strv[j]; + + if (!nm_utils_hwaddr_valid (s, ETH_ALEN)) { + PARSE_WARNING ("invalid MAC in HWADDR_BLACKLIST '%s'", s); + continue; } + strv[i++] = s; } + strv[i] = NULL; return strv; } @@ -3630,13 +3689,12 @@ make_wireless_setting (shvarFile *ifcfg, g_object_set (s_wireless, NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, value, NULL); g_free (value); - value = svGetValueStr_cp (ifcfg, "HWADDR_BLACKLIST"); - if (value) { - char **strv; + cvalue = svGetValueStr (ifcfg, "HWADDR_BLACKLIST", &value); + if (cvalue) { + gs_free const char **strv = NULL; - strv = transform_hwaddr_blacklist (value); + strv = transform_hwaddr_blacklist (cvalue); g_object_set (s_wireless, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, strv, NULL); - g_strfreev (strv); g_free (value); } @@ -4096,6 +4154,7 @@ make_wired_setting (shvarFile *ifcfg, GError **error) { gs_unref_object NMSettingWired *s_wired = NULL; + const char *cvalue; gs_free char *value = NULL; char *nettype; @@ -4204,11 +4263,11 @@ make_wired_setting (shvarFile *ifcfg, NULL); nm_clear_g_free (&value); - value = svGetValueStr_cp (ifcfg, "HWADDR_BLACKLIST"); - if (value) { - gs_strfreev char **strv = NULL; + cvalue = svGetValueStr (ifcfg, "HWADDR_BLACKLIST", &value); + if (cvalue) { + gs_free const char **strv = NULL; - strv = transform_hwaddr_blacklist (value); + strv = transform_hwaddr_blacklist (cvalue); g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, strv, NULL); nm_clear_g_free (&value); } @@ -4633,66 +4692,114 @@ team_connection_from_ifcfg (const char *file, return connection; } +typedef enum { + BRIDGE_OPT_TYPE_MAIN, + BRIDGE_OPT_TYPE_OPTION, + BRIDGE_OPT_TYPE_PORT_MAIN, + BRIDGE_OPT_TYPE_PORT_OPTION, +} BridgeOptType; + typedef void (*BridgeOptFunc) (NMSetting *setting, gboolean stp, const char *key, - const char *value); + const char *value, + BridgeOptType opt_type); static void handle_bridge_option (NMSetting *setting, gboolean stp, const char *key, - const char *value) + const char *value, + BridgeOptType opt_type) { - guint32 u = 0; + static const struct { + const char *key; + const char *property_name; + BridgeOptType opt_type; + gboolean only_with_stp; + gboolean extended_bool; + } m/*etadata*/[] = { + { "DELAY", NM_SETTING_BRIDGE_FORWARD_DELAY, BRIDGE_OPT_TYPE_MAIN, .only_with_stp = TRUE }, + { "priority", NM_SETTING_BRIDGE_PRIORITY, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "hello_time", NM_SETTING_BRIDGE_HELLO_TIME, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "max_age", NM_SETTING_BRIDGE_MAX_AGE, BRIDGE_OPT_TYPE_OPTION, .only_with_stp = TRUE }, + { "ageing_time", NM_SETTING_BRIDGE_AGEING_TIME, BRIDGE_OPT_TYPE_OPTION }, + { "multicast_snooping", NM_SETTING_BRIDGE_MULTICAST_SNOOPING, BRIDGE_OPT_TYPE_OPTION }, + { "group_fwd_mask", NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, BRIDGE_OPT_TYPE_OPTION }, + { "priority", NM_SETTING_BRIDGE_PORT_PRIORITY, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "path_cost", NM_SETTING_BRIDGE_PORT_PATH_COST, BRIDGE_OPT_TYPE_PORT_OPTION }, + { "hairpin_mode", NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, BRIDGE_OPT_TYPE_PORT_OPTION, .extended_bool = TRUE, }, + }; + const char *error_message = NULL; + int i; + gint64 v; - if (!strcmp (key, "priority")) { - if (stp == FALSE) - PARSE_WARNING ("'priority' invalid when STP is disabled"); - else if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_PRIORITY, u, NULL); - else - PARSE_WARNING ("invalid priority value '%s'", value); - } else if (!strcmp (key, "hello_time")) { - if (stp == FALSE) - PARSE_WARNING ("'hello_time' invalid when STP is disabled"); - else if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_HELLO_TIME, u, NULL); - else - PARSE_WARNING ("invalid hello_time value '%s'", value); - } else if (!strcmp (key, "max_age")) { - if (stp == FALSE) - PARSE_WARNING ("'max_age' invalid when STP is disabled"); - else if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_MAX_AGE, u, NULL); - else - PARSE_WARNING ("invalid max_age value '%s'", value); - } else if (!strcmp (key, "ageing_time")) { - if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_AGEING_TIME, u, NULL); - else - PARSE_WARNING ("invalid ageing_time value '%s'", value); - } else if (!strcmp (key, "multicast_snooping")) { - if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_MULTICAST_SNOOPING, - (gboolean) u, NULL); - else - PARSE_WARNING ("invalid multicast_snooping value '%s'", value); - } else if (!strcmp (key, "group_fwd_mask")) { - if (get_uint (value, &u) && u <= 0xFFFF && !NM_FLAGS_ANY (u, 7)) - g_object_set (setting, NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, - (gboolean) u, NULL); - else - PARSE_WARNING ("invalid group_fwd_mask value '%s'", value); - } else - PARSE_WARNING ("unhandled bridge option '%s'", key); + for (i = 0; i < G_N_ELEMENTS (m); i++) { + GParamSpec *param_spec; + + if (opt_type != m[i].opt_type) + continue; + if (!nm_streq (key, m[i].key)) + continue; + if (m[i].only_with_stp && !stp) { + PARSE_WARNING ("'%s' invalid when STP is disabled", key); + return; + } + + param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), m[i].property_name); + switch (param_spec->value_type) { + case G_TYPE_BOOLEAN: + if (m[i].extended_bool) { + if (!strcasecmp (value, "on") || !strcasecmp (value, "yes") || !strcmp (value, "1")) + v = TRUE; + else if (!strcasecmp (value, "off") || !strcasecmp (value, "no")) + v = FALSE; + else { + error_message = "is not a boolean"; + goto warn; + } + } else { + v = _nm_utils_ascii_str_to_int64 (value, 10, 0, 1, -1); + if (v == -1) { + error_message = g_strerror (errno); + goto warn; + } + } + if (!nm_g_object_set_property_boolean (G_OBJECT (setting), m[i].property_name, v, NULL)) { + error_message = "number is out of range"; + goto warn; + } + return; + case G_TYPE_UINT: + v = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT, -1); + if (v == -1) { + error_message = g_strerror (errno); + goto warn; + } + if (!nm_g_object_set_property_uint (G_OBJECT (setting), m[i].property_name, v, NULL)) { + error_message = "number is out of range"; + goto warn; + } + return; + default: + nm_assert_not_reached (); + continue; + } + +warn: + PARSE_WARNING ("invalid %s value '%s': %s", key, value, error_message); + return; + } + + PARSE_WARNING ("unhandled bridge option '%s'", key); } static void handle_bridging_opts (NMSetting *setting, gboolean stp, const char *value, - BridgeOptFunc func) + BridgeOptFunc func, + BridgeOptType opt_type) { gs_free const char **items = NULL; const char *const *iter; @@ -4707,7 +4814,7 @@ handle_bridging_opts (NMSetting *setting, key = *keys; val = *(keys + 1); if (val && key[0] && val[0]) - func (setting, stp, key, val); + func (setting, stp, key, val, opt_type); } } } @@ -4717,30 +4824,29 @@ make_bridge_setting (shvarFile *ifcfg, const char *file, GError **error) { - NMSettingBridge *s_bridge; - char *value; - guint32 u; + gs_unref_object NMSettingBridge *s_bridge = NULL; + gs_free char *value_to_free = NULL; + const char *value; gboolean stp = FALSE; gboolean stp_set = FALSE; - value = svGetValueStr_cp (ifcfg, "DEVICE"); + value = svGetValueStr (ifcfg, "DEVICE", &value_to_free); if (!value) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "mandatory DEVICE keyword missing"); return NULL; } - g_free (value); + nm_clear_g_free (&value_to_free); s_bridge = NM_SETTING_BRIDGE (nm_setting_bridge_new ()); - value = svGetValueStr_cp (ifcfg, "MACADDR"); + value = svGetValueStr (ifcfg, "BRIDGE_MACADDR", &value_to_free); if (value) { - value = g_strstrip (value); g_object_set (s_bridge, NM_SETTING_BRIDGE_MAC_ADDRESS, value, NULL); - g_free (value); + nm_clear_g_free (&value_to_free); } - value = svGetValueStr_cp (ifcfg, "STP"); + value = svGetValueStr (ifcfg, "STP", &value_to_free); if (value) { if (!strcasecmp (value, "on") || !strcasecmp (value, "yes")) { g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, TRUE, NULL); @@ -4751,7 +4857,7 @@ make_bridge_setting (shvarFile *ifcfg, stp_set = TRUE; } else PARSE_WARNING ("invalid STP value '%s'", value); - g_free (value); + nm_clear_g_free (&value_to_free); } if (!stp_set) { @@ -4759,25 +4865,19 @@ make_bridge_setting (shvarFile *ifcfg, g_object_set (s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL); } - value = svGetValueStr_cp (ifcfg, "DELAY"); + value = svGetValueStr (ifcfg, "DELAY", &value_to_free); if (value) { - if (stp) { - if (get_uint (value, &u)) - g_object_set (s_bridge, NM_SETTING_BRIDGE_FORWARD_DELAY, u, NULL); - else - PARSE_WARNING ("invalid forward delay value '%s'", value); - } else - PARSE_WARNING ("DELAY invalid when STP is disabled"); - g_free (value); + handle_bridge_option (NM_SETTING (s_bridge), stp, "DELAY", value, BRIDGE_OPT_TYPE_MAIN); + nm_clear_g_free (&value_to_free); } - value = svGetValueStr_cp (ifcfg, "BRIDGING_OPTS"); + value = svGetValueStr (ifcfg, "BRIDGING_OPTS", &value_to_free); if (value) { - handle_bridging_opts (NM_SETTING (s_bridge), stp, value, handle_bridge_option); - g_free (value); + handle_bridging_opts (NM_SETTING (s_bridge), stp, value, handle_bridge_option, BRIDGE_OPT_TYPE_OPTION); + nm_clear_g_free (&value_to_free); } - return (NMSetting *) s_bridge; + return (NMSetting *) g_steal_pointer (&s_bridge); } static NMConnection * @@ -4788,6 +4888,8 @@ bridge_connection_from_ifcfg (const char *file, NMConnection *connection = NULL; NMSetting *con_setting = NULL; NMSetting *bridge_setting = NULL; + NMSetting *wired_setting = NULL; + NMSetting8021x *s_8021x = NULL; g_return_val_if_fail (file != NULL, NULL); g_return_val_if_fail (ifcfg != NULL, NULL); @@ -4810,57 +4912,40 @@ bridge_connection_from_ifcfg (const char *file, } nm_connection_add_setting (connection, bridge_setting); - return connection; -} + wired_setting = make_wired_setting (ifcfg, file, &s_8021x, error); + if (!wired_setting) { + g_object_unref (connection); + return NULL; + } + nm_connection_add_setting (connection, wired_setting); -static void -handle_bridge_port_option (NMSetting *setting, - gboolean stp, - const char *key, - const char *value) -{ - guint32 u = 0; + if (s_8021x) + nm_connection_add_setting (connection, NM_SETTING (s_8021x)); - if (!strcmp (key, "priority")) { - if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_PORT_PRIORITY, u, NULL); - else - PARSE_WARNING ("invalid priority value '%s'", value); - } else if (!strcmp (key, "path_cost")) { - if (get_uint (value, &u)) - g_object_set (setting, NM_SETTING_BRIDGE_PORT_PATH_COST, u, NULL); - else - PARSE_WARNING ("invalid path_cost value '%s'", value); - } else if (!strcmp (key, "hairpin_mode")) { - if (!strcasecmp (value, "on") || !strcasecmp (value, "yes") || !strcmp (value, "1")) - g_object_set (setting, NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, TRUE, NULL); - else if (!strcasecmp (value, "off") || !strcasecmp (value, "no")) - g_object_set (setting, NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, FALSE, NULL); - else - PARSE_WARNING ("invalid hairpin_mode value '%s'", value); - } else - PARSE_WARNING ("unhandled bridge port option '%s'", key); + return connection; } static NMSetting * make_bridge_port_setting (shvarFile *ifcfg) { NMSetting *s_port = NULL; - char *value; + gs_free char *value_to_free = NULL; + const char *value; g_return_val_if_fail (ifcfg != NULL, FALSE); - value = svGetValueStr_cp (ifcfg, "BRIDGE_UUID"); + value = svGetValueStr (ifcfg, "BRIDGE_UUID", &value_to_free); if (!value) - value = svGetValueStr_cp (ifcfg, "BRIDGE"); + value = svGetValueStr (ifcfg, "BRIDGE", &value_to_free); if (value) { - g_free (value); + nm_clear_g_free (&value_to_free); s_port = nm_setting_bridge_port_new (); - value = svGetValueStr_cp (ifcfg, "BRIDGING_OPTS"); - if (value) - handle_bridging_opts (s_port, FALSE, value, handle_bridge_port_option); - g_free (value); + value = svGetValueStr (ifcfg, "BRIDGING_OPTS", &value_to_free); + if (value) { + handle_bridging_opts (s_port, FALSE, value, handle_bridge_option, BRIDGE_OPT_TYPE_PORT_OPTION); + nm_clear_g_free (&value_to_free); + } } return s_port; @@ -5206,10 +5291,11 @@ connection_from_file_full (const char *filename, gboolean *out_ignore_error) { nm_auto_shvar_file_close shvarFile *parsed = NULL; + nm_auto_shvar_file_close shvarFile *network_ifcfg = NULL; gs_unref_object NMConnection *connection = NULL; gs_free char *type = NULL; char *devtype, *bootproto; - NMSetting *s_ip4, *s_ip6, *s_proxy, *s_port, *s_dcb = NULL, *s_user; + NMSetting *s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user; const char *ifcfg_name = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; @@ -5233,6 +5319,8 @@ connection_from_file_full (const char *filename, if (!parsed) return NULL; + network_ifcfg = svOpenFile (network_file, NULL); + if (!svGetValueBoolean (parsed, "NM_CONTROLLED", TRUE)) { connection = create_unhandled_connection (filename, parsed, "unmanaged", out_unhandled); if (!connection) { @@ -5442,7 +5530,7 @@ connection_from_file_full (const char *filename, } s_ip6 = make_ip6_setting (parsed, - network_file, + network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, error); if (!s_ip6) @@ -5451,7 +5539,7 @@ connection_from_file_full (const char *filename, nm_connection_add_setting (connection, s_ip6); s_ip4 = make_ip4_setting (parsed, - network_file, + network_ifcfg, !has_complex_routes_v4 && !has_complex_routes_v6, &has_ip4_defroute, error); @@ -5464,17 +5552,21 @@ connection_from_file_full (const char *filename, nm_connection_add_setting (connection, s_ip4); } - /* There is only one DOMAIN variable and it is read and put to IPv4 config - * But if IPv4 is disabled or the config fails for some reason, we read - * DOMAIN and put the values into IPv6 config instead. + s_tc = make_tc_setting (parsed); + if (s_tc) + nm_connection_add_setting (connection, s_tc); + + /* For backwards compatibility, if IPv4 is disabled or the + * config fails for some reason, we read DOMAIN and put the + * values into IPv6 config instead of IPv4. */ check_dns_search_domains (parsed, s_ip4, s_ip6); - s_proxy = make_proxy_setting (parsed, error); + s_proxy = make_proxy_setting (parsed); if (s_proxy) nm_connection_add_setting (connection, s_proxy); - s_user = make_user_setting (parsed, error); + s_user = make_user_setting (parsed); if (s_user) nm_connection_add_setting (connection, s_user); @@ -5488,7 +5580,7 @@ connection_from_file_full (const char *filename, if (s_port) nm_connection_add_setting (connection, s_port); - if (!make_dcb_setting (parsed, network_file, &s_dcb, error)) + if (!make_dcb_setting (parsed, &s_dcb, error)) return NULL; if (s_dcb) nm_connection_add_setting (connection, s_dcb); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 6434ad7d..862e640e 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -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. * - * (C) Copyright 2008 - 2012 Red Hat, Inc. + * (C) Copyright 2008 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -243,12 +243,6 @@ utils_get_route_ifcfg (const char *parent, gboolean should_create) return utils_get_extra_ifcfg (parent, ROUTE_TAG, should_create); } -shvarFile * -utils_get_route6_ifcfg (const char *parent, gboolean should_create) -{ - return utils_get_extra_ifcfg (parent, ROUTE6_TAG, should_create); -} - /* Finds out if route file has new or older format * Returns TRUE - new syntax (ADDRESS<n>=a.b.c.d ...), error opening file or empty * FALSE - older syntax, i.e. argument to 'ip route add' (1.2.3.0/24 via 11.22.33.44) diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index e7abf4d8..3756af7c 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -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. * - * (C) Copyright 2008 - 2012 Red Hat, Inc. + * (C) Copyright 2008 - 2017 Red Hat, Inc. */ #ifndef _UTILS_H_ @@ -45,7 +45,6 @@ char *utils_get_route6_path (const char *parent); shvarFile *utils_get_extra_ifcfg (const char *parent, const char *tag, gboolean should_create); shvarFile *utils_get_keys_ifcfg (const char *parent, gboolean should_create); shvarFile *utils_get_route_ifcfg (const char *parent, gboolean should_create); -shvarFile *utils_get_route6_ifcfg (const char *parent, gboolean should_create); gboolean utils_has_route_file_new_syntax (const char *filename); gboolean utils_has_complex_routes (const char *filename, int addr_family); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 5c8de7d1..5cb8ee98 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -150,7 +150,7 @@ write_secrets (shvarFile *ifcfg, /* sort the keys. */ secrets_keys = (const char **) g_hash_table_get_keys_as_array (secrets, &secrets_keys_n); - if (secrets_keys) { + if (secrets_keys_n > 1) { g_qsort_with_data (secrets_keys, secrets_keys_n, sizeof (const char *), @@ -662,12 +662,26 @@ write_wireless_security_setting (NMConnection *connection, /* And write the new ones out */ if (wep) { + NMWepKeyType key_type; + const char *key_type_str = NULL; + /* Default WEP TX key index */ svSetValueInt64 (ifcfg, "DEFAULTKEY", nm_setting_wireless_security_get_wep_tx_keyidx(s_wsec) + 1); - for (i = 0; i < 4; i++) { - NMWepKeyType key_type; + key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec); + switch (key_type) { + case NM_WEP_KEY_TYPE_KEY: + key_type_str = "key"; + break; + case NM_WEP_KEY_TYPE_PASSPHRASE: + key_type_str = "passphrase"; + break; + case NM_WEP_KEY_TYPE_UNKNOWN: + break; + } + svSetValue (ifcfg, "KEY_TYPE", key_type_str); + for (i = 0; i < 4; i++) { key = nm_setting_wireless_security_get_wep_key (s_wsec, i); if (key) { gs_free char *ascii_key = NULL; @@ -678,7 +692,6 @@ write_wireless_security_setting (NMConnection *connection, * are some passphrases that are indistinguishable from WEP hex * keys. */ - key_type = nm_setting_wireless_security_get_wep_key_type (s_wsec); if (key_type == NM_WEP_KEY_TYPE_UNKNOWN) { if (nm_utils_wep_key_valid (key, NM_WEP_KEY_TYPE_KEY)) key_type = NM_WEP_KEY_TYPE_KEY; @@ -1309,25 +1322,19 @@ write_bond_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wired, svUnsetValue (ifcfg, "BONDING_OPTS"); num_opts = nm_setting_bond_get_num_options (s_bond); - if (num_opts > 0) { - GString *str = g_string_sized_new (64); - - for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) { - const char *key, *value; - - if (!nm_setting_bond_get_option (s_bond, i, &key, &value)) - continue; + if (num_opts) { + nm_auto_free_gstring GString *str = NULL; + const char *name, *value; + str = g_string_sized_new (64); + for (i = 0; i < num_opts; i++) { if (str->len) g_string_append_c (str, ' '); - - g_string_append_printf (str, "%s=%s", key, value); + nm_setting_bond_get_option (s_bond, i, &name, &value); + g_string_append_printf (str, "%s=%s", name, value); } - if (str->len) - svSetValueStr (ifcfg, "BONDING_OPTS", str->str); - - g_string_free (str, TRUE); + svSetValueStr (ifcfg, "BONDING_OPTS", str->str); } svSetValueStr (ifcfg, "TYPE", TYPE_BOND); @@ -1414,7 +1421,7 @@ write_bridge_setting (NMConnection *connection, shvarFile *ifcfg, gboolean *wire svUnsetValue (ifcfg, "DELAY"); mac = nm_setting_bridge_get_mac_address (s_bridge); - svSetValueStr (ifcfg, "MACADDR", mac); + svSetValueStr (ifcfg, "BRIDGE_MACADDR", mac); /* Bridge options */ opts = g_string_sized_new (32); @@ -1928,8 +1935,11 @@ get_route_attributes_string (NMIPRoute *route, int family) g_string_append_printf (str, "%s 0x%02x", names[i], (unsigned) g_variant_get_byte (attr)); } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_TABLE)) { g_string_append_printf (str, "%s %u", names[i], (unsigned) g_variant_get_uint32 (attr)); - } else if ( nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) - || nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_FROM)) { + } else if (nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_ONLINK)) { + if (g_variant_get_boolean (attr)) + g_string_append (str, "onlink"); + } else if (NM_IN_STRSET (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC, + NM_IP_ROUTE_ATTRIBUTE_FROM)) { char *arg = nm_streq (names[i], NM_IP_ROUTE_ATTRIBUTE_SRC) ? "src" : "from"; g_string_append_printf (str, "%s %s", arg, g_variant_get_string (attr, NULL)); @@ -2116,6 +2126,73 @@ write_user_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) } static gboolean +write_tc_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) +{ + NMSettingTCConfig *s_tc; + guint i, num, n; + char tag[64]; + + svUnsetAll (ifcfg, SV_KEY_TYPE_TC); + + s_tc = nm_connection_get_setting_tc_config (connection); + if (!s_tc) + return TRUE; + + num = nm_setting_tc_config_get_num_qdiscs (s_tc); + for (n = 1, i = 0; i < num; i++) { + NMTCQdisc *qdisc; + gs_free char *str = NULL; + + qdisc = nm_setting_tc_config_get_qdisc (s_tc, i); + str = nm_utils_tc_qdisc_to_str (qdisc, error); + if (!str) + return FALSE; + + svSetValueStr (ifcfg, numbered_tag (tag, "QDISC", n), str); + n++; + } + + + num = nm_setting_tc_config_get_num_tfilters (s_tc); + for (n = 1, i = 0; i < num; i++) { + NMTCTfilter *tfilter; + gs_free char *str = NULL; + + tfilter = nm_setting_tc_config_get_tfilter (s_tc, i); + str = nm_utils_tc_tfilter_to_str (tfilter, error); + if (!str) + return FALSE; + + svSetValueStr (ifcfg, numbered_tag (tag, "FILTER", n), str); + n++; + } + + return TRUE; +} + +static void +write_res_options (shvarFile *ifcfg, NMSettingIPConfig *s_ip, const char *var) +{ + nm_auto_free_gstring GString *value = NULL; + guint i, num_options; + + if (!nm_setting_ip_config_has_dns_options (s_ip)) { + svUnsetValue (ifcfg, var); + return; + } + + value = g_string_new (NULL); + num_options = nm_setting_ip_config_get_num_dns_options (s_ip); + for (i = 0; i < num_options; i++) { + if (i > 0) + g_string_append_c (value, ' '); + g_string_append (value, nm_setting_ip_config_get_dns_option (s_ip, i)); + } + + svSetValue (ifcfg, var, value->str); +} + +static gboolean write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, shvarFile **out_route_content_svformat, @@ -2146,6 +2223,7 @@ write_ip4_setting (NMConnection *connection, * Some IPv4 setting related options are not cleared, * for no strong reason. */ svUnsetValue (ifcfg, "BOOTPROTO"); + svUnsetValue (ifcfg, "RES_OPTIONS"); svUnsetAll (ifcfg, SV_KEY_TYPE_IP4_ADDRESS); return TRUE; } @@ -2342,6 +2420,8 @@ write_ip4_setting (NMConnection *connection, else svUnsetValue (ifcfg, "IPV4_DNS_PRIORITY"); + write_res_options (ifcfg, s_ip4, "RES_OPTIONS"); + return TRUE; } @@ -2483,6 +2563,7 @@ write_ip6_setting (NMConnection *connection, svUnsetValue (ifcfg, "IPV6_FAILURE_FATAL"); svUnsetValue (ifcfg, "IPV6_ROUTE_METRIC"); svUnsetValue (ifcfg, "IPV6_ADDR_GEN_MODE"); + svUnsetValue (ifcfg, "IPV6_RES_OPTIONS"); return TRUE; } @@ -2557,21 +2638,20 @@ write_ip6_setting (NMConnection *connection, } } - /* Write out DNS domains - 'DOMAIN' key is shared for both IPv4 and IPv6 domains */ + /* Write out DNS domains */ num = nm_setting_ip_config_get_num_dns_searches (s_ip6); if (num > 0) { - gs_free char *ip4_domains = NULL; nm_auto_free_gstring GString *searches = NULL; - searches = g_string_new (svGetValueStr (ifcfg, "DOMAIN", &ip4_domains)); + searches = g_string_new (NULL); for (i = 0; i < num; i++) { if (searches->len > 0) g_string_append_c (searches, ' '); g_string_append (searches, nm_setting_ip_config_get_dns_search (s_ip6, i)); } - svSetValueStr (ifcfg, "DOMAIN", searches->str); - } - + svSetValueStr (ifcfg, "IPV6_DOMAIN", searches->str); + } else + svUnsetValue (ifcfg, "IPV6_DOMAIN"); /* handle IPV6_DEFROUTE */ /* IPV6_DEFROUTE has the opposite meaning from 'never-default' */ @@ -2638,66 +2718,9 @@ write_ip6_setting (NMConnection *connection, else svUnsetValue (ifcfg, "IPV6_DNS_PRIORITY"); - NM_SET_OUT (out_route6_content, write_route_file (s_ip6)); + write_res_options (ifcfg, s_ip6, "IPV6_RES_OPTIONS"); - return TRUE; -} - -static void -add_dns_option (GPtrArray *array, const char *option) -{ - if (_nm_utils_dns_option_find_idx (array, option) < 0) - g_ptr_array_add (array, (gpointer) option); -} - -static gboolean -write_res_options (NMConnection *connection, shvarFile *ifcfg, GError **error) -{ - NMSettingIPConfig *s_ip6; - NMSettingIPConfig *s_ip4; - const char *method; - int i, num_options; - gs_unref_ptrarray GPtrArray *array = NULL; - GString *value; - - s_ip4 = nm_connection_get_setting_ip4_config (connection); - - if (!s_ip4) { - /* slave-type: clear res-options */ - svUnsetValue (ifcfg, "RES_OPTIONS"); - return TRUE; - } - - array = g_ptr_array_new (); - - method = nm_setting_ip_config_get_method (s_ip4); - if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { - num_options = nm_setting_ip_config_get_num_dns_options (s_ip4); - for (i = 0; i < num_options; i++) - add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip4, i)); - } - - s_ip6 = nm_connection_get_setting_ip6_config (connection); - method = nm_setting_ip_config_get_method (s_ip6); - if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { - num_options = nm_setting_ip_config_get_num_dns_options (s_ip6); - for (i = 0; i < num_options; i++) - add_dns_option (array, nm_setting_ip_config_get_dns_option (s_ip6, i)); - } - - if ( array->len > 0 - || nm_setting_ip_config_has_dns_options (s_ip4) - || nm_setting_ip_config_has_dns_options (s_ip6)) { - value = g_string_new (NULL); - for (i = 0; i < array->len; i++) { - if (i > 0) - g_string_append_c (value, ' '); - g_string_append (value, array->pdata[i]); - } - svSetValue (ifcfg, "RES_OPTIONS", value->str); - g_string_free (value, TRUE); - } else - svUnsetValue (ifcfg, "RES_OPTIONS"); + NM_SET_OUT (out_route6_content, write_route_file (s_ip6)); return TRUE; } @@ -2882,6 +2905,9 @@ do_write_construct (NMConnection *connection, if (!write_user_setting (connection, ifcfg, error)) return FALSE; + if (!write_tc_setting (connection, ifcfg, error)) + return FALSE; + svUnsetValue (ifcfg, "DHCP_HOSTNAME"); svUnsetValue (ifcfg, "DHCP_FQDN"); @@ -2930,9 +2956,6 @@ do_write_construct (NMConnection *connection, error)) return FALSE; - if (!write_res_options (connection, ifcfg, error)) - return FALSE; - write_connection_setting (s_con, ifcfg); NM_SET_OUT (out_ifcfg, g_steal_pointer (&ifcfg)); diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index df03bf65..2b64f3fc 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -776,7 +776,7 @@ line_free (shvarLine *line) ASSERT_shvarLine (line); g_free (line->line); g_free (line->key_with_prefix); - c_list_unlink (&line->lst); + c_list_unlink_stale (&line->lst); g_slice_free (shvarLine, line); } @@ -1171,6 +1171,11 @@ svUnsetAll (shvarFile *s, SvKeyType match_key_type) if (g_str_has_prefix (line->key, "NM_USER_")) goto do_clear; } + if (NM_FLAGS_HAS (match_key_type, SV_KEY_TYPE_TC)) { + if ( IS_NUMBERED_TAG (line->key, "QDISC") + || IS_NUMBERED_TAG (line->key, "FILTER")) + goto do_clear; + } continue; do_clear: @@ -1318,7 +1323,7 @@ svWriteFile (shvarFile *s, int mode, GError **error) return FALSE; } - tmpfd = dup (s->fd); + tmpfd = fcntl (s->fd, F_DUPFD_CLOEXEC, 0); if (tmpfd == -1) { int errsv = errno; @@ -1373,7 +1378,8 @@ svCloseFile (shvarFile *s) g_return_if_fail (s != NULL); - nm_close (s->fd); + if (s->fd >= 0) + nm_close (s->fd); g_free (s->fileName); c_list_for_each_safe (current, safe, &s->lst_head) line_free (c_list_entry (current, shvarLine, lst)); diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index c48bbfd3..dbc4d950 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -90,7 +90,8 @@ typedef enum { SV_KEY_TYPE_ANY = (1LL << 0), SV_KEY_TYPE_ROUTE_SVFORMAT = (1LL << 1), SV_KEY_TYPE_IP4_ADDRESS = (1LL << 2), - SV_KEY_TYPE_USER = (1LL << 3), + SV_KEY_TYPE_TC = (1LL << 3), + SV_KEY_TYPE_USER = (1LL << 4), } SvKeyType; gboolean svUnsetAll (shvarFile *s, SvKeyType match_key_type); diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected index 854d2490..5d81dfef 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected @@ -1,4 +1,4 @@ -BONDING_OPTS=mode=balance-rr +BONDING_OPTS="downdelay=5 miimon=100 mode=balance-rr updelay=10" TYPE=Bond BONDING_MASTER=yes PROXY_METHOD=none diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected index 460278e1..2df1fbb3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected @@ -1,6 +1,6 @@ CONNECTED_MODE=no TYPE=InfiniBand -TEAM_PORT_CONFIG="{ \"inf1\": { \"prio\": -10, \"sticky\": true } }" +TEAM_PORT_CONFIG="{\"inf1\": {\"prio\": -10, \"sticky\": true}}" NAME="Test Write Team Infiniband Port" UUID=${UUID} DEVICE=inf1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected index 0b1deb80..ff55cefe 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected @@ -1,4 +1,4 @@ -TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }" +TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}" NAME="Test Write Team Port" UUID=${UUID} ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected new file mode 100644 index 00000000..c0e47c48 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected @@ -0,0 +1,20 @@ +HWADDR=31:33:33:37:BE:CD +MTU=1492 +TYPE=Ethernet +PROXY_METHOD=none +BROWSER_ONLY=no +BOOTPROTO=none +IPADDR=1.1.1.3 +PREFIX=24 +IPADDR1=1.1.1.5 +PREFIX1=24 +GATEWAY=1.1.1.1 +DNS1=4.2.2.1 +DNS2=4.2.2.2 +DOMAIN="foobar.com lab.foobar.com" +DEFROUTE=yes +IPV4_FAILURE_FATAL=no +IPV6INIT=no +NAME="Test Write Wired Static Routes" +UUID=${UUID} +ONBOOT=yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options index 62e301e3..cea2471a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options @@ -8,7 +8,8 @@ NM_CONTROLLED=yes PEERDNS=yes DNS1=10.2.0.4 DOMAIN="lorem.com ipsum.org dolor.edu" -RES_OPTIONS="ndots:3 single-request-reopen inet6" +RES_OPTIONS="ndots:3 single-request-reopen" +IPV6_RES_OPTIONS="inet6" IPV6INIT=yes IPV6_AUTOCONF=no IPV6ADDR="1001:abba::1234/56" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 index 7edc736a..209447b8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 @@ -2,5 +2,5 @@ DEVICE=team0 ONBOOT=no DEVICETYPE=Team BOOTPROTO=dhcp -TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }" +TEAM_CONFIG="{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 index d01e37c5..26e448cc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 @@ -1,5 +1,5 @@ DEVICE=team0 ONBOOT=no BOOTPROTO=dhcp -TEAM_CONFIG="{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }" +TEAM_CONFIG="{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 index 966bec67..80355c26 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 @@ -1,5 +1,5 @@ TYPE=Ethernet -TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }" +TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}" DEVICE=p4p1 TEAM_MASTER=team0 DEVICETYPE=TeamPort diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 index 992510ee..4284737a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 @@ -1,4 +1,4 @@ TYPE=Ethernet -TEAM_PORT_CONFIG="{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }" +TEAM_PORT_CONFIG="{\"p4p1\": {\"prio\": -10, \"sticky\": true}}" DEVICE=p4p1 TEAM_MASTER=team0 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only index 59ec32e5..94189064 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only @@ -7,7 +7,7 @@ USERCTL=yes NM_CONTROLLED=yes PEERDNS=yes DNS1=1:2:3:4::a -DOMAIN="lorem.com ipsum.org dolor.edu" +IPV6_DOMAIN="lorem.com ipsum.org dolor.edu" IPV6INIT=yes IPV6_AUTOCONF=no IPV6ADDR="1001:abba::1234/56" diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static index 6d49c01c..34acf9fe 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static @@ -19,3 +19,4 @@ IPV6ADDR_SECONDARIES="dead:beaf::2/56" DNS3=1:2:3:4::a DNS4=1:2:3:4::b RES_OPTIONS= +IPV6_RES_OPTIONS= diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 10a63b67..8d6aaac2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -7,3 +7,9 @@ NETMASK1=255.255.255.255 GATEWAY1=192.168.1.7 METRIC1=3 OPTIONS1="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 window 30000 initcwnd lock 13 initrwnd 14" + +ADDRESS2=44.55.66.78 +NETMASK2=255.255.255.255 +GATEWAY2=192.168.1.8 +METRIC2=3 +OPTIONS2="mtu lock 9000 cwnd 12 src 1.1.1.1 tos 0x28 onlink window 30000 initcwnd lock 13 initrwnd 14" diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 5044a2d7..6bf27556 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1318,7 +1318,7 @@ test_read_wired_static_routes (void) g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL); /* Routes */ - g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 3); ip4_route = nm_setting_ip_config_get_route (s_ip4, 0); g_assert (ip4_route); @@ -1343,6 +1343,23 @@ test_read_wired_static_routes (void) nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE); nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1"); + ip4_route = nm_setting_ip_config_get_route (s_ip4, 2); + g_assert (ip4_route); + g_assert_cmpstr (nm_ip_route_get_dest (ip4_route), ==, "44.55.66.78"); + g_assert_cmpint (nm_ip_route_get_prefix (ip4_route), ==, 32); + g_assert_cmpstr (nm_ip_route_get_next_hop (ip4_route), ==, "192.168.1.8"); + g_assert_cmpint (nm_ip_route_get_metric (ip4_route), ==, 3); + nmtst_assert_route_attribute_byte (ip4_route, NM_IP_ROUTE_ATTRIBUTE_TOS, 0x28); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, 30000); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_CWND, 12); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITCWND, 13); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_INITRWND, 14); + nmtst_assert_route_attribute_uint32 (ip4_route, NM_IP_ROUTE_ATTRIBUTE_MTU, 9000); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, TRUE); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_LOCK_INITCWND, TRUE); + nmtst_assert_route_attribute_string (ip4_route, NM_IP_ROUTE_ATTRIBUTE_SRC, "1.1.1.1"); + nmtst_assert_route_attribute_boolean (ip4_route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, TRUE); + g_object_unref (connection); } @@ -2145,8 +2162,9 @@ test_read_dns_options (void) NMSettingIPConfig *s_ip4, *s_ip6; char *unmanaged = NULL; const char *option; - const char *options[] = { "ndots:3", "single-request-reopen", "inet6" }; - guint32 i, options_len = sizeof (options) / sizeof (options[0]); + const char *options4[] = { "ndots:3", "single-request-reopen" }; + const char *options6[] = { "inet6" }; + guint32 i, num; connection = _connection_from_file (TEST_IFCFG_DIR "/network-scripts/ifcfg-test-dns-options", NULL, TYPE_ETHERNET, &unmanaged); @@ -2158,18 +2176,20 @@ test_read_dns_options (void) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - i = nm_setting_ip_config_get_num_dns_options (s_ip4); - g_assert_cmpint (i, ==, options_len); - - i = nm_setting_ip_config_get_num_dns_options (s_ip6); - g_assert_cmpint (i, ==, options_len); + num = nm_setting_ip_config_get_num_dns_options (s_ip4); + g_assert_cmpint (num, ==, G_N_ELEMENTS (options4)); - for (i = 0; i < options_len; i++) { + for (i = 0; i < num; i++) { option = nm_setting_ip_config_get_dns_option (s_ip4, i); - g_assert_cmpstr (options[i], ==, option); + g_assert_cmpstr (options4[i], ==, option); + } + + num = nm_setting_ip_config_get_num_dns_options (s_ip6); + g_assert_cmpint (num, ==, G_N_ELEMENTS (options6)); + for (i = 0; i < num; i++) { option = nm_setting_ip_config_get_dns_option (s_ip6, i); - g_assert_cmpstr (options[i], ==, option); + g_assert_cmpstr (options6[i], ==, option); } g_object_unref (connection); @@ -2280,6 +2300,8 @@ test_write_dns_options (void) nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); + nm_setting_ip_config_add_dns_option (s_ip4, "debug"); + /* IP6 setting */ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip6)); @@ -2295,26 +2317,16 @@ test_write_dns_options (void) nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); - nm_setting_ip_config_add_dns_option (s_ip4, "debug"); nm_setting_ip_config_add_dns_option (s_ip6, "timeout:3"); nmtst_assert_connection_verifies (connection); - _writer_new_connection_FIXME (connection, - TEST_SCRATCH_DIR "/network-scripts/", - &testfile); + _writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); - /* RES_OPTIONS is copied to both IPv4 and IPv6 settings */ - nm_setting_ip_config_clear_dns_options (s_ip4, TRUE); - nm_setting_ip_config_add_dns_option (s_ip4, "debug"); - nm_setting_ip_config_add_dns_option (s_ip4, "timeout:3"); - - nm_setting_ip_config_clear_dns_options (s_ip6, TRUE); - nm_setting_ip_config_add_dns_option (s_ip6, "debug"); - nm_setting_ip_config_add_dns_option (s_ip6, "timeout:3"); - nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); } @@ -2674,7 +2686,7 @@ test_read_wifi_wep_passphrase (void) g_assert (s_wsec); g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "none"); g_assert_cmpint (nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec), ==, 0); - g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_PASSPHRASE); + g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_UNKNOWN); g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, "foobar222blahblah"); g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 1)); g_assert (!nm_setting_wireless_security_get_wep_key (s_wsec, 2)); @@ -4175,23 +4187,15 @@ test_write_wired_static (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection_FIXME (connection, - TEST_SCRATCH_DIR "/network-scripts/", - &testfile); + _writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile); route6file = utils_get_route6_path (testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); - /* FIXME: currently DNS domains from IPv6 setting are stored in 'DOMAIN' key in ifcfg-file - * However after re-reading they are dropped into IPv4 setting. - * So, in order to comparison succeeded, move DNS domains back to IPv6 setting. - */ reread_s_ip4 = nm_connection_get_setting_ip4_config (reread); reread_s_ip6 = nm_connection_get_setting_ip6_config (reread); - nm_setting_ip_config_add_dns_search (reread_s_ip6, nm_setting_ip_config_get_dns_search (reread_s_ip4, 2)); - nm_setting_ip_config_add_dns_search (reread_s_ip6, nm_setting_ip_config_get_dns_search (reread_s_ip4, 3)); - nm_setting_ip_config_remove_dns_search (reread_s_ip4, 3); - nm_setting_ip_config_remove_dns_search (reread_s_ip4, 2); g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip4), ==, 204); g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip6), ==, 206); @@ -4329,17 +4333,8 @@ test_write_wired_static_with_generic (void) route6file = utils_get_route6_path (testfile); reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); - - /* FIXME: currently DNS domains from IPv6 setting are stored in 'DOMAIN' key in ifcfg-file - * However after re-reading they are dropped into IPv4 setting. - * So, in order to comparison succeeded, move DNS domains back to IPv6 setting. - */ reread_s_ip4 = nm_connection_get_setting_ip4_config (reread); reread_s_ip6 = nm_connection_get_setting_ip6_config (reread); - nm_setting_ip_config_add_dns_search (reread_s_ip6, nm_setting_ip_config_get_dns_search (reread_s_ip4, 2)); - nm_setting_ip_config_add_dns_search (reread_s_ip6, nm_setting_ip_config_get_dns_search (reread_s_ip4, 3)); - nm_setting_ip_config_remove_dns_search (reread_s_ip4, 3); - nm_setting_ip_config_remove_dns_search (reread_s_ip4, 2); g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip4), ==, 204); g_assert_cmpint (nm_setting_ip_config_get_route_metric (reread_s_ip6), ==, 206); @@ -4748,6 +4743,7 @@ test_write_wired_static_routes (void) NMIPAddress *addr; NMIPRoute *route; GError *error = NULL; + gboolean reread_same = FALSE; connection = nm_simple_connection_new (); @@ -4792,11 +4788,15 @@ test_write_wired_static_routes (void) /* Write out routes */ route = nm_ip_route_new (AF_INET, "1.2.3.0", 24, "222.173.190.239", 0, &error); + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (3455)); + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (TRUE)); g_assert_no_error (error); nm_setting_ip_config_add_route (s_ip4, route); nm_ip_route_unref (route); route = nm_ip_route_new (AF_INET, "3.2.1.0", 24, "202.254.186.190", 77, &error); + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (30000)); + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE)); g_assert_no_error (error); nm_setting_ip_config_add_route (s_ip4, route); nm_ip_route_unref (route); @@ -4818,15 +4818,28 @@ test_write_wired_static_routes (void) nmtst_assert_connection_verifies (connection); - _writer_new_connection (connection, - TEST_SCRATCH_DIR "/network-scripts/", - &testfile); + _writer_new_connection_reread (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + TEST_IFCFG_DIR "/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected", + &reread, + &reread_same); + /* ifcfg does not support setting onlink=0. It gets lost during write+re-read. + * Assert that it's missing, and patch it to check whether the rest of the + * connection equals. */ + g_assert (!reread_same); + nmtst_assert_connection_verifies_without_normalization (reread); + s_ip4 = nm_connection_get_setting_ip4_config (reread); + g_assert (s_ip4); + g_assert_cmpint (nm_setting_ip_config_get_num_routes (s_ip4), ==, 2); + route = nm_setting_ip_config_get_route (s_ip4, 1); + g_assert (route); + g_assert (!nm_ip_route_get_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK)); + nm_ip_route_set_attribute (route, NM_IP_ROUTE_ATTRIBUTE_ONLINK, g_variant_new_boolean (FALSE)); - reread = _connection_from_file (testfile, NULL, TYPE_ETHERNET, NULL); + nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); routefile = utils_get_route_path (testfile); - - nmtst_assert_connection_equals (connection, TRUE, reread, FALSE); } static void @@ -5728,6 +5741,7 @@ test_write_wifi_wep_40_ascii (void) g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 2, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_KEY, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", NULL); nm_setting_wireless_security_set_wep_key (s_wsec, 0, "lorem"); @@ -5815,6 +5829,7 @@ test_write_wifi_wep_104_ascii (void) g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none", NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, 0, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_UNKNOWN, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open", NULL); nm_setting_wireless_security_set_wep_key (s_wsec, 0, "LoremIpsumSit"); @@ -7368,6 +7383,7 @@ test_read_bridge_main (void) { NMConnection *connection; NMSettingBridge *s_bridge; + NMSettingWired *s_wired; const char *mac; char expected_mac_address[ETH_ALEN] = { 0x00, 0x16, 0x41, 0x11, 0x22, 0x33 }; @@ -7390,7 +7406,9 @@ test_read_bridge_main (void) g_assert (!nm_setting_bridge_get_multicast_snooping (s_bridge)); /* MAC address */ - mac = nm_setting_bridge_get_mac_address (s_bridge); + s_wired = nm_connection_get_setting_wired (connection); + g_assert (s_wired); + mac = nm_setting_wired_get_cloned_mac_address (s_wired); g_assert (mac); g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, ETH_ALEN)); @@ -7405,8 +7423,8 @@ test_write_bridge_main (void) gs_unref_object NMConnection *reread = NULL; NMSettingConnection *s_con; NMSettingBridge *s_bridge; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; + NMSettingIPConfig *s_ip4, *s_ip6; + NMSettingWired *s_wired; NMIPAddress *addr; static const char *mac = "31:33:33:37:be:cd"; GError *error = NULL; @@ -7458,6 +7476,10 @@ test_write_bridge_main (void) NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + nm_connection_add_setting (connection, nm_setting_proxy_new ()); nmtst_assert_connection_verifies_without_normalization (connection); @@ -8023,6 +8045,10 @@ test_write_bond_main (void) s_bond = (NMSettingBond *) nm_setting_bond_new (); nm_connection_add_setting (connection, NM_SETTING (s_bond)); + nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "5"); + nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY, "10"); + nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON, "100"); + /* IP4 setting */ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); @@ -8669,7 +8695,7 @@ test_read_team_master (gconstpointer user_data) NMConnection *connection; NMSettingConnection *s_con; NMSettingTeam *s_team; - const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"; + const char *expected_config = "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"; connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL); @@ -8722,7 +8748,7 @@ test_write_team_master (void) NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; NMSettingIPConfig *s_ip6; - const char *expected_config = "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"; + const char *expected_config = "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"; shvarFile *f; connection = nm_simple_connection_new (); @@ -8791,7 +8817,7 @@ test_read_team_port (gconstpointer user_data) NMConnection *connection; NMSettingConnection *s_con; NMSettingTeamPort *s_team_port; - const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"; + const char *expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"; connection = _connection_from_file (PATH_NAME, NULL, TYPE_ETHERNET, NULL); @@ -8816,7 +8842,7 @@ test_write_team_port (void) NMSettingConnection *s_con; NMSettingTeamPort *s_team_port; NMSettingWired *s_wired; - const char *expected_config = "{ \"p4p1\": { \"prio\": -10, \"sticky\": true } }"; + const char *expected_config = "{\"p4p1\": {\"prio\": -10, \"sticky\": true}}"; shvarFile *f; connection = nm_simple_connection_new (); @@ -8871,7 +8897,7 @@ test_write_team_infiniband_port (void) NMSettingConnection *s_con; NMSettingTeamPort *s_team_port; NMSettingInfiniband *s_inf; - const char *expected_config = "{ \"inf1\": { \"prio\": -10, \"sticky\": true } }"; + const char *expected_config = "{\"inf1\": {\"prio\": -10, \"sticky\": true}}"; shvarFile *f; connection = nm_simple_connection_new (); @@ -9232,7 +9258,9 @@ test_svUnescape (void) V0 ("Bob outside LAN", NULL), V1 ("x", "x"), V1 ("'{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }'", - "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"), + "{ \"device\": \"team0\", \"link_watch\": { \"name\": \"ethtool\" } }"), + V1 ("'{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}'", + "{\"device\": \"team0\", \"link_watch\": {\"name\": \"ethtool\"}}"), V1 ("x\"\"b", "xb"), V1 ("x\"c\"b", "xcb"), V1 ("\"c\"b", "cb"), |