keyfile: add IPv6 support (bgo #593814)

(fixes by dcbw to use '/' as the prefix separator)
This commit is contained in:
Jirka Klimes 2010-01-08 11:23:39 -08:00 committed by Dan Williams
parent 686425adce
commit a74e2cfde0
4 changed files with 803 additions and 20 deletions

View file

@ -15,8 +15,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
* Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
*/
#include <errno.h>
@ -27,6 +27,7 @@
#include <dbus/dbus-glib.h>
#include <nm-setting.h>
#include <nm-setting-ip4-config.h>
#include <nm-setting-ip6-config.h>
#include <nm-setting-vpn.h>
#include <nm-setting-connection.h>
#include <nm-setting-wired.h>
@ -69,7 +70,7 @@ get_one_int (const char *str, guint32 max_val, const char *key_name, guint32 *ou
errno = 0;
tmp = strtol (str, NULL, 10);
if (errno || (tmp < 0) || (tmp > max_val)) {
g_warning ("%s: ignoring invalid IPv4 %s item '%s'", __func__, key_name, str);
g_warning ("%s: ignoring invalid IP %s item '%s'", __func__, key_name, str);
return FALSE;
}
@ -78,13 +79,13 @@ get_one_int (const char *str, guint32 max_val, const char *key_name, guint32 *ou
}
static void
free_one_address (gpointer data, gpointer user_data)
free_one_ip4_address (gpointer data, gpointer user_data)
{
g_array_free ((GArray *) data, TRUE);
}
static GPtrArray *
read_addresses (GKeyFile *file,
read_ip4_addresses (GKeyFile *file,
const char *setting_name,
const char *key)
{
@ -166,27 +167,27 @@ ip4_addr_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
GPtrArray *addresses;
const char *setting_name = nm_setting_get_name (setting);
addresses = read_addresses (keyfile, setting_name, key);
addresses = read_ip4_addresses (keyfile, setting_name, key);
/* Work around for previous syntax */
if (!addresses && !strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES))
addresses = read_addresses (keyfile, setting_name, "address");
addresses = read_ip4_addresses (keyfile, setting_name, "address");
if (addresses) {
g_object_set (setting, key, addresses, NULL);
g_ptr_array_foreach (addresses, free_one_address, NULL);
g_ptr_array_foreach (addresses, free_one_ip4_address, NULL);
g_ptr_array_free (addresses, TRUE);
}
}
static void
free_one_route (gpointer data, gpointer user_data)
free_one_ip4_route (gpointer data, gpointer user_data)
{
g_array_free ((GArray *) data, TRUE);
}
static GPtrArray *
read_routes (GKeyFile *file,
read_ip4_routes (GKeyFile *file,
const char *setting_name,
const char *key)
{
@ -272,10 +273,10 @@ ip4_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
GPtrArray *routes;
const char *setting_name = nm_setting_get_name (setting);
routes = read_routes (keyfile, setting_name, key);
routes = read_ip4_routes (keyfile, setting_name, key);
if (routes) {
g_object_set (setting, key, routes, NULL);
g_ptr_array_foreach (routes, free_one_route, NULL);
g_ptr_array_foreach (routes, free_one_ip4_route, NULL);
g_ptr_array_free (routes, TRUE);
}
}
@ -303,8 +304,9 @@ ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
continue;
}
g_array_append_val (array, addr.s_addr);
g_array_append_val (array, addr.s_addr);
}
g_strfreev (list);
if (array) {
g_object_set (setting, key, array, NULL);
@ -312,6 +314,294 @@ ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
}
}
static void
free_one_ip6_address (gpointer data, gpointer user_data)
{
g_value_array_free ((GValueArray *) data);
}
static char *
split_prefix (char *addr)
{
char *slash;
g_return_val_if_fail (addr != NULL, NULL);
/* Find the prefix and split the string */
slash = strchr (addr, '/');
if (slash && slash > addr) {
slash++;
*(slash - 1) = '\0';
}
return slash;
}
static GPtrArray *
read_ip6_addresses (GKeyFile *file,
const char *setting_name,
const char *key)
{
GPtrArray *addresses;
struct in6_addr addr;
guint32 prefix;
int i = 0;
addresses = g_ptr_array_sized_new (3);
/* Look for individual addresses */
while (i++ < 1000) {
char *tmp, *key_name, *str_prefix;
int ret;
GValueArray *values;
GByteArray *address;
GValue value = { 0 };
key_name = g_strdup_printf ("%s%d", key, i);
tmp = g_key_file_get_string (file, setting_name, key_name, NULL);
g_free (key_name);
if (!tmp)
break; /* all done */
/* convert the string array into IPv6 addresses */
values = g_value_array_new (2); /* NMIP6Address has 2 items */
/* Split the address and prefix */
str_prefix = split_prefix (tmp);
/* address */
ret = inet_pton (AF_INET6, tmp, &addr);
if (ret <= 0) {
g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp);
g_value_array_free (values);
goto next;
}
address = g_byte_array_new ();
g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (&value, address);
g_value_array_append (values, &value);
g_value_unset (&value);
/* prefix */
prefix = 0;
if (str_prefix) {
if (!get_one_int (str_prefix, 128, key_name, &prefix)) {
g_value_array_free (values);
goto next;
}
} else {
/* Missing prefix defaults to /64 */
prefix = 64;
}
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, prefix);
g_value_array_append (values, &value);
g_value_unset (&value);
g_ptr_array_add (addresses, values);
next:
g_free (tmp);
}
if (addresses->len < 1) {
g_ptr_array_free (addresses, TRUE);
addresses = NULL;
}
return addresses;
}
static void
ip6_addr_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
{
GPtrArray *addresses;
const char *setting_name = nm_setting_get_name (setting);
addresses = read_ip6_addresses (keyfile, setting_name, key);
if (addresses) {
g_object_set (setting, key, addresses, NULL);
g_ptr_array_foreach (addresses, free_one_ip6_address, NULL);
g_ptr_array_free (addresses, TRUE);
}
}
static void
free_one_ip6_route (gpointer data, gpointer user_data)
{
g_value_array_free ((GValueArray *) data);
}
static GPtrArray *
read_ip6_routes (GKeyFile *file,
const char *setting_name,
const char *key)
{
GPtrArray *routes;
struct in6_addr addr;
guint32 prefix, metric;
int i = 0;
routes = g_ptr_array_sized_new (3);
/* Look for individual routes */
while (i++ < 1000) {
gchar **tmp;
char *key_name, *str_prefix;
gsize length = 0;
int ret;
GValueArray *values;
GByteArray *address;
GValue value = { 0 };
key_name = g_strdup_printf ("%s%d", key, i);
tmp = g_key_file_get_string_list (file, setting_name, key_name, &length, NULL);
g_free (key_name);
if (!tmp || !length)
break; /* all done */
if (length != 3) {
g_warning ("%s: ignoring invalid IPv6 address item '%s'", __func__, key_name);
goto next;
}
/* convert the string array into IPv6 routes */
values = g_value_array_new (4); /* NMIP6Route has 4 items */
/* Split the route and prefix */
str_prefix = split_prefix (tmp[0]);
/* destination address */
ret = inet_pton (AF_INET6, tmp[0], &addr);
if (ret <= 0) {
g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp[0]);
g_value_array_free (values);
goto next;
}
address = g_byte_array_new ();
g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (&value, address);
g_value_array_append (values, &value);
g_value_unset (&value);
/* prefix */
prefix = 0;
if (str_prefix) {
if (!get_one_int (str_prefix, 128, key_name, &prefix)) {
g_value_array_free (values);
goto next;
}
} else {
/* default to 64 if unspecified */
prefix = 64;
}
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, prefix);
g_value_array_append (values, &value);
g_value_unset (&value);
/* next hop address */
ret = inet_pton (AF_INET6, tmp[1], &addr);
if (ret <= 0) {
g_warning ("%s: ignoring invalid IPv6 %s element '%s'", __func__, key_name, tmp[1]);
g_value_array_free (values);
goto next;
}
address = g_byte_array_new ();
g_byte_array_append (address, (guint8 *) addr.s6_addr, 16);
g_value_init (&value, DBUS_TYPE_G_UCHAR_ARRAY);
g_value_take_boxed (&value, address);
g_value_array_append (values, &value);
g_value_unset (&value);
/* metric */
metric = 0;
if (!get_one_int (tmp[2], G_MAXUINT32, key_name, &metric)) {
g_value_array_free (values);
goto next;
}
g_value_init (&value, G_TYPE_UINT);
g_value_set_uint (&value, metric);
g_value_array_append (values, &value);
g_value_unset (&value);
g_ptr_array_add (routes, values);
next:
g_strfreev (tmp);
}
if (routes->len < 1) {
g_ptr_array_free (routes, TRUE);
routes = NULL;
}
return routes;
}
static void
ip6_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
{
GPtrArray *routes;
const char *setting_name = nm_setting_get_name (setting);
routes = read_ip6_routes (keyfile, setting_name, key);
if (routes) {
g_object_set (setting, key, routes, NULL);
g_ptr_array_foreach (routes, free_one_ip6_route, NULL);
g_ptr_array_free (routes, TRUE);
}
}
static void
free_one_ip6_dns (gpointer data, gpointer user_data)
{
g_byte_array_free ((GByteArray *) data, TRUE);
}
static void
ip6_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
{
const char *setting_name = nm_setting_get_name (setting);
GPtrArray *array = NULL;
gsize length;
char **list, **iter;
int ret;
list = g_key_file_get_string_list (keyfile, setting_name, key, &length, NULL);
if (!list || !g_strv_length (list))
return;
array = g_ptr_array_sized_new (length);
for (iter = list; *iter; iter++) {
GByteArray *byte_array;
struct in6_addr addr;
ret = inet_pton (AF_INET6, *iter, &addr);
if (ret <= 0) {
g_warning ("%s: ignoring invalid DNS server IPv6 address '%s'", __func__, *iter);
continue;
}
byte_array = g_byte_array_new ();
g_byte_array_append (byte_array, (guint8 *) addr.s6_addr, 16);
g_ptr_array_add (array, byte_array);
}
g_strfreev (list);
if (array) {
g_object_set (setting, key, array, NULL);
g_ptr_array_foreach (array, free_one_ip6_dns, NULL);
g_ptr_array_free (array, TRUE);
}
}
static void
mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile)
@ -407,22 +697,35 @@ typedef struct {
/* 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".
* i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
* stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
* in struct in6_addr internally, but as string in keyfiles.
*/
static KeyParser key_parsers[] = {
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES,
FALSE,
ip4_addr_parser },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES,
FALSE,
ip6_addr_parser },
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ROUTES,
FALSE,
ip4_route_parser },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES,
FALSE,
ip6_route_parser },
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS,
FALSE,
ip4_dns_parser },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS,
FALSE,
ip6_dns_parser },
{ NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS,
TRUE,

View file

@ -16,7 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 Red Hat, Inc.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
*/
#include <sys/stat.h>
@ -26,6 +26,7 @@
#include <nm-setting.h>
#include <nm-setting-connection.h>
#include <nm-setting-ip4-config.h>
#include <nm-setting-ip6-config.h>
#include <nm-setting-vpn.h>
#include <nm-setting-wired.h>
#include <nm-setting-wireless.h>
@ -184,6 +185,189 @@ ip4_route_writer (GKeyFile *file,
write_ip4_values (file, setting_name, key, array, 4, 0, 2);
}
static void
ip6_dns_writer (GKeyFile *file,
NMSetting *setting,
const char *key,
const GValue *value)
{
GPtrArray *array;
GByteArray *byte_array;
char **list;
int i, num = 0;
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR));
array = (GPtrArray *) g_value_get_boxed (value);
if (!array || !array->len)
return;
list = g_new0 (char *, array->len + 1);
for (i = 0; i < array->len; i++) {
char buf[INET6_ADDRSTRLEN];
byte_array = g_ptr_array_index (array, i);
if (!inet_ntop (AF_INET6, (struct in6_addr *) byte_array->data, buf, sizeof (buf))) {
int j;
GString *ip6_str = g_string_new (NULL);
g_string_append_printf (ip6_str, "%02X", byte_array->data[0]);
for (j = 1; j < 16; j++)
g_string_append_printf (ip6_str, " %02X", byte_array->data[j]);
nm_warning ("%s: error converting IP6 address %s",
__func__, ip6_str->str);
g_string_free (ip6_str, TRUE);
} else
list[num++] = g_strdup (buf);
}
g_key_file_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num);
g_strfreev (list);
}
static gboolean
ip6_array_to_addr (GValueArray *values, guint32 idx, char *buf, size_t buflen)
{
GByteArray *byte_array;
GValue *addr_val;
g_return_val_if_fail (buflen >= INET6_ADDRSTRLEN, FALSE);
/* address */
addr_val = g_value_array_get_nth (values, idx);
byte_array = g_value_get_boxed (addr_val);
errno = 0;
if (!inet_ntop (AF_INET6, (struct in6_addr *) byte_array->data, buf, buflen)) {
GString *ip6_str = g_string_sized_new (INET6_ADDRSTRLEN + 10);
/* error converting the address */
g_string_append_printf (ip6_str, "%02X", byte_array->data[0]);
for (idx = 1; idx < 16; idx++)
g_string_append_printf (ip6_str, " %02X", byte_array->data[idx]);
nm_warning ("%s: error %d converting IP6 address %s",
__func__, errno, ip6_str->str);
g_string_free (ip6_str, TRUE);
return FALSE;
}
return TRUE;
}
static char *
ip6_array_to_addr_prefix (GValueArray *values)
{
GValue *prefix_val;
char *ret = NULL;
GString *ip6_str;
char buf[INET6_ADDRSTRLEN];
/* address */
if (ip6_array_to_addr (values, 0, buf, sizeof (buf))) {
/* Enough space for the address, '/', and the prefix */
ip6_str = g_string_sized_new (INET6_ADDRSTRLEN + 5);
/* prefix */
g_string_append (ip6_str, buf);
prefix_val = g_value_array_get_nth (values, 1);
g_string_append_printf (ip6_str, "/%u", g_value_get_uint (prefix_val));
ret = ip6_str->str;
g_string_free (ip6_str, FALSE);
}
return ret;
}
static void
ip6_addr_writer (GKeyFile *file,
NMSetting *setting,
const char *key,
const GValue *value)
{
GPtrArray *array;
const char *setting_name = nm_setting_get_name (setting);
int i, j;
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS));
array = (GPtrArray *) g_value_get_boxed (value);
if (!array || !array->len)
return;
for (i = 0, j = 1; i < array->len; i++) {
GValueArray *values = g_ptr_array_index (array, i);
char *key_name, *ip6_addr;
if (values->n_values % 2) {
nm_warning ("%s: error writing IP6 address %d; address array length"
" %d is not a multiple of 2.",
__func__, i, values->n_values);
continue;
}
ip6_addr = ip6_array_to_addr_prefix (values);
if (ip6_addr) {
/* Write it out */
key_name = g_strdup_printf ("%s%d", key, j++);
g_key_file_set_string (file, setting_name, key_name, ip6_addr);
g_free (key_name);
g_free (ip6_addr);
}
}
}
static void
ip6_route_writer (GKeyFile *file,
NMSetting *setting,
const char *key,
const GValue *value)
{
GPtrArray *array;
const char *setting_name = nm_setting_get_name (setting);
char *list[3];
int i, j;
g_return_if_fail (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE));
array = (GPtrArray *) g_value_get_boxed (value);
if (!array || !array->len)
return;
for (i = 0, j = 1; i < array->len; i++) {
GValueArray *values = g_ptr_array_index (array, i);
char *key_name;
guint32 int_val;
char buf[INET6_ADDRSTRLEN];
memset (list, 0, sizeof (list));
/* Address and prefix */
list[0] = ip6_array_to_addr_prefix (values);
if (!list[0])
continue;
/* Next Hop */
if (!ip6_array_to_addr (values, 2, buf, sizeof (buf)))
continue;
list[1] = g_strdup (buf);
/* Metric */
value = g_value_array_get_nth (values, 3);
int_val = g_value_get_uint (value);
list[2] = g_strdup_printf ("%d", int_val);
/* Write it out */
key_name = g_strdup_printf ("%s%d", key, j++);
g_key_file_set_string_list (file, setting_name, key_name, (const char **) list, 3);
g_free (key_name);
g_free (list[0]);
g_free (list[1]);
g_free (list[2]);
}
}
static void
mac_address_writer (GKeyFile *file,
NMSetting *setting,
@ -259,19 +443,29 @@ typedef struct {
/* 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".
* i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
* stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
* in struct in6_addr internally, but as string in keyfiles.
*/
static KeyWriter key_writers[] = {
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES,
ip4_addr_writer },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES,
ip6_addr_writer },
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ROUTES,
ip4_route_writer },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES,
ip6_route_writer },
{ NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_DNS,
ip4_dns_writer },
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS,
ip6_dns_writer },
{ NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_WIRED_MAC_ADDRESS,
mac_address_writer },

