ifcfg-rh: merge branch 'th/ifcfg-rh-cleanup-bgo766518'

https://bugzilla.gnome.org/show_bug.cgi?id=766518
This commit is contained in:
Thomas Haller 2016-05-17 12:26:35 +02:00
commit 54474993fd
13 changed files with 116 additions and 145 deletions

View file

@ -21,8 +21,6 @@
#ifndef __COMMON_H__
#define __COMMON_H__
#include "nm-default.h"
#define IFCFG_TAG "ifcfg-"
#define KEYS_TAG "keys-"
#define ROUTE_TAG "route-"
@ -38,7 +36,7 @@
#define AUGNEW_TAG ".augnew"
#define AUGTMP_TAG ".augtmp"
#define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts"
#define IFCFG_DIR SYSCONFDIR "/sysconfig/network-scripts"
#define IFCFG_PLUGIN_NAME "ifcfg-rh"
#define IFCFG_PLUGIN_INFO "(c) 2007 - 2015 Red Hat, Inc. To report bugs please use the NetworkManager mailing list."

View file

@ -20,6 +20,8 @@
#include "nm-default.h"
#include "nm-ifcfg-connection.h"
#include <string.h>
#include <glib/gstdio.h>
@ -37,7 +39,6 @@
#include "common.h"
#include "nm-config.h"
#include "nm-ifcfg-connection.h"
#include "reader.h"
#include "writer.h"
#include "nm-inotify-helper.h"

View file

@ -21,10 +21,8 @@
#ifndef __NETWORKMANAGER_IFCFG_CONNECTION_H__
#define __NETWORKMANAGER_IFCFG_CONNECTION_H__
G_BEGIN_DECLS
#include <nm-dbus-interface.h>
#include <nm-settings-connection.h>
#include "nm-dbus-interface.h"
#include "nm-settings-connection.h"
#define NM_TYPE_IFCFG_CONNECTION (nm_ifcfg_connection_get_type ())
#define NM_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnection))
@ -58,6 +56,4 @@ gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self,
GHashTable *new_settings,
GError **error);
G_END_DECLS
#endif /* __NETWORKMANAGER_IFCFG_CONNECTION_H__ */

View file

