diff --git a/callouts/nm-dispatcher-utils.c b/callouts/nm-dispatcher-utils.c index d2deb41fdf..8feec72d25 100644 --- a/callouts/nm-dispatcher-utils.c +++ b/callouts/nm-dispatcher-utils.c @@ -92,7 +92,7 @@ static GSList * construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix) { GPtrArray *addresses, *routes; - char **dns, **wins; + char **dns, **wins, *gateway; GString *tmp; GVariant *val; int i; @@ -106,26 +106,24 @@ construct_ip4_items (GSList *items, GVariant *ip4_config, const char *prefix) /* IP addresses */ val = g_variant_lookup_value (ip4_config, "addresses", G_VARIANT_TYPE ("aau")); if (val) { - addresses = nm_utils_ip4_addresses_from_variant (val); + addresses = nm_utils_ip4_addresses_from_variant (val, &gateway); + if (!gateway) + gateway = g_strdup ("0.0.0.0"); for (i = 0; i < addresses->len; i++) { NMIPAddress *addr = addresses->pdata[i]; - const char *gw; char *addrtmp; - gw = nm_ip_address_get_gateway (addr); - if (!gw) - gw = "0.0.0.0"; - addrtmp = g_strdup_printf ("%sIP4_ADDRESS_%d=%s/%d %s", prefix, i, nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr), - gw); + gateway); items = g_slist_prepend (items, addrtmp); } if (addresses->len) items = g_slist_prepend (items, g_strdup_printf ("%sIP4_NUM_ADDRESSES=%d", prefix, addresses->len)); g_ptr_array_unref (addresses); + g_free (gateway); g_variant_unref (val); } @@ -228,7 +226,7 @@ static GSList * construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix) { GPtrArray *addresses, *routes; - char **dns; + char **dns, *gateway = NULL; GString *tmp; GVariant *val; int i; @@ -242,26 +240,24 @@ construct_ip6_items (GSList *items, GVariant *ip6_config, const char *prefix) /* IP addresses */ val = g_variant_lookup_value (ip6_config, "addresses", G_VARIANT_TYPE ("a(ayuay)")); if (val) { - addresses = nm_utils_ip6_addresses_from_variant (val); + addresses = nm_utils_ip6_addresses_from_variant (val, &gateway); + if (!gateway) + gateway = g_strdup ("::"); for (i = 0; i < addresses->len; i++) { NMIPAddress *addr = addresses->pdata[i]; - const char *gw; char *addrtmp; - gw = nm_ip_address_get_gateway (addr); - if (!gw) - gw = "::"; - addrtmp = g_strdup_printf ("%sIP6_ADDRESS_%d=%s/%d %s", prefix, i, nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr), - gw); + gateway); items = g_slist_prepend (items, addrtmp); } if (addresses->len) items = g_slist_prepend (items, g_strdup_printf ("%sIP6_NUM_ADDRESSES=%d", prefix, addresses->len)); g_ptr_array_unref (addresses); + g_free (gateway); g_variant_unref (val); } diff --git a/callouts/tests/test-dispatcher-envp.c b/callouts/tests/test-dispatcher-envp.c index 5daf5e9a64..423d29fd83 100644 --- a/callouts/tests/test-dispatcher-envp.c +++ b/callouts/tests/test-dispatcher-envp.c @@ -183,6 +183,7 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err char *tmp; char **split, **iter; GPtrArray *addresses, *routes; + const char *gateway = NULL; g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}")); @@ -221,7 +222,7 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); for (iter = split; iter && *iter; iter++) { NMIPAddress *addr; - char *ip, *prefix, *gw; + char *ip, *prefix; if (strlen (g_strstrip (*iter)) == 0) continue; @@ -232,11 +233,13 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err g_assert (prefix); *prefix++ = '\0'; - gw = strchr (prefix, ' '); - g_assert (gw); - gw++; + if (addresses->len == 0) { + gateway = strchr (prefix, ' '); + g_assert (gateway); + gateway++; + } - addr = nm_ip_address_new (AF_INET, ip, (guint) atoi (prefix), gw, error); + addr = nm_ip_address_new (AF_INET, ip, (guint) atoi (prefix), error); if (!addr) { g_ptr_array_unref (addresses); return FALSE; @@ -245,7 +248,7 @@ parse_ip4 (GKeyFile *kf, GVariant **out_props, const char *section, GError **err } g_variant_builder_add (&props, "{sv}", "addresses", - nm_utils_ip4_addresses_to_variant (addresses)); + nm_utils_ip4_addresses_to_variant (addresses, gateway)); g_ptr_array_unref (addresses); } g_strfreev (split); diff --git a/clients/cli/common.c b/clients/cli/common.c index e7382b985b..2c56976a26 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -82,6 +82,7 @@ print_ip4_config (NMIP4Config *cfg4, const char *one_field) { GPtrArray *ptr_array; + const char *gw; char **addr_arr = NULL; char **route_arr = NULL; char **dns_arr = NULL; @@ -103,20 +104,16 @@ print_ip4_config (NMIP4Config *cfg4, /* addresses */ ptr_array = nm_ip4_config_get_addresses (cfg4); + gw = nm_ip4_config_get_gateway (cfg4); if (ptr_array) { addr_arr = g_new (char *, ptr_array->len + 1); for (i = 0; i < ptr_array->len; i++) { NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i); - const char *gw; - - gw = nm_ip_address_get_gateway (addr); - if (!gw) - gw = "0.0.0.0"; addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s", nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr), - gw); + (i == 0) && gw ? gw : "0.0.0.0"); } addr_arr[i] = NULL; } @@ -175,6 +172,7 @@ print_ip6_config (NMIP6Config *cfg6, const char *one_field) { GPtrArray *ptr_array; + const char *gw; char **addr_arr = NULL; char **route_arr = NULL; char **dns_arr = NULL; @@ -195,20 +193,16 @@ print_ip6_config (NMIP6Config *cfg6, /* addresses */ ptr_array = nm_ip6_config_get_addresses (cfg6); + gw = nm_ip6_config_get_gateway (cfg6); if (ptr_array) { addr_arr = g_new (char *, ptr_array->len + 1); for (i = 0; i < ptr_array->len; i++) { NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (ptr_array, i); - const char *gw; - - gw = nm_ip_address_get_gateway (addr); - if (!gw) - gw = "::"; addr_arr[i] = g_strdup_printf ("ip = %s/%u, gw = %s", nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr), - gw); + (i == 0) && gw ? gw : "::"); } addr_arr[i] = NULL; } @@ -355,10 +349,9 @@ print_dhcp6_config (NMDhcp6Config *dhcp6, /* * Parse IP address from string to NMIPAddress stucture. * ip_str is the IP address in the form address/prefix - * gw_str is the gateway address (it is optional) */ NMIPAddress * -nmc_parse_and_build_address (int family, const char *ip_str, const char *gw_str, GError **error) +nmc_parse_and_build_address (int family, const char *ip_str, GError **error) { int max_prefix = (family == AF_INET) ? 32 : 128; NMIPAddress *addr = NULL; @@ -387,7 +380,7 @@ nmc_parse_and_build_address (int family, const char *ip_str, const char *gw_str, } } - addr = nm_ip_address_new (family, ip, (guint32) prefix, gw_str, &local); + addr = nm_ip_address_new (family, ip, (guint32) prefix, &local); if (!addr) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("invalid IP address: %s"), local->message); diff --git a/clients/cli/common.h b/clients/cli/common.h index d608ef5ce0..bf881bf2f4 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -29,7 +29,7 @@ gboolean print_ip6_config (NMIP6Config *cfg6, NmCli *nmc, const char *group_pref gboolean print_dhcp4_config (NMDhcp4Config *dhcp4, NmCli *nmc, const char *group_prefix, const char *one_field); gboolean print_dhcp6_config (NMDhcp6Config *dhcp6, NmCli *nmc, const char *group_prefix, const char *one_field); -NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, const char *gw_str, GError **error); +NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, GError **error); NMIPRoute *nmc_parse_and_build_route (int family, const char *first, const char *second, const char *third, GError **error); const char * nmc_device_state_to_string (NMDeviceState state); diff --git a/clients/cli/connections.c b/clients/cli/connections.c index c131054168..969adb80d0 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -3811,24 +3811,21 @@ do_questionnaire_olpc (char **channel, char **dhcp_anycast) } static gboolean -split_address (char* str, char **ip, char **gw, char **rest) +split_address (char* str, char **ip, char **rest) { - size_t n1, n2, n3, n4, n5; + size_t n1, n2, n3; - *ip = *gw = *rest = NULL; + *ip = *rest = NULL; if (!str) return FALSE; n1 = strspn (str, " \t"); n2 = strcspn (str+n1, " \t\0") + n1; n3 = strspn (str+n2, " \t") + n2; - n4 = strcspn (str+n3, " \t\0") + n3; - n5 = strspn (str+n4, " \t") + n4; - str[n2] = str[n4] = '\0'; + str[n2] = '\0'; *ip = str[n1] ? str + n1 : NULL; - *gw = str[n3] ? str + n3 : NULL; - *rest = str[n5] ? str + n5 : NULL; + *rest = str[n3] ? str + n3 : NULL; return TRUE; } @@ -3838,32 +3835,31 @@ ask_for_ip_addresses (NMConnection *connection, int family) { gboolean ip_loop; GError *error = NULL; - char *str, *ip, *gw, *rest; + char *str, *ip, *rest; const char *prompt; gboolean added; NMIPAddress *ipaddr; if (family == AF_INET) - prompt =_("IPv4 address (IP[/plen] [gateway]) [none]: "); + prompt =_("IPv4 address (IP[/plen]) [none]: "); else - prompt =_("IPv6 address (IP[/plen] [gateway]) [none]: "); + prompt =_("IPv6 address (IP[/plen]) [none]: "); ip_loop = TRUE; do { str = nmc_readline ("%s", prompt); - split_address (str, &ip, &gw, &rest); + split_address (str, &ip, &rest); if (ip) { - ipaddr = nmc_parse_and_build_address (family, ip, gw, &error); + ipaddr = nmc_parse_and_build_address (family, ip, &error); if (ipaddr) { if (family == AF_INET) added = add_ip4_address_to_connection (ipaddr, connection); else added = add_ip6_address_to_connection (ipaddr, connection); - gw = gw ? gw : (family == AF_INET) ? "0.0.0.0" : "::"; if (added) - g_print (_(" Address successfully added: %s %s\n"), ip, gw); + g_print (_(" Address successfully added: %s\n"), ip); else - g_print (_(" Warning: address already present: %s %s\n"), ip, gw); + g_print (_(" Warning: address already present: %s\n"), ip); if (rest) g_print (_(" Warning: ignoring garbage at the end: '%s'\n"), rest); } else { @@ -3878,6 +3874,45 @@ ask_for_ip_addresses (NMConnection *connection, int family) } while (ip_loop); } +static void +maybe_ask_for_gateway (NMConnection *connection, int family) +{ + gboolean gw_loop; + char *str, *gw, *rest; + const char *prompt; + NMSettingIPConfig *s_ip; + + if (family == AF_INET) { + prompt =_("IPv4 gateway [none]: "); + s_ip = nm_connection_get_setting_ip4_config (connection); + } else { + prompt =_("IPv6 gateway [none]: "); + s_ip = nm_connection_get_setting_ip6_config (connection); + } + if (s_ip == NULL) + return; + if ( nm_setting_ip_config_get_num_addresses (s_ip) == 0 + || nm_setting_ip_config_get_gateway (s_ip) != NULL) + return; + + gw_loop = TRUE; + do { + str = nmc_readline ("%s", prompt); + split_address (str, &gw, &rest); + if (gw) { + if (nm_utils_ipaddr_valid (family, gw)) { + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_GATEWAY, gw, + NULL); + gw_loop = FALSE; + } else + g_print (_("Error: invalid gateway address '%s'\n"), gw); + } else + gw_loop = FALSE; + g_free (str); + } while (gw_loop); +} + static void do_questionnaire_ip (NMConnection *connection) { @@ -3890,14 +3925,14 @@ do_questionnaire_ip (NMConnection *connection) g_free (answer); return; } + g_free (answer); g_print (_("Press to finish adding addresses.\n")); ask_for_ip_addresses (connection, AF_INET); + maybe_ask_for_gateway (connection, AF_INET); ask_for_ip_addresses (connection, AF_INET6); - - g_free (answer); - return; + maybe_ask_for_gateway (connection, AF_INET6); } static gboolean @@ -5168,7 +5203,7 @@ cleanup_olpc: /* coverity[dead_error_begin] */ if (ip4) { - ip4addr = nmc_parse_and_build_address (AF_INET, ip4, gw4, error); + ip4addr = nmc_parse_and_build_address (AF_INET, ip4, error); if (!ip4addr) { g_prefix_error (error, _("Error: ")); return FALSE; @@ -5176,15 +5211,59 @@ cleanup_olpc: add_ip4_address_to_connection (ip4addr, connection); } + if (gw4) { + NMSettingIPConfig *s_ip = nm_connection_get_setting_ip4_config (connection); + + if (!s_ip) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: IPv4 gateway specified without IPv4 addresses")); + return FALSE; + } else if (nm_setting_ip_config_get_gateway (s_ip)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: multiple IPv4 gateways specified")); + return FALSE; + } else if (!nm_utils_ipaddr_valid (AF_INET, gw4)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: Invalid IPv4 gateway '%s'"), + gw4); + } + + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_GATEWAY, gw4, + NULL); + } + /* coverity[dead_error_begin] */ if (ip6) { - ip6addr = nmc_parse_and_build_address (AF_INET6, ip6, gw6, error); + ip6addr = nmc_parse_and_build_address (AF_INET6, ip6, error); if (!ip6addr) { g_prefix_error (error, _("Error: ")); return FALSE; } add_ip6_address_to_connection (ip6addr, connection); } + + if (gw6) { + NMSettingIPConfig *s_ip = nm_connection_get_setting_ip6_config (connection); + + if (!s_ip) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: IPv6 gateway specified without IPv6 addresses")); + return FALSE; + } else if (nm_setting_ip_config_get_gateway (s_ip)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: multiple IPv6 gateways specified")); + return FALSE; + } else if (!nm_utils_ipaddr_valid (AF_INET, gw6)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: Invalid IPv6 gateway '%s'"), + gw6); + } + + g_object_set (s_ip, + NM_SETTING_IP_CONFIG_GATEWAY, gw6, + NULL); + } } /* Ask for addresses if '--ask' is specified. */ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index cb3dccf48e..292a09b52a 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -257,14 +257,15 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS, 20), /* 2 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH, 15), /* 3 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES, 20), /* 4 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES, 20), /* 5 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, 19), /* 6 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, 16), /* 7 */ - SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, 15), /* 8 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, 19), /* 9 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, 14), /* 10 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 11 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY, 20), /* 5 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES, 20), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, 19), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, 16), /* 8 */ + SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, 15), /* 9 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, 19), /* 10 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, 14), /* 11 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 13 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_IP4_CONFIG_ALL "name"","\ @@ -272,6 +273,7 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { NM_SETTING_IP_CONFIG_DNS","\ NM_SETTING_IP_CONFIG_DNS_SEARCH","\ NM_SETTING_IP_CONFIG_ADDRESSES","\ + NM_SETTING_IP_CONFIG_GATEWAY","\ NM_SETTING_IP_CONFIG_ROUTES","\ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES","\ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS","\ @@ -289,14 +291,15 @@ NmcOutputField nmc_fields_setting_ip6_config[] = { SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS, 20), /* 2 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH, 15), /* 3 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES, 20), /* 4 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES, 20), /* 5 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, 19), /* 6 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, 16), /* 7 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 8 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 9 */ - SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, 15), /* 10 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, 19), /* 11 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, 14), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY, 20), /* 5 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES, 20), /* 6 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, 19), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, 16), /* 8 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 9 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 10 */ + SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, 15), /* 11 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, 19), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, 14), /* 13 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_IP6_CONFIG_ALL "name"","\ @@ -304,6 +307,7 @@ NmcOutputField nmc_fields_setting_ip6_config[] = { NM_SETTING_IP_CONFIG_DNS","\ NM_SETTING_IP_CONFIG_DNS_SEARCH","\ NM_SETTING_IP_CONFIG_ADDRESSES","\ + NM_SETTING_IP_CONFIG_GATEWAY","\ NM_SETTING_IP_CONFIG_ROUTES","\ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES","\ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS","\ @@ -1207,34 +1211,25 @@ DEFINE_GETTER (nmc_property_ipv4_get_dns, NM_SETTING_IP_CONFIG_DNS) DEFINE_GETTER (nmc_property_ipv4_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH) static char * -nmc_property_ipv4_get_addresses (NMSetting *setting) +nmc_property_ip_get_addresses (NMSetting *setting) { - NMSettingIPConfig *s_ip4 = NM_SETTING_IP_CONFIG (setting); + NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); GString *printable; guint32 num_addresses, i; NMIPAddress *addr; printable = g_string_new (NULL); - num_addresses = nm_setting_ip_config_get_num_addresses (s_ip4); + num_addresses = nm_setting_ip_config_get_num_addresses (s_ip); for (i = 0; i < num_addresses; i++) { - addr = nm_setting_ip_config_get_address (s_ip4, i); + addr = nm_setting_ip_config_get_address (s_ip, i); if (printable->len > 0) - g_string_append (printable, "; "); + g_string_append (printable, ", "); - g_string_append (printable, "{ "); - - g_string_append_printf (printable, "ip = %s/%u", + g_string_append_printf (printable, "%s/%u", nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr)); - - if (nm_ip_address_get_gateway (addr)) { - g_string_append_printf (printable, ", gw = %s", - nm_ip_address_get_gateway (addr)); - } - - g_string_append (printable, " }"); } return g_string_free (printable, FALSE); @@ -1277,6 +1272,7 @@ nmc_property_ipv4_get_routes (NMSetting *setting) return g_string_free (printable, FALSE); } +DEFINE_GETTER (nmc_property_ipv4_get_gateway, NM_SETTING_IP_CONFIG_GATEWAY) DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_routes, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES) DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_dns, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS) DEFINE_GETTER (nmc_property_ipv4_get_dhcp_client_id, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID) @@ -1290,40 +1286,6 @@ DEFINE_GETTER (nmc_property_ipv6_get_method, NM_SETTING_IP_CONFIG_METHOD) DEFINE_GETTER (nmc_property_ipv6_get_dns, NM_SETTING_IP_CONFIG_DNS) DEFINE_GETTER (nmc_property_ipv6_get_dns_search, NM_SETTING_IP_CONFIG_DNS_SEARCH) -static char * -nmc_property_ipv6_get_addresses (NMSetting *setting) -{ - NMSettingIPConfig *s_ip6 = NM_SETTING_IP_CONFIG (setting); - GString *printable; - guint32 num_addresses, i; - NMIPAddress *addr; - - printable = g_string_new (NULL); - - num_addresses = nm_setting_ip_config_get_num_addresses (s_ip6); - for (i = 0; i < num_addresses; i++) { - addr = nm_setting_ip_config_get_address (s_ip6, i); - - if (printable->len > 0) - g_string_append (printable, "; "); - - g_string_append (printable, "{ "); - - g_string_append_printf (printable, "ip = %s/%u", - nm_ip_address_get_address (addr), - nm_ip_address_get_prefix (addr)); - - if (nm_ip_address_get_gateway (addr)) { - g_string_append_printf (printable, ", gw = %s", - nm_ip_address_get_gateway (addr)); - } - - g_string_append (printable, " }"); - } - - return g_string_free (printable, FALSE); -} - static char * nmc_property_ipv6_get_routes (NMSetting *setting) { @@ -1361,6 +1323,7 @@ nmc_property_ipv6_get_routes (NMSetting *setting) return g_string_free (printable, FALSE); } +DEFINE_GETTER (nmc_property_ipv6_get_gateway, NM_SETTING_IP_CONFIG_GATEWAY) DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_routes, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES) DEFINE_GETTER (nmc_property_ipv6_get_ignore_auto_dns, NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS) DEFINE_GETTER (nmc_property_ipv6_get_never_default, NM_SETTING_IP_CONFIG_NEVER_DEFAULT) @@ -3075,20 +3038,10 @@ static NMIPAddress * _parse_ip_address (int family, const char *address, GError **error) { char *value = g_strdup (address); - char **addrv; NMIPAddress *ipaddr; - addrv = nmc_strsplit_set (g_strstrip (value), " \t", 0); - if (addrv[0] == NULL || g_strv_length (addrv) > 2) { - g_set_error (error, 1, 0, _("'%s' is not valid (use ip[/prefix] [gateway])"), - address); - g_free (value); - g_strfreev (addrv); - return NULL; - } - ipaddr = nmc_parse_and_build_address (family, addrv[0], addrv[1], error); + ipaddr = nmc_parse_and_build_address (family, g_strstrip (value), error); g_free (value); - g_strfreev (addrv); return ipaddr; } @@ -3292,44 +3245,31 @@ static const char * nmc_property_ipv4_describe_addresses (NMSetting *setting, const char *prop) { return _("Enter a list of IPv4 addresses formatted as:\n" - " ip[/prefix] [gateway], ip[/prefix] [gateway],...\n" + " ip[/prefix], ip[/prefix],...\n" "Missing prefix is regarded as prefix of 32.\n\n" - "Example: 192.168.1.5/24 192.168.1.1, 10.0.0.11/24\n"); + "Example: 192.168.1.5/24, 10.0.0.11/24\n"); } -/* - * from: { ip = 1.2.3.4/24, gw = 1.2.3.254 }; { ip = 2.2.2.2/16, gw = 5.5.5.5 } - * to: 1.2.3.4/24 1.2.3.254, 2.2.2.2/16 5.5.5.5 - * from: { ip = 11::22/64, gw = 22::33 }; { ip = ab::cd/64, gw = ab::1 } - * to: 11::22/64 22:33, ab::cd/64 ab::1 -*/ -static char * -nmc_property_out2in_addresses (const char *out_format) +/* 'gateway' */ +static gboolean +nmc_property_ipv4_set_gateway (NMSetting *setting, const char *prop, const char *val, GError **error) { - GRegex *regex; - GString *str; - char **strv; - int i; + NMIPAddress *ip4addr; - str = g_string_sized_new (128); - regex = g_regex_new ("\\{ ip = ([^/]+)/([^,]+), gw = ([^ ]+) \\}", 0, 0, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - strv = g_regex_split (regex, out_format, 0); - for (i = 1; strv && strv[i] && strv[i+1] && strv[i+2]; i=i+4) { - g_string_append (str, strv[i]); /* IP */ - g_string_append_c (str, '/'); - g_string_append (str, strv[i+1]); /* prefix */ - g_string_append_c (str, ' '); - g_string_append (str, strv[i+2]); /* gateway */ - g_string_append (str, ", "); + if (strchr (val, '/')) { + g_set_error (error, 1, 0, + _("invalid gateway address '%s'"), val); + return FALSE; } - if (str->len > 0) - g_string_truncate (str, str->len - 2); + ip4addr = _parse_ipv4_address (val, error); + if (!ip4addr) + return FALSE; - g_strfreev (strv); - g_regex_unref (regex); - - return g_string_free (str, FALSE); + g_object_set (setting, prop, val, NULL); + nm_ip_address_unref (ip4addr); + return TRUE; } /* 'routes' */ @@ -3611,9 +3551,31 @@ static const char * nmc_property_ipv6_describe_addresses (NMSetting *setting, const char *prop) { return _("Enter a list of IPv6 addresses formatted as:\n" - " ip[/prefix] [gateway], ip[/prefix] [gateway],...\n" + " ip[/prefix], ip[/prefix],...\n" "Missing prefix is regarded as prefix of 128.\n\n" - "Example: 2607:f0d0:1002:51::4/64 2607:f0d0:1002:51::1, 1050:0:0:0:5:600:300c:326b\n"); + "Example: 2607:f0d0:1002:51::4/64, 1050:0:0:0:5:600:300c:326b\n"); +} + +/* 'gateway' */ +static gboolean +nmc_property_ipv6_set_gateway (NMSetting *setting, const char *prop, const char *val, GError **error) +{ + NMIPAddress *ip6addr; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (strchr (val, '/')) { + g_set_error (error, 1, 0, + _("invalid gateway address '%s'"), val); + return FALSE; + } + ip6addr = _parse_ipv6_address (val, error); + if (!ip6addr) + return FALSE; + + g_object_set (setting, prop, val, NULL); + nm_ip_address_unref (ip6addr); + return TRUE; } /* 'routes' */ @@ -5448,12 +5410,19 @@ nmc_properties_init (void) NULL, NULL); nmc_add_prop_funcs (GLUE_IP (4, ADDRESSES), - nmc_property_ipv4_get_addresses, + nmc_property_ip_get_addresses, nmc_property_ipv4_set_addresses, nmc_property_ipv4_remove_addresses, nmc_property_ipv4_describe_addresses, NULL, - nmc_property_out2in_addresses); + NULL); + nmc_add_prop_funcs (GLUE_IP (4, GATEWAY), + nmc_property_ipv4_get_gateway, + nmc_property_ipv4_set_gateway, + NULL, + NULL, + NULL, + NULL); nmc_add_prop_funcs (GLUE_IP (4, ROUTES), nmc_property_ipv4_get_routes, nmc_property_ipv4_set_routes, @@ -5534,12 +5503,19 @@ nmc_properties_init (void) NULL, NULL); nmc_add_prop_funcs (GLUE_IP (6, ADDRESSES), - nmc_property_ipv6_get_addresses, + nmc_property_ip_get_addresses, nmc_property_ipv6_set_addresses, nmc_property_ipv6_remove_addresses, nmc_property_ipv6_describe_addresses, NULL, - nmc_property_out2in_addresses); + NULL); + nmc_add_prop_funcs (GLUE_IP (6, GATEWAY), + nmc_property_ipv6_get_gateway, + nmc_property_ipv6_set_gateway, + NULL, + NULL, + NULL, + NULL); nmc_add_prop_funcs (GLUE_IP (6, ROUTES), nmc_property_ipv6_get_routes, nmc_property_ipv6_set_routes, @@ -6746,15 +6722,16 @@ setting_ip4_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro set_val_str (arr, 1, nmc_property_ipv4_get_method (setting)); set_val_str (arr, 2, nmc_property_ipv4_get_dns (setting)); set_val_str (arr, 3, nmc_property_ipv4_get_dns_search (setting)); - set_val_str (arr, 4, nmc_property_ipv4_get_addresses (setting)); - set_val_str (arr, 5, nmc_property_ipv4_get_routes (setting)); - set_val_str (arr, 6, nmc_property_ipv4_get_ignore_auto_routes (setting)); - set_val_str (arr, 7, nmc_property_ipv4_get_ignore_auto_dns (setting)); - set_val_str (arr, 8, nmc_property_ipv4_get_dhcp_client_id (setting)); - set_val_str (arr, 9, nmc_property_ipv4_get_dhcp_send_hostname (setting)); - set_val_str (arr, 10, nmc_property_ipv4_get_dhcp_hostname (setting)); - set_val_str (arr, 11, nmc_property_ipv4_get_never_default (setting)); - set_val_str (arr, 12, nmc_property_ipv4_get_may_fail (setting)); + set_val_str (arr, 4, nmc_property_ip_get_addresses (setting)); + set_val_str (arr, 5, nmc_property_ipv4_get_gateway (setting)); + set_val_str (arr, 6, nmc_property_ipv4_get_routes (setting)); + set_val_str (arr, 7, nmc_property_ipv4_get_ignore_auto_routes (setting)); + set_val_str (arr, 8, nmc_property_ipv4_get_ignore_auto_dns (setting)); + set_val_str (arr, 9, nmc_property_ipv4_get_dhcp_client_id (setting)); + set_val_str (arr, 10, nmc_property_ipv4_get_dhcp_send_hostname (setting)); + set_val_str (arr, 11, nmc_property_ipv4_get_dhcp_hostname (setting)); + set_val_str (arr, 12, nmc_property_ipv4_get_never_default (setting)); + set_val_str (arr, 13, nmc_property_ipv4_get_may_fail (setting)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ @@ -6783,15 +6760,16 @@ setting_ip6_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro set_val_str (arr, 1, nmc_property_ipv6_get_method (setting)); set_val_str (arr, 2, nmc_property_ipv6_get_dns (setting)); set_val_str (arr, 3, nmc_property_ipv6_get_dns_search (setting)); - set_val_str (arr, 4, nmc_property_ipv6_get_addresses (setting)); - set_val_str (arr, 5, nmc_property_ipv6_get_routes (setting)); - set_val_str (arr, 6, nmc_property_ipv6_get_ignore_auto_routes (setting)); - set_val_str (arr, 7, nmc_property_ipv6_get_ignore_auto_dns (setting)); - set_val_str (arr, 8, nmc_property_ipv6_get_never_default (setting)); - set_val_str (arr, 9, nmc_property_ipv6_get_may_fail (setting)); - set_val_str (arr, 10, nmc_property_ipv6_get_ip6_privacy (setting)); - set_val_str (arr, 11, nmc_property_ipv6_get_dhcp_send_hostname (setting)); - set_val_str (arr, 12, nmc_property_ipv6_get_dhcp_hostname (setting)); + set_val_str (arr, 4, nmc_property_ip_get_addresses (setting)); + set_val_str (arr, 5, nmc_property_ipv6_get_gateway (setting)); + set_val_str (arr, 6, nmc_property_ipv6_get_routes (setting)); + set_val_str (arr, 7, nmc_property_ipv6_get_ignore_auto_routes (setting)); + set_val_str (arr, 8, nmc_property_ipv6_get_ignore_auto_dns (setting)); + set_val_str (arr, 9, nmc_property_ipv6_get_never_default (setting)); + set_val_str (arr, 10, nmc_property_ipv6_get_may_fail (setting)); + set_val_str (arr, 11, nmc_property_ipv6_get_ip6_privacy (setting)); + set_val_str (arr, 12, nmc_property_ipv6_get_dhcp_send_hostname (setting)); + set_val_str (arr, 13, nmc_property_ipv6_get_dhcp_hostname (setting)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ diff --git a/clients/tui/nm-editor-bindings.c b/clients/tui/nm-editor-bindings.c index 4c42caad35..9db44c9d80 100644 --- a/clients/tui/nm-editor-bindings.c +++ b/clients/tui/nm-editor-bindings.c @@ -156,7 +156,7 @@ ip_addresses_with_prefix_from_strv (GBinding *binding, int i; strings = g_value_get_boxed (source_value); - /* Fetch the original property value, so as to preserve the gateway elements */ + /* Fetch the original property value, so as to preserve their extra attributes */ g_object_get (g_binding_get_source (binding), g_binding_get_source_property (binding), &addrs, NULL); @@ -164,9 +164,9 @@ ip_addresses_with_prefix_from_strv (GBinding *binding, for (i = 0; strings[i]; i++) { if (i >= addrs->len) { if (family == AF_INET) - addr = nm_ip_address_new (AF_INET, "0.0.0.0", 32, NULL, NULL); + addr = nm_ip_address_new (AF_INET, "0.0.0.0", 32, NULL); else - addr = nm_ip_address_new (AF_INET6, "::", 128, NULL, NULL); + addr = nm_ip_address_new (AF_INET6, "::", 128, NULL); g_ptr_array_add (addrs, addr); } else addr = addrs->pdata[i]; @@ -202,9 +202,7 @@ ip_addresses_with_prefix_from_strv (GBinding *binding, * * Each #NMIPAddress in @source_property will be converted to a string of the * form "ip.ad.dr.ess/prefix" or "ip:ad:dr:ess/prefix" in @target_property (and - * vice versa if %G_BINDING_BIDIRECTIONAL) is specified. The "gateway" fields in - * @source_property are ignored when converting to strings, and unmodified when - * converting from strings. + * vice versa if %G_BINDING_BIDIRECTIONAL) is specified. */ void nm_editor_bind_ip_addresses_with_prefix_to_strv (int family, @@ -274,108 +272,6 @@ nm_editor_bind_ip_addresses_to_strv (int family, GINT_TO_POINTER (family), NULL); } -static gboolean -ip_gateway_to_string (GBinding *binding, - const GValue *source_value, - GValue *target_value, - gpointer user_data) -{ - GPtrArray *addrs; - NMIPAddress *addr; - const char *gateway = NULL; - int i; - - addrs = g_value_get_boxed (source_value); - for (i = 0; i < addrs->len; i++) { - addr = addrs->pdata[i]; - gateway = nm_ip_address_get_gateway (addr); - if (gateway) - break; - } - - if (!gateway) - gateway = ""; - g_value_set_string (target_value, gateway); - return TRUE; -} - -static gboolean -ip_gateway_from_string (GBinding *binding, - const GValue *source_value, - GValue *target_value, - gpointer user_data) -{ - int family = GPOINTER_TO_INT (user_data); - const char *text; - GPtrArray *addrs; - NMIPAddress *addr; - int i; - - text = g_value_get_string (source_value); - if (*text) { - if (!nm_utils_ipaddr_valid (family, text)) - return FALSE; - } else - text = NULL; - - /* Fetch the original property value, so as to preserve the IP address elements */ - g_object_get (g_binding_get_source (binding), - g_binding_get_source_property (binding), &addrs, - NULL); - if (!addrs->len) { - g_ptr_array_unref (addrs); - return FALSE; - } - addr = addrs->pdata[0]; - if (!g_strcmp0 (text, nm_ip_address_get_gateway (addr))) { - g_ptr_array_unref (addrs); - return FALSE; - } - nm_ip_address_set_gateway (addr, text); - - for (i = 1; i < addrs->len; i++) { - addr = addrs->pdata[i]; - nm_ip_address_set_gateway (addr, NULL); - } - - g_value_take_boxed (target_value, addrs); - return TRUE; -} - -/** - * nm_editor_bind_ip_gateway_to_string: - * @family: the IP address family - * @source: the source object (eg, an #NMSettingIP4Config) - * @source_property: the property on @source to bind (eg, - * %NM_SETTING_IP4_CONFIG_ADDRESSES) - * @target: the target object (eg, an #NmtNewtEntry) - * @target_property: the property on @target to bind - * (eg, "text") - * @flags: %GBindingFlags - * - * Binds the #GPtrArray-of-#NMIPRoute property @source_property on @source to - * the %G_TYPE_STRING property @target_property on @target. - * - * Specifically, this binds the "gateway" field of the first address in - * @source_property; all other addresses in @source_property are ignored, and - * its "address" and "prefix" fields are unmodified. - */ -void -nm_editor_bind_ip_gateway_to_string (int family, - gpointer source, - const gchar *source_property, - gpointer target, - const gchar *target_property, - GBindingFlags flags) -{ - g_object_bind_property_full (source, source_property, - target, target_property, - flags, - ip_gateway_to_string, - ip_gateway_from_string, - GINT_TO_POINTER (family), NULL); -} - static gboolean ip_route_transform_to_dest_string (GBinding *binding, const GValue *source_value, diff --git a/clients/tui/nm-editor-bindings.h b/clients/tui/nm-editor-bindings.h index 5e34c42dec..19a172f344 100644 --- a/clients/tui/nm-editor-bindings.h +++ b/clients/tui/nm-editor-bindings.h @@ -37,12 +37,6 @@ void nm_editor_bind_ip_addresses_to_strv (int family, gpointer target, const gchar *target_property, GBindingFlags flags); -void nm_editor_bind_ip_gateway_to_string (int family, - gpointer source, - const gchar *source_property, - gpointer target, - const gchar *target_property, - GBindingFlags flags); void nm_editor_bind_ip_route_to_strings (int family, gpointer source, diff --git a/clients/tui/nmt-page-ip4.c b/clients/tui/nmt-page-ip4.c index 782a204fc9..b365cc41a2 100644 --- a/clients/tui/nmt-page-ip4.c +++ b/clients/tui/nmt-page-ip4.c @@ -145,10 +145,9 @@ nmt_page_ip4_constructed (GObject *object) nmt_page_grid_append (grid, _("Addresses"), widget, NULL); widget = nmt_ip_entry_new (25, AF_INET, FALSE, TRUE); - nm_editor_bind_ip_gateway_to_string (AF_INET, - s_ip4, NM_SETTING_IP_CONFIG_ADDRESSES, - widget, "text", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, + widget, "text", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); nmt_page_grid_append (grid, _("Gateway"), widget, NULL); widget = nmt_address_list_new (NMT_ADDRESS_LIST_IP4); diff --git a/clients/tui/nmt-page-ip6.c b/clients/tui/nmt-page-ip6.c index 88b948cd14..1003c1a8aa 100644 --- a/clients/tui/nmt-page-ip6.c +++ b/clients/tui/nmt-page-ip6.c @@ -145,10 +145,9 @@ nmt_page_ip6_constructed (GObject *object) nmt_page_grid_append (grid, _("Addresses"), widget, NULL); widget = nmt_ip_entry_new (25, AF_INET6, FALSE, TRUE); - nm_editor_bind_ip_gateway_to_string (AF_INET6, - s_ip6, NM_SETTING_IP_CONFIG_ADDRESSES, - widget, "text", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, + widget, "text", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); nmt_page_grid_append (grid, _("Gateway"), widget, NULL); widget = nmt_address_list_new (NMT_ADDRESS_LIST_IP6); diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index ebe38712b2..0ed612cd06 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -102,7 +102,7 @@ G_DEFINE_BOXED_TYPE (NMIPAddress, nm_ip_address, nm_ip_address_dup, nm_ip_addres struct NMIPAddress { guint refcount; - char *address, *gateway; + char *address; int prefix, family; GHashTable *attributes; @@ -113,7 +113,6 @@ struct NMIPAddress { * @family: the IP address family (%AF_INET or %AF_INET6) * @addr: the IP address * @prefix: the address prefix length - * @gateway: (allow-none): the gateway * @error: location to store error, or %NULL * * Creates a new #NMIPAddress object. @@ -122,7 +121,7 @@ struct NMIPAddress { **/ NMIPAddress * nm_ip_address_new (int family, - const char *addr, guint prefix, const char *gateway, + const char *addr, guint prefix, GError **error) { NMIPAddress *address; @@ -134,8 +133,6 @@ nm_ip_address_new (int family, return NULL; if (!valid_prefix (family, prefix, error)) return NULL; - if (gateway && !valid_ip (family, gateway, error)) - return NULL; address = g_slice_new0 (NMIPAddress); address->refcount = 1; @@ -143,7 +140,6 @@ nm_ip_address_new (int family, address->family = family; address->address = canonicalize_ip (family, addr, FALSE); address->prefix = prefix; - address->gateway = canonicalize_ip (family, gateway, TRUE); return address; } @@ -153,17 +149,16 @@ nm_ip_address_new (int family, * @family: the IP address family (%AF_INET or %AF_INET6) * @addr: the IP address * @prefix: the address prefix length - * @gateway: (allow-none): the gateway * @error: location to store error, or %NULL * - * Creates a new #NMIPAddress object. @addr and @gateway (if non-%NULL) must - * point to buffers of the correct size for @family. + * Creates a new #NMIPAddress object. @addr must point to a buffer of the + * correct size for @family. * * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error **/ NMIPAddress * nm_ip_address_new_binary (int family, - gconstpointer addr, guint prefix, gconstpointer gateway, + gconstpointer addr, guint prefix, GError **error) { NMIPAddress *address; @@ -181,8 +176,6 @@ nm_ip_address_new_binary (int family, address->family = family; address->address = g_strdup (inet_ntop (family, addr, string, sizeof (string))); address->prefix = prefix; - if (gateway) - address->gateway = g_strdup (inet_ntop (family, gateway, string, sizeof (string))); return address; } @@ -218,7 +211,6 @@ nm_ip_address_unref (NMIPAddress *address) address->refcount--; if (address->refcount == 0) { g_free (address->address); - g_free (address->gateway); if (address->attributes) g_hash_table_unref (address->attributes); g_slice_free (NMIPAddress, address); @@ -230,8 +222,8 @@ nm_ip_address_unref (NMIPAddress *address) * @address: the #NMIPAddress * @other: the #NMIPAddress to compare @address to. * - * Determines if two #NMIPAddress objects contain the same address, prefix, and - * gateway (attributes are not compared). + * Determines if two #NMIPAddress objects contain the same address and prefix + * (attributes are not compared). * * Returns: %TRUE if the objects contain the same values, %FALSE if they do not. **/ @@ -246,8 +238,7 @@ nm_ip_address_equal (NMIPAddress *address, NMIPAddress *other) if ( address->family != other->family || address->prefix != other->prefix - || strcmp (address->address, other->address) != 0 - || g_strcmp0 (address->gateway, other->gateway) != 0) + || strcmp (address->address, other->address) != 0) return FALSE; return TRUE; } @@ -269,7 +260,7 @@ nm_ip_address_dup (NMIPAddress *address) g_return_val_if_fail (address->refcount > 0, NULL); copy = nm_ip_address_new (address->family, - address->address, address->prefix, address->gateway, + address->address, address->prefix, NULL); if (address->attributes) { GHashTableIter iter; @@ -417,46 +408,6 @@ nm_ip_address_set_prefix (NMIPAddress *address, address->prefix = prefix; } -/** - * nm_ip_address_get_gateway: - * @address: the #NMIPAddress - * - * Gets the gateway property of this address object; this will be %NULL if the - * address has no associated gateway. - * - * Returns: the gateway - **/ -const char * -nm_ip_address_get_gateway (NMIPAddress *address) -{ - g_return_val_if_fail (address != NULL, NULL); - g_return_val_if_fail (address->refcount > 0, NULL); - - return address->gateway; -} - -/** - * nm_ip_address_set_gateway: - * @address: the #NMIPAddress - * @gateway: (allow-none): the gateway, as a string - * - * Sets the gateway property of this address object. - * - * @gateway (if non-%NULL) must be a valid address of @address's family. If you - * aren't sure you have a valid address, use nm_utils_ipaddr_valid() to check - * it. - **/ -void -nm_ip_address_set_gateway (NMIPAddress *address, - const char *gateway) -{ - g_return_if_fail (address != NULL); - g_return_if_fail (!gateway || nm_utils_ipaddr_valid (address->family, gateway)); - - g_free (address->gateway); - address->gateway = canonicalize_ip (address->family, gateway, TRUE); -} - /** * nm_ip_address_get_attribute_names: * @address: the #NMIPAddress @@ -1081,6 +1032,7 @@ typedef struct { GPtrArray *dns_search; /* array of domain name strings */ GPtrArray *addresses; /* array of NMIPAddress */ GPtrArray *routes; /* array of NMIPRoute */ + char *gateway; gboolean ignore_auto_routes; gboolean ignore_auto_dns; char *dhcp_hostname; @@ -1095,6 +1047,7 @@ enum { PROP_DNS, PROP_DNS_SEARCH, PROP_ADDRESSES, + PROP_GATEWAY, PROP_ROUTES, PROP_IGNORE_AUTO_ROUTES, PROP_IGNORE_AUTO_DNS, @@ -1543,6 +1496,21 @@ nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting) g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES); } +/** + * nm_setting_ip_config_get_gateway: + * @setting: the #NMSettingIPConfig + * + * Returns: the IP address of the gateway associated with this configuration, or + * %NULL. + **/ +const char * +nm_setting_ip_config_get_gateway (NMSettingIPConfig *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->gateway; +} + /** * nm_setting_ip_config_get_num_routes: * @setting: the #NMSettingIPConfig @@ -1882,6 +1850,27 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } + /* Validate gateway */ + if (priv->gateway) { + if (!priv->addresses->len) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("gateway cannot be set if there are no addresses configured")); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY); + return FALSE; + } + + if (!nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), priv->gateway)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("gateway is invalid")); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY); + return FALSE; + } + } + /* Validate routes */ for (i = 0; i < priv->routes->len; i++) { NMIPRoute *route = (NMIPRoute *) priv->routes->pdata[i]; @@ -1919,6 +1908,7 @@ finalize (GObject *object) NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (self); g_free (priv->method); + g_free (priv->gateway); g_free (priv->dhcp_hostname); g_ptr_array_unref (priv->dns); @@ -1935,6 +1925,7 @@ set_property (GObject *object, guint prop_id, { NMSettingIPConfig *setting = NM_SETTING_IP_CONFIG (object); NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting); + const char *gateway; switch (prop_id) { case PROP_METHOD: @@ -1955,6 +1946,12 @@ set_property (GObject *object, guint prop_id, (NMUtilsCopyFunc) nm_ip_address_dup, (GDestroyNotify) nm_ip_address_unref); break; + case PROP_GATEWAY: + gateway = g_value_get_string (value); + g_return_if_fail (!gateway || nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway)); + g_free (priv->gateway); + priv->gateway = canonicalize_ip (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway, TRUE); + break; case PROP_ROUTES: g_ptr_array_unref (priv->routes); priv->routes = _nm_utils_copy_array (g_value_get_boxed (value), @@ -2008,6 +2005,9 @@ get_property (GObject *object, guint prop_id, (NMUtilsCopyFunc) nm_ip_address_dup, (GDestroyNotify) nm_ip_address_unref)); break; + case PROP_GATEWAY: + g_value_set_string (value, nm_setting_ip_config_get_gateway (setting)); + break; case PROP_ROUTES: g_value_take_boxed (value, _nm_utils_copy_array (priv->routes, (NMUtilsCopyFunc) nm_ip_route_dup, @@ -2118,6 +2118,20 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) NM_SETTING_PARAM_INFERRABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMSettingIPConfig:gateway: + * + * The gateway associated with this configuration. This is only meaningful + * if #NMSettingIPConfig:addresses is also set. + **/ + g_object_class_install_property + (object_class, PROP_GATEWAY, + g_param_spec_string (NM_SETTING_IP_CONFIG_GATEWAY, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + /** * NMSettingIPConfig:routes: * diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 0f2d16367c..37437761c4 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -38,12 +38,10 @@ GType nm_ip_address_get_type (void); NMIPAddress *nm_ip_address_new (int family, const char *addr, guint prefix, - const char *gateway, GError **error); NMIPAddress *nm_ip_address_new_binary (int family, gconstpointer addr, guint prefix, - gconstpointer gateway, GError **error); void nm_ip_address_ref (NMIPAddress *address); @@ -63,9 +61,6 @@ void nm_ip_address_set_address_binary (NMIPAddress *address, guint nm_ip_address_get_prefix (NMIPAddress *address); void nm_ip_address_set_prefix (NMIPAddress *address, guint prefix); -const char *nm_ip_address_get_gateway (NMIPAddress *address); -void nm_ip_address_set_gateway (NMIPAddress *address, - const char *gateway); char **nm_ip_address_get_attribute_names (NMIPAddress *address); GVariant *nm_ip_address_get_attribute (NMIPAddress *address, @@ -139,6 +134,7 @@ void nm_ip_route_set_attribute (NMIPRoute *route, #define NM_SETTING_IP_CONFIG_DNS "dns" #define NM_SETTING_IP_CONFIG_DNS_SEARCH "dns-search" #define NM_SETTING_IP_CONFIG_ADDRESSES "addresses" +#define NM_SETTING_IP_CONFIG_GATEWAY "gateway" #define NM_SETTING_IP_CONFIG_ROUTES "routes" #define NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes" #define NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns" @@ -195,6 +191,8 @@ gboolean nm_setting_ip_config_remove_address_by_value (NMSettingIPConfig NMIPAddress *address); void nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting); +const char *nm_setting_ip_config_get_gateway (NMSettingIPConfig *setting); + guint nm_setting_ip_config_get_num_routes (NMSettingIPConfig *setting); NMIPRoute *nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int i); diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index 068ba0451a..66f2ea997e 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -102,10 +102,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting); NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); + NMSettingVerifyResult ret; const char *method; - if (!NM_SETTING_CLASS (nm_setting_ip4_config_parent_class)->verify (setting, connection, error)) - return FALSE; + ret = NM_SETTING_CLASS (nm_setting_ip4_config_parent_class)->verify (setting, connection, error); + if (ret != NM_SETTING_VERIFY_SUCCESS) + return ret; method = nm_setting_ip_config_get_method (s_ip); /* Base class already checked that it exists */ @@ -245,10 +247,12 @@ ip4_addresses_get (NMSetting *setting, const char *property) { GPtrArray *addrs; + const char *gateway; GVariant *ret; g_object_get (setting, property, &addrs, NULL); - ret = nm_utils_ip4_addresses_to_variant (addrs); + gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting)); + ret = nm_utils_ip4_addresses_to_variant (addrs, gateway); g_ptr_array_unref (addrs); return ret; @@ -262,18 +266,27 @@ ip4_addresses_set (NMSetting *setting, { GPtrArray *addrs; GVariant *s_ip4; - char **labels; + char **labels, *gateway = NULL; int i; - addrs = nm_utils_ip4_addresses_from_variant (value); + addrs = nm_utils_ip4_addresses_from_variant (value, &gateway); s_ip4 = g_variant_lookup_value (connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + if (g_variant_lookup (s_ip4, "address-labels", "^as", &labels)) { for (i = 0; i < addrs->len && labels[i]; i++) if (*labels[i]) nm_ip_address_set_attribute (addrs->pdata[i], "label", g_variant_new_string (labels[i])); g_strfreev (labels); } + + if (gateway && !g_variant_lookup (s_ip4, "gateway", "s", NULL)) { + g_object_set (setting, + NM_SETTING_IP_CONFIG_GATEWAY, gateway, + NULL); + } + g_free (gateway); + g_variant_unref (s_ip4); g_object_set (setting, property, addrs, NULL); diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index dc05e541c3..9e3001157e 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -100,10 +100,12 @@ static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); + NMSettingVerifyResult ret; const char *method; - if (!NM_SETTING_CLASS (nm_setting_ip6_config_parent_class)->verify (setting, connection, error)) - return FALSE; + ret = NM_SETTING_CLASS (nm_setting_ip6_config_parent_class)->verify (setting, connection, error); + if (ret != NM_SETTING_VERIFY_SUCCESS) + return ret; method = nm_setting_ip_config_get_method (s_ip); /* Base class already checked that it exists */ @@ -187,16 +189,46 @@ ip6_dns_from_dbus (GVariant *dbus_value, } static GVariant * -ip6_addresses_to_dbus (const GValue *prop_value) +ip6_addresses_get (NMSetting *setting, + const char *property) { - return nm_utils_ip6_addresses_to_variant (g_value_get_boxed (prop_value)); + GPtrArray *addrs; + const char *gateway; + GVariant *ret; + + g_object_get (setting, property, &addrs, NULL); + gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting)); + ret = nm_utils_ip6_addresses_to_variant (addrs, gateway); + g_ptr_array_unref (addrs); + + return ret; } static void -ip6_addresses_from_dbus (GVariant *dbus_value, - GValue *prop_value) +ip6_addresses_set (NMSetting *setting, + GVariant *connection_dict, + const char *property, + GVariant *value) { - g_value_take_boxed (prop_value, nm_utils_ip6_addresses_from_variant (dbus_value)); + GPtrArray *addrs; + GVariant *s_ip6; + char *gateway = NULL; + + addrs = nm_utils_ip6_addresses_from_variant (value, &gateway); + + s_ip6 = g_variant_lookup_value (connection_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + + if (gateway && !g_variant_lookup (s_ip6, "gateway", "s", NULL)) { + g_object_set (setting, + NM_SETTING_IP_CONFIG_GATEWAY, gateway, + NULL); + } + g_free (gateway); + + g_variant_unref (s_ip6); + + g_object_set (setting, property, addrs, NULL); + g_ptr_array_unref (addrs); } static GVariant * @@ -285,11 +317,12 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) ip6_dns_to_dbus, ip6_dns_from_dbus); - _nm_setting_class_transform_property (setting_class, - NM_SETTING_IP_CONFIG_ADDRESSES, - G_VARIANT_TYPE ("a(ayuay)"), - ip6_addresses_to_dbus, - ip6_addresses_from_dbus); + _nm_setting_class_override_property (setting_class, + NM_SETTING_IP_CONFIG_ADDRESSES, + G_VARIANT_TYPE ("a(ayuay)"), + ip6_addresses_get, + ip6_addresses_set, + NULL); _nm_setting_class_transform_property (setting_class, NM_SETTING_IP_CONFIG_ROUTES, diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 110142fbfc..62698eefc8 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -1136,16 +1136,18 @@ nm_utils_ip4_dns_from_variant (GVariant *value) /** * nm_utils_ip4_addresses_to_variant: * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects + * @gateway: (allow-none): the gateway IP address * * Utility function to convert a #GPtrArray of #NMIPAddress objects representing * IPv4 addresses into a #GVariant of type 'aau' representing an array of * NetworkManager IPv4 addresses (which are tuples of address, prefix, and - * gateway, although only the first "gateway" field is preserved) + * gateway). The "gateway" field of the first address will get the value of + * @gateway (if non-%NULL). In all of the other addresses, that field will be 0. * * Returns: (transfer none): a new floating #GVariant representing @addresses. **/ GVariant * -nm_utils_ip4_addresses_to_variant (GPtrArray *addresses) +nm_utils_ip4_addresses_to_variant (GPtrArray *addresses, const char *gateway) { GVariantBuilder builder; int i; @@ -1162,8 +1164,8 @@ nm_utils_ip4_addresses_to_variant (GPtrArray *addresses) nm_ip_address_get_address_binary (addr, &array[0]); array[1] = nm_ip_address_get_prefix (addr); - if (i == 0 && nm_ip_address_get_gateway (addr)) - inet_pton (AF_INET, nm_ip_address_get_gateway (addr), &array[2]); + if (i == 0 && gateway) + inet_pton (AF_INET, gateway, &array[2]); else array[2] = 0; @@ -1179,17 +1181,19 @@ nm_utils_ip4_addresses_to_variant (GPtrArray *addresses) /** * nm_utils_ip4_addresses_from_variant: * @value: a #GVariant of type 'aau' + * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway * * Utility function to convert a #GVariant of type 'aau' representing a list of * NetworkManager IPv4 addresses (which are tuples of address, prefix, and - * gateway, although only the first "gateway" field is preserved) into a - * #GPtrArray of #NMIPAddress objects. + * gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field of + * the first address (if set) will be returned in @out_gateway; the "gateway" fields + * of the other addresses are ignored. * * Returns: (transfer full) (element-type NMIPAddress): a newly allocated * #GPtrArray of #NMIPAddress objects **/ GPtrArray * -nm_utils_ip4_addresses_from_variant (GVariant *value) +nm_utils_ip4_addresses_from_variant (GVariant *value, char **out_gateway) { GPtrArray *addresses; GVariantIter iter; @@ -1197,6 +1201,9 @@ nm_utils_ip4_addresses_from_variant (GVariant *value) g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL); + if (out_gateway) + *out_gateway = NULL; + g_variant_iter_init (&iter, value); addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); @@ -1213,16 +1220,19 @@ nm_utils_ip4_addresses_from_variant (GVariant *value) continue; } - addr = nm_ip_address_new_binary (AF_INET, - &addr_array[0], addr_array[1], - addresses->len == 0 ? &addr_array[2] : NULL, - &error); + addr = nm_ip_address_new_binary (AF_INET, &addr_array[0], addr_array[1], &error); + if (addresses->len == 0 && out_gateway) { + if (addr_array[2]) + *out_gateway = g_strdup (nm_utils_inet4_ntop (addr_array[2], NULL)); + } + if (addr) g_ptr_array_add (addresses, addr); else { g_warning ("Ignoring invalid IP4 address: %s", error->message); g_clear_error (&error); } + g_variant_unref (addr_var); } @@ -1469,16 +1479,19 @@ nm_utils_ip6_dns_from_variant (GVariant *value) /** * nm_utils_ip6_addresses_to_variant: * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects + * @gateway: (allow-none): the gateway IP address * * Utility function to convert a #GPtrArray of #NMIPAddress objects representing * IPv6 addresses into a #GVariant of type 'a(ayuay)' representing an array of * NetworkManager IPv6 addresses (which are tuples of address, prefix, and - * gateway, although only the first "gateway" field is preserved). + * gateway). The "gateway" field of the first address will get the value of + * @gateway (if non-%NULL). In all of the other addresses, that field will be + * all 0s. * * Returns: (transfer none): a new floating #GVariant representing @addresses. **/ GVariant * -nm_utils_ip6_addresses_to_variant (GPtrArray *addresses) +nm_utils_ip6_addresses_to_variant (GPtrArray *addresses, const char *gateway) { GVariantBuilder builder; int i; @@ -1489,24 +1502,24 @@ nm_utils_ip6_addresses_to_variant (GPtrArray *addresses) for (i = 0; i < addresses->len; i++) { NMIPAddress *addr = addresses->pdata[i]; struct in6_addr ip_bytes, gateway_bytes; - GVariant *ip, *gateway; + GVariant *ip_var, *gateway_var; guint32 prefix; if (nm_ip_address_get_family (addr) != AF_INET6) continue; nm_ip_address_get_address_binary (addr, &ip_bytes); - ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &ip_bytes, 16, 1); + ip_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &ip_bytes, 16, 1); prefix = nm_ip_address_get_prefix (addr); - - if (i == 0 && nm_ip_address_get_gateway (addr)) - inet_pton (AF_INET6, nm_ip_address_get_gateway (addr), &gateway_bytes); + + if (i == 0 && gateway) + inet_pton (AF_INET6, gateway, &gateway_bytes); else memset (&gateway_bytes, 0, sizeof (gateway_bytes)); - gateway = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &gateway_bytes, 16, 1); + gateway_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &gateway_bytes, 16, 1); - g_variant_builder_add (&builder, "(@ayu@ay)", ip, prefix, gateway); + g_variant_builder_add (&builder, "(@ayu@ay)", ip_var, prefix, gateway_var); } } @@ -1516,17 +1529,19 @@ nm_utils_ip6_addresses_to_variant (GPtrArray *addresses) /** * nm_utils_ip6_addresses_from_variant: * @value: a #GVariant of type 'a(ayuay)' + * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway * * Utility function to convert a #GVariant of type 'a(ayuay)' representing a * list of NetworkManager IPv6 addresses (which are tuples of address, prefix, - * and gateway, although only the first "gateway" field is preserved) into a - * #GPtrArray of #NMIPAddress objects. + * and gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field + * of the first address (if set) will be returned in @out_gateway; the "gateway" + * fields of the other addresses are ignored. * * Returns: (transfer full) (element-type NMIPAddress): a newly allocated * #GPtrArray of #NMIPAddress objects **/ GPtrArray * -nm_utils_ip6_addresses_from_variant (GVariant *value) +nm_utils_ip6_addresses_from_variant (GVariant *value, char **out_gateway) { GVariantIter iter; GVariant *addr_var, *gateway_var; @@ -1535,6 +1550,9 @@ nm_utils_ip6_addresses_from_variant (GVariant *value) g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuay)")), NULL); + if (out_gateway) + *out_gateway = NULL; + g_variant_iter_init (&iter, value); addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); @@ -1556,16 +1574,19 @@ nm_utils_ip6_addresses_from_variant (GVariant *value) __func__, (int) addr_len); goto next; } - gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1); - if (gateway_len != 16) { - g_warning ("%s: ignoring invalid IP6 address of length %d", - __func__, (int) gateway_len); - goto next; + + if (addresses->len == 0 && out_gateway) { + gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1); + if (gateway_len != 16) { + g_warning ("%s: ignoring invalid IP6 address of length %d", + __func__, (int) gateway_len); + goto next; + } + if (!IN6_IS_ADDR_UNSPECIFIED (gateway_bytes)) + *out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL)); } - addr = nm_ip_address_new_binary (AF_INET6, addr_bytes, prefix, - addresses->len == 0 ? gateway_bytes : NULL, - &error); + addr = nm_ip_address_new_binary (AF_INET6, addr_bytes, prefix, &error); if (addr) g_ptr_array_add (addresses, addr); else { diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h index ccf15f7b84..628fa0f5a6 100644 --- a/libnm-core/nm-utils.h +++ b/libnm-core/nm-utils.h @@ -97,8 +97,10 @@ gboolean nm_utils_wpa_psk_valid (const char *psk); GVariant *nm_utils_ip4_dns_to_variant (char **dns); char **nm_utils_ip4_dns_from_variant (GVariant *value); -GVariant *nm_utils_ip4_addresses_to_variant (GPtrArray *addresses); -GPtrArray *nm_utils_ip4_addresses_from_variant (GVariant *value); +GVariant *nm_utils_ip4_addresses_to_variant (GPtrArray *addresses, + const char *gateway); +GPtrArray *nm_utils_ip4_addresses_from_variant (GVariant *value, + char **out_gateway); GVariant *nm_utils_ip4_routes_to_variant (GPtrArray *routes); GPtrArray *nm_utils_ip4_routes_from_variant (GVariant *value); @@ -108,8 +110,10 @@ guint32 nm_utils_ip4_get_default_prefix (guint32 ip); GVariant *nm_utils_ip6_dns_to_variant (char **dns); char **nm_utils_ip6_dns_from_variant (GVariant *value); -GVariant *nm_utils_ip6_addresses_to_variant (GPtrArray *addresses); -GPtrArray *nm_utils_ip6_addresses_from_variant (GVariant *value); +GVariant *nm_utils_ip6_addresses_to_variant (GPtrArray *addresses, + const char *gateway); +GPtrArray *nm_utils_ip6_addresses_from_variant (GVariant *value, + char **out_gateway); GVariant *nm_utils_ip6_routes_to_variant (GPtrArray *routes); GPtrArray *nm_utils_ip6_routes_from_variant (GVariant *value); diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 041c4263f4..d66a9c9f6e 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -338,7 +338,7 @@ test_setting_ip4_config_labels (void) NULL); /* addr 1 */ - addr = nm_ip_address_new (AF_INET, "1.1.1.1", 24, NULL, &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.1", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); @@ -351,7 +351,7 @@ test_setting_ip4_config_labels (void) g_assert (label == NULL); /* addr 2 */ - addr = nm_ip_address_new (AF_INET, "2.2.2.2", 24, NULL, &error); + addr = nm_ip_address_new (AF_INET, "2.2.2.2", 24, &error); g_assert_no_error (error); nm_ip_address_set_attribute (addr, "label", g_variant_new_string ("eth0:1")); @@ -366,7 +366,7 @@ test_setting_ip4_config_labels (void) g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1"); /* addr 3 */ - addr = nm_ip_address_new (AF_INET, "3.3.3.3", 24, NULL, &error); + addr = nm_ip_address_new (AF_INET, "3.3.3.3", 24, &error); g_assert_no_error (error); nm_ip_address_set_attribute (addr, "label", NULL); @@ -1634,6 +1634,7 @@ test_connection_diff_a_only (void) { NM_SETTING_IP_CONFIG_DNS, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_DNS_SEARCH, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_ADDRESSES, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A }, @@ -2480,7 +2481,7 @@ test_setting_ip4_changed_signal (void) ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com")); ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip4)); - addr = nm_ip_address_new (AF_INET, "22.33.0.0", 24, NULL, &error); + addr = nm_ip_address_new (AF_INET, "22.33.0.0", 24, &error); g_assert_no_error (error); ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr)); ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0)); @@ -2549,7 +2550,7 @@ test_setting_ip6_changed_signal (void) nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com"); ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip6)); - addr = nm_ip_address_new (AF_INET6, "1:2:3::4:5:6", 64, NULL, &error); + addr = nm_ip_address_new (AF_INET6, "1:2:3::4:5:6", 64, &error); g_assert_no_error (error); ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr)); @@ -3336,6 +3337,145 @@ test_connection_normalize_infiniband_mtu (void) g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini)); } +static void +test_setting_ip4_gateway (void) +{ + NMConnection *conn; + NMSettingIPConfig *s_ip4; + NMIPAddress *addr; + GVariant *conn_dict, *ip4_dict, *value; + GVariantIter iter; + GVariant *addr_var; + GError *error = NULL; + + /* When serializing, ipv4.gateway is copied to the first entry of ipv4.addresses */ + conn = nmtst_create_minimal_connection ("test_setting_ip4_gateway", NULL, + NM_SETTING_WIRED_SETTING_NAME, NULL); + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "192.168.1.1", + NULL); + nm_connection_add_setting (conn, NM_SETTING (s_ip4)); + + addr = nm_ip_address_new (AF_INET, "192.168.1.10", 24, &error); + g_assert_no_error (error); + nm_setting_ip_config_add_address (s_ip4, addr); + nm_ip_address_unref (addr); + + conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref (conn); + + ip4_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert (ip4_dict != NULL); + + value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); + g_assert (value != NULL); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "192.168.1.1"); + g_variant_unref (value); + + value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("aau")); + g_assert (value != NULL); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "@au", &addr_var)) { + const guint32 *addr_array; + gsize length; + + addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32)); + g_assert_cmpint (length, ==, 3); + g_assert_cmpstr (nm_utils_inet4_ntop (addr_array[2], NULL), ==, "192.168.1.1"); + g_variant_unref (addr_var); + } + g_variant_unref (value); + + g_variant_unref (ip4_dict); + + /* When deserializing, the first gateway in ipv4.addresses is copied to ipv4.gateway */ + NMTST_VARIANT_EDITOR (conn_dict, + NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); + ); + + conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + g_variant_unref (conn_dict); + g_assert_no_error (error); + + s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn); + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1"); + + g_object_unref (conn); +} + +static void +test_setting_ip6_gateway (void) +{ + NMConnection *conn; + NMSettingIPConfig *s_ip6; + NMIPAddress *addr; + GVariant *conn_dict, *ip6_dict, *value; + GVariantIter iter; + GVariant *gateway_var; + GError *error = NULL; + + /* When serializing, ipv6.gateway is copied to the first entry of ipv6.addresses */ + conn = nmtst_create_minimal_connection ("test_setting_ip6_gateway", NULL, + NM_SETTING_WIRED_SETTING_NAME, NULL); + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "abcd::1", + NULL); + nm_connection_add_setting (conn, NM_SETTING (s_ip6)); + + addr = nm_ip_address_new (AF_INET6, "abcd::10", 64, &error); + g_assert_no_error (error); + nm_setting_ip_config_add_address (s_ip6, addr); + nm_ip_address_unref (addr); + + conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref (conn); + + ip6_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING); + g_assert (ip6_dict != NULL); + + value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING); + g_assert (value != NULL); + g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "abcd::1"); + + value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("a(ayuay)")); + g_assert (value != NULL); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) { + const guint8 *gateway_bytes; + gsize length; + + gateway_bytes = g_variant_get_fixed_array (gateway_var, &length, 1); + g_assert_cmpint (length, ==, 16); + g_assert_cmpstr (nm_utils_inet6_ntop ((struct in6_addr *) gateway_bytes, NULL), ==, "abcd::1"); + g_variant_unref (gateway_var); + } + g_variant_unref (value); + + g_variant_unref (ip6_dict); + + /* When deserializing, the first gateway in ipv4.addresses is copied to ipv4.gateway */ + NMTST_VARIANT_EDITOR (conn_dict, + NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); + ); + + conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + g_variant_unref (conn_dict); + g_assert_no_error (error); + + s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn); + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1"); + + g_object_unref (conn); +} + NMTST_DEFINE (); int main (int argc, char **argv) @@ -3424,6 +3564,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_setting_wireless_changed_signal", test_setting_wireless_changed_signal); g_test_add_func ("/core/general/test_setting_wireless_security_changed_signal", test_setting_wireless_security_changed_signal); g_test_add_func ("/core/general/test_setting_802_1x_changed_signal", test_setting_802_1x_changed_signal); + g_test_add_func ("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway); + g_test_add_func ("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway); return g_test_run (); } diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 5a5d534bfc..952b1dc263 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -289,7 +289,6 @@ global: nm_ip_address_get_attribute; nm_ip_address_get_attribute_names; nm_ip_address_get_family; - nm_ip_address_get_gateway; nm_ip_address_get_prefix; nm_ip_address_get_type; nm_ip_address_new; @@ -298,7 +297,6 @@ global: nm_ip_address_set_address; nm_ip_address_set_address_binary; nm_ip_address_set_attribute; - nm_ip_address_set_gateway; nm_ip_address_set_prefix; nm_ip_address_unref; nm_ip_route_equal; @@ -571,6 +569,7 @@ global: nm_setting_ip_config_get_dhcp_send_hostname; nm_setting_ip_config_get_dns; nm_setting_ip_config_get_dns_search; + nm_setting_ip_config_get_gateway; nm_setting_ip_config_get_ignore_auto_dns; nm_setting_ip_config_get_ignore_auto_routes; nm_setting_ip_config_get_may_fail; diff --git a/libnm/nm-ip4-config.c b/libnm/nm-ip4-config.c index bc86821043..a37f835774 100644 --- a/libnm/nm-ip4-config.c +++ b/libnm/nm-ip4-config.c @@ -74,7 +74,7 @@ demarshal_ip4_address_array (NMObject *object, GParamSpec *pspec, GVariant *valu NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object); g_ptr_array_unref (priv->addresses); - priv->addresses = nm_utils_ip4_addresses_from_variant (value); + priv->addresses = nm_utils_ip4_addresses_from_variant (value, NULL); _nm_object_queue_notify (object, NM_IP4_CONFIG_ADDRESSES); return TRUE; diff --git a/libnm/nm-ip6-config.c b/libnm/nm-ip6-config.c index 589b79ce1c..82d377ee93 100644 --- a/libnm/nm-ip6-config.c +++ b/libnm/nm-ip6-config.c @@ -59,7 +59,7 @@ demarshal_ip6_address_array (NMObject *object, GParamSpec *pspec, GVariant *valu NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object); g_ptr_array_unref (priv->addresses); - priv->addresses = nm_utils_ip6_addresses_from_variant (value); + priv->addresses = nm_utils_ip6_addresses_from_variant (value, NULL); _nm_object_queue_notify (object, NM_IP6_CONFIG_ADDRESSES); return TRUE; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index af284f0bc2..12d3919e77 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -319,14 +319,11 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, in nm_ip4_config_set_never_default (config, TRUE); else if (nm_setting_ip_config_get_ignore_auto_routes (setting)) nm_ip4_config_set_never_default (config, FALSE); - if (naddresses) { - const char *gateway_str = nm_ip_address_get_gateway (nm_setting_ip_config_get_address (setting, 0)); + if (nm_setting_ip_config_get_gateway (setting)) { guint32 gateway; - if (gateway_str) { - inet_pton (AF_INET, gateway_str, &gateway); - nm_ip4_config_set_gateway (config, gateway); - } + inet_pton (AF_INET, nm_setting_ip_config_get_gateway (setting), &gateway); + nm_ip4_config_set_gateway (config, gateway); } /* Addresses */ @@ -425,9 +422,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) if (!method) method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; - s_addr = nm_ip_address_new_binary (AF_INET, &address->address, address->plen, - i == 0 ? &gateway : NULL, - NULL); + s_addr = nm_ip_address_new_binary (AF_INET, &address->address, address->plen, NULL); if (*address->label) nm_ip_address_set_attribute (s_addr, "label", g_variant_new_string (address->label)); @@ -435,6 +430,13 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nm_ip_address_unref (s_addr); } + /* Gateway */ + if (gateway) { + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet4_ntop (gateway, NULL), + NULL); + } + /* Use 'disabled' if the method wasn't previously set */ if (!method) method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index fd21e5a624..e007b20104 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -404,6 +404,7 @@ void nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, int default_route_metric) { guint naddresses, nroutes, nnameservers, nsearches; + const char *gateway_str; int i; if (!setting) @@ -423,14 +424,12 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, in nm_ip6_config_set_never_default (config, TRUE); else if (nm_setting_ip_config_get_ignore_auto_routes (setting)) nm_ip6_config_set_never_default (config, FALSE); - if (naddresses) { - const char *gateway_str = nm_ip_address_get_gateway (nm_setting_ip_config_get_address (setting, 0)); + gateway_str = nm_setting_ip_config_get_gateway (setting); + if (gateway_str) { struct in6_addr gateway; - if (gateway_str) { - inet_pton (AF_INET6, gateway_str, &gateway); - nm_ip6_config_set_gateway (config, &gateway); - } + inet_pton (AF_INET6, gateway_str, &gateway); + nm_ip6_config_set_gateway (config, &gateway); } /* Addresses */ @@ -531,13 +530,18 @@ nm_ip6_config_create_setting (const NMIP6Config *config) if (!method || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; - s_addr = nm_ip_address_new_binary (AF_INET6, &address->address, address->plen, - i == 0 ? gateway : NULL, - NULL); + s_addr = nm_ip_address_new_binary (AF_INET6, &address->address, address->plen, NULL); nm_setting_ip_config_add_address (s_ip6, s_addr); nm_ip_address_unref (s_addr); } + /* Gateway */ + if (gateway) { + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_GATEWAY, nm_utils_inet6_ntop (gateway, NULL), + NULL); + } + /* Use 'ignore' if the method wasn't previously set */ if (!method) method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; diff --git a/src/settings/plugins/ibft/reader.c b/src/settings/plugins/ibft/reader.c index 487e3f8b05..340e197bff 100644 --- a/src/settings/plugins/ibft/reader.c +++ b/src/settings/plugins/ibft/reader.c @@ -349,7 +349,7 @@ ip4_setting_add_from_block (const GPtrArray *block, goto error; } - addr = nm_ip_address_new (AF_INET, s_ipaddr, prefix, s_gateway, error); + addr = nm_ip_address_new (AF_INET, s_ipaddr, prefix, error); if (!addr) { g_prefix_error (error, "iBFT: malformed iscsiadm record: "); goto error; @@ -358,6 +358,8 @@ ip4_setting_add_from_block (const GPtrArray *block, nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, s_gateway, NULL); + if (s_dns1) nm_setting_ip_config_add_dns (s_ip4, s_dns1); if (s_dns2) diff --git a/src/settings/plugins/ibft/tests/test-ibft.c b/src/settings/plugins/ibft/tests/test-ibft.c index 28a05bafe1..5fc63b1180 100644 --- a/src/settings/plugins/ibft/tests/test-ibft.c +++ b/src/settings/plugins/ibft/tests/test-ibft.c @@ -162,7 +162,8 @@ test_read_ibft_static (void) g_assert (ip4_addr); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.32.72"); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 22); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, "192.168.35.254"); + + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.35.254"); g_object_unref (connection); g_ptr_array_unref (block); @@ -259,7 +260,8 @@ test_read_ibft_vlan (void) g_assert (ip4_addr); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.6.200"); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, NULL); + + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, NULL); g_object_unref (connection); g_ptr_array_ref (block); diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 7b193589d2..9c3e9b0d2d 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -334,13 +334,13 @@ read_full_ip4_address (shvarFile *ifcfg, gint32 which, NMIPAddress *base_addr, NMIPAddress **out_address, + char **out_gateway, GError **error) { char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag; - char *ip = NULL, *gw = NULL; + char *ip = NULL; long prefix = 0; gboolean success = FALSE; - shvarFile *network_ifcfg; char *value; guint32 tmp; @@ -370,21 +370,9 @@ read_full_ip4_address (shvarFile *ifcfg, } /* Gateway */ - if (!read_ip4_address (ifcfg, gw_tag, &gw, error)) - goto done; - if (!gw && base_addr) - gw = g_strdup (nm_ip_address_get_gateway (base_addr)); - if (!gw) { - gboolean read_success; - - /* If no gateway in the ifcfg, try /etc/sysconfig/network instead */ - network_ifcfg = svOpenFile (network_file, NULL); - if (network_ifcfg) { - read_success = read_ip4_address (network_ifcfg, "GATEWAY", &gw, error); - svCloseFile (network_ifcfg); - if (!read_success) - goto done; - } + if (out_gateway && !*out_gateway) { + if (!read_ip4_address (ifcfg, gw_tag, out_gateway, error)) + goto done; } /* Prefix */ @@ -431,13 +419,12 @@ read_full_ip4_address (shvarFile *ifcfg, goto done; } - *out_address = nm_ip_address_new (AF_INET, ip, prefix, gw, error); + *out_address = nm_ip_address_new (AF_INET, ip, prefix, error); if (*out_address) success = TRUE; done: g_free (ip); - g_free (gw); g_free (ip_tag); g_free (prefix_tag); g_free (netmask_tag); @@ -698,9 +685,8 @@ parse_full_ip6_address (shvarFile *ifcfg, GError **error) { char **list; - char *ip_val, *prefix_val, *gateway_val = NULL; + char *ip_val, *prefix_val; long prefix; - shvarFile *network_ifcfg; gboolean success = FALSE; g_return_val_if_fail (addr_str != NULL, FALSE); @@ -733,33 +719,12 @@ parse_full_ip6_address (shvarFile *ifcfg, prefix = 64; } - /* Gateway */ - if (i == 0) { - char *ptr; - - gateway_val = svGetValue (ifcfg, "IPV6_DEFAULTGW", FALSE); - if (!gateway_val) { - /* If no gateway in the ifcfg, try global /etc/sysconfig/network instead */ - network_ifcfg = svOpenFile (network_file, NULL); - if (network_ifcfg) { - gateway_val = svGetValue (network_ifcfg, "IPV6_DEFAULTGW", FALSE); - svCloseFile (network_ifcfg); - } - } - - if ( gateway_val - && (ptr = strchr (gateway_val, '%')) != NULL) - *ptr = '\0'; /* remove %interface suffix if present */ - } else - gateway_val = NULL; - - *out_address = nm_ip_address_new (AF_INET6, ip_val, prefix, gateway_val, error); + *out_address = nm_ip_address_new (AF_INET6, ip_val, prefix, error); if (*out_address) success = TRUE; error: g_strfreev (list); - g_free (gateway_val); return success; } @@ -927,6 +892,7 @@ make_ip4_setting (shvarFile *ifcfg, char *value = NULL; char *route_path = NULL; char *method; + char *gateway = NULL; gint32 i; shvarFile *network_ifcfg; shvarFile *route_ifcfg; @@ -1031,7 +997,7 @@ make_ip4_setting (shvarFile *ifcfg, for (i = -1; i < 256; i++) { NMIPAddress *addr = NULL; - if (!read_full_ip4_address (ifcfg, network_file, i, NULL, &addr, error)) + if (!read_full_ip4_address (ifcfg, network_file, i, NULL, &addr, &gateway, error)) goto done; if (!addr) { @@ -1042,14 +1008,25 @@ make_ip4_setting (shvarFile *ifcfg, continue; } - if (nm_setting_ip_config_get_num_addresses (s_ip4)) - nm_ip_address_set_gateway (addr, NULL); - if (!nm_setting_ip_config_add_address (s_ip4, addr)) PARSE_WARNING ("duplicate IP4 address"); nm_ip_address_unref (addr); } + /* Gateway */ + if (!gateway) { + network_ifcfg = svOpenFile (network_file, NULL); + if (network_ifcfg) { + gboolean read_success; + + read_success = read_ip4_address (network_ifcfg, "GATEWAY", &gateway, error); + svCloseFile (network_ifcfg); + if (!read_success) + goto done; + } + } + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); + /* DNS servers * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ @@ -1155,6 +1132,7 @@ make_ip4_setting (shvarFile *ifcfg, return NM_SETTING (s_ip4); done: + g_free (gateway); g_free (route_path); g_object_unref (s_ip4); return NULL; @@ -1235,7 +1213,7 @@ read_aliases (NMSettingIPConfig *s_ip4, const char *filename, const char *networ } addr = NULL; - ok = read_full_ip4_address (parsed, network_file, -1, base_addr, &addr, &err); + ok = read_full_ip4_address (parsed, network_file, -1, base_addr, &addr, NULL, &err); svCloseFile (parsed); if (ok) { nm_ip_address_set_attribute (addr, "label", g_variant_new_string (device)); @@ -1431,6 +1409,33 @@ make_ip6_setting (shvarFile *ifcfg, } g_strfreev (list); + /* Gateway */ + if (nm_setting_ip_config_get_num_addresses (s_ip6)) { + value = svGetValue (ifcfg, "IPV6_DEFAULTGW", FALSE); + if (!value) { + /* If no gateway in the ifcfg, try global /etc/sysconfig/network instead */ + network_ifcfg = svOpenFile (network_file, NULL); + if (network_ifcfg) { + value = svGetValue (network_ifcfg, "IPV6_DEFAULTGW", FALSE); + svCloseFile (network_ifcfg); + } + } + if (value) { + char *ptr; + if ((ptr = strchr (value, '%')) != NULL) + *ptr = '\0'; /* remove %interface prefix if present */ + if (!nm_utils_ipaddr_valid (AF_INET6, value)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid IP6 address '%s'", value); + g_free (value); + goto error; + } + + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, value, NULL); + g_free (value); + } + } + /* DNS servers * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ 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 e9ce7ca43b..4511878642 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -493,7 +493,9 @@ test_read_wired_static (const char *file, g_assert (ip4_addr); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.1.5"); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, "192.168.1.1"); + + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1"); /* ===== IPv6 SETTING ===== */ s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -762,7 +764,9 @@ test_read_wired_dhcp_plus_ip (void) g_assert (ip4_addr); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "1.2.3.4"); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, "1.1.1.1"); + + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "1.1.1.1"); ip4_addr = nm_setting_ip_config_get_address (s_ip4, 1); g_assert (ip4_addr); @@ -836,7 +840,9 @@ test_read_wired_global_gateway (void) g_assert (ip4_addr); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.1.5"); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, "192.168.1.2"); + + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.2"); g_object_unref (connection); } @@ -2377,7 +2383,7 @@ test_read_wired_aliases_good (void) int expected_num_addresses = 4; const char *expected_address[4] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99" }; const char *expected_label[4] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99" }; - const char *expected_gateway[4] = { "192.168.1.1", "192.168.1.1", "192.168.1.1", "192.168.1.1" }; + const char *expected_gateway = "192.168.1.1"; int i, j; connection = connection_from_file (TEST_IFCFG_ALIASES_GOOD, @@ -2457,7 +2463,6 @@ test_read_wired_aliases_good (void) g_assert (j < expected_num_addresses); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, expected_gateway[j]); label = nm_ip_address_get_attribute (ip4_addr, "label"); if (expected_label[j]) g_assert_cmpstr (g_variant_get_string (label, NULL), ==, expected_label[j]); @@ -2465,10 +2470,12 @@ test_read_wired_aliases_good (void) g_assert (label == NULL); expected_address[j] = NULL; - expected_gateway[j] = NULL; expected_label[j] = NULL; } + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, expected_gateway); + for (i = 0; i < expected_num_addresses; i++) { ASSERT (expected_address[i] == NULL, "aliases-good-verify-ip4", "failed to verify %s: did not find IP4 address %s", @@ -2561,9 +2568,11 @@ test_read_wired_aliases_bad (const char *base, const char *expected_id) g_assert (ip4_addr != NULL); g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "192.168.1.5"); g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 24); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4_addr), ==, "192.168.1.1"); g_assert (nm_ip_address_get_attribute (ip4_addr, "label") == NULL); + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1"); + g_free (keyfile); g_free (routefile); g_free (route6file); @@ -6282,14 +6291,15 @@ test_write_wired_static (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); - addr = nm_ip_address_new (AF_INET, "1.1.1.5", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.5", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -6310,17 +6320,17 @@ test_write_wired_static (void) NULL); /* Add addresses */ - addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, NULL, &error); + addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); - addr6 = nm_ip_address_new (AF_INET6, "2003:1234:abcd::2", 22, NULL, &error); + addr6 = nm_ip_address_new (AF_INET6, "2003:1234:abcd::2", 22, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); - addr6 = nm_ip_address_new (AF_INET6, "3003:1234:abcd::3", 33, NULL, &error); + addr6 = nm_ip_address_new (AF_INET6, "3003:1234:abcd::3", 33, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); @@ -6689,7 +6699,7 @@ test_write_wired_static_ip6_only (void) NULL); /* Add addresses */ - addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, NULL, &error); + addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); @@ -6815,10 +6825,11 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data) g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, gateway6, NULL); /* Add addresses */ - addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, gateway6, &error); + addr6 = nm_ip_address_new (AF_INET6, "1003:1234:abcd::1", 11, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip6, addr6); nm_ip_address_unref (addr6); @@ -6873,11 +6884,11 @@ test_write_wired_static_ip6_only_gw (gconstpointer user_data) /* assert that the gateway was written and reloaded as expected */ if (!gateway6 || !strcmp (gateway6, "::")) { - g_assert (nm_ip_address_get_gateway (addr6) == NULL); + g_assert (nm_setting_ip_config_get_gateway (s_ip6) == NULL); g_assert (written_ifcfg_gateway == NULL); } else { - g_assert (nm_ip_address_get_gateway (addr6) != NULL); - g_assert_cmpstr (nm_ip_address_get_gateway (addr6), ==, gateway6); + g_assert (nm_setting_ip_config_get_gateway (s_ip6) != NULL); + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, gateway6); g_assert_cmpstr (written_ifcfg_gateway, ==, gateway6); } @@ -7092,14 +7103,15 @@ test_write_wired_static_routes (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); - addr = nm_ip_address_new (AF_INET, "1.1.1.5", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.5", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -7610,11 +7622,12 @@ test_write_wired_aliases (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); for (i = 0; i < num_addresses; i++) { - addr = nm_ip_address_new (AF_INET, ip[i], 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, ip[i], 24, &error); g_assert_no_error (error); if (label[i]) nm_ip_address_set_attribute (addr, "label", g_variant_new_string (label[i])); @@ -7709,7 +7722,6 @@ test_write_wired_aliases (void) g_assert (j < num_addresses); g_assert_cmpint (nm_ip_address_get_prefix (addr), ==, 24); - g_assert_cmpstr (nm_ip_address_get_gateway (addr), ==, "1.1.1.1"); if (label[j]) g_assert_cmpstr (g_variant_get_string (nm_ip_address_get_attribute (addr, "label"), NULL), ==, label[j]); else @@ -7725,6 +7737,9 @@ test_write_wired_aliases (void) ip[i]); } + /* Gateway */ + g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "1.1.1.1"); + g_free (testfile); g_free (keyfile); g_free (routefile); @@ -7770,15 +7785,16 @@ test_write_gateway (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.254", NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.254", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); - addr = nm_ip_address_new (AF_INET, "2.2.2.5", 24, "2.2.2.254", &error); + addr = nm_ip_address_new (AF_INET, "2.2.2.5", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -8319,10 +8335,13 @@ test_write_wifi_wep_adhoc (void) s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", + NULL); /* IP Address */ - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -9313,10 +9332,13 @@ test_write_wifi_wpa_psk_adhoc (void) s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); nm_connection_add_setting (connection, NM_SETTING (s_ip4)); - g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NULL); + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", + NULL); /* IP Address */ - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 25, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 25, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -11262,10 +11284,11 @@ test_write_bridge_main (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -12040,10 +12063,11 @@ test_write_bond_main (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); @@ -12380,10 +12404,11 @@ test_write_infiniband (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); - addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, "1.1.1.1", &error); + addr = nm_ip_address_new (AF_INET, "1.1.1.3", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index 694ed4315e..559342d4cd 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -1915,8 +1915,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_free (tmp); svSetValue (ifcfg, netmask_key, NULL, FALSE); - - svSetValue (ifcfg, gw_key, n == 0 ? nm_ip_address_get_gateway (addr) : NULL, FALSE); + svSetValue (ifcfg, gw_key, NULL, FALSE); g_free (addr_key); g_free (prefix_key); @@ -1943,6 +1942,8 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_free (gw_key); } + svSetValue (ifcfg, "GATEWAY", nm_setting_ip_config_get_gateway (s_ip4), FALSE); + num = nm_setting_ip_config_get_num_dns (s_ip4); for (i = 0; i < 254; i++) { const char *dns; @@ -2172,8 +2173,6 @@ write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path) svSetValue (ifcfg, "PREFIX", tmp, FALSE); g_free (tmp); - svSetValue (ifcfg, "GATEWAY", i == 0 ? nm_ip_address_get_gateway (addr) : NULL, FALSE); - svWriteFile (ifcfg, 0644, NULL); svCloseFile (ifcfg); } @@ -2237,7 +2236,6 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) char *addr_key; guint32 i, num, num4; GString *searches; - const char *ipv6_defaultgw; NMIPAddress *addr; const char *dns; GString *ip_str1, *ip_str2, *ip_ptr; @@ -2292,7 +2290,6 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) num = nm_setting_ip_config_get_num_addresses (s_ip6); ip_str1 = g_string_new (NULL); ip_str2 = g_string_new (NULL); - ipv6_defaultgw = NULL; for (i = 0; i < num; i++) { if (i == 0) ip_ptr = ip_str1; @@ -2306,14 +2303,10 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_string_append_printf (ip_ptr, "%s/%u", nm_ip_address_get_address (addr), nm_ip_address_get_prefix (addr)); - - /* We only support gateway for the first IP address */ - if (i == 0) - ipv6_defaultgw = nm_ip_address_get_gateway (addr); } svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE); svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE); - svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE); + svSetValue (ifcfg, "IPV6_DEFAULTGW", nm_setting_ip_config_get_gateway (s_ip6), FALSE); g_string_free (ip_str1, TRUE); g_string_free (ip_str2, TRUE); diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c index 6deee55f0a..3880e8f274 100644 --- a/src/settings/plugins/ifnet/connection_parser.c +++ b/src/settings/plugins/ifnet/connection_parser.c @@ -614,9 +614,7 @@ make_ip4_setting (NMConnection *connection, NMIPAddress *ip4_addr; GError *local = NULL; - ip4_addr = nm_ip_address_new (AF_INET, iblock->ip, iblock->prefix, - nm_setting_ip_config_get_num_addresses (ip4_setting) == 0 ? iblock->next_hop : NULL, - &local); + ip4_addr = nm_ip_address_new (AF_INET, iblock->ip, iblock->prefix, &local); if (iblock->next_hop) g_object_set (ip4_setting, NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, @@ -795,7 +793,7 @@ make_ip6_setting (NMConnection *connection, NMIPAddress *ip6_addr; GError *local = NULL; - ip6_addr = nm_ip_address_new (AF_INET6, iblock->ip, iblock->prefix, NULL, &local); + ip6_addr = nm_ip_address_new (AF_INET6, iblock->ip, iblock->prefix, &local); if (ip6_addr) { if (nm_setting_ip_config_add_address (s_ip6, ip6_addr)) { nm_log_info (LOGD_SETTINGS, "ipv6 addresses count: %d", @@ -2408,10 +2406,10 @@ write_ip4_setting (NMConnection *connection, const char *conn_name, GError **err nm_ip_address_get_prefix (addr)); /* only the first gateway will be written */ - if (i == 0 && nm_ip_address_get_gateway (addr)) { + if (i == 0 && nm_setting_ip_config_get_gateway (s_ip4)) { g_string_append_printf (routes, "\"default via %s\" ", - nm_ip_address_get_gateway (addr)); + nm_setting_ip_config_get_gateway (s_ip4)); } } ifnet_set_data (conn_name, "config", ips->str); diff --git a/src/settings/plugins/ifupdown/parser.c b/src/settings/plugins/ifupdown/parser.c index 8dc37dcd7d..4ccfb62f8a 100644 --- a/src/settings/plugins/ifupdown/parser.c +++ b/src/settings/plugins/ifupdown/parser.c @@ -480,15 +480,8 @@ update_ip4_setting_from_if_block(NMConnection *connection, } } - /* gateway */ - gateway_v = ifparser_getkey (block, "gateway"); - if (!gateway_v) - gateway_v = address_v; /* dcbw: whaaa?? */ - /* Add the new address to the setting */ - addr = nm_ip_address_new (AF_INET, address_v, netmask_int, - nm_setting_ip_config_get_num_addresses (s_ip4) == 0 ? gateway_v : NULL, - error); + addr = nm_ip_address_new (AF_INET, address_v, netmask_int, error); if (!addr) goto error; @@ -500,6 +493,18 @@ update_ip4_setting_from_if_block(NMConnection *connection, } nm_ip_address_unref (addr); + /* gateway */ + gateway_v = ifparser_getkey (block, "gateway"); + if (gateway_v) { + if (!nm_utils_ipaddr_valid (AF_INET, gateway_v)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid IPv4 gateway '%s'", gateway_v); + goto error; + } + if (!nm_setting_ip_config_get_gateway (s_ip4)) + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL); + } + nameserver_v = ifparser_getkey (block, "dns-nameserver"); ifupdown_ip4_add_dns (s_ip4, nameserver_v); @@ -595,15 +600,8 @@ update_ip6_setting_from_if_block(NMConnection *connection, if (prefix_v) prefix_int = g_ascii_strtoll (prefix_v, NULL, 10); - /* Gateway */ - gateway_v = ifparser_getkey (block, "gateway"); - if (!gateway_v) - gateway_v = address_v; /* dcbw: whaaa?? */ - /* Add the new address to the setting */ - addr = nm_ip_address_new (AF_INET6, address_v, prefix_int, - nm_setting_ip_config_get_num_addresses (s_ip6) == 0 ? gateway_v : NULL, - error); + addr = nm_ip_address_new (AF_INET6, address_v, prefix_int, error); if (!addr) goto error; @@ -615,6 +613,18 @@ update_ip6_setting_from_if_block(NMConnection *connection, } nm_ip_address_unref (addr); + /* gateway */ + gateway_v = ifparser_getkey (block, "gateway"); + if (gateway_v) { + if (!nm_utils_ipaddr_valid (AF_INET6, gateway_v)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, + "Invalid IPv6 gateway '%s'", gateway_v); + goto error; + } + if (!nm_setting_ip_config_get_gateway (s_ip6)) + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_v, NULL); + } + nameserver_v = ifparser_getkey(block, "dns-nameserver"); ifupdown_ip6_add_dns (s_ip6, nameserver_v); diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c index 46c80552e9..793e485993 100644 --- a/src/settings/plugins/keyfile/reader.c +++ b/src/settings/plugins/keyfile/reader.c @@ -108,15 +108,37 @@ get_one_int (const char *str, guint32 max_val, const char *key_name, guint32 *ou } static gpointer -build_address_or_route (const char *key_name, const char *address_str, guint32 plen, const char *gateway_str, const char *metric_str, int family, gboolean route) +build_address (int family, const char *address_str, guint32 plen) { - gpointer result; - guint32 metric = 0; + NMIPAddress *addr; GError *error = NULL; g_return_val_if_fail (address_str, NULL); - /* Gateway */ + addr = nm_ip_address_new (family, address_str, plen, &error); + if (!addr) { + nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid %s address: %s", __func__, + family == AF_INET ? "IPv4" : "IPv6", + error->message); + g_error_free (error); + } + + return addr; +} + +static gpointer +build_route (int family, + const char *dest_str, guint32 plen, + const char *gateway_str, const char *metric_str, + const char *key_name) +{ + NMIPRoute *route; + guint32 metric = 0; + GError *error = NULL; + + g_return_val_if_fail (dest_str, NULL); + + /* Next hop */ if (gateway_str && gateway_str[0]) { if (!nm_utils_ipaddr_valid (family, gateway_str)) { /* Try workaround for routes written by broken keyfile writer. @@ -128,7 +150,6 @@ build_address_or_route (const char *key_name, const char *address_str, guint32 p * supported. **/ if ( family == AF_INET6 - && route && !metric_str && get_one_int (gateway_str, G_MAXUINT32, NULL, &metric)) gateway_str = NULL; @@ -146,19 +167,15 @@ build_address_or_route (const char *key_name, const char *address_str, guint32 p return NULL; } - if (route) - result = nm_ip_route_new (family, address_str, plen, gateway_str, metric, &error); - else - result = nm_ip_address_new (family, address_str, plen, gateway_str, &error); - if (!result) { - nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid %s %s: %s", __func__, + route = nm_ip_route_new (family, dest_str, plen, gateway_str, metric, &error); + if (!route) { + nm_log_warn (LOGD_SETTINGS, "%s: ignoring invalid %s route: %s", __func__, family == AF_INET ? "IPv4" : "IPv6", - route ? "route" : "address", error->message); g_error_free (error); } - return result; + return route; } /* On success, returns pointer to the zero-terminated field (original @current). @@ -251,7 +268,8 @@ read_one_ip_address_or_route (GKeyFile *file, const char *setting_name, const char *key_name, gboolean ipv6, - gboolean route) + gboolean route, + char **out_gateway) { guint32 plen; gpointer result; @@ -317,8 +335,16 @@ read_one_ip_address_or_route (GKeyFile *file, } /* build the appropriate data structure for NetworkManager settings */ - result = build_address_or_route (key_name, address_str, plen, gateway_str, metric_str, - ipv6 ? AF_INET6 : AF_INET, route); + if (route) { + result = build_route (ipv6 ? AF_INET6 : AF_INET, + address_str, plen, gateway_str, metric_str, + key_name); + } else { + result = build_address (ipv6 ? AF_INET6 : AF_INET, + address_str, plen); + if (out_gateway && gateway_str) + *out_gateway = g_strdup (gateway_str); + } g_free (value); return result; @@ -336,6 +362,7 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi static const char *key_names_routes[] = { "route", "routes", NULL }; static const char *key_names_addresses[] = { "address", "addresses", NULL }; const char **key_names = routes ? key_names_routes : key_names_addresses; + char *gateway = NULL; GPtrArray *list; GDestroyNotify free_func; int i; @@ -359,21 +386,23 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi else key_name = g_strdup (*key_basename); - item = read_one_ip_address_or_route (keyfile, setting_name, key_name, ipv6, routes); + item = read_one_ip_address_or_route (keyfile, setting_name, key_name, ipv6, routes, + gateway ? NULL : &gateway); + if (item) + g_ptr_array_add (list, item); + g_free (key_name); - - if (!item) - continue; - - if (!routes && list->len > 0) - nm_ip_address_set_gateway (item, NULL); - g_ptr_array_add (list, item); } } if (list->len >= 1) g_object_set (setting, key, list, NULL); + if (gateway) { + g_object_set (setting, "gateway", gateway, NULL); + g_free (gateway); + } + g_ptr_array_unref (list); } diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index 9cc98615ff..2e0b619dad 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -38,14 +38,13 @@ #define TEST_WIRELESS_FILE TEST_KEYFILES_DIR"/Test_Wireless_Connection" static void -check_ip_address (NMSettingIPConfig *config, int idx, const char *address, int plen, const char *gateway) +check_ip_address (NMSettingIPConfig *config, int idx, const char *address, int plen) { NMIPAddress *ip4 = nm_setting_ip_config_get_address (config, idx); g_assert (ip4); g_assert_cmpstr (nm_ip_address_get_address (ip4), ==, address); g_assert_cmpint (nm_ip_address_get_prefix (ip4), ==, plen); - g_assert_cmpstr (nm_ip_address_get_gateway (ip4), ==, gateway); } static void @@ -246,12 +245,19 @@ test_read_valid_wired_connection (void) /* IPv4 addresses */ g_assert (nm_setting_ip_config_get_num_addresses (s_ip4) == 6); - check_ip_address (s_ip4, 0, "2.3.4.5", 24, "2.3.4.6"); - check_ip_address (s_ip4, 1, "192.168.0.5", 24, NULL); - check_ip_address (s_ip4, 2, "1.2.3.4", 16, NULL); - check_ip_address (s_ip4, 3, "3.4.5.6", 16, NULL); - check_ip_address (s_ip4, 4, "4.5.6.7", 24, NULL); - check_ip_address (s_ip4, 5, "5.6.7.8", 24, NULL); + check_ip_address (s_ip4, 0, "2.3.4.5", 24); + check_ip_address (s_ip4, 1, "192.168.0.5", 24); + check_ip_address (s_ip4, 2, "1.2.3.4", 16); + check_ip_address (s_ip4, 3, "3.4.5.6", 16); + check_ip_address (s_ip4, 4, "4.5.6.7", 24); + check_ip_address (s_ip4, 5, "5.6.7.8", 24); + + /* IPv4 gateway */ + ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip4), "2.3.4.6") == 0, + "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value", + TEST_WIRED_FILE, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); /* IPv4 routes */ g_assert (nm_setting_ip_config_get_num_routes (s_ip4) == 12); @@ -328,16 +334,23 @@ test_read_valid_wired_connection (void) /* IPv6 addresses */ g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 10); - check_ip_address (s_ip6, 0, "2:3:4:5:6:7:8:9", 64, "2:3:4:5:1:2:3:4"); - check_ip_address (s_ip6, 1, "abcd:1234:ffff::cdde", 64, NULL); - check_ip_address (s_ip6, 2, "1:2:3:4:5:6:7:8", 96, NULL); - check_ip_address (s_ip6, 3, "3:4:5:6:7:8:9:0", 128, NULL); - check_ip_address (s_ip6, 4, "3:4:5:6:7:8:9:14", 64, NULL); - check_ip_address (s_ip6, 5, "3:4:5:6:7:8:9:15", 64, NULL); - check_ip_address (s_ip6, 6, "3:4:5:6:7:8:9:16", 66, NULL); - check_ip_address (s_ip6, 7, "3:4:5:6:7:8:9:17", 67, NULL); - check_ip_address (s_ip6, 8, "3:4:5:6:7:8:9:18", 68, NULL); - check_ip_address (s_ip6, 9, "3:4:5:6:7:8:9:19", 69, NULL); + check_ip_address (s_ip6, 0, "2:3:4:5:6:7:8:9", 64); + check_ip_address (s_ip6, 1, "abcd:1234:ffff::cdde", 64); + check_ip_address (s_ip6, 2, "1:2:3:4:5:6:7:8", 96); + check_ip_address (s_ip6, 3, "3:4:5:6:7:8:9:0", 128); + check_ip_address (s_ip6, 4, "3:4:5:6:7:8:9:14", 64); + check_ip_address (s_ip6, 5, "3:4:5:6:7:8:9:15", 64); + check_ip_address (s_ip6, 6, "3:4:5:6:7:8:9:16", 66); + check_ip_address (s_ip6, 7, "3:4:5:6:7:8:9:17", 67); + check_ip_address (s_ip6, 8, "3:4:5:6:7:8:9:18", 68); + check_ip_address (s_ip6, 9, "3:4:5:6:7:8:9:19", 69); + + /* IPv6 gateway */ + ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "2:3:4:5:1:2:3:4") == 0, + "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value", + TEST_WIRED_FILE, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); /* Route #1 */ g_assert (nm_setting_ip_config_get_num_routes (s_ip6) == 7); @@ -354,14 +367,13 @@ test_read_valid_wired_connection (void) static void add_one_ip_address (NMSettingIPConfig *s_ip, const char *addr, - guint32 prefix, - const char *gw) + guint32 prefix) { NMIPAddress *ip_addr; GError *error = NULL; ip_addr = nm_ip_address_new (NM_IS_SETTING_IP4_CONFIG (s_ip) ? AF_INET : AF_INET6, - addr, prefix, gw, &error); + addr, prefix, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip, ip_addr); nm_ip_address_unref (ip_addr); @@ -404,8 +416,8 @@ test_write_wired_connection (void) 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 *gw = "192.168.0.1"; const char *route1 = "10.10.10.2"; const char *route1_nh = "10.10.10.1"; const char *route2 = "1.1.1.1"; @@ -462,11 +474,12 @@ test_write_wired_connection (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, gw, NULL); /* Addresses */ - add_one_ip_address (s_ip4, address1, 24, address1_gw); - add_one_ip_address (s_ip4, address2, 8, NULL); + add_one_ip_address (s_ip4, address1, 24); + add_one_ip_address (s_ip4, address2, 8); /* Routes */ add_one_ip_route (s_ip4, route1, route1_nh, 24, 3); @@ -488,8 +501,8 @@ test_write_wired_connection (void) NULL); /* Addresses */ - add_one_ip_address (s_ip6, address6_1, 64, NULL); - add_one_ip_address (s_ip6, address6_2, 56, NULL); + add_one_ip_address (s_ip6, address6_1, 64); + add_one_ip_address (s_ip6, address6_2, 56); /* Routes */ add_one_ip_route (s_ip6, route6_1, route6_1_nh, 64, 3); @@ -634,7 +647,14 @@ test_read_ip6_wired_connection (void) /* IPv6 address */ g_assert (nm_setting_ip_config_get_num_addresses (s_ip6) == 1); - check_ip_address (s_ip6, 0, "abcd:1234:ffff::cdde", 64, "abcd:1234:ffff::cdd1"); + check_ip_address (s_ip6, 0, "abcd:1234:ffff::cdde", 64); + + /* IPv6 gateway */ + ASSERT (strcmp (nm_setting_ip_config_get_gateway (s_ip6), "abcd:1234:ffff::cdd1") == 0, + "connection-verify-wired", "failed to verify %s: unexpected %s / %s key value", + TEST_WIRED_IP6_FILE, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY); g_object_unref (connection); } @@ -695,10 +715,11 @@ test_write_ip6_wired_connection (void) g_object_set (s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, gw, NULL); /* Addresses */ - add_one_ip_address (s_ip6, address, 64, gw); + add_one_ip_address (s_ip6, address, 64); /* DNS servers */ nm_setting_ip_config_add_dns (s_ip6, dns); @@ -2816,9 +2837,10 @@ test_write_bridge_main (void) g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.1", NULL); - add_one_ip_address (s_ip4, "1.2.3.4", 24, "1.1.1.1"); + add_one_ip_address (s_ip4, "1.2.3.4", 24); /* IP6 setting */ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c index e6515398e2..24d7aba991 100644 --- a/src/settings/plugins/keyfile/writer.c +++ b/src/settings/plugins/keyfile/writer.c @@ -117,6 +117,7 @@ static void write_ip_values (GKeyFile *file, const char *setting_name, GPtrArray *array, + const char *gateway, gboolean is_route) { GString *output; @@ -147,10 +148,7 @@ write_ip_values (GKeyFile *file, addr = nm_ip_address_get_address (address); plen = nm_ip_address_get_prefix (address); - if (i == 0) - gw = nm_ip_address_get_gateway (address); - else - gw = NULL; + gw = i == 0 ? gateway : NULL; metric = 0; } @@ -190,10 +188,11 @@ addr_writer (GKeyFile *file, { GPtrArray *array; const char *setting_name = nm_setting_get_name (setting); + const char *gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting)); array = (GPtrArray *) g_value_get_boxed (value); if (array && array->len) - write_ip_values (file, setting_name, array, FALSE); + write_ip_values (file, setting_name, array, gateway, FALSE); } static void @@ -207,6 +206,17 @@ ip4_addr_label_writer (GKeyFile *file, /* skip */ } +static void +gateway_writer (GKeyFile *file, + const char *keyfile_dir, + const char *uuid, + NMSetting *setting, + const char *key, + const GValue *value) +{ + /* skip */ +} + static void route_writer (GKeyFile *file, const char *keyfile_dir, @@ -220,7 +230,7 @@ route_writer (GKeyFile *file, array = (GPtrArray *) g_value_get_boxed (value); if (array && array->len) - write_ip_values (file, setting_name, array, TRUE); + write_ip_values (file, setting_name, array, NULL, TRUE); } static void @@ -589,6 +599,12 @@ static KeyWriter key_writers[] = { { NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES, addr_writer }, + { NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY, + gateway_writer }, + { NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_GATEWAY, + gateway_writer }, { NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ROUTES, route_writer }, diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 2f073c9cac..968a4bae87 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -601,8 +601,9 @@ test_connection_no_match_ip4_addr (void) g_assert (s_ip4); g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.254", NULL); - nm_addr = nm_ip_address_new (AF_INET, "1.1.1.4", 24, "1.1.1.254", &error); + nm_addr = nm_ip_address_new (AF_INET, "1.1.1.4", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, nm_addr); nm_ip_address_unref (nm_addr); @@ -611,8 +612,9 @@ test_connection_no_match_ip4_addr (void) g_assert (s_ip4); g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP_CONFIG_GATEWAY, "2.2.2.254", NULL); - nm_addr = nm_ip_address_new (AF_INET, "2.2.2.4", 24, "2.2.2.254", &error); + nm_addr = nm_ip_address_new (AF_INET, "2.2.2.4", 24, &error); g_assert_no_error (error); nm_setting_ip_config_add_address (s_ip4, nm_addr); nm_ip_address_unref (nm_addr);