View file

@ -20,3 +20,13 @@ addresses1=192.168.0.5;24;192.168.0.1;
addresses2=1.2.3.4;16;1.2.1.1;
ignore-auto-routes=false
ignore-auto-dns=false
[ipv6]
method=manual
dns=1111:dddd::aaaa;1::cafe;
dns-search=super-domain.com;redhat.com;gnu.org;
addresses1=abcd:1234:ffff::cdde/64
addresses2=1:2:3:4:5:6:7:8/96
routes1=a:b:c:d::/64;f:e:d:c:1:2:3:4;99;
ignore-auto-routes=false
ignore-auto-dns=false

View file

@ -34,6 +34,7 @@
#include <nm-setting-wired.h>
#include <nm-setting-wireless.h>
#include <nm-setting-ip4-config.h>
#include <nm-setting-ip6-config.h>
#include "nm-test-helpers.h"
@ -50,6 +51,7 @@ test_read_valid_wired_connection (void)
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
GError *error = NULL;
const GByteArray *array;
char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
@ -66,6 +68,18 @@ test_read_valid_wired_connection (void)
const char *expected_address1_gw = "192.168.0.1";
const char *expected_address2_gw = "1.2.1.1";
NMIP4Address *ip4_addr;
const char *expected6_dns1 = "1111:dddd::aaaa";
const char *expected6_dns2 = "1::cafe";
const char *expected6_dnssearch1 = "super-domain.com";
const char *expected6_dnssearch2 = "redhat.com";
const char *expected6_dnssearch3 = "gnu.org";
struct in6_addr addr6;
const char *expected6_address1 = "abcd:1234:ffff::cdde";
const char *expected6_address2 = "1:2:3:4:5:6:7:8";
const char *expected6_route_dest = "a:b:c:d::";
const char *expected6_route_nh = "f:e:d:c:1:2:3:4";
NMIP6Address *ip6_addr;
NMIP6Route *ip6_route;
connection = connection_from_file (TEST_WIRED_FILE);
ASSERT (connection != NULL,
@ -215,7 +229,7 @@ test_read_valid_wired_connection (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 24,
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #1 gateway",
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #1 prefix",
TEST_WIRED_FILE,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -251,7 +265,7 @@ test_read_valid_wired_connection (void)
NM_SETTING_IP4_CONFIG_ADDRESSES);
ASSERT (nm_ip4_address_get_prefix (ip4_addr) == 16,
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #2 gateway",
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #2 prefix",
TEST_WIRED_FILE,
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
@ -278,6 +292,172 @@ test_read_valid_wired_connection (void)
NM_SETTING_IP4_CONFIG_SETTING_NAME,
NM_SETTING_IP4_CONFIG_ADDRESSES);
/* ===== IPv6 SETTING ===== */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG));
ASSERT (s_ip6 != NULL,
"connection-verify-ip6", "failed to verify %s: missing %s setting",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME);
/* Method */
tmp = nm_setting_ip6_config_get_method (s_ip6);
ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_METHOD);
/* DNS Addresses */
ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (inet_pton (AF_INET6, expected6_dns1, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert DNS IP6 address #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (inet_pton (AF_INET6, expected6_dns2, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert DNS IP address #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 2,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
/* DNS Searches */
ASSERT (nm_setting_ip6_config_get_num_dns_searches (s_ip6) == 3,
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS_SEARCH);
ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 0), expected6_dnssearch1),
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS_SEARCH);
ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 1), expected6_dnssearch2),
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS_SEARCH);
ASSERT (!strcmp (nm_setting_ip6_config_get_dns_search (s_ip6, 2), expected6_dnssearch3),
"connection-verify-wired", "failed to verify %s: unexpected %s / %s key value #3",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS_SEARCH);
/* Address #1 */
ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0);
ASSERT (ip6_addr,
"connection-verify-wired", "failed to verify %s: missing IP6 address #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (nm_ip6_address_get_prefix (ip6_addr) == 64,
"connection-verify-wired", "failed to verify %s: unexpected IP6 address #1 prefix",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET6, expected6_address1, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert IP address #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP4 address #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
/* Address #2 */
ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 1);
ASSERT (ip6_addr,
"connection-verify-wired", "failed to verify %s: missing IP6 address #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (nm_ip6_address_get_prefix (ip6_addr) == 96,
"connection-verify-wired", "failed to verify %s: unexpected IP6 address #2 prefix",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
ASSERT (inet_pton (AF_INET6, expected6_address2, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert IP address #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP6 address #2",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ADDRESSES);
/* Route #1 */
ip6_route = nm_setting_ip6_config_get_route (s_ip6, 0);
ASSERT (ip6_route,
"connection-verify-wired", "failed to verify %s: missing IP6 route #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES);
ASSERT (inet_pton (AF_INET6, expected6_route_dest, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert IP route dest #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_route_get_dest (ip6_route), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP4 route dest #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES);
ASSERT (nm_ip6_route_get_prefix (ip6_route) == 64,
"connection-verify-wired", "failed to verify %s: unexpected IP6 route #1 prefix",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES);
ASSERT (inet_pton (AF_INET6, expected6_route_nh, &addr6) > 0,
"connection-verify-wired", "failed to verify %s: couldn't convert IP route next hop #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_DNS);
ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_route_get_next_hop (ip6_route), &addr6),
"connection-verify-wired", "failed to verify %s: unexpected IP4 route dest #1",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES);
ASSERT (nm_ip6_route_get_metric (ip6_route) == 99,
"connection-verify-wired", "failed to verify %s: unexpected IP6 route #1 metric",
TEST_WIRED_FILE,
NM_SETTING_IP6_CONFIG_SETTING_NAME,
NM_SETTING_IP6_CONFIG_ROUTES);
g_object_unref (connection);
}
@ -327,6 +507,49 @@ add_one_ip4_route (NMSettingIP4Config *s_ip4,
nm_ip4_route_unref (route);
}
static void
add_one_ip6_address (NMSettingIP6Config *s_ip6,
const char *addr,
guint32 prefix)
{
struct in6_addr tmp;
NMIP6Address *ip6_addr;
ip6_addr = nm_ip6_address_new ();
nm_ip6_address_set_prefix (ip6_addr, prefix);
inet_pton (AF_INET6, addr, &tmp);
nm_ip6_address_set_address (ip6_addr, &tmp);
nm_setting_ip6_config_add_address (s_ip6, ip6_addr);
nm_ip6_address_unref (ip6_addr);
}
static void
add_one_ip6_route (NMSettingIP6Config *s_ip6,
const char *dest,
const char *nh,
guint32 prefix,
guint32 metric)
{
struct in6_addr addr;
NMIP6Route *route;
route = nm_ip6_route_new ();
nm_ip6_route_set_prefix (route, prefix);
nm_ip6_route_set_metric (route, metric);
inet_pton (AF_INET6, dest, &addr);
nm_ip6_route_set_dest (route, &addr);
inet_pton (AF_INET6, nh, &addr);
nm_ip6_route_set_next_hop (route, &addr);
nm_setting_ip6_config_add_route (s_ip6, route);
nm_ip6_route_unref (route);
}
static void
test_write_wired_connection (void)
{
@ -334,6 +557,7 @@ test_write_wired_connection (void)
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
char *uuid;
GByteArray *mac;
unsigned char tmpmac[] = { 0x99, 0x88, 0x77, 0x66, 0x55, 0x44 };
@ -344,6 +568,7 @@ test_write_wired_connection (void)
pid_t owner_grp;
uid_t owner_uid;
struct in_addr addr;
struct in6_addr addr6;
const char *dns1 = "4.2.2.1";
const char *dns2 = "4.2.2.2";
const char *address1 = "192.168.0.5";
@ -354,6 +579,14 @@ test_write_wired_connection (void)
const char *route1_nh = "10.10.10.1";
const char *route2 = "0.0.0.0";
const char *route2_nh = "1.2.1.1";
const char *dns6_1 = "1::cafe";
const char *dns6_2 = "2::cafe";
const char *address6_1 = "abcd::beef";
const char *address6_2 = "dcba::beef";
const char *route6_1 = "1:2:3:4:5:6:7:8";
const char *route6_1_nh = "8:7:6:5:4:3:2:1";
const char *route6_2 = "::";
const char *route6_2_nh = "2001::1111";
guint64 timestamp = 0x12345678L;
connection = nm_connection_new ();
@ -420,6 +653,35 @@ test_write_wired_connection (void)
inet_pton (AF_INET, dns2, &addr);
nm_setting_ip4_config_add_dns (s_ip4, addr.s_addr);
/* IP6 setting */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
ASSERT (s_ip6 != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_IP6_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
g_object_set (s_ip6,
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
NULL);
/* Addresses */
add_one_ip6_address (s_ip6, address6_1, 64);
add_one_ip6_address (s_ip6, address6_2, 56);
/* Routes */
add_one_ip6_route (s_ip6, route6_1, route6_1_nh, 64, 3);
add_one_ip6_route (s_ip6, route6_2, route6_2_nh, 56, 1);
/* DNS servers */
inet_pton (AF_INET6, dns6_1, &addr6);
nm_setting_ip6_config_add_dns (s_ip6, &addr6);
inet_pton (AF_INET6, dns6_2, &addr6);
nm_setting_ip6_config_add_dns (s_ip6, &addr6);
/* DNS searches */
nm_setting_ip6_config_add_dns_search (s_ip6, "wallaceandgromit.com");
/* Write out the connection */
owner_uid = geteuid ();
owner_grp = getegid ();
@ -570,6 +832,7 @@ test_write_wireless_connection (void)
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
NMSettingIP4Config *s_ip4;
NMSettingIP6Config *s_ip6;
char *uuid;
GByteArray *bssid;
unsigned char tmpbssid[] = { 0xaa, 0xb9, 0xa1, 0x74, 0x55, 0x44 };
@ -640,6 +903,18 @@ test_write_wireless_connection (void)
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
NULL);
/* IP6 setting */
s_ip6 = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new ());
ASSERT (s_ip6 != NULL,
"connection-write", "failed to allocate new %s setting",
NM_SETTING_IP6_CONFIG_SETTING_NAME);
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
g_object_set (s_ip6,
NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NULL);
/* Write out the connection */
owner_uid = geteuid ();
owner_grp = getegid ();
@ -688,6 +963,7 @@ int main (int argc, char **argv)
base = g_path_get_basename (argv[0]);
fprintf (stdout, "%s: SUCCESS\n", base);
g_free (base);
dbus_g_connection_unref (bus);
return 0;
}