@ -23,6 +23,8 @@
#include "nm-default.h"
#include "plugin.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
@ -31,20 +33,19 @@
#include <gmodule.h>
#include "nm-dbus-compat.h"
#include "nm-setting-connection.h"
#include "common.h"
#include "plugin.h"
#include "nm-settings-plugin.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
#include "nm-ifcfg-connection.h"
#include "shvar.h"
#include "common.h"
#include "reader.h"
#include "writer.h"
#include "utils.h"
#include "nm-dbus-compat.h"
#include "nm-exported-object.h"
#include "nmdbus-ifcfg-rh.h"
@ -61,8 +62,6 @@
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} G_STMT_END
#define ERR_GET_MSG(err) (((err) && (err)->message) ? (err)->message : "(unknown)")
static NMIfcfgConnection *update_connection (SettingsPluginIfcfg *plugin,
NMConnection *source,

View file

@ -24,8 +24,6 @@
#ifndef _PLUGIN_H_
#define _PLUGIN_H_
#include "nm-exported-object.h"
#define SETTINGS_TYPE_PLUGIN_IFCFG (settings_plugin_ifcfg_get_type ())
#define SETTINGS_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfg))
#define SETTINGS_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgClass))
@ -46,5 +44,5 @@ struct _SettingsPluginIfcfgClass {
GType settings_plugin_ifcfg_get_type (void);
#endif /* _PLUGIN_H_ */
#endif /* _PLUGIN_H_ */

View file

@ -20,6 +20,8 @@
#include "nm-default.h"
#include "reader.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@ -57,35 +59,31 @@
#include "shvar.h"
#include "utils.h"
#include "reader.h"
/*****************************************************************************/
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)
#define _NMLOG_DOMAIN LOGD_SETTINGS
#define _NMLOG_PREFIX_NAME "ifcfg-rh"
#define _NMLOG(level, ...) \
G_STMT_START { \
nm_log ((level), (_NMLOG_DOMAIN), \
"%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
_NMLOG_PREFIX_NAME": " \
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} G_STMT_END
static gboolean
get_int (const char *str, int *value)
{
char *e;
long int tmp;
#define PARSE_WARNING(...) _LOGW ("%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), " " _NM_UTILS_MACRO_REST(__VA_ARGS__))
errno = 0;
tmp = strtol (str, &e, 0);
if (errno || *e != '\0' || tmp > G_MAXINT || tmp < G_MININT)
return FALSE;
*value = (int) tmp;
return TRUE;
}
/*****************************************************************************/
static gboolean
get_uint (const char *str, guint32 *value)
{
char *e;
long unsigned int tmp;
gint64 tmp;
errno = 0;
tmp = strtoul (str, &e, 0);
if (errno || *e != '\0')
tmp = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT32, -1);
if (tmp == -1)
return FALSE;
*value = (guint32) tmp;
*value = tmp;
return TRUE;
}
@ -242,15 +240,12 @@ make_connection_setting (const char *file,
value = svGetValue (ifcfg, "GATEWAY_PING_TIMEOUT", FALSE);
if (value) {
long int tmp;
guint32 timeout;
gint64 tmp;
errno = 0;
tmp = strtol (value, NULL, 10);
if (errno == 0 && tmp >= 0 && tmp < G_MAXINT32) {
timeout = (guint32) tmp;
g_object_set (s_con, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, timeout, NULL);
} else
tmp = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT32 - 1, -1);
if (tmp >= 0)
g_object_set (s_con, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, (guint) tmp, NULL);
else
PARSE_WARNING ("invalid GATEWAY_PING_TIMEOUT time");
g_free (value);
}
@ -541,7 +536,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError *
char **lines = NULL, **iter;
GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric;
GMatchInfo *match_info;
gint64 prefix_int, metric_int;
int prefix_int;
gint64 metric_int;
gboolean success = FALSE;
const char *pattern_empty = "^\\s*(\\#.*)?$";
@ -609,9 +605,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError *
g_match_info_free (match_info);
prefix_int = 32;
if (prefix) {
errno = 0;
prefix_int = strtol (prefix, NULL, 10);
if (errno || prefix_int <= 0 || prefix_int > 32) {
prefix_int = _nm_utils_ascii_str_to_int64 (prefix, 10, 1, 32, -1);
if (prefix_int == -1) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid IP4 route destination prefix '%s'", prefix);
g_free (prefix);
@ -641,9 +636,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError *
metric_int = -1;
if (g_match_info_matches (match_info)) {
metric = g_match_info_fetch (match_info, 1);
errno = 0;
metric_int = strtol (metric, NULL, 10);
if (errno || metric_int < 0) {
metric_int = _nm_utils_ascii_str_to_int64 (metric, 10, 0, G_MAXUINT32, -1);
if (metric_int == -1) {
g_match_info_free (match_info);
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid IP4 route metric '%s'", metric);
@ -766,7 +760,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error
GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric;
GMatchInfo *match_info;
char *dest = NULL, *prefix = NULL, *next_hop = NULL, *metric = NULL;
gint64 prefix_int, metric_int;
int prefix_int;
gint64 metric_int;
gboolean success = FALSE;
const char *pattern_empty = "^\\s*(\\#.*)?$";
@ -828,9 +823,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error
g_match_info_free (match_info);
prefix_int = 128;
if (prefix) {
errno = 0;
prefix_int = strtol (prefix, NULL, 10);
if (errno || prefix_int <= 0 || prefix_int > 128) {
prefix_int = _nm_utils_ascii_str_to_int64 (prefix, 10, 1, 128, -1);
if (prefix_int == -1) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid IP6 route destination prefix '%s'", prefix);
g_free (dest);
@ -864,9 +858,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error
metric_int = -1;
if (g_match_info_matches (match_info)) {
metric = g_match_info_fetch (match_info, 1);
errno = 0;
metric_int = strtol (metric, NULL, 10);
if (errno || metric_int < 0 || metric_int > G_MAXUINT32) {
metric_int = _nm_utils_ascii_str_to_int64 (metric, 10, 0, G_MAXUINT32, -1);
if (metric_int == -1) {
g_match_info_free (match_info);
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid IP6 route metric '%s'", metric);
@ -1697,10 +1690,9 @@ read_dcb_app (shvarFile *ifcfg,
tmp = g_strdup_printf ("DCB_APP_%s_PRIORITY", app);
val = svGetValue (ifcfg, tmp, FALSE);
if (val) {
success = get_int (val, &priority);
if (success)
success = (priority >= 0 && priority <= 7);
if (!success) {
priority = _nm_utils_ascii_str_to_int64 (val, 0, 0, 7, -1);
if (priority < 0) {
success = FALSE;
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid %s value '%s' (expected 0 - 7)",
tmp, val);
@ -1840,7 +1832,6 @@ read_dcb_percent_array (shvarFile *ifcfg,
char *val;
gboolean success = FALSE;
char **split = NULL, **iter;
int tmp;
guint i, sum = 0;
val = svGetValue (ifcfg, prop, FALSE);
@ -1863,7 +1854,10 @@ read_dcb_percent_array (shvarFile *ifcfg,
}
for (iter = split, i = 0; iter && *iter; iter++, i++) {
if (!get_int (*iter, &tmp) || tmp < 0 || tmp > 100) {
int tmp;
tmp = _nm_utils_ascii_str_to_int64 (*iter, 0, 0, 100, -1);
if (tmp < 0) {
PARSE_WARNING ("invalid %s percentage value '%s'", prop, *iter);
g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"invalid percent element");
@ -2185,7 +2179,7 @@ make_wep_setting (shvarFile *ifcfg,
char *value;
shvarFile *keys_ifcfg = NULL;
int default_key_idx = 0;
gboolean has_default_key = FALSE, success;
gboolean has_default_key = FALSE;
NMSettingSecretFlags key_flags;
s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
@ -2193,18 +2187,17 @@ make_wep_setting (shvarFile *ifcfg,
value = svGetValue (ifcfg, "DEFAULTKEY", FALSE);
if (value) {
success = get_int (value, &default_key_idx);
if (success && (default_key_idx >= 1) && (default_key_idx <= 4)) {
has_default_key = TRUE;
default_key_idx--; /* convert to [0...3] */
g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, default_key_idx, NULL);
} else {
default_key_idx = _nm_utils_ascii_str_to_int64 (value, 0, 1, 4, 0);
if (default_key_idx == 0) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid default WEP key '%s'", value);
g_free (value);
g_free (value);
goto error;
}
g_free (value);
has_default_key = TRUE;
default_key_idx--; /* convert to [0...3] */
g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, (guint) default_key_idx, NULL);
g_free (value);
}
/* Read WEP key flags */
@ -3505,17 +3498,16 @@ make_wireless_setting (shvarFile *ifcfg,
value = svGetValue (ifcfg, "MTU", FALSE);
if (value) {
long int mtu;
int mtu;
errno = 0;
mtu = strtol (value, NULL, 10);
if (errno || mtu < 0 || mtu > 50000) {
mtu = _nm_utils_ascii_str_to_int64 (value, 10, 0, 50000, -1);
if (mtu == -1) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid wireless MTU '%s'", value);
g_free (value);
goto error;
}
g_object_set (s_wireless, NM_SETTING_WIRELESS_MTU, (guint32) mtu, NULL);
g_object_set (s_wireless, NM_SETTING_WIRELESS_MTU, (guint) mtu, NULL);
g_free (value);
}
@ -3777,20 +3769,19 @@ make_wired_setting (shvarFile *ifcfg,
{
NMSettingWired *s_wired;
char *value = NULL;
int mtu;
char *nettype;
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
value = svGetValue (ifcfg, "MTU", FALSE);
if (value) {
if (get_int (value, &mtu)) {
if (mtu >= 0 && mtu < 65536)
g_object_set (s_wired, NM_SETTING_WIRED_MTU, mtu, NULL);
} else {
/* Shouldn't be fatal... */
int mtu;
mtu = _nm_utils_ascii_str_to_int64 (value, 0, 0, 65535, -1);
if (mtu >= 0)
g_object_set (s_wired, NM_SETTING_WIRED_MTU, (guint) mtu, NULL);
else
PARSE_WARNING ("invalid MTU '%s'", value);
}
g_free (value);
}
@ -3961,9 +3952,9 @@ parse_infiniband_p_key (shvarFile *ifcfg,
char **out_parent,
GError **error)
{
char *device = NULL, *physdev = NULL, *pkey_id = NULL, *end;
char *device = NULL, *physdev = NULL, *pkey_id = NULL;
char *ifname = NULL;
guint32 id = G_MAXUINT32;
int id;
gboolean ret = FALSE;
device = svGetValue (ifcfg, "DEVICE", FALSE);
@ -3984,19 +3975,14 @@ parse_infiniband_p_key (shvarFile *ifcfg,
goto done;
}
if (g_str_has_prefix (pkey_id, "0x"))
id = strtoul (pkey_id, &end, 16);
else if (!g_str_has_prefix (pkey_id, "0"))
id = strtoul (pkey_id, &end, 10);
else
end = pkey_id;
if (end == pkey_id || *end || id > 0xFFFF) {
id = _nm_utils_ascii_str_to_int64 (pkey_id, 0, 0, 0xFFFF, -1);
if (id == -1) {
PARSE_WARNING ("invalid InfiniBand PKEY_ID '%s'", pkey_id);
goto done;
}
id = (id | 0x8000);
ifname = g_strdup_printf ("%s.%04x", physdev, id);
ifname = g_strdup_printf ("%s.%04x", physdev, (unsigned) id);
if (strcmp (device, ifname) != 0) {
PARSE_WARNING ("InfiniBand DEVICE (%s) does not match PHYSDEV+PKEY_ID (%s)",
device, ifname);
@ -4028,19 +4014,18 @@ make_infiniband_setting (shvarFile *ifcfg,
{
NMSettingInfiniband *s_infiniband;
char *value = NULL;
int mtu;
s_infiniband = NM_SETTING_INFINIBAND (nm_setting_infiniband_new ());
value = svGetValue (ifcfg, "MTU", FALSE);
if (value) {
if (get_int (value, &mtu)) {
if (mtu >= 0 && mtu < 65536)
g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, mtu, NULL);
} else {
/* Shouldn't be fatal... */
int mtu;
mtu = _nm_utils_ascii_str_to_int64 (value, 0, 0, 65535, -1);
if (mtu >= 0)
g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, (guint) mtu, NULL);
else
PARSE_WARNING ("invalid MTU '%s'", value);
}
g_free (value);
}
@ -4664,16 +4649,14 @@ make_vlan_setting (shvarFile *ifcfg,
char *iface_name = NULL;
char *parent = NULL;
const char *p = NULL;
char *end = NULL;
gint vlan_id = -1;
int vlan_id = -1;
guint32 vlan_flags = 0;
gint gvrp, reorder_hdr;
value = svGetValue (ifcfg, "VLAN_ID", FALSE);
if (value) {
errno = 0;
vlan_id = (gint) g_ascii_strtoll (value, NULL, 10);
if (vlan_id < 0 || vlan_id > 4096 || errno) {
vlan_id = _nm_utils_ascii_str_to_int64 (value, 10, 0, 4095, -1);
if (vlan_id == -1) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"Invalid VLAN_ID '%s'", value);
g_free (value);
@ -4717,12 +4700,13 @@ make_vlan_setting (shvarFile *ifcfg,
}
if (p) {
int device_vlan_id;
/* Grab VLAN ID from interface name; this takes precedence over the
* separate VLAN_ID property for backwards compat.
*/
gint device_vlan_id = (gint) g_ascii_strtoll (p, &end, 10);
if (device_vlan_id >= 0 && device_vlan_id <= 4095 && end != p && !*end)
device_vlan_id = _nm_utils_ascii_str_to_int64 (p, 10, 0, 4095, -1);
if (device_vlan_id != -1)
vlan_id = device_vlan_id;
}
}

View file

@ -21,10 +21,7 @@
#ifndef __READER_H__
#define __READER_H__
#include <nm-connection.h>
#include "nm-default.h"
#include "shvar.h"
#include "nm-connection.h"
NMConnection *connection_from_file (const char *filename,
char **out_unhandled,

View file

@ -25,6 +25,8 @@
#include "nm-default.h"
#include "shvar.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@ -34,12 +36,8 @@
#include <sys/stat.h>
#include <unistd.h>
#include "shvar.h"
#include "nm-core-internal.h"
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)
/* Open the file <name>, returning a shvarFile on success and NULL on failure.
* Add a wrinkle to let the caller specify whether or not to create the file
* (actually, return a structure anyway) if it doesn't exist.
@ -373,11 +371,10 @@ svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 m
result = _nm_utils_ascii_str_to_int64 (tmp, base, min, max, fallback);
errsv = errno;
if (errsv != 0)
PARSE_WARNING ("Error reading '%s' value '%s' as integer (%d)", key, tmp, errsv);
g_free (tmp);
errno = errsv;
return result;
}

View file

@ -31,10 +31,6 @@
#ifndef _SHVAR_H
#define _SHVAR_H
#include "nm-default.h"
G_BEGIN_DECLS
typedef struct _shvarFile shvarFile;
struct _shvarFile {
char *fileName; /* read-only */
@ -95,6 +91,4 @@ const char *svEscape (const char *s, char **to_free);
/* Unescape a string in-place */
void svUnescape (char *s);
G_END_DECLS
#endif /* ! _SHVAR_H */
#endif /* _SHVAR_H */

View file

@ -27,7 +27,8 @@
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "shvar.h"
#include "common.h"
/*
* utils_single_quote_string

View file

@ -21,10 +21,9 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include <nm-connection.h>
#include "nm-default.h"
#include "nm-connection.h"
#include "shvar.h"
#include "common.h"
#define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory")
#define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")"

View file

@ -42,7 +42,6 @@
#include "nm-setting-vlan.h"
#include "nm-setting-team.h"
#include "nm-setting-team-port.h"
#include "nm-core-internal.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
@ -51,8 +50,20 @@
#include "shvar.h"
#include "reader.h"
#include "utils.h"
#include "crypto.h"
/*****************************************************************************/
#define _NMLOG_DOMAIN LOGD_SETTINGS
#define _NMLOG_PREFIX_NAME "ifcfg-rh"
#define _NMLOG(level, ...) \
G_STMT_START { \
nm_log ((level), (_NMLOG_DOMAIN), \
"%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
_NMLOG_PREFIX_NAME": " \
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
} G_STMT_END
/*****************************************************************************/
static void
save_secret_flags (shvarFile *ifcfg,
@ -100,7 +111,7 @@ set_secret (shvarFile *ifcfg,
{
shvarFile *keyfile;
GError *error = NULL;
/* Clear the secret from the ifcfg and the associated "keys" file */
svSetValue (ifcfg, key, NULL, FALSE);
@ -109,7 +120,7 @@ set_secret (shvarFile *ifcfg,
keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE);
if (!keyfile) {
nm_log_warn (LOGD_SETTINGS, " could not create ifcfg file for '%s'", ifcfg->fileName);
_LOGW ("could not create ifcfg file for '%s'", ifcfg->fileName);
goto error;
}
@ -121,8 +132,8 @@ set_secret (shvarFile *ifcfg,
svSetValue (keyfile, key, value, verbatim);
if (!svWriteFile (keyfile, 0600, &error)) {
nm_log_warn (LOGD_SETTINGS, " could not update ifcfg file '%s': %s",
keyfile->fileName, error->message);
_LOGW ("could not update ifcfg file '%s': %s",
keyfile->fileName, error->message);
g_clear_error (&error);
svCloseFile (keyfile);
goto error;
@ -715,7 +726,7 @@ write_wireless_security_setting (NMConnection *connection,
key = ascii_key;
}
} else {
nm_log_warn (LOGD_SETTINGS, " invalid WEP key '%s'", key);
_LOGW ("invalid WEP key '%s'", key);
tmp = NULL;
}

View file

@ -21,11 +21,7 @@
#ifndef _WRITER_H_
#define _WRITER_H_
#include <sys/types.h>
#include <nm-connection.h>
#include "nm-default.h"
#include "nm-connection.h"
gboolean writer_can_write_connection (NMConnection *connection,
GError **error);