mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 16:30:07 +01:00
keyfile: write nicely formatted MAC addresses; clean up "special" key handling
Add testcases for keyfile ip4-config setting writing too.
This commit is contained in:
parent
45f2f1144d
commit
07d3ffbcec
2 changed files with 214 additions and 49 deletions
|
|
@ -27,9 +27,13 @@
|
|||
#include <nm-setting-connection.h>
|
||||
#include <nm-setting-ip4-config.h>
|
||||
#include <nm-setting-vpn.h>
|
||||
#include <nm-setting-wired.h>
|
||||
#include <nm-setting-wireless.h>
|
||||
#include <nm-setting-ip4-config.h>
|
||||
#include <nm-utils.h>
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <nm-settings.h>
|
||||
|
||||
#include "nm-dbus-glib-types.h"
|
||||
|
|
@ -44,44 +48,53 @@ write_array_of_uint (GKeyFile *file,
|
|||
{
|
||||
GArray *array;
|
||||
int i;
|
||||
int *tmp_array;
|
||||
|
||||
array = (GArray *) g_value_get_boxed (value);
|
||||
if (!array || !array->len)
|
||||
return TRUE;
|
||||
|
||||
if (NM_IS_SETTING_IP4_CONFIG (setting) && !strcmp (key, NM_SETTING_IP4_CONFIG_DNS)) {
|
||||
char **list;
|
||||
tmp_array = g_new (gint, array->len);
|
||||
for (i = 0; i < array->len; i++)
|
||||
tmp_array[i] = g_array_index (array, int, i);
|
||||
|
||||
list = g_new0 (char *, array->len + 1);
|
||||
g_key_file_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len);
|
||||
g_free (tmp_array);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < array->len; i++) {
|
||||
char buf[INET_ADDRSTRLEN + 1];
|
||||
struct in_addr addr;
|
||||
static void
|
||||
ip4_dns_writer (GKeyFile *file,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
GArray *array;
|
||||
char **list;
|
||||
int i, num = 0;
|
||||
|
||||
addr.s_addr = g_array_index (array, guint32, i);
|
||||
if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (addr.s_addr));
|
||||
list[i] = NULL;
|
||||
} else {
|
||||
list[i] = g_strdup (buf);
|
||||
}
|
||||
}
|
||||
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UINT_ARRAY));
|
||||
|
||||
g_key_file_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, array->len);
|
||||
g_strfreev (list);
|
||||
} else {
|
||||
int *tmp_array;
|
||||
array = (GArray *) g_value_get_boxed (value);
|
||||
if (!array || !array->len)
|
||||
return;
|
||||
|
||||
tmp_array = g_new (gint, array->len);
|
||||
for (i = 0; i < array->len; i++)
|
||||
tmp_array[i] = g_array_index (array, int, i);
|
||||
list = g_new0 (char *, array->len + 1);
|
||||
|
||||
g_key_file_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len);
|
||||
g_free (tmp_array);
|
||||
for (i = 0; i < array->len; i++) {
|
||||
char buf[INET_ADDRSTRLEN + 1];
|
||||
struct in_addr addr;
|
||||
|
||||
addr.s_addr = g_array_index (array, guint32, i);
|
||||
if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
|
||||
nm_warning ("%s: error converting IP4 address 0x%X",
|
||||
__func__, ntohl (addr.s_addr));
|
||||
} else
|
||||
list[num++] = g_strdup (buf);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
g_key_file_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num);
|
||||
g_strfreev (list);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -96,7 +109,7 @@ write_ip4_values (GKeyFile *file,
|
|||
char **list = NULL;
|
||||
int i, j;
|
||||
|
||||
list = g_malloc (tuple_len);
|
||||
list = g_new (char *, tuple_len);
|
||||
|
||||
for (i = 0, j = 0; i < array->len; i++, j++) {
|
||||
GArray *tuple = g_ptr_array_index (array, i);
|
||||
|
|
@ -104,7 +117,7 @@ write_ip4_values (GKeyFile *file,
|
|||
char *key_name;
|
||||
int k;
|
||||
|
||||
memset (list, 0, tuple_len);
|
||||
memset (list, 0, tuple_len * sizeof (char *));
|
||||
|
||||
for (k = 0; k < tuple_len; k++) {
|
||||
if (k == addr1_pos || k == addr2_pos) {
|
||||
|
|
@ -139,28 +152,64 @@ write_ip4_values (GKeyFile *file,
|
|||
g_free (list);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_array_of_array_of_uint (GKeyFile *file,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
static void
|
||||
ip4_addr_writer (GKeyFile *file,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
GPtrArray *array;
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
|
||||
/* Only handle IPv4 addresses and routes for now */
|
||||
if (!NM_IS_SETTING_IP4_CONFIG (setting))
|
||||
return FALSE;
|
||||
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
|
||||
|
||||
array = (GPtrArray *) g_value_get_boxed (value);
|
||||
if (!array || !array->len)
|
||||
return TRUE;
|
||||
if (array && array->len)
|
||||
write_ip4_values (file, setting_name, key, array, 3, 0, 2);
|
||||
}
|
||||
|
||||
if (!strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES))
|
||||
write_ip4_values (file, nm_setting_get_name (setting), key, array, 3, 0, 2);
|
||||
else if (!strcmp (key, NM_SETTING_IP4_CONFIG_ROUTES))
|
||||
write_ip4_values (file, nm_setting_get_name (setting), key, array, 4, 0, 2);
|
||||
static void
|
||||
ip4_route_writer (GKeyFile *file,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
GPtrArray *array;
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
|
||||
return TRUE;
|
||||
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT));
|
||||
|
||||
array = (GPtrArray *) g_value_get_boxed (value);
|
||||
if (array && array->len)
|
||||
write_ip4_values (file, setting_name, key, array, 4, 0, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
mac_address_writer (GKeyFile *file,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
GByteArray *array;
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
char *mac;
|
||||
struct ether_addr tmp;
|
||||
|
||||
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY));
|
||||
|
||||
array = (GByteArray *) g_value_get_boxed (value);
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
if (array->len != ETH_ALEN) {
|
||||
nm_warning ("%s: invalid %s / %s MAC address length %d",
|
||||
__func__, setting_name, key, array->len);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (tmp.ether_addr_octet, array->data, ETH_ALEN);
|
||||
mac = ether_ntoa (&tmp);
|
||||
g_key_file_set_string (file, setting_name, key, mac);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -202,6 +251,36 @@ write_hash_of_string (GKeyFile *file,
|
|||
g_hash_table_foreach (hash, write_hash_of_string_helper, &info);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *setting_name;
|
||||
const char *key;
|
||||
void (*writer) (GKeyFile *keyfile, NMSetting *setting, const char *key, const GValue *value);
|
||||
} KeyWriter;
|
||||
|
||||
/* A table of keys that require further parsing/conversion becuase they are
|
||||
* stored in a format that can't be automatically read using the key's type.
|
||||
* i.e. IP addresses, which are stored in NetworkManager as guint32, but are
|
||||
* stored in keyfiles as strings, eg "10.1.1.2".
|
||||
*/
|
||||
static KeyWriter key_writers[] = {
|
||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP4_CONFIG_ADDRESSES,
|
||||
ip4_addr_writer },
|
||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP4_CONFIG_ROUTES,
|
||||
ip4_route_writer },
|
||||
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP4_CONFIG_DNS,
|
||||
ip4_dns_writer },
|
||||
{ NM_SETTING_WIRED_SETTING_NAME,
|
||||
NM_SETTING_WIRED_MAC_ADDRESS,
|
||||
mac_address_writer },
|
||||
{ NM_SETTING_WIRELESS_SETTING_NAME,
|
||||
NM_SETTING_WIRELESS_MAC_ADDRESS,
|
||||
mac_address_writer },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
write_setting_value (NMSetting *setting,
|
||||
const char *key,
|
||||
|
|
@ -212,6 +291,7 @@ write_setting_value (NMSetting *setting,
|
|||
GKeyFile *file = (GKeyFile *) user_data;
|
||||
const char *setting_name;
|
||||
GType type;
|
||||
KeyWriter *writer = &key_writers[0];
|
||||
|
||||
type = G_VALUE_TYPE (value);
|
||||
|
||||
|
|
@ -226,6 +306,15 @@ write_setting_value (NMSetting *setting,
|
|||
|
||||
setting_name = nm_setting_get_name (setting);
|
||||
|
||||
/* Look through the list of handlers for non-standard format key values */
|
||||
while (writer->setting_name) {
|
||||
if (!strcmp (writer->setting_name, setting_name) && !strcmp (writer->key, key)) {
|
||||
(*writer->writer) (file, setting, key, value);
|
||||
return;
|
||||
}
|
||||
writer++;
|
||||
}
|
||||
|
||||
if (type == G_TYPE_STRING) {
|
||||
const char *str;
|
||||
|
||||
|
|
@ -261,7 +350,7 @@ write_setting_value (NMSetting *setting,
|
|||
g_key_file_set_integer_list (file, setting_name, key, tmp_array, array->len);
|
||||
g_free (tmp_array);
|
||||
}
|
||||
} else if (type == dbus_g_type_get_collection ("GSList", G_TYPE_STRING)) {
|
||||
} else if (type == DBUS_TYPE_G_LIST_OF_STRING) {
|
||||
GSList *list;
|
||||
GSList *iter;
|
||||
|
||||
|
|
@ -277,18 +366,13 @@ write_setting_value (NMSetting *setting,
|
|||
g_key_file_set_string_list (file, setting_name, key, (const gchar **const) array, i);
|
||||
g_free (array);
|
||||
}
|
||||
} else if (type == dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)) {
|
||||
} else if (type == DBUS_TYPE_G_MAP_OF_STRING) {
|
||||
write_hash_of_string (file, setting, key, value);
|
||||
} else if (type == DBUS_TYPE_G_UINT_ARRAY) {
|
||||
if (!write_array_of_uint (file, setting, key, value)) {
|
||||
g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
|
||||
setting_name, key, g_type_name (type));
|
||||
}
|
||||
} else if (type == DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT) {
|
||||
if (!write_array_of_array_of_uint (file, setting, key, value)) {
|
||||
g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
|
||||
setting_name, key, g_type_name (type));
|
||||
}
|
||||
} else {
|
||||
g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
|
||||
setting_name, key, g_type_name (type));
|
||||
|
|
|
|||
|
|
@ -297,6 +297,52 @@ test_read_valid_wired_connection (void)
|
|||
g_object_unref (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
add_one_ip4_address (NMSettingIP4Config *s_ip4,
|
||||
const char *addr,
|
||||
const char *gw,
|
||||
guint32 prefix)
|
||||
{
|
||||
struct in_addr tmp;
|
||||
NMIP4Address *ip4_addr;
|
||||
|
||||
ip4_addr = nm_ip4_address_new ();
|
||||
nm_ip4_address_set_prefix (ip4_addr, prefix);
|
||||
|
||||
inet_pton (AF_INET, addr, &tmp);
|
||||
nm_ip4_address_set_address (ip4_addr, tmp.s_addr);
|
||||
|
||||
inet_pton (AF_INET, gw, &tmp);
|
||||
nm_ip4_address_set_gateway (ip4_addr, tmp.s_addr);
|
||||
|
||||
nm_setting_ip4_config_add_address (s_ip4, ip4_addr);
|
||||
nm_ip4_address_unref (ip4_addr);
|
||||
}
|
||||
|
||||
static void
|
||||
add_one_ip4_route (NMSettingIP4Config *s_ip4,
|
||||
const char *dest,
|
||||
const char *nh,
|
||||
guint32 prefix,
|
||||
guint32 metric)
|
||||
{
|
||||
struct in_addr addr;
|
||||
NMIP4Route *route;
|
||||
|
||||
route = nm_ip4_route_new ();
|
||||
nm_ip4_route_set_prefix (route, prefix);
|
||||
nm_ip4_route_set_metric (route, metric);
|
||||
|
||||
inet_pton (AF_INET, dest, &addr);
|
||||
nm_ip4_route_set_dest (route, addr.s_addr);
|
||||
|
||||
inet_pton (AF_INET, nh, &addr);
|
||||
nm_ip4_route_set_next_hop (route, addr.s_addr);
|
||||
|
||||
nm_setting_ip4_config_add_route (s_ip4, route);
|
||||
nm_ip4_route_unref (route);
|
||||
}
|
||||
|
||||
static void
|
||||
test_write_wired_connection (void)
|
||||
{
|
||||
|
|
@ -313,11 +359,24 @@ test_write_wired_connection (void)
|
|||
GError *error = NULL;
|
||||
pid_t owner_grp;
|
||||
uid_t owner_uid;
|
||||
struct in_addr addr;
|
||||
const char *dns1 = "4.2.2.1";
|
||||
const char *dns2 = "4.2.2.2";
|
||||
const char *address1 = "192.168.0.5";
|
||||
const char *address1_gw = "192.168.0.1";
|
||||
const char *address2 = "1.2.3.4";
|
||||
const char *address2_gw = "1.2.1.1";
|
||||
const char *route1 = "10.10.10.2";
|
||||
const char *route1_nh = "10.10.10.1";
|
||||
const char *route2 = "0.0.0.0";
|
||||
const char *route2_nh = "1.2.1.1";
|
||||
|
||||
connection = nm_connection_new ();
|
||||
ASSERT (connection != NULL,
|
||||
"connection-write", "failed to allocate new connection");
|
||||
|
||||
/* Connection setting */
|
||||
|
||||
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
|
||||
ASSERT (s_con != NULL,
|
||||
"connection-write", "failed to allocate new %s setting",
|
||||
|
|
@ -334,6 +393,8 @@ test_write_wired_connection (void)
|
|||
NULL);
|
||||
g_free (uuid);
|
||||
|
||||
/* Wired setting */
|
||||
|
||||
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
|
||||
ASSERT (s_wired != NULL,
|
||||
"connection-write", "failed to allocate new %s setting",
|
||||
|
|
@ -348,12 +409,32 @@ test_write_wired_connection (void)
|
|||
NULL);
|
||||
g_byte_array_free (mac, TRUE);
|
||||
|
||||
/* IP4 setting */
|
||||
|
||||
s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
|
||||
ASSERT (s_ip4 != NULL,
|
||||
"connection-write", "failed to allocate new %s setting",
|
||||
NM_SETTING_WIRED_SETTING_NAME);
|
||||
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
|
||||
|
||||
g_object_set (s_ip4,
|
||||
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
||||
NULL);
|
||||
|
||||
/* Addresses */
|
||||
add_one_ip4_address (s_ip4, address1, address1_gw, 24);
|
||||
add_one_ip4_address (s_ip4, address2, address2_gw, 8);
|
||||
|
||||
/* Routes */
|
||||
add_one_ip4_route (s_ip4, route1, route1_nh, 24, 3);
|
||||
add_one_ip4_route (s_ip4, route2, route2_nh, 8, 1);
|
||||
|
||||
/* DNS servers */
|
||||
inet_pton (AF_INET, dns1, &addr);
|
||||
nm_setting_ip4_config_add_dns (s_ip4, addr.s_addr);
|
||||
inet_pton (AF_INET, dns2, &addr);
|
||||
nm_setting_ip4_config_add_dns (s_ip4, addr.s_addr);
|
||||
|
||||
/* Write out the connection */
|
||||
owner_uid = geteuid ();
|
||||
owner_grp = getegid ();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue