diff options
237 files changed, 8335 insertions, 5102 deletions
diff --git a/.travis.yml b/.travis.yml index b907bf13ed..44e5e0a247 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_install: libnl-3-dev libnl-route-3-dev libnl-genl-3-dev ppp-dev libpolkit-gobject-1-dev libgnutls28-dev libgcrypt11-dev uuid-dev libudev-dev libgudev-1.0-dev libgirepository1.0-dev gobject-introspection libsoup2.4-dev gtk-doc-tools libglib2.0-doc libreadline-dev libnewt-dev libnss3-dev iptables make python-software-properties python-gi - python-dbus dbus dbus-x11 + python-dbus dbus dbus-x11 libjansson4 libjansson-dev - sudo dbus-uuidgen --ensure - sudo apt-add-repository 'deb http://archive.ubuntu.com/ubuntu trusty main' - sudo apt-add-repository 'deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse' diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 65c4be7286..e1688278a4 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -186,7 +186,7 @@ static NmcOutputField nmc_fields_dev_wimax_list[] = { #define NMC_FIELDS_DEV_WIMAX_LIST_COMMON "NSP,SIGNAL,TYPE,DEVICE,ACTIVE" #define NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST "NAME,"NMC_FIELDS_DEV_WIMAX_LIST_COMMON -/* Available fields for 'device show' - BOND, TEAM, BRIDGE part */ +/* Available fields for 'device show' - BOND, BRIDGE part */ static NmcOutputField nmc_fields_dev_show_master_prop[] = { {"NAME", N_("NAME")}, /* 0 */ {"SLAVES", N_("SLAVES")}, /* 1 */ @@ -195,6 +195,16 @@ static NmcOutputField nmc_fields_dev_show_master_prop[] = { #define NMC_FIELDS_DEV_SHOW_MASTER_PROP_ALL "NAME,SLAVES" #define NMC_FIELDS_DEV_SHOW_MASTER_PROP_COMMON "NAME,SLAVES" +/* Available fields for 'device show' - TEAM part */ +static NmcOutputField nmc_fields_dev_show_team_prop[] = { + {"NAME", N_("NAME")}, /* 0 */ + {"SLAVES", N_("SLAVES")}, /* 1 */ + {"CONFIG", N_("CONFIG")}, /* 2 */ + {NULL, NULL} +}; +#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL "NAME,SLAVES,CONFIG" +#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_COMMON "NAME,SLAVES,CONFIG" + /* Available fields for 'device show' - VLAN part */ static NmcOutputField nmc_fields_dev_show_vlan_prop[] = { {"NAME", N_("NAME")}, /* 0 */ @@ -234,7 +244,7 @@ static NmcOutputField nmc_fields_dev_show_sections[] = { {"IP6", N_("IP6"), 0, nmc_fields_ip6_config + 1 }, /* 9 */ {"DHCP6", N_("DHCP6"), 0, nmc_fields_dhcp6_config + 1 }, /* 10 */ {"BOND", N_("BOND"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 11 */ - {"TEAM", N_("TEAM"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 12 */ + {"TEAM", N_("TEAM"), 0, nmc_fields_dev_show_team_prop + 1 }, /* 12 */ {"BRIDGE", N_("BRIDGE"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 13 */ {"VLAN", N_("VLAN"), 0, nmc_fields_dev_show_vlan_prop + 1 }, /* 14 */ {"BLUETOOTH", N_("BLUETOOTH"), 0, nmc_fields_dev_show_bluetooth + 1 }, /* 15 */ @@ -840,10 +850,10 @@ get_active_connection_id (NMDevice *device) } static gboolean -print_bond_team_bridge_info (NMDevice *device, - NmCli *nmc, - const char *group_prefix, - const char *one_field) +print_bond_bridge_info (NMDevice *device, + NmCli *nmc, + const char *group_prefix, + const char *one_field) { const GPtrArray *slaves = NULL; GString *slaves_str; @@ -853,10 +863,10 @@ print_bond_team_bridge_info (NMDevice *device, if (NM_IS_DEVICE_BOND (device)) slaves = nm_device_bond_get_slaves (NM_DEVICE_BOND (device)); - else if (NM_IS_DEVICE_TEAM (device)) - slaves = nm_device_team_get_slaves (NM_DEVICE_TEAM (device)); else if (NM_IS_DEVICE_BRIDGE (device)) slaves = nm_device_bridge_get_slaves (NM_DEVICE_BRIDGE (device)); + else + g_return_val_if_reached (FALSE); slaves_str = g_string_new (NULL); for (idx = 0; slaves && idx < slaves->len; idx++) { @@ -891,6 +901,76 @@ print_bond_team_bridge_info (NMDevice *device, return TRUE; } +static char * +sanitize_team_config (const char *config) +{ + char *ret; + int i; + + if (!config) + return NULL; + + ret = g_strdup (config); + + for (i = 0; i < strlen (ret); i++) { + if (ret[i] == '\n') + ret[i] = ' '; + } + + return ret; +} + +static gboolean +print_team_info (NMDevice *device, + NmCli *nmc, + const char *group_prefix, + const char *one_field) +{ + const GPtrArray *slaves = NULL; + GString *slaves_str; + int idx; + NmcOutputField *tmpl, *arr; + size_t tmpl_len; + + if (NM_IS_DEVICE_TEAM (device)) + slaves = nm_device_team_get_slaves (NM_DEVICE_TEAM (device)); + else + g_return_val_if_reached (FALSE); + + slaves_str = g_string_new (NULL); + for (idx = 0; slaves && idx < slaves->len; idx++) { + NMDevice *slave = g_ptr_array_index (slaves, idx); + const char *iface = nm_device_get_iface (slave); + + if (iface) { + g_string_append (slaves_str, iface); + g_string_append_c (slaves_str, ' '); + } + } + if (slaves_str->len > 0) + g_string_truncate (slaves_str, slaves_str->len-1); /* Chop off last space */ + + tmpl = nmc_fields_dev_show_team_prop; + tmpl_len = sizeof (nmc_fields_dev_show_team_prop); + nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL, + tmpl, FALSE, NULL, NULL); + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES); + g_ptr_array_add (nmc->output_data, arr); + + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX); + set_val_strc (arr, 0, group_prefix); /* TEAM */ + set_val_str (arr, 1, slaves_str->str); + set_val_str (arr, 2, sanitize_team_config (nm_device_team_get_config (NM_DEVICE_TEAM (device)))); + g_ptr_array_add (nmc->output_data, arr); + + print_data (nmc); /* Print all data */ + + g_string_free (slaves_str, FALSE); + nmc_empty_output_fields (nmc); + + return TRUE; +} + static gboolean show_device_info (NMDevice *device, NmCli *nmc) { @@ -1146,19 +1226,19 @@ show_device_info (NMDevice *device, NmCli *nmc) /* Bond specific information */ if (NM_IS_DEVICE_BOND (device)) { if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[11].name)) - was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[11].name, section_fld); + was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[11].name, section_fld); } /* Team specific information */ if (NM_IS_DEVICE_TEAM (device)) { if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[12].name)) - was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[12].name, section_fld); + was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[12].name, section_fld); } /* Bridge specific information */ if (NM_IS_DEVICE_BRIDGE (device)) { if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[13].name)) - was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[13].name, section_fld); + was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[13].name, section_fld); } /* VLAN-specific information */ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index d254df3c68..0f75d2a791 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -272,20 +272,21 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS), /* 2 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH), /* 3 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_OPTIONS), /* 4 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES), /* 5 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY), /* 6 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES), /* 7 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC), /* 8 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES), /* 9 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS), /* 10 */ - SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID), /* 11 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_TIMEOUT), /* 12 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 13 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 14 */ - SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_FQDN), /* 15 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT), /* 16 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL), /* 17 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DAD_TIMEOUT), /* 18 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_PRIORITY), /* 5 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES), /* 6 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES), /* 8 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC), /* 9 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES), /* 10 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS), /* 11 */ + SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_TIMEOUT), /* 13 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 14 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 15 */ + SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_FQDN), /* 16 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT), /* 17 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL), /* 18 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DAD_TIMEOUT), /* 19 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_IP4_CONFIG_ALL "name"","\ @@ -293,6 +294,7 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { NM_SETTING_IP_CONFIG_DNS","\ NM_SETTING_IP_CONFIG_DNS_SEARCH","\ NM_SETTING_IP_CONFIG_DNS_OPTIONS","\ + NM_SETTING_IP_CONFIG_DNS_PRIORITY","\ NM_SETTING_IP_CONFIG_ADDRESSES","\ NM_SETTING_IP_CONFIG_GATEWAY","\ NM_SETTING_IP_CONFIG_ROUTES","\ @@ -315,18 +317,20 @@ NmcOutputField nmc_fields_setting_ip6_config[] = { SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS), /* 2 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_SEARCH), /* 3 */ SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_OPTIONS), /* 4 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES), /* 5 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY), /* 6 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES), /* 7 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC), /* 8 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES), /* 9 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS), /* 10 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT), /* 11 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL), /* 12 */ - SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY), /* 13 */ - SETTING_FIELD (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE), /* 14 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 15 */ - SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 16 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DNS_PRIORITY), /* 5 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ADDRESSES), /* 6 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_GATEWAY), /* 7 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTES), /* 8 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_ROUTE_METRIC), /* 9 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES), /* 10 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS), /* 11 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT), /* 12 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL), /* 13 */ + SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY), /* 14 */ + SETTING_FIELD (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE), /* 15 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 16 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 17 */ + SETTING_FIELD (NM_SETTING_IP6_CONFIG_TOKEN), /* 18 */ {NULL, NULL, 0, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTING_IP6_CONFIG_ALL "name"","\ @@ -334,6 +338,7 @@ NmcOutputField nmc_fields_setting_ip6_config[] = { NM_SETTING_IP_CONFIG_DNS","\ NM_SETTING_IP_CONFIG_DNS_SEARCH","\ NM_SETTING_IP_CONFIG_DNS_OPTIONS","\ + NM_SETTING_IP_CONFIG_DNS_PRIORITY","\ NM_SETTING_IP_CONFIG_ADDRESSES","\ NM_SETTING_IP_CONFIG_GATEWAY","\ NM_SETTING_IP_CONFIG_ROUTES","\ @@ -345,7 +350,8 @@ NmcOutputField nmc_fields_setting_ip6_config[] = { NM_SETTING_IP6_CONFIG_IP6_PRIVACY","\ NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE","\ NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME","\ - NM_SETTING_IP_CONFIG_DHCP_HOSTNAME + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME","\ + NM_SETTING_IP6_CONFIG_TOKEN /* Available fields for NM_SETTING_SERIAL_SETTING_NAME */ NmcOutputField nmc_fields_setting_serial[] = { @@ -1488,6 +1494,7 @@ DEFINE_GETTER (nmc_property_ipv4_get_method, NM_SETTING_IP_CONFIG_METHOD) 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) DEFINE_GETTER_WITH_DEFAULT (nmc_property_ipv4_get_dns_options, NM_SETTING_IP_CONFIG_DNS_OPTIONS, !nm_setting_ip_config_has_dns_options ((NMSettingIPConfig *) setting)) +DEFINE_GETTER (nmc_property_ipv4_get_dns_priority, NM_SETTING_IP_CONFIG_DNS_PRIORITY) static char * nmc_property_ip_get_addresses (NMSetting *setting, NmcPropertyGetType get_type) @@ -1608,6 +1615,7 @@ 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) DEFINE_GETTER_WITH_DEFAULT (nmc_property_ipv6_get_dns_options, NM_SETTING_IP_CONFIG_DNS_OPTIONS, !nm_setting_ip_config_has_dns_options ((NMSettingIPConfig *) setting)) +DEFINE_GETTER (nmc_property_ipv6_get_dns_priority, NM_SETTING_IP_CONFIG_DNS_PRIORITY) static char * nmc_property_ipv6_get_routes (NMSetting *setting, NmcPropertyGetType get_type) @@ -1623,6 +1631,7 @@ DEFINE_GETTER (nmc_property_ipv6_get_never_default, NM_SETTING_IP_CONFIG_NEVER_D DEFINE_GETTER (nmc_property_ipv6_get_may_fail, NM_SETTING_IP_CONFIG_MAY_FAIL) DEFINE_GETTER (nmc_property_ipv6_get_dhcp_send_hostname, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME) DEFINE_GETTER (nmc_property_ipv6_get_dhcp_hostname, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME) +DEFINE_GETTER (nmc_property_ipv6_get_token, NM_SETTING_IP6_CONFIG_TOKEN) static char * nmc_property_ipv6_get_ip6_privacy (NMSetting *setting, NmcPropertyGetType get_type) @@ -6496,6 +6505,13 @@ nmc_properties_init (void) NULL, NULL, NULL); + nmc_add_prop_funcs (GLUE_IP (4, DNS_PRIORITY), + nmc_property_ipv4_get_dns_priority, + nmc_property_set_int, + NULL, + NULL, + NULL, + NULL); nmc_add_prop_funcs (GLUE_IP (4, ADDRESSES), nmc_property_ip_get_addresses, nmc_property_ipv4_set_addresses, @@ -6624,6 +6640,13 @@ nmc_properties_init (void) NULL, NULL, NULL); + nmc_add_prop_funcs (GLUE_IP (6, DNS_PRIORITY), + nmc_property_ipv6_get_dns_priority, + nmc_property_set_int, + NULL, + NULL, + NULL, + NULL); nmc_add_prop_funcs (GLUE_IP (6, ADDRESSES), nmc_property_ip_get_addresses, nmc_property_ipv6_set_addresses, @@ -6708,6 +6731,13 @@ nmc_properties_init (void) NULL, NULL, NULL); + nmc_add_prop_funcs (GLUE (IP6_CONFIG, TOKEN), + nmc_property_ipv6_get_token, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); /* Add editable properties for NM_SETTING_OLPC_MESH_SETTING_NAME */ nmc_add_prop_funcs (GLUE (OLPC_MESH, SSID), @@ -8179,20 +8209,21 @@ setting_ip4_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro set_val_str (arr, 2, nmc_property_ipv4_get_dns (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 3, nmc_property_ipv4_get_dns_search (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 4, nmc_property_ipv4_get_dns_options (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 5, nmc_property_ip_get_addresses (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 6, nmc_property_ipv4_get_gateway (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 7, nmc_property_ipv4_get_routes (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 8, nmc_property_ipv4_get_route_metric (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 9, nmc_property_ipv4_get_ignore_auto_routes (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 10, nmc_property_ipv4_get_ignore_auto_dns (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 11, nmc_property_ipv4_get_dhcp_client_id (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 12, nmc_property_ipv4_get_dhcp_timeout (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 13, nmc_property_ipv4_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 14, nmc_property_ipv4_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 15, nmc_property_ipv4_get_dhcp_fqdn (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 16, nmc_property_ipv4_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 17, nmc_property_ipv4_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 18, nmc_property_ipv4_get_dad_timeout (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 5, nmc_property_ipv4_get_dns_priority (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 6, nmc_property_ip_get_addresses (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 7, nmc_property_ipv4_get_gateway (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 8, nmc_property_ipv4_get_routes (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 9, nmc_property_ipv4_get_route_metric (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 10, nmc_property_ipv4_get_ignore_auto_routes (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_ipv4_get_ignore_auto_dns (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_ipv4_get_dhcp_client_id (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 13, nmc_property_ipv4_get_dhcp_timeout (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 14, nmc_property_ipv4_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 15, nmc_property_ipv4_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 16, nmc_property_ipv4_get_dhcp_fqdn (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 17, nmc_property_ipv4_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 18, nmc_property_ipv4_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 19, nmc_property_ipv4_get_dad_timeout (setting, NMC_PROPERTY_GET_PRETTY)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ @@ -8222,18 +8253,20 @@ setting_ip6_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro set_val_str (arr, 2, nmc_property_ipv6_get_dns (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 3, nmc_property_ipv6_get_dns_search (setting, NMC_PROPERTY_GET_PRETTY)); set_val_str (arr, 4, nmc_property_ipv6_get_dns_options (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 5, nmc_property_ip_get_addresses (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 6, nmc_property_ipv6_get_gateway (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 7, nmc_property_ipv6_get_routes (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 8, nmc_property_ipv6_get_route_metric (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 9, nmc_property_ipv6_get_ignore_auto_routes (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 10, nmc_property_ipv6_get_ignore_auto_dns (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 11, nmc_property_ipv6_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 12, nmc_property_ipv6_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 13, nmc_property_ipv6_get_ip6_privacy (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 14, nmc_property_ipv6_get_addr_gen_mode (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 15, nmc_property_ipv6_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY)); - set_val_str (arr, 16, nmc_property_ipv6_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 5, nmc_property_ipv6_get_dns_priority (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 6, nmc_property_ip_get_addresses (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 7, nmc_property_ipv6_get_gateway (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 8, nmc_property_ipv6_get_routes (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 9, nmc_property_ipv6_get_route_metric (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 10, nmc_property_ipv6_get_ignore_auto_routes (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_ipv6_get_ignore_auto_dns (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_ipv6_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 13, nmc_property_ipv6_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 14, nmc_property_ipv6_get_ip6_privacy (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 15, nmc_property_ipv6_get_addr_gen_mode (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 16, nmc_property_ipv6_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 17, nmc_property_ipv6_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 18, nmc_property_ipv6_get_token (setting, NMC_PROPERTY_GET_PRETTY)); g_ptr_array_add (nmc->output_data, arr); print_data (nmc); /* Print all data */ diff --git a/clients/common/nm-vpn-helpers.c b/clients/common/nm-vpn-helpers.c index fe777ef55f..43ac4b2e61 100644 --- a/clients/common/nm-vpn-helpers.c +++ b/clients/common/nm-vpn-helpers.c @@ -28,7 +28,6 @@ #include "nm-vpn-helpers.h" #include <string.h> -#include <gmodule.h> #include "nm-utils.h" @@ -157,9 +156,7 @@ nm_vpn_get_service_for_name (const char *name) if (plugin_info) { /* this only means we have a .name file (NMVpnPluginInfo). Possibly the * NMVpnEditorPlugin is not loadable. */ - return nm_vpn_plugin_info_lookup_property (plugin_info, - NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, - "service"); + return nm_vpn_plugin_info_get_service (plugin_info); } return NULL; } diff --git a/clients/tui/nmtui-connect.c b/clients/tui/nmtui-connect.c index 46e3361740..ae9dd43ed9 100644 --- a/clients/tui/nmtui-connect.c +++ b/clients/tui/nmtui-connect.c @@ -378,7 +378,7 @@ listbox_active_changed (GObject *object, } static NmtNewtForm * -nmt_connect_connection_list (void) +nmt_connect_connection_list (gboolean is_top) { int screen_width, screen_height; NmtNewtForm *form; @@ -410,7 +410,7 @@ nmt_connect_connection_list (void) listbox_active_changed (G_OBJECT (list), NULL, activate); g_signal_connect (activate, "clicked", G_CALLBACK (activate_clicked), list); - quit = nmt_newt_button_box_add_end (NMT_NEWT_BUTTON_BOX (bbox), _("Quit")); + quit = nmt_newt_button_box_add_end (NMT_NEWT_BUTTON_BOX (bbox), is_top ? _("Quit") : _("Back")); nmt_newt_widget_set_exit_on_activate (quit, TRUE); nmt_newt_form_set_content (form, grid); @@ -444,10 +444,10 @@ nmt_connect_connection (const char *identifier) } NmtNewtForm * -nmtui_connect (int argc, char **argv) +nmtui_connect (gboolean is_top, int argc, char **argv) { if (argc == 2) return nmt_connect_connection (argv[1]); else - return nmt_connect_connection_list (); + return nmt_connect_connection_list (is_top); } diff --git a/clients/tui/nmtui-connect.h b/clients/tui/nmtui-connect.h index 8310ac389a..89cb3916da 100644 --- a/clients/tui/nmtui-connect.h +++ b/clients/tui/nmtui-connect.h @@ -21,7 +21,7 @@ G_BEGIN_DECLS -NmtNewtForm *nmtui_connect (int argc, char **argv); +NmtNewtForm *nmtui_connect (gboolean is_top, int argc, char **argv); G_END_DECLS diff --git a/clients/tui/nmtui-edit.c b/clients/tui/nmtui-edit.c index c7efd856db..1e887f516f 100644 --- a/clients/tui/nmtui-edit.c +++ b/clients/tui/nmtui-edit.c @@ -103,7 +103,7 @@ edit_connection_list_filter (NmtEditConnectionList *list, } static NmtNewtForm * -nmt_edit_main_connection_list (void) +nmt_edit_main_connection_list (gboolean is_top) { int screen_width, screen_height; NmtNewtForm *form; @@ -117,7 +117,7 @@ nmt_edit_main_connection_list (void) "escape-exits", TRUE, NULL); - quit = nmt_newt_button_new (_("Quit")); + quit = nmt_newt_button_new (is_top ? _("Quit") : _("Back")); nmt_newt_widget_set_exit_on_activate (quit, TRUE); list = g_object_new (NMT_TYPE_EDIT_CONNECTION_LIST, @@ -555,7 +555,7 @@ nmt_remove_connection (NMRemoteConnection *connection) } NmtNewtForm * -nmtui_edit (int argc, char **argv) +nmtui_edit (gboolean is_top, int argc, char **argv) { NMConnection *conn = NULL; @@ -572,5 +572,5 @@ nmtui_edit (int argc, char **argv) return nmt_editor_new (conn); } else - return nmt_edit_main_connection_list (); + return nmt_edit_main_connection_list (is_top); } diff --git a/clients/tui/nmtui-edit.h b/clients/tui/nmtui-edit.h index dae91cfac7..459011e10b 100644 --- a/clients/tui/nmtui-edit.h +++ b/clients/tui/nmtui-edit.h @@ -26,7 +26,7 @@ G_BEGIN_DECLS typedef gboolean (*NmtAddConnectionTypeFilter) (GType connection_type, gpointer user_data); -NmtNewtForm *nmtui_edit (int argc, char **argv); +NmtNewtForm *nmtui_edit (gboolean is_top, int argc, char **argv); void nmt_add_connection (void); void nmt_add_connection_full (const char *primary_text, diff --git a/clients/tui/nmtui-hostname.c b/clients/tui/nmtui-hostname.c index ada2393fd1..f800550292 100644 --- a/clients/tui/nmtui-hostname.c +++ b/clients/tui/nmtui-hostname.c @@ -96,7 +96,7 @@ hostname_set (GObject *object, } NmtNewtForm * -nmtui_hostname (int argc, char **argv) +nmtui_hostname (gboolean is_top, int argc, char **argv) { const char *hostname; char *tmp = NULL; diff --git a/clients/tui/nmtui-hostname.h b/clients/tui/nmtui-hostname.h index a14bc69937..1af711f9bb 100644 --- a/clients/tui/nmtui-hostname.h +++ b/clients/tui/nmtui-hostname.h @@ -21,7 +21,7 @@ G_BEGIN_DECLS -NmtNewtForm *nmtui_hostname (int argc, char **argv); +NmtNewtForm *nmtui_hostname (gboolean is_top, int argc, char **argv); G_END_DECLS diff --git a/clients/tui/nmtui.c b/clients/tui/nmtui.c index 47ba5bf56e..70cad5d6ad 100644 --- a/clients/tui/nmtui.c +++ b/clients/tui/nmtui.c @@ -43,7 +43,7 @@ NMClient *nm_client; static GMainLoop *loop; -typedef NmtNewtForm * (*NmtuiSubprogram) (int argc, char **argv); +typedef NmtNewtForm * (*NmtuiSubprogram) (gboolean is_top, int argc, char **argv); static const struct { const char *name, *shortcut, *arg; @@ -61,22 +61,43 @@ static const struct { nmtui_hostname } }; static const int num_subprograms = G_N_ELEMENTS (subprograms); +static NmtNewtForm *toplevel_form; -static void +static NmtNewtForm * quit_func (int argc, char **argv) { + if (toplevel_form) + nmt_newt_form_quit (toplevel_form); + nmtui_quit (); + + return NULL; +} + +static void +main_list_activated (NmtNewtWidget *widget, NmtNewtListbox *listbox) +{ + NmtNewtForm *form; + NmtuiSubprogram sub; + + sub = nmt_newt_listbox_get_active_key (listbox); + if (sub) { + form = sub (FALSE, 0, NULL); + if (form) { + nmt_newt_form_show (form); + g_object_unref (form); + } + } } static NmtNewtForm * -nmtui_main (int argc, char **argv) +nmtui_main (gboolean is_top, int argc, char **argv) { NmtNewtForm *form; NmtNewtWidget *widget, *ok; NmtNewtGrid *grid; NmtNewtListbox *listbox; NmtNewtButtonBox *bbox; - NmtuiSubprogram subprogram = NULL; int i; form = g_object_new (NMT_TYPE_NEWT_FORM, @@ -97,8 +118,9 @@ nmtui_main (int argc, char **argv) NULL); nmt_newt_grid_add (grid, widget, 0, 1); nmt_newt_widget_set_padding (widget, 0, 1, 0, 1); - nmt_newt_widget_set_exit_on_activate (widget, TRUE); listbox = NMT_NEWT_LISTBOX (widget); + g_signal_connect (widget, "activated", + G_CALLBACK (main_list_activated), listbox); for (i = 0; i < num_subprograms; i++) { nmt_newt_listbox_append (listbox, _(subprograms[i].display_name), @@ -112,17 +134,12 @@ nmtui_main (int argc, char **argv) bbox = NMT_NEWT_BUTTON_BOX (widget); ok = nmt_newt_button_box_add_end (bbox, _("OK")); - nmt_newt_widget_set_exit_on_activate (ok, TRUE); + g_signal_connect (ok, "activated", + G_CALLBACK (main_list_activated), listbox); - widget = nmt_newt_form_run_sync (form); - if (widget) - subprogram = nmt_newt_listbox_get_active_key (listbox); - g_object_unref (form); + toplevel_form = form; - if (subprogram) - return subprogram (argc, argv); - else - return NULL; + return form; } /** @@ -179,7 +196,7 @@ idle_run_subprogram (gpointer user_data) NmtuiStartupData *data = user_data; NmtNewtForm *form; - form = data->subprogram (data->argc, data->argv); + form = data->subprogram (TRUE, data->argc, data->argv); if (form) { g_signal_connect (form, "quit", G_CALLBACK (toplevel_form_quit), NULL); nmt_newt_form_show (form); diff --git a/configure.ac b/configure.ac index 6067a88fbe..e963b4f3a9 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,10 @@ AC_PROG_CXX AC_PROG_LN_S +# Prefer gcc-* variants; the ones libtool would choose don't work with LTO +AC_CHECK_TOOLS(AR, [gcc-ar ar], false) +AC_CHECK_TOOLS(RANLIB, [gcc-ranlib ranlib], :) + dnl Initialize libtool LT_PREREQ([2.2]) LT_INIT([disable-static]) @@ -553,6 +557,18 @@ else fi AM_CONDITIONAL(WITH_TEAMDCTL, test "${enable_teamdctl}" = "yes") +PKG_CHECK_MODULES(JANSSON, jansson, [have_jansson=yes], [have_jansson=no]) +AC_ARG_ENABLE(json-validation, AS_HELP_STRING([--enable-json-validation], [Enable JSON validation in libnm]), + [enable_json_validation=${enableval}], [enable_json_validation=${have_jansson}]) +if (test "${enable_json_validation}" = "yes"); then + if test x"$have_jansson" = x"no"; then + AC_MSG_ERROR(Jansson is required for JSON validation) + fi + AC_DEFINE(WITH_JANSSON, 1, [Define if JANSSON is enabled]) +else + AC_DEFINE(WITH_JANSSON, 0, [Define if JANSSON is enabled]) +fi + # we usually compile with polkit support. --enable-polkit=yes|no only sets the # default configuration for main.auth-polkit. User can always enable/disable polkit # autorization via config. Only when specifying --enable-polkit=disabled, we do @@ -763,6 +779,11 @@ fi # resolvconf and netconfig support AC_ARG_WITH(resolvconf, AS_HELP_STRING([--with-resolvconf=yes|no|path], [Enable resolvconf support])) AC_ARG_WITH(netconfig, AS_HELP_STRING([--with-netconfig=yes|no], [Enable SUSE netconfig support])) +AC_ARG_WITH(config-dns-rc-manager-default, AS_HELP_STRING([--with-config-dns-rc-manager-default=symlink|file|netconfig|resolvconf], [Configure default value for main.rc-manager setting]), [config_dns_rc_manager_default=$withval]) +if test "$config_dns_rc_manager_default" != symlink -a "$config_dns_rc_manager_default" != file -a "$config_dns_rc_manager_default" != netconfig -a "$config_dns_rc_manager_default" != resolvconf; then + AC_MSG_WARN([Unknown --with-config-dns-rc-manager-default=$config_dns_rc_manager_default setting.]) + config_dns_rc_manager_default= +fi # Use netconfig by default on SUSE AS_IF([test -z "$with_netconfig"], AC_CHECK_FILE(/etc/SuSE-release, with_netconfig=yes)) # Otherwise default to "no" @@ -772,9 +793,16 @@ AS_IF([test -z "$with_netconfig"], with_netconfig=no) if test "$with_resolvconf" = "yes"; then AC_PATH_PROGS(with_resolvconf, resolvconf, no, /sbin:/usr/sbin:/usr/local/sbin) fi +if test "$with_resolvconf" != "no"; then + AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=resolvconf) +fi if test "$with_netconfig" = "yes"; then AC_PATH_PROGS(with_netconfig, netconfig, no, /sbin:/usr/sbin:/usr/local/sbin) fi +if test "$with_netconfig" != "no"; then + AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=netconfig) +fi +AS_IF([test -z "$config_dns_rc_manager_default"], config_dns_rc_manager_default=symlink) # Define resolvconf and netconfig paths if test "$with_resolvconf" != "no"; then AC_DEFINE_UNQUOTED(RESOLVCONF_PATH, "$with_resolvconf", [Path to resolvconf]) @@ -782,6 +810,8 @@ fi if test "$with_netconfig" != "no"; then AC_DEFINE_UNQUOTED(NETCONFIG_PATH, "$with_netconfig", [Path to netconfig]) fi +AC_DEFINE_UNQUOTED(NM_CONFIG_DEFAULT_DNS_RC_MANAGER, "$config_dns_rc_manager_default", [Default value for main.rc-manager setting (--with-config-dns-rc-manager-default)]) +AC_SUBST(NM_CONFIG_DEFAULT_DNS_RC_MANAGER, $config_dns_rc_manager_default) # iptables path AC_ARG_WITH(iptables, AS_HELP_STRING([--with-iptables=/path/to/iptables], [path to iptables])) @@ -919,6 +949,16 @@ else enable_lto='no' fi +AC_ARG_ENABLE(ld-gc, AS_HELP_STRING([--enable-ld-gc], [Enable garbage collection of unused symbols on linking (default: auto)])) +if (test "${enable_ld_gc}" != "no"); then + NM_COMPILER_FLAG([-fdata-sections -ffunction-sections -Wl,--gc-sections], [enable_ld_gc='yes'], [ + if (test "${enable_ld_gc}" = "yes"); then + AC_MSG_ERROR([Unused symbol eviction requested but not supported.]) + else + enable_ld_gc='no' + fi + ]) +fi dnl ------------------------- dnl Vala bindings @@ -1164,6 +1204,7 @@ echo echo "Handlers for /etc/resolv.conf:" echo " resolvconf: ${with_resolvconf}" echo " netconfig: ${with_netconfig}" +echo " config-dns-rc-manager-default: ${config_dns_rc_manager_default}" echo echo "DHCP clients:" @@ -1178,4 +1219,6 @@ echo " more-asserts: $more_asserts" echo " valgrind: $with_valgrind $with_valgrind_suppressions" echo " code coverage: $enable_code_coverage" echo " LTO: $enable_lto" +echo " linker garbage collection: $enable_ld_gc" +echo " JSON validation: $enable_json_validation" echo diff --git a/contrib/fedora/REQUIRED_PACKAGES b/contrib/fedora/REQUIRED_PACKAGES index 559ac848f6..5a4b42863c 100644 --- a/contrib/fedora/REQUIRED_PACKAGES +++ b/contrib/fedora/REQUIRED_PACKAGES @@ -42,4 +42,10 @@ yum install \ rpm-build \ perl-YAML-LibYAM \ perl-YAML \ + audit-libs-devel \ + bluez-libs-devel \ + dbus-python \ + libselinux-devel \ + pygobject3-base \ + jansson-devel \ diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 1f40e01a5f..8a25690efe 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -30,7 +30,14 @@ %global _hardened_build 1 -%global git_sha_version %{?git_sha:.%{git_sha}} +%if x%{?snapshot} != x +%global snapshot_dot .%{snapshot} +%endif +%if x%{?git_sha} != x +%global git_sha_dot .%{git_sha} +%endif + +%global snap %{?git_sha_dot}%{?snapshot_dot} ############################################################################### @@ -89,7 +96,7 @@ Name: NetworkManager Summary: Network connection manager and user applications Epoch: %{epoch_version} Version: %{rpm_version} -Release: %{release_version}%{snapshot}%{git_sha_version}%{?dist} +Release: %{release_version}%{?snap}%{?dist} Group: System Environment/Base License: GPLv2+ URL: http://www.gnome.org/projects/NetworkManager/ @@ -169,6 +176,7 @@ BuildRequires: pygobject3-base BuildRequires: dbus-python BuildRequires: libselinux-devel BuildRequires: polkit-devel +BuildRequires: jansson-devel %description @@ -324,6 +332,18 @@ ethernet devices with no carrier. This package is intended to be installed by default for server deployments. +%package dispatcher-routing-rules +Summary: NetworkManager dispatcher file for advanced routing rules +Group: System Environment/Base +BuildArch: noarch +Provides: %{name}-config-routing-rules = %{epoch}:%{version}-%{release} +Obsoletes: %{name}-config-routing-rules < %{epoch}:%{version}-%{release} + +%description dispatcher-routing-rules +This adds a NetworkManager dispatcher file to support networking +configurations using "/etc/sysconfig/network-scripts/rule-NAME" files +(eg, to do policy-based routing). + %if 0%{with_nmtui} %package tui Summary: NetworkManager curses-based UI @@ -498,12 +518,9 @@ fi %{_datadir}/bash-completion/completions/nmcli %dir %{_sysconfdir}/%{name}/ %dir %{_sysconfdir}/%{name}/dispatcher.d -%{_sysconfdir}/%{name}/dispatcher.d/10-ifcfg-rh-routes.sh %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-down.d %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-up.d %dir %{_sysconfdir}/%{name}/dispatcher.d/no-wait.d -%{_sysconfdir}/%{name}/dispatcher.d/no-wait.d/10-ifcfg-rh-routes.sh -%{_sysconfdir}/%{name}/dispatcher.d/pre-up.d/10-ifcfg-rh-routes.sh %dir %{_sysconfdir}/%{name}/dnsmasq.d %dir %{_sysconfdir}/%{name}/dnsmasq-shared.d %dir %{_sysconfdir}/%{name}/VPN @@ -633,6 +650,11 @@ fi %dir %{nmlibdir}/conf.d %{nmlibdir}/conf.d/00-server.conf +%files dispatcher-routing-rules +%{_sysconfdir}/%{name}/dispatcher.d/10-ifcfg-rh-routes.sh +%{_sysconfdir}/%{name}/dispatcher.d/no-wait.d/10-ifcfg-rh-routes.sh +%{_sysconfdir}/%{name}/dispatcher.d/pre-up.d/10-ifcfg-rh-routes.sh + %if %{with nmtui} %files tui %{_bindir}/nmtui diff --git a/contrib/fedora/rpm/build.sh b/contrib/fedora/rpm/build.sh index 6da1ade3c1..35336bad15 100755 --- a/contrib/fedora/rpm/build.sh +++ b/contrib/fedora/rpm/build.sh @@ -70,7 +70,7 @@ get_version() { write_changelog() { if [[ "x$CHANGELOG" == x ]]; then cat <<- EOF - * $(LC_TIME=C date '+%a %b %d %Y') $USERNAME - %{epoch_version}:%{version}-%{release_version}%{snapshot}%{git_sha_version} + * $(LC_TIME=C date '+%a %b %d %Y') $USERNAME - %{epoch_version}:%{version}-%{release_version}%{?snap} - build of NetworkManager ($DATE, uuid: $UUID, git: $COMMIT_FULL) $(git log -n20 --date=local --format='- %h %s [%an] (%ci)') - ... @@ -163,6 +163,7 @@ sed -e "s/__VERSION__/$VERSION/g" \ -e "s/__RELEASE_VERSION__/$RELEASE_VERSION/g" \ -e "s/__COMMIT__/$COMMIT/g" \ -e "s/__COMMIT_FULL__/$COMMIT_FULL/g" \ + -e "s/__SNAPSHOT__/$SNAPSHOT/g" \ -e "s/__SOURCE1__/$(basename "$SOURCE")/g" \ "$SPECFILE" | sed -e "/^__CHANGELOG__$/ \ diff --git a/introspection/nm-device-team.xml b/introspection/nm-device-team.xml index 05bbbafe46..64faaec4b0 100644 --- a/introspection/nm-device-team.xml +++ b/introspection/nm-device-team.xml @@ -26,6 +26,13 @@ <property name="Slaves" type="ao" access="read"/> <!-- + Config: + + The JSON configuration currently applied on the device. + --> + <property name="Config" type="s" access="read" /> + + <!-- PropertiesChanged: @properties: A dictionary mapping property names to variant boxed values --> diff --git a/introspection/nm-ip4-config.xml b/introspection/nm-ip4-config.xml index c2a0f06828..bbe7bebeae 100644 --- a/introspection/nm-ip4-config.xml +++ b/introspection/nm-ip4-config.xml @@ -77,6 +77,13 @@ <property name="DnsOptions" type="as" access="read"/> <!-- + DnsPriority: + + The relative priority of DNS servers. + --> + <property name="DnsPriority" type="i" access="read"/> + + <!-- WinsServers: The Windows Internet Name Service servers associated with the connection. diff --git a/introspection/nm-ip6-config.xml b/introspection/nm-ip6-config.xml index 606761dd2b..a58bfffa55 100644 --- a/introspection/nm-ip6-config.xml +++ b/introspection/nm-ip6-config.xml @@ -77,6 +77,13 @@ <property name="DnsOptions" type="as" access="read"/> <!-- + DnsPriority: + + The relative priority of DNS servers. + --> + <property name="DnsPriority" type="i" access="read"/> + + <!-- PropertiesChanged: @properties: A dictionary mapping property names to variant boxed values --> diff --git a/libnm-core/Makefile.am b/libnm-core/Makefile.am index 3335720a4a..695b6a3a58 100644 --- a/libnm-core/Makefile.am +++ b/libnm-core/Makefile.am @@ -12,9 +12,11 @@ AM_CPPFLAGS = \ -DNMCONFDIR=\"$(nmconfdir)\" \ -DNMLIBDIR=\"$(nmlibdir)\" \ -DNMPLUGINDIR=\"$(pkglibdir)\" \ + -DLIBEXECDIR=\"$(libexecdir)\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \ $(GLIB_CFLAGS) \ - $(CODE_COVERAGE_CFLAGS) + $(CODE_COVERAGE_CFLAGS) \ + $(JANSSON_CFLAGS) noinst_LTLIBRARIES = libnm-core.la @@ -36,7 +38,8 @@ GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM libnm_core_la_LIBADD = \ $(GLIB_LIBS) \ - $(UUID_LIBS) + $(UUID_LIBS) \ + $(JANSSON_LIBS) libnm_core_la_LDFLAGS = \ $(CODE_COVERAGE_LDFLAGS) diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 7a0e1f6bda..a823af9bea 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -23,6 +23,7 @@ #include "nm-default.h" #include <string.h> +#include <arpa/inet.h> #include "nm-connection.h" #include "nm-connection-private.h" @@ -724,6 +725,7 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) const char *default_ip6_method = NULL; NMSettingIPConfig *s_ip4, *s_ip6; NMSetting *setting; + gboolean changed = FALSE; if (parameters) default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD); @@ -756,6 +758,12 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) NM_SETTING_IP_CONFIG_METHOD, default_ip4_method, NULL); nm_connection_add_setting (self, setting); + } else { + if ( nm_setting_ip_config_get_gateway (s_ip4) + && nm_setting_ip_config_get_never_default (s_ip4)) { + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); + changed = TRUE; + } } if (!s_ip6) { setting = nm_setting_ip6_config_new (); @@ -765,8 +773,32 @@ _normalize_ip_config (NMConnection *self, GHashTable *parameters) NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, NULL); nm_connection_add_setting (self, setting); + } else { + const char *token; + + token = nm_setting_ip6_config_get_token ((NMSettingIP6Config *) s_ip6); + if ( token + && nm_setting_ip6_config_get_addr_gen_mode ((NMSettingIP6Config *) s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { + struct in6_addr i6_token; + char normalized[NM_UTILS_INET_ADDRSTRLEN]; + + if ( inet_pton (AF_INET6, token, &i6_token) == 1 + && _nm_utils_inet6_is_token (&i6_token)) { + nm_utils_inet6_ntop (&i6_token, normalized); + if (g_strcmp0 (token, normalized)) { + g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, normalized, NULL); + changed = TRUE; + } + } + } + + if ( nm_setting_ip_config_get_gateway (s_ip6) + && nm_setting_ip_config_get_never_default (s_ip6)) { + g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, NULL, NULL); + changed = TRUE; + } } - return !s_ip4 || !s_ip6; + return !s_ip4 || !s_ip6 || changed; } } diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 2041a1d3a1..a09ee26c48 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -296,4 +296,8 @@ typedef enum { NMBondOptionType _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name); +/***********************************************************/ + +gboolean _nm_utils_inet6_is_token (const struct in6_addr *in6addr); + #endif diff --git a/libnm-core/nm-keyfile-writer.c b/libnm-core/nm-keyfile-writer.c index 0ce7641c1d..f62e97c3e6 100644 --- a/libnm-core/nm-keyfile-writer.c +++ b/libnm-core/nm-keyfile-writer.c @@ -233,16 +233,23 @@ route_writer (KeyfileWriterInfo *info, write_ip_values (info->keyfile, setting_name, array, NULL, TRUE); } +static int +sort_hash_keys (gconstpointer a, gconstpointer b, gpointer user_data) +{ + return g_strcmp0 (*((const char **) a), *((const char **) b)); +} + static void write_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key, const GValue *value) { - GHashTableIter iter; - const char *property = NULL, *data = NULL; + GHashTable *hash; const char *group_name = nm_setting_get_name (setting); gboolean vpn_secrets = FALSE; + gs_free const char **keys = NULL; + guint i, l; /* Write VPN secrets out to a different group to keep them separate */ if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) { @@ -250,10 +257,19 @@ write_hash_of_string (GKeyFile *file, vpn_secrets = TRUE; } - g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value)); - while (g_hash_table_iter_next (&iter, (gpointer *) &property, (gpointer *) &data)) { + hash = g_value_get_boxed (value); + keys = (const char **) g_hash_table_get_keys_as_array (hash, &l); + if (!keys) + return; + + g_qsort_with_data (keys, l, sizeof (const char *), sort_hash_keys, NULL); + + for (i = 0; keys[i]; i++) { + const char *property, *data; gboolean write_item = TRUE; + property = keys[i]; + /* Handle VPN secrets specially; they are nested in the property's hash; * we don't want to write them if the secret is not saved, not required, * or owned by a user's secret agent. @@ -266,8 +282,10 @@ write_hash_of_string (GKeyFile *file, write_item = FALSE; } - if (write_item) + if (write_item) { + data = g_hash_table_lookup (hash, property); nm_keyfile_plugin_kf_set_string (file, group_name, property, data); + } } } diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 3e7f93b065..bdcbc23b08 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -1120,6 +1120,7 @@ typedef struct { GPtrArray *dns; /* array of IP address strings */ GPtrArray *dns_search; /* array of domain name strings */ GPtrArray *dns_options;/* array of DNS options */ + gint dns_priority; GPtrArray *addresses; /* array of NMIPAddress */ GPtrArray *routes; /* array of NMIPRoute */ gint64 route_metric; @@ -1140,6 +1141,7 @@ enum { PROP_DNS, PROP_DNS_SEARCH, PROP_DNS_OPTIONS, + PROP_DNS_PRIORITY, PROP_ADDRESSES, PROP_GATEWAY, PROP_ROUTES, @@ -1684,6 +1686,22 @@ nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_ } /** + * nm_setting_ip_config_get_dns_priority: + * @setting: the #NMSettingIPConfig + * + * Returns: the priority of DNS servers + * + * Since: 1.2.4 + **/ +gint +nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0); + + return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_priority; +} + +/** * nm_setting_ip_config_get_num_addresses: * @setting: the #NMSettingIPConfig * @@ -2274,6 +2292,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) } } + if (priv->gateway && priv->never_default) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("a gateway is incompatible with '%s'"), + NM_SETTING_IP_CONFIG_NEVER_DEFAULT); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + return TRUE; } @@ -2352,6 +2380,9 @@ set_property (GObject *object, guint prop_id, } } break; + case PROP_DNS_PRIORITY: + priv->dns_priority = g_value_get_int (value); + break; case PROP_ADDRESSES: g_ptr_array_unref (priv->addresses); priv->addresses = _nm_utils_copy_array (g_value_get_boxed (value), @@ -2424,6 +2455,9 @@ get_property (GObject *object, guint prop_id, case PROP_DNS_OPTIONS: g_value_take_boxed (value, priv->dns_options ? _nm_utils_ptrarray_to_strv (priv->dns_options) : NULL); break; + case PROP_DNS_PRIORITY: + g_value_set_int (value, priv->dns_priority); + break; case PROP_ADDRESSES: g_value_take_boxed (value, _nm_utils_copy_array (priv->addresses, (NMUtilsCopyFunc) nm_ip_address_dup, @@ -2576,6 +2610,34 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) G_PARAM_STATIC_STRINGS)); /** + * NMSettingIPConfig:dns-priority: + * + * DNS priority. + * + * The relative priority to be used when determining the order of DNS + * servers in resolv.conf. A lower value means that servers will be on top + * of the file. Zero selects the default value, which is 50 for VPNs and + * 100 for other connections. When multiple devices have configurations + * with the same priority, the one with an active default route will be + * preferred. Note that when using dns=dnsmasq the order is meaningless + * since dnsmasq forwards queries to all known servers at the same time. + * + * Negative values have the special effect of excluding other configurations + * with a greater priority value; so in presence of at least a negative + * priority, only DNS servers from configurations with the lowest priority + * value will be used. + * + * Since: 1.2.4 + **/ + g_object_class_install_property + (object_class, PROP_DNS_PRIORITY, + g_param_spec_int (NM_SETTING_IP_CONFIG_DNS_PRIORITY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** * NMSettingIPConfig:addresses: * * Array of IP addresses. diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index 79c7e63921..a41c5466c8 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -136,6 +136,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_DNS_OPTIONS "dns-options" +#define NM_SETTING_IP_CONFIG_DNS_PRIORITY "dns-priority" #define NM_SETTING_IP_CONFIG_ADDRESSES "addresses" #define NM_SETTING_IP_CONFIG_GATEWAY "gateway" #define NM_SETTING_IP_CONFIG_ROUTES "routes" @@ -219,6 +220,9 @@ gboolean nm_setting_ip_config_remove_dns_option_by_value (NMSettingIPConfig const char *dns_option); void nm_setting_ip_config_clear_dns_options (NMSettingIPConfig *setting, gboolean is_set); +NM_AVAILABLE_IN_1_2_4 +gint nm_setting_ip_config_get_dns_priority (NMSettingIPConfig *setting); + guint nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting); NMIPAddress *nm_setting_ip_config_get_address (NMSettingIPConfig *setting, int idx); diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index 9b479a083d..8f43def019 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -654,6 +654,17 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) * ---end--- */ + /* ---ifcfg-rh--- + * property: dns-priority + * variable: IPV4_DNS_PRIORITY(+) + * description: The priority for DNS servers of this connection. Lower values have higher priority. + * If zero, the default value will be used (50 for VPNs, 100 for other connections). + * A negative value prevents DNS from other connections with greater values to be used. + * default: 0 + * example: IPV4_DNS_PRIORITY=20 + * ---end--- + */ + /** * NMSettingIP4Config:dhcp-client-id: * diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index 1f0b11fc98..17afcae79e 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -24,6 +24,7 @@ #include "nm-setting-ip6-config.h" #include <string.h> +#include <arpa/inet.h> #include "nm-setting-private.h" #include "nm-core-enum-types.h" @@ -59,6 +60,7 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG) typedef struct { NMSettingIP6ConfigPrivacy ip6_privacy; NMSettingIP6ConfigAddrGenMode addr_gen_mode; + char *token; } NMSettingIP6ConfigPrivate; @@ -66,6 +68,7 @@ enum { PROP_0, PROP_IP6_PRIVACY, PROP_ADDR_GEN_MODE, + PROP_TOKEN, LAST_PROP }; @@ -120,6 +123,25 @@ nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting) return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->addr_gen_mode; } +/** + * nm_setting_ip6_config_get_token: + * @setting: the #NMSettingIP6Config + * + * Returns the value contained in the #NMSettingIP6Config:token + * property. + * + * Returns: A string. + * + * Since: 1.2.4 + **/ +const char * +nm_setting_ip6_config_get_token (NMSettingIP6Config *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL); + + return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->token; +} + static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { @@ -127,6 +149,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); NMSettingVerifyResult ret; const char *method; + gboolean token_needs_normalization = FALSE; ret = NM_SETTING_CLASS (nm_setting_ip6_config_parent_class)->verify (setting, connection, error); if (ret != NM_SETTING_VERIFY_SUCCESS) @@ -201,6 +224,44 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return FALSE; } + if (priv->token) { + if (priv->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) { + struct in6_addr i6_token; + char s_token[NM_UTILS_INET_ADDRSTRLEN]; + + if ( inet_pton (AF_INET6, priv->token, &i6_token) != 1 + || !_nm_utils_inet6_is_token (&i6_token)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("value is not a valid token")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_TOKEN); + return FALSE; + } + + if (g_strcmp0 (priv->token, nm_utils_inet6_ntop (&i6_token, s_token))) + token_needs_normalization = TRUE; + } else { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("only makes sense with EUI64 address generation mode")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_TOKEN); + return FALSE; + } + } + + /* Failures from here on, are NORMALIZABLE_ERROR... */ + + if (token_needs_normalization) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("token is not in canonical form")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_TOKEN); + return NM_SETTING_VERIFY_NORMALIZABLE_ERROR; + } + return TRUE; } @@ -388,6 +449,10 @@ set_property (GObject *object, guint prop_id, case PROP_ADDR_GEN_MODE: priv->addr_gen_mode = g_value_get_int (value); break; + case PROP_TOKEN: + g_free (priv->token); + priv->token = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -407,6 +472,9 @@ get_property (GObject *object, guint prop_id, case PROP_ADDR_GEN_MODE: g_value_set_int (value, priv->addr_gen_mode); break; + case PROP_TOKEN: + g_value_set_string (value, priv->token); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -414,6 +482,17 @@ get_property (GObject *object, guint prop_id, } static void +finalize (GObject *object) +{ + NMSettingIP6Config *self = NM_SETTING_IP6_CONFIG (object); + NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (self); + + g_free (priv->token); + + G_OBJECT_CLASS (nm_setting_ip6_config_parent_class)->finalize (object); +} + +static void nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) { GObjectClass *object_class = G_OBJECT_CLASS (ip6_class); @@ -424,6 +503,7 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) /* virtual methods */ object_class->set_property = set_property; object_class->get_property = get_property; + object_class->finalize = finalize; setting_class->verify = verify; /* Properties */ @@ -556,6 +636,17 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) * ---end--- */ + /* ---ifcfg-rh--- + * property: dns-priority + * variable: IPV6_DNS_PRIORITY(+) + * description: The priority for DNS servers of this connection. Lower values have higher priority. + * If zero, the default value will be used (50 for VPNs, 100 for other connections). + * A negative value prevents DNS from other connections with greater values to be used. + * default: 0 + * example: IPV6_DNS_PRIORITY=20 + * ---end--- + */ + /** * NMSettingIP6Config:ip6-privacy: * @@ -645,6 +736,30 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class) G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + /** + * NMSettingIP6Config:token: + * + * Configure the token for draft-chown-6man-tokenised-ipv6-identifiers-02 + * IPv6 tokenized interface identifiers. Useful with eui64 addr-gen-mode. + * + * Since: 1.2.4 + **/ + /* ---ifcfg-rh--- + * property: token + * variable: IPV6_TOKEN + * description: The IPv6 tokenized interface identifier token + * example: IPV6_TOKEN=::53 + * ---end--- + */ + g_object_class_install_property + (object_class, PROP_TOKEN, + g_param_spec_string (NM_SETTING_IP6_CONFIG_TOKEN, "", "", + NULL, + G_PARAM_READWRITE | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /* IP6-specific property overrides */ /* ---dbus--- diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h index 2966e558cb..f5623b4ae0 100644 --- a/libnm-core/nm-setting-ip6-config.h +++ b/libnm-core/nm-setting-ip6-config.h @@ -43,6 +43,8 @@ G_BEGIN_DECLS #define NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE "addr-gen-mode" +#define NM_SETTING_IP6_CONFIG_TOKEN "token" + /** * NM_SETTING_IP6_CONFIG_METHOD_IGNORE: * @@ -156,6 +158,8 @@ NMSetting *nm_setting_ip6_config_new (void); NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting); NM_AVAILABLE_IN_1_2 NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting); +NM_AVAILABLE_IN_1_2_4 +const char *nm_setting_ip6_config_get_token (NMSettingIP6Config *setting); G_END_DECLS diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c index 9671f1d915..8d570c9e1c 100644 --- a/libnm-core/nm-setting-team-port.c +++ b/libnm-core/nm-setting-team-port.c @@ -85,6 +85,18 @@ nm_setting_team_port_get_config (NMSettingTeamPort *setting) static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { + NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting); + + if (priv->config) { + if (!_nm_utils_check_valid_json (priv->config, error)) { + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_TEAM_PORT_SETTING_NAME, + NM_SETTING_TEAM_PORT_CONFIG); + return FALSE; + } + } + if (connection) { NMSettingConnection *s_con; const char *slave_type; @@ -116,6 +128,31 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) return TRUE; } +static gboolean +compare_property (NMSetting *setting, + NMSetting *other, + const GParamSpec *prop_spec, + NMSettingCompareFlags flags) +{ + NMSettingClass *parent_class; + + /* If we are trying to match a connection in order to assume it (and thus + * @flags contains INFERRABLE), use the "relaxed" matching for team + * configuration. Otherwise, for all other purposes (including connection + * comparison before an update), resort to the default string comparison. + */ + if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) + && nm_streq0 (prop_spec->name, NM_SETTING_TEAM_PORT_CONFIG)) { + return _nm_utils_team_config_equal (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config, + NM_SETTING_TEAM_PORT_GET_PRIVATE (other)->config, + TRUE); + } + + /* Otherwise chain up to parent to handle generic compare */ + parent_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class); + return parent_class->compare_property (setting, other, prop_spec, flags); +} + static void nm_setting_team_port_init (NMSettingTeamPort *setting) { @@ -173,10 +210,11 @@ nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class) g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate)); /* virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->compare_property = compare_property; + parent_class->verify = verify; /* Properties */ /** diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c index d47b1e72ca..36cd312b6e 100644 --- a/libnm-core/nm-setting-team.c +++ b/libnm-core/nm-setting-team.c @@ -27,6 +27,7 @@ #include "nm-utils.h" #include "nm-utils-private.h" #include "nm-connection-private.h" +#include "nm-utils-private.h" /** * SECTION:nm-setting-team @@ -82,7 +83,47 @@ nm_setting_team_get_config (NMSettingTeam *setting) static gboolean verify (NMSetting *setting, NMConnection *connection, GError **error) { - return _nm_connection_verify_required_interface_name (connection, error); + NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (setting); + + if (!_nm_connection_verify_required_interface_name (connection, error)) + return FALSE; + + if (priv->config) { + if (!_nm_utils_check_valid_json (priv->config, error)) { + g_prefix_error (error, + "%s.%s: ", + NM_SETTING_TEAM_SETTING_NAME, + NM_SETTING_TEAM_CONFIG); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +compare_property (NMSetting *setting, + NMSetting *other, + const GParamSpec *prop_spec, + NMSettingCompareFlags flags) +{ + NMSettingClass *parent_class; + + /* If we are trying to match a connection in order to assume it (and thus + * @flags contains INFERRABLE), use the "relaxed" matching for team + * configuration. Otherwise, for all other purposes (including connection + * comparison before an update), resort to the default string comparison. + */ + if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE) + && nm_streq0 (prop_spec->name, NM_SETTING_TEAM_CONFIG)) { + return _nm_utils_team_config_equal (NM_SETTING_TEAM_GET_PRIVATE (setting)->config, + NM_SETTING_TEAM_GET_PRIVATE (other)->config, + FALSE); + } + + /* Otherwise chain up to parent to handle generic compare */ + parent_class = NM_SETTING_CLASS (nm_setting_team_parent_class); + return parent_class->compare_property (setting, other, prop_spec, flags); } static void @@ -142,10 +183,11 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class) g_type_class_add_private (setting_class, sizeof (NMSettingTeamPrivate)); /* virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - parent_class->verify = verify; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->compare_property = compare_property; + parent_class->verify = verify; /* Properties */ /** diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h index 68aaaa1c80..611c467d06 100644 --- a/libnm-core/nm-utils-private.h +++ b/libnm-core/nm-utils-private.h @@ -31,6 +31,9 @@ gboolean _nm_utils_string_slist_validate (GSList *list, const char **valid_values); +gboolean _nm_utils_check_valid_json (const char *json, GError **error); +gboolean _nm_utils_team_config_equal (const char *conf1, const char *conf2, gboolean port); + /* D-Bus transform funcs */ GVariant * _nm_utils_hwaddr_to_dbus (const GValue *prop_value); diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 1080d9ea20..7a87dc18c4 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -33,6 +33,10 @@ #include <gmodule.h> #include <sys/stat.h> +#if WITH_JANSSON +#include <jansson.h> +#endif + #include "nm-utils-private.h" #include "nm-setting-private.h" #include "crypto.h" @@ -3562,6 +3566,40 @@ nm_utils_ipaddr_valid (int family, const char *ip) } /** + * nm_utils_iinet6_is_token: + * @in6addr: the AF_INET6 address structure + * + * Checks if only the bottom 64bits of the address are set. + * + * Return value: %TRUE or %FALSE + */ +gboolean +_nm_utils_inet6_is_token (const struct in6_addr *in6addr) +{ + if ( in6addr->s6_addr[0] + || in6addr->s6_addr[1] + || in6addr->s6_addr[2] + || in6addr->s6_addr[3] + || in6addr->s6_addr[4] + || in6addr->s6_addr[5] + || in6addr->s6_addr[6] + || in6addr->s6_addr[7]) + return FALSE; + + if ( in6addr->s6_addr[8] + || in6addr->s6_addr[9] + || in6addr->s6_addr[10] + || in6addr->s6_addr[11] + || in6addr->s6_addr[12] + || in6addr->s6_addr[13] + || in6addr->s6_addr[14] + || in6addr->s6_addr[15]) + return TRUE; + + return FALSE; +} + +/** * nm_utils_check_virtual_device_compatibility: * @virtual_type: a virtual connection type * @other_type: a connection type to test against @virtual_type @@ -4090,3 +4128,140 @@ const char **nm_utils_enum_get_values (GType type, gint from, gint to) return (const char **) g_ptr_array_free (array, FALSE); } +#if WITH_JANSSON +gboolean +_nm_utils_check_valid_json (const char *str, GError **error) +{ + json_t *json; + json_error_t jerror; + + g_return_val_if_fail (!error || !*error, FALSE); + + if (!str || !str[0]) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "value is NULL or empty"); + return FALSE; + } + + json = json_loads (str, 0, &jerror); + if (!json) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "%s at position %d", + jerror.text, + jerror.position); + return FALSE; + } + + json_decref (json); + return TRUE; +} + +/* json_object_foreach_safe() is only available since Jansson 2.8, + * reimplement it */ +#define _json_object_foreach_safe(object, n, key, value) \ + for (key = json_object_iter_key (json_object_iter (object)), \ + n = json_object_iter_next (object, json_object_iter_at (object, key)); \ + key && (value = json_object_iter_value (json_object_iter_at (object, key))); \ + key = json_object_iter_key (n), \ + n = json_object_iter_next (object, json_object_iter_at (object, key))) + +gboolean +_nm_utils_team_config_equal (const char *conf1, + const char *conf2, + gboolean port_config) +{ + json_t *json1 = NULL, *json2 = NULL, *json; + gs_free char *dump1 = NULL, *dump2 = NULL; + json_t *value, *property; + json_error_t jerror; + const char *key; + gboolean ret; + void *tmp; + int i; + + if (nm_streq0 (conf1, conf2)) + return TRUE; + + /* A NULL configuration is equivalent to default value '{}' */ + json1 = json_loads (conf1 ?: "{}", 0, &jerror); + if (json1) + json2 = json_loads (conf2 ?: "{}", 0, &jerror); + + if (!json1 || !json2) { + ret = FALSE; + goto out; + } + + /* Some properties are added by teamd when missing from the initial + * configuration. Add them with the default value if necessary, depending + * on the configuration type. + */ + for (i = 0, json = json1; i < 2; i++, json = json2) { + if (port_config) { + property = json_object_get (json, "link_watch"); + if (!property) { + property = json_object (); + json_object_set_new (property, "name", json_string ("ethtool")); + json_object_set_new (json, "link_watch", property); + } + } else { + property = json_object_get (json, "runner"); + if (!property) { + property = json_object (); + json_object_set_new (property, "name", json_string ("roundrobin")); + json_object_set_new (json, "runner", property); + } + } + } + + /* Only consider a given subset of nodes, others can change depending on + * current state */ + for (i = 0, json = json1; i < 2; i++, json = json2) { + _json_object_foreach_safe (json, tmp, key, value) { + if (!NM_IN_STRSET (key, "runner", "link_watch")) + json_object_del (json, key); + } + } + + dump1 = json_dumps (json1, JSON_INDENT(0) | JSON_ENSURE_ASCII | JSON_SORT_KEYS); + dump2 = json_dumps (json2, JSON_INDENT(0) | JSON_ENSURE_ASCII | JSON_SORT_KEYS); + + ret = nm_streq0 (dump1, dump2); +out: + + if (json1) + json_decref (json1); + if (json2) + json_decref (json2); + + return ret; +} + +#else /* WITH_JANSSON */ + +gboolean +_nm_utils_check_valid_json (const char *str, GError **error) +{ + if (!str || !str[0]) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + "value is NULL or empty"); + return FALSE; + } + + return TRUE; +} + +gboolean +_nm_utils_team_config_equal (const char *conf1, + const char *conf2, + gboolean port_config) +{ + return nm_streq0 (conf1, conf2); +} +#endif diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h index d7f112bf93..95131f9e87 100644 --- a/libnm-core/nm-version.h +++ b/libnm-core/nm-version.h @@ -90,18 +90,10 @@ # define NM_AVAILABLE_IN_1_2 #endif -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_4 -# define NM_DEPRECATED_IN_1_4 G_DEPRECATED -# define NM_DEPRECATED_IN_1_4_FOR(f) G_DEPRECATED_FOR(f) +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2_4 +# define NM_AVAILABLE_IN_1_2_4 G_UNAVAILABLE(1,4) #else -# define NM_DEPRECATED_IN_1_4 -# define NM_DEPRECATED_IN_1_4_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_4 -# define NM_AVAILABLE_IN_1_4 G_UNAVAILABLE(1,4) -#else -# define NM_AVAILABLE_IN_1_4 +# define NM_AVAILABLE_IN_1_2_4 #endif #endif /* NM_VERSION_H */ diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c index 6c78c20983..d0539b045b 100644 --- a/libnm-core/nm-vpn-editor-plugin.c +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -25,6 +25,7 @@ #include "nm-vpn-editor-plugin.h" #include <dlfcn.h> +#include <gmodule.h> #include "nm-core-internal.h" @@ -232,7 +233,8 @@ _nm_vpn_editor_plugin_load (const char *plugin_name, * If @plugin_name is not an absolute path name, it assumes the file * is in the plugin directory of NetworkManager. In any case, the call * will do certain checks on the file before passing it to dlopen. - * A consequence for that is, that you cannot omit the ".so" suffix. + * A consequence for that is, that you cannot omit the ".so" suffix + * as you could for nm_vpn_editor_plugin_load(). * * Returns: (transfer full): a new plugin instance or %NULL on error. * @@ -255,6 +257,42 @@ nm_vpn_editor_plugin_load_from_file (const char *plugin_name, error); } +/** + * nm_vpn_editor_plugin_load: + * @plugin_name: The name of the shared library to load. + * This path will be directly passed to dlopen() without + * further checks. + * @check_service: if not-null, check that the loaded plugin advertises + * the given service. + * @error: on failure the error reason. + * + * Load the shared libary @plugin_name and create a new + * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory + * function. + * + * This is similar to nm_vpn_editor_plugin_load_from_file(), but + * it does no validation of the plugin name, instead passes it directly + * to dlopen(). If you have the full path to a plugin file, + * nm_vpn_editor_plugin_load_from_file() is preferred. + * + * Returns: (transfer full): a new plugin instance or %NULL on error. + * + * Since: 1.2.4 + */ +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load (const char *plugin_name, + const char *check_service, + GError **error) +{ + return _nm_vpn_editor_plugin_load (plugin_name, + FALSE, + check_service, + -1, + NULL, + NULL, + error); +} + /*********************************************************************/ /** diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h index 9ff23a8134..62d09cc758 100644 --- a/libnm-core/nm-vpn-editor-plugin.h +++ b/libnm-core/nm-vpn-editor-plugin.h @@ -147,6 +147,11 @@ NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file (const char *plugin_name gpointer user_data, GError **error); +NM_AVAILABLE_IN_1_2_4 +NMVpnEditorPlugin *nm_vpn_editor_plugin_load (const char *plugin_name, + const char *check_service, + GError **error); + G_END_DECLS #endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ diff --git a/libnm-core/nm-vpn-plugin-info.c b/libnm-core/nm-vpn-plugin-info.c index 2e6275e341..3e63f1bd29 100644 --- a/libnm-core/nm-vpn-plugin-info.c +++ b/libnm-core/nm-vpn-plugin-info.c @@ -45,6 +45,7 @@ typedef struct { char *filename; char *name; char *service; + char *auth_dialog; char **aliases; GKeyFile *keyfile; @@ -188,6 +189,23 @@ _sort_files (LoadDirInfo *a, LoadDirInfo *b) nm_vpn_plugin_info_get_filename (b->plugin_info)); } +#define DEFINE_DEFAULT_DIR_LIST(dir) \ + const char *dir[] = { \ + /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with + * preference to the former. + * + * load user directory with highest priority. */ \ + _nm_vpn_plugin_info_get_default_dir_user (), \ + \ + /* lib directory has higher priority then etc. The reason is that + * etc is deprecated and used by old plugins. We expect newer plugins + * to install their file in lib, where they have higher priority. + * + * Optimally, there are no duplicates anyway, so it doesn't really matter. */ \ + _nm_vpn_plugin_info_get_default_dir_lib (), \ + _nm_vpn_plugin_info_get_default_dir_etc (), \ + } + /** * _nm_vpn_plugin_info_get_default_dir_etc: * @@ -253,7 +271,10 @@ _nm_vpn_plugin_info_list_load_dir (const char *dirname, GSList *res = NULL; guint i; - g_return_val_if_fail (dirname && dirname[0], NULL); + g_return_val_if_fail (dirname, NULL); + + if (!dirname[0]) + return NULL; dir = g_dir_open (dirname, 0, NULL); if (!dir) @@ -312,21 +333,7 @@ nm_vpn_plugin_info_list_load () gint64 uid; GSList *list = NULL; GSList *infos, *info; - const char *dir[] = { - /* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with - * preference to the former. - * - * load user directory with highest priority. */ - _nm_vpn_plugin_info_get_default_dir_user (), - - /* lib directory has higher priority then etc. The reason is that - * etc is deprecated and used by old plugins. We expect newer plugins - * to install their file in lib, where they have higher priority. - * - * Optimally, there are no duplicates anyway, so it doesn't really matter. */ - _nm_vpn_plugin_info_get_default_dir_lib (), - _nm_vpn_plugin_info_get_default_dir_etc (), - }; + DEFINE_DEFAULT_DIR_LIST (dir); uid = getuid (); @@ -345,6 +352,66 @@ nm_vpn_plugin_info_list_load () return list; } +/** + * nm_vpn_plugin_info_new_search_file: + * @name: (allow-none): the name to search for. Either @name or @service + * must be present. + * @service: (allow-none): the service to search for. Either @name or + * @service must be present. + * + * This has the same effect as doing a full nm_vpn_plugin_info_list_load() + * followed by a search for the first matching VPN plugin info that has the + * given @name and/or @service. + * + * Returns: (transfer full): a newly created instance of plugin info + * or %NULL if no matching value was found. + * + * Since: 1.2.4 + */ +NMVpnPluginInfo * +nm_vpn_plugin_info_new_search_file (const char *name, const char *service) +{ + int i; + gint64 uid; + NMVpnPluginInfo *plugin_info = NULL; + GSList *infos, *info; + DEFINE_DEFAULT_DIR_LIST (dir); + + if (!name && !service) + g_return_val_if_reached (NULL); + + uid = getuid (); + + for (i = 0; !plugin_info && i < G_N_ELEMENTS (dir); i++) { + if ( !dir[i] + || _nm_utils_strv_find_first ((char **) dir, i, dir[i]) >= 0) + continue; + + /* We still must load the entire directory while searching for the matching + * plugin-info. The reason is that reading the directory has no stable + * order and we can only sort them after reading the entire directory -- + * which _nm_vpn_plugin_info_list_load_dir() does. */ + infos = _nm_vpn_plugin_info_list_load_dir (dir[i], TRUE, uid, NULL, NULL); + + for (info = infos; info; info = info->next) { + NMVpnPluginInfo *p = info->data; + + if (name && !nm_streq (nm_vpn_plugin_info_get_name (p), name)) + continue; + if ( service + && !nm_streq (nm_vpn_plugin_info_get_service (p), service) + && (_nm_utils_strv_find_first (NM_VPN_PLUGIN_INFO_GET_PRIVATE (p)->aliases, + -1, service) < 0)) + continue; + plugin_info = g_object_ref (p); + break; + } + + g_slist_free_full (infos, g_object_unref); + } + return plugin_info; +} + /*********************************************************************/ static gboolean @@ -525,7 +592,7 @@ nm_vpn_plugin_info_list_find_by_service (GSList *list, const char *service) /* First, consider the primary service name. */ for (iter = list; iter; iter = iter->next) { - if (strcmp (NM_VPN_PLUGIN_INFO_GET_PRIVATE (iter->data)->service, service) == 0) + if (strcmp (nm_vpn_plugin_info_get_service (iter->data), service) == 0) return iter->data; } @@ -576,6 +643,77 @@ nm_vpn_plugin_info_get_name (NMVpnPluginInfo *self) } /** + * nm_vpn_plugin_info_get_service: + * @self: plugin info instance + * + * Returns: (transfer none): the service. Cannot be %NULL. + * + * Since: 1.2.4 + */ +const char * +nm_vpn_plugin_info_get_service (NMVpnPluginInfo *self) +{ + g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL); + + return NM_VPN_PLUGIN_INFO_GET_PRIVATE (self)->service; +} + +/** + * nm_vpn_plugin_info_get_auth_dialog: + * @self: plugin info instance + * + * Returns: the absolute path to the auth-dialog helper or %NULL. + * + * Since: 1.2.4 + **/ +const char * +nm_vpn_plugin_info_get_auth_dialog (NMVpnPluginInfo *self) +{ + NMVpnPluginInfoPrivate *priv; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), NULL); + + priv = NM_VPN_PLUGIN_INFO_GET_PRIVATE (self); + + if (G_UNLIKELY (priv->auth_dialog == NULL)) { + const char *s; + + s = g_hash_table_lookup (priv->keys, _nm_utils_strstrdictkey_static (NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "auth-dialog")); + if (!s || !s[0]) + priv->auth_dialog = g_strdup (""); + else if (g_path_is_absolute (s)) + priv->auth_dialog = g_strdup (s); + else { + /* for relative paths, we take the basename and assume it's in LIBEXECDIR. */ + gs_free char *prog_basename = g_path_get_basename (s); + + priv->auth_dialog = g_build_filename (LIBEXECDIR, prog_basename, NULL); + } + } + + return priv->auth_dialog[0] ? priv->auth_dialog : NULL; +} + +/** + * nm_vpn_plugin_info_supports_hints: + * @self: plugin info instance + * + * Returns: %TRUE if the supports hints for secret requests, otherwise %FALSE + * + * Since: 1.2.4 + */ +gboolean +nm_vpn_plugin_info_supports_hints (NMVpnPluginInfo *self) +{ + const char *s; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN_INFO (self), FALSE); + + s = nm_vpn_plugin_info_lookup_property (self, NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "supports-hints"); + return _nm_utils_ascii_str_to_bool (s, FALSE); +} + +/** * nm_vpn_plugin_info_get_plugin: * @self: plugin info instance * @@ -753,7 +891,7 @@ nm_vpn_plugin_info_load_editor_plugin (NMVpnPluginInfo *self, GError **error) priv->editor_plugin_loaded = TRUE; priv->editor_plugin = nm_vpn_editor_plugin_load_from_file (plugin_filename, - priv->service, + nm_vpn_plugin_info_get_service (self), getuid (), NULL, NULL, @@ -947,6 +1085,7 @@ finalize (GObject *object) g_free (priv->name); g_free (priv->service); + g_free (priv->auth_dialog); g_strfreev (priv->aliases); g_free (priv->filename); g_hash_table_unref (priv->keys); diff --git a/libnm-core/nm-vpn-plugin-info.h b/libnm-core/nm-vpn-plugin-info.h index c7fef8574a..fce07e6d1b 100644 --- a/libnm-core/nm-vpn-plugin-info.h +++ b/libnm-core/nm-vpn-plugin-info.h @@ -73,14 +73,24 @@ NMVpnPluginInfo *nm_vpn_plugin_info_new_with_data (const char *filename, GKeyFile *keyfile, GError **error); +NM_AVAILABLE_IN_1_2_4 +NMVpnPluginInfo *nm_vpn_plugin_info_new_search_file (const char *name, + const char *service); + NM_AVAILABLE_IN_1_2 const char *nm_vpn_plugin_info_get_name (NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_2 const char *nm_vpn_plugin_info_get_filename (NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2_4 +const char *nm_vpn_plugin_info_get_service (NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_2 const char *nm_vpn_plugin_info_get_plugin (NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_2 const char *nm_vpn_plugin_info_get_program (NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2_4 +const char *nm_vpn_plugin_info_get_auth_dialog (NMVpnPluginInfo *self); +NM_AVAILABLE_IN_1_2_4 +gboolean nm_vpn_plugin_info_supports_hints (NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_2 gboolean nm_vpn_plugin_info_supports_multiple (NMVpnPluginInfo *self); NM_AVAILABLE_IN_1_2 diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index dcbcb88021..c80f55893f 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -1968,6 +1968,7 @@ test_connection_diff_a_only (void) { NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_IP_CONFIG_DAD_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_DNS_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A }, { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }, } }, }; @@ -3717,6 +3718,57 @@ test_connection_normalize_infiniband_mtu (void) } static void +test_connection_normalize_gateway_never_default (void) +{ + gs_unref_object NMConnection *con = NULL; + NMSettingIPConfig *s_ip4, *s_ip6; + NMIPAddress *addr; + gs_free_error GError *error = NULL; + + con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nmtst_assert_connection_verifies_and_normalizable (con); + + s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); + g_object_set (G_OBJECT (s_ip4), + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + 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); + nm_ip_address_unref (addr); + + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.254", + NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE, + NULL); + + s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new (); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); + + nm_connection_add_setting (con, (NMSetting *) s_ip4); + nm_connection_add_setting (con, (NMSetting *) s_ip6); + + nmtst_assert_connection_verifies_without_normalization (con); + g_assert_cmpstr ("1.1.1.254", ==, nm_setting_ip_config_get_gateway (s_ip4)); + + /* Now set never-default to TRUE and check that the gateway is + * removed during normalization + * */ + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_NEVER_DEFAULT, TRUE, + NULL); + + nmtst_assert_connection_verifies_after_normalization (con, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY); + nmtst_connection_normalize (con); + g_assert_cmpstr (NULL, ==, nm_setting_ip_config_get_gateway (s_ip4)); +} + +static void test_setting_ip4_gateway (void) { NMConnection *conn; @@ -4382,6 +4434,110 @@ test_nm_utils_dns_option_find_idx (void) /******************************************************************************/ +static void +_json_config_check_valid (const char *conf, gboolean expected) +{ + GError *error = NULL; + gboolean res; + + res = _nm_utils_check_valid_json (conf, &error); + g_assert_cmpint (res, ==, expected); + g_assert (res || error); +} + +static void +test_nm_utils_check_valid_json (void) +{ + _json_config_check_valid (NULL, FALSE); + _json_config_check_valid ("", FALSE); +#if WITH_JANSSON + _json_config_check_valid ("{ }", TRUE); + _json_config_check_valid ("{ \"a\" : 1 }", TRUE); + _json_config_check_valid ("{ \"a\" : }", FALSE); +#else + /* Without JSON library everything except empty string is considered valid */ + _json_config_check_valid ("{ }", TRUE); + _json_config_check_valid ("{'%!-a1", TRUE); +#endif +} + +static void +_team_config_equal_check (const char *conf1, + const char *conf2, + gboolean port_config, + gboolean expected) +{ + g_assert_cmpint (_nm_utils_team_config_equal (conf1, conf2, port_config), ==, expected); +} + +static void +test_nm_utils_team_config_equal (void) +{ +#if WITH_JANSSON + _team_config_equal_check ("", "", TRUE, TRUE); + _team_config_equal_check ("{}", + "{ }", + TRUE, + TRUE); + _team_config_equal_check ("{}", + "{", + TRUE, + FALSE); + + /* team config */ + _team_config_equal_check ("{ }", + "{ \"runner\" : { \"name\" : \"roundrobin\"} }", + FALSE, + TRUE); + _team_config_equal_check ("{ }", + "{ \"runner\" : { \"name\" : \"random\"} }", + FALSE, + FALSE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }", + "{ \"runner\" : { \"name\" : \"random\"} }", + FALSE, + FALSE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"} }", + "{ \"runner\" : { \"name\" : \"random\"} }", + FALSE, + TRUE); + _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }", + "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }", + FALSE, + TRUE); + + /* team port config */ + _team_config_equal_check ("{ }", + "{ \"link_watch\" : { \"name\" : \"ethtool\"} }", + TRUE, + TRUE); + _team_config_equal_check ("{ }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + FALSE); + _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + FALSE); + _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }", + TRUE, + TRUE); + _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth0\" : {} } }", + "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }", + TRUE, + TRUE); +#else + /* Without JSON library, strings are compared for equality */ + _team_config_equal_check ("", "", TRUE, TRUE); + _team_config_equal_check ("", " ", TRUE, FALSE); + _team_config_equal_check ("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, TRUE); + _team_config_equal_check ("{ \"a\": 1 }", "{ \"a\": 1 }", TRUE, FALSE); +#endif +} + +/******************************************************************************/ + enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED { _DUMMY_1 = -1, }; @@ -5010,6 +5166,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_connection_normalize_slave_type_1", test_connection_normalize_slave_type_1); g_test_add_func ("/core/general/test_connection_normalize_slave_type_2", test_connection_normalize_slave_type_2); g_test_add_func ("/core/general/test_connection_normalize_infiniband_mtu", test_connection_normalize_infiniband_mtu); + g_test_add_func ("/core/general/test_connection_normalize_gateway_never_default", test_connection_normalize_gateway_never_default); g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers); g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property); @@ -5066,7 +5223,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate); g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx); - + g_test_add_func ("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json); + g_test_add_func ("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal); g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum); return g_test_run (); diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c index 2af9deb4bd..0534b766e8 100644 --- a/libnm-glib/nm-vpn-plugin.c +++ b/libnm-glib/nm-vpn-plugin.c @@ -800,7 +800,7 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_DBUS_SERVICE_NAME: /* Construct-only */ - priv->dbus_service_name = g_strdup (g_value_get_string (value)); + priv->dbus_service_name = g_value_dup_string (value); break; case PROP_STATE: nm_vpn_plugin_set_state (NM_VPN_PLUGIN (object), diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 990d6fe73b..c0d82b4263 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -1403,7 +1403,7 @@ _nm_setting_verify_deprecated_virtual_iface_name (const char *interface_name, e_invalid_property, _("property is invalid")); g_prefix_error (error, "%s.%s: ", setting_name, setting_property); - /* we would like to make this a NORMALIZEABLE_ERROR, but that might + /* we would like to make this a NORMALIZABLE_ERROR, but that might * break older connections. */ return NM_SETTING_VERIFY_NORMALIZABLE; } diff --git a/libnm-util/nm-version.h b/libnm-util/nm-version.h index 760151a68f..29f848930d 100644 --- a/libnm-util/nm-version.h +++ b/libnm-util/nm-version.h @@ -90,18 +90,10 @@ # define NM_AVAILABLE_IN_1_2 #endif -#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_4 -# define NM_DEPRECATED_IN_1_4 G_DEPRECATED -# define NM_DEPRECATED_IN_1_4_FOR(f) G_DEPRECATED_FOR(f) +#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_2_4 +# define NM_AVAILABLE_IN_1_2_4 G_UNAVAILABLE(1,2,4) #else -# define NM_DEPRECATED_IN_1_4 -# define NM_DEPRECATED_IN_1_4_FOR(f) -#endif - -#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_4 -# define NM_AVAILABLE_IN_1_4 G_UNAVAILABLE(1,4) -#else -# define NM_AVAILABLE_IN_1_4 +# define NM_AVAILABLE_IN_1_2_4 #endif #endif /* NM_VERSION_H */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 7ece1b2fef..4362cd25c0 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1058,3 +1058,15 @@ global: nm_vpn_service_plugin_set_ip6_config; nm_vpn_service_plugin_set_login_banner; } libnm_1_0_0; + +libnm_1_2_4 { +global: + nm_device_team_get_config; + nm_setting_ip6_config_get_token; + nm_setting_ip_config_get_dns_priority; + nm_vpn_editor_plugin_load; + nm_vpn_plugin_info_get_auth_dialog; + nm_vpn_plugin_info_get_service; + nm_vpn_plugin_info_new_search_file; + nm_vpn_plugin_info_supports_hints; +} libnm_1_2_0; diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c index b855d5ec38..7fa24f23f9 100644 --- a/libnm/nm-device-team.c +++ b/libnm/nm-device-team.c @@ -39,6 +39,7 @@ typedef struct { char *hw_address; gboolean carrier; GPtrArray *slaves; + char *config; } NMDeviceTeamPrivate; enum { @@ -46,6 +47,7 @@ enum { PROP_HW_ADDRESS, PROP_CARRIER, PROP_SLAVES, + PROP_CONFIG, LAST_PROP }; @@ -101,6 +103,25 @@ nm_device_team_get_slaves (NMDeviceTeam *device) return NM_DEVICE_TEAM_GET_PRIVATE (device)->slaves; } +/** + * nm_device_team_get_config: + * @device: a #NMDeviceTeam + * + * Gets the current JSON configuration of the #NMDeviceTeam + * + * Returns: the current configuration. This is the internal string used by the + * device, and must not be modified. + * + * Since: 1.2.4 + **/ +const char * +nm_device_team_get_config (NMDeviceTeam *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), NULL); + + return NM_DEVICE_TEAM_GET_PRIVATE (device)->config; +} + static const char * get_hw_address (NMDevice *device) { @@ -150,6 +171,7 @@ init_dbus (NMObject *object) { NM_DEVICE_TEAM_HW_ADDRESS, &priv->hw_address }, { NM_DEVICE_TEAM_CARRIER, &priv->carrier }, { NM_DEVICE_TEAM_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, + { NM_DEVICE_TEAM_CONFIG, &priv->config }, { NULL }, }; @@ -176,6 +198,7 @@ finalize (GObject *object) NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); g_free (priv->hw_address); + g_free (priv->config); G_OBJECT_CLASS (nm_device_team_parent_class)->finalize (object); } @@ -198,6 +221,9 @@ get_property (GObject *object, case PROP_SLAVES: g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_team_get_slaves (device))); break; + case PROP_CONFIG: + g_value_set_string (value, nm_device_team_get_config (device)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -265,4 +291,18 @@ nm_device_team_class_init (NMDeviceTeamClass *team_class) G_TYPE_PTR_ARRAY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceTeam:config: + * + * The current JSON configuration of the device. + * + * Since: 1.2.4 + **/ + g_object_class_install_property + (object_class, PROP_CONFIG, + g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm/nm-device-team.h b/libnm/nm-device-team.h index a9b71c6ab0..93cc14e51d 100644 --- a/libnm/nm-device-team.h +++ b/libnm/nm-device-team.h @@ -39,6 +39,7 @@ G_BEGIN_DECLS #define NM_DEVICE_TEAM_HW_ADDRESS "hw-address" #define NM_DEVICE_TEAM_CARRIER "carrier" #define NM_DEVICE_TEAM_SLAVES "slaves" +#define NM_DEVICE_TEAM_CONFIG "config" /** * NMDeviceTeam: @@ -59,6 +60,8 @@ GType nm_device_team_get_type (void); const char *nm_device_team_get_hw_address (NMDeviceTeam *device); gboolean nm_device_team_get_carrier (NMDeviceTeam *device); const GPtrArray *nm_device_team_get_slaves (NMDeviceTeam *device); +NM_AVAILABLE_IN_1_2_4 +const char *nm_device_team_get_config (NMDeviceTeam *device); G_END_DECLS diff --git a/libnm/nm-vpn-editor.h b/libnm/nm-vpn-editor.h index a11e9fd16d..2ee34525d8 100644 --- a/libnm/nm-vpn-editor.h +++ b/libnm/nm-vpn-editor.h @@ -30,7 +30,7 @@ #include <glib-object.h> #include <nm-types.h> -#include "nm-vpn-editor-plugin.h" +#include <nm-vpn-editor-plugin.h> G_BEGIN_DECLS diff --git a/m4/compiler_warnings.m4 b/m4/compiler_options.m4 index 77dcc7a50d..3d2e4dbefc 100644 --- a/m4/compiler_warnings.m4 +++ b/m4/compiler_options.m4 @@ -1,17 +1,17 @@ -dnl Check whether a particular compiler flag works with code provided, -dnl disable it in CFLAGS if the check fails. -AC_DEFUN([NM_COMPILER_WARNING], [ +AC_DEFUN([_NM_COMPILER_FLAG], [ CFLAGS_SAVED="$CFLAGS" - CFLAGS="$CFLAGS -Werror -W$1" - AC_MSG_CHECKING(whether -W$1 works) + CFLAGS="$CFLAGS $GLIB_CFLAGS -Werror $1" + AC_MSG_CHECKING([whether $1 works as expected]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[]])], [ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[$2]])], [ AC_MSG_RESULT(yes) - CFLAGS="$CFLAGS_SAVED -W$1" + CFLAGS="$CFLAGS_SAVED" + $3 ],[ AC_MSG_RESULT(no) - CFLAGS="$CFLAGS_SAVED -Wno-$1" + CFLAGS="$CFLAGS_SAVED" + $4 ]) ],[ AC_MSG_RESULT(not supported) @@ -19,6 +19,21 @@ AC_DEFUN([NM_COMPILER_WARNING], [ ]) ]) +dnl Check whether a particular compiler flag is supported, +dnl add it to CFLAGS if it is +AC_DEFUN([NM_COMPILER_FLAG], [ + _NM_COMPILER_FLAG([$1], [], [ + CFLAGS="$CFLAGS $1" + $2 + ], [$3]) +]) + +dnl Check whether a particular warning is not emitted with code provided, +dnl disable it in CFLAGS if the check fails. +AC_DEFUN([NM_COMPILER_WARNING], [ + _NM_COMPILER_FLAG([-W$1], [$2], [CFLAGS="$CFLAGS -W$1"], [CFLAGS="$CFLAGS -Wno-$1"]) +]) + AC_DEFUN([NM_COMPILER_WARNINGS], [AC_ARG_ENABLE(more-warnings, AS_HELP_STRING([--enable-more-warnings], [Possible values: no/yes/error]), @@ -40,7 +55,6 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then dnl attach it to the CFLAGS. NM_COMPILER_WARNING([unknown-warning-option], []) - CFLAGS_SAVED="$CFLAGS" CFLAGS_MORE_WARNINGS="-Wall -std=gnu89" if test "x$set_more_warnings" = xerror; then @@ -57,22 +71,11 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then -Wpointer-arith -Winit-self \ -Wmissing-include-dirs -Wno-pragmas; do dnl GCC 4.4 does not warn when checking for -Wno-* flags (https://gcc.gnu.org/wiki/FAQ#wnowarning) - CFLAGS="-Werror $CFLAGS_MORE_WARNINGS $(printf '%s' "$option" | sed 's/^-Wno-/-W/') $CFLAGS_SAVED" - AC_MSG_CHECKING([whether compiler understands $option]) - AC_TRY_COMPILE([], [], - has_option=yes, - has_option=no,) - if test $has_option != no; then - CFLAGS_MORE_WARNINGS="$CFLAGS_MORE_WARNINGS $option" - fi - AC_MSG_RESULT($has_option) - unset has_option + _NM_COMPILER_FLAG([$(printf '%s' "$option" | sed 's/^-Wno-/-W/')], [], + [CFLAGS_MORE_WARNINGS="$CFLAGS_MORE_WARNINGS $option"], []) done unset option - CFLAGS="$CFLAGS_SAVED" - unset CFLAGS_SAVED - dnl Disable warnings triggered by known compiler problems dnl https://bugzilla.gnome.org/show_bug.cgi?id=745821 diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index 9b53ce993e..fd6d7cef59 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -303,7 +303,8 @@ no-auto-default=* configuration with DNSSEC support. The /etc/resolv.conf will be managed by dnssec-trigger daemon.</para> <para><literal>none</literal>: NetworkManager will not - modify resolv.conf.</para> + modify resolv.conf. This implies + <literal>rc-manager</literal> <literal>unmanaged</literal></para> </listitem> </varlistentry> @@ -311,17 +312,28 @@ no-auto-default=* <term><varname>rc-manager</varname></term> <listitem><para>Set the <filename>resolv.conf</filename> management mode. The default value depends on how NetworkManager - was built. Regardless of this setting, NetworkManager will + was built, whereas this version of NetworkManager was build with + a default of "<literal>&NM_CONFIG_DEFAULT_DNS_RC_MANAGER;</literal>". + Regardless of this setting, NetworkManager will always write resolv.conf to its runtime state directory.</para> - <para><literal>none</literal>: NetworkManager will symlink + <para><literal>symlink</literal>: NetworkManager will symlink <filename>/etc/resolv.conf</filename> to its private - resolv.conf file in the runtime state directory.</para> + resolv.conf file in the runtime state directory. If + <filename>/etc/resolv.conf</filename> + already is a symlink pointing to a different location, the file + will not be modified. This allows the user to disable managing + by pointing the link <filename>/etc/resolv.conf</filename> to + somewhere else.</para> <para><literal>file</literal>: NetworkManager will write <filename>/etc/resolv.conf</filename> as file.</para> <para><literal>resolvconf</literal>: NetworkManager will run resolvconf to update the DNS configuration.</para> <para><literal>netconfig</literal>: NetworkManager will run netconfig to update the DNS configuration.</para> + <para><literal>unmanaged</literal>: don't touch + <filename>/etc/resolv.conf</filename>.</para> + <para><literal>none</literal>: deprecated alias for + <literal>symlink</literal>.</para> </listitem> </varlistentry> @@ -448,7 +460,7 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth WIFI_SCAN, IP4, IP6, AUTOIP4, DNS, VPN, SHARING, SUPPLICANT, AGENTS, SETTINGS, SUSPEND, CORE, DEVICE, OLPC, WIMAX, INFINIBAND, FIREWALL, ADSL, BOND, VLAN, BRIDGE, DBUS_PROPS, - TEAM, CONCHECK, DCB, DISPATCH, AUDIT.</para> + TEAM, CONCHECK, DCB, DISPATCH, AUDIT, SYSTEMD, VPN_PLUGIN.</para> <para>In addition, these special domains can be used: NONE, ALL, DEFAULT, DHCP, IP.</para> <para>You can specify per-domain log level overrides by @@ -494,6 +506,8 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth <member>DCB : Data Center Bridging (DCB) operations</member> <member>DISPATCH : Dispatcher scripts</member> <member>AUDIT : Audit records</member> + <member>SYSTEMD : Messages from internal libsystemd</member> + <member>VPN_PLUGIN : logging messages from VPN plugins</member> <member> </member> <member>NONE : when given by itself logging is disabled</member> <member>ALL : all log domains</member> @@ -504,6 +518,12 @@ unmanaged-devices=mac:00:22:68:1c:59:b1;mac:00:1E:65:30:D1:C4;interface-name:eth <member>HW : deprecated alias for "PLATFORM"</member> </simplelist> </para> + <para> + In general, the logfile should not contain passwords or private data. However, + you are always advised to check the file before posting it online or attaching + to a bug report. <literal>VPN_PLUGIN</literal> is special in that it might + reveal private information from the VPN plugins and thus this level is excluded + from <literal>ALL</literal></para> </varlistentry> <varlistentry> <term><varname>backend</varname></term> diff --git a/man/NetworkManager.xml b/man/NetworkManager.xml index 1088cc9c36..4624f0adaa 100644 --- a/man/NetworkManager.xml +++ b/man/NetworkManager.xml @@ -475,7 +475,7 @@ <citerefentry><refentrytitle>nm-online</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>nm-settings</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry><refentrytitle>nm-applet</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>nm-connection-editor</refentrytitle><manvolnum>1</manvolnum></citerefentry> + <citerefentry><refentrytitle>nm-connection-editor</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry> </para> </refsect1> diff --git a/man/common.ent.in b/man/common.ent.in index ae8897eb8a..ec91e8a6a2 100644 --- a/man/common.ent.in +++ b/man/common.ent.in @@ -4,3 +4,4 @@ <!ENTITY NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT "@NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@"> <!ENTITY NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT "@NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@"> <!ENTITY NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT "@NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@"> +<!ENTITY NM_CONFIG_DEFAULT_DNS_RC_MANAGER "@NM_CONFIG_DEFAULT_DNS_RC_MANAGER@"> diff --git a/po/pt_BR.po b/po/pt_BR.po index ddb94f223c..3aa989dcb7 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "Project-Id-Version: NetworkManager\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=NetworkManager&keywords=I18N+L10N&component=Translations\n" -"POT-Creation-Date: 2016-05-04 02:03+0000\n" -"PO-Revision-Date: 2016-05-04 08:14-0300\n" +"POT-Creation-Date: 2016-05-04 02:01+0000\n" +"PO-Revision-Date: 2016-05-04 08:11-0300\n" "Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n" "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n" "Language: pt_BR\n" @@ -1856,7 +1856,7 @@ msgstr "Erro: \"%s\": \"%s\" não é um endereço MAC %s válido." #. Ask for optional arguments #: ../clients/cli/connections.c:3037 ../clients/cli/connections.c:3569 -#: ../clients/tui/nm-editor-utils.c:163 ../libnm-core/nm-connection.c:1716 +#: ../clients/tui/nm-editor-utils.c:163 ../libnm-core/nm-connection.c:1729 #: ../libnm-glib/nm-device.c:1861 ../libnm/nm-device.c:1812 msgid "InfiniBand" msgstr "InfiniBand" @@ -2043,7 +2043,7 @@ msgstr "Erro: o \"bt-type\": \"%s\" não é um tipo bluetooth válido.\n" #. 13 #: ../clients/cli/connections.c:3782 ../clients/cli/devices.c:239 #: ../clients/tui/nm-editor-utils.c:217 ../clients/tui/nmt-page-vlan.c:94 -#: ../libnm-core/nm-connection.c:1714 ../libnm-glib/nm-device.c:1869 +#: ../libnm-core/nm-connection.c:1727 ../libnm-glib/nm-device.c:1869 #: ../libnm-util/nm-connection.c:1632 ../libnm/nm-device.c:1820 msgid "VLAN" msgstr "VLAN" @@ -4186,6 +4186,42 @@ msgstr "TIPO-ID-PORTA" #: ../clients/cli/devices.c:283 #, c-format +#| msgid "" +#| "Usage: nmcli device { COMMAND | help }\n" +#| "\n" +#| "COMMAND := { status | show | connect | reapply | disconnect | delete | " +#| "monitor | wifi | lldp }\n" +#| "\n" +#| " status\n" +#| "\n" +#| " show [<ifname>]\n" +#| "\n" +#| " set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n" +#| "\n" +#| " connect <ifname>\n" +#| "\n" +#| " reapply <ifname> ...\n" +#| "\n" +#| " disconnect <ifname> ...\n" +#| "\n" +#| " delete <ifname> ...\n" +#| "\n" +#| " monitor <ifname> ...\n" +#| "\n" +#| " wifi [list [ifname <ifname>] [bssid <BSSID>]]\n" +#| "\n" +#| " wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] " +#| "[ifname <ifname>]\n" +#| " [bssid <BSSID>] [name <name>] [private yes|no] " +#| "[hidden yes|no]\n" +#| "\n" +#| " wifi hotspot [ifname <ifname>] [con-name <name>] [ssid <SSID>] [band a|" +#| "bg] [channel <channel>] [password <password>]\n" +#| "\n" +#| " wifi rescan [ifname <ifname>] [[ssid <SSID to scan>] ...]\n" +#| "\n" +#| " lldp [list [ifname <ifname>]]\n" +#| "\n" msgid "" "Usage: nmcli device { COMMAND | help }\n" "\n" @@ -4335,6 +4371,15 @@ msgstr "" #: ../clients/cli/devices.c:343 #, c-format +#| msgid "" +#| "Usage: nmcli device reapply { ARGUMENTS | help }\n" +#| "\n" +#| "ARGUMENTS := <ifname> ...\n" +#| "\n" +#| "Attempts to update device with changes to the currently active " +#| "connection\n" +#| "made since it was last applied.\n" +#| "\n" msgid "" "Usage: nmcli device reapply { ARGUMENTS | help }\n" "\n" @@ -4746,6 +4791,7 @@ msgstr "Dispositivo \"%s\" removido com sucesso.\n" #: ../clients/cli/devices.c:1838 #, c-format +#| msgid "Error: Reapplying connection to device '%s' (%s) failed: %s\n" msgid "Error: Reapplying connection to device '%s' (%s) failed: %s" msgstr "Erro: a reaplicação da conexão no dispositivo \"%s\" (%s) falhou: %s" @@ -4756,11 +4802,13 @@ msgstr "Conexão reaplicada com sucesso no dispositivo \"%s\".\n" #: ../clients/cli/devices.c:1885 #, c-format +#| msgid "Error: Unexpected argument '%s'" msgid "Error: unsupported argument '%s'." msgstr "Erro: argumento \"%s\" sem suporte." #: ../clients/cli/devices.c:1899 #, c-format +#| msgid "Error: Device '%s' not found." msgid "Error: device '%s' not found." msgstr "Erro: dispositivo \"%s\" não localizado." @@ -6708,9 +6756,9 @@ msgstr "Nome de usuário" #: ../clients/common/nm-secret-agent-simple.c:492 #: ../clients/common/nm-secret-agent-simple.c:507 #: ../clients/common/nm-secret-agent-simple.c:525 +#: ../clients/common/nm-vpn-helpers.c:100 #: ../clients/common/nm-vpn-helpers.c:101 -#: ../clients/common/nm-vpn-helpers.c:102 -#: ../clients/common/nm-vpn-helpers.c:105 ../clients/tui/nmt-page-dsl.c:75 +#: ../clients/common/nm-vpn-helpers.c:104 ../clients/tui/nmt-page-dsl.c:75 #: ../clients/tui/nmt-page-wifi.c:277 ../clients/tui/nmt-page-wifi.c:308 #: ../clients/tui/nmt-page-wifi.c:341 msgid "Password" @@ -6789,25 +6837,25 @@ msgstr "Requer uma senha para conectar ao \"%s\"." msgid "VPN password required" msgstr "Senha de VPN necessária" -#: ../clients/common/nm-vpn-helpers.c:61 +#: ../clients/common/nm-vpn-helpers.c:60 msgid "could not get VPN plugin info" msgstr "não foi possível obter informação de plug-in VPN" -#: ../clients/common/nm-vpn-helpers.c:103 -#: ../clients/common/nm-vpn-helpers.c:106 +#: ../clients/common/nm-vpn-helpers.c:102 +#: ../clients/common/nm-vpn-helpers.c:105 msgid "Group password" msgstr "Senha do grupo" -#: ../clients/common/nm-vpn-helpers.c:108 ../clients/tui/nmt-page-ip4.c:143 +#: ../clients/common/nm-vpn-helpers.c:107 ../clients/tui/nmt-page-ip4.c:143 #: ../clients/tui/nmt-page-ip6.c:143 msgid "Gateway" msgstr "Gateway" -#: ../clients/common/nm-vpn-helpers.c:109 +#: ../clients/common/nm-vpn-helpers.c:108 msgid "Cookie" msgstr "Cookie" -#: ../clients/common/nm-vpn-helpers.c:110 +#: ../clients/common/nm-vpn-helpers.c:109 msgid "Gateway certificate hash" msgstr "Hash de certificado do gateway" @@ -6851,7 +6899,7 @@ msgstr "" #: ../clients/tui/newt/nmt-newt-utils.c:177 ../clients/tui/nmt-editor.c:415 #: ../clients/tui/nmt-password-dialog.c:174 #: ../clients/tui/nmt-route-editor.c:122 ../clients/tui/nmtui-hostname.c:69 -#: ../clients/tui/nmtui.c:114 +#: ../clients/tui/nmtui.c:136 msgid "OK" msgstr "OK" @@ -6915,9 +6963,9 @@ msgstr "DSL" msgid "DSL connection %d" msgstr "Conexão DSL %d" -#: ../clients/tui/nm-editor-utils.c:190 ../libnm-core/nm-connection.c:1708 +#: ../clients/tui/nm-editor-utils.c:190 ../libnm-core/nm-connection.c:1721 #: ../libnm-glib/nm-device.c:1863 ../libnm-util/nm-connection.c:1626 -#: ../libnm/nm-device.c:1814 ../src/settings/plugins/ifcfg-rh/reader.c:4182 +#: ../libnm/nm-device.c:1814 ../src/settings/plugins/ifcfg-rh/reader.c:4187 msgid "Bond" msgstr "Vínculo" @@ -6926,9 +6974,9 @@ msgstr "Vínculo" msgid "Bond connection %d" msgstr "Conexão vinculada %d" -#: ../clients/tui/nm-editor-utils.c:199 ../libnm-core/nm-connection.c:1712 +#: ../clients/tui/nm-editor-utils.c:199 ../libnm-core/nm-connection.c:1725 #: ../libnm-glib/nm-device.c:1867 ../libnm-util/nm-connection.c:1630 -#: ../libnm/nm-device.c:1818 ../src/settings/plugins/ifcfg-rh/reader.c:4479 +#: ../libnm/nm-device.c:1818 ../src/settings/plugins/ifcfg-rh/reader.c:4484 msgid "Bridge" msgstr "Ponte" @@ -6937,9 +6985,9 @@ msgstr "Ponte" msgid "Bridge connection %d" msgstr "Conexão de Ponte %d" -#: ../clients/tui/nm-editor-utils.c:208 ../libnm-core/nm-connection.c:1710 +#: ../clients/tui/nm-editor-utils.c:208 ../libnm-core/nm-connection.c:1723 #: ../libnm-glib/nm-device.c:1865 ../libnm-util/nm-connection.c:1628 -#: ../libnm/nm-device.c:1816 ../src/settings/plugins/ifcfg-rh/reader.c:4288 +#: ../libnm/nm-device.c:1816 ../src/settings/plugins/ifcfg-rh/reader.c:4293 msgid "Team" msgstr "União" @@ -7539,10 +7587,14 @@ msgid "Deactivate" msgstr "Desativar" #: ../clients/tui/nmtui-connect.c:413 ../clients/tui/nmtui-edit.c:120 -#: ../clients/tui/nmtui.c:108 +#: ../clients/tui/nmtui.c:130 msgid "Quit" msgstr "Cancelar" +#: ../clients/tui/nmtui-connect.c:413 ../clients/tui/nmtui-edit.c:120 +msgid "Back" +msgstr "Voltar" + #: ../clients/tui/nmtui-connect.c:436 #, c-format msgid "No such connection '%s'" @@ -7626,28 +7678,28 @@ msgstr "novo nome de máquina" msgid "Set system hostname" msgstr "Definir nome de máquina do sistema" -#: ../clients/tui/nmtui.c:83 +#: ../clients/tui/nmtui.c:104 msgid "NetworkManager TUI" msgstr "NetworkManager TUI" -#: ../clients/tui/nmtui.c:91 +#: ../clients/tui/nmtui.c:112 msgid "Please select an option" msgstr "Por favor selecione uma opção" -#: ../clients/tui/nmtui.c:143 +#: ../clients/tui/nmtui.c:160 msgid "Usage" msgstr "Uso" -#: ../clients/tui/nmtui.c:224 +#: ../clients/tui/nmtui.c:241 msgid "Could not parse arguments" msgstr "Não foi possível analisar argumentos" -#: ../clients/tui/nmtui.c:234 +#: ../clients/tui/nmtui.c:251 #, c-format msgid "Could not contact NetworkManager: %s.\n" msgstr "Não foi possível contatar o NetworkManager: %s.\n" -#: ../clients/tui/nmtui.c:239 +#: ../clients/tui/nmtui.c:256 msgid "NetworkManager is not running." msgstr "NetworkManager não está em execução." @@ -7949,27 +8001,27 @@ msgstr "nome de definição desconhecido" msgid "duplicate setting name" msgstr "nome de definição duplicado" -#: ../libnm-core/nm-connection.c:873 +#: ../libnm-core/nm-connection.c:886 msgid "setting not found" msgstr "definição não localizada" -#: ../libnm-core/nm-connection.c:937 +#: ../libnm-core/nm-connection.c:950 msgid "setting not allowed in slave connection" msgstr "definição não permitida para conexão escrava" -#: ../libnm-core/nm-connection.c:948 +#: ../libnm-core/nm-connection.c:961 msgid "setting is required for non-slave connections" msgstr "definição é exigida para conexões não escravas" -#: ../libnm-core/nm-connection.c:1042 +#: ../libnm-core/nm-connection.c:1055 msgid "Unexpected failure to verify the connection" msgstr "Falha inesperada ao verificar a conexão" -#: ../libnm-core/nm-connection.c:1075 +#: ../libnm-core/nm-connection.c:1088 msgid "Unexpected failure to normalize the connection" msgstr "Falha inesperada ao normalizar a conexão" -#: ../libnm-core/nm-connection.c:1576 ../libnm-core/nm-setting-8021x.c:2411 +#: ../libnm-core/nm-connection.c:1589 ../libnm-core/nm-setting-8021x.c:2411 #: ../libnm-core/nm-setting-8021x.c:2428 ../libnm-core/nm-setting-8021x.c:2459 #: ../libnm-core/nm-setting-8021x.c:2476 ../libnm-core/nm-setting-8021x.c:2518 #: ../libnm-core/nm-setting-8021x.c:2530 ../libnm-core/nm-setting-8021x.c:2548 @@ -8401,13 +8453,13 @@ msgid "'%d' is not a valid value for the property (should be <= %d)" msgstr "\"%d\" não é um valor válido para a propriedade (deveria ser <= %d)" #: ../libnm-core/nm-setting-bridge-port.c:154 -#: ../libnm-core/nm-setting-team-port.c:97 +#: ../libnm-core/nm-setting-team-port.c:109 #, c-format msgid "missing setting" msgstr "faltando definição" #: ../libnm-core/nm-setting-bridge-port.c:165 -#: ../libnm-core/nm-setting-team-port.c:108 +#: ../libnm-core/nm-setting-team-port.c:120 #, c-format msgid "" "A connection with a '%s' setting must have the slave-type set to '%s'. " @@ -8637,6 +8689,12 @@ msgstr "%d: rota é inválida" msgid "%d. route cannot be a default route" msgstr "%d. rota não pode ser uma rota padrão" +#: ../libnm-core/nm-setting-ip-config.c:2281 +#, c-format +#| msgid "'%s=%s' is incompatible with '%s > 0'" +msgid "a gateway is incompatible with '%s'" +msgstr "um gateway é incompatível com \"%s\"" + #: ../libnm-core/nm-setting-ip4-config.c:143 #: ../libnm-core/nm-setting-ip6-config.c:144 #: ../libnm-util/nm-setting-ip4-config.c:879 @@ -8920,137 +8978,138 @@ msgstr "segredo não localizado" msgid "secret is not set" msgstr "segredo não está definido" -#: ../libnm-core/nm-utils.c:2447 +#: ../libnm-core/nm-utils.c:2451 #, c-format msgid "failed stat file %s: %s" msgstr "falha ao obter estado do arquivo %s: %s" -#: ../libnm-core/nm-utils.c:2456 +#: ../libnm-core/nm-utils.c:2460 #, c-format msgid "not a file (%s)" msgstr "não é um arquivo (%s)" -#: ../libnm-core/nm-utils.c:2467 +#: ../libnm-core/nm-utils.c:2471 #, c-format msgid "invalid file owner %d for %s" msgstr "proprietário %d de arquivo inválido para %s" -#: ../libnm-core/nm-utils.c:2478 +#: ../libnm-core/nm-utils.c:2482 #, c-format msgid "file permissions for %s" msgstr "permissões de arquivo para %s" -#: ../libnm-core/nm-utils.c:2488 +#: ../libnm-core/nm-utils.c:2492 #, c-format msgid "reject %s" msgstr "rejeitar %s" -#: ../libnm-core/nm-utils.c:2508 +#: ../libnm-core/nm-utils.c:2512 #, c-format msgid "path is not absolute (%s)" msgstr "o caminho não é absoluto (%s)" -#: ../libnm-core/nm-utils.c:2522 +#: ../libnm-core/nm-utils.c:2526 #, c-format msgid "Plugin file does not exist (%s)" msgstr "O arquivo do plug-in não existe (%s)" -#: ../libnm-core/nm-utils.c:2530 +#: ../libnm-core/nm-utils.c:2534 #, c-format msgid "Plugin is not a valid file (%s)" msgstr "O plug-in não é um arquivo válido (%s)" -#: ../libnm-core/nm-utils.c:2540 +#: ../libnm-core/nm-utils.c:2544 #, c-format msgid "libtool archives are not supported (%s)" msgstr "Não há suporte a arquivos de libtool (%s)" -#: ../libnm-core/nm-utils.c:2622 ../libnm-util/nm-utils.c:1815 +#: ../libnm-core/nm-utils.c:2626 ../libnm-util/nm-utils.c:1815 #, c-format msgid "Could not find \"%s\" binary" msgstr "Não foi possível localizar o executável \"%s\"" -#: ../libnm-core/nm-vpn-editor-plugin.c:142 +#: ../libnm-core/nm-vpn-editor-plugin.c:143 #, c-format +#| msgid "cannot load plugin %s" msgid "cannot load plugin \"%s\": %s" msgstr "não foi possível carregar plug-in \"%s\": %s" -#: ../libnm-core/nm-vpn-editor-plugin.c:153 +#: ../libnm-core/nm-vpn-editor-plugin.c:154 #, c-format msgid "failed to load nm_vpn_editor_plugin_factory() from %s (%s)" msgstr "falha ao carregar nm_vpn_editor_plugin_factory() de %s (%s)" -#: ../libnm-core/nm-vpn-editor-plugin.c:178 +#: ../libnm-core/nm-vpn-editor-plugin.c:179 #, c-format msgid "unknown error initializing plugin %s" msgstr "erro desconhecido de inicialização do plug-in %s" -#: ../libnm-core/nm-vpn-editor-plugin.c:195 +#: ../libnm-core/nm-vpn-editor-plugin.c:196 #, c-format msgid "cannot load VPN plugin in '%s': missing plugin name" msgstr "" "não foi possível carregar plug-in de VPN em \"%s\": faltando nome do plug-in" -#: ../libnm-core/nm-vpn-editor-plugin.c:204 +#: ../libnm-core/nm-vpn-editor-plugin.c:205 #, c-format msgid "cannot load VPN plugin in '%s': invalid service name" msgstr "" "não foi possível carregar plug-in de VPN em \"%s\": nome de serviço inválido" -#: ../libnm-core/nm-vpn-editor-plugin.c:310 +#: ../libnm-core/nm-vpn-editor-plugin.c:348 #, c-format msgid "the plugin does not support import capability" msgstr "o plug-in não oferece suporte à capacidade de importação" -#: ../libnm-core/nm-vpn-editor-plugin.c:330 +#: ../libnm-core/nm-vpn-editor-plugin.c:368 #, c-format msgid "the plugin does not support export capability" msgstr "o plug-in não oferece suporte à capacidade de exportação" -#: ../libnm-core/nm-vpn-plugin-info.c:109 +#: ../libnm-core/nm-vpn-plugin-info.c:110 #, c-format msgid "missing filename" msgstr "faltando nome de arquivo" -#: ../libnm-core/nm-vpn-plugin-info.c:117 +#: ../libnm-core/nm-vpn-plugin-info.c:118 #, c-format msgid "filename must be an absolute path (%s)" msgstr "nome de arquivo deve ser um caminho absoluto (%s)" -#: ../libnm-core/nm-vpn-plugin-info.c:126 +#: ../libnm-core/nm-vpn-plugin-info.c:127 #, c-format msgid "filename has invalid format (%s)" msgstr "nome de arquivo possui formato inválido (%s)" -#: ../libnm-core/nm-vpn-plugin-info.c:383 +#: ../libnm-core/nm-vpn-plugin-info.c:450 #, c-format msgid "there exists a conflicting plugin (%s) that has the same %s.%s value" msgstr "há um plug-in conflitante (%s) que possui o mesmo valor %s.%s" -#: ../libnm-core/nm-vpn-plugin-info.c:421 +#: ../libnm-core/nm-vpn-plugin-info.c:488 #, c-format msgid "there exists a conflicting plugin with the same name (%s)" msgstr "há um plug-in conflitante com o mesmo nome (%s)" -#: ../libnm-core/nm-vpn-plugin-info.c:740 +#: ../libnm-core/nm-vpn-plugin-info.c:878 #, c-format msgid "missing \"plugin\" setting" msgstr "faltando definição \"plugin\"" -#: ../libnm-core/nm-vpn-plugin-info.c:750 +#: ../libnm-core/nm-vpn-plugin-info.c:888 #, c-format msgid "%s: don't retry loading plugin which already failed previously" msgstr "%s: não tentar novamente carregar plug-in que já falhou anteriormente" -#: ../libnm-core/nm-vpn-plugin-info.c:842 +#: ../libnm-core/nm-vpn-plugin-info.c:980 msgid "missing filename to load VPN plugin info" msgstr "faltando nome de arquivo para carregar informação de plug-in de VPN" -#: ../libnm-core/nm-vpn-plugin-info.c:854 +#: ../libnm-core/nm-vpn-plugin-info.c:992 msgid "missing name for VPN plugin info" msgstr "faltando nome de arquivo para carregar informação de plug-in de VPN" -#: ../libnm-core/nm-vpn-plugin-info.c:863 +#: ../libnm-core/nm-vpn-plugin-info.c:1001 msgid "missing service for VPN plugin info" msgstr "faltando serviço para informação de plug-in de VPN" @@ -9522,47 +9581,43 @@ msgctxt "connection id fallback" msgid "%s %d" msgstr "%s %d" -#: ../src/main.c:220 ../src/main.c:358 +#: ../src/main.c:148 ../src/main.c:283 #, c-format msgid "Failed to read configuration: %s\n" msgstr "Falha ao ler configuração: %s\n" #. Logging/debugging -#: ../src/main.c:234 ../src/nm-iface-helper.c:298 +#: ../src/main.c:162 ../src/nm-iface-helper.c:298 msgid "Print NetworkManager version and exit" msgstr "Imprime a versão do NetworkManager e sai" -#: ../src/main.c:235 ../src/nm-iface-helper.c:299 +#: ../src/main.c:163 ../src/nm-iface-helper.c:299 msgid "Don't become a daemon" msgstr "Não se torna um daemon" -#: ../src/main.c:236 ../src/nm-iface-helper.c:301 +#: ../src/main.c:164 ../src/nm-iface-helper.c:301 #, c-format msgid "Log level: one of [%s]" msgstr "Nível de registro: um dos [%s]" -#: ../src/main.c:238 ../src/nm-iface-helper.c:303 +#: ../src/main.c:166 ../src/nm-iface-helper.c:303 #, c-format msgid "Log domains separated by ',': any combination of [%s]" msgstr "Domínios de registro separados por \",\": qualquer combinação de [%s]" -#: ../src/main.c:240 ../src/nm-iface-helper.c:305 +#: ../src/main.c:168 ../src/nm-iface-helper.c:305 msgid "Make all warnings fatal" msgstr "Torna todos os avisos fatais" -#: ../src/main.c:241 +#: ../src/main.c:169 msgid "Specify the location of a PID file" msgstr "Especifica a localização de um arquivo PID" -#: ../src/main.c:242 -msgid "State file location" -msgstr "Localização do arquivo de estado" - -#: ../src/main.c:244 +#: ../src/main.c:171 msgid "Print NetworkManager configuration and exit" msgstr "Imprime a configuração do NetworkManager e sai" -#: ../src/main.c:254 +#: ../src/main.c:181 msgid "" "NetworkManager monitors all network connections and automatically\n" "chooses the best connection to use. It also allows the user to\n" @@ -9574,60 +9629,60 @@ msgstr "" "especifique pontos de acesso sem fio os quais cartões sem fio no\n" "computador podem ser associados." -#: ../src/main.c:343 ../src/main-utils.c:269 ../src/nm-iface-helper.c:393 +#: ../src/main.c:268 ../src/main-utils.c:268 ../src/nm-iface-helper.c:393 #, c-format msgid "%s. Please use --help to see a list of valid options.\n" msgstr "%s. Por favor, use --help para ver uma lista de opções válidas.\n" -#: ../src/main.c:348 ../src/nm-iface-helper.c:398 +#: ../src/main.c:273 ../src/nm-iface-helper.c:398 #, c-format msgid "Ignoring unrecognized log domain(s) '%s' passed on command line.\n" msgstr "" "Ignorando domínio(s) de log irreconhecíveis '%s' passaram na linha de " "comando.\n" -#: ../src/main.c:373 +#: ../src/main.c:298 #, c-format msgid "Error in configuration file: %s.\n" msgstr "Erro no arquivo de configuração: %s.\n" -#: ../src/main.c:378 +#: ../src/main.c:303 #, c-format msgid "Ignoring unrecognized log domain(s) '%s' from config files.\n" msgstr "" "Ignorando domínio(s) de log irreconhecíveis '%s' dos arquivos de config.\n" -#: ../src/main.c:389 ../src/nm-iface-helper.c:408 +#: ../src/main.c:314 ../src/nm-iface-helper.c:408 #, c-format msgid "Could not daemonize: %s [error %u]\n" msgstr "Não foi possível tornar um daemon: %s [erro %u]\n" -#: ../src/main-utils.c:99 +#: ../src/main-utils.c:98 #, c-format msgid "Opening %s failed: %s\n" msgstr "Abertura de %s falhou: %s\n" -#: ../src/main-utils.c:105 +#: ../src/main-utils.c:104 #, c-format msgid "Writing to %s failed: %s\n" msgstr "Escrita para %s falhou: %s\n" -#: ../src/main-utils.c:110 +#: ../src/main-utils.c:109 #, c-format msgid "Closing %s failed: %s\n" msgstr "Fechamento de %s falhou: %s\n" -#: ../src/main-utils.c:145 +#: ../src/main-utils.c:144 #, c-format msgid "Cannot create '%s': %s" msgstr "Não foi possível criar \"%s\": %s" -#: ../src/main-utils.c:197 +#: ../src/main-utils.c:196 #, c-format msgid "%s is already running (pid %ld)\n" msgstr "%s já está em execução (pid %ld)\n" -#: ../src/main-utils.c:207 +#: ../src/main-utils.c:206 #, c-format msgid "You must be root to run %s!\n" msgstr "Você precisa ser superusuário para executar %s!\n" @@ -9649,7 +9704,7 @@ msgstr "" msgid "ADSL connection" msgstr "Conexão ADSL" -#: ../src/devices/bluetooth/nm-bluez-device.c:197 +#: ../src/devices/bluetooth/nm-bluez-device.c:199 #, c-format msgid "%s Network" msgstr "Rede %s" @@ -9740,7 +9795,7 @@ msgstr "Conexão VLAN" msgid "VXLAN connection" msgstr "Conexão VXLAN" -#: ../src/devices/team/nm-device-team.c:115 +#: ../src/devices/team/nm-device-team.c:116 msgid "Team connection" msgstr "Conexão de união" @@ -9917,48 +9972,52 @@ msgstr "Falha ao determinar informação de segurança do AP" msgid "GSM mobile broadband connection requires a 'gsm' setting" msgstr "Conexão de banda larga móvel (GSM) requer uma configuração \"gsm\"" -#: ../src/nm-config.c:465 +#: ../src/nm-config.c:499 msgid "Config file location" msgstr "Localização do arquivo de configuração" -#: ../src/nm-config.c:466 +#: ../src/nm-config.c:500 msgid "Config directory location" msgstr "Localização do diretório de configuração" -#: ../src/nm-config.c:467 +#: ../src/nm-config.c:501 msgid "System config directory location" msgstr "Localização do diretório de configuração do sistema" -#: ../src/nm-config.c:468 +#: ../src/nm-config.c:502 msgid "Internal config file location" msgstr "Localização do arquivo de configuração interna" -#: ../src/nm-config.c:469 +#: ../src/nm-config.c:503 +msgid "State file location" +msgstr "Localização do arquivo de estado" + +#: ../src/nm-config.c:504 msgid "State file for no-auto-default devices" msgstr "Arquivo de estado para dispositivos no-auto-default" -#: ../src/nm-config.c:470 +#: ../src/nm-config.c:505 msgid "List of plugins separated by ','" msgstr "Lista de plug-ins separada por \",\"" -#: ../src/nm-config.c:471 +#: ../src/nm-config.c:506 msgid "Quit after initial configuration" msgstr "Sair após configuração inicial" -#: ../src/nm-config.c:472 ../src/nm-iface-helper.c:300 +#: ../src/nm-config.c:507 ../src/nm-iface-helper.c:300 msgid "Don't become a daemon, and log to stderr" msgstr "Não se tornar um daemon e registrar à saída padrão de erro (stderr)" #. These three are hidden for now, and should eventually just go away. -#: ../src/nm-config.c:475 +#: ../src/nm-config.c:510 msgid "An http(s) address for checking internet connectivity" msgstr "Um endereço http(s) para verificar a conectividade com a internet" -#: ../src/nm-config.c:476 +#: ../src/nm-config.c:511 msgid "The interval between connectivity checks (in seconds)" msgstr "O intervalo de tempo entre verificações de conectividade (em segundos)" -#: ../src/nm-config.c:477 +#: ../src/nm-config.c:512 msgid "The expected start of the response" msgstr "O início esperado da resposta" @@ -10084,14 +10143,10 @@ msgstr "Nível de registro \"%s\" desconhecido" msgid "Unknown log domain '%s'" msgstr "Domínio de registro \"%s\" desconhecido" -#: ../src/nm-manager.c:3635 +#: ../src/nm-manager.c:3603 msgid "VPN connection" msgstr "Conexão VPN" -#: ../src/nm-sleep-monitor-systemd.c:131 -msgid "NetworkManager needs to turn off networks" -msgstr "O NetworkManager precisa desligar as redes" - #: ../src/settings/plugins/ifcfg-rh/reader.c:108 msgid "System" msgstr "Sistema" @@ -10108,6 +10163,9 @@ msgstr "Sistema" #~ msgid "Error converting IP6 address '%s' to text form" #~ msgstr "Erro ao converter endereço IP6 \"%s\" para o formato texto" +#~ msgid "NetworkManager needs to turn off networks" +#~ msgstr "O NetworkManager precisa desligar as redes" + #~ msgid "Failed to read configuration: (%d) %s\n" #~ msgstr "Falha ao ler configuração: (%d) %s\n" @@ -10,8 +10,8 @@ msgstr "" "Project-Id-Version: NetworkManager\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=NetworkManager&keywords=I18N+L10N&component=Translations\n" -"POT-Creation-Date: 2016-05-05 14:02+0000\n" -"PO-Revision-Date: 2016-05-07 00:25+0200\n" +"POT-Creation-Date: 2016-04-07 13:40+0000\n" +"PO-Revision-Date: 2016-04-05 22:40+0200\n" "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -106,14 +106,14 @@ msgstr "Fel: Initiering av polkit-agent misslyckades: %s" msgid "nmcli successfully registered as a polkit agent.\n" msgstr "nmcli registrerade en polkit-agent.\n" -#: ../clients/cli/agent.c:206 ../clients/cli/connections.c:11054 -#: ../clients/cli/devices.c:3644 ../clients/cli/general.c:343 -#: ../clients/cli/general.c:481 +#: ../clients/cli/agent.c:206 ../clients/cli/connections.c:11050 +#: ../clients/cli/devices.c:3669 ../clients/cli/general.c:343 +#: ../clients/cli/general.c:484 #, c-format msgid "Error: NetworkManager is not running." msgstr "Fel: Nätverkshanteraren är inte igång." -#: ../clients/cli/agent.c:239 +#: ../clients/cli/agent.c:242 #, c-format msgid "Error: 'agent' command '%s' is not valid." msgstr "Fel: ”agent”-kommandot ”%s” är inte giltigt." @@ -235,7 +235,7 @@ msgstr "ansluter (startar sekundära anslutningar)" msgid "connected" msgstr "ansluten" -#: ../clients/cli/common.c:514 ../clients/cli/connections.c:645 +#: ../clients/cli/common.c:514 ../clients/cli/connections.c:648 msgid "deactivating" msgstr "inaktiverar" @@ -244,25 +244,25 @@ msgid "connection failed" msgstr "anslutningen misslyckades" #: ../clients/cli/common.c:518 ../clients/cli/common.c:535 -#: ../clients/cli/connections.c:650 ../clients/cli/connections.c:673 -#: ../clients/cli/connections.c:1946 ../clients/cli/devices.c:1024 +#: ../clients/cli/connections.c:653 ../clients/cli/connections.c:676 +#: ../clients/cli/connections.c:1949 ../clients/cli/devices.c:1024 #: ../clients/cli/devices.c:1065 ../clients/cli/devices.c:1067 #: ../clients/cli/general.c:248 ../clients/cli/general.c:286 -#: ../clients/cli/general.c:429 ../clients/cli/general.c:445 +#: ../clients/cli/general.c:432 ../clients/cli/general.c:448 #: ../clients/cli/settings.c:839 ../clients/cli/settings.c:925 #: ../clients/cli/settings.c:1265 ../clients/cli/settings.c:1901 -#: ../clients/cli/settings.c:3198 +#: ../clients/cli/settings.c:3205 ../clients/cli/utils.c:1400 #, c-format msgid "unknown" msgstr "okänd" #. "CAPABILITIES" -#: ../clients/cli/common.c:527 ../clients/cli/connections.c:930 -#: ../clients/cli/connections.c:932 ../clients/cli/connections.c:934 -#: ../clients/cli/connections.c:968 ../clients/cli/connections.c:1037 -#: ../clients/cli/connections.c:1038 ../clients/cli/connections.c:1040 -#: ../clients/cli/connections.c:3454 ../clients/cli/connections.c:8567 -#: ../clients/cli/connections.c:8568 ../clients/cli/devices.c:772 +#: ../clients/cli/common.c:527 ../clients/cli/connections.c:933 +#: ../clients/cli/connections.c:935 ../clients/cli/connections.c:937 +#: ../clients/cli/connections.c:971 ../clients/cli/connections.c:1040 +#: ../clients/cli/connections.c:1041 ../clients/cli/connections.c:1043 +#: ../clients/cli/connections.c:3450 ../clients/cli/connections.c:8563 +#: ../clients/cli/connections.c:8564 ../clients/cli/devices.c:772 #: ../clients/cli/devices.c:989 ../clients/cli/devices.c:990 #: ../clients/cli/devices.c:991 ../clients/cli/devices.c:992 #: ../clients/cli/devices.c:993 ../clients/cli/devices.c:1028 @@ -271,15 +271,15 @@ msgstr "okänd" #: ../clients/cli/devices.c:1061 ../clients/cli/devices.c:1062 #: ../clients/cli/devices.c:1063 ../clients/cli/devices.c:1064 #: ../clients/cli/devices.c:1066 ../clients/cli/devices.c:1068 -#: ../clients/cli/general.c:439 ../clients/cli/settings.c:3193 +#: ../clients/cli/general.c:442 ../clients/cli/settings.c:3200 msgid "yes" msgstr "ja" -#: ../clients/cli/common.c:529 ../clients/cli/connections.c:930 -#: ../clients/cli/connections.c:932 ../clients/cli/connections.c:934 -#: ../clients/cli/connections.c:1037 ../clients/cli/connections.c:1038 -#: ../clients/cli/connections.c:1040 ../clients/cli/connections.c:3455 -#: ../clients/cli/connections.c:8567 ../clients/cli/connections.c:8568 +#: ../clients/cli/common.c:529 ../clients/cli/connections.c:933 +#: ../clients/cli/connections.c:935 ../clients/cli/connections.c:937 +#: ../clients/cli/connections.c:1040 ../clients/cli/connections.c:1041 +#: ../clients/cli/connections.c:1043 ../clients/cli/connections.c:3451 +#: ../clients/cli/connections.c:8563 ../clients/cli/connections.c:8564 #: ../clients/cli/devices.c:772 ../clients/cli/devices.c:989 #: ../clients/cli/devices.c:990 ../clients/cli/devices.c:991 #: ../clients/cli/devices.c:992 ../clients/cli/devices.c:993 @@ -288,8 +288,8 @@ msgstr "ja" #: ../clients/cli/devices.c:1060 ../clients/cli/devices.c:1061 #: ../clients/cli/devices.c:1062 ../clients/cli/devices.c:1063 #: ../clients/cli/devices.c:1064 ../clients/cli/devices.c:1066 -#: ../clients/cli/devices.c:1068 ../clients/cli/general.c:441 -#: ../clients/cli/settings.c:3195 +#: ../clients/cli/devices.c:1068 ../clients/cli/general.c:444 +#: ../clients/cli/settings.c:3202 msgid "no" msgstr "nej" @@ -306,7 +306,7 @@ msgid "No reason given" msgstr "Ingen anledning angiven" #. We should not really come here -#: ../clients/cli/common.c:547 ../clients/cli/connections.c:2980 +#: ../clients/cli/common.c:547 ../clients/cli/connections.c:2976 #, c-format msgid "Unknown error" msgstr "Okänt fel" @@ -776,7 +776,7 @@ msgstr "SPEC-OBJEKT" #. 4 #. Ask for optional 'vpn' arguments. #: ../clients/cli/connections.c:200 ../clients/cli/connections.c:238 -#: ../clients/cli/connections.c:4173 ../clients/tui/nm-editor-utils.c:233 +#: ../clients/cli/connections.c:4169 ../clients/tui/nm-editor-utils.c:233 #: ../clients/tui/nmt-connect-connection-list.c:405 msgid "VPN" msgstr "VPN" @@ -847,7 +847,7 @@ msgstr "IP6" msgid "DHCP6" msgstr "DHCP6" -#: ../clients/cli/connections.c:269 +#: ../clients/cli/connections.c:272 #, c-format msgid "" "Usage: nmcli connection { COMMAND | help }\n" @@ -924,7 +924,7 @@ msgstr "" " export [id | uuid | path] <ID> [<utdatafil>]\n" "\n" -#: ../clients/cli/connections.c:291 +#: ../clients/cli/connections.c:294 #, c-format msgid "" "Usage: nmcli connection show { ARGUMENTS | help }\n" @@ -971,7 +971,7 @@ msgstr "" "räknas. Flaggan --show-secrets kommer dessutom att visa associerade " "hemligheter.\n" -#: ../clients/cli/connections.c:312 +#: ../clients/cli/connections.c:315 #, c-format msgid "" "Usage: nmcli connection up { ARGUMENTS | help }\n" @@ -1016,7 +1016,7 @@ msgstr "" "passwd-file - fil med lösenord som krävs för att aktivera anslutningen\n" "\n" -#: ../clients/cli/connections.c:333 +#: ../clients/cli/connections.c:336 #, c-format msgid "" "Usage: nmcli connection down { ARGUMENTS | help }\n" @@ -1039,7 +1039,7 @@ msgstr "" "UUID eller D-Bus-sökväg.\n" "\n" -#: ../clients/cli/connections.c:345 +#: ../clients/cli/connections.c:348 #, c-format msgid "" "Usage: nmcli connection add { ARGUMENTS | help }\n" @@ -1324,7 +1324,7 @@ msgstr "" " [ip6 <IPv6-adress>] [gw6 <IPv6-gateway>]\n" "\n" -#: ../clients/cli/connections.c:457 +#: ../clients/cli/connections.c:460 #, c-format msgid "" "Usage: nmcli connection modify { ARGUMENTS | help }\n" @@ -1374,7 +1374,7 @@ msgstr "" "nmcli con mod bond0 -bond.options downdelay\n" "\n" -#: ../clients/cli/connections.c:480 +#: ../clients/cli/connections.c:483 #, c-format msgid "" "Usage: nmcli connection clone { ARGUMENTS | help }\n" @@ -1397,7 +1397,7 @@ msgstr "" "id (tillhandahålls av argumentet <nytt namn>).\n" "\n" -#: ../clients/cli/connections.c:492 +#: ../clients/cli/connections.c:495 #, c-format msgid "" "Usage: nmcli connection edit { ARGUMENTS | help }\n" @@ -1424,7 +1424,7 @@ msgstr "" "Lägg till en ny anslutningsprofil i en interaktiv redigerare.\n" "\n" -#: ../clients/cli/connections.c:507 +#: ../clients/cli/connections.c:510 #, c-format msgid "" "Usage: nmcli connection delete { ARGUMENTS | help }\n" @@ -1443,7 +1443,7 @@ msgstr "" "Profilen identifieras genom dess namn, UUID, och D-Bus-sökväg.\n" "\n" -#: ../clients/cli/connections.c:518 +#: ../clients/cli/connections.c:521 #, c-format msgid "" "Usage: nmcli connection monitor { ARGUMENTS | help }\n" @@ -1465,7 +1465,7 @@ msgstr "" "Övervakar alla anslutningsprofiler om ingen har angivits.\n" "\n" -#: ../clients/cli/connections.c:530 +#: ../clients/cli/connections.c:533 #, c-format msgid "" "Usage: nmcli connection reload { help }\n" @@ -1478,7 +1478,7 @@ msgstr "" "Läs om alla anslutningsfiler från disk.\n" "\n" -#: ../clients/cli/connections.c:538 +#: ../clients/cli/connections.c:541 #, c-format msgid "" "Usage: nmcli connection load { ARGUMENTS | help }\n" @@ -1502,7 +1502,7 @@ msgstr "" "tillstånd.\n" "\n" -#: ../clients/cli/connections.c:550 +#: ../clients/cli/connections.c:553 #, c-format msgid "" "Usage: nmcli connection import { ARGUMENTS | help }\n" @@ -1527,7 +1527,7 @@ msgstr "" "importeras av Nätverkshanterarens VPN-insticksmoduler.\n" "\n" -#: ../clients/cli/connections.c:563 +#: ../clients/cli/connections.c:566 #, c-format msgid "" "Usage: nmcli connection export { ARGUMENTS | help }\n" @@ -1546,197 +1546,197 @@ msgstr "" "Data dirigeras till standard ut eller till en fil om ett namn anges.\n" "\n" -#: ../clients/cli/connections.c:641 +#: ../clients/cli/connections.c:644 msgid "activating" msgstr "aktiverar" -#: ../clients/cli/connections.c:643 +#: ../clients/cli/connections.c:646 msgid "activated" msgstr "aktiverad" -#: ../clients/cli/connections.c:647 +#: ../clients/cli/connections.c:650 msgid "deactivated" msgstr "inaktiverad" -#: ../clients/cli/connections.c:659 +#: ../clients/cli/connections.c:662 msgid "VPN connecting (prepare)" msgstr "VPN ansluter (förbereder)" -#: ../clients/cli/connections.c:661 +#: ../clients/cli/connections.c:664 msgid "VPN connecting (need authentication)" msgstr "VPN ansluter (behöver autentisering)" -#: ../clients/cli/connections.c:663 +#: ../clients/cli/connections.c:666 msgid "VPN connecting" msgstr "VPN ansluter" -#: ../clients/cli/connections.c:665 +#: ../clients/cli/connections.c:668 msgid "VPN connecting (getting IP configuration)" msgstr "VPN ansluter (hämtar IP-konfiguration)" -#: ../clients/cli/connections.c:667 +#: ../clients/cli/connections.c:670 msgid "VPN connected" msgstr "VPN ansluten" -#: ../clients/cli/connections.c:669 +#: ../clients/cli/connections.c:672 msgid "VPN connection failed" msgstr "VPN-anslutning misslyckades" -#: ../clients/cli/connections.c:671 +#: ../clients/cli/connections.c:674 msgid "VPN disconnected" msgstr "VPN frånkopplad" -#: ../clients/cli/connections.c:741 +#: ../clients/cli/connections.c:744 #, c-format msgid "Error updating secrets for %s: %s\n" msgstr "Fel vid uppdatering av hemligheterna för %s: %s\n" -#: ../clients/cli/connections.c:761 +#: ../clients/cli/connections.c:764 msgid "Connection profile details" msgstr "Detaljer för anslutningsprofil" -#: ../clients/cli/connections.c:773 ../clients/cli/connections.c:1166 +#: ../clients/cli/connections.c:776 ../clients/cli/connections.c:1169 #, c-format msgid "Error: 'connection show': %s" msgstr "Fel: ”connection show”: %s" -#: ../clients/cli/connections.c:929 ../clients/cli/settings.c:1897 +#: ../clients/cli/connections.c:932 ../clients/cli/settings.c:1897 msgid "never" msgstr "aldrig" -#: ../clients/cli/connections.c:1154 +#: ../clients/cli/connections.c:1157 msgid "Activate connection details" msgstr "Aktivera anslutningsdetaljer" -#: ../clients/cli/connections.c:1390 +#: ../clients/cli/connections.c:1393 #, c-format msgid "invalid field '%s'; allowed fields: %s and %s, or %s,%s" msgstr "ogiltigt fält ”%s”; tillåtna fält: %s och %s, eller %s, %s" -#: ../clients/cli/connections.c:1405 ../clients/cli/connections.c:1413 +#: ../clients/cli/connections.c:1408 ../clients/cli/connections.c:1416 #, c-format msgid "'%s' has to be alone" msgstr "”%s” måste vara ensamt" #. Add headers -#: ../clients/cli/connections.c:1631 +#: ../clients/cli/connections.c:1634 msgid "NetworkManager active profiles" msgstr "Aktiva profiler för Nätverkshanteraren" -#: ../clients/cli/connections.c:1632 +#: ../clients/cli/connections.c:1635 msgid "NetworkManager connection profiles" msgstr "Anslutningsprofiler för Nätverkshanteraren" -#: ../clients/cli/connections.c:1678 ../clients/cli/connections.c:2393 -#: ../clients/cli/connections.c:2415 ../clients/cli/connections.c:2424 -#: ../clients/cli/connections.c:2433 ../clients/cli/connections.c:2592 -#: ../clients/cli/connections.c:10160 ../clients/cli/connections.c:10277 -#: ../clients/cli/connections.c:10409 ../clients/cli/connections.c:10542 -#: ../clients/cli/connections.c:10652 ../clients/cli/connections.c:10663 -#: ../clients/cli/connections.c:10762 ../clients/cli/devices.c:2322 -#: ../clients/cli/devices.c:2330 ../clients/cli/devices.c:2653 -#: ../clients/cli/devices.c:2660 ../clients/cli/devices.c:2674 -#: ../clients/cli/devices.c:2681 ../clients/cli/devices.c:2698 -#: ../clients/cli/devices.c:2706 ../clients/cli/devices.c:2719 -#: ../clients/cli/devices.c:3083 ../clients/cli/devices.c:3090 -#: ../clients/cli/devices.c:3097 ../clients/cli/devices.c:3109 -#: ../clients/cli/devices.c:3122 ../clients/cli/devices.c:3129 -#: ../clients/cli/devices.c:3301 ../clients/cli/devices.c:3308 -#: ../clients/cli/devices.c:3481 +#: ../clients/cli/connections.c:1681 ../clients/cli/connections.c:2389 +#: ../clients/cli/connections.c:2411 ../clients/cli/connections.c:2420 +#: ../clients/cli/connections.c:2429 ../clients/cli/connections.c:2588 +#: ../clients/cli/connections.c:10156 ../clients/cli/connections.c:10273 +#: ../clients/cli/connections.c:10405 ../clients/cli/connections.c:10538 +#: ../clients/cli/connections.c:10648 ../clients/cli/connections.c:10659 +#: ../clients/cli/connections.c:10758 ../clients/cli/devices.c:2344 +#: ../clients/cli/devices.c:2352 ../clients/cli/devices.c:2675 +#: ../clients/cli/devices.c:2682 ../clients/cli/devices.c:2696 +#: ../clients/cli/devices.c:2703 ../clients/cli/devices.c:2720 +#: ../clients/cli/devices.c:2728 ../clients/cli/devices.c:2741 +#: ../clients/cli/devices.c:3105 ../clients/cli/devices.c:3112 +#: ../clients/cli/devices.c:3119 ../clients/cli/devices.c:3131 +#: ../clients/cli/devices.c:3144 ../clients/cli/devices.c:3151 +#: ../clients/cli/devices.c:3323 ../clients/cli/devices.c:3330 +#: ../clients/cli/devices.c:3503 #, c-format msgid "Error: %s argument is missing." msgstr "Fel: %s-argument saknas." -#: ../clients/cli/connections.c:1693 +#: ../clients/cli/connections.c:1696 #, c-format msgid "Error: %s - no such connection profile." msgstr "Fel: %s - inga sådana anslutningsprofiler." -#: ../clients/cli/connections.c:1752 ../clients/cli/connections.c:2456 -#: ../clients/cli/connections.c:11163 ../clients/cli/devices.c:3270 -#: ../clients/cli/devices.c:3751 ../clients/cli/general.c:536 -#: ../clients/cli/general.c:585 ../clients/cli/general.c:602 -#: ../clients/cli/general.c:641 ../clients/cli/general.c:655 -#: ../clients/cli/general.c:773 ../clients/cli/general.c:820 -#: ../clients/cli/general.c:840 +#: ../clients/cli/connections.c:1755 ../clients/cli/connections.c:2452 +#: ../clients/cli/connections.c:11162 ../clients/cli/devices.c:3292 +#: ../clients/cli/devices.c:3779 ../clients/cli/general.c:539 +#: ../clients/cli/general.c:588 ../clients/cli/general.c:605 +#: ../clients/cli/general.c:644 ../clients/cli/general.c:658 +#: ../clients/cli/general.c:776 ../clients/cli/general.c:823 +#: ../clients/cli/general.c:843 #, c-format msgid "Error: %s." msgstr "Fel: %s." -#: ../clients/cli/connections.c:1848 +#: ../clients/cli/connections.c:1851 #, c-format msgid "no active connection on device '%s'" msgstr "ingen aktiv anslutning på enheten ”%s”" -#: ../clients/cli/connections.c:1856 +#: ../clients/cli/connections.c:1859 msgid "no active connection or device" msgstr "ingen aktiv anslutning eller enhet" -#: ../clients/cli/connections.c:1907 +#: ../clients/cli/connections.c:1910 #, c-format msgid "device '%s' not compatible with connection '%s'" msgstr "enheten ”%s” är inte kompatibel med anslutningen ”%s”" -#: ../clients/cli/connections.c:1910 +#: ../clients/cli/connections.c:1913 #, c-format msgid "no device found for connection '%s'" msgstr "ingen enhet hittades för anslutningen ”%s”" -#: ../clients/cli/connections.c:1922 +#: ../clients/cli/connections.c:1925 msgid "unknown reason" msgstr "okänd anledning" -#: ../clients/cli/connections.c:1924 ../clients/cli/general.c:277 +#: ../clients/cli/connections.c:1927 ../clients/cli/general.c:277 msgid "none" msgstr "ingen" -#: ../clients/cli/connections.c:1926 +#: ../clients/cli/connections.c:1929 msgid "the user was disconnected" msgstr "användaren kopplades från" -#: ../clients/cli/connections.c:1928 +#: ../clients/cli/connections.c:1931 msgid "the base network connection was interrupted" msgstr "basnätverksanslutningen avbröts" -#: ../clients/cli/connections.c:1930 +#: ../clients/cli/connections.c:1933 msgid "the VPN service stopped unexpectedly" msgstr "VPN-tjänsten stoppades oväntat" -#: ../clients/cli/connections.c:1932 +#: ../clients/cli/connections.c:1935 msgid "the VPN service returned invalid configuration" msgstr "VPN-tjänsten returnerade en ogiltig konfiguration" -#: ../clients/cli/connections.c:1934 +#: ../clients/cli/connections.c:1937 msgid "the connection attempt timed out" msgstr "anslutningsförsöket översteg tidsgränsen" -#: ../clients/cli/connections.c:1936 +#: ../clients/cli/connections.c:1939 msgid "the VPN service did not start in time" msgstr "VPN-tjänsten startade inte i tid" -#: ../clients/cli/connections.c:1938 +#: ../clients/cli/connections.c:1941 msgid "the VPN service failed to start" msgstr "VPN-tjänsten misslyckades med att starta" -#: ../clients/cli/connections.c:1940 +#: ../clients/cli/connections.c:1943 msgid "no valid VPN secrets" msgstr "inga giltiga VPN-hemligheter" -#: ../clients/cli/connections.c:1942 +#: ../clients/cli/connections.c:1945 msgid "invalid VPN secrets" msgstr "ogiltiga VPN-hemligheter" -#: ../clients/cli/connections.c:1944 +#: ../clients/cli/connections.c:1947 msgid "the connection was removed" msgstr "anslutningen togs bort" -#: ../clients/cli/connections.c:1966 ../clients/cli/connections.c:2001 -#: ../clients/cli/connections.c:2162 ../clients/cli/connections.c:8458 +#: ../clients/cli/connections.c:1969 ../clients/cli/connections.c:1997 +#: ../clients/cli/connections.c:2158 ../clients/cli/connections.c:8454 #, c-format msgid "Connection successfully activated (D-Bus active path: %s)\n" msgstr "Anslutning aktiverades (aktiv sökväg för D-Bus: %s)\n" -#: ../clients/cli/connections.c:1974 +#: ../clients/cli/connections.c:1976 #, c-format msgid "" "Connection successfully activated (master waiting for slaves) (D-Bus active " @@ -1745,204 +1745,203 @@ msgstr "" "Anslutning aktiverades (master väntar på slavar) (aktiv sökväg för D-Bus: " "%s)\n" -#: ../clients/cli/connections.c:1981 ../clients/cli/connections.c:1984 -#: ../clients/cli/connections.c:2006 +#: ../clients/cli/connections.c:1980 ../clients/cli/connections.c:2002 #, c-format msgid "Error: Connection activation failed." msgstr "Fel: Aktivering av anslutning misslyckades." -#: ../clients/cli/connections.c:2057 +#: ../clients/cli/connections.c:2053 #, c-format msgid "VPN connection successfully activated (D-Bus active path: %s)\n" msgstr "VPN-anslutning aktiverad (aktiv sökväg för D-Bus: %s)\n" -#: ../clients/cli/connections.c:2065 +#: ../clients/cli/connections.c:2061 #, c-format msgid "Error: Connection activation failed: %s." msgstr "Fel: Aktivering av anslutning misslyckades: %s." -#: ../clients/cli/connections.c:2084 ../clients/cli/devices.c:1426 +#: ../clients/cli/connections.c:2080 ../clients/cli/devices.c:1426 #, c-format msgid "Error: Timeout %d sec expired." msgstr "Fel: Tidsgränsen %d sekunder gick ut." -#: ../clients/cli/connections.c:2144 +#: ../clients/cli/connections.c:2140 #, c-format msgid "Error: Connection activation failed: %s" msgstr "Fel: Aktivering av anslutning misslyckades: %s" -#: ../clients/cli/connections.c:2229 +#: ../clients/cli/connections.c:2225 #, c-format msgid "failed to read passwd-file '%s': %s" msgstr "misslyckades med att läsa lösenordsfilen ”%s”: %s" -#: ../clients/cli/connections.c:2241 +#: ../clients/cli/connections.c:2237 #, c-format msgid "missing colon in 'password' entry '%s'" msgstr "saknar kolon i ”password”-posten ”%s”" -#: ../clients/cli/connections.c:2249 +#: ../clients/cli/connections.c:2245 #, c-format msgid "missing dot in 'password' entry '%s'" msgstr "saknar punkt i ”password”-posten ”%s”" -#: ../clients/cli/connections.c:2262 +#: ../clients/cli/connections.c:2258 #, c-format msgid "invalid setting name in 'password' entry '%s'" msgstr "ogiltig inställning i ”password”-posten ”%s”" -#: ../clients/cli/connections.c:2318 +#: ../clients/cli/connections.c:2314 #, c-format msgid "unknown device '%s'." msgstr "okänd enhet ”%s”." -#: ../clients/cli/connections.c:2323 +#: ../clients/cli/connections.c:2319 msgid "neither a valid connection nor device given" msgstr "ingen aktiv anslutning eller enhet angiven" -#: ../clients/cli/connections.c:2406 +#: ../clients/cli/connections.c:2402 #, c-format msgid "Error: Connection '%s' does not exist." msgstr "Fel: anslutningen ”%s” finns inte." -#: ../clients/cli/connections.c:2441 ../clients/cli/devices.c:1325 -#: ../clients/cli/devices.c:2336 ../clients/cli/devices.c:2730 -#: ../clients/cli/devices.c:3314 +#: ../clients/cli/connections.c:2437 ../clients/cli/devices.c:1325 +#: ../clients/cli/devices.c:2358 ../clients/cli/devices.c:2752 +#: ../clients/cli/devices.c:3336 #, c-format msgid "Unknown parameter: %s\n" msgstr "Okänd parameter: %s\n" -#: ../clients/cli/connections.c:2466 +#: ../clients/cli/connections.c:2462 msgid "preparing" msgstr "förbereder" -#: ../clients/cli/connections.c:2487 +#: ../clients/cli/connections.c:2483 #, c-format msgid "Connection '%s' (%s) successfully deleted.\n" msgstr "Anslutningen ”%s” (%s) togs bort.\n" -#: ../clients/cli/connections.c:2503 +#: ../clients/cli/connections.c:2499 #, c-format msgid "Connection '%s' successfully deactivated (D-Bus active path: %s)\n" msgstr "Anslutningen ”%s” inaktiverades (aktiv sökväg för D-Bus: %s)\n" -#: ../clients/cli/connections.c:2574 ../clients/cli/connections.c:10395 -#: ../clients/cli/connections.c:10594 +#: ../clients/cli/connections.c:2570 ../clients/cli/connections.c:10391 +#: ../clients/cli/connections.c:10590 #, c-format msgid "Error: No connection specified." msgstr "Fel: Ingen anslutning angiven." -#: ../clients/cli/connections.c:2606 +#: ../clients/cli/connections.c:2602 #, c-format msgid "Error: '%s' is not an active connection.\n" msgstr "Fel: ”%s” är inte en aktiv anslutning.\n" -#: ../clients/cli/connections.c:2607 ../clients/cli/connections.c:10424 +#: ../clients/cli/connections.c:2603 ../clients/cli/connections.c:10420 #, c-format msgid "Error: not all active connections found." msgstr "Fel: hittade inte alla aktiva anslutningar." -#: ../clients/cli/connections.c:2616 +#: ../clients/cli/connections.c:2612 #, c-format msgid "Error: no active connection provided." msgstr "Fel: inga aktiva anslutningar tillhandahållna." -#: ../clients/cli/connections.c:2959 ../clients/cli/utils.c:648 +#: ../clients/cli/connections.c:2955 ../clients/cli/utils.c:702 #, c-format msgid "'%s' not among [%s]" msgstr "”%s” inte bland [%s]" -#: ../clients/cli/connections.c:3036 +#: ../clients/cli/connections.c:3032 #, c-format msgid "Error: '%s': '%s' is not a valid %s MAC address." msgstr "Fel: ”%s”: ”%s” är inte en giltig %s-MAC-adress." #. Ask for optional arguments -#: ../clients/cli/connections.c:3037 ../clients/cli/connections.c:3569 +#: ../clients/cli/connections.c:3033 ../clients/cli/connections.c:3565 #: ../clients/tui/nm-editor-utils.c:163 ../libnm-core/nm-connection.c:1716 #: ../libnm-glib/nm-device.c:1861 ../libnm/nm-device.c:1812 msgid "InfiniBand" msgstr "InfiniBand" -#: ../clients/cli/connections.c:3037 ../clients/tui/nm-editor-utils.c:146 +#: ../clients/cli/connections.c:3033 ../clients/tui/nm-editor-utils.c:146 #: ../libnm-glib/nm-device.c:1849 ../libnm/nm-device.c:1800 msgid "Ethernet" msgstr "Ethernet" -#: ../clients/cli/connections.c:3057 +#: ../clients/cli/connections.c:3053 #, c-format msgid "Error: 'mtu': '%s' is not a valid MTU." msgstr "Fel: ”mtu”: ”%s” är inte ett giltigt MTU." -#: ../clients/cli/connections.c:3073 +#: ../clients/cli/connections.c:3069 #, c-format msgid "Error: 'parent': '%s' is not a valid interface name." msgstr "Fel: ”parent”: ”%s” är inte ett giltigt gränssnittsnamn." -#: ../clients/cli/connections.c:3094 +#: ../clients/cli/connections.c:3090 #, c-format msgid "Error: 'p-key': '%s' is not a valid InfiniBand P_KEY." msgstr "Fel: ”p-key”: ”%s” är inte en giltig InfiniBand P_KEY." -#: ../clients/cli/connections.c:3109 +#: ../clients/cli/connections.c:3105 #, c-format msgid "Error: '%s' is not a valid UID/GID." msgstr "Fel: ”%s” är inte ett giltigt UID/GID." -#: ../clients/cli/connections.c:3153 +#: ../clients/cli/connections.c:3149 #, c-format msgid "Error: '%s': '%s' is not a valid %s %s." msgstr "Fel: ”%s”: ”%s” är inte en giltig %s %s." -#: ../clients/cli/connections.c:3166 +#: ../clients/cli/connections.c:3162 msgid "Wi-Fi mode" msgstr "Wi-Fi-läge" -#: ../clients/cli/connections.c:3175 +#: ../clients/cli/connections.c:3171 msgid "InfiniBand transport mode" msgstr "InfiniBand transportläge" -#: ../clients/cli/connections.c:3187 +#: ../clients/cli/connections.c:3183 msgid "ADSL protocol" msgstr "ADSL-protokoll" -#: ../clients/cli/connections.c:3198 +#: ../clients/cli/connections.c:3194 msgid "ADSL encapsulation" msgstr "ADSL-inkapsling" -#: ../clients/cli/connections.c:3207 +#: ../clients/cli/connections.c:3203 msgid "TUN device mode" msgstr "TUN-enhetsläge" -#: ../clients/cli/connections.c:3220 +#: ../clients/cli/connections.c:3216 #, c-format msgid "Error: 'flags': '%s' is not valid; use <0-7>." msgstr "Fel: ”flags”: ”%s” är inte giltig; använd <0-7>." -#: ../clients/cli/connections.c:3242 +#: ../clients/cli/connections.c:3238 #, c-format msgid "Error: '%s': '%s' is not valid; %s " msgstr "Fel: ”%s”: ”%s” är inte giltig; %s " -#: ../clients/cli/connections.c:3420 +#: ../clients/cli/connections.c:3416 #, c-format msgid "Warning: master='%s' doesn't refer to any existing profile.\n" msgstr "Varning: master=”%s” hänvisar inte till någon befintlig profil.\n" -#: ../clients/cli/connections.c:3445 +#: ../clients/cli/connections.c:3441 #, c-format msgid "Error: '%s': '%s' is not valid; use <%u-%u>." msgstr "Fel: ”%s”: ”%s” är inte giltig; använd <%u-%u>." #. Ask for optional arguments. -#: ../clients/cli/connections.c:3501 +#: ../clients/cli/connections.c:3497 #, c-format msgid "There is %d optional argument for '%s' connection type.\n" msgid_plural "There are %d optional arguments for '%s' connection type.\n" msgstr[0] "Det finns %d valfritt argument för anslutningstypen ”%s”.\n" msgstr[1] "Det finns %d valfria argument för anslutningstypen ”%s”.\n" -#: ../clients/cli/connections.c:3504 +#: ../clients/cli/connections.c:3500 #, c-format msgid "Do you want to provide it? %s" msgid_plural "Do you want to provide them? %s" @@ -1950,879 +1949,879 @@ msgstr[0] "Vill du tillhandahålla det? %s" msgstr[1] "Vill du tillhandahålla dem? %s" #. Ask for optional arguments -#: ../clients/cli/connections.c:3521 +#: ../clients/cli/connections.c:3517 msgid "ethernet" msgstr "ethernet" -#: ../clients/cli/connections.c:3526 ../clients/cli/connections.c:3574 -#: ../clients/cli/connections.c:3708 ../clients/cli/connections.c:3787 +#: ../clients/cli/connections.c:3522 ../clients/cli/connections.c:3570 +#: ../clients/cli/connections.c:3704 ../clients/cli/connections.c:3783 msgid "MTU [auto]: " msgstr "MTU [auto]: " -#: ../clients/cli/connections.c:3537 ../clients/cli/connections.c:3585 -#: ../clients/cli/connections.c:3680 ../clients/cli/connections.c:3719 -#: ../clients/cli/connections.c:4105 +#: ../clients/cli/connections.c:3533 ../clients/cli/connections.c:3581 +#: ../clients/cli/connections.c:3676 ../clients/cli/connections.c:3715 +#: ../clients/cli/connections.c:4101 msgid "MAC [none]: " msgstr "MAC [ingen]: " -#: ../clients/cli/connections.c:3548 +#: ../clients/cli/connections.c:3544 msgid "Cloned MAC [none]: " msgstr "Klonad MAC [ingen]: " -#: ../clients/cli/connections.c:3596 +#: ../clients/cli/connections.c:3592 #, c-format msgid "Transport mode %s" msgstr "Transportläge %s" -#: ../clients/cli/connections.c:3609 +#: ../clients/cli/connections.c:3605 msgid "Parent interface [none]: " msgstr "Överordnat gränssnitt [inget]: " -#: ../clients/cli/connections.c:3620 +#: ../clients/cli/connections.c:3616 msgid "P_KEY [none]: " msgstr "P_KEY [ingen]: " -#: ../clients/cli/connections.c:3630 +#: ../clients/cli/connections.c:3626 #, c-format msgid "Error: 'p-key' is mandatory when 'parent' is specified.\n" msgstr "Fel: ”p-key” är obligatoriskt när ”parent” är angett.\n" #. Ask for optional arguments -#: ../clients/cli/connections.c:3647 ../clients/tui/nm-editor-utils.c:154 +#: ../clients/cli/connections.c:3643 ../clients/tui/nm-editor-utils.c:154 #: ../libnm-glib/nm-device.c:1851 ../libnm/nm-device.c:1802 msgid "Wi-Fi" msgstr "Wi-Fi" -#: ../clients/cli/connections.c:3655 ../clients/cli/connections.c:6203 +#: ../clients/cli/connections.c:3651 ../clients/cli/connections.c:6199 #, c-format msgid "Mode %s" msgstr "Läge %s" #. Ask for optional 'wimax' arguments. -#: ../clients/cli/connections.c:3675 ../libnm-glib/nm-device.c:1857 +#: ../clients/cli/connections.c:3671 ../libnm-glib/nm-device.c:1857 #: ../libnm/nm-device.c:1808 msgid "WiMAX" msgstr "WiMAX" #. Ask for optional 'pppoe' arguments. -#: ../clients/cli/connections.c:3698 +#: ../clients/cli/connections.c:3694 msgid "PPPoE" msgstr "PPPoE" -#: ../clients/cli/connections.c:3702 ../clients/cli/connections.c:3740 -#: ../clients/cli/connections.c:4227 +#: ../clients/cli/connections.c:3698 ../clients/cli/connections.c:3736 +#: ../clients/cli/connections.c:4223 msgid "Password [none]: " msgstr "Lösenord [inget]: " -#: ../clients/cli/connections.c:3704 +#: ../clients/cli/connections.c:3700 msgid "Service [none]: " msgstr "Tjänst [ingen]: " #. Ask for optional 'gsm' or 'cdma' arguments. -#: ../clients/cli/connections.c:3734 +#: ../clients/cli/connections.c:3730 msgid "mobile broadband" msgstr "mobilt bredband" -#: ../clients/cli/connections.c:3738 ../clients/cli/connections.c:4177 +#: ../clients/cli/connections.c:3734 ../clients/cli/connections.c:4173 msgid "Username [none]: " msgstr "Användarnamn [inget]: " #. Ask for optional 'bluetooth' arguments. -#: ../clients/cli/connections.c:3753 +#: ../clients/cli/connections.c:3749 msgid "bluetooth" msgstr "bluetooth" -#: ../clients/cli/connections.c:3760 +#: ../clients/cli/connections.c:3756 #, c-format msgid "Bluetooth type %s" msgstr "Bluetooth-typen %s" -#: ../clients/cli/connections.c:3766 +#: ../clients/cli/connections.c:3762 #, c-format msgid "Error: 'bt-type': '%s' is not a valid bluetooth type.\n" msgstr "Fel: ”bt-type”: ”%s” är inte en giltig Bluetoothtyp.\n" #. Ask for optional 'vlan' arguments. #. 13 -#: ../clients/cli/connections.c:3782 ../clients/cli/devices.c:239 +#: ../clients/cli/connections.c:3778 ../clients/cli/devices.c:239 #: ../clients/tui/nm-editor-utils.c:217 ../clients/tui/nmt-page-vlan.c:94 #: ../libnm-core/nm-connection.c:1714 ../libnm-glib/nm-device.c:1869 #: ../libnm-util/nm-connection.c:1632 ../libnm/nm-device.c:1820 msgid "VLAN" msgstr "VLAN" -#: ../clients/cli/connections.c:3798 +#: ../clients/cli/connections.c:3794 msgid "VLAN flags (<0-7>) [none]: " msgstr "VLAN-flaggor (<0-7>) [inga]: " -#: ../clients/cli/connections.c:3809 +#: ../clients/cli/connections.c:3805 msgid "Ingress priority maps [none]: " msgstr "Inträdesprioritetshash [ingen]: " -#: ../clients/cli/connections.c:3820 +#: ../clients/cli/connections.c:3816 msgid "Egress priority maps [none]: " msgstr "Utträdesprioritetshash [ingen]: " -#: ../clients/cli/connections.c:3831 +#: ../clients/cli/connections.c:3827 msgid "Bonding mode [balance-rr]: " msgstr "Kombineringsläge [balance-rr]: " #. Ask for optional 'bond' arguments. -#: ../clients/cli/connections.c:3847 +#: ../clients/cli/connections.c:3843 msgid "bond" msgstr "kombinera" -#: ../clients/cli/connections.c:3869 +#: ../clients/cli/connections.c:3865 msgid "Bonding primary interface [none]: " msgstr "Primärt kombineringsgränssnitt [inget]: " -#: ../clients/cli/connections.c:3872 +#: ../clients/cli/connections.c:3868 #, c-format msgid "Error: 'primary': '%s' is not a valid interface name.\n" msgstr "Fel: ”primary”: ”%s” är inte ett giltigt gränssnittsnamn.\n" -#: ../clients/cli/connections.c:3880 +#: ../clients/cli/connections.c:3876 #, c-format msgid "Bonding monitoring mode %s" msgstr "Övervakningsläge %s för kombinering" -#: ../clients/cli/connections.c:3886 +#: ../clients/cli/connections.c:3882 #, c-format msgid "Error: '%s' is not a valid monitoring mode; use '%s' or '%s'.\n" msgstr "" "Fel: ”%s”: är inte ett giltigt övervakningsläge; använd ”%s” eller ”%s”.\n" -#: ../clients/cli/connections.c:3895 +#: ../clients/cli/connections.c:3891 msgid "Bonding miimon [100]: " msgstr "Kombinerings-miimon [100]: " -#: ../clients/cli/connections.c:3898 +#: ../clients/cli/connections.c:3894 #, c-format msgid "Error: 'miimon': '%s' is not a valid number <0-%u>.\n" msgstr "Fel: ”miimon” : ”%s” är inte ett giltigt nummer <0-%u>.\n" -#: ../clients/cli/connections.c:3906 +#: ../clients/cli/connections.c:3902 msgid "Bonding downdelay [0]: " msgstr "Nedfördröjning för kombinering [0]: " -#: ../clients/cli/connections.c:3909 +#: ../clients/cli/connections.c:3905 #, c-format msgid "Error: 'downdelay': '%s' is not a valid number <0-%u>.\n" msgstr "Fel: ”downdelay”: ”%s” är inte ett giltigt nummer <0-%u>.\n" -#: ../clients/cli/connections.c:3917 +#: ../clients/cli/connections.c:3913 msgid "Bonding updelay [0]: " msgstr "Uppfördröjning för kombinering [0]: " -#: ../clients/cli/connections.c:3920 +#: ../clients/cli/connections.c:3916 #, c-format msgid "Error: 'updelay': '%s' is not a valid number <0-%u>.\n" msgstr "Fel: ”updelay”: ”%s” är inte ett giltigt nummer <0-%u>.\n" -#: ../clients/cli/connections.c:3929 +#: ../clients/cli/connections.c:3925 msgid "Bonding arp-interval [0]: " msgstr "arp-intervall för kombinering [0]: " -#: ../clients/cli/connections.c:3932 +#: ../clients/cli/connections.c:3928 #, c-format msgid "Error: 'arp-interval': '%s' is not a valid number <0-%u>.\n" msgstr "Fel: ”arp-interval”: ”%s” är inte ett giltigt nummer <0-%u>.\n" #. FIXME: verify the string -#: ../clients/cli/connections.c:3940 +#: ../clients/cli/connections.c:3936 msgid "Bonding arp-ip-target [none]: " msgstr "arp-ip-target för kombinering [inget]: " -#: ../clients/cli/connections.c:3947 +#: ../clients/cli/connections.c:3943 msgid "LACP rate ('slow' or 'fast') [slow]: " msgstr "LACP-hastighet (\"slow\" eller \"fast\") [slow]: " -#: ../clients/cli/connections.c:3953 +#: ../clients/cli/connections.c:3949 #, c-format msgid "Error: 'lacp_rate': '%s' is invalid ('slow' or 'fast').\n" msgstr "Fel: ”lacp-rate”: ”%s” är ogiltig (”slow” eller ”fast”).\n" -#: ../clients/cli/connections.c:3976 +#: ../clients/cli/connections.c:3972 msgid "Team JSON configuration [none]: " msgstr "JSON-konfiguration för grupp [ingen]: " -#: ../clients/cli/connections.c:3993 +#: ../clients/cli/connections.c:3989 msgid "team" msgstr "grupp" -#: ../clients/cli/connections.c:3999 +#: ../clients/cli/connections.c:3995 msgid "team-slave" msgstr "grupp-slav" #. Ask for optional 'bridge' arguments. -#: ../clients/cli/connections.c:4011 +#: ../clients/cli/connections.c:4007 msgid "bridge" msgstr "brygga" -#: ../clients/cli/connections.c:4017 +#: ../clients/cli/connections.c:4013 #, c-format msgid "Enable STP %s" msgstr "Aktivera STP %s" -#: ../clients/cli/connections.c:4022 +#: ../clients/cli/connections.c:4018 #, c-format msgid "Error: 'stp': %s.\n" msgstr "Fel: ”stp”: %s.\n" -#: ../clients/cli/connections.c:4030 +#: ../clients/cli/connections.c:4026 msgid "STP priority [32768]: " msgstr "STP-prioritet [32768]: " -#: ../clients/cli/connections.c:4034 +#: ../clients/cli/connections.c:4030 #, c-format msgid "Error: 'priority': '%s' is not a valid number <0-%d>.\n" msgstr "Fel: ”priority”: ”%s” är inte ett giltigt nummer <0-%d>.\n" -#: ../clients/cli/connections.c:4042 +#: ../clients/cli/connections.c:4038 msgid "Forward delay [15]: " msgstr "Framåtfördröjning [15]: " -#: ../clients/cli/connections.c:4046 +#: ../clients/cli/connections.c:4042 #, c-format msgid "Error: 'forward-delay': '%s' is not a valid number <2-30>.\n" msgstr "Fel: ”forward-delay”: ”%s” är inte ett giltigt nummer <2-30>.\n" -#: ../clients/cli/connections.c:4055 +#: ../clients/cli/connections.c:4051 msgid "Hello time [2]: " msgstr "Hallå-tid [2]: " -#: ../clients/cli/connections.c:4059 +#: ../clients/cli/connections.c:4055 #, c-format msgid "Error: 'hello-time': '%s' is not a valid number <1-10>.\n" msgstr "Fel: ”hello-time”: ”%s” är inte ett giltigt nummer <1-10>.\n" -#: ../clients/cli/connections.c:4067 +#: ../clients/cli/connections.c:4063 msgid "Max age [20]: " msgstr "Max ålder [20]: " -#: ../clients/cli/connections.c:4071 +#: ../clients/cli/connections.c:4067 #, c-format msgid "Error: 'max-age': '%s' is not a valid number <6-40>.\n" msgstr "Fel: ”max-age”: ”%s” är inte ett giltig nummer <6-40>.\n" -#: ../clients/cli/connections.c:4079 +#: ../clients/cli/connections.c:4075 msgid "MAC address ageing time [300]: " msgstr "Livstid för MAC-adress [300]: " -#: ../clients/cli/connections.c:4083 +#: ../clients/cli/connections.c:4079 #, c-format msgid "Error: 'ageing-time': '%s' is not a valid number <0-1000000>.\n" msgstr "Fel: ”ageing-time”: ”%s” är inte ett giltig nummer <0-1000000>.\n" -#: ../clients/cli/connections.c:4092 +#: ../clients/cli/connections.c:4088 #, c-format msgid "Enable IGMP snooping %s" msgstr "Aktivera IGMP-avlyssning %s" -#: ../clients/cli/connections.c:4097 +#: ../clients/cli/connections.c:4093 #, c-format msgid "Error: 'multicast-snooping': %s.\n" msgstr "Fel: ”multicast-avlyssning”: %s.\n" #. Ask for optional 'bridge-slave' arguments. -#: ../clients/cli/connections.c:4124 +#: ../clients/cli/connections.c:4120 msgid "bridge-slave" msgstr "brygga-slav" -#: ../clients/cli/connections.c:4129 +#: ../clients/cli/connections.c:4125 msgid "Bridge port priority [32]: " msgstr "Prioritet för bryggport [32]: " -#: ../clients/cli/connections.c:4142 +#: ../clients/cli/connections.c:4138 msgid "Bridge port STP path cost [100]: " msgstr "STP-sökvägskostnad för bryggport [100]: " -#: ../clients/cli/connections.c:4156 +#: ../clients/cli/connections.c:4152 #, c-format msgid "Hairpin %s" msgstr "Hårnål %s" -#: ../clients/cli/connections.c:4161 +#: ../clients/cli/connections.c:4157 #, c-format msgid "Error: 'hairpin': %s.\n" msgstr "Fel: ”hairpin”: %s.\n" #. Ask for optional 'olpc' arguments. -#: ../clients/cli/connections.c:4188 ../libnm-glib/nm-device.c:1855 +#: ../clients/cli/connections.c:4184 ../libnm-glib/nm-device.c:1855 #: ../libnm/nm-device.c:1806 msgid "OLPC Mesh" msgstr "OLPC-mesh" -#: ../clients/cli/connections.c:4193 +#: ../clients/cli/connections.c:4189 msgid "OLPC Mesh channel [1]: " msgstr "OLPC-meshkanal [1]: " -#: ../clients/cli/connections.c:4196 +#: ../clients/cli/connections.c:4192 #, c-format msgid "Error: 'channel': '%s' is not a valid number <1-13>.\n" msgstr "Fel: ”channel”: ”%s” är inte ett giltigt nummer <1-13>.\n" -#: ../clients/cli/connections.c:4204 +#: ../clients/cli/connections.c:4200 msgid "DHCP anycast MAC address [none]: " msgstr "DHCP-anycast MAC-adress [ingen]: " #. Ask for optional 'adsl' arguments. -#: ../clients/cli/connections.c:4223 ../libnm-glib/nm-device.c:1871 +#: ../clients/cli/connections.c:4219 ../libnm-glib/nm-device.c:1871 #: ../libnm/nm-device.c:1822 msgid "ADSL" msgstr "ADSL" -#: ../clients/cli/connections.c:4231 +#: ../clients/cli/connections.c:4227 #, c-format msgid "ADSL encapsulation %s" msgstr "ADSL-inkapsling %s" #. Ask for optional 'macvlan' arguments. -#: ../clients/cli/connections.c:4249 +#: ../clients/cli/connections.c:4245 msgid "macvlan" msgstr "macvlan" -#: ../clients/cli/connections.c:4255 +#: ../clients/cli/connections.c:4251 #, c-format msgid "Tap %s" msgstr "Tap %s" -#: ../clients/cli/connections.c:4260 +#: ../clients/cli/connections.c:4256 #, c-format msgid "Error: 'tap': %s.\n" msgstr "Fel: ”tap”: %s.\n" #. Ask for optional 'vxlan' arguments. -#: ../clients/cli/connections.c:4276 ../libnm-glib/nm-device.c:1875 +#: ../clients/cli/connections.c:4272 ../libnm-glib/nm-device.c:1875 #: ../libnm/nm-device.c:1826 msgid "VXLAN" msgstr "VXLAN" -#: ../clients/cli/connections.c:4281 ../clients/cli/connections.c:4605 +#: ../clients/cli/connections.c:4277 ../clients/cli/connections.c:4601 msgid "Parent device [none]: " msgstr "Överordnad enhet [ingen]: " -#: ../clients/cli/connections.c:4286 ../clients/cli/connections.c:4610 +#: ../clients/cli/connections.c:4282 ../clients/cli/connections.c:4606 #, c-format msgid "Error: 'dev': '%s' is neither UUID nor interface name.\n" msgstr "Fel: ”dev”: ”%s” är varken UUID eller gränssnittsnamn.\n" -#: ../clients/cli/connections.c:4295 +#: ../clients/cli/connections.c:4291 msgid "Local address [none]: " msgstr "Lokal adress [ingen]: " -#: ../clients/cli/connections.c:4300 +#: ../clients/cli/connections.c:4296 #, c-format msgid "Error: 'local': '%s' is not a valid IP address.\n" msgstr "Fel: ”local”: ”%s” är inte en giltig IP-adress.\n" -#: ../clients/cli/connections.c:4309 +#: ../clients/cli/connections.c:4305 msgid "Minimum source port [0]: " msgstr "Lägsta källport [0]: " -#: ../clients/cli/connections.c:4313 +#: ../clients/cli/connections.c:4309 #, c-format msgid "Error: 'source-port-min': '%s' is not a valid number <0-65535>.\n" msgstr "Fel: ”source-port-min”: ”%s” är inte ett giltigt nummer <0-65535>.\n" -#: ../clients/cli/connections.c:4322 +#: ../clients/cli/connections.c:4318 msgid "Maximum source port [0]: " msgstr "Högsta källport [0]: " -#: ../clients/cli/connections.c:4326 +#: ../clients/cli/connections.c:4322 #, c-format msgid "Error: 'source-port-max': '%s' is not a valid number <0-65535>.\n" msgstr "Fel: ”source-port-max”: ”%s” är inte ett giltigt nummer <0-65535>.\n" -#: ../clients/cli/connections.c:4335 +#: ../clients/cli/connections.c:4331 msgid "Destination port [8472]: " msgstr "Destinationsport [8472]: " -#: ../clients/cli/connections.c:4339 +#: ../clients/cli/connections.c:4335 #, c-format msgid "Error: 'destination-port': '%s' is not a valid number <0-65535>.\n" msgstr "" "Fel: ”destination-port” : ”%s” är inte ett giltigt nummer <0-65535>.\n" -#: ../clients/cli/connections.c:4378 +#: ../clients/cli/connections.c:4374 msgid "IPv4 address (IP[/plen]) [none]: " msgstr "IPv4-adress (IP[/plen]) [ingen]: " -#: ../clients/cli/connections.c:4380 +#: ../clients/cli/connections.c:4376 msgid "IPv6 address (IP[/plen]) [none]: " msgstr "IPv6-adress (IP[/plen]) [ingen]: " -#: ../clients/cli/connections.c:4394 +#: ../clients/cli/connections.c:4390 #, c-format msgid " Address successfully added: %s\n" msgstr " Adress lades till: %s\n" -#: ../clients/cli/connections.c:4396 +#: ../clients/cli/connections.c:4392 #, c-format msgid " Warning: address already present: %s\n" msgstr " Varning: adressen finns redan: %s\n" -#: ../clients/cli/connections.c:4398 +#: ../clients/cli/connections.c:4394 #, c-format msgid " Warning: ignoring garbage at the end: '%s'\n" msgstr " Varning: ignorerar skräp på slutet: ”%s”\n" -#: ../clients/cli/connections.c:4400 ../clients/cli/connections.c:5609 -#: ../clients/cli/connections.c:5656 ../clients/cli/connections.c:6573 -#: ../clients/cli/connections.c:6606 +#: ../clients/cli/connections.c:4396 ../clients/cli/connections.c:5605 +#: ../clients/cli/connections.c:5652 ../clients/cli/connections.c:6569 +#: ../clients/cli/connections.c:6602 msgid "Error: " msgstr "Fel: " -#: ../clients/cli/connections.c:4420 +#: ../clients/cli/connections.c:4416 msgid "IPv4 gateway [none]: " msgstr "IPv4-gateway [ingen]: " -#: ../clients/cli/connections.c:4423 +#: ../clients/cli/connections.c:4419 msgid "IPv6 gateway [none]: " msgstr "IPv6-gateway [ingen]: " -#: ../clients/cli/connections.c:4443 +#: ../clients/cli/connections.c:4439 #, c-format msgid "Error: invalid gateway address '%s'\n" msgstr "Fel: ogiltig gateway-adress ”%s”\n" #. Ask for IP addresses -#: ../clients/cli/connections.c:4456 +#: ../clients/cli/connections.c:4452 #, c-format msgid "Do you want to add IP addresses? %s" msgstr "Vill du lägga till IP-adresser? %s" -#: ../clients/cli/connections.c:4464 +#: ../clients/cli/connections.c:4460 #, c-format msgid "Press <Enter> to finish adding addresses.\n" msgstr "Tryck <Retur> för att sluta lägga till adresser.\n" #. Ask for optional 'tun' arguments. -#: ../clients/cli/connections.c:4508 ../libnm-glib/nm-device.c:1879 +#: ../clients/cli/connections.c:4504 ../libnm-glib/nm-device.c:1879 #: ../libnm/nm-device.c:1830 msgid "Tun" msgstr "Tun" -#: ../clients/cli/connections.c:4513 +#: ../clients/cli/connections.c:4509 msgid "User ID [none]: " msgstr "Användar-ID [inget]: " -#: ../clients/cli/connections.c:4526 +#: ../clients/cli/connections.c:4522 msgid "Group ID [none]: " msgstr "Grupp-ID [inget]: " -#: ../clients/cli/connections.c:4540 +#: ../clients/cli/connections.c:4536 #, c-format msgid "Enable PI %s" msgstr "Aktivera PI %s" -#: ../clients/cli/connections.c:4545 +#: ../clients/cli/connections.c:4541 #, c-format msgid "Error: 'pi': %s.\n" msgstr "Fel: ”pi”: %s.\n" -#: ../clients/cli/connections.c:4553 +#: ../clients/cli/connections.c:4549 #, c-format msgid "Enable VNET header %s" msgstr "Aktivera VNET-huvud %s" -#: ../clients/cli/connections.c:4558 +#: ../clients/cli/connections.c:4554 #, c-format msgid "Error: 'vnet-hdr': %s.\n" msgstr "Fel: ”vnet-hdr”: %s.\n" -#: ../clients/cli/connections.c:4566 +#: ../clients/cli/connections.c:4562 #, c-format msgid "Enable multi queue %s" msgstr "Aktivera multikö %s" -#: ../clients/cli/connections.c:4571 +#: ../clients/cli/connections.c:4567 #, c-format msgid "Error: 'multi-queue': %s.\n" msgstr "Fel: ”multi-queue”: %s.\n" #. Ask for optional 'ip-tunnel' arguments. -#: ../clients/cli/connections.c:4585 +#: ../clients/cli/connections.c:4581 msgid "IP Tunnel" msgstr "IP-tunnel" -#: ../clients/cli/connections.c:4590 +#: ../clients/cli/connections.c:4586 msgid "Local endpoint [none]: " msgstr "Lokal ändpunkt [ingen]: " -#: ../clients/cli/connections.c:4596 +#: ../clients/cli/connections.c:4592 #, c-format msgid "Error: 'local': '%s' is not valid; must be an IP address\n" msgstr "Fel: ”local”: ”%s” är inte giltig, måste vara en IP-adress\n" -#: ../clients/cli/connections.c:4662 ../clients/cli/connections.c:10188 +#: ../clients/cli/connections.c:4658 ../clients/cli/connections.c:10184 #, c-format msgid "Error: <setting>.<property> argument is missing." msgstr "Fel: <inställning>.<egenskap>-argument saknas." -#: ../clients/cli/connections.c:4667 +#: ../clients/cli/connections.c:4663 #, c-format msgid "Error: value for '%s' is missing." msgstr "Fel: värdet för ”%s” saknas." -#: ../clients/cli/connections.c:4685 +#: ../clients/cli/connections.c:4681 #, c-format msgid "Error: invalid <setting>.<property> '%s'." msgstr "Fel: ogiltig <inställning>.<egenskap> ”%s”." -#: ../clients/cli/connections.c:4693 +#: ../clients/cli/connections.c:4689 #, c-format msgid "Error: invalid or not allowed setting '%s': %s." msgstr "Fel: ogiltig eller ej tillåten inställning: ”%s”: %s." -#: ../clients/cli/connections.c:4704 +#: ../clients/cli/connections.c:4700 #, c-format msgid "Error: don't know how to create '%s' setting." msgstr "Fel: vet inte hur man skapar en ”%s”-inställning." -#: ../clients/cli/connections.c:4714 +#: ../clients/cli/connections.c:4710 #, c-format msgid "Error: invalid property '%s': %s." msgstr "Fel: ogiltig egenskap ”%s”: %s." -#: ../clients/cli/connections.c:4726 +#: ../clients/cli/connections.c:4722 #, c-format msgid "Error: failed to modify %s.%s: %s." msgstr "Fel: misslyckades med att ändra %s.%s: %s." -#: ../clients/cli/connections.c:4745 +#: ../clients/cli/connections.c:4741 #, c-format msgid "Error: failed to remove a value from %s.%s: %s." msgstr "Fel: misslyckades att ta bort ett värde från %s.%s: %s." -#: ../clients/cli/connections.c:4779 +#: ../clients/cli/connections.c:4775 #, c-format msgid "" "Warning: 'type' is ignored. Use 'nmcli connection add \"%s\" ...' instead." msgstr "" "Varning: ”type” ignoreras. Använd ”nmcli connection add \"%s\"…” istället." -#: ../clients/cli/connections.c:4787 +#: ../clients/cli/connections.c:4783 msgid "Error: redundant 'master' option." msgstr "Fel: redundant ”master”-flagga." -#: ../clients/cli/connections.c:4800 +#: ../clients/cli/connections.c:4796 msgid "Error: 'master' is required." msgstr "Fel: ”master” krävs." -#: ../clients/cli/connections.c:4954 +#: ../clients/cli/connections.c:4950 #, c-format msgid "Error: 'parent': not valid without 'p-key'." msgstr "Fel: ”parent”: inte giltig utan ”p-key”." -#: ../clients/cli/connections.c:5009 ../clients/cli/connections.c:5971 +#: ../clients/cli/connections.c:5005 ../clients/cli/connections.c:5967 msgid "SSID: " msgstr "SSID: " -#: ../clients/cli/connections.c:5012 ../clients/cli/connections.c:5974 +#: ../clients/cli/connections.c:5008 ../clients/cli/connections.c:5970 msgid "Error: 'ssid' is required." msgstr "Fel: ”ssid” krävs." -#: ../clients/cli/connections.c:5076 +#: ../clients/cli/connections.c:5072 msgid "WiMAX NSP name: " msgstr "WiMAX NSP-lista: " -#: ../clients/cli/connections.c:5079 +#: ../clients/cli/connections.c:5075 msgid "Error: 'nsp' is required." msgstr "Fel: ”nsp” krävs." -#: ../clients/cli/connections.c:5131 +#: ../clients/cli/connections.c:5127 msgid "PPPoE username: " msgstr "PPPoE-användarnamn: " -#: ../clients/cli/connections.c:5134 ../clients/cli/connections.c:6041 +#: ../clients/cli/connections.c:5130 ../clients/cli/connections.c:6037 msgid "Error: 'username' is required." msgstr "Fel: ”username” krävs." -#: ../clients/cli/connections.c:5203 +#: ../clients/cli/connections.c:5199 msgid "APN: " msgstr "APN: " -#: ../clients/cli/connections.c:5206 +#: ../clients/cli/connections.c:5202 msgid "Error: 'apn' is required." msgstr "Fel: ”apn” krävs." -#: ../clients/cli/connections.c:5264 +#: ../clients/cli/connections.c:5260 msgid "Bluetooth device address: " msgstr "Adress för Bluetooth-enhet: " -#: ../clients/cli/connections.c:5267 +#: ../clients/cli/connections.c:5263 msgid "Error: 'addr' is required." msgstr "Fel: ”addr” krävs." -#: ../clients/cli/connections.c:5308 +#: ../clients/cli/connections.c:5304 #, c-format msgid "Error: 'bt-type': '%s' not valid; use [%s, %s (%s), %s]." msgstr "Fel: ”bt-type”: ”%s” inte giltig; använd [%s, %s (%s), %s]." -#: ../clients/cli/connections.c:5352 +#: ../clients/cli/connections.c:5348 msgid "VLAN parent device or connection UUID: " msgstr "Överordnad VLAN-enhet eller anslutnings-UUID: " -#: ../clients/cli/connections.c:5355 ../clients/cli/connections.c:6112 +#: ../clients/cli/connections.c:5351 ../clients/cli/connections.c:6108 msgid "Error: 'dev' is required." msgstr "Fel: ”dev” krävs." -#: ../clients/cli/connections.c:5359 +#: ../clients/cli/connections.c:5355 msgid "VLAN ID <0-4094>: " msgstr "VLAN-ID <0-4094>: " -#: ../clients/cli/connections.c:5362 ../clients/cli/connections.c:6428 +#: ../clients/cli/connections.c:5358 ../clients/cli/connections.c:6424 msgid "Error: 'id' is required." msgstr "Fel: ”id” krävs." -#: ../clients/cli/connections.c:5368 +#: ../clients/cli/connections.c:5364 #, c-format msgid "Error: 'id': '%s' is not valid; use <0-4094>." msgstr "Fel: ”id”: ”%s” är inte giltigt: använd <0-4094>." -#: ../clients/cli/connections.c:5378 ../clients/cli/connections.c:6120 +#: ../clients/cli/connections.c:5374 ../clients/cli/connections.c:6116 #, c-format msgid "Error: 'dev': '%s' is neither UUID, interface name, nor MAC." msgstr "Fel: ”dev”: ”%s” är varken UUID, gränssnittsnamn eller MAC." -#: ../clients/cli/connections.c:5510 +#: ../clients/cli/connections.c:5506 #, c-format msgid "Error: 'mode': %s." msgstr "Fel: ”mode”: %s." -#: ../clients/cli/connections.c:5519 +#: ../clients/cli/connections.c:5515 #, c-format msgid "Error: 'primary': '%s' is not a valid interface name." msgstr "Fel: ”primary”: ”%s” är inte ett giltigt gränssnittsnamn." -#: ../clients/cli/connections.c:5742 +#: ../clients/cli/connections.c:5738 #, c-format msgid "Error: 'stp': %s." msgstr "Fel: ”stp”: %s." -#: ../clients/cli/connections.c:5751 +#: ../clients/cli/connections.c:5747 #, c-format msgid "Error: 'multicast-snooping': %s." msgstr "Fel: ”multicast-avlyssning”: %s." -#: ../clients/cli/connections.c:5870 +#: ../clients/cli/connections.c:5866 #, c-format msgid "Error: 'hairpin': %s." msgstr "Fel: ”hairpin”: %s." -#: ../clients/cli/connections.c:5919 +#: ../clients/cli/connections.c:5915 msgid "Error: 'vpn-type' is required." msgstr "Fel: ”vpn-type” krävs." -#: ../clients/cli/connections.c:5926 +#: ../clients/cli/connections.c:5922 #, c-format msgid "Warning: 'vpn-type': %s not known.\n" msgstr "Varning: ”vpn-type”: %s okänd.\n" -#: ../clients/cli/connections.c:5987 +#: ../clients/cli/connections.c:5983 #, c-format msgid "Error: 'channel': '%s' is not valid; use <1-13>." msgstr "Fel: ”channel”: ”%s” är inte giltigt; använd <1-13>." -#: ../clients/cli/connections.c:6038 +#: ../clients/cli/connections.c:6034 msgid "Username: " msgstr "Användarnamn: " -#: ../clients/cli/connections.c:6047 +#: ../clients/cli/connections.c:6043 #, c-format msgid "Protocol %s" msgstr "Protokoll %s" -#: ../clients/cli/connections.c:6050 +#: ../clients/cli/connections.c:6046 msgid "Error: 'protocol' is required." msgstr "Fel: ”protocol” krävs." -#: ../clients/cli/connections.c:6109 +#: ../clients/cli/connections.c:6105 msgid "MACVLAN parent device or connection UUID: " msgstr "Överordnad MACVLAN-enhet eller anslutnings-UUID: " -#: ../clients/cli/connections.c:6129 ../clients/cli/connections.c:6209 -#: ../clients/cli/connections.c:6311 +#: ../clients/cli/connections.c:6125 ../clients/cli/connections.c:6205 +#: ../clients/cli/connections.c:6307 msgid "Error: 'mode' is required." msgstr "Fel: ”mode” krävs." -#: ../clients/cli/connections.c:6135 +#: ../clients/cli/connections.c:6131 msgid "Error: 'mode' is not valid." msgstr "Fel: ”mode” är inte giltigt." -#: ../clients/cli/connections.c:6148 +#: ../clients/cli/connections.c:6144 #, c-format msgid "Error: 'tap': %s." msgstr "Fel: ”tap”: %s." -#: ../clients/cli/connections.c:6234 +#: ../clients/cli/connections.c:6230 #, c-format msgid "Error: 'pi': %s." msgstr "Fel: ”pi”: %s." -#: ../clients/cli/connections.c:6245 +#: ../clients/cli/connections.c:6241 #, c-format msgid "Error: 'vnet-hdr': %s." msgstr "Fel: ”vnet-hdr”: %s." -#: ../clients/cli/connections.c:6256 +#: ../clients/cli/connections.c:6252 #, c-format msgid "Error: 'multi-queue': %s." msgstr "Fel: ”multi-queue”: %s." -#: ../clients/cli/connections.c:6325 +#: ../clients/cli/connections.c:6321 #, c-format msgid "Error: 'mode': '%s' is not valid, use one of %s" msgstr "Fel: ”mode”: ”%s” är inte giltigt, använd ett av %s" -#: ../clients/cli/connections.c:6331 +#: ../clients/cli/connections.c:6327 msgid "Remote endpoint: " msgstr "Fjärrändpunkt: " -#: ../clients/cli/connections.c:6334 ../clients/cli/connections.c:6436 +#: ../clients/cli/connections.c:6330 ../clients/cli/connections.c:6432 msgid "Error: 'remote' is required." msgstr "Fel: ”remote” krävs." -#: ../clients/cli/connections.c:6341 +#: ../clients/cli/connections.c:6337 #, c-format msgid "Error: 'remote': '%s' is not valid; must be an IP address" msgstr "Fel: ”remote”: ”%s” är inte giltig, måste vara en IP-adress" -#: ../clients/cli/connections.c:6355 +#: ../clients/cli/connections.c:6351 #, c-format msgid "Error: 'local': '%s' is not valid; must be an IP address" msgstr "Fel: ”local”: ”%s” är inte giltig, måste vara en IP-adress" -#: ../clients/cli/connections.c:6364 ../clients/cli/connections.c:6459 +#: ../clients/cli/connections.c:6360 ../clients/cli/connections.c:6455 #, c-format msgid "Error: 'dev': '%s' is neither UUID nor interface name." msgstr "Fel: ”dev”: ”%s” är varken UUID eller gränssnittsnamn." -#: ../clients/cli/connections.c:6425 +#: ../clients/cli/connections.c:6421 msgid "VXLAN ID: " msgstr "VXLAN-ID: " -#: ../clients/cli/connections.c:6433 +#: ../clients/cli/connections.c:6429 msgid "Remote: " msgstr "Fjärr: " -#: ../clients/cli/connections.c:6442 +#: ../clients/cli/connections.c:6438 #, c-format msgid "Error: 'id': '%s' is not valid; use <0-16777215>." msgstr "Fel: ”id”: ”%s” är inte giltigt: använd <0-16777215>." -#: ../clients/cli/connections.c:6468 +#: ../clients/cli/connections.c:6464 #, c-format msgid "Error: 'remote': '%s' is not a valid IP address" msgstr "Fel: ”remote”: ”%s” är inte en giltig IP-adress" -#: ../clients/cli/connections.c:6477 +#: ../clients/cli/connections.c:6473 #, c-format msgid "Error: 'local': '%s' is not a valid IP address" msgstr "Fel: ”local”: ”%s” är inte en giltig IP-adress" -#: ../clients/cli/connections.c:6486 +#: ../clients/cli/connections.c:6482 #, c-format msgid "Error: 'source-port-min': %s is not valid; use <0-65535>." msgstr "Fel: ”source-port-min”: %s är inte giltig; använd <0-65535>." -#: ../clients/cli/connections.c:6495 +#: ../clients/cli/connections.c:6491 #, c-format msgid "Error: 'source-port-max': %s is not valid; use <0-65535>." msgstr "Fel: ”source-port-max”: %s är inte giltig; använd <0-65535>." -#: ../clients/cli/connections.c:6504 +#: ../clients/cli/connections.c:6500 #, c-format msgid "Error: 'destination-port': %s is not valid; use <0-65535>." msgstr "Fel: ”destination-port”: %s är inte giltig: använd <0-65535>." -#: ../clients/cli/connections.c:6544 +#: ../clients/cli/connections.c:6540 #, c-format msgid "Error: '%s' is not a valid connection type." msgstr "Fel: ”%s” är inte en giltig anslutningstyp." -#: ../clients/cli/connections.c:6585 +#: ../clients/cli/connections.c:6581 #, c-format msgid "Error: IPv4 gateway specified without IPv4 addresses" msgstr "Fel: IPv4-gateway angiven utan IPv4-adresser" -#: ../clients/cli/connections.c:6589 +#: ../clients/cli/connections.c:6585 #, c-format msgid "Error: multiple IPv4 gateways specified" msgstr "Fel: flera IPv4-gateways angivna" -#: ../clients/cli/connections.c:6593 +#: ../clients/cli/connections.c:6589 #, c-format msgid "Error: Invalid IPv4 gateway '%s'" msgstr "Fel: ogiltig IPv4-gateway ”%s”" -#: ../clients/cli/connections.c:6618 +#: ../clients/cli/connections.c:6614 #, c-format msgid "Error: IPv6 gateway specified without IPv6 addresses" msgstr "Fel: IPv6-gateway angiven utan IPv6-adresser" -#: ../clients/cli/connections.c:6622 +#: ../clients/cli/connections.c:6618 #, c-format msgid "Error: multiple IPv6 gateways specified" msgstr "Fel: flera IPv6-gateways angivna" -#: ../clients/cli/connections.c:6626 +#: ../clients/cli/connections.c:6622 #, c-format msgid "Error: Invalid IPv6 gateway '%s'" msgstr "Fel: ogiltig IPv6-gateway ”%s”" -#: ../clients/cli/connections.c:6674 ../clients/cli/connections.c:10227 +#: ../clients/cli/connections.c:6670 ../clients/cli/connections.c:10223 #, c-format msgid "Error: Failed to add '%s' connection: %s" msgstr "Fel: Misslyckades med att lägga till ”%s”-anslutning: %s" -#: ../clients/cli/connections.c:6679 +#: ../clients/cli/connections.c:6675 #, c-format msgid "Connection '%s' (%s) successfully added.\n" msgstr "Anslutning ”%s” (%s) lades till.\n" -#: ../clients/cli/connections.c:6955 ../clients/cli/connections.c:10682 +#: ../clients/cli/connections.c:6951 ../clients/cli/connections.c:10678 #, c-format msgid "Error: 'type' argument is required." msgstr "Fel: ”type”-argument saknas." -#: ../clients/cli/connections.c:6963 +#: ../clients/cli/connections.c:6959 #, c-format msgid "Error: invalid connection type; %s." msgstr "Fel: ogiltig anslutningstyp; %s." -#: ../clients/cli/connections.c:6972 ../clients/cli/devices.c:2142 +#: ../clients/cli/connections.c:6968 ../clients/cli/devices.c:2164 #, c-format msgid "Error: 'autoconnect': %s." msgstr "Fel: ”autoconnect”: %s." -#: ../clients/cli/connections.c:6982 +#: ../clients/cli/connections.c:6978 #, c-format msgid "Error: 'save': %s." msgstr "Fel: ”save”: %s." -#: ../clients/cli/connections.c:6999 +#: ../clients/cli/connections.c:6995 msgid "Interface name [*]: " msgstr "Gränssnittsnamn [*]: " -#: ../clients/cli/connections.c:7004 +#: ../clients/cli/connections.c:7000 #, c-format msgid "Error: 'ifname' argument is required." msgstr "Fel: ”ifname”-argument krävs." -#: ../clients/cli/connections.c:7006 +#: ../clients/cli/connections.c:7002 #, c-format msgid "Error: mandatory 'ifname' not seen before '%s'." msgstr "Fel: obligatoriskt ”ifname” inte sett innan ”%s”." -#: ../clients/cli/connections.c:7015 +#: ../clients/cli/connections.c:7011 #, c-format msgid "Error: 'ifname': '%s' is not a valid interface nor '*'." msgstr "" "Fel: ”ifname”: ”%s” är inte ett giltigt gränssnittsnamn, inte heller ”*”." -#: ../clients/cli/connections.c:8039 +#: ../clients/cli/connections.c:8035 #, c-format msgid "['%s' setting values]\n" msgstr "[”%s”-inställningsvärden]\n" @@ -2830,7 +2829,7 @@ msgstr "[”%s”-inställningsvärden]\n" #. TRANSLATORS: do not translate command names and keywords before :: #. * However, you should translate terms enclosed in <>. #. -#: ../clients/cli/connections.c:8121 +#: ../clients/cli/connections.c:8117 #, c-format msgid "" "---[ Main menu ]---\n" @@ -2864,7 +2863,7 @@ msgstr "" "nmcli <konf-flagga> <value> :: nmcli-konfiguration\n" "quit :: avsluta nmcli\n" -#: ../clients/cli/connections.c:8148 +#: ../clients/cli/connections.c:8144 #, c-format msgid "" "goto <setting>[.<prop>] | <prop> :: enter setting/property for editing\n" @@ -2884,7 +2883,7 @@ msgstr "" " nmcli connection> goto secondaries\n" " nmcli> goto ipv4.addresses\n" -#: ../clients/cli/connections.c:8155 +#: ../clients/cli/connections.c:8151 #, c-format msgid "" "remove <setting>[.<prop>] :: remove setting or reset property value\n" @@ -2906,7 +2905,7 @@ msgstr "" "Exempel: nmcli> remove wifi-sec\n" " nmcli> remove eth.mtu\n" -#: ../clients/cli/connections.c:8162 +#: ../clients/cli/connections.c:8158 #, c-format msgid "" "set [<setting>.<prop> <value>] :: set property value\n" @@ -2921,7 +2920,7 @@ msgstr "" "\n" "Exempel: nmcli> set con.id My connection\n" -#: ../clients/cli/connections.c:8167 +#: ../clients/cli/connections.c:8163 #, c-format msgid "" "describe [<setting>.<prop>] :: describe property\n" @@ -2934,7 +2933,7 @@ msgstr "" "Visar egenskapsbeskrivning. Du kan titta i handboken för nm-settings(5) för " "att se alla NH-inställningar och egenskaper.\n" -#: ../clients/cli/connections.c:8172 +#: ../clients/cli/connections.c:8168 #, c-format msgid "" "print [all] :: print setting or connection values\n" @@ -2949,7 +2948,7 @@ msgstr "" "\n" "Exempel: nmcli ipv4> print all\n" -#: ../clients/cli/connections.c:8177 +#: ../clients/cli/connections.c:8173 #, c-format msgid "" "verify [all | fix] :: verify setting or connection validity\n" @@ -2975,7 +2974,7 @@ msgstr "" " nmcli> verify fix\n" " nmcli bond> verify\n" -#: ../clients/cli/connections.c:8186 +#: ../clients/cli/connections.c:8182 #, c-format msgid "" "save [persistent|temporary] :: save the connection\n" @@ -3001,7 +3000,7 @@ msgstr "" "Om du vill ta bort den sparade anslutningen helt\n" "måste profilen tas bort.\n" -#: ../clients/cli/connections.c:8197 +#: ../clients/cli/connections.c:8193 #, c-format msgid "" "activate [<ifname>] [/<ap>|<nsp>] :: activate the connection\n" @@ -3022,7 +3021,7 @@ msgstr "" "/<ap>|<nsp> - AP (Wi-Fi) eller NSP (WiMAX) (lägg till / i början när " "<grnamn> inte anges)\n" -#: ../clients/cli/connections.c:8204 ../clients/cli/connections.c:8363 +#: ../clients/cli/connections.c:8200 ../clients/cli/connections.c:8359 #, c-format msgid "" "back :: go to upper menu level\n" @@ -3031,7 +3030,7 @@ msgstr "" "back :: gå upp en menynivå\n" "\n" -#: ../clients/cli/connections.c:8207 +#: ../clients/cli/connections.c:8203 #, c-format msgid "" "help/? [<command>] :: help for the nmcli commands\n" @@ -3040,7 +3039,7 @@ msgstr "" "help/? [<kommando>] :: hjälp för nmcli-kommandot\n" "\n" -#: ../clients/cli/connections.c:8210 +#: ../clients/cli/connections.c:8206 #, c-format msgid "" "nmcli [<conf-option> <value>] :: nmcli configuration\n" @@ -3067,7 +3066,7 @@ msgstr "" " nmcli> nmcli save-confirmation no\n" " nmcli> nmcli prompt-color 3\n" -#: ../clients/cli/connections.c:8232 ../clients/cli/connections.c:8369 +#: ../clients/cli/connections.c:8228 ../clients/cli/connections.c:8365 #, c-format msgid "" "quit :: exit nmcli\n" @@ -3080,8 +3079,8 @@ msgstr "" "Kommandot avslutar nmcli. När anslutningen som redigerats inte sparas frågas " "användaren om att bekräfta åtgärden.\n" -#: ../clients/cli/connections.c:8237 ../clients/cli/connections.c:8374 -#: ../clients/cli/connections.c:8798 ../clients/cli/connections.c:9746 +#: ../clients/cli/connections.c:8233 ../clients/cli/connections.c:8370 +#: ../clients/cli/connections.c:8794 ../clients/cli/connections.c:9742 #, c-format msgid "Unknown command: '%s'\n" msgstr "Okänt kommando: ”%s”\n" @@ -3089,7 +3088,7 @@ msgstr "Okänt kommando: ”%s”\n" #. TRANSLATORS: do not translate command names and keywords before :: #. * However, you should translate terms enclosed in <>. #. -#: ../clients/cli/connections.c:8303 +#: ../clients/cli/connections.c:8299 #, c-format msgid "" "---[ Property menu ]---\n" @@ -3118,7 +3117,7 @@ msgstr "" "kommandobeskrivning\n" "quit :: avsluta nmcli\n" -#: ../clients/cli/connections.c:8328 +#: ../clients/cli/connections.c:8324 #, c-format msgid "" "set [<value>] :: set new value\n" @@ -3129,7 +3128,7 @@ msgstr "" "\n" "Detta kommando sätter angivet <värde> till denna egenskap\n" -#: ../clients/cli/connections.c:8332 +#: ../clients/cli/connections.c:8328 #, c-format msgid "" "add [<value>] :: append new value to the property\n" @@ -3144,7 +3143,7 @@ msgstr "" "egenskapen är av en behållartyp. För egenskaper med ett värde ersätts " "egenskapsvärdet (samma som ”set”).\n" -#: ../clients/cli/connections.c:8338 +#: ../clients/cli/connections.c:8334 #, c-format msgid "" "change :: change current value\n" @@ -3155,7 +3154,7 @@ msgstr "" "\n" "Visar aktuellt värde och tillåter redigering av det.\n" -#: ../clients/cli/connections.c:8342 +#: ../clients/cli/connections.c:8338 #, c-format msgid "" "remove [<value>|<index>|<option name>] :: delete the value\n" @@ -3190,7 +3189,7 @@ msgstr "" " nmcli bond.options> remove downdelay\n" "\n" -#: ../clients/cli/connections.c:8353 +#: ../clients/cli/connections.c:8349 #, c-format msgid "" "describe :: describe property\n" @@ -3203,7 +3202,7 @@ msgstr "" "Visar egenskapsbeskrivning. Se nm-settings(5)-handboken för att se alla NH-" "inställningar och egenskaper.\n" -#: ../clients/cli/connections.c:8358 +#: ../clients/cli/connections.c:8354 #, c-format msgid "" "print [property|setting|connection] :: print property (setting, connection) " @@ -3218,7 +3217,7 @@ msgstr "" "Visar egenskapsvärdet. Med argument kan du också visa värden för hela " "inställningen eller anslutningen.\n" -#: ../clients/cli/connections.c:8366 +#: ../clients/cli/connections.c:8362 #, c-format msgid "" "help/? [<command>] :: help for nmcli commands\n" @@ -3227,28 +3226,28 @@ msgstr "" "help/? [<kommando>] :: hjälp för nmcli-kommandon\n" "\n" -#: ../clients/cli/connections.c:8464 +#: ../clients/cli/connections.c:8460 #, c-format msgid "Error: Connection activation failed.\n" msgstr "Fel: Aktivering av anslutning misslyckades.\n" -#: ../clients/cli/connections.c:8547 +#: ../clients/cli/connections.c:8543 #, c-format msgid "Error: setting '%s' is mandatory and cannot be removed.\n" msgstr "Fel: inställningen ”%s” är obligatorisk och kan inte tas bort.\n" #. TRANSLATORS: status line in nmcli connection editor -#: ../clients/cli/connections.c:8565 +#: ../clients/cli/connections.c:8561 #, c-format msgid "[ Type: %s | Name: %s | UUID: %s | Dirty: %s | Temp: %s ]\n" msgstr "[ Typ: %s | Namn: %s | UUID: %s | Dirty: %s | Temp: %s ]\n" -#: ../clients/cli/connections.c:8601 +#: ../clients/cli/connections.c:8597 #, c-format msgid "The connection is not saved. Do you really want to quit? %s" msgstr "Anslutningen sparas inte. Vill du verkligen avsluta? %s" -#: ../clients/cli/connections.c:8650 +#: ../clients/cli/connections.c:8646 #, c-format msgid "" "The connection profile has been removed from another client. You may type " @@ -3257,66 +3256,66 @@ msgstr "" "Anslutningsprofilen har tagits bort från en annan klient. Du kan skriva " "”save” i huvudmenyn för att återställa den.\n" -#: ../clients/cli/connections.c:8675 ../clients/cli/connections.c:9097 -#: ../clients/cli/connections.c:9155 +#: ../clients/cli/connections.c:8671 ../clients/cli/connections.c:9093 +#: ../clients/cli/connections.c:9151 #, c-format msgid "Allowed values for '%s' property: %s\n" msgstr "Tillgängliga värden för ”%s”-egenskapen: %s\n" -#: ../clients/cli/connections.c:8679 ../clients/cli/connections.c:9101 -#: ../clients/cli/connections.c:9159 +#: ../clients/cli/connections.c:8675 ../clients/cli/connections.c:9097 +#: ../clients/cli/connections.c:9155 #, c-format msgid "Enter '%s' value: " msgstr "Ange ”%s”-värde: " -#: ../clients/cli/connections.c:8694 ../clients/cli/connections.c:8716 -#: ../clients/cli/connections.c:9105 ../clients/cli/connections.c:9164 +#: ../clients/cli/connections.c:8690 ../clients/cli/connections.c:8712 +#: ../clients/cli/connections.c:9101 ../clients/cli/connections.c:9160 #, c-format msgid "Error: failed to set '%s' property: %s\n" msgstr "Fel: misslyckades med att sätta ”%s”-egenskapen: %s\n" -#: ../clients/cli/connections.c:8710 +#: ../clients/cli/connections.c:8706 #, c-format msgid "Edit '%s' value: " msgstr "Redigera ”%s”-värde: " -#: ../clients/cli/connections.c:8739 +#: ../clients/cli/connections.c:8735 #, c-format msgid "Error: %s\n" msgstr "Fel: %s\n" -#: ../clients/cli/connections.c:8745 ../clients/cli/connections.c:9246 -#: ../clients/cli/connections.c:9294 +#: ../clients/cli/connections.c:8741 ../clients/cli/connections.c:9242 +#: ../clients/cli/connections.c:9290 #, c-format msgid "Error: failed to remove value of '%s': %s\n" msgstr "Fel: misslyckades med att ta bort värdet ”%s”: %s\n" -#: ../clients/cli/connections.c:8766 +#: ../clients/cli/connections.c:8762 #, c-format msgid "Unknown command argument: '%s'\n" msgstr "Okänt kommandoargument: ”%s”\n" -#: ../clients/cli/connections.c:8871 +#: ../clients/cli/connections.c:8867 #, c-format msgid "Available settings: %s\n" msgstr "Tillgängliga inställningar: %s\n" -#: ../clients/cli/connections.c:8883 +#: ../clients/cli/connections.c:8879 #, c-format msgid "Error: invalid setting name; %s\n" msgstr "Fel: ogiltigt namn på inställning; %s\n" -#: ../clients/cli/connections.c:8900 +#: ../clients/cli/connections.c:8896 #, c-format msgid "Available properties: %s\n" msgstr "Tillgängliga egenskaper: %s\n" -#: ../clients/cli/connections.c:8908 +#: ../clients/cli/connections.c:8904 #, c-format msgid "Error: property %s\n" msgstr "Fel: egenskapen %s\n" -#: ../clients/cli/connections.c:8949 +#: ../clients/cli/connections.c:8945 #, c-format msgid "" "Saving the connection with 'autoconnect=yes'. That might result in an " @@ -3327,12 +3326,12 @@ msgstr "" "anslutningen aktiveras omedelbart.\n" "Vill du fortfarande spara? %s" -#: ../clients/cli/connections.c:9039 +#: ../clients/cli/connections.c:9035 #, c-format msgid "You may edit the following settings: %s\n" msgstr "Du kan redigera följande inställningar: %s\n" -#: ../clients/cli/connections.c:9067 +#: ../clients/cli/connections.c:9063 #, c-format msgid "" "The connection profile has been removed from another client. You may type " @@ -3341,219 +3340,219 @@ msgstr "" "Anslutningsprofilen har tagits bort från en annan klient. Du kan skriva " "”save” för att återställa den.\n" -#: ../clients/cli/connections.c:9109 ../clients/cli/connections.c:9339 +#: ../clients/cli/connections.c:9105 ../clients/cli/connections.c:9335 #, c-format msgid "Error: no setting selected; valid are [%s]\n" msgstr "Fel: ingen inställning vald; giltiga är [%s]\n" -#: ../clients/cli/connections.c:9110 +#: ../clients/cli/connections.c:9106 #, c-format msgid "use 'goto <setting>' first, or 'set <setting>.<property>'\n" msgstr "" "använd ”goto <inställning>” först eller ”set <inställning>.<egenskap>”\n" -#: ../clients/cli/connections.c:9124 ../clients/cli/connections.c:9273 -#: ../clients/cli/connections.c:9361 +#: ../clients/cli/connections.c:9120 ../clients/cli/connections.c:9269 +#: ../clients/cli/connections.c:9357 #, c-format msgid "Error: invalid setting argument '%s'; valid are [%s]\n" msgstr "Fel: ogiltigt argument för inställningen ”%s”; giltiga är [%s]\n" -#: ../clients/cli/connections.c:9134 +#: ../clients/cli/connections.c:9130 #, c-format msgid "Error: missing setting for '%s' property\n" msgstr "Fel: saknar inställning för egenskapen ”%s”\n" -#: ../clients/cli/connections.c:9141 +#: ../clients/cli/connections.c:9137 #, c-format msgid "Error: invalid property: %s\n" msgstr "Fel: ogiltig egenskap: %s\n" -#: ../clients/cli/connections.c:9194 +#: ../clients/cli/connections.c:9190 #, c-format msgid "Error: unknown setting '%s'\n" msgstr "Fel: Okänd inställning: ”%s”\n" -#: ../clients/cli/connections.c:9207 +#: ../clients/cli/connections.c:9203 #, c-format msgid "You may edit the following properties: %s\n" msgstr "Du kan redigera följande egenskaper: %s\n" -#: ../clients/cli/connections.c:9251 +#: ../clients/cli/connections.c:9247 #, c-format msgid "Error: no argument given; valid are [%s]\n" msgstr "Fel: inga argument givna; giltiga är [%s]\n" -#: ../clients/cli/connections.c:9270 +#: ../clients/cli/connections.c:9266 #, c-format msgid "Setting '%s' is not present in the connection.\n" msgstr "Inställningen ”%s” finns inte i anslutningen.\n" -#: ../clients/cli/connections.c:9315 +#: ../clients/cli/connections.c:9311 #, c-format msgid "Error: %s properties, nor it is a setting name.\n" msgstr "Fel: %s-egenskaper, inte heller ett inställningsnamn.\n" -#: ../clients/cli/connections.c:9340 +#: ../clients/cli/connections.c:9336 #, c-format msgid "use 'goto <setting>' first, or 'describe <setting>.<property>'\n" msgstr "" "använd ”goto <inställning>” först, eller ”describe <inställning>." "<egenskap>”\n" -#: ../clients/cli/connections.c:9389 +#: ../clients/cli/connections.c:9385 #, c-format msgid "Error: invalid property: %s, neither a valid setting name.\n" msgstr "" "Fel: ogiltig egenskap: %s, och inte heller ett giltigt inställningsnamn.\n" -#: ../clients/cli/connections.c:9421 +#: ../clients/cli/connections.c:9417 #, c-format msgid "Error: unknown setting: '%s'\n" msgstr "Fel: okänd inställning: ”%s”\n" -#: ../clients/cli/connections.c:9426 +#: ../clients/cli/connections.c:9422 #, c-format msgid "Error: '%s' setting not present in the connection\n" msgstr "Fel: inställningen ”%s” finns inte i anslutningen\n" -#: ../clients/cli/connections.c:9454 +#: ../clients/cli/connections.c:9450 #, c-format msgid "Error: invalid property: %s%s\n" msgstr "Fel: ogiltig egenskap: %s%s\n" -#: ../clients/cli/connections.c:9456 +#: ../clients/cli/connections.c:9452 msgid ", neither a valid setting name" msgstr ", inte heller ett giltigt inställningsnamn" -#: ../clients/cli/connections.c:9473 +#: ../clients/cli/connections.c:9469 #, c-format msgid "Invalid verify option: %s\n" msgstr "Ogiltigt verify-argument ”%s”\n" -#: ../clients/cli/connections.c:9481 +#: ../clients/cli/connections.c:9477 #, c-format msgid "Verify setting '%s': %s\n" msgstr "Verifiera inställningen ”%s”: %s\n" -#: ../clients/cli/connections.c:9496 +#: ../clients/cli/connections.c:9492 #, c-format msgid "Verify connection: %s\n" msgstr "Verifiera anslutningen: %s\n" -#: ../clients/cli/connections.c:9499 +#: ../clients/cli/connections.c:9495 #, c-format msgid "The error cannot be fixed automatically.\n" msgstr "Felet kan inte lagas automatiskt.\n" -#: ../clients/cli/connections.c:9516 +#: ../clients/cli/connections.c:9512 #, c-format msgid "Error: invalid argument '%s'\n" msgstr "Fel: ogiltigt argument ”%s”\n" -#: ../clients/cli/connections.c:9549 +#: ../clients/cli/connections.c:9545 #, c-format msgid "Error: Failed to save '%s' (%s) connection: %s\n" msgstr "Fel: Misslyckades med att spara ”%s” (%s)-anslutning %s\n" -#: ../clients/cli/connections.c:9556 +#: ../clients/cli/connections.c:9552 #, c-format msgid "Connection '%s' (%s) successfully saved.\n" msgstr "Anslutningen ”%s” (%s) sparades.\n" -#: ../clients/cli/connections.c:9557 +#: ../clients/cli/connections.c:9553 #, c-format msgid "Connection '%s' (%s) successfully updated.\n" msgstr "Anslutningen ”%s” (%s) uppdaterades.\n" -#: ../clients/cli/connections.c:9590 +#: ../clients/cli/connections.c:9586 #, c-format msgid "Error: connection verification failed: %s\n" msgstr "Fel: verifiering av anslutning misslyckades: %s\n" -#: ../clients/cli/connections.c:9591 +#: ../clients/cli/connections.c:9587 msgid "(unknown error)" msgstr "(okänt fel)" -#: ../clients/cli/connections.c:9592 +#: ../clients/cli/connections.c:9588 #, c-format msgid "You may try running 'verify fix' to fix errors.\n" msgstr "Du kan prova att köra ”verify fix” för att laga fel.\n" -#: ../clients/cli/connections.c:9614 +#: ../clients/cli/connections.c:9610 #, c-format msgid "Error: connection is not saved. Type 'save' first.\n" msgstr "Fel: anslutningen sparas ej. Skriv ”save” först.\n" -#: ../clients/cli/connections.c:9618 +#: ../clients/cli/connections.c:9614 #, c-format msgid "Error: connection is not valid: %s\n" msgstr "Fel: anslutningen är inte giltig: %s\n" -#: ../clients/cli/connections.c:9628 +#: ../clients/cli/connections.c:9624 #, c-format msgid "Error: Cannot activate connection: %s.\n" msgstr "Fel: Kan inte aktivera anslutningen: %s.\n" -#: ../clients/cli/connections.c:9638 +#: ../clients/cli/connections.c:9634 #, c-format msgid "Error: Failed to activate '%s' (%s) connection: %s\n" msgstr "Fel: Misslyckades med att aktivera ”%s” (%s)-anslutning: %s\n" -#: ../clients/cli/connections.c:9644 +#: ../clients/cli/connections.c:9640 #, c-format msgid "Monitoring connection activation (press any key to continue)\n" msgstr "" "Övervakar anslutningsaktivering (tryck valfri tangent för att fortsätta)\n" -#: ../clients/cli/connections.c:9682 +#: ../clients/cli/connections.c:9678 #, c-format msgid "Error: status-line: %s\n" msgstr "Fel: status-line: %s\n" -#: ../clients/cli/connections.c:9690 +#: ../clients/cli/connections.c:9686 #, c-format msgid "Error: save-confirmation: %s\n" msgstr "Fel: save-confirmation: %s\n" -#: ../clients/cli/connections.c:9698 +#: ../clients/cli/connections.c:9694 #, c-format msgid "Error: show-secrets: %s\n" msgstr "Fel: show-secrets: %s\n" -#: ../clients/cli/connections.c:9707 +#: ../clients/cli/connections.c:9703 #, c-format msgid "Error: bad color: %s\n" msgstr "Fel: dålig färg: %s\n" -#: ../clients/cli/connections.c:9721 +#: ../clients/cli/connections.c:9717 #, c-format msgid "Current nmcli configuration:\n" msgstr "Aktuell nmcli-konfiguration:\n" -#: ../clients/cli/connections.c:9731 +#: ../clients/cli/connections.c:9727 #, c-format msgid "Invalid configuration option '%s'; allowed [%s]\n" msgstr "Ogiltigt konfigurationsalternativ ”%s”; tillåtet [%s]\n" -#: ../clients/cli/connections.c:9986 +#: ../clients/cli/connections.c:9982 #, c-format msgid "Error: only one of 'id', uuid, or 'path' can be provided." msgstr "Fel: endast en av ”id”, uuid eller ”path” kan ges." -#: ../clients/cli/connections.c:9998 ../clients/cli/connections.c:10175 -#: ../clients/cli/connections.c:10182 ../clients/cli/connections.c:10310 -#: ../clients/cli/connections.c:10786 +#: ../clients/cli/connections.c:9994 ../clients/cli/connections.c:10171 +#: ../clients/cli/connections.c:10178 ../clients/cli/connections.c:10306 +#: ../clients/cli/connections.c:10782 #, c-format msgid "Error: Unknown connection '%s'." msgstr "Fel: Okänd anslutning: ”%s”." -#: ../clients/cli/connections.c:10016 +#: ../clients/cli/connections.c:10012 #, c-format msgid "Warning: editing existing connection '%s'; 'type' argument is ignored\n" msgstr "" "Varning: redigerar befintliga anslutningen ”%s”; ”type”-argument ignoreras\n" -#: ../clients/cli/connections.c:10019 +#: ../clients/cli/connections.c:10015 #, c-format msgid "" "Warning: editing existing connection '%s'; 'con-name' argument is ignored\n" @@ -3561,223 +3560,223 @@ msgstr "" "Varning: redigerar befintliga anslutningen ”%s”; ”con-name”-argument " "ignoreras\n" -#: ../clients/cli/connections.c:10033 +#: ../clients/cli/connections.c:10029 #, c-format msgid "Valid connection types: %s\n" msgstr "Giltiga anslutningstyper: %s\n" -#: ../clients/cli/connections.c:10035 +#: ../clients/cli/connections.c:10031 #, c-format msgid "Error: invalid connection type; %s\n" msgstr "Fel: ogiltig anslutningstyp: %s\n" -#: ../clients/cli/connections.c:10074 +#: ../clients/cli/connections.c:10070 #, c-format msgid "===| nmcli interactive connection editor |===" msgstr "===| nmcli interaktiv anslutningsredigerare |===" -#: ../clients/cli/connections.c:10077 +#: ../clients/cli/connections.c:10073 #, c-format msgid "Editing existing '%s' connection: '%s'" msgstr "Redigerar befintlig ”%s”-anslutning: ”%s”" -#: ../clients/cli/connections.c:10079 +#: ../clients/cli/connections.c:10075 #, c-format msgid "Adding a new '%s' connection" msgstr "Lägger till en ny ”%s”-anslutning" -#: ../clients/cli/connections.c:10081 +#: ../clients/cli/connections.c:10077 #, c-format msgid "Type 'help' or '?' for available commands." msgstr "Skriv ”help” eller ”?” för tillgängliga kommandon." -#: ../clients/cli/connections.c:10083 +#: ../clients/cli/connections.c:10079 #, c-format msgid "Type 'describe [<setting>.<prop>]' for detailed property description." msgstr "" "Skriv ”describe [<inställning>.<egenskap>]” för en detaljerad " "egenskapsbeskrivning." -#: ../clients/cli/connections.c:10121 +#: ../clients/cli/connections.c:10117 #, c-format msgid "Error: Failed to modify connection '%s': %s" msgstr "Fel: Misslyckades med att ändra anslutningen ”%s”: %s" -#: ../clients/cli/connections.c:10128 +#: ../clients/cli/connections.c:10124 #, c-format msgid "Connection '%s' (%s) successfully modified.\n" msgstr "Anslutningen ”%s” (%s) ändrades.\n" -#: ../clients/cli/connections.c:10150 ../clients/cli/connections.c:10266 -#: ../clients/cli/connections.c:10643 ../clients/cli/connections.c:10751 +#: ../clients/cli/connections.c:10146 ../clients/cli/connections.c:10262 +#: ../clients/cli/connections.c:10639 ../clients/cli/connections.c:10747 #, c-format msgid "Error: No arguments provided." msgstr "Fel: Inga argument angavs." -#: ../clients/cli/connections.c:10169 ../clients/cli/connections.c:10298 -#: ../clients/cli/connections.c:10780 +#: ../clients/cli/connections.c:10165 ../clients/cli/connections.c:10294 +#: ../clients/cli/connections.c:10776 #, c-format msgid "Error: connection ID is missing." msgstr "Fel: anslutnings-ID saknas." -#: ../clients/cli/connections.c:10232 +#: ../clients/cli/connections.c:10228 #, c-format msgid "%s (%s) cloned as %s (%s).\n" msgstr "%s (%s) klonad som %s (%s).\n" -#: ../clients/cli/connections.c:10264 +#: ../clients/cli/connections.c:10260 msgid "New connection name: " msgstr "Nytt anslutningsnamn: " -#: ../clients/cli/connections.c:10285 ../clients/cli/connections.c:10303 +#: ../clients/cli/connections.c:10281 ../clients/cli/connections.c:10299 #, c-format msgid "Error: <new name> argument is missing." msgstr "Fel: <nytt namn>-argument saknas." -#: ../clients/cli/connections.c:10291 +#: ../clients/cli/connections.c:10287 #, c-format msgid "Error: unexpected extra argument '%s'." msgstr "Fel: oväntat extra argument ”%s”." -#: ../clients/cli/connections.c:10360 +#: ../clients/cli/connections.c:10356 #, c-format msgid "Error: not all connections deleted." msgstr "Fel: alla anslutningar är inte borttagna." -#: ../clients/cli/connections.c:10361 +#: ../clients/cli/connections.c:10357 #, c-format msgid "Error: Connection deletion failed: %s" msgstr "Fel: Borttagning av anslutningen misslyckades: %s" -#: ../clients/cli/connections.c:10423 ../clients/cli/connections.c:10551 +#: ../clients/cli/connections.c:10419 ../clients/cli/connections.c:10547 #, c-format msgid "Error: unknown connection '%s'\n" msgstr "Fel: Okänd anslutning: ”%s”\n" -#: ../clients/cli/connections.c:10437 +#: ../clients/cli/connections.c:10433 #, c-format msgid "Error: no connection provided." msgstr "Fel: ingen anslutning tillhandahållen." #. truncate trailing ", " -#: ../clients/cli/connections.c:10462 +#: ../clients/cli/connections.c:10458 #, c-format msgid "Error: cannot delete unknown connection(s): %s." msgstr "Fel: kan inte ta bort okänd(a) anslutning(ar): %s." -#: ../clients/cli/connections.c:10474 +#: ../clients/cli/connections.c:10470 #, c-format msgid "%s: connection profile changed\n" msgstr "%s: anslutningsprofil ändrad\n" -#: ../clients/cli/connections.c:10500 +#: ../clients/cli/connections.c:10496 #, c-format msgid "%s: connection profile created\n" msgstr "%s: anslutningsprofil skapad\n" -#: ../clients/cli/connections.c:10509 +#: ../clients/cli/connections.c:10505 #, c-format msgid "%s: connection profile removed\n" msgstr "%s: anslutningsprofil borttagen\n" -#: ../clients/cli/connections.c:10552 +#: ../clients/cli/connections.c:10548 #, c-format msgid "Error: not all connections found." msgstr "Fel: hittade inte alla anslutningar." -#: ../clients/cli/connections.c:10575 +#: ../clients/cli/connections.c:10571 #, c-format msgid "Error: failed to reload connections: %s." msgstr "Fel: Misslyckades med att läsa om anslutningar: %s." -#: ../clients/cli/connections.c:10607 +#: ../clients/cli/connections.c:10603 #, c-format msgid "Error: failed to load connection: %s." msgstr "Fel: misslyckades med att läsa in anslutningen: %s." -#: ../clients/cli/connections.c:10615 +#: ../clients/cli/connections.c:10611 #, c-format msgid "Could not load file '%s'\n" msgstr "Kunde inte läsa in filen: ”%s”\n" -#: ../clients/cli/connections.c:10624 +#: ../clients/cli/connections.c:10620 msgid "File to import: " msgstr "Fil att importera: " -#: ../clients/cli/connections.c:10659 +#: ../clients/cli/connections.c:10655 #, c-format msgid "Warning: 'type' already specified, ignoring extra one.\n" msgstr "Varning: ”type” redan angiven, ignorerar extra förekomst.\n" -#: ../clients/cli/connections.c:10670 +#: ../clients/cli/connections.c:10666 #, c-format msgid "Warning: 'file' already specified, ignoring extra one.\n" msgstr "Varning: ”file” redan angiven, ignorerar extra förekomst.\n" -#: ../clients/cli/connections.c:10672 +#: ../clients/cli/connections.c:10668 #, c-format msgid "Unknown parameter: %s" msgstr "Okänd parameter: %s" -#: ../clients/cli/connections.c:10687 +#: ../clients/cli/connections.c:10683 #, c-format msgid "Error: 'file' argument is required." msgstr "Fel: ”file”-argument krävs." -#: ../clients/cli/connections.c:10695 ../clients/cli/connections.c:10802 +#: ../clients/cli/connections.c:10691 ../clients/cli/connections.c:10798 #, c-format msgid "Error: failed to load VPN plugin: %s." msgstr "Fel: misslyckades med att läsa in VPN-insticksmodul: %s." -#: ../clients/cli/connections.c:10703 +#: ../clients/cli/connections.c:10699 #, c-format msgid "Error: failed to import '%s': %s." msgstr "Fel: misslyckades med att importera ”%s”: %s." -#: ../clients/cli/connections.c:10749 +#: ../clients/cli/connections.c:10745 msgid "Output file name: " msgstr "Utdatafilnamn: " -#: ../clients/cli/connections.c:10773 +#: ../clients/cli/connections.c:10769 #, c-format msgid "Error: unknown extra argument: '%s'." msgstr "Fel: okänt extra argument: ”%s”." -#: ../clients/cli/connections.c:10793 +#: ../clients/cli/connections.c:10789 #, c-format msgid "Error: the connection is not VPN." msgstr "Fel: anslutningen är inte VPN." -#: ../clients/cli/connections.c:10814 +#: ../clients/cli/connections.c:10810 #, c-format msgid "Error: failed to create temporary file %s." msgstr "Fel: misslyckades med att skapa temporära filen %s." -#: ../clients/cli/connections.c:10823 +#: ../clients/cli/connections.c:10819 #, c-format msgid "Error: failed to export '%s': %s." msgstr "Fel: misslyckades med att exportera ”%s”: %s" -#: ../clients/cli/connections.c:10834 +#: ../clients/cli/connections.c:10830 #, c-format msgid "Error: failed to read temporary file '%s': %s." msgstr "Fel: misslyckades med att läsa temporära filen ”%s”: %s." -#: ../clients/cli/connections.c:10980 +#: ../clients/cli/connections.c:10976 #, c-format msgid "incorrect string '%s' of '--order' option" msgstr "fel sträng ”%s” för flaggan ”--order”" -#: ../clients/cli/connections.c:11006 +#: ../clients/cli/connections.c:11002 #, c-format msgid "incorrect item '%s' in '--order' option" msgstr "fel objekt ”%s” i flaggan ”--order”" -#: ../clients/cli/connections.c:11090 +#: ../clients/cli/connections.c:11089 msgid "'--order' argument is missing" msgstr "”--order”-argumentet saknas" -#: ../clients/cli/connections.c:11155 +#: ../clients/cli/connections.c:11154 #, c-format msgid "Error: '%s' is not valid 'connection' command." msgstr "Fel: ”%s” är inte ett giltigt ”connection”-kommando." @@ -4210,7 +4209,7 @@ msgid "" "\n" " connect <ifname>\n" "\n" -" reapply <ifname>\n" +" reapply <ifname> ...\n" "\n" " disconnect <ifname> ...\n" "\n" @@ -4246,7 +4245,7 @@ msgstr "" "\n" " connect <grnamn>\n" "\n" -" reapply <grnamn>\n" +" reapply <grnamn> …\n" "\n" " disconnect <grnamn> …\n" "\n" @@ -4347,7 +4346,7 @@ msgstr "" msgid "" "Usage: nmcli device reapply { ARGUMENTS | help }\n" "\n" -"ARGUMENTS := <ifname>\n" +"ARGUMENTS := <ifname> ...\n" "\n" "Attempts to update device with changes to the currently active connection\n" "made since it was last applied.\n" @@ -4355,7 +4354,7 @@ msgid "" msgstr "" "Användning: nmcli device reapply { ARGUMENT | help }\n" "\n" -"ARGUMENT := <grnamn>\n" +"ARGUMENT := <grnamn> …\n" "\n" "Försöker uppdatera enhet med ändringar till den aktuellt aktiva " "anslutningen\n" @@ -4581,23 +4580,23 @@ msgstr "" "\n" #: ../clients/cli/devices.c:527 ../clients/cli/devices.c:1676 -#: ../clients/cli/devices.c:1685 ../clients/cli/devices.c:1876 -#: ../clients/cli/devices.c:2081 ../clients/cli/devices.c:2088 +#: ../clients/cli/devices.c:1685 ../clients/cli/devices.c:1879 +#: ../clients/cli/devices.c:2103 ../clients/cli/devices.c:2110 #, c-format msgid "Error: No interface specified." msgstr "Fel: Inget gränssnitt angivet." -#: ../clients/cli/devices.c:547 +#: ../clients/cli/devices.c:547 ../clients/cli/devices.c:1899 #, c-format msgid "Warning: argument '%s' is duplicated.\n" msgstr "Varning: argumentet ”%s” är duplicerat.\n" -#: ../clients/cli/devices.c:549 +#: ../clients/cli/devices.c:549 ../clients/cli/devices.c:1901 #, c-format msgid "Error: Device '%s' not found.\n" msgstr "Fel: Enheten ”%s” hittades inte.\n" -#: ../clients/cli/devices.c:550 +#: ../clients/cli/devices.c:550 ../clients/cli/devices.c:1902 #, c-format msgid "Error: not all devices found." msgstr "Fel: hittade inte alla enheter." @@ -4672,14 +4671,14 @@ msgstr "Fel: ”device status”: %s" msgid "Status of devices" msgstr "Status för enheter" -#: ../clients/cli/devices.c:1380 ../clients/cli/devices.c:3487 +#: ../clients/cli/devices.c:1380 ../clients/cli/devices.c:3509 #, c-format msgid "Error: invalid extra argument '%s'." msgstr "Fel: ogiltigt extra argument: ”%s”." #: ../clients/cli/devices.c:1397 ../clients/cli/devices.c:1707 -#: ../clients/cli/devices.c:2104 ../clients/cli/devices.c:2374 -#: ../clients/cli/devices.c:3526 +#: ../clients/cli/devices.c:2126 ../clients/cli/devices.c:2396 +#: ../clients/cli/devices.c:3548 #, c-format msgid "Error: Device '%s' not found." msgstr "Fel: Enheten ”%s” hittades inte." @@ -4745,7 +4744,7 @@ msgid "Error: extra argument not allowed: '%s'." msgstr "Fel: extra argument saknas: ”%s”." #: ../clients/cli/devices.c:1776 ../clients/cli/devices.c:1791 -#: ../clients/cli/devices.c:1942 +#: ../clients/cli/devices.c:1964 #, c-format msgid "Device '%s' successfully disconnected.\n" msgstr "Lyckades: Enheten ”%s” kopplades från.\n" @@ -4757,94 +4756,95 @@ msgstr "Enheten ”%s” togs bort.\n" #: ../clients/cli/devices.c:1838 #, c-format -msgid "Error: Reapplying connection to device '%s' (%s) failed: %s" -msgstr "Fel: Uppdatering av anslutning till enheten ”%s” (%s) misslyckades: %s" +msgid "Error: not all connections reapplied." +msgstr "Fel: alla anslutningar har inte uppdaterats." -#: ../clients/cli/devices.c:1848 +#: ../clients/cli/devices.c:1839 #, c-format -msgid "Connection successfully reapplied to device '%s'.\n" -msgstr "Anslutning uppdaterades till enheten ”%s”.\n" +msgid "Error: Reapplying connection to device '%s' (%s) failed: %s\n" +msgstr "" +"Fel: Uppdatering av anslutning till enheten ”%s” (%s) misslyckades: %s\n" -#: ../clients/cli/devices.c:1885 +#: ../clients/cli/devices.c:1849 #, c-format -msgid "Error: unsupported argument '%s'." -msgstr "Fel: argument ”%s” stöds inte." +msgid "Connection successfully reapplied to device '%s'.\n" +msgstr "Anslutning uppdaterades till enheten ”%s”.\n" -#: ../clients/cli/devices.c:1899 +#: ../clients/cli/devices.c:1912 #, c-format -msgid "Error: device '%s' not found." -msgstr "Fel: enheten ”%s” hittades inte." +msgid "Error: no valid device provided." +msgstr "Fel: ingen giltig enhet tillhandahållen." -#: ../clients/cli/devices.c:1927 +#: ../clients/cli/devices.c:1949 #, c-format msgid "Error: not all devices disconnected." msgstr "Fel: alla anslutningar inte frånkopplade." -#: ../clients/cli/devices.c:1928 +#: ../clients/cli/devices.c:1950 #, c-format msgid "Error: Device '%s' (%s) disconnecting failed: %s\n" msgstr "Fel: Frånkoppling av enheten ”%s” (%s) misslyckades: %s\n" -#: ../clients/cli/devices.c:2003 +#: ../clients/cli/devices.c:2025 #, c-format msgid "Error: not all devices deleted." msgstr "Fel: alla enheter inte borttagna." -#: ../clients/cli/devices.c:2004 +#: ../clients/cli/devices.c:2026 #, c-format msgid "Error: Device '%s' (%s) deletion failed: %s\n" msgstr "Fel: Borttagning av enheten ”%s” (%s) misslyckades: %s\n" -#: ../clients/cli/devices.c:2110 +#: ../clients/cli/devices.c:2132 #, c-format msgid "Error: No property specified." msgstr "Fel: Ingen egenskap angiven." -#: ../clients/cli/devices.c:2122 ../clients/cli/devices.c:2137 +#: ../clients/cli/devices.c:2144 ../clients/cli/devices.c:2159 #, c-format msgid "Error: '%s' argument is missing." msgstr "Fel: ”%s”-argument saknas." -#: ../clients/cli/devices.c:2127 +#: ../clients/cli/devices.c:2149 #, c-format msgid "Error: 'managed': %s." msgstr "Fel: ”managed”: %s." -#: ../clients/cli/devices.c:2152 +#: ../clients/cli/devices.c:2174 #, c-format msgid "Error: property '%s' is not known." msgstr "Fel: egenskapen ”%s” är okänd." -#: ../clients/cli/devices.c:2198 +#: ../clients/cli/devices.c:2220 #, c-format msgid "%s: using connection '%s'\n" msgstr "%s: använder anslutningen ”%s”\n" -#: ../clients/cli/devices.c:2224 +#: ../clients/cli/devices.c:2246 #, c-format msgid "%s: device created\n" msgstr "%s: enhet skapad\n" -#: ../clients/cli/devices.c:2231 +#: ../clients/cli/devices.c:2253 #, c-format msgid "%s: device removed\n" msgstr "%s: enhet borttagen\n" -#: ../clients/cli/devices.c:2317 +#: ../clients/cli/devices.c:2339 msgid "Wi-Fi scan list" msgstr "Trådlös avsökningslista" -#: ../clients/cli/devices.c:2355 +#: ../clients/cli/devices.c:2377 #, c-format msgid "Error: 'device wifi': %s" msgstr "Fel: ”device wifi”: %s" -#: ../clients/cli/devices.c:2397 ../clients/cli/devices.c:2478 +#: ../clients/cli/devices.c:2419 ../clients/cli/devices.c:2500 #, c-format msgid "Error: Access point with bssid '%s' not found." msgstr "Fel: Accesspunkt med bssid ”%s” hittades inte." -#: ../clients/cli/devices.c:2424 +#: ../clients/cli/devices.c:2446 #, c-format msgid "" "Error: Device '%s' was not recognized as a Wi-Fi device, check " @@ -4853,27 +4853,27 @@ msgstr "" "Fel: Enheten ”%s” kändes inte igen som en trådlös enhet, kontrollera " "insticksmodulen NetworkManager Wi-Fi." -#: ../clients/cli/devices.c:2426 ../clients/cli/devices.c:2758 -#: ../clients/cli/devices.c:3178 ../clients/cli/devices.c:3327 +#: ../clients/cli/devices.c:2448 ../clients/cli/devices.c:2780 +#: ../clients/cli/devices.c:3200 ../clients/cli/devices.c:3349 #, c-format msgid "Error: Device '%s' is not a Wi-Fi device." msgstr "Fel: Enheten ”%s” är inte en trådlös enhet." -#: ../clients/cli/devices.c:2638 +#: ../clients/cli/devices.c:2660 msgid "SSID or BSSID: " msgstr "SSID eller BSSID: " -#: ../clients/cli/devices.c:2643 +#: ../clients/cli/devices.c:2665 #, c-format msgid "Error: SSID or BSSID are missing." msgstr "Fel: SSID eller BSSID saknas." -#: ../clients/cli/devices.c:2667 +#: ../clients/cli/devices.c:2689 #, c-format msgid "Error: bssid argument value '%s' is not a valid BSSID." msgstr "Fel: bssid-argumentvärdet ”%s” är inte ett giltigt BSSID." -#: ../clients/cli/devices.c:2691 +#: ../clients/cli/devices.c:2713 #, c-format msgid "" "Error: wep-key-type argument value '%s' is invalid, use 'key' or 'phrase'." @@ -4881,44 +4881,44 @@ msgstr "" "Fel: wep-key-type-argumentvärdet ”%s” är ogiltigt, använd ”key” eller " "”phrase”." -#: ../clients/cli/devices.c:2711 ../clients/cli/devices.c:2724 +#: ../clients/cli/devices.c:2733 ../clients/cli/devices.c:2746 #, c-format msgid "Error: %s: %s." msgstr "Fel: %s %s." -#: ../clients/cli/devices.c:2739 +#: ../clients/cli/devices.c:2761 #, c-format msgid "Error: BSSID to connect to (%s) differs from bssid argument (%s)." msgstr "" "Fel: BSSID att ansluta till (%s) skiljer sig från bssid-argumentet (%s)." -#: ../clients/cli/devices.c:2745 +#: ../clients/cli/devices.c:2767 #, c-format msgid "Error: Parameter '%s' is neither SSID nor BSSID." msgstr "Fel: Parameter ”%s” är varken SSID eller BSSID." -#: ../clients/cli/devices.c:2760 ../clients/cli/devices.c:3180 -#: ../clients/cli/devices.c:3329 +#: ../clients/cli/devices.c:2782 ../clients/cli/devices.c:3202 +#: ../clients/cli/devices.c:3351 #, c-format msgid "Error: No Wi-Fi device found." msgstr "Fel: Ingen trådlös enhet hittades." -#: ../clients/cli/devices.c:2780 +#: ../clients/cli/devices.c:2802 #, c-format msgid "Error: Failed to scan hidden SSID: %s." msgstr "Fel: Misslyckades att söka av dolt SSID: %s." -#: ../clients/cli/devices.c:2805 +#: ../clients/cli/devices.c:2827 #, c-format msgid "Error: No network with SSID '%s' found." msgstr "Fel: Inget nätverk med SSID ”%s” hittades." -#: ../clients/cli/devices.c:2807 +#: ../clients/cli/devices.c:2829 #, c-format msgid "Error: No access point with BSSID '%s' found." msgstr "Fel: Ingen accesspunkt med BSSID ”%s” hittades." -#: ../clients/cli/devices.c:2849 +#: ../clients/cli/devices.c:2871 #, c-format msgid "" "Warning: '%s' should be SSID for hidden APs; but it looks like a BSSID.\n" @@ -4926,87 +4926,87 @@ msgstr "" "Varning: ”%s” borde vara SSID för dolda accesspunkter, men det ser ut som " "ett BSSID.\n" -#: ../clients/cli/devices.c:2863 +#: ../clients/cli/devices.c:2885 msgid "Password: " msgstr "Lösenord: " -#: ../clients/cli/devices.c:3012 +#: ../clients/cli/devices.c:3034 #, c-format msgid "'%s' is not valid WPA PSK" msgstr "”%s” inte giltig WPA PSK" -#: ../clients/cli/devices.c:3029 +#: ../clients/cli/devices.c:3051 #, c-format msgid "'%s' is not valid WEP key (it should be 5 or 13 ASCII chars)" msgstr "”%s” är inte en giltig WEP-nyckel (ska vara 5 eller 13 ASCII-tecken)" -#: ../clients/cli/devices.c:3045 +#: ../clients/cli/devices.c:3067 #, c-format msgid "Hotspot password: %s\n" msgstr "Lösenord för surfzon: %s\n" -#: ../clients/cli/devices.c:3103 +#: ../clients/cli/devices.c:3125 #, c-format msgid "Error: ssid is too long." msgstr "Fel: ssid är för långt." -#: ../clients/cli/devices.c:3115 +#: ../clients/cli/devices.c:3137 #, c-format msgid "Error: band argument value '%s' is invalid; use 'a' or 'bg'." msgstr "Fel: argumentvärdet ”%s” för band är ogiltigt, använd ”a” eller ”bg”." -#: ../clients/cli/devices.c:3139 +#: ../clients/cli/devices.c:3161 #, c-format msgid "Error: Unknown parameter %s." msgstr "Fel: Okänd parameter %s." -#: ../clients/cli/devices.c:3158 +#: ../clients/cli/devices.c:3180 #, c-format msgid "Error: channel requires band too." msgstr "Fel: kanal kräver även band." -#: ../clients/cli/devices.c:3164 +#: ../clients/cli/devices.c:3186 #, c-format msgid "Error: channel '%s' not valid for band '%s'." msgstr "Fel: kanal ”%s” är inte giltig för bandet ”%s”." -#: ../clients/cli/devices.c:3192 +#: ../clients/cli/devices.c:3214 #, c-format msgid "Error: Device '%s' supports neither AP nor Ad-Hoc mode." msgstr "Fel: Enheten ”%s” stöder varken accesspunkts- eller Ad-Hoc-läge." -#: ../clients/cli/devices.c:3227 +#: ../clients/cli/devices.c:3249 #, c-format msgid "Error: Invalid 'password': %s." msgstr "Fel: ogiltigt ”password”: %s." # flaggan "ssid" kan upprepas -#: ../clients/cli/devices.c:3296 +#: ../clients/cli/devices.c:3318 #, c-format msgid "Error: '%s' cannot repeat." msgstr "Fel: ”%s” kan inte upprepas." -#: ../clients/cli/devices.c:3377 +#: ../clients/cli/devices.c:3399 #, c-format msgid "Error: 'device wifi' command '%s' is not valid." msgstr "Fel: ”device wifi”-kommandot ”%s” är inte giltigt." #. Main header name -#: ../clients/cli/devices.c:3403 +#: ../clients/cli/devices.c:3425 msgid "Device LLDP neighbors" msgstr "LLDP-grannar för enhet" -#: ../clients/cli/devices.c:3506 +#: ../clients/cli/devices.c:3528 #, c-format msgid "Error: 'device lldp list': %s" msgstr "Fel: ”device lldp list”: %s" -#: ../clients/cli/devices.c:3553 +#: ../clients/cli/devices.c:3575 #, c-format msgid "Error: 'device lldp' command '%s' is not valid." msgstr "Fel: ”device lldp”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/devices.c:3742 +#: ../clients/cli/devices.c:3770 #, c-format msgid "Error: 'dev' command '%s' is not valid." msgstr "Fel: ”dev”-kommandot ”%s” är inte giltigt." @@ -5382,158 +5382,158 @@ msgstr "full" msgid "Error: only these fields are allowed: %s" msgstr "Fel: endast dessa fält är tillåtna: %s" -#: ../clients/cli/general.c:357 +#: ../clients/cli/general.c:360 msgid "NetworkManager status" msgstr "Status för Nätverkshanteraren" -#: ../clients/cli/general.c:362 +#: ../clients/cli/general.c:365 msgid "running" msgstr "kör" -#: ../clients/cli/general.c:365 +#: ../clients/cli/general.c:368 msgid "starting" msgstr "startar" -#: ../clients/cli/general.c:365 +#: ../clients/cli/general.c:368 msgid "started" msgstr "startad" -#: ../clients/cli/general.c:367 ../clients/cli/general.c:368 -#: ../clients/cli/general.c:369 ../clients/cli/general.c:370 -#: ../clients/cli/general.c:371 +#: ../clients/cli/general.c:370 ../clients/cli/general.c:371 +#: ../clients/cli/general.c:372 ../clients/cli/general.c:373 +#: ../clients/cli/general.c:374 msgid "enabled" msgstr "aktiverad" -#: ../clients/cli/general.c:367 ../clients/cli/general.c:368 -#: ../clients/cli/general.c:369 ../clients/cli/general.c:370 -#: ../clients/cli/general.c:371 +#: ../clients/cli/general.c:370 ../clients/cli/general.c:371 +#: ../clients/cli/general.c:372 ../clients/cli/general.c:373 +#: ../clients/cli/general.c:374 msgid "disabled" msgstr "inaktiverad" -#: ../clients/cli/general.c:443 +#: ../clients/cli/general.c:446 msgid "auth" msgstr "aute" -#: ../clients/cli/general.c:472 +#: ../clients/cli/general.c:475 #, c-format msgid "Error: 'general permissions': %s" msgstr "Fel: ”general permissions”: %s" -#: ../clients/cli/general.c:486 +#: ../clients/cli/general.c:489 msgid "NetworkManager permissions" msgstr "Rättigheter för Nätverkshanteraren" -#: ../clients/cli/general.c:527 +#: ../clients/cli/general.c:530 #, c-format msgid "Error: 'general logging': %s" msgstr "Fel: ”general logging”: %s" -#: ../clients/cli/general.c:542 +#: ../clients/cli/general.c:545 msgid "NetworkManager logging" msgstr "Loggning för Nätverkshanteraren" -#: ../clients/cli/general.c:564 +#: ../clients/cli/general.c:567 #, c-format msgid "Error: failed to set hostname: %s" msgstr "Fel: misslyckades med att sätta värdnamn: %s" -#: ../clients/cli/general.c:677 +#: ../clients/cli/general.c:680 #, c-format msgid "Error: failed to set logging: %s" msgstr "Fel: misslyckades att sätta loggning: %s" -#: ../clients/cli/general.c:686 +#: ../clients/cli/general.c:689 #, c-format msgid "Error: 'general' command '%s' is not valid." msgstr "Fel: ”general”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/general.c:704 +#: ../clients/cli/general.c:707 #, c-format msgid "Error: '--fields' value '%s' is not valid here (allowed field: %s)" msgstr "" "Fel: värdet ”%s” för ”--fields” är inte giltigt här (tillåtna fält: %s)" -#: ../clients/cli/general.c:729 +#: ../clients/cli/general.c:732 #, c-format msgid "Error: invalid '%s' argument: '%s' (use on/off)." msgstr "Fel: ogiltigt ”%s”-argument: ”%s” (använd på/av)." -#: ../clients/cli/general.c:740 +#: ../clients/cli/general.c:743 msgid "Connectivity" msgstr "Anslutning" -#: ../clients/cli/general.c:755 +#: ../clients/cli/general.c:758 msgid "Networking" msgstr "Nätverk" -#: ../clients/cli/general.c:780 +#: ../clients/cli/general.c:783 #, c-format msgid "Error: 'networking connectivity' command '%s' is not valid." msgstr "Fel: ”networking connectivity”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/general.c:796 +#: ../clients/cli/general.c:799 #, c-format msgid "Error: 'networking' command '%s' is not valid." msgstr "Fel: ”networking”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/general.c:825 ../clients/cli/general.c:845 +#: ../clients/cli/general.c:828 ../clients/cli/general.c:848 msgid "Radio switches" msgstr "Radioväxlar" #. no argument, show current WiFi state -#: ../clients/cli/general.c:863 +#: ../clients/cli/general.c:866 msgid "Wi-Fi radio switch" msgstr "Trådlös radioväxel" #. no argument, show current WWAN (mobile broadband) state -#: ../clients/cli/general.c:879 +#: ../clients/cli/general.c:882 msgid "WWAN radio switch" msgstr "WWAN radioväxel" -#: ../clients/cli/general.c:890 +#: ../clients/cli/general.c:893 #, c-format msgid "Error: 'radio' command '%s' is not valid." msgstr "Fel: ”radio”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/general.c:911 +#: ../clients/cli/general.c:914 msgid "NetworkManager has started" msgstr "Nätverkshanteraren har startats" -#: ../clients/cli/general.c:914 +#: ../clients/cli/general.c:917 msgid "NetworkManager has stopped" msgstr "Nätverkshanteraren har stoppats" -#: ../clients/cli/general.c:928 +#: ../clients/cli/general.c:931 #, c-format msgid "Hostname set to '%s'\n" msgstr "Värdnamnet sattes till ”%s”\n" -#: ../clients/cli/general.c:943 +#: ../clients/cli/general.c:946 #, c-format msgid "'%s' is now the primary connection\n" msgstr "”%s” är nu den primära anslutningen\n" -#: ../clients/cli/general.c:945 +#: ../clients/cli/general.c:948 #, c-format msgid "There's no primary connection\n" msgstr "Det finns ingen primär anslutning\n" -#: ../clients/cli/general.c:957 +#: ../clients/cli/general.c:960 #, c-format msgid "Connectivity is now '%s'\n" msgstr "Anslutbarhet är nu ”%s”\n" -#: ../clients/cli/general.c:970 +#: ../clients/cli/general.c:973 #, c-format msgid "Networkmanager is now in the '%s' state\n" msgstr "Nätverkshanteraren är nu i tillståndet ”%s”\n" -#: ../clients/cli/general.c:981 +#: ../clients/cli/general.c:984 #, c-format msgid "Error: 'monitor' command '%s' is not valid." msgstr "Fel: ”monitor”-kommandot ”%s” är inte giltigt." -#: ../clients/cli/general.c:995 +#: ../clients/cli/general.c:998 msgid "Networkmanager is not running (waiting for it)\n" msgstr "Nätverkshanteraren är inte startad (väntar på den)\n" @@ -5595,64 +5595,64 @@ msgstr "" " m[onitor] övervaka ändringar för Nätverkshanteraren\n" "\n" -#: ../clients/cli/nmcli.c:142 +#: ../clients/cli/nmcli.c:143 #, c-format msgid "Error: Object '%s' is unknown, try 'nmcli help'." msgstr "Fel: Objektet ”%s” är okänt, prova ”nmcli help”." -#: ../clients/cli/nmcli.c:172 +#: ../clients/cli/nmcli.c:173 #, c-format msgid "Error: Option '--terse' is specified the second time." msgstr "Fel: Flaggan ”--terse” har angivits en andra gång." -#: ../clients/cli/nmcli.c:177 +#: ../clients/cli/nmcli.c:178 #, c-format msgid "Error: Option '--terse' is mutually exclusive with '--pretty'." msgstr "Fel: Flaggan ”--terse” är ömsesidigt uteslutande med ”--pretty”." -#: ../clients/cli/nmcli.c:185 +#: ../clients/cli/nmcli.c:186 #, c-format msgid "Error: Option '--pretty' is specified the second time." msgstr "Fel: Flaggan ”--pretty” har angivits en andra gång." -#: ../clients/cli/nmcli.c:190 +#: ../clients/cli/nmcli.c:191 #, c-format msgid "Error: Option '--pretty' is mutually exclusive with '--terse'." msgstr "Fel: Flaggan ”--pretty” är ömsesidigt uteslutande med ”--terse”." -#: ../clients/cli/nmcli.c:200 ../clients/cli/nmcli.c:216 -#: ../clients/cli/nmcli.c:234 ../clients/cli/nmcli.c:265 +#: ../clients/cli/nmcli.c:201 ../clients/cli/nmcli.c:217 +#: ../clients/cli/nmcli.c:235 ../clients/cli/nmcli.c:266 #, c-format msgid "Error: missing argument for '%s' option." msgstr "Fel: argument för flaggan ”%s” saknas." -#: ../clients/cli/nmcli.c:209 ../clients/cli/nmcli.c:227 -#: ../clients/cli/nmcli.c:243 +#: ../clients/cli/nmcli.c:210 ../clients/cli/nmcli.c:228 +#: ../clients/cli/nmcli.c:244 #, c-format msgid "Error: '%s' is not valid argument for '%s' option." msgstr "Fel: ”%s” är inte ett giltigt argument för flaggan ”%s”." -#: ../clients/cli/nmcli.c:250 +#: ../clients/cli/nmcli.c:251 #, c-format msgid "Error: fields for '%s' options are missing." msgstr "Fel: fält för ”%s”-flaggor saknas." -#: ../clients/cli/nmcli.c:270 +#: ../clients/cli/nmcli.c:271 #, c-format msgid "Error: '%s' is not a valid timeout for '%s' option." msgstr "Fel: ”%s” är inte en giltig tidsgräns för flaggan ”%s”." -#: ../clients/cli/nmcli.c:277 +#: ../clients/cli/nmcli.c:278 #, c-format msgid "nmcli tool, version %s\n" msgstr "nmcli-verktyg, version %s\n" -#: ../clients/cli/nmcli.c:283 +#: ../clients/cli/nmcli.c:284 #, c-format msgid "Error: Option '%s' is unknown, try 'nmcli -help'." msgstr "Fel: Flaggan ”%s” är okänd, prova ”nmcli -help”." -#: ../clients/cli/nmcli.c:366 ../clients/cli/nmcli.c:376 +#: ../clients/cli/nmcli.c:367 ../clients/cli/nmcli.c:377 #, c-format msgid "" "\n" @@ -5661,22 +5661,22 @@ msgstr "" "\n" "Fel: nmcli dödad av signalen %s (%d)\n" -#: ../clients/cli/nmcli.c:407 +#: ../clients/cli/nmcli.c:408 #, c-format msgid "Failed to set signal mask: %d\n" msgstr "Misslyckades med att sätta signalmasken: %d\n" -#: ../clients/cli/nmcli.c:414 +#: ../clients/cli/nmcli.c:415 #, c-format msgid "Failed to create signal handling thread: %d\n" msgstr "Misslyckades med att skapa signalhanteringstråd: %d\n" -#: ../clients/cli/nmcli.c:511 ../clients/nm-online.c:193 +#: ../clients/cli/nmcli.c:512 ../clients/nm-online.c:193 #, c-format msgid "Error: Could not create NMClient object: %s." msgstr "Fel: Kunde inte skapa NMClient-objektet: %s." -#: ../clients/cli/nmcli.c:528 +#: ../clients/cli/nmcli.c:529 msgid "Success" msgstr "Lyckades" @@ -5837,112 +5837,112 @@ msgstr "ogiltigt läge ”%s”, använd en av %s" msgid "always" msgstr "alltid" -#: ../clients/cli/settings.c:1999 ../clients/cli/settings.c:3279 -#: ../clients/cli/settings.c:4471 ../clients/cli/settings.c:4974 +#: ../clients/cli/settings.c:1999 ../clients/cli/settings.c:3286 +#: ../clients/cli/settings.c:4478 ../clients/cli/settings.c:4981 #: ../libnm-core/nm-keyfile-reader.c:573 #, c-format msgid "invalid option '%s', use one of [%s]" msgstr "ogiltig flagga ”%s”, använd en av [%s]" -#: ../clients/cli/settings.c:2109 +#: ../clients/cli/settings.c:2116 #, c-format msgid "Do you also want to set '%s' to '%s'? [yes]: " msgstr "Vill du också sätta ”%s” till ”%s”? [yes]: " -#: ../clients/cli/settings.c:2111 +#: ../clients/cli/settings.c:2118 #, c-format msgid "Do you also want to clear '%s'? [yes]: " msgstr "Vill du också rensa ”%s”? [yes]: " -#: ../clients/cli/settings.c:2272 +#: ../clients/cli/settings.c:2279 #, c-format msgid "" "Warning: %s.%s set to '%s', but it might be ignored in infrastructure mode\n" msgstr "" "Varning: %s.%s sätts till ”%s”, men kan ignoreras i infrastrukturläge\n" -#: ../clients/cli/settings.c:2291 +#: ../clients/cli/settings.c:2298 #, c-format msgid "Warning: setting %s.%s requires removing ipv4 and ipv6 settings\n" msgstr "" "Varning: inställningen %s.%s kräver att inställningar för ipv4 och ipv6 tas " "bort\n" -#: ../clients/cli/settings.c:2293 +#: ../clients/cli/settings.c:2300 msgid "Do you want to remove them? [yes] " msgstr "Vill du ta bort dem? [ja] " -#: ../clients/cli/settings.c:2389 ../clients/cli/settings.c:2784 -#: ../clients/cli/settings.c:5175 +#: ../clients/cli/settings.c:2396 ../clients/cli/settings.c:2791 +#: ../clients/cli/settings.c:5182 #, c-format msgid "'%s' is not valid" msgstr "”%s” är inte giltigt" -#: ../clients/cli/settings.c:2412 +#: ../clients/cli/settings.c:2419 #, c-format msgid "'%d' is not valid; use <%d-%d>" msgstr "”%d” är inte giltigt; använd <%d-%d>" -#: ../clients/cli/settings.c:2434 +#: ../clients/cli/settings.c:2441 #, c-format msgid "'%lld' is not valid; use <%lld-%lld>" msgstr "”%lld” är inte giltigt; använd <%lld-%lld>" -#: ../clients/cli/settings.c:2456 +#: ../clients/cli/settings.c:2463 #, c-format msgid "'%u' is not valid; use <%u-%u>" msgstr "”%u” är inte giltigt; använd <%u-%u>" -#: ../clients/cli/settings.c:2495 +#: ../clients/cli/settings.c:2502 #, c-format msgid "'%u' flags are not valid; use combination of %s" msgstr "”%u”-flaggor är inte giltiga; använd en kombination av %s" -#: ../clients/cli/settings.c:2562 +#: ../clients/cli/settings.c:2569 #, c-format msgid "'%s' is not valid; use <option>=<value>" msgstr "”%s” är inte giltigt; använd <flagga>=<värde>" -#: ../clients/cli/settings.c:2596 +#: ../clients/cli/settings.c:2603 #, c-format msgid "index '%s' is not valid" msgstr "indexet ”%s” är inte giltigt" -#: ../clients/cli/settings.c:2601 ../clients/cli/settings.c:2626 +#: ../clients/cli/settings.c:2608 ../clients/cli/settings.c:2633 msgid "no item to remove" msgstr "inget objekt att ta bort" -#: ../clients/cli/settings.c:2605 ../clients/cli/settings.c:2630 +#: ../clients/cli/settings.c:2612 ../clients/cli/settings.c:2637 #, c-format msgid "index '%d' is not in range <0-%d>" msgstr "index ”%d” är inte i intervallet <0-%d>" -#: ../clients/cli/settings.c:2645 +#: ../clients/cli/settings.c:2652 #, c-format msgid "invalid option '%s'" msgstr "ogiltig flagga ”%s”" -#: ../clients/cli/settings.c:2647 +#: ../clients/cli/settings.c:2654 msgid "missing option" msgstr "saknad flagga" -#: ../clients/cli/settings.c:2674 ../clients/cli/settings.c:2694 -#: ../clients/cli/settings.c:2714 ../clients/cli/settings.c:2734 +#: ../clients/cli/settings.c:2681 ../clients/cli/settings.c:2701 +#: ../clients/cli/settings.c:2721 ../clients/cli/settings.c:2741 #, c-format msgid "'%s' is not a valid number (or out of range)" msgstr "”%s” är inte ett giltigt nummer (eller utanför intervallet)" -#: ../clients/cli/settings.c:2768 +#: ../clients/cli/settings.c:2775 #, c-format msgid "'%s' is not a valid value; use -1, 0 or 1" msgstr "”%s” är inte ett giltigt värde; använd -1, 0 eller 1" -#: ../clients/cli/settings.c:2800 +#: ../clients/cli/settings.c:2807 #, c-format msgid "'%s' is not a valid Ethernet MAC" msgstr "”%s” är inte en giltig Ethernet MAC" -#: ../clients/cli/settings.c:2825 ../libnm-core/nm-setting-connection.c:864 +#: ../clients/cli/settings.c:2832 ../libnm-core/nm-setting-connection.c:864 #: ../libnm-core/nm-setting-infiniband.c:255 #: ../libnm-util/nm-setting-connection.c:834 #: ../libnm-util/nm-setting-infiniband.c:269 @@ -5950,38 +5950,38 @@ msgstr "”%s” är inte en giltig Ethernet MAC" msgid "'%s' is not a valid interface name" msgstr "”%s” är inte ett giltigt gränssnittsnamn" -#: ../clients/cli/settings.c:2849 +#: ../clients/cli/settings.c:2856 #, c-format msgid "'%s' is not a valid flag number; use <0-%d>" msgstr "”%s” är inte ett giltigt flaggnummer; använd <0-%d>" -#: ../clients/cli/settings.c:2861 +#: ../clients/cli/settings.c:2868 #, c-format msgid "Warning: '%s' sum is higher than all flags => all flags set\n" msgstr "Varning: ”%s”-summan är högre än alla flaggor => alla flaggor satta\n" -#: ../clients/cli/settings.c:2902 +#: ../clients/cli/settings.c:2909 #, c-format msgid "'%s' is not a valid hex character" msgstr "”%s” är inte ett giltigt hextecken" -#: ../clients/cli/settings.c:2932 +#: ../clients/cli/settings.c:2939 #, c-format msgid "'%s' is not a valid MAC" msgstr "”%s” är inte ett giltigt MAC" -#: ../clients/cli/settings.c:2958 ../libnm-core/nm-setting-connection.c:853 +#: ../clients/cli/settings.c:2965 ../libnm-core/nm-setting-connection.c:853 #: ../libnm-util/nm-setting-connection.c:791 #, c-format msgid "'%s' is not a valid UUID" msgstr "”%s” är inte ett giltigt UUID" -#: ../clients/cli/settings.c:3025 +#: ../clients/cli/settings.c:3032 #, c-format msgid "the property doesn't contain permission '%s'" msgstr "egenskapen innehåller inte rättigheten ”%s”" -#: ../clients/cli/settings.c:3037 +#: ../clients/cli/settings.c:3044 msgid "" "Enter a list of user permissions. This is a list of user names formatted " "as:\n" @@ -5997,37 +5997,37 @@ msgstr "" "\n" "Exempel: anders maria sebastian\n" -#: ../clients/cli/settings.c:3056 +#: ../clients/cli/settings.c:3063 #, c-format msgid "'%s' is not valid master; use ifname or connection UUID" msgstr "”%s” är inte en giltig master; använd grnamn eller anslutnings-UUID" -#: ../clients/cli/settings.c:3100 +#: ../clients/cli/settings.c:3107 #, c-format msgid "Warning: %s is not an UUID of any existing connection profile\n" msgstr "Varning: %s är inte ett UUID på någon befintlig anslutningsprofil\n" -#: ../clients/cli/settings.c:3104 ../clients/cli/settings.c:3120 +#: ../clients/cli/settings.c:3111 ../clients/cli/settings.c:3127 #, c-format msgid "'%s' is not a VPN connection profile" msgstr "”%s” är inte en giltig VPN-anslutningsprofil" -#: ../clients/cli/settings.c:3113 +#: ../clients/cli/settings.c:3120 #, c-format msgid "'%s' is not a name of any exiting profile" msgstr "”%s” är inte ett namn på någon befintlig profil" -#: ../clients/cli/settings.c:3147 +#: ../clients/cli/settings.c:3154 #, c-format msgid "the value '%s' is not a valid UUID" msgstr "värdet ”%s” är inte ett giltigt UUID" -#: ../clients/cli/settings.c:3154 +#: ../clients/cli/settings.c:3161 #, c-format msgid "the property doesn't contain UUID '%s'" msgstr "egenskapen innehåller inte UUID ”%s”" -#: ../clients/cli/settings.c:3166 +#: ../clients/cli/settings.c:3173 msgid "" "Enter secondary connections that should be activated when this connection " "is\n" @@ -6048,7 +6048,7 @@ msgstr "" "\n" "Exempel: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n" -#: ../clients/cli/settings.c:3233 +#: ../clients/cli/settings.c:3240 msgid "" "Enter a value which indicates whether the connection is subject to a data\n" "quota, usage costs or other limitations. Accepted options are:\n" @@ -6064,16 +6064,16 @@ msgstr "" "”unknown” för att låta Nätverkshanteraren välja ett värde enligt någon " "heuristik\n" -#: ../clients/cli/settings.c:3357 +#: ../clients/cli/settings.c:3364 msgid "private key password not provided" msgstr "lösenord för privat nyckel inte angivet" -#: ../clients/cli/settings.c:3385 +#: ../clients/cli/settings.c:3392 #, c-format msgid "the property doesn't contain EAP method '%s'" msgstr "egenskapen innehåller inte EAP-metoden ”%s”" -#: ../clients/cli/settings.c:3402 +#: ../clients/cli/settings.c:3409 msgid "" "Enter file path to CA certificate (optionally prefixed with file://).\n" " [file://]<file path>\n" @@ -6085,12 +6085,12 @@ msgstr "" "Observera att nmcli inte stödjer att ange certifikat som rå blob-data.\n" "Exempel: /home/cimrman/cacert.crt\n" -#: ../clients/cli/settings.c:3421 +#: ../clients/cli/settings.c:3428 #, c-format msgid "the property doesn't contain alternative subject match '%s'" msgstr "egenskapen innehåller inte alternativa ämnesmatchningen ”%s”" -#: ../clients/cli/settings.c:3437 +#: ../clients/cli/settings.c:3444 msgid "" "Enter file path to client certificate (optionally prefixed with file://).\n" " [file://]<file path>\n" @@ -6102,7 +6102,7 @@ msgstr "" "Observera att nmcli inte stödjer att ange certifikat som rå blob-data.\n" "Exempel: /home/cimrman/jara.crt\n" -#: ../clients/cli/settings.c:3449 +#: ../clients/cli/settings.c:3456 msgid "" "Enter file path to CA certificate for inner authentication (optionally " "prefixed\n" @@ -6118,12 +6118,12 @@ msgstr "" "Observera att nmcli inte stödjer att ange certifikat som rå blob-data.\n" "Exempel: /home/cimrman/ca-zweite-phase.crt\n" -#: ../clients/cli/settings.c:3469 +#: ../clients/cli/settings.c:3476 #, c-format msgid "the property doesn't contain \"phase2\" alternative subject match '%s'" msgstr "egenskapen innehåller inte ”phase2”-alternativa ämnesmatchningen ”%s”" -#: ../clients/cli/settings.c:3485 +#: ../clients/cli/settings.c:3492 msgid "" "Enter file path to client certificate for inner authentication (optionally " "prefixed\n" @@ -6139,7 +6139,7 @@ msgstr "" "Observera att nmcli inte stödjer att ange certifikat som rå blob-data.\n" "Exempel: /home/cimrman/jara-zweite-phase.crt\n" -#: ../clients/cli/settings.c:3505 +#: ../clients/cli/settings.c:3512 msgid "" "Enter path to a private key and the key password (if not set yet):\n" " [file://]<file path> [<password>]\n" @@ -6152,7 +6152,7 @@ msgstr "" "Observera att nmcli inte stödjer att ange privat nyckel som rå blob-data.\n" "Exempel: /home/cimrman/jara-priv-key Dardanely\n" -#: ../clients/cli/settings.c:3576 +#: ../clients/cli/settings.c:3583 msgid "" "Enter bytes as a list of hexadecimal values.\n" "Two formats are accepted:\n" @@ -6174,7 +6174,7 @@ msgstr "" "Exempel: ab0455a6ea3a74C2\n" " ab 4 55 0xa6 ea 3a 74 C2\n" -#: ../clients/cli/settings.c:3697 +#: ../clients/cli/settings.c:3704 #, c-format msgid "" "Enter a list of bonding options formatted as:\n" @@ -6205,32 +6205,32 @@ msgstr "" "\n" "Exempel: mode=2,miimon=120\n" -#: ../clients/cli/settings.c:3728 +#: ../clients/cli/settings.c:3735 #, c-format msgid "'%s' is not a valid InfiniBand MAC" msgstr "”%s” är inte en giltig InfiniBand MAC" -#: ../clients/cli/settings.c:3765 +#: ../clients/cli/settings.c:3772 #, c-format msgid "'%s' is not a valid IBoIP P_Key" msgstr "”%s” är inte en giltig IBoIP P_Key" -#: ../clients/cli/settings.c:3796 +#: ../clients/cli/settings.c:3803 #, c-format msgid "'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric])" msgstr "”%s” är inte giltigt (formatet är: ip[/prefix] [next-hop] [metric])" -#: ../clients/cli/settings.c:3844 ../clients/cli/settings.c:3863 +#: ../clients/cli/settings.c:3851 ../clients/cli/settings.c:3870 #, c-format msgid "invalid IPv4 address '%s'" msgstr "ogiltig IPv4-adress ”%s”" -#: ../clients/cli/settings.c:3869 ../clients/cli/settings.c:4177 +#: ../clients/cli/settings.c:3876 ../clients/cli/settings.c:4184 #, c-format msgid "the property doesn't contain DNS server '%s'" msgstr "egenskapen innehåller inte DNS-servern ”%s”" -#: ../clients/cli/settings.c:3881 +#: ../clients/cli/settings.c:3888 msgid "" "Enter a list of IPv4 addresses of DNS servers.\n" "\n" @@ -6240,22 +6240,22 @@ msgstr "" "\n" "Exempel: 8.8.8.8, 8.8.4.4\n" -#: ../clients/cli/settings.c:3917 ../clients/cli/settings.c:4231 +#: ../clients/cli/settings.c:3924 ../clients/cli/settings.c:4238 #, c-format msgid "the property doesn't contain DNS search domain '%s'" msgstr "egenskapen innehåller inte DNS-sökdomänen ”%s”" -#: ../clients/cli/settings.c:3955 ../clients/cli/settings.c:4269 +#: ../clients/cli/settings.c:3962 ../clients/cli/settings.c:4276 #, c-format msgid "the property doesn't contain DNS option '%s'" msgstr "egenskapen stöder inte DNS-alternativet ”%s”" -#: ../clients/cli/settings.c:4009 ../clients/cli/settings.c:4322 +#: ../clients/cli/settings.c:4016 ../clients/cli/settings.c:4329 #, c-format msgid "the property doesn't contain IP address '%s'" msgstr "egenskapen innehåller inte IP-adressen ”%s”" -#: ../clients/cli/settings.c:4022 +#: ../clients/cli/settings.c:4029 msgid "" "Enter a list of IPv4 addresses formatted as:\n" " ip[/prefix], ip[/prefix],...\n" @@ -6269,17 +6269,17 @@ msgstr "" "\n" "Exempel: 192.168.1.5/24 192.168.1.1, 10.0.0.11/24\n" -#: ../clients/cli/settings.c:4038 ../clients/cli/settings.c:4351 +#: ../clients/cli/settings.c:4045 ../clients/cli/settings.c:4358 #, c-format msgid "invalid gateway address '%s'" msgstr "ogiltig gateway-adress ”%s”" -#: ../clients/cli/settings.c:4093 ../clients/cli/settings.c:4406 +#: ../clients/cli/settings.c:4100 ../clients/cli/settings.c:4413 #, c-format msgid "the property doesn't contain route '%s'" msgstr "egenskapen innehåller inte rutten ”%s”" -#: ../clients/cli/settings.c:4106 +#: ../clients/cli/settings.c:4113 msgid "" "Enter a list of IPv4 routes formatted as:\n" " ip[/prefix] [next-hop] [metric],...\n" @@ -6302,12 +6302,12 @@ msgstr "" "Exempel: 192.168.2.0/24 192.168.2.1 3, 10.1.0.0/16 10.0.0.254\n" " 10.1.2.0/24\n" -#: ../clients/cli/settings.c:4152 ../clients/cli/settings.c:4171 +#: ../clients/cli/settings.c:4159 ../clients/cli/settings.c:4178 #, c-format msgid "invalid IPv6 address '%s'" msgstr "ogiltig IPv6-adress ”%s”" -#: ../clients/cli/settings.c:4189 +#: ../clients/cli/settings.c:4196 msgid "" "Enter a list of IPv6 addresses of DNS servers. If the IPv6 configuration " "method is 'auto' these DNS servers are appended to those (if any) returned " @@ -6327,7 +6327,7 @@ msgstr "" "\n" "Exempel: 2607:f0d0:1002:51::4, 2607:f0d0:1002:51::1\n" -#: ../clients/cli/settings.c:4335 +#: ../clients/cli/settings.c:4342 msgid "" "Enter a list of IPv6 addresses formatted as:\n" " ip[/prefix], ip[/prefix],...\n" @@ -6342,7 +6342,7 @@ msgstr "" "Exempel: 2607:f0d0:1002:51::4/64 2607:f0d0:1002:51::1, " "1050:0:0:0:5:600:300c:326b\n" -#: ../clients/cli/settings.c:4419 +#: ../clients/cli/settings.c:4426 msgid "" "Enter a list of IPv6 routes formatted as:\n" " ip[/prefix] [next-hop] [metric],...\n" @@ -6366,28 +6366,28 @@ msgstr "" "db8:beef::3 2\n" " abbe::/64 55\n" -#: ../clients/cli/settings.c:4436 ../libnm-core/nm-setting-gsm.c:363 +#: ../clients/cli/settings.c:4443 ../libnm-core/nm-setting-gsm.c:363 #: ../libnm-util/nm-setting-gsm.c:364 #, c-format msgid "'%s' is not a number" msgstr "”%s” är inte ett nummer" -#: ../clients/cli/settings.c:4443 +#: ../clients/cli/settings.c:4450 #, c-format msgid "'%s' is not valid; use 0, 1, or 2" msgstr "”%s” är inte giltig; använd 0, 1 eller 2" -#: ../clients/cli/settings.c:4490 +#: ../clients/cli/settings.c:4497 #, c-format msgid "'%s' is not a valid channel; use <1-13>" msgstr "”%s” är inte en giltig kanal; använd <1-13>" -#: ../clients/cli/settings.c:4527 +#: ../clients/cli/settings.c:4534 #, c-format msgid "'%s' is not valid; use [e, o, n]" msgstr "”%s” är inte giltig; använd [e, o, n]" -#: ../clients/cli/settings.c:4555 +#: ../clients/cli/settings.c:4562 msgid "" "nmcli can accepts both direct JSON configuration data and a file name " "containing the configuration. In the latter case the file is read and the " @@ -6405,32 +6405,32 @@ msgstr "" "\"roundrobin\"}, \"ports\": {\"eth1\": {}, \"eth2\": {}} }\n" " set team.config /etc/my-team.conf\n" -#: ../clients/cli/settings.c:4595 +#: ../clients/cli/settings.c:4602 msgid "no priority to remove" msgstr "ingen prioritet att ta bort" -#: ../clients/cli/settings.c:4599 +#: ../clients/cli/settings.c:4606 #, c-format msgid "index '%d' is not in the range of <0-%d>" msgstr "index ”%d” är inte i intervallet för <0-%d>" -#: ../clients/cli/settings.c:4638 +#: ../clients/cli/settings.c:4645 #, c-format msgid "" "Warning: only one mapping at a time is supported; taking the first one (%s)\n" msgstr "Varning: endast en mappning åt gången stöds; tar den första (%s)\n" -#: ../clients/cli/settings.c:4645 +#: ../clients/cli/settings.c:4652 #, c-format msgid "the property doesn't contain mapping '%s'" msgstr "egenskapen stöder inte mappningen ”%s”" -#: ../clients/cli/settings.c:4693 +#: ../clients/cli/settings.c:4700 #, c-format msgid "'%s' cannot be empty" msgstr "”%s” kan inte vara tomt" -#: ../clients/cli/settings.c:4767 ../clients/cli/settings.c:4934 +#: ../clients/cli/settings.c:4774 ../clients/cli/settings.c:4941 #: ../libnm-core/nm-setting-wired.c:651 ../libnm-core/nm-setting-wireless.c:820 #: ../libnm-core/nm-setting-wireless.c:832 ../libnm-util/nm-setting-wired.c:646 #: ../libnm-util/nm-setting-wireless.c:859 @@ -6439,17 +6439,17 @@ msgstr "”%s” kan inte vara tomt" msgid "'%s' is not a valid MAC address" msgstr "”%s” är inte en giltig MAC-adress" -#: ../clients/cli/settings.c:4773 ../clients/cli/settings.c:4940 +#: ../clients/cli/settings.c:4780 ../clients/cli/settings.c:4947 #, c-format msgid "the property doesn't contain MAC address '%s'" msgstr "egenskapen innehåller inte MAC-adress ”%s”" -#: ../clients/cli/settings.c:4792 +#: ../clients/cli/settings.c:4799 #, c-format msgid "'%s' is not valid; 2 or 3 strings should be provided" msgstr "”%s” är ogiltig; Två eller tre strängar ska anges" -#: ../clients/cli/settings.c:4806 +#: ../clients/cli/settings.c:4813 msgid "" "Enter a list of subchannels (comma or space separated).\n" "\n" @@ -6459,12 +6459,12 @@ msgstr "" "\n" "Exempel: 0.0.0e20 0.0.0e21 0.0.0e22\n" -#: ../clients/cli/settings.c:4828 +#: ../clients/cli/settings.c:4835 #, c-format msgid "'%s' string value should consist of 1 - 199 characters" msgstr "”%s”-strängvärde ska bestå av 1 - 199 tecken" -#: ../clients/cli/settings.c:4860 +#: ../clients/cli/settings.c:4867 #, c-format msgid "" "Enter a list of S/390 options formatted as:\n" @@ -6475,28 +6475,28 @@ msgstr "" " option = <värde>, option = <värde>,…\n" "Giltiga val är: %s\n" -#: ../clients/cli/settings.c:4906 +#: ../clients/cli/settings.c:4913 #, c-format msgid "'%s' is not a valid channel" msgstr "”%s” är inte en giltig kanal" -#: ../clients/cli/settings.c:4912 +#: ../clients/cli/settings.c:4919 #, c-format msgid "'%ld' is not a valid channel" msgstr "”%ld” är en ogiltig kanal" -#: ../clients/cli/settings.c:5006 +#: ../clients/cli/settings.c:5013 #, c-format msgid "invalid option '%s', use 'default', 'never' or 'always'" msgstr "ogiltig flagga ”%s”, använd ”default”, ”never” eller ”always”" -#: ../clients/cli/settings.c:5067 ../clients/cli/settings.c:5106 -#: ../clients/cli/settings.c:5145 +#: ../clients/cli/settings.c:5074 ../clients/cli/settings.c:5113 +#: ../clients/cli/settings.c:5152 #, c-format msgid "the property doesn't contain protocol '%s'" msgstr "egenskapen innehåller inte protokollet ”%s”" -#: ../clients/cli/settings.c:5184 +#: ../clients/cli/settings.c:5191 #, c-format msgid "" "'%s' not compatible with %s '%s', please change the key or set the right %s " @@ -6504,23 +6504,23 @@ msgid "" msgstr "" "”%s” är inte kompatibel med %s ”%s”, ändra nyckeln eller sätt rätt %s först." -#: ../clients/cli/settings.c:5192 +#: ../clients/cli/settings.c:5199 #, c-format msgid "WEP key is guessed to be of '%s'\n" msgstr "WEP-nyckel antas vara ”%s”\n" -#: ../clients/cli/settings.c:5194 +#: ../clients/cli/settings.c:5201 #, c-format msgid "WEP key index set to '%d'\n" msgstr "index för WEP-nyckel satt till ”%d”\n" -#: ../clients/cli/settings.c:5217 +#: ../clients/cli/settings.c:5224 #, c-format msgid "'%s' not among [0 (unknown), 1 (key), 2 (passphrase)]" msgstr "”%s” inte bland [0 (okänd), 1 (nyckel), 2 (lösenfras)]" -#: ../clients/cli/settings.c:5233 ../clients/cli/settings.c:5236 -#: ../clients/cli/settings.c:5239 ../clients/cli/settings.c:5242 +#: ../clients/cli/settings.c:5240 ../clients/cli/settings.c:5243 +#: ../clients/cli/settings.c:5246 ../clients/cli/settings.c:5249 #, c-format msgid "" "Warning: '%s' is not compatible with '%s' type, please change or delete the " @@ -6528,7 +6528,7 @@ msgid "" msgstr "" "Varning:”%s” är inte kompatibel med ”%s”-typ, ändra eller ta bort nyckeln.\n" -#: ../clients/cli/settings.c:5255 +#: ../clients/cli/settings.c:5262 #, c-format msgid "" "Enter the type of WEP keys. The accepted values are: 0 or unknown, 1 or key, " @@ -6537,36 +6537,36 @@ msgstr "" "Ange typ på WEP-nycklarna. Accepterade värden är: 0 eller okänd, 1 eller " "nyckel, 2 eller lösenfras.\n" -#: ../clients/cli/settings.c:5268 +#: ../clients/cli/settings.c:5275 #, c-format msgid "'%s' is not a valid PSK" msgstr "”%s” inte en giltig PSK" -#: ../clients/cli/settings.c:5312 +#: ../clients/cli/settings.c:5319 #, c-format msgid "'%s' is not a valid DCB flag" msgstr "”%s” är inte en giltig DCB-flagga" -#: ../clients/cli/settings.c:5335 +#: ../clients/cli/settings.c:5342 #, c-format msgid "'%s' is not a DCB app priority" msgstr "”%s” är inte en giltig DCB-programprioritet" -#: ../clients/cli/settings.c:5361 +#: ../clients/cli/settings.c:5368 msgid "must contain 8 comma-separated numbers" msgstr "måste innehålla 8 kommaseparerade siffror" -#: ../clients/cli/settings.c:5378 +#: ../clients/cli/settings.c:5385 #, c-format msgid "'%s' not a number between 0 and %u (inclusive) or %u" msgstr "”%s” inte en siffra mellan 0 och %u (inklusive) eller %u" -#: ../clients/cli/settings.c:5381 +#: ../clients/cli/settings.c:5388 #, c-format msgid "'%s' not a number between 0 and %u (inclusive)" msgstr "”%s” inte en siffra mellan 0 och %u (inklusive)" -#: ../clients/cli/settings.c:5403 +#: ../clients/cli/settings.c:5410 #, c-format msgid "" "Warning: changes will have no effect until '%s' includes 1 (enabled)\n" @@ -6576,42 +6576,42 @@ msgstr "" "(aktiverad)\n" "\n" -#: ../clients/cli/settings.c:5456 +#: ../clients/cli/settings.c:5463 #, c-format msgid "bandwidth percentages must total 100%%" msgstr "summan för bandbreddsprocenten måste vara 100%%" -#: ../clients/cli/settings.c:5542 ../clients/cli/settings.c:5548 +#: ../clients/cli/settings.c:5549 ../clients/cli/settings.c:5555 msgid "SIM operator ID must be a 5 or 6 number MCCMNC code" msgstr "SIM-operatörs-ID måste vara en 5- eller 6-siffrig MCCMNC-kod" -#: ../clients/cli/settings.c:5591 +#: ../clients/cli/settings.c:5598 #, c-format msgid "invalid option '%s', use '%s' or '%s'" msgstr "ogiltig flagga ”%s”, använd ”%s” eller ”%s”" -#: ../clients/cli/settings.c:7637 +#: ../clients/cli/settings.c:7644 msgid "don't know how to get the property value" msgstr "vet inte hur egenskapsvärdet ska hämtas" -#: ../clients/cli/settings.c:7690 ../clients/cli/settings.c:7730 +#: ../clients/cli/settings.c:7697 ../clients/cli/settings.c:7737 msgid "the property can't be changed" msgstr "egenskapen kan inte ändras" -#: ../clients/cli/settings.c:7814 +#: ../clients/cli/settings.c:7821 msgid "(not available)" msgstr "(ej tillgänglig)" -#: ../clients/cli/settings.c:7839 +#: ../clients/cli/settings.c:7846 msgid "[NM property description]" msgstr "[NH egenskapsbeskrivning]" -#: ../clients/cli/settings.c:7844 +#: ../clients/cli/settings.c:7851 msgid "[nmcli specific description]" msgstr "[nmcli specifik beskrivning]" #. ---------------------------------------------------------------------------- -#: ../clients/cli/settings.c:7893 +#: ../clients/cli/settings.c:7900 msgid "<hidden>" msgstr "<dold>" @@ -6630,49 +6630,59 @@ msgstr "Fel: Förväntade argumentet ”%s” men gavs ”%s”." msgid "Error: Unexpected argument '%s'" msgstr "Fel: Oväntat argument ”%s”" +#: ../clients/cli/utils.c:202 +#, c-format +msgid "Error converting IP4 address '0x%X' to text form" +msgstr "Fel vid konvertering av IP4-adress ”0x%X” till textformat" + +#: ../clients/cli/utils.c:230 +#, c-format +msgid "Error converting IP6 address '%s' to text form" +msgstr "Fel vid konvertering av IP6-adress ”%s” till textformat" + #. Translators: the first %s is the partial value entered by #. * the user, the second %s a list of compatible values. #. -#: ../clients/cli/utils.c:492 ../clients/cli/utils.c:523 +#: ../clients/cli/utils.c:546 ../clients/cli/utils.c:577 #, c-format msgid "'%s' is ambiguous (%s)" msgstr "”%s” är dubbeltydig (%s)" -#: ../clients/cli/utils.c:502 +#: ../clients/cli/utils.c:556 #, c-format msgid "'%s' is not valid; use [%s] or [%s]" msgstr "”%s” är inte giltig; använd [%s] eller [%s]" -#: ../clients/cli/utils.c:535 +#: ../clients/cli/utils.c:589 #, c-format msgid "'%s' is not valid; use [%s], [%s] or [%s]" msgstr "”%s” är inte giltig; använd [%s], [%s] eller [%s]" -#: ../clients/cli/utils.c:634 +#: ../clients/cli/utils.c:688 #, c-format msgid "'%s' is ambiguous (%s x %s)" msgstr "”%s” är dubbeltydig (%s x %s)" -#: ../clients/cli/utils.c:646 +#: ../clients/cli/utils.c:700 #, c-format msgid "missing name, try one of [%s]" msgstr "saknat namn, prova en av [%s]" -#: ../clients/cli/utils.c:893 +#: ../clients/cli/utils.c:964 #, c-format msgid "field '%s' has to be alone" msgstr "fältet ”%s” måste vara ensamt" -#: ../clients/cli/utils.c:896 +#: ../clients/cli/utils.c:967 #, c-format msgid "invalid field '%s'; allowed fields: %s" msgstr "ogiltigt fält ”%s”; tillåtna fält: %s" -#: ../clients/cli/utils.c:953 +#: ../clients/cli/utils.c:1024 msgid "Option '--terse' requires specifying '--fields'" msgstr "Flaggan ”--terse” kräver att ”--fields” anges" -#: ../clients/cli/utils.c:957 +#: ../clients/cli/utils.c:1028 #, c-format msgid "Option '--terse' requires specific '--fields' option values , not '%s'" msgstr "" @@ -6701,8 +6711,7 @@ msgstr "Användarnamn" #: ../clients/common/nm-secret-agent-simple.c:525 #: ../clients/common/nm-vpn-helpers.c:101 #: ../clients/common/nm-vpn-helpers.c:102 -#: ../clients/common/nm-vpn-helpers.c:106 -#: ../clients/common/nm-vpn-helpers.c:109 ../clients/tui/nmt-page-dsl.c:75 +#: ../clients/common/nm-vpn-helpers.c:105 ../clients/tui/nmt-page-dsl.c:75 #: ../clients/tui/nmt-page-wifi.c:277 ../clients/tui/nmt-page-wifi.c:308 #: ../clients/tui/nmt-page-wifi.c:341 msgid "Password" @@ -6786,28 +6795,20 @@ msgid "could not get VPN plugin info" msgstr "kunde inte hämta VPN-insticksinfo" #: ../clients/common/nm-vpn-helpers.c:103 -msgid "Certificate password" -msgstr "Certifikatlösenord" - -#: ../clients/common/nm-vpn-helpers.c:104 -msgid "HTTP proxy password" -msgstr "HTTP-proxylösenord" - -#: ../clients/common/nm-vpn-helpers.c:107 -#: ../clients/common/nm-vpn-helpers.c:110 +#: ../clients/common/nm-vpn-helpers.c:106 msgid "Group password" msgstr "Grupplösenord" -#: ../clients/common/nm-vpn-helpers.c:112 ../clients/tui/nmt-page-ip4.c:143 +#: ../clients/common/nm-vpn-helpers.c:108 ../clients/tui/nmt-page-ip4.c:143 #: ../clients/tui/nmt-page-ip6.c:143 msgid "Gateway" msgstr "Gateway" -#: ../clients/common/nm-vpn-helpers.c:113 +#: ../clients/common/nm-vpn-helpers.c:109 msgid "Cookie" msgstr "Kaka" -#: ../clients/common/nm-vpn-helpers.c:114 +#: ../clients/common/nm-vpn-helpers.c:110 msgid "Gateway certificate hash" msgstr "Certifikathash för gateway" @@ -6914,7 +6915,7 @@ msgstr "DSL-anslutning %d" #: ../clients/tui/nm-editor-utils.c:190 ../libnm-core/nm-connection.c:1708 #: ../libnm-glib/nm-device.c:1863 ../libnm-util/nm-connection.c:1626 -#: ../libnm/nm-device.c:1814 ../src/settings/plugins/ifcfg-rh/reader.c:4182 +#: ../libnm/nm-device.c:1814 ../src/settings/plugins/ifcfg-rh/reader.c:4190 msgid "Bond" msgstr "Kombinera" @@ -6925,7 +6926,7 @@ msgstr "Kombinationsanslutning %d" #: ../clients/tui/nm-editor-utils.c:199 ../libnm-core/nm-connection.c:1712 #: ../libnm-glib/nm-device.c:1867 ../libnm-util/nm-connection.c:1630 -#: ../libnm/nm-device.c:1818 ../src/settings/plugins/ifcfg-rh/reader.c:4479 +#: ../libnm/nm-device.c:1818 ../src/settings/plugins/ifcfg-rh/reader.c:4487 msgid "Bridge" msgstr "Brygga" @@ -6936,7 +6937,7 @@ msgstr "Brygganslutning %d" #: ../clients/tui/nm-editor-utils.c:208 ../libnm-core/nm-connection.c:1710 #: ../libnm-glib/nm-device.c:1865 ../libnm-util/nm-connection.c:1628 -#: ../libnm/nm-device.c:1816 ../src/settings/plugins/ifcfg-rh/reader.c:4288 +#: ../libnm/nm-device.c:1816 ../src/settings/plugins/ifcfg-rh/reader.c:4296 msgid "Team" msgstr "Grupp" @@ -7978,7 +7979,7 @@ msgstr "Oväntat misslyckande med att normalisera anslutningen" #: ../libnm-core/nm-setting-connection.c:837 #: ../libnm-core/nm-setting-connection.c:876 #: ../libnm-core/nm-setting-connection.c:989 -#: ../libnm-core/nm-setting-ip-config.c:2167 +#: ../libnm-core/nm-setting-ip-config.c:2162 #: ../libnm-core/nm-setting-olpc-mesh.c:120 #: ../libnm-core/nm-setting-pppoe.c:142 ../libnm-core/nm-setting-vpn.c:419 #: ../libnm-core/nm-setting-vxlan.c:360 ../libnm-core/nm-setting-wimax.c:126 @@ -8216,7 +8217,7 @@ msgstr "ogiltig privat nyckel för phase2" #: ../libnm-core/nm-setting-connection.c:844 #: ../libnm-core/nm-setting-connection.c:887 ../libnm-core/nm-setting-gsm.c:281 #: ../libnm-core/nm-setting-gsm.c:338 ../libnm-core/nm-setting-gsm.c:375 -#: ../libnm-core/nm-setting-gsm.c:384 ../libnm-core/nm-setting-ip-config.c:2174 +#: ../libnm-core/nm-setting-gsm.c:384 ../libnm-core/nm-setting-ip-config.c:2169 #: ../libnm-core/nm-setting-ip4-config.c:198 #: ../libnm-core/nm-setting-ip4-config.c:205 #: ../libnm-core/nm-setting-pppoe.c:149 ../libnm-core/nm-setting-pppoe.c:158 @@ -8579,55 +8580,55 @@ msgstr "Ogiltig IPv4-adress ”%s”" msgid "Invalid IPv6 address '%s'" msgstr "Ogiltig IPv6-adress ”%s”" -#: ../libnm-core/nm-setting-ip-config.c:153 +#: ../libnm-core/nm-setting-ip-config.c:152 #, c-format msgid "Invalid IPv4 address prefix '%u'" msgstr "Ogiltig IPv4-adressprefix ”%u”" -#: ../libnm-core/nm-setting-ip-config.c:153 +#: ../libnm-core/nm-setting-ip-config.c:152 #, c-format msgid "Invalid IPv6 address prefix '%u'" msgstr "Ogiltigt IPv6-adressprefix ”%u”" -#: ../libnm-core/nm-setting-ip-config.c:168 +#: ../libnm-core/nm-setting-ip-config.c:170 #, c-format msgid "Invalid routing metric '%s'" msgstr "Ogiltigt ruttmätvärde ”%s”" -#: ../libnm-core/nm-setting-ip-config.c:2187 +#: ../libnm-core/nm-setting-ip-config.c:2182 #, c-format msgid "%d. DNS server address is invalid" msgstr "%d. DNS-serveradressen är ogiltig" -#: ../libnm-core/nm-setting-ip-config.c:2203 +#: ../libnm-core/nm-setting-ip-config.c:2198 #, c-format msgid "%d. IP address is invalid" msgstr "%d. IP-adressen är ogiltig" -#: ../libnm-core/nm-setting-ip-config.c:2215 +#: ../libnm-core/nm-setting-ip-config.c:2210 #, c-format msgid "%d. IP address has 'label' property with invalid type" msgstr "%d. IP-adressen har ”label”-egenskap med ogiltig typ" -#: ../libnm-core/nm-setting-ip-config.c:2224 +#: ../libnm-core/nm-setting-ip-config.c:2219 #, c-format msgid "%d. IP address has invalid label '%s'" msgstr "%d. IP-adressen har ogiltig etikett ”%s”" -#: ../libnm-core/nm-setting-ip-config.c:2238 +#: ../libnm-core/nm-setting-ip-config.c:2233 msgid "gateway cannot be set if there are no addresses configured" msgstr "gateway kan inte bestämmas om det inte finns adresser konfigurerade" -#: ../libnm-core/nm-setting-ip-config.c:2247 +#: ../libnm-core/nm-setting-ip-config.c:2242 msgid "gateway is invalid" msgstr "ogiltig gateway" -#: ../libnm-core/nm-setting-ip-config.c:2261 +#: ../libnm-core/nm-setting-ip-config.c:2256 #, c-format msgid "%d. route is invalid" msgstr "%d.-rutt ogiltig" -#: ../libnm-core/nm-setting-ip-config.c:2270 +#: ../libnm-core/nm-setting-ip-config.c:2265 #, c-format msgid "%d. route cannot be a default route" msgstr "%d. rutt kan inte vara en standardrutt" @@ -8962,39 +8963,39 @@ msgstr "libtool-arkiv stöds inte (%s)" msgid "Could not find \"%s\" binary" msgstr "Kunde inte hitta binären ”%s”" -#: ../libnm-core/nm-vpn-editor-plugin.c:142 +#: ../libnm-core/nm-vpn-editor-plugin.c:132 #, c-format -msgid "cannot load plugin \"%s\": %s" -msgstr "kan inte läsa in insticksmodulen ”%s”: %s" +msgid "cannot load plugin %s" +msgstr "kan inte läsa in insticksmodulen %s" -#: ../libnm-core/nm-vpn-editor-plugin.c:153 +#: ../libnm-core/nm-vpn-editor-plugin.c:160 #, c-format -msgid "failed to load nm_vpn_editor_plugin_factory() from %s (%s)" +msgid "cannot load VPN plugin in '%s': missing plugin name" msgstr "" -"misslyckades med att läsa in nm_vpn_editor_plugin_factory() från %s (%s)" +"kan inte läsa in VPN-insticksmodul i ”%s”: saknar namn på insticksmodul" -#: ../libnm-core/nm-vpn-editor-plugin.c:178 +#: ../libnm-core/nm-vpn-editor-plugin.c:167 +#, c-format +msgid "cannot load VPN plugin in '%s': invalid service name" +msgstr "kan inte läsa in VPN-insticksmodul i ”%s”: ogiltigt namn på tjänst" + +#: ../libnm-core/nm-vpn-editor-plugin.c:183 #, c-format msgid "unknown error initializing plugin %s" msgstr "okänt fel vid initiering av insticksmodulen %s" #: ../libnm-core/nm-vpn-editor-plugin.c:195 #, c-format -msgid "cannot load VPN plugin in '%s': missing plugin name" +msgid "failed to load nm_vpn_editor_plugin_factory() from %s (%s)" msgstr "" -"kan inte läsa in VPN-insticksmodul i ”%s”: saknar namn på insticksmodul" - -#: ../libnm-core/nm-vpn-editor-plugin.c:204 -#, c-format -msgid "cannot load VPN plugin in '%s': invalid service name" -msgstr "kan inte läsa in VPN-insticksmodul i ”%s”: ogiltigt namn på tjänst" +"misslyckades med att läsa in nm_vpn_editor_plugin_factory() från %s (%s)" -#: ../libnm-core/nm-vpn-editor-plugin.c:310 +#: ../libnm-core/nm-vpn-editor-plugin.c:256 #, c-format msgid "the plugin does not support import capability" msgstr "insticksmodulen stöder inte importförmåga" -#: ../libnm-core/nm-vpn-editor-plugin.c:330 +#: ../libnm-core/nm-vpn-editor-plugin.c:276 #, c-format msgid "the plugin does not support export capability" msgstr "insticksmodulen stöder inte exportförmåga" @@ -9460,17 +9461,17 @@ msgid "" msgstr "" "Systemets policy förhindrar ändring av bestående global DNS-konfiguration" -#: ../shared/nm-shared-utils.c:185 +#: ../shared/nm-shared-utils.c:174 #, c-format msgid "object class '%s' has no property named '%s'" msgstr "objektklassen ”%s” har ingen egenskap med namnet ”%s”" -#: ../shared/nm-shared-utils.c:192 +#: ../shared/nm-shared-utils.c:181 #, c-format msgid "property '%s' of object class '%s' is not writable" msgstr "egenskapen ”%s” för objektklassen ”%s” är inte skrivbar" -#: ../shared/nm-shared-utils.c:199 +#: ../shared/nm-shared-utils.c:188 #, c-format msgid "" "construct property \"%s\" for object '%s' can't be set after construction" @@ -9478,19 +9479,19 @@ msgstr "" "konstruktionsegenskap ”%s” för objektet ”%s” kan inte ställas in efter att " "det skapats" -#: ../shared/nm-shared-utils.c:207 +#: ../shared/nm-shared-utils.c:196 #, c-format msgid "'%s::%s' is not a valid property name; '%s' is not a GObject subtype" msgstr "" "”%s::%s” är inte ett giltigt egenskapsnamn; ”%s” är inte en undertyp till " "GObject" -#: ../shared/nm-shared-utils.c:216 +#: ../shared/nm-shared-utils.c:205 #, c-format msgid "unable to set property '%s' of type '%s' from value of type '%s'" msgstr "kan inte sätta egenskapen ”%s” av typen ”%s” från värdet av typen ”%s”" -#: ../shared/nm-shared-utils.c:227 +#: ../shared/nm-shared-utils.c:216 #, c-format msgid "" "value \"%s\" of type '%s' is invalid or out of range for property '%s' of " @@ -9515,25 +9516,25 @@ msgid "Failed to read configuration: %s\n" msgstr "Misslyckades med att läsa konfiguration: %s\n" #. Logging/debugging -#: ../src/main.c:234 ../src/nm-iface-helper.c:298 +#: ../src/main.c:234 ../src/nm-iface-helper.c:297 msgid "Print NetworkManager version and exit" msgstr "Skriv ut version för Nätverkshanteraren och avsluta" -#: ../src/main.c:235 ../src/nm-iface-helper.c:299 +#: ../src/main.c:235 ../src/nm-iface-helper.c:298 msgid "Don't become a daemon" msgstr "Bli inte en demon" -#: ../src/main.c:236 ../src/nm-iface-helper.c:301 +#: ../src/main.c:236 ../src/nm-iface-helper.c:300 #, c-format msgid "Log level: one of [%s]" msgstr "Loggnivå: en av [%s]" -#: ../src/main.c:238 ../src/nm-iface-helper.c:303 +#: ../src/main.c:238 ../src/nm-iface-helper.c:302 #, c-format msgid "Log domains separated by ',': any combination of [%s]" msgstr "Logga domäner separerade med ”,”: vilken kombination som helst av [%s]" -#: ../src/main.c:240 ../src/nm-iface-helper.c:305 +#: ../src/main.c:240 ../src/nm-iface-helper.c:304 msgid "Make all warnings fatal" msgstr "Gör alla varningar till ödesdigra" @@ -9561,12 +9562,12 @@ msgstr "" "att användaren anger trådlösa accesspunkter som trådlösa nätverks-\n" "kort i datorn ska associeras med." -#: ../src/main.c:343 ../src/main-utils.c:269 ../src/nm-iface-helper.c:393 +#: ../src/main.c:343 ../src/main-utils.c:269 ../src/nm-iface-helper.c:392 #, c-format msgid "%s. Please use --help to see a list of valid options.\n" msgstr "%s. Använd --help för att se en lista över giltiga flaggor.\n" -#: ../src/main.c:348 ../src/nm-iface-helper.c:398 +#: ../src/main.c:348 ../src/nm-iface-helper.c:397 #, c-format msgid "Ignoring unrecognized log domain(s) '%s' passed on command line.\n" msgstr "Ignorerar okända loggdomän(en|er) ”%s” given via kommandoraden.\n" @@ -9581,7 +9582,7 @@ msgstr "Fel i konfigurationsfilen: %s.\n" msgid "Ignoring unrecognized log domain(s) '%s' from config files.\n" msgstr "Ignorerar okända loggdomän(en|er) ”%s” från konfigurationsfiler.\n" -#: ../src/main.c:389 ../src/nm-iface-helper.c:408 +#: ../src/main.c:389 ../src/nm-iface-helper.c:407 #, c-format msgid "Could not daemonize: %s [error %u]\n" msgstr "Kunde inte bli demon: %s [fel %u]\n" @@ -9674,8 +9675,8 @@ msgid "Unknown/unhandled Bluetooth connection type" msgstr "Okänd/ohanterad Bluetooth-anslutningstyp" #: ../src/devices/bluetooth/nm-device-bt.c:336 -#: ../src/devices/nm-device-ethernet.c:1420 -#: ../src/devices/nm-device-infiniband.c:193 +#: ../src/devices/nm-device-ethernet.c:1415 +#: ../src/devices/nm-device-infiniband.c:192 #: ../src/devices/wifi/nm-device-wifi.c:872 msgid "connection does not match device" msgstr "anslutning matchar inte enhet" @@ -9688,11 +9689,11 @@ msgstr "Kombinationsanslutning" msgid "Bridge connection" msgstr "Brygganslutning" -#: ../src/devices/nm-device-ethernet.c:1401 +#: ../src/devices/nm-device-ethernet.c:1396 msgid "PPPoE connection" msgstr "PPPoE-anslutning" -#: ../src/devices/nm-device-ethernet.c:1401 +#: ../src/devices/nm-device-ethernet.c:1396 msgid "Wired connection" msgstr "Trådbunden anslutning" @@ -9701,7 +9702,7 @@ msgstr "Trådbunden anslutning" msgid "Wired connection %d" msgstr "Trådbunden anslutning %d" -#: ../src/devices/nm-device-infiniband.c:175 +#: ../src/devices/nm-device-infiniband.c:174 msgid "InfiniBand connection" msgstr "InfiniBand-anslutning" @@ -9709,7 +9710,7 @@ msgstr "InfiniBand-anslutning" msgid "IP tunnel connection" msgstr "IP-tunnelanslutning" -#: ../src/devices/nm-device-macvlan.c:435 +#: ../src/devices/nm-device-macvlan.c:428 msgid "MACVLAN connection" msgstr "MACVLAN-anslutning" @@ -9717,7 +9718,7 @@ msgstr "MACVLAN-anslutning" msgid "TUN connection" msgstr "TUN-anslutning" -#: ../src/devices/nm-device-vlan.c:457 +#: ../src/devices/nm-device-vlan.c:447 msgid "VLAN connection" msgstr "VLAN-anslutning" @@ -9930,7 +9931,7 @@ msgstr "Lista över insticksmoduler separerade med ”,”" msgid "Quit after initial configuration" msgstr "Avsluta efter initial konfiguration" -#: ../src/nm-config.c:472 ../src/nm-iface-helper.c:300 +#: ../src/nm-config.c:472 ../src/nm-iface-helper.c:299 msgid "Don't become a daemon, and log to stderr" msgstr "Bli inte en demon, och logga till stderr" @@ -9948,94 +9949,94 @@ msgid "The expected start of the response" msgstr "Den förväntade starten på svaret" #. Interface/IP config -#: ../src/nm-iface-helper.c:281 +#: ../src/nm-iface-helper.c:280 msgid "The interface to manage" msgstr "Gränssnittet att hantera" -#: ../src/nm-iface-helper.c:281 +#: ../src/nm-iface-helper.c:280 msgid "eth0" msgstr "eth0" -#: ../src/nm-iface-helper.c:282 +#: ../src/nm-iface-helper.c:281 msgid "Connection UUID" msgstr "UUID för anslutning" -#: ../src/nm-iface-helper.c:282 +#: ../src/nm-iface-helper.c:281 msgid "661e8cd0-b618-46b8-9dc9-31a52baaa16b" msgstr "661e8cd0-b618-46b8-9dc9-31a52baaa16b" -#: ../src/nm-iface-helper.c:283 +#: ../src/nm-iface-helper.c:282 msgid "Whether to manage IPv6 SLAAC" msgstr "Huruvida IPv6 SLAAC ska hanteras" -#: ../src/nm-iface-helper.c:284 +#: ../src/nm-iface-helper.c:283 msgid "Whether SLAAC must be successful" msgstr "Huruvida SLAAC måste lyckas" -#: ../src/nm-iface-helper.c:285 +#: ../src/nm-iface-helper.c:284 msgid "Use an IPv6 temporary privacy address" msgstr "Använd en temporär IPv6-adress för sekretess" -#: ../src/nm-iface-helper.c:286 +#: ../src/nm-iface-helper.c:285 msgid "Current DHCPv4 address" msgstr "Aktuell DCHPv4-adress" -#: ../src/nm-iface-helper.c:287 +#: ../src/nm-iface-helper.c:286 msgid "Whether DHCPv4 must be successful" msgstr "Huruvida DHCPv4 måste lyckas" -#: ../src/nm-iface-helper.c:288 +#: ../src/nm-iface-helper.c:287 msgid "Hex-encoded DHCPv4 client ID" msgstr "Hexkodat DHCPv4 klient-ID" -#: ../src/nm-iface-helper.c:289 +#: ../src/nm-iface-helper.c:288 msgid "Hostname to send to DHCP server" msgstr "Värdnamn att skicka till DHCP-server" -#: ../src/nm-iface-helper.c:289 +#: ../src/nm-iface-helper.c:288 msgid "barbar" msgstr "barbar" -#: ../src/nm-iface-helper.c:290 +#: ../src/nm-iface-helper.c:289 msgid "FQDN to send to DHCP server" msgstr "FQDN att skicka till DHCP-server" -#: ../src/nm-iface-helper.c:290 +#: ../src/nm-iface-helper.c:289 msgid "host.domain.org" msgstr "host.domain.org" -#: ../src/nm-iface-helper.c:291 +#: ../src/nm-iface-helper.c:290 msgid "Route priority for IPv4" msgstr "Ruttprioritet för IPv4" -#: ../src/nm-iface-helper.c:291 +#: ../src/nm-iface-helper.c:290 msgid "0" msgstr "0" -#: ../src/nm-iface-helper.c:292 +#: ../src/nm-iface-helper.c:291 msgid "Route priority for IPv6" msgstr "Ruttprioritet för IPv6" -#: ../src/nm-iface-helper.c:292 +#: ../src/nm-iface-helper.c:291 msgid "1024" msgstr "1024" -#: ../src/nm-iface-helper.c:293 +#: ../src/nm-iface-helper.c:292 msgid "Hex-encoded Interface Identifier" msgstr "Hexkodad gränssnittsidentifierare" -#: ../src/nm-iface-helper.c:294 +#: ../src/nm-iface-helper.c:293 msgid "IPv6 SLAAC address generation mode" msgstr "SLAAC-adressgenereringsläge för IPv6" -#: ../src/nm-iface-helper.c:295 +#: ../src/nm-iface-helper.c:294 msgid "" "The logging backend configuration value. See logging.backend in " "NetworkManager.conf" msgstr "" "Loggbakändens konfigurationsvärde. Se logging.backend i NetworkManager.conf" -#: ../src/nm-iface-helper.c:315 +#: ../src/nm-iface-helper.c:314 msgid "" "nm-iface-helper is a small, standalone process that manages a single network " "interface." @@ -10043,17 +10044,17 @@ msgstr "" "nm-iface-helper är en liten fristående process som hanterar ett enstaka " "nätverksgränssnitt." -#: ../src/nm-iface-helper.c:374 +#: ../src/nm-iface-helper.c:373 #, c-format msgid "An interface name and UUID are required\n" msgstr "Kräver ett gränssnittsnamn och UUID\n" -#: ../src/nm-iface-helper.c:380 +#: ../src/nm-iface-helper.c:379 #, c-format msgid "Failed to find interface index for %s (%s)\n" msgstr "Misslyckades med att hitta gränssnittsindex för %s (%s)\n" -#: ../src/nm-iface-helper.c:442 +#: ../src/nm-iface-helper.c:441 #, c-format msgid "(%s): Invalid IID %s\n" msgstr "(%s): Ogiltig IID %s\n" @@ -10068,7 +10069,7 @@ msgstr "Okänd loggnivå ”%s”" msgid "Unknown log domain '%s'" msgstr "Okänd loggdomän ”%s”" -#: ../src/nm-manager.c:3635 +#: ../src/nm-manager.c:3625 msgid "VPN connection" msgstr "VPN-anslutning" @@ -10080,18 +10081,6 @@ msgstr "Nätverkshanteraren behöver stänga av nätverk" msgid "System" msgstr "System" -#~ msgid "Error: not all connections reapplied." -#~ msgstr "Fel: alla anslutningar har inte uppdaterats." - -#~ msgid "Error: no valid device provided." -#~ msgstr "Fel: ingen giltig enhet tillhandahållen." - -#~ msgid "Error converting IP4 address '0x%X' to text form" -#~ msgstr "Fel vid konvertering av IP4-adress ”0x%X” till textformat" - -#~ msgid "Error converting IP6 address '%s' to text form" -#~ msgstr "Fel vid konvertering av IP6-adress ”%s” till textformat" - #~ msgid "Error: unknown parameter: %s" #~ msgstr "Fel: okänd parameter: %s" diff --git a/shared/nm-macros-internal.h b/shared/nm-macros-internal.h index e584b9d031..7a5c90fc53 100644 --- a/shared/nm-macros-internal.h +++ b/shared/nm-macros-internal.h @@ -27,6 +27,9 @@ /********************************************************/ #define _nm_packed __attribute__ ((packed)) +#define _nm_unused __attribute__ ((unused)) +#define _nm_pure __attribute__ ((pure)) +#define _nm_const __attribute__ ((const)) #define nm_auto(fcn) __attribute__ ((cleanup(fcn))) @@ -296,6 +299,22 @@ _NM_IN_STRSET_streq (const char *x, const char *s) /*****************************************************************************/ +/* glib/C provides the following kind of assertions: + * - assert() -- disable with NDEBUG + * - g_return_if_fail() -- disable with G_DISABLE_CHECKS + * - g_assert() -- disable with G_DISABLE_ASSERT + * but they are all enabled by default and usually even production builds have + * these kind of assertions enabled. It also means, that disabling assertions + * is an untested configuration, and might have bugs. + * + * Add our own assertion macro nm_assert(), which is disabled by default and must + * be explicitly enabled. They are useful for more expensive checks or checks that + * depend less on runtime conditions (that is, are generally expected to be true). */ + +#ifndef NM_MORE_ASSERTS +#define NM_MORE_ASSERTS 0 +#endif + #if NM_MORE_ASSERTS #define nm_assert(cond) G_STMT_START { g_assert (cond); } G_STMT_END #define nm_assert_not_reached() G_STMT_START { g_assert_not_reached (); } G_STMT_END diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h index b792a69c85..ad3cad650f 100644 --- a/shared/nm-test-utils.h +++ b/shared/nm-test-utils.h @@ -101,13 +101,6 @@ #include "nm-utils.h" -#ifdef __NETWORKMANAGER_LOGGING_H__ -/* We are running tests under src/. Let's include some files by default. - * They are useful, and affect how nm-test-utils.h itself behaves. */ -#include "NetworkManagerUtils.h" -#include "nm-keyfile-internal.h" -#endif - /*******************************************************************************/ /* general purpose functions that have no dependency on other nmtst functions */ @@ -153,13 +146,11 @@ g_assert_not_reached (); \ } G_STMT_END -inline static void -_nmtst_assert_success (gboolean success, GError *error, const char *file, int line) -{ - if (!success || error) - g_error ("(%s:%d) FAILURE success=%d, error=%s", file, line, success, error ? error->message : "(no error)"); -} -#define nmtst_assert_success(success, error) _nmtst_assert_success ((success), (error), __FILE__, __LINE__) +#define nmtst_assert_success(success, error) \ + G_STMT_START { \ + g_assert_no_error (error); \ + g_assert ((success)); \ + } G_STMT_END #define nmtst_assert_no_success(success, error) \ G_STMT_START { \ @@ -512,7 +503,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ if (!__nmtst_internal.assert_logging) { gboolean success = TRUE; -#ifdef __NETWORKMANAGER_LOGGING_H__ +#ifdef _NMTST_INSIDE_CORE success = nm_logging_setup (log_level, log_domains, NULL, NULL); *out_set_logging = TRUE; #endif @@ -529,7 +520,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ * This transforms g_test_expect_message() into a NOP, but we also have to relax * g_log_set_always_fatal(), which was set by g_test_init(). */ g_log_set_always_fatal (G_LOG_FATAL_MASK); -#ifdef __NETWORKMANAGER_LOGGING_H__ +#ifdef _NMTST_INSIDE_CORE if (c_log_domains || c_log_level) { /* Normally, tests with assert_logging do not overwrite the logging level/domains because * the logging statements are part of the assertions. But if the test is run with @@ -590,27 +581,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ #endif } -#ifdef __NETWORKMANAGER_LOGGING_H__ -inline static void -nmtst_init_with_logging (int *argc, char ***argv, const char *log_level, const char *log_domains) -{ - __nmtst_init (argc, argv, FALSE, log_level, log_domains, NULL); -} -inline static void -nmtst_init_assert_logging (int *argc, char ***argv, const char *log_level, const char *log_domains) -{ - gboolean set_logging; - - __nmtst_init (argc, argv, TRUE, NULL, NULL, &set_logging); - - if (!set_logging) { - gboolean success; - - success = nm_logging_setup (log_level, log_domains, NULL, NULL); - g_assert (success); - } -} -#else +#ifndef _NMTST_INSIDE_CORE inline static void nmtst_init (int *argc, char ***argv, gboolean assert_logging) { @@ -1177,247 +1148,6 @@ _nmtst_assert_resolve_relative_path_equals (const char *f1, const char *f2, cons /*******************************************************************************/ -#ifdef __NETWORKMANAGER_PLATFORM_H__ - -inline static NMPlatformIP4Address * -nmtst_platform_ip4_address (const char *address, const char *peer_address, guint plen) -{ - static NMPlatformIP4Address addr; - - g_assert (plen <= 32); - - memset (&addr, 0, sizeof (addr)); - addr.address = nmtst_inet4_from_string (address); - if (peer_address) - addr.peer_address = nmtst_inet4_from_string (peer_address); - else - addr.peer_address = addr.address; - addr.plen = plen; - - return &addr; -} - -inline static NMPlatformIP4Address * -nmtst_platform_ip4_address_full (const char *address, const char *peer_address, guint plen, - int ifindex, NMIPConfigSource source, guint32 timestamp, - guint32 lifetime, guint32 preferred, guint32 flags, - const char *label) -{ - NMPlatformIP4Address *addr = nmtst_platform_ip4_address (address, peer_address, plen); - - G_STATIC_ASSERT (IFNAMSIZ == sizeof (addr->label)); - g_assert (!label || strlen (label) < IFNAMSIZ); - - addr->ifindex = ifindex; - addr->source = source; - addr->timestamp = timestamp; - addr->lifetime = lifetime; - addr->preferred = preferred; - addr->n_ifa_flags = flags; - if (label) - g_strlcpy (addr->label, label, sizeof (addr->label)); - - return addr; -} - -inline static NMPlatformIP6Address * -nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen) -{ - static NMPlatformIP6Address addr; - - g_assert (plen <= 128); - - memset (&addr, 0, sizeof (addr)); - addr.address = *nmtst_inet6_from_string (address); - addr.peer_address = *nmtst_inet6_from_string (peer_address); - addr.plen = plen; - - return &addr; -} - -inline static NMPlatformIP6Address * -nmtst_platform_ip6_address_full (const char *address, const char *peer_address, guint plen, - int ifindex, NMIPConfigSource source, guint32 timestamp, - guint32 lifetime, guint32 preferred, guint32 flags) -{ - NMPlatformIP6Address *addr = nmtst_platform_ip6_address (address, peer_address, plen); - - addr->ifindex = ifindex; - addr->source = source; - addr->timestamp = timestamp; - addr->lifetime = lifetime; - addr->preferred = preferred; - addr->n_ifa_flags = flags; - - return addr; -} - -inline static NMPlatformIP4Route * -nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway) -{ - static NMPlatformIP4Route route; - - g_assert (plen <= 32); - - memset (&route, 0, sizeof (route)); - route.network = nmtst_inet4_from_string (network); - route.plen = plen; - route.gateway = nmtst_inet4_from_string (gateway); - - return &route; -} - -inline static NMPlatformIP4Route * -nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway, - int ifindex, NMIPConfigSource source, - guint metric, guint mss, - guint8 scope, - const char *pref_src) -{ - NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway); - - route->ifindex = ifindex; - route->source = source; - route->metric = metric; - route->mss = mss; - route->scope_inv = nm_platform_route_scope_inv (scope); - route->pref_src = nmtst_inet4_from_string (pref_src); - - return route; -} - -inline static NMPlatformIP6Route * -nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) -{ - static NMPlatformIP6Route route; - - nm_assert (plen <= 128); - - memset (&route, 0, sizeof (route)); - route.network = *nmtst_inet6_from_string (network); - route.plen = plen; - route.gateway = *nmtst_inet6_from_string (gateway); - - return &route; -} - -inline static NMPlatformIP6Route * -nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway, - int ifindex, NMIPConfigSource source, - guint metric, guint mss) -{ - NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway); - - route->ifindex = ifindex; - route->source = source; - route->metric = metric; - route->mss = mss; - - return route; -} - -inline static int -_nmtst_platform_ip4_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data) -{ - return nm_platform_ip4_route_cmp ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b); -} - -inline static void -nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len, gboolean ignore_order) -{ - gsize i; - gs_free const NMPlatformIP4Route *c_a = NULL, *c_b = NULL; - - g_assert (a); - g_assert (b); - - if (ignore_order) { - a = c_a = g_memdup (a, sizeof (NMPlatformIP4Route) * len); - b = c_b = g_memdup (b, sizeof (NMPlatformIP4Route) * len); - g_qsort_with_data (c_a, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL); - g_qsort_with_data (c_b, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL); - } - - for (i = 0; i < len; i++) { - if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) { - char buf[sizeof (_nm_utils_to_string_buffer)]; - - g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (long unsigned) i, - nm_platform_ip4_route_to_string (&a[i], NULL, 0), - nm_platform_ip4_route_to_string (&b[i], buf, sizeof (buf))); - g_assert_not_reached (); - } - } -} - -inline static int -_nmtst_platform_ip6_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data) -{ - return nm_platform_ip6_route_cmp ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b); -} - -inline static void -nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len, gboolean ignore_order) -{ - gsize i; - gs_free const NMPlatformIP6Route *c_a = NULL, *c_b = NULL; - - g_assert (a); - g_assert (b); - - if (ignore_order) { - a = c_a = g_memdup (a, sizeof (NMPlatformIP6Route) * len); - b = c_b = g_memdup (b, sizeof (NMPlatformIP6Route) * len); - g_qsort_with_data (c_a, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL); - g_qsort_with_data (c_b, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL); - } - - for (i = 0; i < len; i++) { - if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) { - char buf[sizeof (_nm_utils_to_string_buffer)]; - - g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (long unsigned) i, - nm_platform_ip6_route_to_string (&a[i], NULL, 0), - nm_platform_ip6_route_to_string (&b[i], buf, sizeof (buf))); - g_assert_not_reached (); - } - } -} - -#endif - - -#ifdef __NETWORKMANAGER_IP4_CONFIG_H__ - -inline static NMIP4Config * -nmtst_ip4_config_clone (NMIP4Config *config) -{ - NMIP4Config *copy = nm_ip4_config_new (-1); - - g_assert (copy); - g_assert (config); - nm_ip4_config_replace (copy, config, NULL); - return copy; -} - -#endif - - -#ifdef __NETWORKMANAGER_IP6_CONFIG_H__ - -inline static NMIP6Config * -nmtst_ip6_config_clone (NMIP6Config *config) -{ - NMIP6Config *copy = nm_ip6_config_new (-1); - - g_assert (copy); - g_assert (config); - nm_ip6_config_replace (copy, config, NULL); - return copy; -} - -#endif - #ifdef NM_SETTING_IP_CONFIG_H inline static void nmtst_setting_ip_config_add_address (NMSettingIPConfig *s_ip, diff --git a/shared/nm-version-macros.h.in b/shared/nm-version-macros.h.in index 3e0ef361c0..3df95ffe51 100644 --- a/shared/nm-version-macros.h.in +++ b/shared/nm-version-macros.h.in @@ -70,7 +70,6 @@ #define NM_VERSION_1_2 (NM_ENCODE_VERSION (1, 2, 0)) #define NM_VERSION_1_2_2 (NM_ENCODE_VERSION (1, 2, 2)) #define NM_VERSION_1_2_4 (NM_ENCODE_VERSION (1, 2, 4)) -#define NM_VERSION_1_4 (NM_ENCODE_VERSION (1, 4, 0)) #define NM_VERSION_CUR_STABLE NM_VERSION_1_2_2 #define NM_VERSION_NEXT_STABLE NM_VERSION_1_2_4 diff --git a/src/Makefile.am b/src/Makefile.am index 652aae6f9b..e61e5aa9dd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -74,6 +74,8 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/escape.h \ systemd/src/basic/ether-addr-util.c \ systemd/src/basic/ether-addr-util.h \ + systemd/src/basic/extract-word.c \ + systemd/src/basic/extract-word.h \ systemd/src/basic/fd-util.c \ systemd/src/basic/fd-util.h \ systemd/src/basic/fileio.c \ @@ -107,6 +109,7 @@ libsystemd_nm_la_SOURCES = \ systemd/src/basic/random-util.h \ systemd/src/basic/refcnt.h \ systemd/src/basic/set.h \ + systemd/src/basic/signal-util.h \ systemd/src/basic/siphash24.c \ systemd/src/basic/siphash24.h \ systemd/src/basic/socket-util.c \ @@ -394,8 +397,6 @@ libNetworkManager_la_SOURCES = \ nm-config.h \ nm-config-data.c \ nm-config-data.h \ - nm-connection-provider.c \ - nm-connection-provider.h \ nm-connectivity.c \ nm-connectivity.h \ nm-dcb.c \ @@ -478,6 +479,7 @@ AM_CPPFLAGS += \ $(SYSTEMD_LOGIN_CFLAGS) \ $(SYSTEMD_JOURNAL_CFLAGS) \ $(SYSTEMD_NM_CFLAGS_PATHS) \ + $(CODE_COVERAGE_CFLAGS) \ \ -DBINDIR=\"$(bindir)\" \ -DDATADIR=\"$(datadir)\" \ @@ -501,6 +503,8 @@ AM_CPPFLAGS += \ \ $(NULL) +AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) + libNetworkManager_la_LIBADD = \ $(top_builddir)/libnm-core/libnm-core.la \ $(top_builddir)/introspection/libnmdbus.la \ @@ -626,6 +630,7 @@ dbusservice_DATA = org.freedesktop.NetworkManager.conf EXTRA_DIST = \ $(dbusservice_DATA) \ $(NetworkManager_DATA) \ + nm-test-utils-core.h \ NetworkManager.ver rundir=$(runstatedir)/NetworkManager diff --git a/src/NetworkManager.ver b/src/NetworkManager.ver index b4397b9c20..c91affcb5f 100644 --- a/src/NetworkManager.ver +++ b/src/NetworkManager.ver @@ -1,6 +1,7 @@ { global: - nm*; + nm_*; + nmp_*; _nm*; NM*; _NM*; diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index dcfa5eec24..3463da6be8 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -28,6 +28,7 @@ #include "nm-bt-error.h" #include "nm-bluez-common.h" #include "nm-bluez-device.h" +#include "nm-settings.h" #include "nm-settings-connection.h" #include "NetworkManagerUtils.h" @@ -67,7 +68,7 @@ typedef struct { NMBluez5DunContext *b5_dun_context; #endif - NMConnectionProvider *provider; + NMSettings *settings; GSList *connections; NMConnection *pan_connection; @@ -96,7 +97,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void cp_connection_added (NMConnectionProvider *provider, +static void cp_connection_added (NMSettings *settings, NMConnection *connection, NMBluezDevice *self); static gboolean connection_compatible (NMBluezDevice *self, NMConnection *connection); @@ -233,9 +234,9 @@ pan_connection_check_create (NMBluezDevice *self) /* Adding a new connection raises a signal which eventually calls check_emit_usable (again) * which then already finds the suitable connection in priv->connections. This is confusing, * so block the signal. check_emit_usable will succeed after this function call returns. */ - g_signal_handlers_block_by_func (priv->provider, cp_connection_added, self); - added = nm_connection_provider_add_connection (priv->provider, connection, FALSE, &error); - g_signal_handlers_unblock_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_block_by_func (priv->settings, cp_connection_added, self); + added = NM_CONNECTION (nm_settings_add_connection (priv->settings, connection, FALSE, &error)); + g_signal_handlers_unblock_by_func (priv->settings, cp_connection_added, self); if (added) { g_assert (!g_slist_find (priv->connections, added)); @@ -367,7 +368,7 @@ _internal_track_connection (NMBluezDevice *self, NMConnection *connection, gbool } static void -cp_connection_added (NMConnectionProvider *provider, +cp_connection_added (NMSettings *settings, NMConnection *connection, NMBluezDevice *self) { @@ -378,7 +379,7 @@ cp_connection_added (NMConnectionProvider *provider, } static void -cp_connection_removed (NMConnectionProvider *provider, +cp_connection_removed (NMSettings *settings, NMConnection *connection, NMBluezDevice *self) { @@ -387,8 +388,9 @@ cp_connection_removed (NMConnectionProvider *provider, } static void -cp_connection_updated (NMConnectionProvider *provider, +cp_connection_updated (NMSettings *settings, NMConnection *connection, + gboolean by_user, NMBluezDevice *self) { if (_internal_track_connection (self, connection, @@ -400,12 +402,13 @@ static void load_connections (NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - const GSList *connections, *iter; + NMSettingsConnection *const*connections; + guint i; gboolean changed = FALSE; - connections = nm_connection_provider_get_connections (priv->provider); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = iter->data; + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *connection = (NMConnection *) connections[i]; if (connection_compatible (self, connection)) changed |= _internal_track_connection (self, connection, TRUE); @@ -1029,7 +1032,7 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) NMBluezDevice * nm_bluez_device_new (const char *path, const char *adapter_address, - NMConnectionProvider *provider, + NMSettings *settings, int bluez_version) { NMBluezDevice *self; @@ -1037,7 +1040,7 @@ nm_bluez_device_new (const char *path, const char *interface_name = NULL; g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (provider), NULL); + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); g_return_val_if_fail (bluez_version == 4 || bluez_version == 5, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, @@ -1051,14 +1054,14 @@ nm_bluez_device_new (const char *path, priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); priv->bluez_version = bluez_version; - priv->provider = g_object_ref (provider); + priv->settings = g_object_ref (settings); g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL); if (adapter_address) set_adapter_address (self, adapter_address); - g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); - g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); - g_signal_connect (priv->provider, NM_CP_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, G_CALLBACK (cp_connection_added), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, G_CALLBACK (cp_connection_removed), self); + g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, G_CALLBACK (cp_connection_updated), self); g_bus_get (G_BUS_TYPE_SYSTEM, NULL, @@ -1116,10 +1119,10 @@ dispose (GObject *object) } #endif - if (priv->provider) { - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); - g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + if (priv->settings) { + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); } g_slist_free_full (priv->connections, g_object_unref); @@ -1137,7 +1140,7 @@ dispose (GObject *object) g_object_unref (to_delete); } - g_clear_object (&priv->provider); + g_clear_object (&priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h index c956054074..66a349e0db 100644 --- a/src/devices/bluetooth/nm-bluez-device.h +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -22,7 +22,6 @@ #define __NETWORKMANAGER_BLUEZ_DEVICE_H__ #include "nm-connection.h" -#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) #define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) @@ -59,7 +58,7 @@ GType nm_bluez_device_get_type (void); NMBluezDevice *nm_bluez_device_new (const char *path, const char *adapter_address, - NMConnectionProvider *provider, + NMSettings *settings, int bluez_version); const char *nm_bluez_device_get_path (NMBluezDevice *self); diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index 766ecc0abc..0d2e302cfc 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -20,19 +20,20 @@ #include "nm-default.h" +#include "nm-bluez-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> #include <gmodule.h> -#include "nm-bluez-manager.h" #include "nm-device-factory.h" #include "nm-setting-bluetooth.h" +#include "nm-settings.h" #include "nm-bluez4-manager.h" #include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" -#include "nm-connection-provider.h" #include "nm-device-bt.h" #include "nm-core-internal.h" #include "nm-platform.h" @@ -51,7 +52,7 @@ typedef struct { int bluez_version; - NMConnectionProvider *provider; + NMSettings *settings; NMBluez4Manager *manager4; NMBluez5Manager *manager5; @@ -190,7 +191,7 @@ setup_bluez4 (NMBluezManager *self) g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); setup_version_number (self, 4); - priv->manager4 = manager = nm_bluez4_manager_new (priv->provider); + priv->manager4 = manager = nm_bluez4_manager_new (priv->settings); g_signal_connect (manager, NM_BLUEZ_MANAGER_BDADDR_ADDED, @@ -209,7 +210,7 @@ setup_bluez5 (NMBluezManager *self) g_return_if_fail (!priv->manager4 && !priv->manager5 && !priv->bluez_version); setup_version_number (self, 5); - priv->manager5 = manager = nm_bluez5_manager_new (priv->provider); + priv->manager5 = manager = nm_bluez5_manager_new (priv->settings); g_signal_connect (manager, NM_BLUEZ_MANAGER_BDADDR_ADDED, @@ -407,9 +408,9 @@ dispose (GObject *object) priv->bluez_version = 0; - g_clear_object (&priv->provider); - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); + + g_clear_object (&priv->settings); } static void @@ -417,7 +418,7 @@ nm_bluez_manager_init (NMBluezManager *self) { NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); - priv->provider = g_object_ref (nm_connection_provider_get ()); + priv->settings = g_object_ref (NM_SETTINGS_GET); } static NMDevice * diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/devices/bluetooth/nm-bluez-manager.h index 1f5597d831..d23b33a7d8 100644 --- a/src/devices/bluetooth/nm-bluez-manager.h +++ b/src/devices/bluetooth/nm-bluez-manager.h @@ -22,10 +22,6 @@ #ifndef __NETWORKMANAGER_BLUEZ_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ_MANAGER_H__ -#include "nm-default.h" - -G_BEGIN_DECLS - #define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) #define NM_BLUEZ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManager)) diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index 9d8fd21056..2ef071a8bf 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -20,13 +20,15 @@ #include "nm-default.h" +#include "nm-bluez4-adapter.h" + #include <string.h> #include "nm-dbus-interface.h" -#include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" +#include "nm-settings.h" G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) @@ -41,7 +43,7 @@ typedef struct { GHashTable *devices; /* Cached for devices */ - NMConnectionProvider *provider; + NMSettings *settings; } NMBluez4AdapterPrivate; @@ -160,7 +162,7 @@ device_created (GDBusProxy *proxy, const char *path, gpointer user_data) NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path, priv->address, priv->provider, 4); + device = nm_bluez_device_new (path, priv->address, priv->settings, 4); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -234,17 +236,19 @@ query_properties (NMBluez4Adapter *self) /***********************************************************/ NMBluez4Adapter * -nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) +nm_bluez4_adapter_new (const char *path, NMSettings *settings) { NMBluez4Adapter *self; NMBluez4AdapterPrivate *priv; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, NM_BLUEZ4_ADAPTER_PATH, path, NULL); priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - priv->provider = provider; + priv->settings = g_object_ref (settings); priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, @@ -301,6 +305,8 @@ finalize (GObject *object) g_object_unref (priv->proxy); G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object); + + g_object_unref (priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h index a8a2bfb4d2..ee61112f2e 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.h +++ b/src/devices/bluetooth/nm-bluez4-adapter.h @@ -21,10 +21,7 @@ #ifndef __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ #define __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ - -#include "nm-default.h" #include "nm-bluez-device.h" -#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ4_ADAPTER (nm_bluez4_adapter_get_type ()) #define NM_BLUEZ4_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ4_ADAPTER, NMBluez4Adapter)) @@ -54,7 +51,7 @@ typedef struct { GType nm_bluez4_adapter_get_type (void); NMBluez4Adapter *nm_bluez4_adapter_new (const char *path, - NMConnectionProvider *provider); + NMSettings *settings); const char *nm_bluez4_adapter_get_path (NMBluez4Adapter *self); diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index 146612a890..36bc30e59c 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -21,20 +21,22 @@ #include "nm-default.h" +#include "nm-bluez4-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> -#include "nm-bluez-manager.h" -#include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" +#include "nm-bluez-manager.h" #include "nm-bluez-common.h" #include "nm-core-internal.h" +#include "nm-settings.h" typedef struct { gulong name_owner_changed_id; - NMConnectionProvider *provider; + NMSettings *settings; GDBusProxy *proxy; @@ -155,7 +157,7 @@ default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *s /* Add the new default adapter */ if (path) { - priv->adapter = nm_bluez4_adapter_new (path, priv->provider); + priv->adapter = nm_bluez4_adapter_new (path, priv->settings); g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); } } @@ -223,12 +225,14 @@ name_owner_changed_cb (GObject *object, /****************************************************************/ NMBluez4Manager * -nm_bluez4_manager_new (NMConnectionProvider *provider) +nm_bluez4_manager_new (NMSettings *settings) { NMBluez4Manager *instance; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + instance = g_object_new (NM_TYPE_BLUEZ4_MANAGER, NULL); - NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->provider = provider; + NM_BLUEZ4_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); return instance; } @@ -264,6 +268,8 @@ dispose (GObject *object) g_clear_object (&priv->adapter); G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); + + g_clear_object (&priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez4-manager.h b/src/devices/bluetooth/nm-bluez4-manager.h index f6bf76586b..dbf7688940 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.h +++ b/src/devices/bluetooth/nm-bluez4-manager.h @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager -- Network link manager * * This program is free software; you can redistribute it and/or modify @@ -23,7 +22,6 @@ #define __NETWORKMANAGER_BLUEZ4_MANAGER_H__ #include "nm-default.h" -#include "nm-connection-provider.h" G_BEGIN_DECLS @@ -51,7 +49,7 @@ typedef struct { GType nm_bluez4_manager_get_type (void); -NMBluez4Manager *nm_bluez4_manager_new (NMConnectionProvider *provider); +NMBluez4Manager *nm_bluez4_manager_new (NMSettings *settings); void nm_bluez4_manager_query_devices (NMBluez4Manager *manager); diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index 66d171bf2e..183f23c1e4 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -22,19 +22,21 @@ #include "nm-default.h" +#include "nm-bluez5-manager.h" + #include <signal.h> #include <string.h> #include <stdlib.h> +#include "nm-core-internal.h" + #include "nm-bluez-manager.h" -#include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" - -#include "nm-core-internal.h" +#include "nm-settings.h" typedef struct { - NMConnectionProvider *provider; + NMSettings *settings; GDBusProxy *proxy; @@ -140,7 +142,7 @@ device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path, NULL, priv->provider, 5); + device = nm_bluez_device_new (path, NULL, priv->settings, 5); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); @@ -309,12 +311,14 @@ bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) /****************************************************************/ NMBluez5Manager * -nm_bluez5_manager_new (NMConnectionProvider *provider) +nm_bluez5_manager_new (NMSettings *settings) { NMBluez5Manager *instance = NULL; + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + instance = g_object_new (NM_TYPE_BLUEZ5_MANAGER, NULL); - NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->provider = provider; + NM_BLUEZ5_MANAGER_GET_PRIVATE (instance)->settings = g_object_ref (settings); return instance; } @@ -347,6 +351,8 @@ finalize (GObject *object) g_hash_table_destroy (priv->devices); G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->finalize (object); + + g_object_unref (priv->settings); } static void diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h index 1c531090b7..0e309d33a3 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -22,11 +22,6 @@ #ifndef __NETWORKMANAGER_BLUEZ5_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ5_MANAGER_H__ -#include "nm-default.h" -#include "nm-connection-provider.h" - -G_BEGIN_DECLS - #define NM_TYPE_BLUEZ5_MANAGER (nm_bluez5_manager_get_type ()) #define NM_BLUEZ5_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ5_MANAGER, NMBluez5Manager)) #define NM_BLUEZ5_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ5_MANAGER, NMBluez5ManagerClass)) @@ -51,7 +46,7 @@ typedef struct { GType nm_bluez5_manager_get_type (void); -NMBluez5Manager *nm_bluez5_manager_new (NMConnectionProvider *provider); +NMBluez5Manager *nm_bluez5_manager_new (NMSettings *settings); void nm_bluez5_manager_query_devices (NMBluez5Manager *manager); diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index eef4ed0a1b..8f3772c69b 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -362,6 +362,7 @@ static void ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDeviceBt *self = NM_DEVICE_BT (user_data); switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -375,7 +376,18 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) case NM_DEVICE_STATE_ACTIVATED: if (nm_device_activate_ip4_state_in_conf (device)) nm_device_activate_schedule_ip4_config_timeout (device); - else { + else if (nm_device_activate_ip6_state_in_conf (device)) + nm_device_activate_schedule_ip6_config_timeout (device); + else if (nm_device_activate_ip4_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else if (nm_device_activate_ip6_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + _LOGW (LOGD_MB, "PPP failure in unexpected state %u", (guint) nm_device_get_state (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); @@ -502,8 +514,9 @@ modem_ip4_config_result (NMModem *modem, _LOGW (LOGD_MB | LOGD_IP4 | LOGD_BT, "retrieving IP4 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else nm_device_activate_schedule_ip4_config_result (device, config); } diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index d034ddfc77..298e6dff95 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -25,30 +25,26 @@ #include "nm-device-ethernet-utils.h" char * -nm_device_ethernet_utils_get_default_wired_name (const GSList *connections) +nm_device_ethernet_utils_get_default_wired_name (NMConnection *const *connections) { - const GSList *iter; - char *cname = NULL; - int i = 0; + char *temp; + guint j; + int i; /* Find the next available unique connection name */ - while (!cname && (i++ < 10000)) { - char *temp; - gboolean found = FALSE; - + for (i = 1; i <= 10000; i++) { temp = g_strdup_printf (_("Wired connection %d"), i); - for (iter = connections; iter; iter = iter->next) { - if (g_strcmp0 (nm_connection_get_id (NM_CONNECTION (iter->data)), temp) == 0) { - found = TRUE; + for (j = 0; connections[j]; j++) { + if (nm_streq0 (nm_connection_get_id (connections[j]), temp)) { g_free (temp); - break; + goto next; } } - - if (found == FALSE) - cname = temp; + return temp; +next: + ; } - return cname; + return NULL; } diff --git a/src/devices/nm-device-ethernet-utils.h b/src/devices/nm-device-ethernet-utils.h index 31d645d851..197d0a9ea4 100644 --- a/src/devices/nm-device-ethernet-utils.h +++ b/src/devices/nm-device-ethernet-utils.h @@ -19,8 +19,6 @@ #ifndef __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ #define __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ -#include "nm-default.h" - -char *nm_device_ethernet_utils_get_default_wired_name (const GSList *connections); +char *nm_device_ethernet_utils_get_default_wired_name (NMConnection *const *connections); #endif /* NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H */ diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index d27f7dcaf1..1367555b3e 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-device-ethernet.h" + #include <netinet/in.h> #include <string.h> #include <stdlib.h> @@ -29,7 +31,6 @@ #include <gudev/gudev.h> -#include "nm-device-ethernet.h" #include "nm-device-private.h" #include "nm-activation-request.h" #include "NetworkManagerUtils.h" @@ -44,7 +45,7 @@ #include "nm-settings-connection.h" #include "nm-config.h" #include "nm-device-ethernet-utils.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-device-factory.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" @@ -1435,7 +1436,7 @@ static NMConnection * new_default_connection (NMDevice *self) { NMConnection *connection; - const GSList *connections; + NMSettingsConnection *const*connections; NMSetting *setting; const char *hw_address; gs_free char *defname = NULL; @@ -1453,8 +1454,8 @@ new_default_connection (NMDevice *self) setting = nm_setting_connection_new (); nm_connection_add_setting (connection, setting); - connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); - defname = nm_device_ethernet_utils_get_default_wired_name (connections); + connections = nm_settings_get_connections (nm_device_get_settings (self), NULL); + defname = nm_device_ethernet_utils_get_default_wired_name ((NMConnection *const*) connections); if (!defname) return NULL; @@ -1581,7 +1582,6 @@ link_changed (NMDevice *device, NMPlatformLink *info) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - static const guint8 zero_hwaddr[ETH_ALEN]; const guint8 *hwaddr; gsize hwaddrlen = 0; @@ -1593,7 +1593,7 @@ link_changed (NMDevice *device, NMPlatformLink *info) hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ifindex (self), &hwaddrlen); - if (!nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, ETH_ALEN)) { + if (!nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth))) { _LOGD (LOGD_DEVICE, "device got a valid hw address"); nm_device_update_hw_address (self); nm_device_update_initial_hw_address (self); diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index 089b10352c..785010ebfa 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -20,19 +20,20 @@ #include "nm-default.h" +#include "nm-device-ip-tunnel.h" + #include <string.h> #include <netinet/in.h> #include <linux/if.h> #include <linux/ip.h> #include <linux/if_tunnel.h> -#include "nm-device-ip-tunnel.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-device-factory.h" #include "nm-core-internal.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" @@ -385,8 +386,8 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), - setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), + setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index c431fe891c..c5443ecd23 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -20,11 +20,12 @@ #include "nm-default.h" +#include "nm-device-macvlan.h" + #include <string.h> -#include "nm-device-macvlan.h" #include "nm-device-private.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-manager.h" #include "nm-platform.h" @@ -488,7 +489,7 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent); if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) new_parent = NULL; } diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 602c2c8575..418ae2d9ca 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -42,6 +42,8 @@ enum NMActStageReturn { #define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000 +NMSettings *nm_device_get_settings (NMDevice *self); + void nm_device_set_ip_iface (NMDevice *self, const char *iface); void nm_device_activate_schedule_stage3_ip_config_start (NMDevice *device); @@ -70,9 +72,11 @@ void nm_device_activate_schedule_ip6_config_timeout (NMDevice *device); gboolean nm_device_activate_ip4_state_in_conf (NMDevice *device); gboolean nm_device_activate_ip4_state_in_wait (NMDevice *device); +gboolean nm_device_activate_ip4_state_done (NMDevice *device); gboolean nm_device_activate_ip6_state_in_conf (NMDevice *device); gboolean nm_device_activate_ip6_state_in_wait (NMDevice *device); +gboolean nm_device_activate_ip6_state_done (NMDevice *device); void nm_device_set_dhcp_timeout (NMDevice *device, guint32 timeout); void nm_device_set_dhcp_anycast_address (NMDevice *device, const char *addr); @@ -103,6 +107,8 @@ void nm_device_queue_recheck_available (NMDevice *device, void nm_device_set_wwan_ip4_config (NMDevice *device, NMIP4Config *config); void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config); +void nm_device_ip_method_failed (NMDevice *self, int family, NMDeviceStateReason reason); + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value); #define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index eb6527de8e..95f36298f5 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -20,15 +20,16 @@ #include "nm-default.h" +#include "nm-device-vlan.h" + #include <sys/socket.h> -#include "nm-device-vlan.h" #include "nm-manager.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-enum-types.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" #include "nm-platform.h" @@ -515,7 +516,7 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), setting_parent); if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) new_parent = NULL; } diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index d308d47abc..f3dfbd9ef5 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -20,9 +20,10 @@ #include "nm-default.h" +#include "nm-device-vxlan.h" + #include <string.h> -#include "nm-device-vxlan.h" #include "nm-device-private.h" #include "nm-manager.h" #include "nm-platform.h" @@ -30,7 +31,7 @@ #include "nm-device-factory.h" #include "nm-setting-vxlan.h" #include "nm-setting-wired.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" @@ -411,8 +412,8 @@ update_connection (NMDevice *device, NMConnection *connection) NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ - parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), - setting_parent); + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (nm_device_get_settings (device), + setting_parent); if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) new_parent = NULL; } diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 5ece950900..88cebe4886 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -21,6 +21,8 @@ #include "nm-default.h" +#include "nm-device.h" + #include <netinet/in.h> #include <string.h> #include <unistd.h> @@ -34,7 +36,6 @@ #include <netlink/route/addr.h> #include <linux/if_addr.h> -#include "nm-device.h" #include "nm-device-private.h" #include "NetworkManagerUtils.h" #include "nm-manager.h" @@ -52,7 +53,7 @@ #include "nm-firewall-manager.h" #include "nm-enum-types.h" #include "nm-settings-connection.h" -#include "nm-connection-provider.h" +#include "nm-settings.h" #include "nm-auth-utils.h" #include "nm-dispatcher.h" #include "nm-config.h" @@ -72,7 +73,18 @@ _LOG_DECLARE_SELF (NMDevice); G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) -#define NM_DEVICE_GET_PRIVATE(o) ((o)->priv) +#define NM_DEVICE_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMDevice *_self2 = (_self); \ + \ + nm_assert (NM_IS_DEVICE (_self)); \ + _self->priv; \ + }) enum { STATE_CHANGED, @@ -134,6 +146,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice, #define PENDING_ACTION_DHCP6 "dhcp6" #define PENDING_ACTION_AUTOCONF6 "autoconf6" +#define DHCP_RESTART_TIMEOUT 120 +#define DHCP_NUM_TRIES_MAX 3 + typedef void (*ActivationHandleFunc) (NMDevice *self); typedef struct { @@ -163,9 +178,9 @@ typedef struct { typedef struct { NMDevice *slave; - gboolean slave_is_enslaved; - gboolean configure; gulong watch_id; + bool slave_is_enslaved; + bool configure; } SlaveInfo; typedef struct { @@ -193,7 +208,7 @@ typedef struct { } ArpingData; typedef struct _NMDevicePrivate { - gboolean in_state_changed; + bool in_state_changed; guint device_link_changed_id; guint device_ip_link_changed_id; @@ -209,7 +224,7 @@ typedef struct _NMDevicePrivate { char * udi; char * iface; /* may change, could be renamed by user */ int ifindex; - gboolean real; + bool real; char * ip_iface; int ip_ifindex; NMDeviceType type; @@ -221,8 +236,8 @@ typedef struct _NMDevicePrivate { char * driver_version; char * firmware_version; RfKillType rfkill_type; - gboolean firmware_missing; - gboolean nm_plugin_missing; + bool firmware_missing; + bool nm_plugin_missing; GHashTable * available_connections; char * hw_addr; guint hw_addr_len; @@ -233,7 +248,7 @@ typedef struct _NMDevicePrivate { NMUnmanagedFlags unmanaged_mask; NMUnmanagedFlags unmanaged_flags; - gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ + bool is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ GCancellable *deactivating_cancellable; @@ -241,7 +256,7 @@ typedef struct _NMDevicePrivate { guint32 ip4_address; NMActRequest * queued_act_request; - gboolean queued_act_request_is_waiting_for_carrier; + bool queued_act_request_is_waiting_for_carrier; NMActRequest * act_request; ActivationHandleData act_handle4; /* for layer2 and IPv4. */ ActivationHandleData act_handle6; @@ -261,11 +276,12 @@ typedef struct _NMDevicePrivate { guint link_connected_id; guint link_disconnected_id; guint carrier_defer_id; - gboolean carrier; + bool carrier; guint carrier_wait_id; - gboolean ignore_carrier; + bool ignore_carrier; + gulong ignore_carrier_id; guint32 mtu; - gboolean up; /* IFF_UP */ + bool up; /* IFF_UP */ /* Generic DHCP stuff */ guint32 dhcp_timeout; @@ -288,14 +304,17 @@ typedef struct _NMDevicePrivate { NMPlatformIP6Route v6; } default_route; - gboolean v4_commit_first_time; - gboolean v6_commit_first_time; + bool v4_commit_first_time; + bool v6_commit_first_time; /* DHCPv4 tracking */ - NMDhcpClient * dhcp4_client; - gulong dhcp4_state_sigid; - NMDhcp4Config * dhcp4_config; - guint dhcp4_restart_id; + struct { + NMDhcpClient * client; + gulong state_sigid; + NMDhcp4Config * config; + guint restart_id; + guint num_tries_left; + } dhcp4; PingInfo gw_ping; @@ -304,7 +323,7 @@ typedef struct _NMDevicePrivate { gulong dnsmasq_state_id; /* Firewall */ - gboolean fw_ready; + bool fw_ready; NMFirewallManagerCallId fw_call; /* IPv4LL stuff */ @@ -325,8 +344,9 @@ typedef struct _NMDevicePrivate { NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ GSList * vpn6_configs; /* VPNs which use this device */ - gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ + bool nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ guint32 ip6_mtu; + NMIP6Config * dad6_ip6_config; NMRDisc * rdisc; gulong rdisc_changed_id; @@ -340,32 +360,36 @@ typedef struct _NMDevicePrivate { GHashTable * ip6_saved_properties; - NMDhcpClient * dhcp6_client; - NMRDiscDHCPLevel dhcp6_mode; - gulong dhcp6_state_sigid; - NMDhcp6Config * dhcp6_config; - /* IP6 config from DHCP */ - NMIP6Config * dhcp6_ip6_config; - /* Event ID of the current IP6 config from DHCP */ - char * dhcp6_event_id; - guint dhcp6_restart_id; + struct { + NMDhcpClient * client; + NMRDiscDHCPLevel mode; + gulong state_sigid; + NMDhcp6Config * config; + /* IP6 config from DHCP */ + NMIP6Config * ip6_config; + /* Event ID of the current IP6 config from DHCP */ + char * event_id; + guint restart_id; + guint num_tries_left; + } dhcp6; /* allow autoconnect feature */ - gboolean autoconnect; + bool autoconnect; /* master interface for bridge/bond/team slave */ NMDevice * master; - gboolean is_enslaved; - gboolean master_ready_handled; + bool is_enslaved; + bool master_ready_handled; gulong master_ready_id; /* slave management */ - gboolean is_master; + bool is_master; GSList * slaves; /* list of SlaveInfo */ NMMetered metered; - NMConnectionProvider *con_provider; + NMSettings *settings; + NMLldpListener *lldp_listener; guint check_delete_unrealized_id; @@ -418,6 +442,8 @@ static void nm_device_start_ip_check (NMDevice *self); static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); static void nm_device_set_mtu (NMDevice *self, guint32 mtu); +static void dhcp_schedule_restart (NMDevice *self, int family, const char *reason); + /***********************************************************/ #define QUEUED_PREFIX "queued state change to " @@ -524,6 +550,40 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, /***********************************************************/ +NMSettings * +nm_device_get_settings (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->settings; +} + +static void +init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) +{ + gs_free char *value = NULL; + gint priority; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv4.dns-priority", + self); + priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); + nm_ip4_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); +} + +static void +init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config) +{ + gs_free char *value = NULL; + gint priority; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv6.dns-priority", + self); + priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); + nm_ip6_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); +} + +/***********************************************************/ + gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value) { @@ -542,6 +602,17 @@ nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps) return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->capabilities, caps); } +static void +_add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!NM_FLAGS_ALL (priv->capabilities, capabilities)) { + priv->capabilities |= capabilities; + _notify (self, PROP_CAPABILITIES); + } +} + /***********************************************************/ const char * @@ -664,39 +735,72 @@ static gboolean get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *out_iid) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMLinkType link_type; - const guint8 *hwaddr = NULL; - size_t hwaddr_len = 0; + const NMPlatformLink *pllink; int ifindex; gboolean success; /* If we get here, we *must* have a kernel netdev, which implies an ifindex */ ifindex = nm_device_get_ip_ifindex (self); - g_assert (ifindex); + g_return_val_if_fail (ifindex > 0, FALSE); - link_type = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); - g_return_val_if_fail (link_type > NM_LINK_TYPE_UNKNOWN, 0); + pllink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + if ( !pllink + || NM_IN_SET (pllink->type, NM_LINK_TYPE_NONE, NM_LINK_TYPE_UNKNOWN)) + return FALSE; - hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddr_len); - if (!hwaddr_len) + if (pllink->addr.len <= 0) return FALSE; + if (pllink->addr.len > NM_UTILS_HWADDR_LEN_MAX) + g_return_val_if_reached (FALSE); - success = nm_utils_get_ipv6_interface_identifier (link_type, - hwaddr, - hwaddr_len, + success = nm_utils_get_ipv6_interface_identifier (pllink->type, + pllink->addr.data, + pllink->addr.len, priv->dev_id, out_iid); if (!success) { _LOGW (LOGD_HW, "failed to generate interface identifier " - "for link type %u hwaddr_len %zu", link_type, hwaddr_len); + "for link type %u hwaddr_len %u", pllink->type, (unsigned) pllink->addr.len); } return success; } +/** + * nm_device_get_ip_iface_identifier: + * @self: an #NMDevice + * @iid: where to place the interface identifier + * @ignore_token: force creation of a non-tokenized address + * + * Return the interface's identifier for the EUI64 address generation mode. + * It's either a manually set token or and identifier generated in a + * hardware-specific way. + * + * Unless @ignore_token is set the token is preferred. That is the case + * for link-local addresses (to mimic kernel behavior). + * + * Returns: #TRUE if the @iid could be set + */ static gboolean -nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid) +nm_device_get_ip_iface_identifier (NMDevice *self, NMUtilsIPv6IfaceId *iid, gboolean ignore_token) { - return NM_DEVICE_GET_CLASS (self)->get_ip_iface_identifier (self, iid); + NMSettingIP6Config *s_ip6; + const char *token = NULL; + NMConnection *connection; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + connection = nm_device_get_applied_connection (self); + nm_assert (connection); + + s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); + nm_assert (s_ip6); + + if (!ignore_token) + token = nm_setting_ip6_config_get_token (s_ip6); + if (token) + return nm_utils_ipv6_interface_identifier_get_from_token (iid, token); + else + return NM_DEVICE_GET_CLASS (self)->get_ip_iface_identifier (self, iid); } const char * @@ -1327,7 +1431,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) g_hash_table_remove_all (priv->ip6_saved_properties); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { if (!nm_device_dhcp4_renew (self, FALSE)) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, @@ -1335,7 +1439,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self) return; } } - if (priv->dhcp6_client) { + if (priv->dhcp6.client) { if (!nm_device_dhcp6_renew (self, FALSE)) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, @@ -1535,13 +1639,13 @@ device_link_changed (NMDevice *self) { NMDeviceClass *klass = NM_DEVICE_GET_CLASS (self); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMUtilsIPv6IfaceId token_iid; gboolean ip_ifname_changed = FALSE; const char *udi; NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; gboolean was_up; + gboolean update_unmanaged_specs = FALSE; priv->device_link_changed_id = 0; @@ -1588,6 +1692,11 @@ device_link_changed (NMDevice *self) /* If the device has no explicit ip_iface, then changing iface changes ip_iface too. */ ip_ifname_changed = !priv->ip_iface; + if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) + nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); + else + update_unmanaged_specs = TRUE; + _notify (self, PROP_IFACE); if (ip_ifname_changed) _notify (self, PROP_IP_IFACE); @@ -1601,10 +1710,11 @@ device_link_changed (NMDevice *self) nm_device_emit_recheck_auto_activate (self); } - if (priv->rdisc && nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &token_iid)) { - _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); - if (nm_rdisc_set_iid (priv->rdisc, token_iid)) + if (priv->rdisc && info.inet6_token.id) { + if (nm_rdisc_set_iid (priv->rdisc, info.inet6_token)) { + _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); nm_rdisc_start (priv->rdisc); + } } if (klass->link_changed) @@ -1623,18 +1733,23 @@ device_link_changed (NMDevice *self) nm_device_set_unmanaged_by_user_udev (self); + reason = NM_DEVICE_STATE_REASON_NOW_MANAGED; + /* If the device is a external-down candidated but no longer has external * down set, we must clear the platform-unmanaged flag with reason * "assumed". */ if ( nm_device_get_unmanaged_mask (self, NM_UNMANAGED_EXTERNAL_DOWN) && !nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN)) { - /* Ensure the assume check is queued before any queued state changes - * from the transition to UNAVAILABLE. - */ - nm_device_queue_recheck_assume (self); - reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; - } else - reason = NM_DEVICE_STATE_REASON_NOW_MANAGED; + /* actually, user-udev overwrites external-down. So we only assume the device, + * when it is a external-down candidate, which is not managed via udev. */ + if (!nm_device_get_unmanaged_mask (self, NM_UNMANAGED_USER_UDEV)) { + /* Ensure the assume check is queued before any queued state changes + * from the transition to UNAVAILABLE. + */ + nm_device_queue_recheck_assume (self); + reason = NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED; + } + } nm_device_set_unmanaged_by_flags (self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason); } @@ -1656,6 +1771,9 @@ device_link_changed (NMDevice *self) } } + if (update_unmanaged_specs) + nm_device_set_unmanaged_by_user_settings (self, nm_settings_get_unmanaged_specs (priv->settings)); + return G_SOURCE_REMOVE; } @@ -1934,6 +2052,8 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) NMDevicePrivate *priv; NMDeviceClass *klass; static guint32 id = 0; + NMDeviceCapabilities capabilities = 0; + NMConfig *config; g_return_if_fail (NM_IS_DEVICE (self)); @@ -1966,7 +2086,7 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex)) - priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; + capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); _notify (self, PROP_MTU); @@ -1986,7 +2106,9 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) } if (klass->get_generic_capabilities) - priv->capabilities |= klass->get_generic_capabilities (self); + capabilities |= klass->get_generic_capabilities (self); + + _add_capabilities (self, capabilities); if (!priv->udi) { /* Use a placeholder UDI until we get a real one */ @@ -2002,15 +2124,16 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) nm_device_update_initial_hw_address (self); /* Note: initial hardware address must be read before calling get_ignore_carrier() */ - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - NMConfig *config = nm_config_get (); - - priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); - g_signal_connect (G_OBJECT (config), - NM_CONFIG_SIGNAL_CONFIG_CHANGED, - G_CALLBACK (config_changed_update_ignore_carrier), - self); + config = nm_config_get (); + priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); + if (!priv->ignore_carrier_id) { + priv->ignore_carrier_id = g_signal_connect (config, + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK (config_changed_update_ignore_carrier), + self); + } + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { check_carrier (self); _LOGD (LOGD_HW, "carrier is %s%s", @@ -2021,8 +2144,6 @@ realize_start_setup (NMDevice *self, const NMPlatformLink *plink) priv->carrier = TRUE; } - _notify (self, PROP_CAPABILITIES); - klass->realize_start_notify (self, plink); /* Do not manage externally created software devices until they are IFF_UP @@ -2202,6 +2323,8 @@ nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); _notify (self, PROP_CAPABILITIES); + nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); + priv->real = FALSE; _notify (self, PROP_REAL); @@ -2971,6 +3094,7 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) gs_free char *uuid = NULL; const char *ip4_method, *ip6_method; GError *error = NULL; + const NMPlatformLink *pllink; /* If update_connection() is not implemented, just fail. */ if (!klass->update_connection) @@ -3017,6 +3141,15 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master) s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (connection, s_ip6); + + pllink = nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex); + if (pllink && pllink->inet6_token.id) { + _LOGD (LOGD_IP6, "IPv6 tokenized identifier present"); + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, NM_IN6_ADDR_GEN_MODE_EUI64, + NM_SETTING_IP6_CONFIG_TOKEN, nm_utils_inet6_interface_identifier_to_token (pllink->inet6_token, NULL), + NULL); + } } klass->update_connection (self, connection); @@ -3323,7 +3456,7 @@ dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer us switch (status) { case NM_DNSMASQ_STATUS_DEAD: - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); break; default: break; @@ -3787,6 +3920,26 @@ check_ip_failed (NMDevice *self, gboolean may_fail) NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } +void +nm_device_ip_method_failed (NMDevice *self, int family, NMDeviceStateReason reason) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (family == AF_INET || family == AF_INET6); + priv = NM_DEVICE_GET_PRIVATE (self); + + if (family == AF_INET) + priv->ip4_state = IP_FAIL; + else + priv->ip6_state = IP_FAIL; + + if (get_ip_config_may_fail (self, family)) + check_ip_failed (self, FALSE); + else + nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); +} + /* * check_ip_done * @@ -4022,14 +4175,14 @@ ipv4ll_get_ip4_config (NMDevice *self, guint32 lla) memset (&address, 0, sizeof (address)); nm_platform_ip4_address_set_addr (&address, lla, 16); - address.source = NM_IP_CONFIG_SOURCE_IP4LL; + address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL; nm_ip4_config_add_address (config, &address); /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */ memset (&route, 0, sizeof (route)); route.network = htonl (0xE0000000L); route.plen = 4; - route.source = NM_IP_CONFIG_SOURCE_IP4LL; + route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL; route.metric = nm_device_get_ip4_route_metric (self); nm_ip4_config_add_route (config, &route); @@ -4066,23 +4219,20 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) r = sd_ipv4ll_get_address (ll, &address); if (r < 0) { _LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED); return; } if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { _LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); return; } config = ipv4ll_get_ip4_config (self, address.s_addr); if (config == NULL) { _LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config"); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); return; } @@ -4092,8 +4242,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) } else if (priv->ip4_state == IP_DONE) { if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } } else g_assert_not_reached (); @@ -4102,8 +4251,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) break; default: _LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); - priv->ip4_state = IP_FAIL; - check_ip_failed (self, FALSE); + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } } @@ -4160,9 +4308,9 @@ ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) goto fail; } - r = sd_ipv4ll_set_index (priv->ipv4ll, ifindex); + r = sd_ipv4ll_set_ifindex (priv->ipv4ll, ifindex); if (r < 0) { - _LOGE (LOGD_AUTOIP4, "IPv4LL: set_index() failed with error %d", r); + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r); goto fail; } @@ -4297,23 +4445,23 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - nm_clear_g_source (&priv->dhcp4_restart_id); + nm_clear_g_source (&priv->dhcp4.restart_id); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { /* Stop any ongoing DHCP transaction on this device */ - nm_clear_g_signal_handler (priv->dhcp4_client, &priv->dhcp4_state_sigid); + nm_clear_g_signal_handler (priv->dhcp4.client, &priv->dhcp4.state_sigid); nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop (priv->dhcp4_client, release); + nm_dhcp_client_stop (priv->dhcp4.client, release); - g_clear_object (&priv->dhcp4_client); + g_clear_object (&priv->dhcp4.client); } - if (priv->dhcp4_config) { - nm_exported_object_clear_and_unexport (&priv->dhcp4_config); + if (priv->dhcp4.config) { + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); _notify (self, PROP_DHCP4_CONFIG); } } @@ -4368,6 +4516,7 @@ ip4_config_merge_and_apply (NMDevice *self, } composite = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + init_ip4_config_dns_priority (self, composite); if (commit) ensure_con_ip4_config (self); @@ -4466,7 +4615,7 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = TRUE; memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); - priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v4.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v4.gateway = gateway; priv->default_route.v4.metric = default_route_metric; priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); @@ -4512,28 +4661,30 @@ END_ADD_DEFAULT_ROUTE: return success; } -static void +static gboolean dhcp4_lease_change (NMDevice *self, NMIP4Config *config) { NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - g_return_if_fail (config != NULL); + g_return_val_if_fail (config != NULL, FALSE); if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } else { - /* Notify dispatcher scripts of new DHCP4 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_settings_connection (self), - nm_device_get_applied_connection (self), - self, - NULL, - NULL, - NULL); - - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + return FALSE; } + + /* Notify dispatcher scripts of new DHCP4 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), + self, + NULL, + NULL, + NULL); + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); + + return TRUE; } static gboolean @@ -4547,11 +4698,11 @@ dhcp4_restart_cb (gpointer user_data) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp4_restart_id = 0; + priv->dhcp4.restart_id = 0; connection = nm_device_get_applied_connection (self); if (dhcp4_start (self, connection, &reason) == NM_ACT_STAGE_RETURN_FAILURE) - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, NULL); return FALSE; } @@ -4561,6 +4712,9 @@ dhcp4_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + _LOGD (LOGD_DHCP4, "DHCPv4 failed: timeout %d, num tries left %u", + timeout, priv->dhcp4.num_tries_left); + dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); /* Don't fail if there are static addresses configured on @@ -4569,8 +4723,7 @@ dhcp4_fail (NMDevice *self, gboolean timeout) if ( priv->ip4_state == IP_DONE && priv->con_ip4_config && nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) { - _LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because device has IP addresses"); - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, "device has IP addresses"); return; } @@ -4579,16 +4732,23 @@ dhcp4_fail (NMDevice *self, gboolean timeout) * retry DHCP again. */ if (nm_device_uses_assumed_connection (self)) { - _LOGI (LOGD_DHCP4, "Scheduling DHCPv4 restart because the connection is assumed"); - priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); + dhcp_schedule_restart (self, AF_INET, "connection is assumed"); return; } - if (timeout || (priv->ip4_state == IP_CONF)) + if ( priv->dhcp4.num_tries_left == DHCP_NUM_TRIES_MAX + && (timeout || (priv->ip4_state == IP_CONF))) nm_device_activate_schedule_ip4_config_timeout (self); - else if (priv->ip4_state == IP_DONE) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - else + else if (priv->ip4_state == IP_DONE) { + /* Don't fail immediately when the lease expires but try to + * restart DHCP for a predefined number of times. + */ + if (priv->dhcp4.num_tries_left) { + priv->dhcp4.num_tries_left--; + dhcp_schedule_restart (self, AF_INET, "lease expired"); + } else + nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + } else g_warn_if_reached (); } @@ -4625,14 +4785,13 @@ dhcp4_state_changed (NMDhcpClient *client, case NM_DHCP_STATE_BOUND: if (!ip4_config) { _LOGW (LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event."); - nm_device_state_changed (self, - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + dhcp4_fail (self, FALSE); break; } - nm_dhcp4_config_set_options (priv->dhcp4_config, options); + nm_dhcp4_config_set_options (priv->dhcp4.config, options); _notify (self, PROP_DHCP4_CONFIG); + priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX; if (priv->ip4_state == IP_CONF) { connection = nm_device_get_applied_connection (self); @@ -4649,8 +4808,10 @@ dhcp4_state_changed (NMDhcpClient *client, ipv4_dad_start (self, configs, dhcp4_dad_cb); } else if (priv->ip4_state == IP_DONE) { - dhcp4_lease_change (self, ip4_config); - nm_device_update_metered (self); + if (dhcp4_lease_change (self, ip4_config)) + nm_device_update_metered (self); + else + dhcp4_fail (self, FALSE); } break; case NM_DHCP_STATE_TIMEOUT: @@ -4706,8 +4867,8 @@ dhcp4_start (NMDevice *self, s_ip4 = nm_connection_get_setting_ip4_config (connection); /* Clear old exported DHCP options */ - nm_exported_object_clear_and_unexport (&priv->dhcp4_config); - priv->dhcp4_config = nm_dhcp4_config_new (); + nm_exported_object_clear_and_unexport (&priv->dhcp4.config); + priv->dhcp4.config = nm_dhcp4_config_new (); hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len); if (hw_addr_len) { @@ -4716,8 +4877,8 @@ dhcp4_start (NMDevice *self, } /* Begin DHCP on the interface */ - g_warn_if_fail (priv->dhcp4_client == NULL); - priv->dhcp4_client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), + g_warn_if_fail (priv->dhcp4.client == NULL); + priv->dhcp4.client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, @@ -4734,12 +4895,12 @@ dhcp4_start (NMDevice *self, if (tmp) g_byte_array_free (tmp, TRUE); - if (!priv->dhcp4_client) { + if (!priv->dhcp4.client) { *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } - priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client, + priv->dhcp4.state_sigid = g_signal_connect (priv->dhcp4.client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (dhcp4_state_changed), self); @@ -4758,7 +4919,7 @@ nm_device_dhcp4_renew (NMDevice *self, gboolean release) NMDeviceStateReason reason; NMConnection *connection; - g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE); + g_return_val_if_fail (priv->dhcp4.client != NULL, FALSE); _LOGI (LOGD_DHCP4, "DHCPv4 lease renewal requested"); @@ -4833,7 +4994,7 @@ shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReaso } config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); - address.source = NM_IP_CONFIG_SOURCE_SHARED; + address.addr_source = NM_IP_CONFIG_SOURCE_SHARED; nm_ip4_config_add_address (config, &address); /* Remove the address lock when the object gets disposed */ @@ -4984,6 +5145,7 @@ act_stage3_ip4_config_start (NMDevice *self, } method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); + priv->dhcp4.num_tries_left = DHCP_NUM_TRIES_MAX; /* Start IPv4 addressing based on the method requested */ if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) @@ -5027,25 +5189,25 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); - nm_clear_g_source (&priv->dhcp6_restart_id); + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE; + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); + nm_clear_g_source (&priv->dhcp6.restart_id); - if (priv->dhcp6_client) { - nm_clear_g_signal_handler (priv->dhcp6_client, &priv->dhcp6_state_sigid); + if (priv->dhcp6.client) { + nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.state_sigid); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) - nm_dhcp_client_stop (priv->dhcp6_client, release); + nm_dhcp_client_stop (priv->dhcp6.client, release); - g_clear_object (&priv->dhcp6_client); + g_clear_object (&priv->dhcp6.client); } nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); - if (priv->dhcp6_config) { - nm_exported_object_clear_and_unexport (&priv->dhcp6_config); + if (priv->dhcp6.config) { + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); _notify (self, PROP_DHCP6_CONFIG); } } @@ -5075,6 +5237,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean auto_method = FALSE; + const char *token = NULL; /* Apply ignore-auto-routes and ignore-auto-dns settings */ connection = nm_device_get_applied_connection (self); @@ -5082,9 +5245,14 @@ ip6_config_merge_and_apply (NMDevice *self, NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) { + NMSettingIP6Config *ip6 = NM_SETTING_IP6_CONFIG (s_ip6); + ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6); ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6); + if (nm_setting_ip6_config_get_addr_gen_mode (ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) + token = nm_setting_ip6_config_get_token (ip6); + if (NM_IN_STRSET (nm_setting_ip_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_AUTO, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) @@ -5094,9 +5262,11 @@ ip6_config_merge_and_apply (NMDevice *self, /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); + init_ip6_config_dns_priority (self, composite); if (commit) ensure_con_ip6_config (self); + g_assert (composite); /* Merge all the IP configs into the composite config */ @@ -5105,8 +5275,8 @@ ip6_config_merge_and_apply (NMDevice *self, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } - if (priv->dhcp6_ip6_config) { - nm_ip6_config_merge (composite, priv->dhcp6_ip6_config, + if (priv->dhcp6.ip6_config) { + nm_ip6_config_merge (composite, priv->dhcp6.ip6_config, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } @@ -5199,7 +5369,7 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = TRUE; memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); - priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v6.rt_source = NM_IP_CONFIG_SOURCE_USER; priv->default_route.v6.gateway = *gateway; priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); @@ -5230,6 +5400,14 @@ END_ADD_DEFAULT_ROUTE: /* Allow setting MTU etc */ if (commit) { + NMUtilsIPv6IfaceId iid; + + if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) { + nm_platform_link_set_ipv6_token (NM_PLATFORM_GET, + nm_device_get_ip_ifindex (self), + iid); + } + if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit) NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, composite); } @@ -5245,37 +5423,38 @@ END_ADD_DEFAULT_ROUTE: return success; } -static void +static gboolean dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingsConnection *settings_connection; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - if (priv->dhcp6_ip6_config == NULL) { + if (priv->dhcp6.ip6_config == NULL) { _LOGW (LOGD_DHCP6, "failed to get DHCPv6 config for rebind"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - return; + return FALSE; } - g_assert (priv->dhcp6_client); /* sanity check */ + g_assert (priv->dhcp6.client); /* sanity check */ settings_connection = nm_device_get_settings_connection (self); g_assert (settings_connection); /* Apply the updated config */ - if (ip6_config_merge_and_apply (self, TRUE, &reason) == FALSE) { - _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event."); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - } else { - /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - settings_connection, - nm_device_get_applied_connection (self), - self, NULL, NULL, NULL); - - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + if (!ip6_config_merge_and_apply (self, TRUE, &reason)) { + _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); + return FALSE; } + + /* Notify dispatcher scripts of new DHCPv6 config */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + settings_connection, + nm_device_get_applied_connection (self), + self, NULL, NULL, NULL); + + nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); + + return TRUE; } static gboolean @@ -5288,30 +5467,63 @@ dhcp6_restart_cb (gpointer user_data) g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); - priv->dhcp6_restart_id = 0; + priv->dhcp6.restart_id = 0; if (!dhcp6_start (self, FALSE, &reason)) - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, NULL); return FALSE; } static void +dhcp_schedule_restart (NMDevice *self, int family, const char *reason) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean inet4; + guint tries_left; + gs_free char *tries_str = NULL; + + g_return_if_fail (family == AF_INET || family == AF_INET6); + inet4 = family == AF_INET; + + tries_left = inet4 ? priv->dhcp4.num_tries_left : priv->dhcp6.num_tries_left; + if (tries_left != DHCP_NUM_TRIES_MAX) + tries_str = g_strdup_printf (", %u tries left", tries_left + 1); + + _LOGI (inet4 ? LOGD_DHCP4 : LOGD_DHCP6, + "scheduling DHCPv%c restart in %u seconds%s%s%s%s", + inet4 ? '4' : '6', + DHCP_RESTART_TIMEOUT, + tries_str ? tries_str : "", + NM_PRINT_FMT_QUOTED (reason, " (reason: ", reason, ")", "")); + + if (inet4) { + priv->dhcp4.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT, + dhcp4_restart_cb, self); + } else { + priv->dhcp6.restart_id = g_timeout_add_seconds (DHCP_RESTART_TIMEOUT, + dhcp6_restart_cb, self); + } +} + +static void dhcp6_fail (NMDevice *self, gboolean timeout) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + _LOGD (LOGD_DHCP6, "DHCPv6 failed: timeout %d, num tries left %u", + timeout, priv->dhcp6.num_tries_left); + dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE); - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) { /* Don't fail if there are static addresses configured on * the device, instead retry after some time. */ if ( priv->ip6_state == IP_DONE && priv->con_ip6_config && nm_ip6_config_get_num_addresses (priv->con_ip6_config)) { - _LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because device has IP addresses"); - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, "device has IP addresses"); return; } @@ -5320,16 +5532,23 @@ dhcp6_fail (NMDevice *self, gboolean timeout) * retry DHCP again. */ if (nm_device_uses_assumed_connection (self)) { - _LOGI (LOGD_DHCP6, "Scheduling DHCPv6 restart because the connection is assumed"); - priv->dhcp6_restart_id = g_timeout_add_seconds (120, dhcp6_restart_cb, self); + dhcp_schedule_restart (self, AF_INET6, "connection is assumed"); return; } - if (timeout || (priv->ip6_state == IP_CONF)) + if ( priv->dhcp6.num_tries_left == DHCP_NUM_TRIES_MAX + && (timeout || (priv->ip6_state == IP_CONF))) nm_device_activate_schedule_ip6_config_timeout (self); - else if (priv->ip6_state == IP_DONE) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); - else + else if (priv->ip6_state == IP_DONE) { + /* Don't fail immediately when the lease expires but try to + * restart DHCP for a predefined number of times. + */ + if (priv->dhcp6.num_tries_left) { + priv->dhcp6.num_tries_left--; + dhcp_schedule_restart (self, AF_INET6, "lease expired"); + } else + nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + } else g_warn_if_reached (); } else { /* not a hard failure; just live with the RA info */ @@ -5343,7 +5562,7 @@ dhcp6_timeout (NMDevice *self, NMDhcpClient *client) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) dhcp6_fail (self, TRUE); else { /* not a hard failure; just live with the RA info */ @@ -5378,32 +5597,34 @@ dhcp6_state_changed (NMDhcpClient *client, */ if ( ip6_config && event_id - && priv->dhcp6_event_id - && !strcmp (event_id, priv->dhcp6_event_id)) { + && priv->dhcp6.event_id + && !strcmp (event_id, priv->dhcp6.event_id)) { for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - nm_ip6_config_add_address (priv->dhcp6_ip6_config, + nm_ip6_config_add_address (priv->dhcp6.ip6_config, nm_ip6_config_get_address (ip6_config, i)); } } else { - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); if (ip6_config) { - priv->dhcp6_ip6_config = g_object_ref (ip6_config); - priv->dhcp6_event_id = g_strdup (event_id); - nm_dhcp6_config_set_options (priv->dhcp6_config, options); + priv->dhcp6.ip6_config = g_object_ref (ip6_config); + priv->dhcp6.event_id = g_strdup (event_id); + nm_dhcp6_config_set_options (priv->dhcp6.config, options); _notify (self, PROP_DHCP6_CONFIG); } } + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; + if (priv->ip6_state == IP_CONF) { - if (priv->dhcp6_ip6_config == NULL) { - /* FIXME: Initial DHCP failed; should we fail IPv6 entirely then? */ - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DHCP_FAILED); + if (priv->dhcp6.ip6_config == NULL) { + nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED); break; } nm_device_activate_schedule_ip6_config_result (self); } else if (priv->ip6_state == IP_DONE) - dhcp6_lease_change (self); + if (!dhcp6_lease_change (self)) + dhcp6_fail (self, FALSE); break; case NM_DHCP_STATE_TIMEOUT: dhcp6_timeout (self, client); @@ -5418,7 +5639,7 @@ dhcp6_state_changed (NMDhcpClient *client, * may exit right after getting a response from the server. That's * normal. In that case we just ignore the exit. */ - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) break; /* Otherwise, fall through */ case NM_DHCP_STATE_FAIL: @@ -5454,7 +5675,7 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) g_return_val_if_fail (ll_addr, FALSE); - priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), + priv->dhcp6.client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, @@ -5465,19 +5686,19 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) nm_setting_ip_config_get_dhcp_hostname (s_ip6), priv->dhcp_timeout, priv->dhcp_anycast_address, - (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, + (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE, nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6))); if (tmp) g_byte_array_free (tmp, TRUE); - if (priv->dhcp6_client) { - priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client, + if (priv->dhcp6.client) { + priv->dhcp6.state_sigid = g_signal_connect (priv->dhcp6.client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (dhcp6_state_changed), self); } - return !!priv->dhcp6_client; + return !!priv->dhcp6.client; } static gboolean @@ -5487,12 +5708,12 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) NMConnection *connection; NMSettingIPConfig *s_ip6; - nm_exported_object_clear_and_unexport (&priv->dhcp6_config); - priv->dhcp6_config = nm_dhcp6_config_new (); + nm_exported_object_clear_and_unexport (&priv->dhcp6.config); + priv->dhcp6.config = nm_dhcp6_config_new (); - g_warn_if_fail (priv->dhcp6_ip6_config == NULL); - g_clear_object (&priv->dhcp6_ip6_config); - g_clear_pointer (&priv->dhcp6_event_id, g_free); + g_warn_if_fail (priv->dhcp6.ip6_config == NULL); + g_clear_object (&priv->dhcp6.ip6_config); + g_clear_pointer (&priv->dhcp6.event_id, g_free); connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -5528,7 +5749,7 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - g_return_val_if_fail (priv->dhcp6_client != NULL, FALSE); + g_return_val_if_fail (priv->dhcp6.client != NULL, FALSE); _LOGI (LOGD_DHCP6, "DHCPv6 lease renewal requested"); @@ -5659,13 +5880,13 @@ check_and_add_ipv6ll_addr (NMDevice *self) return; } - if (!nm_device_get_ip_iface_identifier (self, &iid)) { + if (!nm_device_get_ip_iface_identifier (self, &iid, TRUE)) { _LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); return; } _LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address"); - nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid); + nm_utils_ipv6_addr_set_interface_identifier (&lladdr, iid); } _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); @@ -5828,7 +6049,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) address.preferred = discovered_address->preferred; if (address.preferred > address.lifetime) address.preferred = address.lifetime; - address.source = NM_IP_CONFIG_SOURCE_RDISC; + address.addr_source = NM_IP_CONFIG_SOURCE_RDISC; address.n_ifa_flags = ifa_flags; nm_ip6_config_add_address (priv->ac_ip6_config, &address); @@ -5853,7 +6074,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) nm_assert (discovered_route->plen <= 128); route.plen = discovered_route->plen; route.gateway = discovered_route->gateway; - route.source = NM_IP_CONFIG_SOURCE_RDISC; + route.rt_source = NM_IP_CONFIG_SOURCE_RDISC; route.metric = nm_device_get_ip6_route_metric (self); nm_ip6_config_add_route (priv->ac_ip6_config, &route); @@ -5886,15 +6107,15 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) { dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, TRUE); - priv->dhcp6_mode = rdisc->dhcp_level; - if (priv->dhcp6_mode != NM_RDISC_DHCP_LEVEL_NONE) { + priv->dhcp6.mode = rdisc->dhcp_level; + if (priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE) { NMDeviceStateReason reason; _LOGD (LOGD_DEVICE | LOGD_DHCP6, "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6" " as requested by IPv6 router..."); if (!dhcp6_start (self, FALSE, &reason)) { - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { + if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); return; } @@ -5944,10 +6165,7 @@ addrconf6_start_with_link_ready (NMDevice *self) g_assert (priv->rdisc); - if (nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &iid)) { - _LOGD (LOGD_IP6, "addrconf6: IPv6 tokenized identifier present"); - nm_rdisc_set_iid (priv->rdisc, iid); - } else if (nm_device_get_ip_iface_identifier (self, &iid)) { + if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) { _LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier"); nm_rdisc_set_iid (priv->rdisc, iid); } else { @@ -6255,7 +6473,8 @@ act_stage3_ip6_config_start (NMDevice *self, } } - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE; + priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX; method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -6303,7 +6522,7 @@ act_stage3_ip6_config_start (NMDevice *self, } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { ret = linklocal6_start (self); } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { - priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_MANAGED; + priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_MANAGED; if (!dhcp6_start (self, TRUE, reason)) { /* IPv6 might be disabled; allow IPv4 to proceed */ ret = NM_ACT_STAGE_RETURN_STOP; @@ -6580,7 +6799,6 @@ act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } - /* * nm_device_activate_stage4_ip4_config_timeout * @@ -6608,7 +6826,6 @@ activate_stage4_ip4_config_timeout (NMDevice *self) check_ip_failed (self, FALSE); } - /* * nm_device_activate_schedule_ip4_config_timeout * @@ -6628,7 +6845,6 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET); } - static NMActStageReturn act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) { @@ -6640,7 +6856,6 @@ act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } - /* * activate_stage4_ip6_config_timeout * @@ -6668,7 +6883,6 @@ activate_stage4_ip6_config_timeout (NMDevice *self) check_ip_failed (self, FALSE); } - /* * nm_device_activate_schedule_ip6_config_timeout * @@ -6875,7 +7089,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) /* NULL to use the existing priv->dev_ip4_config */ if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (self, AF_INET, reason); return; } @@ -6893,7 +7107,7 @@ activate_stage5_ip4_config_commit (NMDevice *self) /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure * dispatcher scripts get the DHCP lease information. */ - if ( priv->dhcp4_client + if ( priv->dhcp4.client && nm_device_activate_ip4_state_in_conf (self) && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { /* Notify dispatcher scripts of new DHCP4 config */ @@ -6944,6 +7158,64 @@ nm_device_activate_ip4_state_in_wait (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT; } +gboolean +nm_device_activate_ip4_state_done (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_DONE; +} + +/* + * Returns a NMIP6Config containing NM-configured addresses which + * have the tentative flag, or NULL if none is present. + */ +static NMIP6Config * +dad6_get_pending_addresses (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMIP6Config *confs[] = { priv->ac_ip6_config, + priv->dhcp6.ip6_config, + priv->con_ip6_config, + priv->wwan_ip6_config }; + const NMPlatformIP6Address *addr, *pl_addr; + NMIP6Config *dad6_config = NULL; + guint i, j, num; + int ifindex; + + ifindex = nm_device_get_ip_ifindex (self); + g_return_val_if_fail (ifindex > 0, NULL); + + /* We are interested only in addresses that we have explicitly configured, + * not in externally added ones. + */ + for (i = 0; i < G_N_ELEMENTS (confs); i++) { + if (confs[i]) { + num = nm_ip6_config_get_num_addresses (confs[i]); + for (j = 0; j < num; j++) { + addr = nm_ip6_config_get_address (confs[i], j); + pl_addr = nm_platform_ip6_address_get (NM_PLATFORM_GET, + ifindex, + addr->address, + addr->plen); + if ( pl_addr + && NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_DADFAILED) + && !NM_FLAGS_HAS (pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + _LOGt (LOGD_DEVICE, "IPv6 DAD: pending address %s", + nm_platform_ip6_address_to_string (pl_addr, NULL, 0)); + + if (!dad6_config) + dad6_config = nm_ip6_config_new (ifindex); + + nm_ip6_config_add_address (dad6_config, pl_addr); + } + } + } + } + + return dad6_config; +} + static void activate_stage5_ip6_config_commit (NMDevice *self) { @@ -6967,9 +7239,9 @@ activate_stage5_ip6_config_commit (NMDevice *self) } if (ip6_config_merge_and_apply (self, TRUE, &reason)) { - if ( priv->dhcp6_mode != NM_RDISC_DHCP_LEVEL_NONE + if ( priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { - if (priv->dhcp6_ip6_config) { + if (priv->dhcp6.ip6_config) { /* If IPv6 wasn't the first IP to complete, and DHCP was used, * then ensure dispatcher scripts get the DHCP lease information. */ @@ -6985,16 +7257,23 @@ activate_stage5_ip6_config_commit (NMDevice *self) return; } } - nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); - /* Enter the IP_CHECK state if this is the first method to complete */ - priv->ip6_state = IP_DONE; - check_ip_done (self); + /* Check if we have to wait for DAD */ + if (priv->ip6_state == IP_CONF && !priv->dad6_ip6_config) { + priv->dad6_ip6_config = dad6_get_pending_addresses (self); + if (priv->dad6_ip6_config) { + _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: waiting termination"); + } else { + /* No tentative addresses, proceed right away */ + priv->ip6_state = IP_DONE; + check_ip_done (self); + } + } } else { _LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (self, AF_INET6, reason); } } @@ -7028,6 +7307,13 @@ nm_device_activate_ip6_state_in_wait (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_WAIT; } +gboolean +nm_device_activate_ip6_state_done (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_DONE; +} + static void clear_act_request (NMDevice *self) { @@ -7192,6 +7478,7 @@ _cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) if (nm_clear_g_source (&priv->queued_ip6_config_id)) _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); + g_clear_object (&priv->dad6_ip6_config); dhcp6_cleanup (self, cleanup_type, FALSE); linklocal6_cleanup (self); addrconf6_cleanup (self); @@ -7939,7 +8226,7 @@ nm_device_get_dhcp4_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config; + return NM_DEVICE_GET_PRIVATE (self)->dhcp4.config; } NMIP4Config * @@ -8256,7 +8543,7 @@ nm_device_get_dhcp6_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->dhcp6_config; + return NM_DEVICE_GET_PRIVATE (self)->dhcp6.config; } NMIP6Config * @@ -8564,6 +8851,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); gboolean device_is_up = FALSE; + NMDeviceCapabilities capabilities; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -8574,6 +8862,10 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) return FALSE; } + /* Store carrier immediately. */ + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) + check_carrier (self); + device_is_up = nm_device_is_up (self); if (block && !device_is_up) { int ifindex = nm_device_get_ip_ifindex (self); @@ -8595,6 +8887,13 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) return FALSE; } + /* some ethernet devices fail to report capabilities unless the device + * is up. Re-read the capabilities. */ + capabilities = 0; + if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) + capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); + _add_capabilities (self, capabilities); + /* Devices that support carrier detect must be IFF_UP to report carrier * changes; so after setting the device IFF_UP we must suppress startup * complete (via a pending action) until either the carrier turns on, or @@ -8638,10 +8937,6 @@ bring_up (NMDevice *self, gboolean *no_firmware) result = nm_platform_link_set_up (NM_PLATFORM_GET, ifindex, no_firmware); - /* Store carrier immediately. */ - if (result && nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) - check_carrier (self); - return result; } @@ -8777,7 +9072,7 @@ capture_lease_config (NMDevice *self, NMIP6Config **out_ip6_config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const GSList *connections, *citer; + NMSettingsConnection *const*connections; guint i; gboolean dhcp_used = FALSE; @@ -8810,9 +9105,9 @@ capture_lease_config (NMDevice *self, if (!dhcp_used) return; - connections = nm_connection_provider_get_connections (priv->con_provider); - for (citer = connections; citer; citer = citer->next) { - NMConnection *candidate = citer->data; + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *candidate = (NMConnection *) connections[i]; const char *method; if (!nm_device_check_connection_compatible (self, candidate)) @@ -8858,7 +9153,6 @@ update_ip4_config (NMDevice *self, gboolean initial) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; gboolean capture_resolv_conf; - NMDnsManagerResolvConfMode resolv_conf_mode; /* If a commit is scheduled, this function would potentially interfere with * it changing IP configurations before they are applied. Postpone the @@ -8877,8 +9171,8 @@ update_ip4_config (NMDevice *self, gboolean initial) if (!ifindex) return; - resolv_conf_mode = nm_dns_manager_get_resolv_conf_mode (nm_dns_manager_get ()); - capture_resolv_conf = initial && (resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT); + capture_resolv_conf = initial + && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); /* IPv4 */ g_clear_object (&priv->ext_ip4_config); @@ -8949,7 +9243,6 @@ update_ip6_config (NMDevice *self, gboolean initial) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; gboolean capture_resolv_conf; - NMDnsManagerResolvConfMode resolv_conf_mode; /* If a commit is scheduled, this function would potentially interfere with * it changing IP configurations before they are applied. Postpone the @@ -8968,8 +9261,8 @@ update_ip6_config (NMDevice *self, gboolean initial) if (!ifindex) return; - resolv_conf_mode = nm_dns_manager_get_resolv_conf_mode (nm_dns_manager_get ()); - capture_resolv_conf = initial && (resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT); + capture_resolv_conf = initial + && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); /* IPv6 */ g_clear_object (&priv->ext_ip6_config); @@ -8987,8 +9280,8 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config); if (priv->ac_ip6_config) nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config); - if (priv->dhcp6_ip6_config) - nm_ip6_config_intersect (priv->dhcp6_ip6_config, priv->ext_ip6_config); + if (priv->dhcp6.ip6_config) + nm_ip6_config_intersect (priv->dhcp6.ip6_config, priv->ext_ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config); g_slist_foreach (priv->vpn6_configs, _ip6_config_intersect, priv->ext_ip6_config); @@ -9000,8 +9293,8 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config); if (priv->ac_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config); - if (priv->dhcp6_ip6_config) - nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6_ip6_config); + if (priv->dhcp6.ip6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6.ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config); g_slist_foreach (priv->vpn6_configs, _ip6_config_subtract, priv->ext_ip6_config); @@ -9041,9 +9334,7 @@ queued_ip4_config_change (gpointer user_data) return TRUE; priv->queued_ip4_config_id = 0; - g_object_ref (self); update_ip4_config (self, FALSE); - g_object_unref (self); set_unmanaged_external_down (self, TRUE); @@ -9067,16 +9358,15 @@ queued_ip6_config_change (gpointer user_data) return TRUE; priv->queued_ip6_config_id = 0; - g_object_ref (self); update_ip6_config (self, FALSE); if ( nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex) && priv->state < NM_DEVICE_STATE_DEACTIVATING) { - /* Handle DAD falures */ + /* Handle DAD failures */ for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) { NMPlatformIP6Address *addr = iter->data; - if (addr->source >= NM_IP_CONFIG_SOURCE_USER) + if (addr->addr_source >= NM_IP_CONFIG_SOURCE_USER) continue; _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", @@ -9103,7 +9393,18 @@ queued_ip6_config_change (gpointer user_data) g_slist_free_full (priv->dad6_failed_addrs, g_free); priv->dad6_failed_addrs = NULL; - g_object_unref (self); + /* Check if DAD is still pending */ + if ( priv->ip6_state == IP_CONF + && priv->dad6_ip6_config + && priv->ext_ip6_config_captured) { + if (!nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured, + priv->dad6_ip6_config)) { + _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); + g_clear_object (&priv->dad6_ip6_config); + priv->ip6_state = IP_DONE; + check_ip_done (self); + } + } set_unmanaged_external_down (self, TRUE); @@ -9261,6 +9562,9 @@ _get_managed_by_flags(NMUnmanagedFlags flags, NMUnmanagedFlags mask, gboolean fo /* configuration from udev or nm-config overwrites the by-default flag * which is based on the device type. */ flags &= ~NM_UNMANAGED_BY_DEFAULT; + + /* configuration from udev overwrites external-down */ + flags &= ~NM_UNMANAGED_EXTERNAL_DOWN; } if ( NM_FLAGS_HAS (mask, NM_UNMANAGED_IS_SLAVE) @@ -9499,7 +9803,7 @@ nm_device_set_unmanaged_by_flags_queue (NMDevice *self, } void -nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs) +nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs) { NMDevicePrivate *priv; gboolean unmanaged; @@ -9851,50 +10155,45 @@ void nm_device_recheck_available_connections (NMDevice *self) { NMDevicePrivate *priv; - const GSList *connections, *iter; + NMSettingsConnection *const*connections; gboolean changed = FALSE; GHashTableIter h_iter; NMConnection *connection; + guint i; + gs_unref_hashtable GHashTable *prune_list = NULL; g_return_if_fail (NM_IS_DEVICE (self)); priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->con_provider) { - gs_unref_hashtable GHashTable *prune_list = NULL; - - if (g_hash_table_size (priv->available_connections) > 0) { - prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); - g_hash_table_iter_init (&h_iter, priv->available_connections); - while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) - g_hash_table_add (prune_list, connection); - } - - connections = nm_connection_provider_get_connections (priv->con_provider); - for (iter = connections; iter; iter = g_slist_next (iter)) { - connection = NM_CONNECTION (iter->data); - - if (nm_device_check_connection_available (self, - connection, - NM_DEVICE_CHECK_CON_AVAILABLE_NONE, - NULL)) { - if (available_connections_add (self, connection)) - changed = TRUE; - if (prune_list) - g_hash_table_remove (prune_list, connection); - } + if (g_hash_table_size (priv->available_connections) > 0) { + prune_list = g_hash_table_new (g_direct_hash, g_direct_equal); + g_hash_table_iter_init (&h_iter, priv->available_connections); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) + g_hash_table_add (prune_list, connection); + } + + connections = nm_settings_get_connections (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + connection = (NMConnection *) connections[i]; + + if (nm_device_check_connection_available (self, + connection, + NM_DEVICE_CHECK_CON_AVAILABLE_NONE, + NULL)) { + if (available_connections_add (self, connection)) + changed = TRUE; + if (prune_list) + g_hash_table_remove (prune_list, connection); } + } - if (prune_list) { - g_hash_table_iter_init (&h_iter, prune_list); - while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { - if (available_connections_del (self, connection)) - changed = TRUE; - } + if (prune_list) { + g_hash_table_iter_init (&h_iter, prune_list); + while (g_hash_table_iter_next (&h_iter, (gpointer *) &connection, NULL)) { + if (available_connections_del (self, connection)) + changed = TRUE; } - } else { - if (available_connections_del_all (self)) - changed = TRUE; } if (changed) @@ -9955,10 +10254,9 @@ nm_device_get_best_connection (NMDevice *self, } static void -cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +cp_connection_added_or_updated (NMDevice *self, NMConnection *connection) { gboolean changed; - NMDevice *self = user_data; g_return_if_fail (NM_IS_DEVICE (self)); g_return_if_fail (NM_IS_SETTINGS_CONNECTION (connection)); @@ -9978,6 +10276,18 @@ cp_connection_added_or_updated (NMConnectionProvider *cp, NMConnection *connecti } static void +cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) +{ + cp_connection_added_or_updated (user_data, connection); +} + +static void +cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gboolean by_user, gpointer user_data) +{ + cp_connection_added_or_updated (user_data, connection); +} + +static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { NMDevice *self = user_data; @@ -10184,6 +10494,7 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) g_clear_object (&priv->ext_ip6_config_captured); g_clear_object (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); + g_clear_object (&priv->dad6_ip6_config); g_slist_free_full (priv->vpn4_configs, g_object_unref); priv->vpn4_configs = NULL; @@ -10300,7 +10611,7 @@ find_dhcp4_address (NMDevice *self) for (i = 0; i < n; i++) { const NMPlatformIP4Address *a = nm_ip4_config_get_address (priv->ip4_config, i); - if (a->source == NM_IP_CONFIG_SOURCE_DHCP) + if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP) return g_strdup (nm_utils_inet4_ntop (a->address, NULL)); } return NULL; @@ -10364,11 +10675,11 @@ nm_device_spawn_iface_helper (NMDevice *self) if (nm_setting_ip_config_get_may_fail (s_ip4) == FALSE) g_ptr_array_add (argv, g_strdup ("--dhcp4-required")); - if (priv->dhcp4_client) { + if (priv->dhcp4.client) { const char *hostname, *fqdn; GBytes *client_id; - client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client); + client_id = nm_dhcp_client_get_client_id (priv->dhcp4.client); if (client_id) { g_ptr_array_add (argv, g_strdup ("--dhcp4-clientid")); hex_client_id = bin2hexstr (g_bytes_get_data (client_id, NULL), @@ -10376,13 +10687,13 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, hex_client_id); } - hostname = nm_dhcp_client_get_hostname (priv->dhcp4_client); + hostname = nm_dhcp_client_get_hostname (priv->dhcp4.client); if (hostname) { g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); g_ptr_array_add (argv, g_strdup (hostname)); } - fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4_client); + fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4.client); if (fqdn) { g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); g_ptr_array_add (argv, g_strdup (fqdn)); @@ -10412,7 +10723,7 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--slaac-tempaddr")); g_ptr_array_add (argv, g_strdup_printf ("%d", priv->rdisc_use_tempaddr)); - if (nm_device_get_ip_iface_identifier (self, &iid)) { + if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) { g_ptr_array_add (argv, g_strdup ("--iid")); hex_iid = bin2hexstr ((const char *) iid.id_u8, sizeof (NMUtilsIPv6IfaceId)); g_ptr_array_add (argv, hex_iid); @@ -10720,11 +11031,9 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_DEACTIVATING: _cancel_activation (self); - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - /* We cache the ignore_carrier state to not react on config-reloads while the connection - * is active. But on deactivating, reset the ignore-carrier flag to the current state. */ - priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); - } + /* We cache the ignore_carrier state to not react on config-reloads while the connection + * is active. But on deactivating, reset the ignore-carrier flag to the current state. */ + priv->ignore_carrier = nm_config_data_get_ignore_carrier (NM_CONFIG_GET_DATA, self); if (quitting) { nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, @@ -11007,7 +11316,6 @@ nm_device_update_hw_address (NMDevice *self) int ifindex = nm_device_get_ifindex (self); const guint8 *hwaddr; gsize hwaddrlen = 0; - static const guint8 zero_hwaddr[ETH_ALEN]; if (ifindex <= 0) return; @@ -11015,7 +11323,7 @@ nm_device_update_hw_address (NMDevice *self) hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddrlen); if ( priv->type == NM_DEVICE_TYPE_ETHERNET - && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, sizeof (zero_hwaddr))) + && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, nm_ip_addr_zero.addr_eth, sizeof (nm_ip_addr_zero.addr_eth))) hwaddrlen = 0; if (hwaddrlen) { @@ -11280,33 +11588,31 @@ constructed (GObject *object) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatform *platform; - platform = nm_platform_get (); - if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); /* Watch for external IP config changes */ + platform = NM_PLATFORM_GET; g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); - priv->con_provider = nm_connection_provider_get (); - g_assert (priv->con_provider); - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (cp_connection_added_or_updated), - self); + priv->settings = g_object_ref (NM_SETTINGS_GET); + g_assert (priv->settings); - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (cp_connection_removed), + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), self); - - g_signal_connect (priv->con_provider, - NM_CP_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (cp_connection_added_or_updated), + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + self); + g_signal_connect (priv->settings, + NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), self); G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); @@ -11323,7 +11629,7 @@ dispose (GObject *object) _LOGD (LOGD_DEVICE, "disposing"); - platform = nm_platform_get (); + platform = NM_PLATFORM_GET; g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self); g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self); @@ -11332,7 +11638,7 @@ dispose (GObject *object) arp_cleanup (self); - g_signal_handlers_disconnect_by_func (nm_config_get (), config_changed_update_ignore_carrier, self); + nm_clear_g_signal_handler (nm_config_get (), &priv->ignore_carrier_id); dispatcher_cleanup (self); @@ -11355,10 +11661,10 @@ dispose (GObject *object) link_disconnect_action_cancel (self); - if (priv->con_provider) { - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_added_or_updated, self); - g_signal_handlers_disconnect_by_func (priv->con_provider, cp_connection_removed, self); - priv->con_provider = NULL; + if (priv->settings) { + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_updated, self); + g_signal_handlers_disconnect_by_func (priv->settings, cp_connection_removed, self); } available_connections_del_all (self); @@ -11416,6 +11722,11 @@ finalize (GObject *object) g_hash_table_unref (priv->available_connections); G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); + + /* for testing, NMDeviceTest does not invoke NMDevice::constructed, + * and thus @settings might be unset. */ + if (priv->settings) + g_object_unref (priv->settings); } static void @@ -11447,11 +11758,11 @@ set_property (GObject *object, guint prop_id, break; case PROP_DRIVER_VERSION: g_free (priv->driver_version); - priv->driver_version = g_strdup (g_value_get_string (value)); + priv->driver_version = g_value_dup_string (value); break; case PROP_FIRMWARE_VERSION: g_free (priv->firmware_version); - priv->firmware_version = g_strdup (g_value_get_string (value)); + priv->firmware_version = g_value_dup_string (value); break; case PROP_MTU: priv->mtu = g_value_get_uint (value); @@ -11588,13 +11899,13 @@ get_property (GObject *object, guint prop_id, nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL); break; case PROP_DHCP4_CONFIG: - nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4_config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL); break; case PROP_IP6_CONFIG: nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL); break; case PROP_DHCP6_CONFIG: - nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6_config : NULL); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL); break; case PROP_STATE: g_value_set_uint (value, priv->state); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 2180439631..5f1a168352 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -26,7 +26,6 @@ #include "nm-exported-object.h" #include "nm-dbus-interface.h" -#include "nm-default.h" #include "nm-connection.h" #include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" @@ -493,7 +492,7 @@ void nm_device_set_unmanaged_by_flags_queue (NMDevice *self, NMUnmanagedFlags flags, NMUnmanFlagOp set_op, NMDeviceStateReason reason); -void nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs); +void nm_device_set_unmanaged_by_user_settings (NMDevice *self, const GSList *unmanaged_specs); void nm_device_set_unmanaged_by_user_udev (NMDevice *self); void nm_device_set_unmanaged_by_quitting (NMDevice *device); diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 60842c18ab..fd71899622 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -45,12 +45,18 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) #define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate)) +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceTeam, + PROP_CONFIG, +); + typedef struct { struct teamdctl *tdc; GPid teamd_pid; guint teamd_process_watch; guint teamd_timeout; guint teamd_dbus_watch; + gboolean teamd_dbus_name_owned; + char *config; } NMDeviceTeamPrivate; static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team); @@ -148,6 +154,27 @@ ensure_teamd_connection (NMDevice *device) } static void +teamd_read_config (NMDevice *device) +{ + NMDeviceTeam *self = NM_DEVICE_TEAM (device); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + char *config = NULL; + int err; + + if (priv->tdc) { + err = teamdctl_config_get_raw_direct (priv->tdc, &config); + if (err) + _LOGI (LOGD_TEAM, "failed to read teamd config (err=%d)", err); + } + + if (!nm_streq0 (config, priv->config)) { + g_free (priv->config); + priv->config = g_strdup (config); + _notify (self, PROP_CONFIG); + } +} + +static void update_connection (NMDevice *device, NMConnection *connection) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); @@ -158,19 +185,12 @@ update_connection (NMDevice *device, NMConnection *connection) s_team = (NMSettingTeam *) nm_setting_team_new (); nm_connection_add_setting (connection, (NMSetting *) s_team); } - g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, NULL, NULL); - if (priv->tdc) { - const char *config = NULL; - int err; + /* Read the configuration only if not already set */ + if (!priv->config && ensure_teamd_connection (device)) + teamd_read_config (device); - err = teamdctl_config_get_raw_direct (NM_DEVICE_TEAM_GET_PRIVATE (device)->tdc, - (char **)&config); - if (err == 0) - g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, config, NULL); - else - _LOGE (LOGD_TEAM, "failed to read teamd config (err=%d)", err); - } + g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, priv->config, NULL); } /******************************************************************/ @@ -279,6 +299,11 @@ teamd_timeout_cb (gpointer user_data) g_warn_if_fail (nm_device_is_activating (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); + } else { + /* Read again the configuration after the timeout since it might + * have changed. + */ + teamd_read_config (device); } return G_SOURCE_REMOVE; @@ -296,6 +321,7 @@ teamd_dbus_appeared (GDBusConnection *connection, gboolean success; g_return_if_fail (priv->teamd_dbus_watch); + priv->teamd_dbus_name_owned = TRUE; _LOGI (LOGD_TEAM, "teamd appeared on D-Bus"); nm_device_queue_recheck_assume (device); @@ -330,9 +356,10 @@ teamd_dbus_appeared (GDBusConnection *connection, */ success = ensure_teamd_connection (device); if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { - if (success) + if (success) { + teamd_read_config (device); nm_device_activate_schedule_stage2_device_config (device); - else if (!nm_device_uses_assumed_connection (device)) + } else if (!nm_device_uses_assumed_connection (device)) nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED); } } @@ -349,7 +376,7 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, g_return_if_fail (priv->teamd_dbus_watch); - if (!priv->tdc) { + if (!priv->teamd_dbus_name_owned) { /* g_bus_watch_name will always raise an initial signal, to indicate whether the * name exists/not exists initially. Do not take this as a failure if it hadn't * previously appeared. @@ -358,6 +385,8 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, return; } + priv->teamd_dbus_name_owned = FALSE; + _LOGI (LOGD_TEAM, "teamd vanished from D-Bus"); teamd_cleanup (device, TRUE); @@ -693,6 +722,23 @@ nm_device_team_new (const char *iface) } static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceTeam *self = NM_DEVICE_TEAM (object); + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_CONFIG: + g_value_set_string (value, priv->config); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void nm_device_team_init (NMDeviceTeam * self) { } @@ -730,6 +776,7 @@ dispose (GObject *object) } teamd_cleanup (device, TRUE); + g_clear_pointer (&priv->config, g_free); G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); } @@ -746,6 +793,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) object_class->constructed = constructed; object_class->dispose = dispose; + object_class->get_property = get_property; parent_class->create_and_realize = create_and_realize; parent_class->get_generic_capabilities = get_generic_capabilities; @@ -762,6 +810,14 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; + obj_properties[PROP_CONFIG] = + g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_TEAM_SKELETON, NULL); diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h index 0e81afa744..27bd8227db 100644 --- a/src/devices/team/nm-device-team.h +++ b/src/devices/team/nm-device-team.h @@ -32,6 +32,9 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM)) #define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) +/* Properties */ +#define NM_DEVICE_TEAM_CONFIG "config" + typedef NMDevice NMDeviceTeam; typedef NMDeviceClass NMDeviceTeamClass; diff --git a/src/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c index bff85e6c94..ff6f42a970 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/devices/tests/test-lldp.c @@ -33,7 +33,7 @@ #include "test-common.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /*****************************************************************************/ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 6d83b82fba..9e511a0982 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -21,13 +21,14 @@ #include "nm-default.h" +#include "nm-device-wifi.h" + #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <errno.h> #include "nm-device.h" -#include "nm-device-wifi.h" #include "nm-device-private.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" @@ -45,8 +46,8 @@ #include "nm-platform.h" #include "nm-auth-utils.h" #include "nm-settings-connection.h" +#include "nm-settings.h" #include "nm-enum-types.h" -#include "nm-connection-provider.h" #include "nm-core-internal.h" #include "nm-config.h" @@ -1198,7 +1199,7 @@ check_scanning_allowed (NMDeviceWifi *self) } static gboolean -hidden_filter_func (NMConnectionProvider *provider, +hidden_filter_func (NMSettings *settings, NMConnection *connection, gpointer user_data) { @@ -1225,12 +1226,12 @@ build_hidden_probe_list (NMDeviceWifi *self) if (G_UNLIKELY (nullssid == NULL)) nullssid = g_byte_array_new (); - connections = nm_connection_provider_get_best_connections (nm_connection_provider_get (), - max_scan_ssids - 1, - NM_SETTING_WIRELESS_SETTING_NAME, - NULL, - hidden_filter_func, - NULL); + connections = nm_settings_get_best_connections (nm_device_get_settings ((NMDevice *) self), + max_scan_ssids - 1, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL, + hidden_filter_func, + NULL); if (connections && connections->data) { ssids = g_ptr_array_new_full (max_scan_ssids - 1, (GDestroyNotify) g_byte_array_unref); g_ptr_array_add (ssids, g_byte_array_ref (nullssid)); /* Add wildcard SSID */ @@ -1457,10 +1458,12 @@ schedule_ap_list_dump (NMDeviceWifi *self) } static void -try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) +try_fill_ssid_for_hidden_ap (NMDeviceWifi *self, + NMAccessPoint *ap) { const char *bssid; - const GSList *connections, *iter; + NMSettingsConnection *const*connections; + guint i; g_return_if_fail (nm_ap_get_ssid (ap) == NULL); @@ -1469,9 +1472,9 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) /* Look for this AP's BSSID in the seen-bssids list of a connection, * and if a match is found, copy over the SSID */ - connections = nm_connection_provider_get_connections (nm_connection_provider_get ()); - for (iter = connections; iter; iter = g_slist_next (iter)) { - NMConnection *connection = NM_CONNECTION (iter->data); + connections = nm_settings_get_connections (nm_device_get_settings ((NMDevice *) self), NULL); + for (i = 0; connections[i]; i++) { + NMConnection *connection = (NMConnection *) connections[i]; NMSettingWireless *s_wifi; s_wifi = nm_connection_get_setting_wireless (connection); @@ -1521,7 +1524,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, ssid = nm_ap_get_ssid (ap); if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { /* Try to fill the SSID from the AP database */ - try_fill_ssid_for_hidden_ap (ap); + try_fill_ssid_for_hidden_ap (self, ap); ssid = nm_ap_get_ssid (ap); if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index a0c2570996..d0704b4ea9 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -42,29 +42,48 @@ typedef struct char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ /* Scanned or cached values */ - GByteArray * ssid; - char * address; - NM80211Mode mode; - guint8 strength; - guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ - guint32 max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ + GByteArray * ssid; + char * address; + NM80211Mode mode; + guint8 strength; + guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ + guint32 max_bitrate; /* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ NM80211ApFlags flags; /* General flags */ NM80211ApSecurityFlags wpa_flags; /* WPA-related flags */ NM80211ApSecurityFlags rsn_flags; /* RSN (WPA2) -related flags */ /* Non-scanned attributes */ - gboolean fake; /* Whether or not the AP is from a scan */ - gboolean hotspot; /* Whether the AP is a local device's hotspot network */ + bool fake; /* Whether or not the AP is from a scan */ + bool hotspot; /* Whether the AP is a local device's hotspot network */ gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ } NMAccessPointPrivate; -#define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) +struct _NMAccessPoint { + NMExportedObject parent; + NMAccessPointPrivate _priv; +}; + +struct _NMAccessPointClass{ + NMExportedObjectClass parent; +}; + +#define NM_AP_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMAccessPoint *_self2 = (_self); \ + \ + nm_assert (NM_IS_AP (_self)); \ + &_self->_priv; \ + }) G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT) -enum { - PROP_0, +NM_GOBJECT_PROPERTIES_DEFINE (NMAccessPoint, PROP_FLAGS, PROP_WPA_FLAGS, PROP_RSN_FLAGS, @@ -75,8 +94,7 @@ enum { PROP_MAX_BITRATE, PROP_STRENGTH, PROP_LAST_SEEN, - LAST_PROP -}; +); /*****************************************************************/ @@ -130,7 +148,7 @@ nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len) g_byte_array_append (priv->ssid, ssid, len); } - g_object_notify (G_OBJECT (ap), NM_AP_SSID); + _notify (ap, PROP_SSID); } static void @@ -144,7 +162,7 @@ nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) if (priv->flags != flags) { priv->flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); + _notify (ap, PROP_FLAGS); } } @@ -158,7 +176,7 @@ nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) priv = NM_AP_GET_PRIVATE (ap); if (priv->wpa_flags != flags) { priv->wpa_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); + _notify (ap, PROP_WPA_FLAGS); } } @@ -172,7 +190,7 @@ nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) priv = NM_AP_GET_PRIVATE (ap); if (priv->rsn_flags != flags) { priv->rsn_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); + _notify (ap, PROP_RSN_FLAGS); } } @@ -198,7 +216,7 @@ nm_ap_set_address (NMAccessPoint *ap, const char *addr) if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) { g_free (priv->address); priv->address = g_strdup (addr); - g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); + _notify (ap, PROP_HW_ADDRESS); } } @@ -223,7 +241,7 @@ nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) if (priv->mode != mode) { priv->mode = mode; - g_object_notify (G_OBJECT (ap), NM_AP_MODE); + _notify (ap, PROP_MODE); } } @@ -254,7 +272,7 @@ nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) if (priv->strength != strength) { priv->strength = strength; - g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); + _notify (ap, PROP_STRENGTH); } } @@ -278,7 +296,7 @@ nm_ap_set_freq (NMAccessPoint *ap, if (priv->freq != freq) { priv->freq = freq; - g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); + _notify (ap, PROP_FREQUENCY); } } @@ -302,7 +320,7 @@ nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) if (priv->max_bitrate != bitrate) { priv->max_bitrate = bitrate; - g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); + _notify (ap, PROP_MAX_BITRATE); } } @@ -333,7 +351,7 @@ nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) if (priv->last_seen != last_seen) { priv->last_seen = last_seen; - g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); + _notify (ap, PROP_LAST_SEEN); } } @@ -879,7 +897,7 @@ nm_ap_init (NMAccessPoint *ap) static void finalize (GObject *object) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object); g_free (priv->supplicant_path); if (priv->ssid) @@ -891,16 +909,16 @@ finalize (GObject *object) static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE ((NMAccessPoint *) object); GVariant *ssid; switch (prop_id) { @@ -965,8 +983,6 @@ nm_ap_class_init (NMAccessPointClass *ap_class) | NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X; - g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); - exported_object_class->export_path = NM_DBUS_PATH_ACCESS_POINT "/%u"; /* virtual methods */ @@ -975,72 +991,64 @@ nm_ap_class_init (NMAccessPointClass *ap_class) object_class->finalize = finalize; /* properties */ - g_object_class_install_property - (object_class, PROP_FLAGS, - g_param_spec_uint (NM_AP_FLAGS, "", "", - NM_802_11_AP_FLAGS_NONE, - NM_802_11_AP_FLAGS_PRIVACY, - NM_802_11_AP_FLAGS_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_WPA_FLAGS, - g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_RSN_FLAGS, - g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SSID, - g_param_spec_variant (NM_AP_SSID, "", "", - G_VARIANT_TYPE ("ay"), - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_FREQUENCY, - g_param_spec_uint (NM_AP_FREQUENCY, "", "", - 0, 10000, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_AP_HW_ADDRESS, "", "", + obj_properties[PROP_FLAGS] = + g_param_spec_uint (NM_AP_FLAGS, "", "", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WPA_FLAGS] = + g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_RSN_FLAGS] = + g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SSID] = + g_param_spec_variant (NM_AP_SSID, "", "", + G_VARIANT_TYPE ("ay"), NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_AP_MODE, "", "", - NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MAX_BITRATE, - g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_STRENGTH, - g_param_spec_uchar (NM_AP_STRENGTH, "", "", - 0, G_MAXINT8, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LAST_SEEN, - g_param_spec_int (NM_AP_LAST_SEEN, "", "", - -1, G_MAXINT, -1, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_FREQUENCY] = + g_param_spec_uint (NM_AP_FREQUENCY, "", "", + 0, 10000, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_AP_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODE] = + g_param_spec_uint (NM_AP_MODE, "", "", + NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MAX_BITRATE] = + g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", + 0, G_MAXUINT16, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STRENGTH] = + g_param_spec_uchar (NM_AP_STRENGTH, "", "", + 0, G_MAXINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_LAST_SEEN] = + g_param_spec_int (NM_AP_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class), NMDBUS_TYPE_ACCESS_POINT_SKELETON, diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 84aff983c2..035d1b5e57 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -44,14 +44,8 @@ #define NM_AP_STRENGTH "strength" #define NM_AP_LAST_SEEN "last-seen" -typedef struct { - NMExportedObject parent; -} NMAccessPoint; - -typedef struct { - NMExportedObjectClass parent; - -} NMAccessPointClass; +typedef struct _NMAccessPoint NMAccessPoint; +typedef struct _NMAccessPointClass NMAccessPointClass; GType nm_ap_get_type (void); diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index 838368c479..dbe185b3a8 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -26,7 +26,7 @@ #include "nm-core-internal.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #define DEBUG 1 diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index a8361c4976..0f96dafbfc 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -60,6 +60,7 @@ static void ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); + NMDeviceModem *self = NM_DEVICE_MODEM (user_data); switch (nm_device_get_state (device)) { case NM_DEVICE_STATE_PREPARE: @@ -73,7 +74,18 @@ ppp_failed (NMModem *modem, NMDeviceStateReason reason, gpointer user_data) case NM_DEVICE_STATE_ACTIVATED: if (nm_device_activate_ip4_state_in_conf (device)) nm_device_activate_schedule_ip4_config_timeout (device); - else { + else if (nm_device_activate_ip6_state_in_conf (device)) + nm_device_activate_schedule_ip6_config_timeout (device); + else if (nm_device_activate_ip4_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else if (nm_device_activate_ip6_state_done (device)) { + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + } else { + _LOGW (LOGD_MB, "PPP failure in unexpected state %u", (guint) nm_device_get_state (device)); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); @@ -159,8 +171,9 @@ modem_ip4_config_result (NMModem *modem, if (error) { _LOGW (LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } else { nm_device_set_wwan_ip4_config (device, config); nm_device_activate_schedule_ip4_config_result (device, NULL); @@ -184,9 +197,11 @@ modem_ip6_config_result (NMModem *modem, g_return_if_fail (nm_device_activate_ip6_state_in_conf (device) == TRUE); if (error) { - _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", error->message); - - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: %s", + error->message); + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return; } @@ -201,7 +216,9 @@ modem_ip6_config_result (NMModem *modem, nm_device_activate_schedule_ip6_config_result (device); else { _LOGW (LOGD_MB | LOGD_IP6, "retrieving IPv6 configuration failed: SLAAC not requested and no addresses"); - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + nm_device_ip_method_failed (device, + AF_INET6, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } return; } @@ -211,7 +228,7 @@ modem_ip6_config_result (NMModem *modem, g_assert (ignored == NULL); switch (ret) { case NM_ACT_STAGE_RETURN_FAILURE: - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason); + nm_device_ip_method_failed (device, AF_INET6, reason); break; case NM_ACT_STAGE_RETURN_STOP: /* all done */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index 1a6e6b2524..105cf4ddf3 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -89,8 +89,35 @@ enum { /*****************************************************************************/ +#define _NMLOG_DOMAIN LOGD_MB +#define _NMLOG_PREFIX_NAME "modem-broadband" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled (_level, (_NMLOG_DOMAIN))) { \ + NMModemBroadband *const __self = (self); \ + char __prefix_name[128]; \ + const char *__uid; \ + \ + _nm_log (_level, (_NMLOG_DOMAIN), 0, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (__self \ + ? ({ \ + ((__uid = nm_modem_get_uid ((NMModem *) __self)) \ + ? nm_sprintf_buf (__prefix_name, "[%s]", __uid) \ + : "(null)"); \ + }) \ + : "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } G_STMT_END + +/*****************************************************************************/ + static NMDeviceStateReason -translate_mm_error (GError *error) +translate_mm_error (NMModemBroadband *self, GError *error) { NMDeviceStateReason reason; @@ -122,7 +149,7 @@ translate_mm_error (GError *error) reason = NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT; else { /* unable to map the ModemManager error to a NM_DEVICE_STATE_REASON */ - nm_log_dbg (LOGD_MB, "unmapped error detected: '%s'", error->message); + _LOGD ("unmapped error detected: '%s'", error->message); reason = NM_DEVICE_STATE_REASON_UNKNOWN; } @@ -288,7 +315,7 @@ connect_context_clear (NMModemBroadband *self) g_clear_error (&ctx->first_error); g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); - g_clear_object (&ctx->cancellable); + nm_clear_g_cancellable (&ctx->cancellable); g_clear_object (&ctx->connection); g_clear_object (&ctx->connect_properties); g_clear_object (&ctx->self); @@ -360,8 +387,7 @@ connect_ready (MMModemSimple *simple_iface, if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { - nm_log_warn (LOGD_MB, "(%s): failed to connect modem: invalid bearer IP configuration", - nm_modem_get_uid (NM_MODEM (self))); + _LOGW ("failed to connect modem: invalid bearer IP configuration"); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); connect_context_clear (self); return; @@ -389,7 +415,7 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) return; if (!self->priv->ctx || self->priv->ctx->step != CONNECT_STEP_UNLOCK) - return; + g_return_if_reached (); if (error) { if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || @@ -397,7 +423,7 @@ send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { ask_for_pin (self); } else { - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, error)); } return; } @@ -459,9 +485,8 @@ connect_context_step (NMModemBroadband *self) else if (MODEM_CAPS_3GPP2 (ctx->caps)) ctx->connect_properties = create_cdma_connect_properties (ctx->connection); else { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (ctx->connection)); + _LOGW ("failed to connect '%s': not a mobile broadband modem", + nm_connection_get_id (ctx->connection)); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); connect_context_clear (self); @@ -472,10 +497,9 @@ connect_context_step (NMModemBroadband *self) /* Build up list of IP types that we need to use in the retries */ ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error); if (!ctx->ip_types) { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (ctx->connection), - error->message); + _LOGW ("failed to connect '%s': %s", + nm_connection_get_id (ctx->connection), + error->message); g_clear_error (&error); g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); @@ -502,10 +526,9 @@ connect_context_step (NMModemBroadband *self) else g_assert_not_reached (); - nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s' (try %d)", - nm_modem_get_uid (NM_MODEM (self)), - nm_modem_ip_type_to_string (current), - ctx->ip_type_tries + 1); + _LOGD ("launching connection with ip type '%s' (try %d)", + nm_modem_ip_type_to_string (current), + ctx->ip_type_tries + 1); mm_modem_simple_connect (self->priv->simple_iface, ctx->connect_properties, @@ -528,10 +551,9 @@ connect_context_step (NMModemBroadband *self) NM_DEVICE_ERROR_INVALID_CONNECTION, "invalid bearer IP configuration"); - nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - ctx->first_error->message); - g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error)); + _LOGW ("failed to connect modem: %s", + ctx->first_error->message); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (self, ctx->first_error)); } connect_context_clear (self); @@ -550,8 +572,7 @@ act_stage1_prepare (NMModem *_self, if (!self->priv->simple_iface) { self->priv->simple_iface = mm_object_get_modem_simple (self->priv->modem_object); if (!self->priv->simple_iface) { - nm_log_warn (LOGD_MB, "(%s) cannot access the Simple mobile broadband modem interface", - nm_modem_get_uid (NM_MODEM (self))); + _LOGW ("cannot access the Simple mobile broadband modem interface"); *reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; return NM_ACT_STAGE_RETURN_FAILURE; } @@ -745,9 +766,8 @@ set_power_state_low_ready (MMModem *modem, if (!mm_modem_set_power_state_finish (modem, result, &error)) { /* Log but ignore errors; not all modems support low power state */ - nm_log_dbg (LOGD_MB, "(%s): failed to set modem low power state: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGD ("failed to set modem low power state: %s", + NM_G_ERROR_MSG (error)); g_clear_error (&error); } @@ -770,9 +790,8 @@ modem_disable_ready (MMModem *modem_iface, (GAsyncReadyCallback) set_power_state_low_ready, g_object_ref (self)); } else { - nm_log_warn (LOGD_MB, "(%s): failed to disable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGW ("failed to disable modem: %s", + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "disable failed"); g_clear_error (&error); } @@ -789,9 +808,8 @@ modem_enable_ready (MMModem *modem_iface, GError *error = NULL; if (!mm_modem_enable_finish (modem_iface, res, &error)) { - nm_log_warn (LOGD_MB, "(%s) failed to enable modem: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGW ("failed to enable modem: %s", + NM_G_ERROR_MSG (error)); nm_modem_set_prev_state (NM_MODEM (self), "enable failed"); g_clear_error (&error); } @@ -854,8 +872,7 @@ static_stage3_ip4_done (NMModemBroadband *self) g_assert (self->priv->ipv4_config); g_assert (self->priv->bearer); - nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", - nm_modem_get_uid (NM_MODEM (self))); + _LOGI ("IPv4 static configuration:"); /* Fully fail if invalid IP address retrieved */ address_string = mm_bearer_ip_config_get_address (self->priv->ipv4_config); @@ -880,15 +897,15 @@ static_stage3_ip4_done (NMModemBroadband *self) address.address = address_network; address.peer_address = address_network; address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config); - address.source = NM_IP_CONFIG_SOURCE_WWAN; + address.addr_source = NM_IP_CONFIG_SOURCE_WWAN; if (address.plen <= 32) nm_ip4_config_add_address (config, &address); - nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen); + _LOGI (" address %s/%d", address_string, address.plen); if (gw) { nm_ip4_config_set_gateway (config, gw); - nm_log_info (LOGD_MB, " gateway %s", gw_string); + _LOGI (" gateway %s", gw_string); } /* DNS servers */ @@ -897,7 +914,7 @@ static_stage3_ip4_done (NMModemBroadband *self) if ( ip4_string_to_num (dns[i], &address_network) && address_network > 0) { nm_ip4_config_add_nameserver (config, address_network); - nm_log_info (LOGD_MB, " DNS %s", dns[i]); + _LOGI (" DNS %s", dns[i]); } } @@ -964,8 +981,7 @@ stage3_ip6_done (NMModemBroadband *self) goto out; } - nm_log_info (LOGD_MB, "(%s): IPv6 base configuration:", - nm_modem_get_uid (NM_MODEM (self))); + _LOGI ("IPv6 base configuration:"); data_port = mm_bearer_get_interface (self->priv->bearer); g_assert (data_port); @@ -975,7 +991,7 @@ stage3_ip6_done (NMModemBroadband *self) if (address.plen <= 128) nm_ip6_config_add_address (config, &address); - nm_log_info (LOGD_MB, " address %s/%d", address_string, address.plen); + _LOGI (" address %s/%d", address_string, address.plen); address_string = mm_bearer_ip_config_get_gateway (self->priv->ipv6_config); if (address_string) { @@ -987,7 +1003,7 @@ stage3_ip6_done (NMModemBroadband *self) address_string); goto out; } - nm_log_info (LOGD_MB, " gateway %s", address_string); + _LOGI (" gateway %s", address_string); nm_ip6_config_set_gateway (config, &address.address); } else if (ip_method == NM_MODEM_IP_METHOD_STATIC) { /* Gateway required for the 'static' method */ @@ -1005,7 +1021,7 @@ stage3_ip6_done (NMModemBroadband *self) if (inet_pton (AF_INET6, dns[i], &addr)) { nm_ip6_config_add_nameserver (config, &addr); - nm_log_info (LOGD_MB, " DNS %s", dns[i]); + _LOGI (" DNS %s", dns[i]); } } @@ -1050,19 +1066,6 @@ disconnect_context_complete (DisconnectContext *ctx) } static gboolean -disconnect_context_complete_if_cancelled (DisconnectContext *ctx) -{ - GError *error = NULL; - - if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { - g_simple_async_result_take_error (ctx->result, error); - disconnect_context_complete (ctx); - return TRUE; - } - return FALSE; -} - -static gboolean disconnect_finish (NMModem *self, GAsyncResult *res, GError **error) @@ -1079,9 +1082,10 @@ simple_disconnect_ready (MMModemSimple *modem_iface, if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { if (ctx->warn && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { - nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s", - nm_modem_get_uid (NM_MODEM (ctx->self)), - error->message); + NMModemBroadband *self = ctx->self; + + _LOGW ("failed to disconnect modem: %s", + error->message); } g_simple_async_result_take_error (ctx->result, error); } @@ -1098,9 +1102,11 @@ disconnect (NMModem *modem, { NMModemBroadband *self = NM_MODEM_BROADBAND (modem); DisconnectContext *ctx; + GError *error = NULL; connect_context_clear (self); ctx = g_slice_new (DisconnectContext); + ctx->cancellable = NULL; ctx->self = g_object_ref (self); ctx->result = g_simple_async_result_new (G_OBJECT (self), callback, @@ -1109,10 +1115,12 @@ disconnect (NMModem *modem, /* Don't bother warning on FAILED since the modem is already gone */ ctx->warn = warn; - /* Setup cancellable */ - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - if (disconnect_context_complete_if_cancelled (ctx)) + /* Already cancelled? */ + if (g_cancellable_set_error_if_cancelled (cancellable, &error)) { + g_simple_async_result_take_error (ctx->result, error); + disconnect_context_complete (ctx); return; + } /* If no simple iface, we're done */ if (!ctx->self->priv->simple_iface) { @@ -1120,14 +1128,13 @@ disconnect (NMModem *modem, return; } - nm_log_dbg (LOGD_MB, "(%s): notifying ModemManager about the modem disconnection", - nm_modem_get_uid (NM_MODEM (ctx->self))); - mm_modem_simple_disconnect ( - ctx->self->priv->simple_iface, - NULL, /* bearer path; if NULL given ALL get disconnected */ - cancellable, - (GAsyncReadyCallback)simple_disconnect_ready, - ctx); + _LOGD ("notifying ModemManager about the modem disconnection"); + ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + mm_modem_simple_disconnect (ctx->self->priv->simple_iface, + NULL, /* bearer path; if NULL given ALL get disconnected */ + cancellable, + (GAsyncReadyCallback) simple_disconnect_ready, + ctx); } /*****************************************************************************/ @@ -1274,9 +1281,8 @@ get_sim_ready (MMModem *modem, if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_SIM) connect_context_step (self); } else { - nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s", - nm_modem_get_uid (NM_MODEM (self)), - NM_G_ERROR_MSG (error)); + _LOGW ("failed to retrieve SIM object: %s", + NM_G_ERROR_MSG (error)); } g_clear_error (&error); g_object_unref (self); diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index c102581733..eab6132b2a 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -559,51 +559,49 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) { - char *pid_contents = NULL, *proc_contents = NULL, *proc_path = NULL; - long int tmp; + guint64 start_time; + pid_t pid, ppid; + const char *exe; + char proc_path[NM_STRLEN ("/proc/%lu/cmdline") + 100]; + gs_free char *pid_contents = NULL, *proc_contents = NULL; /* Check for an existing instance and stop it */ if (!g_file_get_contents (pid_file, &pid_contents, NULL, NULL)) return; - errno = 0; - tmp = strtol (pid_contents, NULL, 10); - if ((errno == 0) && (tmp > 1)) { - guint64 start_time; - const char *exe; - pid_t ppid; - - /* Ensure the process is a DHCP client */ - start_time = nm_utils_get_start_time_for_pid (tmp, NULL, &ppid); - proc_path = g_strdup_printf ("/proc/%ld/cmdline", tmp); - if ( start_time - && g_file_get_contents (proc_path, &proc_contents, NULL, NULL)) { - exe = strrchr (proc_contents, '/'); - if (exe) - exe++; - else - exe = proc_contents; - - if (!strcmp (exe, binary_name)) { - if (ppid == getpid ()) { - /* the process is our own child. */ - nm_utils_kill_child_sync (tmp, SIGTERM, LOGD_DHCP, "dhcp-client", NULL, 1000 / 2, 1000 / 20); - } else { - nm_utils_kill_process_sync (tmp, start_time, SIGTERM, LOGD_DHCP, - "dhcp-client", 1000 / 2, 1000 / 20, 2000); - } - } - } + pid = _nm_utils_ascii_str_to_int64 (pid_contents, 10, 1, G_MAXINT64, 0); + if (pid <= 0) + goto out; + + start_time = nm_utils_get_start_time_for_pid (pid, NULL, &ppid); + if (start_time == 0) + goto out; + + nm_sprintf_buf (proc_path, "/proc/%lu/cmdline", (long unsigned) pid); + if (!g_file_get_contents (proc_path, &proc_contents, NULL, NULL)) + goto out; + + exe = strrchr (proc_contents, '/'); + if (exe) + exe++; + else + exe = proc_contents; + if (!nm_streq0 (exe, binary_name)) + goto out; + + if (ppid == getpid ()) { + /* the process is our own child. */ + nm_utils_kill_child_sync (pid, SIGTERM, LOGD_DHCP, "dhcp-client", NULL, 1000 / 2, 1000 / 20); + } else { + nm_utils_kill_process_sync (pid, start_time, SIGTERM, LOGD_DHCP, + "dhcp-client", 1000 / 2, 1000 / 20, 2000); } +out: if (remove (pid_file) == -1) { nm_log_dbg (LOGD_DHCP, "dhcp: could not remove pid file \"%s\": %d (%s)", pid_file, errno, g_strerror (errno)); } - - g_free (proc_path); - g_free (pid_contents); - g_free (proc_contents); } void @@ -836,7 +834,7 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_IFACE: /* construct-only */ - priv->iface = g_strdup (g_value_get_string (value)); + priv->iface = g_value_dup_string (value); break; case PROP_IFINDEX: /* construct-only */ diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c index 008f8af2ba..8d4c54ae15 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c +++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c @@ -720,7 +720,7 @@ nm_dhcp_dhclient_read_lease_ip_configs (const char *iface, address.timestamp = now_monotonic_ts; address.lifetime = address.preferred = expiry; - address.source = NM_IP_CONFIG_SOURCE_DHCP; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; ip4 = nm_ip4_config_new (ifindex); nm_ip4_config_add_address (ip4, &address); diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index 4b6d301b50..ade206bad9 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -18,7 +18,8 @@ * Copyright (C) 2005 - 2012 Red Hat, Inc. */ -#include "config.h" +#include <config.h> +#define __CONFIG_H__ #define _XOPEN_SOURCE #include <time.h> @@ -177,6 +178,9 @@ merge_dhclient_config (NMDhcpDhclient *self, } } + if (is_ip6 && hostname && !strchr (hostname, '.')) + _LOGW ("hostname is not a FQDN, it will be ignored"); + new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, fqdn, orig_path, orig, out_new_client_id); g_assert (new); success = g_file_set_contents (conf_file, new, -1, error); diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c index 82cb335076..28a8988613 100644 --- a/src/dhcp-manager/nm-dhcp-systemd.c +++ b/src/dhcp-manager/nm-dhcp-systemd.c @@ -256,7 +256,7 @@ lease_to_ip4_config (const char *iface, SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, end_time); - address.source = NM_IP_CONFIG_SOURCE_DHCP; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); /* DNS Servers */ @@ -323,7 +323,7 @@ lease_to_ip4_config (const char *iface, route.gateway = a.s_addr; if (route.plen) { - route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = default_priority; nm_ip4_config_add_route (ip4_config, &route); @@ -578,6 +578,8 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last return FALSE; } + _LOGT ("dhcp-client4: set %p", priv->client4); + r = sd_dhcp_client_attach_event (priv->client4, NULL, 0); if (r < 0) { _LOGW ("failed to attach event (%d)", r); @@ -602,9 +604,9 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last } } - r = sd_dhcp_client_set_index (priv->client4, nm_dhcp_client_get_ifindex (client)); + r = sd_dhcp_client_set_ifindex (priv->client4, nm_dhcp_client_get_ifindex (client)); if (r < 0) { - _LOGW ("failed to set ifindex (%d)", r); + _LOGW ("failed to set ififindex (%d)", r); goto error; } @@ -741,7 +743,7 @@ lease_to_ip6_config (const char *iface, .timestamp = ts, .lifetime = lft_valid, .preferred = lft_pref, - .source = NM_IP_CONFIG_SOURCE_DHCP, + .addr_source = NM_IP_CONFIG_SOURCE_DHCP, }; nm_ip6_config_add_address (ip6_config, &address); @@ -895,6 +897,8 @@ ip6_start (NMDhcpClient *client, return FALSE; } + _LOGT ("dhcp-client6: set %p", priv->client4); + if (info_only) sd_dhcp6_client_set_information_request (priv->client6, 1); @@ -928,7 +932,7 @@ ip6_start (NMDhcpClient *client, } } - r = sd_dhcp6_client_set_index (priv->client6, nm_dhcp_client_get_ifindex (client)); + r = sd_dhcp6_client_set_ifindex (priv->client6, nm_dhcp_client_get_ifindex (client)); if (r < 0) { _LOGW ("failed to set ifindex (%d)", r); goto error; @@ -973,6 +977,10 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid) NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); int r = 0; + _LOGT ("dhcp-client%d: stop %p", + priv->client4 ? '4' : '6', + priv->client4 ? (gpointer) priv->client4 : (gpointer) priv->client6); + if (priv->client4) { sd_dhcp_client_set_callback (priv->client4, NULL, NULL); r = sd_dhcp_client_stop (priv->client4); diff --git a/src/dhcp-manager/nm-dhcp-utils.c b/src/dhcp-manager/nm-dhcp-utils.c index a88a7e6d51..3c397ce1f6 100644 --- a/src/dhcp-manager/nm-dhcp-utils.c +++ b/src/dhcp-manager/nm-dhcp-utils.c @@ -84,7 +84,7 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str, route.network = rt_addr; route.plen = rt_cidr; route.gateway = rt_route; - route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = priority; nm_ip4_config_add_route (ip4_config, &route); } @@ -192,7 +192,7 @@ ip4_process_dhclient_rfc3442_routes (const char *str, char addr[INET_ADDRSTRLEN]; /* normal route */ - route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = priority; nm_ip4_config_add_route (ip4_config, &route); @@ -314,7 +314,7 @@ process_classful_routes (GHashTable *options, guint32 priority, NMIP4Config *ip4 route.plen = 32; } route.gateway = rt_route; - route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = priority; nm_ip4_config_add_route (ip4_config, &route); @@ -465,7 +465,7 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex, route.plen = 32; /* this will be a device route if gwaddr is 0 */ route.gateway = gwaddr; - route.source = NM_IP_CONFIG_SOURCE_DHCP; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; route.metric = priority; nm_ip4_config_add_route (ip4_config, &route); nm_log_dbg (LOGD_IP, "adding route for server identifier: %s", @@ -482,7 +482,7 @@ nm_dhcp_utils_ip4_config_from_options (int ifindex, nm_log_info (LOGD_DHCP4, " lease time %u", address.lifetime); } - address.source = NM_IP_CONFIG_SOURCE_DHCP; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip4_config_add_address (ip4_config, &address); str = g_hash_table_lookup (options, "host_name"); @@ -642,7 +642,7 @@ nm_dhcp_utils_ip6_config_from_options (int ifindex, } address.address = tmp_addr; - address.source = NM_IP_CONFIG_SOURCE_DHCP; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; nm_ip6_config_add_address (ip6_config, &address); nm_log_info (LOGD_DHCP6, " address %s", str); } else if (info_only == FALSE) { diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c index 046dd7e242..77849c8c38 100644 --- a/src/dhcp-manager/tests/test-dhcp-dhclient.c +++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c @@ -31,7 +31,7 @@ #include "nm-ip4-config.h" #include "nm-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #define DEBUG 1 diff --git a/src/dhcp-manager/tests/test-dhcp-utils.c b/src/dhcp-manager/tests/test-dhcp-utils.c index f477c061fb..89d693ed11 100644 --- a/src/dhcp-manager/tests/test-dhcp-utils.c +++ b/src/dhcp-manager/tests/test-dhcp-utils.c @@ -28,7 +28,7 @@ #include "nm-dhcp-utils.h" #include "nm-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" typedef struct { const char *name; diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 8868b4bb9f..8c7c8c3ecb 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -26,6 +26,7 @@ #include <sys/wait.h> #include <arpa/inet.h> #include <sys/stat.h> +#include <linux/if.h> #include "nm-dns-dnsmasq.h" #include "nm-utils.h" @@ -90,13 +91,16 @@ add_dnsmasq_nameserver (NMDnsDnsmasq *self, } static gboolean -add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, gboolean split) +add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, + const char *iface, gboolean split) { - char buf[INET_ADDRSTRLEN]; + char buf[INET_ADDRSTRLEN + 1 + IFNAMSIZ]; + char buf2[INET_ADDRSTRLEN]; in_addr_t addr; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; + g_return_val_if_fail (iface, FALSE); nnameservers = nm_ip4_config_get_num_nameservers (ip4); if (split) { @@ -107,7 +111,8 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) { addr = nm_ip4_config_get_nameserver (ip4, i_nameserver); - nm_utils_inet4_ntop (addr, buf); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); /* searches are preferred over domains */ n = nm_ip4_config_get_num_searches (ip4); @@ -147,8 +152,9 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip4_config_get_nameserver (ip4, i); - add_dnsmasq_nameserver (self, servers, - nm_utils_inet4_ntop (addr, NULL), NULL); + g_snprintf (buf, sizeof (buf), "%s@%s", + nm_utils_inet4_ntop (addr, buf2), iface); + add_dnsmasq_nameserver (self, servers, buf, NULL); } } @@ -158,23 +164,22 @@ add_ip4_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP4Config *ip4, static char * ip6_addr_to_string (const struct in6_addr *addr, const char *iface) { - char *buf; + char buf[NM_UTILS_INET_ADDRSTRLEN]; - if (IN6_IS_ADDR_V4MAPPED (addr)) { - buf = g_malloc (INET_ADDRSTRLEN); + if (IN6_IS_ADDR_V4MAPPED (addr)) nm_utils_inet4_ntop (addr->s6_addr32[3], buf); - } else if (!iface || !iface[0] || !IN6_IS_ADDR_LINKLOCAL (addr)) { - buf = g_malloc (INET6_ADDRSTRLEN); + else nm_utils_inet6_ntop (addr, buf); - } else { - /* Need to scope the address with %<zone-id>. Before dnsmasq 2.58, - * only '@' was supported as delimiter. Since 2.58, '@' and '%' - * are supported. Due to a bug, since 2.73 only '%' works properly - * as "server" address. - */ - buf = g_strconcat (nm_utils_inet6_ntop (addr, NULL), "%", iface, NULL); - } - return buf; + + /* Need to scope link-local addresses with %<zone-id>. Before dnsmasq 2.58, + * only '@' was supported as delimiter. Since 2.58, '@' and '%' are + * supported. Due to a bug, since 2.73 only '%' works properly as "server" + * address. + */ + return g_strdup_printf ("%s%c%s", + buf, + IN6_IS_ADDR_LINKLOCAL (addr) ? '%' : '@', + iface); } static void @@ -202,19 +207,17 @@ add_global_config (NMDnsDnsmasq *self, GVariantBuilder *dnsmasq_servers, const N } static gboolean -add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, gboolean split) +add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, + const char *iface, gboolean split) { const struct in6_addr *addr; char *buf = NULL; int nnameservers, i_nameserver, n, i; gboolean added = FALSE; - const char *iface; + g_return_val_if_fail (iface, FALSE); nnameservers = nm_ip6_config_get_num_nameservers (ip6); - iface = g_object_get_data (G_OBJECT (ip6), IP_CONFIG_IFACE_TAG); - g_assert (iface); - if (split) { if (nnameservers == 0) return FALSE; @@ -249,7 +252,7 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, } } - /* If no searches or domains, just add the namservers */ + /* If no searches or domains, just add the nameservers */ if (!added) { for (i = 0; i < nnameservers; i++) { addr = nm_ip6_config_get_nameserver (ip6, i); @@ -264,6 +267,25 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, return TRUE; } +static gboolean +add_ip_config_data (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigData *data) +{ + if (NM_IS_IP4_CONFIG (data->config)) { + return add_ip4_config (self, + servers, + (NMIP4Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else if (NM_IS_IP6_CONFIG (data->config)) { + return add_ip6_config (self, + servers, + (NMIP6Config *) data->config, + data->iface, + data->type == NM_DNS_IP_CONFIG_TYPE_VPN); + } else + g_return_val_if_reached (FALSE); +} + static void dnsmasq_clear_cache_done (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data) { @@ -465,15 +487,12 @@ start_dnsmasq (NMDnsDnsmasq *self) static gboolean update (NMDnsPlugin *plugin, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin); NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self); - const GSList *iter; GVariantBuilder servers; start_dnsmasq (self); @@ -483,28 +502,9 @@ update (NMDnsPlugin *plugin, if (global_config) add_global_config (self, &servers, global_config); else { - /* Use split DNS for VPN configs */ - for (iter = vpn_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, TRUE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, TRUE); - } - - /* Now add interface configs without split DNS */ - for (iter = dev_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, FALSE); - } - - /* And any other random configs */ - for (iter = other_configs; iter; iter = g_slist_next (iter)) { - if (NM_IS_IP4_CONFIG (iter->data)) - add_ip4_config (self, &servers, iter->data, FALSE); - else if (NM_IS_IP6_CONFIG (iter->data)) - add_ip6_config (self, &servers, iter->data, FALSE); + while (*configs) { + add_ip_config_data (self, &servers, *configs); + configs++; } } @@ -518,24 +518,6 @@ update (NMDnsPlugin *plugin, /****************************************************************/ -static const char * -dm_exit_code_to_msg (int status) -{ - if (status == 1) - return "Configuration problem"; - else if (status == 2) - return "Network access problem (address in use; permissions; etc)"; - else if (status == 3) - return "Filesystem problem (missing file/directory; permissions; etc)"; - else if (status == 4) - return "Memory allocation failure"; - else if (status == 5) - return "Other problem"; - else if (status >= 11) - return "Lease-script 'init' process failure"; - return "Unknown error"; -} - static void child_quit (NMDnsPlugin *plugin, gint status) { @@ -546,9 +528,8 @@ child_quit (NMDnsPlugin *plugin, gint status) if (WIFEXITED (status)) { err = WEXITSTATUS (status); if (err) { - _LOGW ("dnsmasq exited with error: %s (%d)", - dm_exit_code_to_msg (err), - err); + _LOGW ("dnsmasq exited with error: %s", + nm_utils_dnsmasq_status_to_string (err, NULL, 0)); } else failed = FALSE; } else if (WIFSTOPPED (status)) diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 7285b89d99..a6aef6fe92 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -63,21 +63,15 @@ G_DEFINE_TYPE (NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) -#define NM_DNS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_DNS_MANAGER, \ - NMDnsManagerPrivate)) +#define NM_DNS_MANAGER_GET_PRIVATE(o) ((o)->priv) #define HASH_LEN 20 -#ifdef RESOLVCONF_PATH -#define RESOLVCONF_SELECTED -#else +#ifndef RESOLVCONF_PATH #define RESOLVCONF_PATH "/sbin/resolvconf" #endif -#ifdef NETCONFIG_PATH -#define NETCONFIG_SELECTED -#else +#ifndef NETCONFIG_PATH #define NETCONFIG_PATH "/sbin/netconfig" #endif @@ -111,23 +105,18 @@ NM_DEFINE_SINGLETON_INSTANCE (NMDnsManager); /*********************************************************************************************/ -typedef struct { - NMIP4Config *ip4_vpn_config; - NMIP4Config *ip4_device_config; - NMIP6Config *ip6_vpn_config; - NMIP6Config *ip6_device_config; - GSList *configs; +typedef struct _NMDnsManagerPrivate { + GPtrArray *configs; + NMDnsIPConfigData *best_conf4, *best_conf6; + gboolean need_sort; + char *hostname; guint updates_queue; guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ - NMDnsManagerResolvConfMode resolv_conf_mode; NMDnsManagerResolvConfManager rc_manager; - char *last_mode; - bool last_immutable:1; - bool mode_initialized:1; NMDnsPlugin *plugin; NMConfig *config; @@ -166,13 +155,88 @@ typedef struct { NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_rc_manager_to_string, NMDnsManagerResolvConfManager, NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, "none"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"), - NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), - NM_UTILS_LOOKUP_ITEM_IGNORE (_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, "unmanaged"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, "immutable"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, "symlink"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, "file"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, "resolvconf"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, "netconfig"), +); + +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_config_type_to_string, NMDnsIPConfigType, + NM_UTILS_LOOKUP_DEFAULT_WARN ("<unknown>"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_DEFAULT, "default"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, "best"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DNS_IP_CONFIG_TYPE_VPN, "vpn"), ); +static NMDnsIPConfigData * +ip_config_data_new (gpointer config, NMDnsIPConfigType type, const char *iface) +{ + NMDnsIPConfigData *data; + + data = g_slice_new0 (NMDnsIPConfigData); + data->config = g_object_ref (config); + data->iface = g_strdup (iface); + data->type = type; + + return data; +} + +static void +ip_config_data_destroy (gpointer ptr) +{ + NMDnsIPConfigData *data = ptr; + + if (!data) + return; + + g_object_unref (data->config); + g_free (data->iface); + g_slice_free (NMDnsIPConfigData, data); +} + +static gint +ip_config_data_compare (const NMDnsIPConfigData *a, const NMDnsIPConfigData *b) +{ + gboolean a_v4, b_v4; + gint a_prio, b_prio; + + a_v4 = NM_IS_IP4_CONFIG (a->config); + b_v4 = NM_IS_IP4_CONFIG (b->config); + + a_prio = a_v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) a->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) a->config); + + b_prio = b_v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) b->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) b->config); + + /* Configurations with lower priority value first */ + if (a_prio < b_prio) + return -1; + else if (a_prio > b_prio) + return 1; + + /* Sort also according to type */ + if (a->type > b->type) + return -1; + else if (a->type < b->type) + return 1; + + return 0; +} + +static gint +ip_config_data_ptr_compare (gconstpointer a, gconstpointer b) +{ + const NMDnsIPConfigData *const *ptr_a = a, *const *ptr_b = b; + + return ip_config_data_compare (*ptr_a, *ptr_b); +} + static void add_string_item (GPtrArray *array, const char *str) { @@ -257,12 +321,9 @@ merge_one_ip4_config (NMResolvConfData *rc, NMIP4Config *src) } static void -merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) +merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src, const char *iface) { guint32 num, num_domains, num_searches, i; - const char *iface; - - iface = g_object_get_data (G_OBJECT (src), IP_CONFIG_IFACE_TAG); num = nm_ip6_config_get_num_nameservers (src); for (i = 0; i < num; i++) { @@ -276,7 +337,7 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) nm_utils_inet4_ntop (addr->s6_addr32[3], buf); else { nm_utils_inet6_ntop (addr, buf); - if (iface && IN6_IS_ADDR_LINKLOCAL (addr)) { + if (IN6_IS_ADDR_LINKLOCAL (addr)) { g_strlcat (buf, "%", sizeof (buf)); g_strlcat (buf, iface, sizeof (buf)); } @@ -316,6 +377,19 @@ merge_one_ip6_config (NMResolvConfData *rc, NMIP6Config *src) } } +static void +merge_one_ip_config_data (NMDnsManager *self, + NMResolvConfData *rc, + NMDnsIPConfigData *data) +{ + if (NM_IS_IP4_CONFIG (data->config)) + merge_one_ip4_config (rc, (NMIP4Config *) data->config); + else if (NM_IS_IP6_CONFIG (data->config)) + merge_one_ip6_config (rc, (NMIP6Config *) data->config, data->iface); + else + g_return_if_reached (); +} + static GPid run_netconfig (NMDnsManager *self, GError **error, gint *stdin_fd) { @@ -470,12 +544,16 @@ write_resolv_conf_contents (FILE *f, const char *content, GError **error) { + int errsv; + if (fprintf (f, "%s", content) < 0) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not write " _PATH_RESCONF ": %s", - g_strerror (errno)); + g_strerror (errsv)); + errno = errsv; return FALSE; } @@ -574,6 +652,7 @@ update_resolv_conf (NMDnsManager *self, gboolean success; gs_free char *content = NULL; SpawnResult write_file_result = SR_SUCCESS; + int errsv; /* If we are not managing /etc/resolv.conf and it points to * MY_RESOLV_CONF, don't write the private DNS configuration to @@ -582,12 +661,12 @@ update_resolv_conf (NMDnsManager *self, * * This is the only situation, where we don't try to update our * internal resolv.conf file. */ - if (rc_manager == _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY) { + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED) { gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL); if (g_strcmp0 (path, MY_RESOLV_CONF) == 0) { - _LOGD ("not updating " MY_RESOLV_CONF - " since it points to " _PATH_RESCONF); + _LOGD ("update-resolv-conf: not updating " _PATH_RESCONF + " since it points to " MY_RESOLV_CONF); return SR_SUCCESS; } } @@ -595,29 +674,46 @@ update_resolv_conf (NMDnsManager *self, content = create_resolv_conf (searches, nameservers, options); if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { + GError *local = NULL; + /* we first write to /etc/resolv.conf directly. If that fails, * we still continue to write to runstatedir but remember the * error. */ - if (!g_file_set_contents (_PATH_RESCONF, content, -1, error)) { + if (!g_file_set_contents (_PATH_RESCONF, content, -1, &local)) { + _LOGT ("update-resolv-conf: write to %s failed (rc-managed=file, %s)", + _PATH_RESCONF, local->message); write_file_result = SR_ERROR; + g_propagate_error (error, local); error = NULL; + } else { + _LOGT ("update-resolv-conf: write to %s succeeded (rc-managed=file)", + _PATH_RESCONF); } } if ((f = fopen (MY_RESOLV_CONF_TMP, "w")) == NULL) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not open %s: %s", MY_RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: open temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } success = write_resolv_conf_contents (f, content, error); + if (!success) { + errsv = errno; + _LOGT ("update-resolv-conf: write temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); + } if (fclose (f) < 0) { if (success) { + errsv = errno; /* only set an error here if write_resolv_conf() was successful, * since its error is more important. */ @@ -626,39 +722,66 @@ update_resolv_conf (NMDnsManager *self, NM_MANAGER_ERROR_FAILED, "Could not close %s: %s", MY_RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: close temporary file %s failed (%s)", + MY_RESOLV_CONF_TMP, g_strerror (errsv)); } return SR_ERROR; } else if (!success) return SR_ERROR; if (rename (MY_RESOLV_CONF_TMP, MY_RESOLV_CONF) < 0) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not replace %s: %s", MY_RESOLV_CONF, g_strerror (errno)); + _LOGT ("update-resolv-conf: failed to rename temporary file %s to %s (%s)", + MY_RESOLV_CONF_TMP, MY_RESOLV_CONF, g_strerror (errsv)); return SR_ERROR; } - if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE) { + _LOGT ("update-resolv-conf: write internal file %s succeeded (rc-manager=file)", + MY_RESOLV_CONF); return write_file_result; + } - if (rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE) + if (rc_manager != NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK) { + _LOGT ("update-resolv-conf: write internal file %s succeeded", MY_RESOLV_CONF); return SR_SUCCESS; + } /* A symlink pointing to NM's own resolv.conf (MY_RESOLV_CONF) is always * overwritten to ensure that changes are indicated with inotify. Symlinks * pointing to any other file are never overwritten. */ - if (lstat (_PATH_RESCONF, &st) != -1) { + if (lstat (_PATH_RESCONF, &st) != 0) { + errsv = errno; + if (errsv != ENOENT) { + /* NM cannot read /etc/resolv.conf */ + _LOGT ("update-resolv-conf: write internal file %s succeeded but lstat(%s) failed (%s)", + MY_RESOLV_CONF, _PATH_RESCONF, g_strerror (errsv)); + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "Could not lstat %s: %s", + _PATH_RESCONF, + g_strerror (errsv)); + return SR_ERROR; + } + } else { if (S_ISLNK (st.st_mode)) { if (stat (_PATH_RESCONF, &st) != -1) { gs_free char *path = g_file_read_link (_PATH_RESCONF, NULL); - if (g_strcmp0 (path, MY_RESOLV_CONF) != 0) { + if (!path || !nm_streq (path, MY_RESOLV_CONF)) { /* It's not NM's symlink; do nothing */ + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but don't update %s as it points to %s", + MY_RESOLV_CONF, _PATH_RESCONF, path ?: ""); return SR_SUCCESS; } @@ -669,56 +792,64 @@ update_resolv_conf (NMDnsManager *self, * some other program is probably managing resolv.conf and * NM should not touch it. */ + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but don't update %s as the symlinks points somewhere else", + MY_RESOLV_CONF, _PATH_RESCONF); return SR_SUCCESS; } } - } else if (errno != ENOENT) { - /* NM cannot read /etc/resolv.conf */ - g_set_error (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "Could not lstat %s: %s", - _PATH_RESCONF, - g_strerror (errno)); - return SR_ERROR; } /* By this point, either /etc/resolv.conf does not exist, is a regular * file, or is a symlink already owned by NM. In all cases /etc/resolv.conf * is replaced with a symlink pointing to NM's resolv.conf in /var/run/. */ - if (unlink (RESOLV_CONF_TMP) == -1 && errno != ENOENT) { + if ( unlink (RESOLV_CONF_TMP) != 0 + && ((errsv = errno) != ENOENT)) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not unlink %s: %s", RESOLV_CONF_TMP, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but canot delete temporary file %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } if (symlink (MY_RESOLV_CONF, RESOLV_CONF_TMP) == -1) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not create symlink %s pointing to %s: %s", RESOLV_CONF_TMP, MY_RESOLV_CONF, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but failed to symlink %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, g_strerror (errsv)); return SR_ERROR; } if (rename (RESOLV_CONF_TMP, _PATH_RESCONF) == -1) { + errsv = errno; g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, "Could not rename %s to %s: %s", RESOLV_CONF_TMP, _PATH_RESCONF, - g_strerror (errno)); + g_strerror (errsv)); + _LOGT ("update-resolv-conf: write internal file %s succeeded " + "but failed to rename temporary symlink %s to %s: %s", + MY_RESOLV_CONF, RESOLV_CONF_TMP, _PATH_RESCONF, g_strerror (errsv)); return SR_ERROR; } + _LOGT ("update-resolv-conf: write internal file %s succeeded and update symlink %s", + MY_RESOLV_CONF, _PATH_RESCONF); return SR_SUCCESS; } @@ -727,79 +858,29 @@ compute_hash (NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); GChecksum *sum; - GSList *iter; gsize len = HASH_LEN; + guint i; sum = g_checksum_new (G_CHECKSUM_SHA1); g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (global) nm_global_dns_config_update_checksum (global, sum); + else { + for (i = 0; i < priv->configs->len; i++) { + NMDnsIPConfigData *data = priv->configs->pdata[i]; - if (priv->ip4_vpn_config) - nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE); - if (priv->ip4_device_config) - nm_ip4_config_hash (priv->ip4_device_config, sum, TRUE); - - if (priv->ip6_vpn_config) - nm_ip6_config_hash (priv->ip6_vpn_config, sum, TRUE); - if (priv->ip6_device_config) - nm_ip6_config_hash (priv->ip6_device_config, sum, TRUE); - - /* add any other configs we know about */ - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - continue; - - if (NM_IS_IP4_CONFIG (iter->data)) - nm_ip4_config_hash (NM_IP4_CONFIG (iter->data), sum, TRUE); - else if (NM_IS_IP6_CONFIG (iter->data)) - nm_ip6_config_hash (NM_IP6_CONFIG (iter->data), sum, TRUE); + if (NM_IS_IP4_CONFIG (data->config)) + nm_ip4_config_hash ((NMIP4Config *) data->config, sum, TRUE); + else if (NM_IS_IP6_CONFIG (data->config)) + nm_ip6_config_hash ((NMIP6Config *) data->config, sum, TRUE); + } } g_checksum_get_digest (sum, buffer, &len); g_checksum_free (sum); } -static void -build_plugin_config_lists (NMDnsManager *self, - GSList **out_vpn_configs, - GSList **out_dev_configs, - GSList **out_other_configs) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - GSList *iter; - - g_return_if_fail (out_vpn_configs && !*out_vpn_configs); - g_return_if_fail (out_dev_configs && !*out_dev_configs); - g_return_if_fail (out_other_configs && !*out_other_configs); - - /* Build up config lists for plugins; we use the raw configs here, not the - * merged information that we write to resolv.conf so that the plugins can - * still use the domain information in each config to provide split DNS if - * they want to. - */ - if (priv->ip4_vpn_config) - *out_vpn_configs = g_slist_append (*out_vpn_configs, priv->ip4_vpn_config); - if (priv->ip6_vpn_config) - *out_vpn_configs = g_slist_append (*out_vpn_configs, priv->ip6_vpn_config); - if (priv->ip4_device_config) - *out_dev_configs = g_slist_append (*out_dev_configs, priv->ip4_device_config); - if (priv->ip6_device_config) - *out_dev_configs = g_slist_append (*out_dev_configs, priv->ip6_device_config); - - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (!NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - *out_other_configs = g_slist_append (*out_other_configs, iter->data); - } -} - static gboolean merge_global_dns_config (NMResolvConfData *rc, NMGlobalDnsConfig *global_conf) { @@ -839,7 +920,6 @@ update_dns (NMDnsManager *self, { NMDnsManagerPrivate *priv; NMResolvConfData rc; - GSList *iter; const char *nis_domain = NULL; char **searches = NULL; char **options = NULL; @@ -851,13 +931,15 @@ update_dns (NMDnsManager *self, SpawnResult result = SR_ERROR; NMConfigData *data; NMGlobalDnsConfig *global_config; + gs_free NMDnsIPConfigData **plugin_confs = NULL; g_return_val_if_fail (!error || !*error, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); nm_clear_g_source (&priv->plugin_ratelimit.timer); - if (priv->resolv_conf_mode == NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED) { + if (NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE)) { update = FALSE; _LOGD ("update-dns: not updating resolv.conf"); } else { @@ -868,6 +950,11 @@ update_dns (NMDnsManager *self, data = nm_config_get_data (priv->config); global_config = nm_config_data_get_global_dns_config (data); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + /* Update hash with config we're applying */ compute_hash (self, global_config, priv->hash); @@ -880,34 +967,40 @@ update_dns (NMDnsManager *self, if (global_config) merge_global_dns_config (&rc, global_config); else { - if (priv->ip4_vpn_config) - merge_one_ip4_config (&rc, priv->ip4_vpn_config); - if (priv->ip4_device_config) - merge_one_ip4_config (&rc, priv->ip4_device_config); - - if (priv->ip6_vpn_config) - merge_one_ip6_config (&rc, priv->ip6_vpn_config); - if (priv->ip6_device_config) - merge_one_ip6_config (&rc, priv->ip6_device_config); - - for (iter = priv->configs; iter; iter = g_slist_next (iter)) { - if (NM_IN_SET (iter->data, priv->ip4_vpn_config, - priv->ip4_device_config, - priv->ip6_vpn_config, - priv->ip6_device_config)) - continue; + int prio, prev_prio = 0; + NMDnsIPConfigData *current; + gboolean skip = FALSE, v4; + + plugin_confs = g_new (NMDnsIPConfigData *, priv->configs->len + 1); + + for (i = 0; i < priv->configs->len; i++) { + current = priv->configs->pdata[i]; + v4 = NM_IS_IP4_CONFIG (current->config); + + prio = v4 ? + nm_ip4_config_get_dns_priority ((NMIP4Config *) current->config) : + nm_ip6_config_get_dns_priority ((NMIP6Config *) current->config); + + if (prev_prio < 0 && prio != prev_prio) { + skip = TRUE; + plugin_confs[i] = NULL; + } - if (NM_IS_IP4_CONFIG (iter->data)) { - NMIP4Config *config = NM_IP4_CONFIG (iter->data); + prev_prio = prio; - merge_one_ip4_config (&rc, config); - } else if (NM_IS_IP6_CONFIG (iter->data)) { - NMIP6Config *config = NM_IP6_CONFIG (iter->data); + _LOGT ("config: %8d %-7s v%c %-16s %s", + prio, + _config_type_to_string (current->type), + v4 ? '4' : '6', + current->iface, + skip ? "<SKIP>" : ""); - merge_one_ip6_config (&rc, config); - } else - g_assert_not_reached (); + if (!skip) { + merge_one_ip_config_data (self, &rc, current); + plugin_confs[i] = current; + } } + plugin_confs[i] = NULL; } /* If the hostname is a FQDN ("dcbw.example.com"), then add the domain part of it @@ -970,7 +1063,6 @@ update_dns (NMDnsManager *self, if (priv->plugin) { NMDnsPlugin *plugin = priv->plugin; const char *plugin_name = nm_dns_plugin_get_name (plugin); - GSList *vpn_configs = NULL, *dev_configs = NULL, *other_configs = NULL; if (nm_dns_plugin_is_caching (plugin)) { if (no_caching) { @@ -981,14 +1073,9 @@ update_dns (NMDnsManager *self, caching = TRUE; } - if (!global_config) - build_plugin_config_lists (self, &vpn_configs, &dev_configs, &other_configs); - _LOGD ("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update (plugin, - vpn_configs, - dev_configs, - other_configs, + (const NMDnsIPConfigData **) plugin_confs, global_config, priv->hostname)) { _LOGW ("update-dns: plugin %s update failed", plugin_name); @@ -998,9 +1085,6 @@ update_dns (NMDnsManager *self, */ caching = FALSE; } - g_slist_free (vpn_configs); - g_slist_free (dev_configs); - g_slist_free (other_configs); skip: ; @@ -1019,7 +1103,7 @@ update_dns (NMDnsManager *self, if (update) { switch (priv->rc_manager) { - case NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: + case NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: case NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: result = update_resolv_conf (self, searches, nameservers, options, error, priv->rc_manager); resolv_conf_updated = TRUE; @@ -1038,7 +1122,7 @@ update_dns (NMDnsManager *self, if (result == SR_NOTFOUND) { _LOGD ("update-dns: program not available, writing to resolv.conf"); g_clear_error (error); - result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE); + result = update_resolv_conf (self, searches, nameservers, options, error, NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK); resolv_conf_updated = TRUE; } } @@ -1046,7 +1130,7 @@ update_dns (NMDnsManager *self, /* Unless we've already done it, update private resolv.conf in NMRUNDIR ignoring any errors */ if (!resolv_conf_updated) - update_resolv_conf (self, searches, nameservers, options, NULL, _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY); + update_resolv_conf (self, searches, nameservers, options, NULL, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED); /* signal that resolv.conf was changed */ if (update && result == SR_SUCCESS) @@ -1124,166 +1208,148 @@ plugin_child_quit (NMDnsPlugin *plugin, int exit_status, gpointer user_data) plugin_child_quit_update_dns (self); } -gboolean -nm_dns_manager_add_ip4_config (NMDnsManager *self, - const char *iface, - NMIP4Config *config, - NMDnsIPConfigType cfg_type) +static void +ip_config_dns_priority_changed (gpointer config, + GParamSpec *pspec, + NMDnsManager *self) { - NMDnsManagerPrivate *priv; - GError *error = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); - - switch (cfg_type) { - case NM_DNS_IP_CONFIG_TYPE_VPN: - if (priv->ip4_vpn_config && priv->ip4_vpn_config != config) { - priv->configs = g_slist_remove (priv->configs, priv->ip4_vpn_config); - g_object_unref (priv->ip4_vpn_config); - } - priv->ip4_vpn_config = config; - break; - case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: - if (priv->ip4_device_config && priv->ip4_device_config != config) { - priv->configs = g_slist_remove (priv->configs, priv->ip4_device_config); - g_object_unref (priv->ip4_device_config); - } - priv->ip4_device_config = config; - break; - default: - break; - } + NM_DNS_MANAGER_GET_PRIVATE (self)->need_sort = TRUE; +} - /* Don't allow the same zone added twice */ - if (!g_slist_find (priv->configs, config)) - priv->configs = g_slist_append (priv->configs, g_object_ref (config)); +static void +forget_data (NMDnsManager *self, NMDnsIPConfigData *data) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } + if (data == priv->best_conf4) + priv->best_conf4 = NULL; + else if (data == priv->best_conf6) + priv->best_conf6 = NULL; - return TRUE; + g_signal_handlers_disconnect_by_func (data->config, ip_config_dns_priority_changed, self); } -gboolean -nm_dns_manager_remove_ip4_config (NMDnsManager *self, NMIP4Config *config) +static gboolean +nm_dns_manager_add_ip_config (NMDnsManager *self, + const char *iface, + gpointer config, + NMDnsIPConfigType cfg_type) { NMDnsManagerPrivate *priv; GError *error = NULL; + NMDnsIPConfigData *data; + gboolean v4 = NM_IS_IP4_CONFIG (config); + guint i; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); + g_return_val_if_fail (iface && iface[0], FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - /* Can't remove it if it wasn't in the list to begin with */ - if (!g_slist_find (priv->configs, config)) - return FALSE; - - priv->configs = g_slist_remove (priv->configs, config); - - if (config == priv->ip4_vpn_config) - priv->ip4_vpn_config = NULL; - if (config == priv->ip4_device_config) - priv->ip4_device_config = NULL; + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + if (data->config == config) { + if ( nm_streq (data->iface, iface) + && data->type == cfg_type) + return FALSE; + else { + forget_data (self, data); + g_ptr_array_remove_index_fast (priv->configs, i); + break; + } + } + } - g_object_unref (config); + data = ip_config_data_new (config, cfg_type, iface); + g_ptr_array_add (priv->configs, data); + g_signal_connect (config, + v4 ? + "notify::" NM_IP4_CONFIG_DNS_PRIORITY : + "notify::" NM_IP6_CONFIG_DNS_PRIORITY, + (GCallback) ip_config_dns_priority_changed, self); + priv->need_sort = TRUE; + + if (cfg_type == NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE) { + /* Only one best-device per IP version is allowed */ + if (v4) { + if (priv->best_conf4) + priv->best_conf4->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf4 = data; + } else { + if (priv->best_conf6) + priv->best_conf6->type = NM_DNS_IP_CONFIG_TYPE_DEFAULT; + priv->best_conf6 = data; + } + } if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } - g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); - return TRUE; } gboolean +nm_dns_manager_add_ip4_config (NMDnsManager *self, + const char *iface, + NMIP4Config *config, + NMDnsIPConfigType cfg_type) +{ + return nm_dns_manager_add_ip_config (self, iface, config, cfg_type); +} + +gboolean nm_dns_manager_add_ip6_config (NMDnsManager *self, const char *iface, NMIP6Config *config, NMDnsIPConfigType cfg_type) { + return nm_dns_manager_add_ip_config (self, iface, config, cfg_type); +} + +static gboolean +nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config) +{ NMDnsManagerPrivate *priv; GError *error = NULL; + NMDnsIPConfigData *data; + guint i; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + g_return_val_if_fail (config, FALSE); priv = NM_DNS_MANAGER_GET_PRIVATE (self); - g_object_set_data_full (G_OBJECT (config), IP_CONFIG_IFACE_TAG, g_strdup (iface), g_free); + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; - switch (cfg_type) { - case NM_DNS_IP_CONFIG_TYPE_VPN: - if (priv->ip6_vpn_config && priv->ip6_vpn_config != config) { - priv->configs = g_slist_remove (priv->configs, priv->ip6_vpn_config); - g_object_unref (priv->ip6_vpn_config); - } - priv->ip6_vpn_config = config; - break; - case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: - if (priv->ip6_device_config && priv->ip6_device_config != config) { - priv->configs = g_slist_remove (priv->configs, priv->ip6_device_config); - g_object_unref (priv->ip6_device_config); - } - priv->ip6_device_config = config; - break; - default: - break; - } + if (data->config == config) { + forget_data (self, data); + g_ptr_array_remove_index (priv->configs, i); - /* Don't allow the same zone added twice */ - if (!g_slist_find (priv->configs, config)) - priv->configs = g_slist_append (priv->configs, g_object_ref (config)); + if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { + _LOGW ("could not commit DNS changes: %s", error->message); + g_clear_error (&error); + } - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); + return TRUE; + } } + return FALSE; +} - return TRUE; +gboolean +nm_dns_manager_remove_ip4_config (NMDnsManager *self, NMIP4Config *config) +{ + return nm_dns_manager_remove_ip_config (self, config); } gboolean nm_dns_manager_remove_ip6_config (NMDnsManager *self, NMIP6Config *config) { - NMDnsManagerPrivate *priv; - GError *error = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (config != NULL, FALSE); - - priv = NM_DNS_MANAGER_GET_PRIVATE (self); - - /* Can't remove it if it wasn't in the list to begin with */ - if (!g_slist_find (priv->configs, config)) - return FALSE; - - priv->configs = g_slist_remove (priv->configs, config); - - if (config == priv->ip6_vpn_config) - priv->ip6_vpn_config = NULL; - if (config == priv->ip6_device_config) - priv->ip6_device_config = NULL; - - g_object_unref (config); - - if (!priv->updates_queue && !update_dns (self, FALSE, &error)) { - _LOGW ("could not commit DNS changes: %s", error->message); - g_clear_error (&error); - } - - g_object_set_data (G_OBJECT (config), IP_CONFIG_IFACE_TAG, NULL); - - return TRUE; + return nm_dns_manager_remove_ip_config (self, config); } void @@ -1324,10 +1390,21 @@ nm_dns_manager_set_hostname (NMDnsManager *self, } } -NMDnsManagerResolvConfMode -nm_dns_manager_get_resolv_conf_mode (NMDnsManager *self) +gboolean +nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self) { - return NM_DNS_MANAGER_GET_PRIVATE (self)->resolv_conf_mode; + NMDnsManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_DNS_MANAGER (self), FALSE); + + priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if ( NM_IN_SET (priv->rc_manager, NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE) + || priv->plugin) + return FALSE; + + return TRUE; } void @@ -1360,6 +1437,11 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_return_if_fail (priv->updates_queue > 0); + if (priv->need_sort) { + g_ptr_array_sort (priv->configs, ip_config_data_ptr_compare); + priv->need_sort = FALSE; + } + compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), new); changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; _LOGD ("(%s): DNS configuration %s", func, changed ? "changed" : "did not change"); @@ -1382,22 +1464,31 @@ nm_dns_manager_end_updates (NMDnsManager *self, const char *func) /******************************************************************/ +static gboolean +_clear_plugin (NMDnsManager *self) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + + if (priv->plugin) { + g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); + g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); + g_clear_object (&priv->plugin); + return TRUE; + } + return FALSE; +} + static bool -_get_resconf_immutable (int *immutable_cached) +_get_resconf_immutable (void) { int fd, flags; - int immutable; - - immutable = *immutable_cached; - if (!NM_IN_SET (immutable, FALSE, TRUE)) { - immutable = FALSE; - fd = open (_PATH_RESCONF, O_RDONLY); - if (fd != -1) { - if (ioctl (fd, FS_IOC_GETFLAGS, &flags) != -1) - immutable = NM_FLAGS_HAS (flags, FS_IMMUTABLE_FL); - close (fd); - } - *immutable_cached = immutable; + bool immutable = FALSE; + + fd = open (_PATH_RESCONF, O_RDONLY); + if (fd != -1) { + if (ioctl (fd, FS_IOC_GETFLAGS, &flags) != -1) + immutable = NM_FLAGS_HAS (flags, FS_IMMUTABLE_FL); + close (fd); } return immutable; } @@ -1408,96 +1499,80 @@ static void init_resolv_conf_mode (NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *mode, *mode_unknown; - int immutable = -1; + NMDnsManagerResolvConfManager rc_manager; + const char *mode; + gboolean plugin_changed = FALSE; mode = nm_config_data_get_dns_mode (nm_config_get_data (priv->config)); - if ( priv->mode_initialized - && nm_streq0 (mode, priv->last_mode) - && ( nm_streq0 (mode, "none") - || priv->last_immutable == _get_resconf_immutable (&immutable))) { - /* we call init_resolv_conf_mode() on every SIGHUP to possibly reload - * when either "mode" or "immutable" changed. However, we don't want to - * re-create the plugin, when the paramters didn't actually change. So - * detect that we would recreate the same plugin and return early. */ - return; - } - - priv->mode_initialized = TRUE; - g_free (priv->last_mode); - priv->last_mode = g_strdup (mode); - priv->last_immutable = FALSE; - g_clear_object (&priv->plugin); - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED; - - if (nm_streq0 (mode, "none")) { - _LOGI ("%s%s", "set resolv-conf-mode: ", "none"); - return; + if (nm_streq0 (mode, "none")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; + else if (_get_resconf_immutable ()) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE; + else { + const char *man; + + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN; + man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config)); + +again: + if (!man) { + /* nop */ + } else if (NM_IN_STRSET (man, "symlink", "none")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK; + else if (nm_streq (man, "file")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE; + else if (nm_streq (man, "resolvconf")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; + else if (nm_streq (man, "netconfig")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; + else if (nm_streq (man, "unmanaged")) + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED; + + if (rc_manager == NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN) { + if (man) { + _LOGW ("init: unknown resolv.conf manager \"%s\", fallback to \"%s\"", + man, ""NM_CONFIG_DEFAULT_DNS_RC_MANAGER); + } + man = ""NM_CONFIG_DEFAULT_DNS_RC_MANAGER; + rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK; + goto again; + } } - priv->last_immutable = _get_resconf_immutable (&immutable); - - if (NM_IN_STRSET (mode, "dnsmasq", "unbound")) { - if (!immutable) - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_PROXY; - if (nm_streq (mode, "dnsmasq")) + if (nm_streq0 (mode, "dnsmasq")) { + if (!NM_IS_DNS_DNSMASQ (priv->plugin)) { + _clear_plugin (self); priv->plugin = nm_dns_dnsmasq_new (); - else + plugin_changed = TRUE; + } + } else if (nm_streq0 (mode, "unbound")) { + if (!NM_IS_DNS_UNBOUND (priv->plugin)) { + _clear_plugin (self); priv->plugin = nm_dns_unbound_new (); + plugin_changed = TRUE; + } + } else { + if (!NM_IN_STRSET (mode, NULL, "none", "default")) { + _LOGW ("init: unknown dns mode '%s'", mode); + mode = "default"; + } + if (_clear_plugin (self)) + plugin_changed = TRUE; + } + if (plugin_changed && priv->plugin) { g_signal_connect (priv->plugin, NM_DNS_PLUGIN_FAILED, G_CALLBACK (plugin_failed), self); g_signal_connect (priv->plugin, NM_DNS_PLUGIN_CHILD_QUIT, G_CALLBACK (plugin_child_quit), self); - - _NMLOG (immutable ? LOGL_WARN : LOGL_INFO, - "%s%s%s%s%s%s", - "set resolv-conf-mode: ", - immutable ? "none" : mode, - ", plugin=\"", nm_dns_plugin_get_name (priv->plugin), "\"", - immutable ? ", resolv.conf immutable" : ""); - return; } - if (!immutable) - priv->resolv_conf_mode = NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT; - - mode_unknown = mode && !nm_streq (mode, "default") ? mode : NULL; - _NMLOG (mode_unknown ? LOGL_WARN : LOGL_INFO, - "%s%s%s%s%s%s", - "set resolv-conf-mode: ", - immutable ? "none" : "default", - NM_PRINT_FMT_QUOTED (mode_unknown, " -- unknown configuration '", mode_unknown, "'", ""), - immutable ? ", resolv.conf immutable" : ""); -} - -static void -init_resolv_conf_manager (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - const char *man; - - man = nm_config_data_get_rc_manager (nm_config_get_data (priv->config)); - if (!g_strcmp0 (man, "none")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE; - else if (nm_streq0 (man, "file")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE; - else if (!g_strcmp0 (man, "resolvconf")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; - else if (!g_strcmp0 (man, "netconfig")) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; - else { -#if defined(RESOLVCONF_SELECTED) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF; -#elif defined(NETCONFIG_SELECTED) - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG; -#else - priv->rc_manager = NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE; -#endif - if (man) - _LOGW ("unknown resolv.conf manager '%s'", man); + if ( plugin_changed + || priv->rc_manager != rc_manager) { + priv->rc_manager = rc_manager; + _LOGI ("init: dns=%s, rc-manager=%s%s%s%s", + mode, _rc_manager_to_string (rc_manager), + NM_PRINT_FMT_QUOTED (priv->plugin, ", plugin=", nm_dns_plugin_get_name (priv->plugin), "", "")); } - - _LOGI ("using resolv.conf manager '%s'", _rc_manager_to_string (priv->rc_manager)); } static void @@ -1510,6 +1585,7 @@ config_changed_cb (NMConfig *config, GError *error = NULL; if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_DNS_MODE | + NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_SIGHUP)) { /* reload the resolv-conf mode also on SIGHUP (when DNS_MODE didn't change). * The reason is, that the configuration also depends on whether resolv.conf @@ -1518,15 +1594,12 @@ config_changed_cb (NMConfig *config, init_resolv_conf_mode (self); } - if (NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_RC_MANAGER)) - init_resolv_conf_manager (self); - if (NM_FLAGS_ANY (changes, NM_CONFIG_CHANGE_SIGHUP | NM_CONFIG_CHANGE_SIGUSR1 | NM_CONFIG_CHANGE_DNS_MODE | NM_CONFIG_CHANGE_RC_MANAGER | NM_CONFIG_CHANGE_GLOBAL_DNS_CONFIG)) { - if (!update_dns (self, TRUE, &error)) { + if (!update_dns (self, FALSE, &error)) { _LOGW ("could not commit DNS changes: %s", error->message); g_clear_error (&error); } @@ -1536,21 +1609,23 @@ config_changed_cb (NMConfig *config, static void nm_dns_manager_init (NMDnsManager *self) { - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + NMDnsManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DNS_MANAGER, NMDnsManagerPrivate); + + self->priv = priv; _LOGT ("creating..."); priv->config = g_object_ref (nm_config_get ()); + priv->configs = g_ptr_array_new_full (8, ip_config_data_destroy); + /* Set the initial hash */ - compute_hash (self, nm_config_data_get_global_dns_config (nm_config_get_data (priv->config)), - NM_DNS_MANAGER_GET_PRIVATE (self)->hash); + compute_hash (self, NULL, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); g_signal_connect (G_OBJECT (priv->config), NM_CONFIG_SIGNAL_CONFIG_CHANGED, G_CALLBACK (config_changed_cb), self); init_resolv_conf_mode (self); - init_resolv_conf_manager (self); } static void @@ -1558,17 +1633,13 @@ dispose (GObject *object) { NMDnsManager *self = NM_DNS_MANAGER (object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + NMDnsIPConfigData *data; GError *error = NULL; + guint i; _LOGT ("disposing"); - if (priv->plugin) { - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_failed, self); - g_signal_handlers_disconnect_by_func (priv->plugin, plugin_child_quit, self); - g_clear_object (&priv->plugin); - } - - g_clear_pointer (&priv->last_mode, g_free); + _clear_plugin (self); /* If we're quitting, leave a valid resolv.conf in place, not one * pointing to 127.0.0.1 if any plugins were active. Thus update @@ -1586,8 +1657,14 @@ dispose (GObject *object) g_clear_object (&priv->config); } - g_slist_free_full (priv->configs, g_object_unref); - priv->configs = NULL; + if (priv->configs) { + for (i = 0; i < priv->configs->len; i++) { + data = priv->configs->pdata[i]; + forget_data (self, data); + } + g_ptr_array_free (priv->configs, TRUE); + priv->configs = NULL; + } G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); } @@ -1595,7 +1672,8 @@ dispose (GObject *object) static void finalize (GObject *object) { - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); + NMDnsManager *self = NM_DNS_MANAGER (object); + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); g_free (priv->hostname); diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index f1293f7ebb..a82fdfc036 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -28,13 +28,24 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" +G_BEGIN_DECLS + typedef enum { NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE, NM_DNS_IP_CONFIG_TYPE_VPN } NMDnsIPConfigType; -G_BEGIN_DECLS +enum { + NM_DNS_PRIORITY_DEFAULT_NORMAL = 100, + NM_DNS_PRIORITY_DEFAULT_VPN = 50, +}; + +typedef struct { + gpointer config; + NMDnsIPConfigType type; + char *iface; +} NMDnsIPConfigData; #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type ()) #define NM_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_DNS_MANAGER, NMDnsManager)) @@ -45,8 +56,12 @@ G_BEGIN_DECLS #define NM_DNS_MANAGER_CONFIG_CHANGED "config-changed" +struct _NMDnsManagerPrivate; + typedef struct { GObject parent; + /* private */ + struct _NMDnsManagerPrivate *priv; } NMDnsManager; typedef struct { @@ -84,32 +99,17 @@ void nm_dns_manager_set_hostname (NMDnsManager *self, const char *hostname); /** - * NMDnsManagerResolvConfMode: - * @NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED: NM is not managing resolv.conf - * @NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT: NM is managing resolv.conf by - * adding and removing "nameserver" lines corresponding to the currently - * active connections - * @NM_DNS_MANAGER_RESOLV_CONF_PROXY: NM is managing resolv.conf by - * pointing it to some other service (eg, dnsmasq) that knows the - * nameservers corresponding to the currently active connections. - * - * NMDnsManager's behavior toward /etc/resolv.conf. - */ -typedef enum { - NM_DNS_MANAGER_RESOLV_CONF_UNMANAGED, - NM_DNS_MANAGER_RESOLV_CONF_EXPLICIT, - NM_DNS_MANAGER_RESOLV_CONF_PROXY -} NMDnsManagerResolvConfMode; - -/** * NMDnsManagerResolvConfManager - * @_NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY: dummy-manager - * to not write resolv.conf at all, only the internal file in - * NM's run state directory. - * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE: NM writes resolv.conf + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN: unspecified rc-manager. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED: do not touch /etc/resolv.conf + * (but still write the internal copy -- unless it is symlinked by + * /etc/resolv.conf) + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE: similar to "unmanaged", + * but indicates that resolv.conf cannot be modified. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK: NM writes resolv.conf * by symlinking it to the run state directory. - * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like NONE, but instead of symlinking - * resolv.conf, write it as a file. + * @NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE: Like SYMLINK, but instead of + * symlinking /etc/resolv.conf, write it as a file. * @NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF: NM is managing resolv.conf through resolvconf * @NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG: NM is managing resolv.conf @@ -118,14 +118,16 @@ typedef enum { * NMDnsManager's management of resolv.conf */ typedef enum { - _NM_DNS_MANAGER_RESOLV_CONF_MAN_INTERNAL_ONLY, - NM_DNS_MANAGER_RESOLV_CONF_MAN_NONE, + NM_DNS_MANAGER_RESOLV_CONF_MAN_UNKNOWN, + NM_DNS_MANAGER_RESOLV_CONF_MAN_UNMANAGED, + NM_DNS_MANAGER_RESOLV_CONF_MAN_IMMUTABLE, + NM_DNS_MANAGER_RESOLV_CONF_MAN_SYMLINK, NM_DNS_MANAGER_RESOLV_CONF_MAN_FILE, NM_DNS_MANAGER_RESOLV_CONF_MAN_RESOLVCONF, NM_DNS_MANAGER_RESOLV_CONF_MAN_NETCONFIG, } NMDnsManagerResolvConfManager; -NMDnsManagerResolvConfMode nm_dns_manager_get_resolv_conf_mode (NMDnsManager *self); +gboolean nm_dns_manager_get_resolv_conf_explicit (NMDnsManager *self); G_END_DECLS diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index 6ab18faa9c..38eaf060c0 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -74,18 +74,14 @@ static guint signals[LAST_SIGNAL] = { 0 }; gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE); return NM_DNS_PLUGIN_GET_CLASS (self)->update (self, - vpn_configs, - dev_configs, - other_configs, + configs, global_config, hostname); } diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h index 7ecaa424dc..d715582cbe 100644 --- a/src/dns-manager/nm-dns-plugin.h +++ b/src/dns-manager/nm-dns-plugin.h @@ -20,6 +20,7 @@ #define __NETWORKMANAGER_DNS_PLUGIN_H__ #include "nm-default.h" +#include "nm-dns-manager.h" #include "nm-config-data.h" @@ -33,8 +34,6 @@ #define NM_DNS_PLUGIN_FAILED "failed" #define NM_DNS_PLUGIN_CHILD_QUIT "child-quit" -#define IP_CONFIG_IFACE_TAG "dns-manager-iface" - typedef struct { GObject parent; } NMDnsPlugin; @@ -44,18 +43,13 @@ typedef struct { /* Methods */ - /* Called when DNS information is changed. 'vpn_configs' is a list of - * NMIP4Config or NMIP6Config objects from VPN connections, while - * 'dev_configs' is a list of NMPI4Config or NMIP6Config objects from - * active devices. 'other_configs' represent other IP configuration that - * may be in-use. 'global_config' is the optional global DNS - * configuration. Configs of the same IP version are sorted in priority - * order. + /* Called when DNS information is changed. 'configs' is an array + * of pointers to NMDnsIPConfigData sorted by priority. + * 'global_config' is the optional global DNS + * configuration. */ gboolean (*update) (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname); @@ -92,9 +86,7 @@ gboolean nm_dns_plugin_is_caching (NMDnsPlugin *self); const char *nm_dns_plugin_get_name (NMDnsPlugin *self); gboolean nm_dns_plugin_update (NMDnsPlugin *self, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname); diff --git a/src/dns-manager/nm-dns-unbound.c b/src/dns-manager/nm-dns-unbound.c index 4c1af1039f..66a287fdf5 100644 --- a/src/dns-manager/nm-dns-unbound.c +++ b/src/dns-manager/nm-dns-unbound.c @@ -28,9 +28,7 @@ G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN) static gboolean update (NMDnsPlugin *plugin, - const GSList *vpn_configs, - const GSList *dev_configs, - const GSList *other_configs, + const NMDnsIPConfigData **configs, const NMGlobalDnsConfig *global_config, const char *hostname) { diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index 764aba2905..7b72594434 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -65,60 +65,6 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void -nm_dnsmasq_manager_init (NMDnsMasqManager *manager) -{ -} - -static void -finalize (GObject *object) -{ - NMDnsMasqManagerPrivate *priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (object); - - nm_dnsmasq_manager_stop (NM_DNSMASQ_MANAGER (object)); - - g_free (priv->iface); - g_free (priv->pidfile); - - G_OBJECT_CLASS (nm_dnsmasq_manager_parent_class)->finalize (object); -} - -static void -nm_dnsmasq_manager_class_init (NMDnsMasqManagerClass *manager_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - - g_type_class_add_private (manager_class, sizeof (NMDnsMasqManagerPrivate)); - - object_class->finalize = finalize; - - /* signals */ - signals[STATE_CHANGED] = - g_signal_new (NM_DNS_MASQ_MANAGER_STATE_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDnsMasqManagerClass, state_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, - G_TYPE_UINT); -} - -NMDnsMasqManager * -nm_dnsmasq_manager_new (const char *iface) -{ - NMDnsMasqManager *manager; - NMDnsMasqManagerPrivate *priv; - - manager = (NMDnsMasqManager *) g_object_new (NM_TYPE_DNSMASQ_MANAGER, NULL); - - priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager); - priv->iface = g_strdup (iface); - priv->pidfile = g_strdup_printf (RUNSTATEDIR "/nm-dnsmasq-%s.pid", iface); - - return manager; -} - typedef struct { GPtrArray *array; GStringChunk *chunk; @@ -165,36 +111,6 @@ nm_cmd_line_add_string (NMCmdLine *cmd, const char *str) /*******************************************/ static void -dm_exit_code (guint dm_exit_status) -{ - char *msg = "Unknown error"; - - switch (dm_exit_status) { - case 1: - msg = "Configuration problem"; - break; - case 2: - msg = "Network access problem (address in use; permissions; etc)"; - break; - case 3: - msg = "Filesystem problem (missing file/directory; permissions; etc)"; - break; - case 4: - msg = "Memory allocation failure"; - break; - case 5: - msg = "Other problem"; - break; - default: - if (dm_exit_status >= 11) - msg = "Lease-script 'init' process failure"; - break; - } - - _LOGW ("dnsmasq exited with error: %s (%d)", msg, dm_exit_status); -} - -static void dm_watch_cb (GPid pid, gint status, gpointer user_data) { NMDnsMasqManager *manager = NM_DNSMASQ_MANAGER (user_data); @@ -203,8 +119,10 @@ dm_watch_cb (GPid pid, gint status, gpointer user_data) if (WIFEXITED (status)) { err = WEXITSTATUS (status); - if (err != 0) - dm_exit_code (err); + if (err != 0) { + _LOGW ("dnsmasq exited with error: %s", + nm_utils_dnsmasq_status_to_string (err, NULL, 0)); + } } else if (WIFSTOPPED (status)) { _LOGW ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { @@ -415,3 +333,56 @@ nm_dnsmasq_manager_stop (NMDnsMasqManager *manager) unlink (priv->pidfile); } + +NMDnsMasqManager * +nm_dnsmasq_manager_new (const char *iface) +{ + NMDnsMasqManager *manager; + NMDnsMasqManagerPrivate *priv; + + manager = (NMDnsMasqManager *) g_object_new (NM_TYPE_DNSMASQ_MANAGER, NULL); + + priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager); + priv->iface = g_strdup (iface); + priv->pidfile = g_strdup_printf (RUNSTATEDIR "/nm-dnsmasq-%s.pid", iface); + + return manager; +} + +static void +nm_dnsmasq_manager_init (NMDnsMasqManager *manager) +{ +} + +static void +finalize (GObject *object) +{ + NMDnsMasqManagerPrivate *priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (object); + + nm_dnsmasq_manager_stop (NM_DNSMASQ_MANAGER (object)); + + g_free (priv->iface); + g_free (priv->pidfile); + + G_OBJECT_CLASS (nm_dnsmasq_manager_parent_class)->finalize (object); +} + +static void +nm_dnsmasq_manager_class_init (NMDnsMasqManagerClass *manager_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (manager_class); + + g_type_class_add_private (manager_class, sizeof (NMDnsMasqManagerPrivate)); + + object_class->finalize = finalize; + + /* signals */ + signals[STATE_CHANGED] = + g_signal_new (NM_DNS_MASQ_MANAGER_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); +} diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.h b/src/dnsmasq-manager/nm-dnsmasq-manager.h index 47c88e6ea4..cc095d66c8 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.h +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.h @@ -48,9 +48,6 @@ typedef struct { typedef struct { GObjectClass parent; - - /* Signals */ - void (*state_changed) (NMDnsMasqManager *manager, NMDnsMasqStatus status); } NMDnsMasqManagerClass; GType nm_dnsmasq_manager_get_type (void); diff --git a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c index aeec5879a1..cf6dab50bb 100644 --- a/src/dnsmasq-manager/tests/test-dnsmasq-utils.c +++ b/src/dnsmasq-manager/tests/test-dnsmasq-utils.c @@ -24,7 +24,7 @@ #include "nm-dnsmasq-utils.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static void test_address_ranges (void) diff --git a/src/main-utils.c b/src/main-utils.c index 8624280221..b94e8b2199 100644 --- a/src/main-utils.c +++ b/src/main-utils.c @@ -31,7 +31,6 @@ #include <glib/gstdio.h> #include <glib-unix.h> -#include <gmodule.h> #include "main-utils.h" #include "NetworkManagerUtils.h" diff --git a/src/main.c b/src/main.c index 4616155d9a..c4782b609e 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,6 @@ #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> -#include <gmodule.h> #include <string.h> #include <sys/resource.h> @@ -71,81 +70,10 @@ static struct { char *opt_log_level; char *opt_log_domains; char *pidfile; - char *state_file; } global_opt = { .become_daemon = TRUE, }; -static gboolean -parse_state_file (const char *filename, - gboolean *net_enabled, - gboolean *wifi_enabled, - gboolean *wwan_enabled, - GError **error) -{ - GKeyFile *state_file; - GError *tmp_error = NULL; - gboolean wifi, net, wwan; - - g_return_val_if_fail (net_enabled != NULL, FALSE); - g_return_val_if_fail (wifi_enabled != NULL, FALSE); - g_return_val_if_fail (wwan_enabled != NULL, FALSE); - - state_file = g_key_file_new (); - g_key_file_set_list_separator (state_file, ','); - if (!g_key_file_load_from_file (state_file, filename, G_KEY_FILE_KEEP_COMMENTS, &tmp_error)) { - gboolean ret = FALSE; - - /* This is kinda ugly; create the file and directory if it doesn't - * exist yet. We can't rely on distros necessarily creating the - * /var/lib/NetworkManager for us since we have to ensure that - * users upgrading NM get this working too. - */ - if (g_error_matches (tmp_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - char *data; - gsize len = 0; - - g_clear_error (&tmp_error); - - /* Write out the initial state to the state file */ - g_key_file_set_boolean (state_file, "main", "NetworkingEnabled", *net_enabled); - g_key_file_set_boolean (state_file, "main", "WirelessEnabled", *wifi_enabled); - g_key_file_set_boolean (state_file, "main", "WWANEnabled", *wwan_enabled); - - data = g_key_file_to_data (state_file, &len, NULL); - if (data) - ret = g_file_set_contents (filename, data, len, error); - g_free (data); - } else { - /* the error is not "No such file or directory" - propagate the error */ - g_propagate_error (error, tmp_error); - } - - return ret; - } - - /* Reading state bits of NetworkManager; an error leaves the passed-in state - * value unchanged. - */ - net = g_key_file_get_boolean (state_file, "main", "NetworkingEnabled", &tmp_error); - if (tmp_error == NULL) - *net_enabled = net; - g_clear_error (&tmp_error); - - wifi = g_key_file_get_boolean (state_file, "main", "WirelessEnabled", &tmp_error); - if (tmp_error == NULL) - *wifi_enabled = wifi; - g_clear_error (&tmp_error); - - wwan = g_key_file_get_boolean (state_file, "main", "WWANEnabled", &tmp_error); - if (tmp_error == NULL) - *wwan_enabled = wwan; - g_clear_error (&tmp_error); - - g_key_file_free (state_file); - return TRUE; -} - static void _set_g_fatal_warnings (void) { @@ -239,7 +167,6 @@ do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli) "PLATFORM,RFKILL,WIFI" }, { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &global_opt.g_fatal_warnings, N_("Make all warnings fatal"), NULL }, { "pid-file", 'p', 0, G_OPTION_ARG_FILENAME, &global_opt.pidfile, N_("Specify the location of a PID file"), N_(NM_DEFAULT_PID_FILE) }, - { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &global_opt.state_file, N_("State file location"), N_(NM_DEFAULT_SYSTEM_STATE_FILE) }, { "run-from-build-dir", 0, 0, G_OPTION_ARG_NONE, &global_opt.run_from_build_dir, "Run from build directory", NULL }, { "print-config", 0, 0, G_OPTION_ARG_NONE, &global_opt.print_config, N_("Print NetworkManager configuration and exit"), NULL }, {NULL} @@ -255,7 +182,6 @@ do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli) exit (1); global_opt.pidfile = global_opt.pidfile ? global_opt.pidfile : g_strdup (NM_DEFAULT_PID_FILE); - global_opt.state_file = global_opt.state_file ? global_opt.state_file : g_strdup (NM_DEFAULT_SYSTEM_STATE_FILE); } /* @@ -265,7 +191,6 @@ do_early_setup (int *argc, char **argv[], NMConfigCmdLineOptions *config_cli) int main (int argc, char *argv[]) { - gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE; gboolean success = FALSE; NMConfig *config; GError *error = NULL; @@ -406,17 +331,12 @@ main (int argc, char *argv[]) nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); - /* Parse the state file */ - if (!parse_state_file (global_opt.state_file, &net_enabled, &wifi_enabled, &wwan_enabled, &error)) { - nm_log_err (LOGD_CORE, "State file %s parsing failed: %s", - global_opt.state_file, - error->message); - /* Not a hard failure */ - } - g_clear_error (&error); - nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", NULL); + + /* the first access to State causes the file to be read (and possibly print a warning) */ + nm_config_state_get (config); + nm_log_dbg (LOGD_CORE, "WEXT support is %s", #if HAVE_WEXT "enabled" @@ -427,10 +347,7 @@ main (int argc, char *argv[]) nm_auth_manager_setup (nm_config_get_auth_polkit (config)); - nm_manager_setup (global_opt.state_file, - net_enabled, - wifi_enabled, - wwan_enabled); + nm_manager_setup (); if (!nm_bus_manager_get_connection (nm_bus_manager_get ())) { nm_log_warn (LOGD_CORE, "Failed to connect to D-Bus; only private bus is available"); @@ -482,6 +399,8 @@ done: nm_manager_stop (nm_manager_get ()); + nm_config_state_set (config, TRUE, TRUE); + if (global_opt.pidfile && wrote_pidfile) unlink (global_opt.pidfile); diff --git a/src/nm-audit-manager.c b/src/nm-audit-manager.c index 728575f663..7096e81934 100644 --- a/src/nm-audit-manager.c +++ b/src/nm-audit-manager.c @@ -233,10 +233,10 @@ nm_audit_manager_audit_enabled (NMAuditManager *self) void _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line, const char *func, const char *op, NMSettingsConnection *connection, - gboolean result, gpointer subject_context, const char *reason) + gboolean result, const char *args, gpointer subject_context, const char *reason) { gs_unref_ptrarray GPtrArray *fields = NULL; - AuditField uuid_field = { }, name_field = { }; + AuditField uuid_field = { }, name_field = { }, args_field = { }; g_return_if_fail (op); @@ -252,6 +252,11 @@ _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, gui g_ptr_array_add (fields, &name_field); } + if (args) { + _audit_field_init_string (&args_field, "args", args, FALSE, BACKEND_ALL); + g_ptr_array_add (fields, &args_field); + } + _audit_log_helper (self, fields, file, line, func, op, result, subject_context, reason); } diff --git a/src/nm-audit-manager.h b/src/nm-audit-manager.h index ed53be6921..ecf581efed 100644 --- a/src/nm-audit-manager.h +++ b/src/nm-audit-manager.h @@ -67,13 +67,13 @@ GType nm_audit_manager_get_type (void); NMAuditManager *nm_audit_manager_get (void); gboolean nm_audit_manager_audit_enabled (NMAuditManager *self); -#define nm_audit_log_connection_op(op, connection, result, subject_context, reason) \ +#define nm_audit_log_connection_op(op, connection, result, args, subject_context, reason) \ G_STMT_START { \ NMAuditManager *_audit = nm_audit_manager_get (); \ \ if (nm_audit_manager_audit_enabled (_audit)) { \ _nm_audit_manager_log_connection_op (_audit, __FILE__, __LINE__, G_STRFUNC, \ - (op), (connection), (result), (subject_context), \ + (op), (connection), (result), (args), (subject_context), \ (reason)); \ } \ } G_STMT_END @@ -100,7 +100,8 @@ gboolean nm_audit_manager_audit_enabled (NMAuditManager *self); void _nm_audit_manager_log_connection_op (NMAuditManager *self, const char *file, guint line, const char *func, const char *op, NMSettingsConnection *connection, - gboolean result, gpointer subject_context, const char *reason); + gboolean result, const char *args, gpointer subject_context, + const char *reason); void _nm_audit_manager_log_control_op (NMAuditManager *self, const char *file, guint line, const char *func, const char *op, const char *arg, diff --git a/src/nm-auth-subject.c b/src/nm-auth-subject.c index 86b873f0f2..eb496b28cb 100644 --- a/src/nm-auth-subject.c +++ b/src/nm-auth-subject.c @@ -37,10 +37,6 @@ #include "nm-enum-types.h" #include "NetworkManagerUtils.h" -G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) - -#define NM_AUTH_SUBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AUTH_SUBJECT, NMAuthSubjectPrivate)) - enum { PROP_0, PROP_SUBJECT_TYPE, @@ -61,6 +57,30 @@ typedef struct { } unix_process; } NMAuthSubjectPrivate; +struct _NMAuthSubject { + GObject parent; + NMAuthSubjectPrivate _priv; +}; + +struct _NMAuthSubjectClass { + GObjectClass parent; +}; + +G_DEFINE_TYPE (NMAuthSubject, nm_auth_subject, G_TYPE_OBJECT) + +#define NM_AUTH_SUBJECT_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMAuthSubject *_self2 = (_self); \ + \ + nm_assert (NM_IS_AUTH_SUBJECT (_self)); \ + &_self->_priv; \ + }) + /**************************************************************/ #define CHECK_SUBJECT(self, error_value) \ @@ -252,7 +272,7 @@ nm_auth_subject_new_internal (void) static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object); + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE ((NMAuthSubject *) object); switch (prop_id) { case PROP_SUBJECT_TYPE: @@ -276,7 +296,7 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object); + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE ((NMAuthSubject *) object); NMAuthSubjectType subject_type; const char *str; gulong id; @@ -317,8 +337,10 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *p } static void -_clear_private (NMAuthSubjectPrivate *priv) +_clear_private (NMAuthSubject *self) { + NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (self); + priv->subject_type = NM_AUTH_SUBJECT_TYPE_INVALID; priv->unix_process.pid = G_MAXULONG; priv->unix_process.uid = G_MAXULONG; @@ -328,7 +350,7 @@ _clear_private (NMAuthSubjectPrivate *priv) static void nm_auth_subject_init (NMAuthSubject *self) { - _clear_private (NM_AUTH_SUBJECT_GET_PRIVATE (self)); + _clear_private (self); } static void @@ -363,7 +385,7 @@ constructed (GObject *object) /* Is the process already gone? Then fail creation of the auth subject * by clearing the type. */ if (kill (priv->unix_process.pid, 0) != 0) - _clear_private (priv); + _clear_private (self); /* Otherwise, although we didn't detect a start_time, the process is still around. * That could be due to procfs mounted with hidepid. So just accept the request. @@ -378,16 +400,14 @@ constructed (GObject *object) break; } - _clear_private (priv); + _clear_private (self); g_return_if_reached (); } static void finalize (GObject *object) { - NMAuthSubjectPrivate *priv = NM_AUTH_SUBJECT_GET_PRIVATE (object); - - _clear_private (priv); + _clear_private ((NMAuthSubject *) object); G_OBJECT_CLASS (nm_auth_subject_parent_class)->finalize (object); } @@ -397,8 +417,6 @@ nm_auth_subject_class_init (NMAuthSubjectClass *config_class) { GObjectClass *object_class = G_OBJECT_CLASS (config_class); - g_type_class_add_private (config_class, sizeof (NMAuthSubjectPrivate)); - /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; diff --git a/src/nm-auth-subject.h b/src/nm-auth-subject.h index 5f50705810..a0b6d14b2a 100644 --- a/src/nm-auth-subject.h +++ b/src/nm-auth-subject.h @@ -39,13 +39,7 @@ typedef enum { #define NM_AUTH_SUBJECT_UNIX_PROCESS_PID "unix-process-pid" #define NM_AUTH_SUBJECT_UNIX_PROCESS_UID "unix-process-uid" -struct _NMAuthSubject { - GObject parent; -}; - -typedef struct { - GObjectClass parent; -} NMAuthSubjectClass; +typedef struct _NMAuthSubjectClass NMAuthSubjectClass; GType nm_auth_subject_get_type (void); diff --git a/src/nm-config.c b/src/nm-config.c index 003a661f9e..e79bd68902 100644 --- a/src/nm-config.c +++ b/src/nm-config.c @@ -38,12 +38,27 @@ #define DEFAULT_SYSTEM_CONFIG_DIR NMLIBDIR "/conf.d" #define DEFAULT_NO_AUTO_DEFAULT_FILE NMSTATEDIR "/no-auto-default.state" #define DEFAULT_INTERN_CONFIG_FILE NMSTATEDIR "/NetworkManager-intern.conf" +#define DEFAULT_STATE_FILE NMSTATEDIR "/NetworkManager.state" + +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "config" +#define _NMLOG_DOMAIN LOGD_CORE + +#define _NMLOG(level, ...) \ + nm_log (level, _NMLOG_DOMAIN, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)) + +/*****************************************************************************/ struct NMConfigCmdLineOptions { char *config_main_file; char *intern_config_file; char *config_dir; char *system_config_dir; + char *state_file; char *no_auto_default_file; char *plugins; gboolean configure_and_quit; @@ -58,6 +73,10 @@ struct NMConfigCmdLineOptions { }; typedef struct { + NMConfigState p; +} State; + +typedef struct { NMConfigCmdLineOptions cli; NMConfigData *config_data; @@ -81,6 +100,19 @@ typedef struct { gboolean configure_and_quit; char **atomic_section_prefixes; + + /* The state. This is actually a mutable data member and it makes sense: + * The regular config is immutable (NMConfigData) and can old be swapped + * as a whole (via nm_config_set_values() or during reload). Thus, it can + * be changed, but it is still immutable and is swapped atomically as a + * whole. Also, we emit a config-changed signal on that occasion. + * + * For state, there are no events. You can query it and set it. + * It only gets read *once* at startup, and later is cached and only + * written out to disk. Hence, no need for the immutable dance here + * because the state changes only on explicit actions from the daemon + * itself. */ + State *state; } NMConfigPrivate; enum { @@ -406,6 +438,7 @@ _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli) g_clear_pointer (&cli->system_config_dir, g_free); g_clear_pointer (&cli->no_auto_default_file, g_free); g_clear_pointer (&cli->intern_config_file, g_free); + g_clear_pointer (&cli->state_file, g_free); g_clear_pointer (&cli->plugins, g_free); cli->configure_and_quit = FALSE; cli->is_debug = FALSE; @@ -427,6 +460,7 @@ _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmd dst->config_main_file = g_strdup (cli->config_main_file); dst->no_auto_default_file = g_strdup (cli->no_auto_default_file); dst->intern_config_file = g_strdup (cli->intern_config_file); + dst->state_file = g_strdup (cli->state_file); dst->plugins = g_strdup (cli->plugins); dst->configure_and_quit = cli->configure_and_quit; dst->is_debug = cli->is_debug; @@ -466,6 +500,7 @@ nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, { "config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->config_dir, N_("Config directory location"), N_(DEFAULT_CONFIG_DIR) }, { "system-config-dir", 0, 0, G_OPTION_ARG_FILENAME, &cli->system_config_dir, N_("System config directory location"), N_(DEFAULT_SYSTEM_CONFIG_DIR) }, { "intern-config", 0, 0, G_OPTION_ARG_FILENAME, &cli->intern_config_file, N_("Internal config file location"), N_(DEFAULT_INTERN_CONFIG_FILE) }, + { "state-file", 0, 0, G_OPTION_ARG_FILENAME, &cli->state_file, N_("State file location"), N_(DEFAULT_STATE_FILE) }, { "no-auto-default", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME, &cli->no_auto_default_file, N_("State file for no-auto-default devices"), N_(DEFAULT_NO_AUTO_DEFAULT_FILE) }, { "plugins", 0, 0, G_OPTION_ARG_STRING, &cli->plugins, N_("List of plugins separated by ','"), N_(CONFIG_PLUGINS_DEFAULT) }, { "configure-and-quit", 0, 0, G_OPTION_ARG_NONE, &cli->configure_and_quit, N_("Quit after initial configuration"), NULL }, @@ -1644,7 +1679,190 @@ nm_config_set_values (NMConfig *self, g_key_file_unref (keyfile_new); } -/************************************************************************/ +/****************************************************************************** + * State + ******************************************************************************/ + +static const char * +state_get_filename (const NMConfigCmdLineOptions *cli) +{ + /* For an empty filename, we assume the user wants to disable + * state. NMConfig will not try to read it nor write it out. */ + if (!cli->state_file) + return DEFAULT_STATE_FILE; + return cli->state_file[0] ? cli->state_file : NULL; +} + +static State * +state_new (void) +{ + State *state; + + state = g_slice_new0 (State); + state->p.net_enabled = TRUE; + state->p.wifi_enabled = TRUE; + state->p.wwan_enabled = TRUE; + + return state; +} + +static void +state_free (State *state) +{ + if (!state) + return; + g_slice_free (State, state); +} + +static State * +state_new_from_file (const char *filename) +{ + GKeyFile *keyfile; + gs_free_error GError *error = NULL; + State *state; + + state = state_new (); + + if (!filename) + return state; + + keyfile = g_key_file_new (); + g_key_file_set_list_separator (keyfile, ','); + if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error)) { + if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + _LOGD ("state: missing state file \"%s\": %s", filename, error->message); + else + _LOGW ("state: error reading state file \"%s\": %s", filename, error->message); + goto out; + } + + _LOGD ("state: successfully read state file \"%s\"", filename); + + state->p.net_enabled = nm_config_keyfile_get_boolean (keyfile, "main", "NetworkingEnabled", state->p.net_enabled); + state->p.wifi_enabled = nm_config_keyfile_get_boolean (keyfile, "main", "WirelessEnabled", state->p.wifi_enabled); + state->p.wwan_enabled = nm_config_keyfile_get_boolean (keyfile, "main", "WWANEnabled", state->p.wwan_enabled); + +out: + g_key_file_unref (keyfile); + return state; +} + +const NMConfigState * +nm_config_state_get (NMConfig *self) +{ + NMConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_CONFIG (self), NULL); + + priv = NM_CONFIG_GET_PRIVATE (self); + + if (G_UNLIKELY (!priv->state)) { + /* read the state from file lazy on first access. The reason is that + * we want to log a failure to read the file via nm-logging. + * + * So we cannot read the state during construction of NMConfig, + * because at that time nm-logging is not yet configured. + */ + priv->state = state_new_from_file (state_get_filename (&priv->cli)); + } + + return &priv->state->p; +} + +static void +state_write (NMConfig *self) +{ + NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self); + const char *filename; + GString *str; + GError *error = NULL; + + filename = state_get_filename (&priv->cli); + + if (!filename) { + priv->state->p.dirty = FALSE; + return; + } + + str = g_string_sized_new (256); + + /* Let's construct the keyfile data by hand. */ + + g_string_append (str, "[main]\n"); + g_string_append_printf (str, "NetworkingEnabled=%s\n", priv->state->p.net_enabled ? "true" : "false"); + g_string_append_printf (str, "WirelessEnabled=%s\n", priv->state->p.wifi_enabled ? "true" : "false"); + g_string_append_printf (str, "WWANEnabled=%s\n", priv->state->p.wwan_enabled ? "true" : "false"); + + if (!g_file_set_contents (filename, + str->str, str->len, + &error)) { + _LOGD ("state: error writing state file \"%s\": %s", filename, error->message); + g_clear_error (&error); + /* we leave the state dirty. That potentally means, that we try to + * write the file over and over again, although it isn't possible. */ + priv->state->p.dirty = TRUE; + } else + priv->state->p.dirty = FALSE; + + _LOGT ("state: success writing state file \"%s\"", filename); + + g_string_free (str, TRUE); +} + +void +_nm_config_state_set (NMConfig *self, + gboolean allow_persist, + gboolean force_persist, + ...) +{ + NMConfigPrivate *priv; + va_list ap; + NMConfigRunStatePropertyType property_type; + + g_return_if_fail (NM_IS_CONFIG (self)); + + priv = NM_CONFIG_GET_PRIVATE (self); + + va_start (ap, force_persist); + + /* We expect that the NMConfigRunStatePropertyType is an integer type <= sizeof (int). + * Smaller would be fine, since the variadic arguments get promoted to int. + * Larger would be a problem, also, because we want that "0" is a valid sentinel. */ + G_STATIC_ASSERT_EXPR (sizeof (NMConfigRunStatePropertyType) <= sizeof (int)); + + while ((property_type = va_arg (ap, int)) != NM_CONFIG_STATE_PROPERTY_NONE) { + bool *p_bool, v_bool; + + switch (property_type) { + case NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED: + p_bool = &priv->state->p.net_enabled; + break; + case NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED: + p_bool = &priv->state->p.wifi_enabled; + break; + case NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED: + p_bool = &priv->state->p.wwan_enabled; + break; + default: + va_end (ap); + g_return_if_reached (); + } + + v_bool = va_arg (ap, gboolean); + if (*p_bool == v_bool) + continue; + *p_bool = v_bool; + priv->state->p.dirty = TRUE; + } + + va_end (ap); + + if ( allow_persist + && (force_persist || priv->state->p.dirty)) + state_write (self); +} + +/*****************************************************************************/ void nm_config_reload (NMConfig *self, int signal) @@ -1917,6 +2135,8 @@ finalize (GObject *gobject) { NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (gobject); + state_free (priv->state); + g_free (priv->config_dir); g_free (priv->system_config_dir); g_free (priv->no_auto_default_file); diff --git a/src/nm-config.h b/src/nm-config.h index 8bbab2ac6f..82e3a00481 100644 --- a/src/nm-config.h +++ b/src/nm-config.h @@ -83,6 +83,24 @@ G_BEGIN_DECLS typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; +typedef enum { + NM_CONFIG_STATE_PROPERTY_NONE, + + /* 1 set-argument: (gboolean enabled) */ + NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED, + NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED, + NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED, +} NMConfigRunStatePropertyType; + +typedef struct { + bool net_enabled; + bool wifi_enabled; + bool wwan_enabled; + + /* Whether the runstate is modified and not saved to disk. */ + bool dirty; +} NMConfigState; + struct _NMConfig { GObject parent; }; @@ -131,6 +149,15 @@ NMConfig *nm_config_new (const NMConfigCmdLineOptions *cli, char **atomic_sectio NMConfig *nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefixes, GError **error); void nm_config_reload (NMConfig *config, int signal); +const NMConfigState *nm_config_state_get (NMConfig *config); + +void _nm_config_state_set (NMConfig *config, + gboolean allow_persist, + gboolean force_persist, + ...); +#define nm_config_state_set(config, allow_persist, force_persist, ...) \ + _nm_config_state_set (config, allow_persist, force_persist, ##__VA_ARGS__, 0) + gint nm_config_parse_boolean (const char *str, gint default_value); GKeyFile *nm_config_create_keyfile (void); diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c deleted file mode 100644 index e04cab928e..0000000000 --- a/src/nm-connection-provider.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2012 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-connection-provider.h" -#include "nm-utils.h" - -G_DEFINE_INTERFACE (NMConnectionProvider, nm_connection_provider, G_TYPE_OBJECT) - -GSList * -nm_connection_provider_get_best_connections (NMConnectionProvider *self, - guint max_requested, - const char *ctype1, - const char *ctype2, - NMConnectionFilterFunc func, - gpointer func_data) -{ - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); - - if (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_best_connections) - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_best_connections (self, max_requested, ctype1, ctype2, func, func_data); - return NULL; -} - -const GSList * -nm_connection_provider_get_connections (NMConnectionProvider *self) -{ - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); - - if (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connections) - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connections (self); - return NULL; -} - -/** - * nm_connection_provider_add_connection: - * @self: the #NMConnectionProvider - * @connection: the source connection to create a new #NMSettingsConnection from - * @save_to_disk: %TRUE to save the connection to disk immediately, %FALSE to - * not save to disk - * @error: on return, a location to store any errors that may occur - * - * Creates a new #NMSettingsConnection for the given source @connection. - * The plugin owns the returned object and the caller must reference the object - * to continue using it. - * - * Returns: the new #NMSettingsConnection or %NULL - */ -NMConnection * -nm_connection_provider_add_connection (NMConnectionProvider *self, - NMConnection *connection, - gboolean save_to_disk, - GError **error) -{ - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); - - g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection); - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->add_connection (self, connection, save_to_disk, error); -} - -/** - * nm_connection_provider_get_connection_by_uuid: - * @self: the #NMConnectionProvider - * @uuid: the UUID to search for - * - * Returns: the connection with the given @uuid, or %NULL - */ -NMConnection * -nm_connection_provider_get_connection_by_uuid (NMConnectionProvider *self, - const char *uuid) -{ - g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); - g_return_val_if_fail (uuid != NULL, NULL); - g_return_val_if_fail (nm_utils_is_uuid (uuid), NULL); - - g_assert (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connection_by_uuid); - return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connection_by_uuid (self, uuid); -} - -/*****************************************************************************/ - -static void -nm_connection_provider_default_init (NMConnectionProviderInterface *g_iface) -{ - GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); - static gboolean initialized = FALSE; - - if (initialized) - return; - initialized = TRUE; - - /* Signals */ - g_signal_new (NM_CP_SIGNAL_CONNECTION_ADDED, - iface_type, - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - g_signal_new (NM_CP_SIGNAL_CONNECTION_UPDATED, - iface_type, - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); - - g_signal_new (NM_CP_SIGNAL_CONNECTION_REMOVED, - iface_type, - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); -} diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h deleted file mode 100644 index b31af05fbe..0000000000 --- a/src/nm-connection-provider.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details: - * - * Copyright (C) 2012 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_CONNECTION_PROVIDER_H__ -#define __NETWORKMANAGER_CONNECTION_PROVIDER_H__ - -#include <nm-connection.h> - -#include "nm-default.h" - -#define NM_TYPE_CONNECTION_PROVIDER (nm_connection_provider_get_type ()) -#define NM_CONNECTION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION_PROVIDER, NMConnectionProvider)) -#define NM_IS_CONNECTION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION_PROVIDER)) -#define NM_CONNECTION_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_CONNECTION_PROVIDER, NMConnectionProviderInterface)) - -#define NM_CP_SIGNAL_CONNECTION_ADDED "cp-connection-added" -#define NM_CP_SIGNAL_CONNECTION_UPDATED "cp-connection-updated" -#define NM_CP_SIGNAL_CONNECTION_REMOVED "cp-connection-removed" - - -/** - * NMConnectionFilterFunc: - * @provider: The provider requesting the filtering - * @connection: the connection to be filtered - * @func_data: the caller-provided data pointer - * - * Returns: %TRUE to allow the connection, %FALSE to ignore it - */ -typedef gboolean (*NMConnectionFilterFunc) (NMConnectionProvider *provider, - NMConnection *connection, - gpointer func_data); - - -typedef struct { - GTypeInterface g_iface; - - /* Methods */ - GSList * (*get_best_connections) (NMConnectionProvider *self, - guint max_requested, - const char *ctype1, - const char *ctype2, - NMConnectionFilterFunc func, - gpointer func_data); - - const GSList * (*get_connections) (NMConnectionProvider *self); - - NMConnection * (*add_connection) (NMConnectionProvider *self, - NMConnection *connection, - gboolean save_to_disk, - GError **error); - - NMConnection * (*get_connection_by_uuid) (NMConnectionProvider *self, - const char *uuid); -} NMConnectionProviderInterface; - -GType nm_connection_provider_get_type (void); - -/** - * nm_connection_provider_get: - * - * Returns: the global #NMConnectionProvider - */ -NMConnectionProvider *nm_connection_provider_get (void); - -/** - * nm_connection_provider_get_best_connections: - * @self: the #NMConnectionProvider - * @max_requested: if non-zero, the maximum number of connections to return - * @ctype1: an #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) to - * filter connections against - * @ctype2: a second #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) - * to filter connections against - * @func: caller-supplied function for filtering connections - * @func_data: caller-supplied data passed to @func - * - * Returns: a #GSList of #NMConnection objects in sorted order representing the - * "best" or highest-priority connections filtered by @ctype1 and/or @ctype2, - * and/or @func. Caller is responsible for freeing the returned #GSList, but - * the contained values do not need to be unreffed. - */ -GSList *nm_connection_provider_get_best_connections (NMConnectionProvider *self, - guint max_requested, - const char *ctype1, - const char *ctype2, - NMConnectionFilterFunc func, - gpointer func_data); - -/** - * nm_connection_provider_get_connections: - * @self: the #NMConnectionProvider - * - * Returns: a #GSList of #NMConnection objects representing all known - * connections. Returned list is owned by the connection provider and must - * not be freed. - */ -const GSList *nm_connection_provider_get_connections (NMConnectionProvider *self); - -/** - * nm_connection_provider_add_connection: - * @self: the #NMConnectionProvider - * @connection: the connection to be added - * @save_to_disk: whether to store the connection on disk - * @error: returns any error if adding fails - * - * returns: a newly added #NMConnection. - */ -NMConnection *nm_connection_provider_add_connection (NMConnectionProvider *self, - NMConnection *connection, - gboolean save_to_disk, - GError **error); - -NMConnection *nm_connection_provider_get_connection_by_uuid (NMConnectionProvider *self, - const char *uuid); - -#endif /* __NETWORKMANAGER_CONNECTION_PROVIDER_H__ */ diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 1c93ca81ee..276dc1c406 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -199,6 +199,27 @@ nm_ethernet_address_is_valid (gconstpointer addr, gssize len) return TRUE; } +gconstpointer +nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen) +{ + g_return_val_if_fail (src, NULL); + g_return_val_if_fail (dst, NULL); + + switch (family) { + case AF_INET: + g_return_val_if_fail (plen <= 32, NULL); + *((guint32 *) dst) = nm_utils_ip4_address_clear_host_address (*((guint32 *) src), plen); + break; + case AF_INET6: + g_return_val_if_fail (plen <= 128, NULL); + nm_utils_ip6_address_clear_host_address (dst, src, plen); + break; + default: + g_return_val_if_reached (NULL); + } + return dst; +} + /* nm_utils_ip4_address_clear_host_address: * @addr: source ip6 address * @plen: prefix length of network @@ -445,8 +466,7 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) gs_strfreev gchar **tokens = NULL; guint num_tokens; gchar *p; - gchar *endp; - char state = '\0'; + char state = ' '; gint64 ppid = 0; start_time = 0; @@ -457,7 +477,7 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) pid); if (!g_file_get_contents (filename, &contents, &length, NULL)) - goto out; + goto fail; /* start time is the token at index 19 after the '(process name)' entry - since only this * field can contain the ')' character, search backwards for this to avoid malicious @@ -465,10 +485,10 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) */ p = strrchr (contents, ')'); if (p == NULL) - goto out; + goto fail; p += 2; /* skip ') ' */ if (p - contents >= (int) length) - goto out; + goto fail; state = p[0]; @@ -477,23 +497,26 @@ nm_utils_get_start_time_for_pid (pid_t pid, char *out_state, pid_t *out_ppid) num_tokens = g_strv_length (tokens); if (num_tokens < 20) - goto out; + goto fail; - if (out_ppid) + if (out_ppid) { ppid = _nm_utils_ascii_str_to_int64 (tokens[1], 10, 1, G_MAXINT, 0); + if (ppid == 0) + goto fail; + } - errno = 0; - start_time = strtoull (tokens[19], &endp, 10); - if (*endp != '\0' || errno != 0) - start_time = 0; - -out: - if (out_state) - *out_state = state; - if (out_ppid) - *out_ppid = ppid; + start_time = _nm_utils_ascii_str_to_int64 (tokens[19], 10, 1, G_MAXINT64, 0); + if (start_time == 0) + goto fail; + NM_SET_OUT (out_state, state); + NM_SET_OUT (out_ppid, ppid); return start_time; + +fail: + NM_SET_OUT (out_state, ' '); + NM_SET_OUT (out_ppid, 0); + return 0; } /******************************************************************************************/ @@ -1900,6 +1923,33 @@ nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id) return ifname; } +/* nm_utils_new_infiniband_name: + * @name: the output-buffer where the value will be written. Must be + * not %NULL and point to a string buffer of at least IFNAMSIZ bytes. + * @parent_name: the parent interface name + * @p_key: the partition key. + * + * Returns: the infiniband name will be written to @name and @name + * is returned. + */ +const char * +nm_utils_new_infiniband_name (char *name, const char *parent_name, int p_key) +{ + g_return_val_if_fail (name, NULL); + g_return_val_if_fail (parent_name && parent_name[0], NULL); + g_return_val_if_fail (strlen (parent_name) < IFNAMSIZ, NULL); + + /* technically, p_key of 0x0000 and 0x8000 is not allowed either. But we don't + * want to assert against that in nm_utils_new_infiniband_name(). So be more + * resilient here, and accept those. */ + g_return_val_if_fail (p_key >= 0 && p_key <= 0xffff, NULL); + + /* If parent+suffix is too long, kernel would just truncate + * the name. We do the same. See ipoib_vlan_add(). */ + g_snprintf (name, IFNAMSIZ, "%s.%04x", parent_name, p_key); + return name; +} + /** * nm_utils_read_resolv_conf_nameservers(): * @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf @@ -2816,20 +2866,92 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, } return FALSE; } + +/*****************************************************************************/ + +/** + * nm_utils_ipv6_addr_set_interface_identifier: + * @addr: output token encoded as %in6_addr + * @iid: %NMUtilsIPv6IfaceId interface identifier + * + * Converts the %NMUtilsIPv6IfaceId to an %in6_addr (suitable for use + * with Linux platform). This only copies the lower 8 bytes, ignoring + * the /64 network prefix which is expected to be all-zero for a valid + * token. + */ void -nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr, +nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, const NMUtilsIPv6IfaceId iid) { memcpy (addr->s6_addr + 8, &iid.id_u8, 8); } +/** + * nm_utils_ipv6_interface_identifier_get_from_addr: + * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token + * @addr: token encoded as %in6_addr + * + * Converts the %in6_addr encoded token (as used by Linux platform) to + * the interface identifier. + */ void -nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid, +nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, const struct in6_addr *addr) { memcpy (iid, addr->s6_addr + 8, 8); } +/** + * nm_utils_ipv6_interface_identifier_get_from_token: + * @iid: output %NMUtilsIPv6IfaceId interface identifier set from the token + * @token: token encoded as string + * + * Converts the %in6_addr encoded token (as used in ip6 settings) to + * the interface identifier. + * + * Returns: %TRUE if the @token is a valid token, %FALSE otherwise + */ +gboolean +nm_utils_ipv6_interface_identifier_get_from_token (NMUtilsIPv6IfaceId *iid, + const char *token) +{ + struct in6_addr i6_token; + + g_return_val_if_fail (token, FALSE); + + if (!inet_pton (AF_INET6, token, &i6_token)) + return FALSE; + + if (!_nm_utils_inet6_is_token (&i6_token)) + return FALSE; + + nm_utils_ipv6_interface_identifier_get_from_addr (iid, &i6_token); + return TRUE; +} + +/** + * nm_utils_inet6_interface_identifier_to_token: + * @iid: %NMUtilsIPv6IfaceId interface identifier + * @buf: the destination buffer or %NULL + * + * Converts the interface identifier to a string token. + * If the destination buffer it set, set it is used to store the + * resulting token, otherwise an internal static buffer is used. + * The buffer needs to be %NM_UTILS_INET_ADDRSTRLEN characters long. + * + * Returns: a statically allocated array. Do not g_free(). + */ +const char * +nm_utils_inet6_interface_identifier_to_token (NMUtilsIPv6IfaceId iid, char *buf) +{ + struct in6_addr i6_token = { .s6_addr = { 0, } }; + + nm_utils_ipv6_addr_set_interface_identifier (&i6_token, iid); + return nm_utils_inet6_ntop (&i6_token, buf); +} + +/*****************************************************************************/ + static gboolean _set_stable_privacy (struct in6_addr *addr, const char *ifname, @@ -3119,3 +3241,40 @@ nm_utils_lifetime_get (guint32 timestamp, return TRUE; } +const char * +nm_utils_dnsmasq_status_to_string (int status, char *dest, guint size) +{ + static char buffer[128]; + char *msg, *ret; + gs_free char *msg_free = NULL; + int len; + + if (status == 0) + msg = "Success"; + else if (status == 1) + msg = "Configuration problem"; + else if (status == 2) + msg = "Network access problem (address in use, permissions)"; + else if (status == 3) + msg = "Filesystem problem (missing file/directory, permissions)"; + else if (status == 4) + msg = "Memory allocation failure"; + else if (status == 5) + msg = "Other problem"; + else if (status >= 11) + msg = msg_free = g_strdup_printf ("Lease script failed with error %d", status - 10); + else + msg = "Unknown problem"; + + if (dest) { + ret = dest; + len = size; + } else { + ret = buffer; + len = sizeof (buffer); + } + + g_snprintf (ret, len, "%s (%d)", msg, status); + + return ret; +} diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 40ea39eddd..a203a8ef71 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -93,6 +93,7 @@ GETTER (void) \ gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len); +gconstpointer nm_utils_ipx_address_clear_host_address (int family, gpointer dst, gconstpointer src, guint8 plen); in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen); const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen); gboolean nm_utils_ip6_address_same_prefix (const struct in6_addr *addr_a, const struct in6_addr *addr_b, guint8 plen); @@ -283,6 +284,7 @@ const char *nm_utils_get_ip_config_method (NMConnection *connection, GType ip_setting_type); char *nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id); +const char *nm_utils_new_infiniband_name (char *name, const char *parent_name, int p_key); GPtrArray *nm_utils_read_resolv_conf_nameservers (const char *rc_contents); GPtrArray *nm_utils_read_resolv_conf_dns_options (const char *rc_contents); @@ -333,24 +335,30 @@ struct _NMUtilsIPv6IfaceId { #define NM_UTILS_IPV6_IFACE_ID_INIT { { .id = 0 } } +void nm_utils_ipv6_addr_set_interface_identifier (struct in6_addr *addr, + const NMUtilsIPv6IfaceId iid); + +void nm_utils_ipv6_interface_identifier_get_from_addr (NMUtilsIPv6IfaceId *iid, + const struct in6_addr *addr); + +gboolean nm_utils_ipv6_interface_identifier_get_from_token (NMUtilsIPv6IfaceId *iid, + const char *token); + +const char *nm_utils_inet6_interface_identifier_to_token (NMUtilsIPv6IfaceId iid, + char *buf); + gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type, const guint8 *hwaddr, guint len, guint dev_id, NMUtilsIPv6IfaceId *out_iid); -void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr, - const NMUtilsIPv6IfaceId iid); - gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr, const char *ifname, const char *uuid, guint dad_counter, GError **error); -void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid, - const struct in6_addr *addr); - void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len); void nm_utils_setpgid (gpointer unused); @@ -396,4 +404,6 @@ gboolean nm_utils_lifetime_get (guint32 timestamp, gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr); +const char *nm_utils_dnsmasq_status_to_string (int status, char *dest, guint size); + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index 3ee634a7b7..2fd2c7db47 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -200,7 +200,7 @@ _vt_routes_has_entry (const VTableIP *vtable, GArray *routes, const Entry *entry for (i = 0; i < routes->len; i++) { NMPlatformIP4Route *r = &g_array_index (routes, NMPlatformIP4Route, i); - route.rx.source = r->source; + route.rx.rt_source = r->rt_source; if (nm_platform_ip4_route_cmp (r, &route.r4) == 0) return TRUE; } @@ -208,7 +208,7 @@ _vt_routes_has_entry (const VTableIP *vtable, GArray *routes, const Entry *entry for (i = 0; i < routes->len; i++) { NMPlatformIP6Route *r = &g_array_index (routes, NMPlatformIP6Route, i); - route.rx.source = r->source; + route.rx.rt_source = r->rt_source; if (nm_platform_ip6_route_cmp (r, &route.r6) == 0) return TRUE; } @@ -289,7 +289,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g if (vtable->vt->is_ip4) { success = nm_platform_ip4_route_add (priv->platform, entry->route.rx.ifindex, - entry->route.rx.source, + entry->route.rx.rt_source, 0, 0, entry->route.r4.gateway, @@ -299,7 +299,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g } else { success = nm_platform_ip6_route_add (priv->platform, entry->route.rx.ifindex, - entry->route.rx.source, + entry->route.rx.rt_source, in6addr_any, 0, entry->route.r6.gateway, @@ -727,16 +727,8 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, if (device) ip_ifindex = nm_device_get_ip_ifindex (device); - else { - ip_ifindex = nm_vpn_connection_get_ip_ifindex (vpn); - - if (ip_ifindex <= 0) { - NMDevice *parent = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - - if (parent) - ip_ifindex = nm_device_get_ip_ifindex (parent); - } - } + else + ip_ifindex = nm_vpn_connection_get_ip_ifindex (vpn, TRUE); entries = vtable->get_entries (priv); entry = _entry_find_by_source (entries, source, &entry_idx); @@ -773,7 +765,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, * the device. */ memset (&rt, 0, sizeof (rt)); rt.rx.ifindex = ip_ifindex; - rt.rx.source = NM_IP_CONFIG_SOURCE_UNKNOWN; + rt.rx.rt_source = NM_IP_CONFIG_SOURCE_UNKNOWN; rt.rx.metric = G_MAXUINT32; default_route = &rt.rx; @@ -795,7 +787,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, if (vpn_config) { never_default = nm_ip4_config_get_never_default (vpn_config); rt.r4.ifindex = ip_ifindex; - rt.r4.source = NM_IP_CONFIG_SOURCE_VPN; + rt.r4.rt_source = NM_IP_CONFIG_SOURCE_VPN; rt.r4.gateway = nm_ip4_config_get_gateway (vpn_config); rt.r4.metric = nm_vpn_connection_get_ip4_route_metric (vpn); rt.r4.mss = nm_ip4_config_get_mss (vpn_config); @@ -810,7 +802,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, never_default = nm_ip6_config_get_never_default (vpn_config); rt.r6.ifindex = ip_ifindex; - rt.r6.source = NM_IP_CONFIG_SOURCE_VPN; + rt.r6.rt_source = NM_IP_CONFIG_SOURCE_VPN; rt.r6.gateway = int_gw ? *int_gw : in6addr_any; rt.r6.metric = nm_vpn_connection_get_ip6_route_metric (vpn); rt.r6.mss = nm_ip6_config_get_mss (vpn_config); @@ -818,7 +810,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self, } } } - if (nm_vpn_connection_get_ip_ifindex (vpn) > 0) + if (nm_vpn_connection_get_ip_ifindex (vpn, FALSE) > 0) synced = TRUE; else { /* a VPN connection without tunnel device cannot have a non-synced, missing default route. @@ -1149,7 +1141,7 @@ _ipx_get_best_config (const VTableIP *vtable, if (out_ac) *out_ac = NM_ACTIVE_CONNECTION (vpn); if (out_ip_iface) - *out_ip_iface = nm_vpn_connection_get_ip_iface (vpn); + *out_ip_iface = nm_vpn_connection_get_ip_iface (vpn, TRUE); } else { NMDevice *device = entry->source.device; NMActRequest *req; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 20f7729a43..1058e76f4c 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -194,7 +194,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da address.preferred = discovered_address->preferred; if (address.preferred > address.lifetime) address.preferred = address.lifetime; - address.source = NM_IP_CONFIG_SOURCE_RDISC; + address.addr_source = NM_IP_CONFIG_SOURCE_RDISC; address.n_ifa_flags = ifa_flags; nm_ip6_config_add_address (rdisc_config, &address); @@ -219,7 +219,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da route.network = discovered_route->network; route.plen = discovered_route->plen; route.gateway = discovered_route->gateway; - route.source = NM_IP_CONFIG_SOURCE_RDISC; + route.rt_source = NM_IP_CONFIG_SOURCE_RDISC; route.metric = global_opt.priority_v6; nm_ip6_config_add_route (rdisc_config, &route); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 75caf7e33c..929b823622 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -35,11 +35,7 @@ #include "nmdbus-ip4-config.h" -G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT) - -#define NM_IP4_CONFIG_GET_PRIVATE(o) ((o)->priv) - -typedef struct _NMIP4ConfigPrivate { +typedef struct { gboolean never_default; guint32 gateway; gboolean has_gateway; @@ -58,8 +54,33 @@ typedef struct _NMIP4ConfigPrivate { int ifindex; gint64 route_metric; gboolean metered; + gint dns_priority; } NMIP4ConfigPrivate; +struct _NMIP4Config { + NMExportedObject parent; + NMIP4ConfigPrivate _priv; +}; + +struct _NMIP4ConfigClass { + NMExportedObjectClass parent; +}; + +G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT) + +#define NM_IP4_CONFIG_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMIP4Config *_self2 = (_self); \ + \ + nm_assert (NM_IS_IP4_CONFIG (_self)); \ + &_self->_priv; \ + }) + /* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */ G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32)); G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF); @@ -76,6 +97,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config, PROP_SEARCHES, PROP_DNS_OPTIONS, PROP_WINS_SERVERS, + PROP_DNS_PRIORITY, ); NMIP4Config * @@ -207,8 +229,8 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b) return p1 > p2 ? -1 : 1; /* Sort the addresses based on their source. */ - if (a1->source != a2->source) - return a1->source > a2->source ? -1 : 1; + if (a1->addr_source != a2->addr_source) + return a1->addr_source > a2->addr_source ? -1 : 1; if ((a1->label[0] == '\0') != (a2->label[0] == '\0')) return (a1->label[0] == '\0') ? -1 : 1; @@ -335,7 +357,7 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf) gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_full_sync, gint64 default_route_metric) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); int i; gs_unref_ptrarray GPtrArray *added_addresses = NULL; @@ -368,7 +390,7 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gboolean routes_fu nm_assert (addr->plen <= 32); route.ifindex = ifindex; - route.source = NM_IP_CONFIG_SOURCE_KERNEL; + route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL; /* The destination network depends on the peer-address. */ route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen); @@ -427,7 +449,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu { NMIP4ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; - int i; + int i, priority; if (!setting) return; @@ -471,7 +493,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu nm_assert (address.plen <= 32); address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT; address.preferred = NM_PLATFORM_LIFETIME_PERMANENT; - address.source = NM_IP_CONFIG_SOURCE_USER; + address.addr_source = NM_IP_CONFIG_SOURCE_USER; label = nm_ip_address_get_attribute (s_addr, "label"); if (label) @@ -500,7 +522,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu route.metric = default_route_metric; else route.metric = nm_ip_route_get_metric (s_route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_route (config, &route); } @@ -526,6 +548,10 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, gu i++; } + priority = nm_setting_ip_config_get_dns_priority (setting); + if (priority) + nm_ip4_config_set_dns_priority (config, priority); + g_object_thaw_notify (G_OBJECT (config)); } @@ -606,7 +632,7 @@ nm_ip4_config_create_setting (const NMIP4Config *config) continue; /* Ignore routes provided by external sources */ - if (route->source != NM_IP_CONFIG_SOURCE_USER) + if (route->rt_source != nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER)) continue; s_route = nm_ip_route_new_binary (AF_INET, @@ -635,6 +661,11 @@ nm_ip4_config_create_setting (const NMIP4Config *config) nm_setting_ip_config_add_dns_option (s_ip4, option); } + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + nm_ip4_config_get_dns_priority (config), + NULL); + return NM_SETTING (s_ip4); } @@ -643,7 +674,8 @@ nm_ip4_config_create_setting (const NMIP4Config *config) void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFlags merge_flags) { - NMIP4ConfigPrivate *dst_priv, *src_priv; + NMIP4ConfigPrivate *dst_priv; + const NMIP4ConfigPrivate *src_priv; guint32 i; g_return_if_fail (src != NULL); @@ -725,6 +757,10 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl nm_ip4_config_set_metered (dst, nm_ip4_config_get_metered (dst) || nm_ip4_config_get_metered (src)); + /* DNS priority */ + if (nm_ip4_config_get_dns_priority (src)) + nm_ip4_config_set_dns_priority (dst, nm_ip4_config_get_dns_priority (src)); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -733,7 +769,7 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl static int _addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->addresses->len; i++) { @@ -748,7 +784,7 @@ _addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr) static int _nameservers_get_index (const NMIP4Config *self, guint32 ns) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->nameservers->len; i++) { @@ -763,7 +799,7 @@ _nameservers_get_index (const NMIP4Config *self, guint32 ns) static int _routes_get_index (const NMIP4Config *self, const NMPlatformIP4Route *route) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->routes->len; i++) { @@ -779,7 +815,7 @@ _routes_get_index (const NMIP4Config *self, const NMPlatformIP4Route *route) static int _domains_get_index (const NMIP4Config *self, const char *domain) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->domains->len; i++) { @@ -794,7 +830,7 @@ _domains_get_index (const NMIP4Config *self, const char *domain) static int _searches_get_index (const NMIP4Config *self, const char *search) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->searches->len; i++) { @@ -809,7 +845,7 @@ _searches_get_index (const NMIP4Config *self, const char *search) static int _dns_options_get_index (const NMIP4Config *self, const char *option) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->dns_options->len; i++) { @@ -824,7 +860,7 @@ _dns_options_get_index (const NMIP4Config *self, const char *option) static int _nis_servers_get_index (const NMIP4Config *self, guint32 nis_server) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->nis->len; i++) { @@ -839,7 +875,7 @@ _nis_servers_get_index (const NMIP4Config *self, guint32 nis_server) static int _wins_get_index (const NMIP4Config *self, guint32 wins_server) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->wins->len; i++) { @@ -948,6 +984,10 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) nm_ip4_config_del_wins (dst, idx); } + /* DNS priority */ + if (nm_ip4_config_get_dns_priority (src) == nm_ip4_config_get_dns_priority (dst)) + nm_ip4_config_set_dns_priority (dst, 0); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -1022,7 +1062,8 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev #endif gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; guint i, num; - NMIP4ConfigPrivate *dst_priv, *src_priv; + NMIP4ConfigPrivate *dst_priv; + const NMIP4ConfigPrivate *src_priv; const NMPlatformIP4Address *dst_addr, *src_addr; const NMPlatformIP4Route *dst_route, *src_route; @@ -1188,6 +1229,12 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev has_relevant_changes = TRUE; } + /* DNS priority */ + if (src_priv->dns_priority != dst_priv->dns_priority) { + nm_ip4_config_set_dns_priority (dst, src_priv->dns_priority); + has_minor_changes = TRUE; + } + /* mss */ if (src_priv->mss != dst_priv->mss) { nm_ip4_config_set_mss (dst, src_priv->mss); @@ -1311,6 +1358,7 @@ nm_ip4_config_dump (const NMIP4Config *config, const char *detail) for (i = 0; i < nm_ip4_config_get_num_dns_options (config); i++) g_message (" dnsopt: %s", nm_ip4_config_get_dns_option (config, i)); + g_message (" dnspri: %d", nm_ip4_config_get_dns_priority (config)); g_message (" mss: %"G_GUINT32_FORMAT, nm_ip4_config_get_mss (config)); g_message (" mtu: %"G_GUINT32_FORMAT, nm_ip4_config_get_mtu (config)); @@ -1372,7 +1420,7 @@ nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default) gboolean nm_ip4_config_get_never_default (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->never_default; } @@ -1414,7 +1462,7 @@ nm_ip4_config_unset_gateway (NMIP4Config *config) gboolean nm_ip4_config_has_gateway (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->has_gateway; } @@ -1422,7 +1470,7 @@ nm_ip4_config_has_gateway (const NMIP4Config *config) guint32 nm_ip4_config_get_gateway (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->gateway; } @@ -1430,7 +1478,7 @@ nm_ip4_config_get_gateway (const NMIP4Config *config) gint64 nm_ip4_config_get_route_metric (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->route_metric; } @@ -1481,14 +1529,14 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new) *item = *new; /* But restore highest priority source */ - item->source = MAX (item_old.source, new->source); + item->addr_source = MAX (item_old.addr_source, new->addr_source); /* for addresses that we read from the kernel, we keep the timestamps as defined * by the previous source (item_old). The reason is, that the other source configured the lifetimes * with "what should be" and the kernel values are "what turned out after configuring it". * * For other sources, the longer lifetime wins. */ - if ( (new->source == NM_IP_CONFIG_SOURCE_KERNEL && new->source != item_old.source) + if ( (new->addr_source == NM_IP_CONFIG_SOURCE_KERNEL && new->addr_source != item_old.addr_source) || nm_platform_ip_address_cmp_expiry ((const NMPlatformIPAddress *) &item_old, (const NMPlatformIPAddress *) new) > 0) { item->timestamp = item_old.timestamp; item->lifetime = item_old.lifetime; @@ -1521,7 +1569,7 @@ nm_ip4_config_del_address (NMIP4Config *config, guint i) guint nm_ip4_config_get_num_addresses (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->addresses->len; } @@ -1529,7 +1577,7 @@ nm_ip4_config_get_num_addresses (const NMIP4Config *config) const NMPlatformIP4Address * nm_ip4_config_get_address (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return &g_array_index (priv->addresses, NMPlatformIP4Address, i); } @@ -1582,10 +1630,10 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new) if (routes_are_duplicate (item, new, FALSE)) { if (nm_platform_ip4_route_cmp (item, new) == 0) return; - old_source = item->source; + old_source = item->rt_source; memcpy (item, new, sizeof (*item)); /* Restore highest priority source */ - item->source = MAX (old_source, new->source); + item->rt_source = MAX (old_source, new->rt_source); item->ifindex = priv->ifindex; goto NOTIFY; } @@ -1613,7 +1661,7 @@ nm_ip4_config_del_route (NMIP4Config *config, guint i) guint nm_ip4_config_get_num_routes (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->routes->len; } @@ -1621,7 +1669,7 @@ nm_ip4_config_get_num_routes (const NMIP4Config *config) const NMPlatformIP4Route * nm_ip4_config_get_route (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return &g_array_index (priv->routes, NMPlatformIP4Route, i); } @@ -1629,7 +1677,7 @@ nm_ip4_config_get_route (const NMIP4Config *config, guint i) const NMPlatformIP4Route * nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); guint i; NMPlatformIP4Route *best_route = NULL; @@ -1699,7 +1747,7 @@ nm_ip4_config_del_nameserver (NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_nameservers (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->nameservers->len; } @@ -1707,7 +1755,7 @@ nm_ip4_config_get_num_nameservers (const NMIP4Config *config) guint32 nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_array_index (priv->nameservers, guint32, i); } @@ -1756,7 +1804,7 @@ nm_ip4_config_del_domain (NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_domains (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->domains->len; } @@ -1764,7 +1812,7 @@ nm_ip4_config_get_num_domains (const NMIP4Config *config) const char * nm_ip4_config_get_domain (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->domains, i); } @@ -1828,7 +1876,7 @@ nm_ip4_config_del_search (NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_searches (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->searches->len; } @@ -1836,7 +1884,7 @@ nm_ip4_config_get_num_searches (const NMIP4Config *config) const char * nm_ip4_config_get_search (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->searches, i); } @@ -1885,7 +1933,7 @@ nm_ip4_config_del_dns_option(NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_dns_options (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->dns_options->len; } @@ -1893,7 +1941,7 @@ nm_ip4_config_get_num_dns_options (const NMIP4Config *config) const char * nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->dns_options, i); } @@ -1901,6 +1949,27 @@ nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i) /******************************************************************/ void +nm_ip4_config_set_dns_priority (NMIP4Config *config, gint priority) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + if (priority != priv->dns_priority) { + priv->dns_priority = priority; + _notify (config, PROP_DNS_PRIORITY); + } +} + +gint +nm_ip4_config_get_dns_priority (const NMIP4Config *config) +{ + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + + return priv->dns_priority; +} + +/******************************************************************/ + +void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); @@ -1911,7 +1980,7 @@ nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss) guint32 nm_ip4_config_get_mss (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->mss; } @@ -1952,7 +2021,7 @@ nm_ip4_config_del_nis_server (NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_nis_servers (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->nis->len; } @@ -1960,7 +2029,7 @@ nm_ip4_config_get_num_nis_servers (const NMIP4Config *config) guint32 nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_array_index (priv->nis, guint32, i); } @@ -1977,7 +2046,7 @@ nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain) const char * nm_ip4_config_get_nis_domain (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->nis_domain; } @@ -2025,7 +2094,7 @@ nm_ip4_config_del_wins (NMIP4Config *config, guint i) guint32 nm_ip4_config_get_num_wins (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->wins->len; } @@ -2033,7 +2102,7 @@ nm_ip4_config_get_num_wins (const NMIP4Config *config) guint32 nm_ip4_config_get_wins (const NMIP4Config *config, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return g_array_index (priv->wins, guint32, i); } @@ -2055,7 +2124,7 @@ nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu, NMIPConfigSource source guint32 nm_ip4_config_get_mtu (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->mtu; } @@ -2063,7 +2132,7 @@ nm_ip4_config_get_mtu (const NMIP4Config *config) NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->mtu_source; } @@ -2081,7 +2150,7 @@ nm_ip4_config_set_metered (NMIP4Config *config, gboolean metered) gboolean nm_ip4_config_get_metered (const NMIP4Config *config) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); return priv->metered; } @@ -2151,7 +2220,6 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only s = nm_ip4_config_get_dns_option (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } - } /** @@ -2199,10 +2267,7 @@ nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b) static void nm_ip4_config_init (NMIP4Config *config) { - NMIP4ConfigPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (config, NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate); - config->priv = priv; + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config); priv->addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address)); priv->routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route)); @@ -2386,6 +2451,9 @@ get_property (GObject *object, guint prop_id, case PROP_DNS_OPTIONS: nm_utils_g_value_set_strv (value, priv->dns_options); break; + case PROP_DNS_PRIORITY: + g_value_set_int (value, priv->dns_priority); + break; case PROP_WINS_SERVERS: g_value_take_variant (value, g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, @@ -2424,8 +2492,6 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) GObjectClass *object_class = G_OBJECT_CLASS (config_class); NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (config_class); - g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate)); - exported_object_class->export_path = NM_DBUS_PATH "/IP4Config/%u"; object_class->get_property = get_property; @@ -2488,7 +2554,11 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class) G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - + obj_properties[PROP_DNS_PRIORITY] = + g_param_spec_int (NM_IP4_CONFIG_DNS_PRIORITY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); obj_properties[PROP_WINS_SERVERS] = g_param_spec_variant (NM_IP4_CONFIG_WINS_SERVERS, "", "", G_VARIANT_TYPE ("au"), diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index b1a5768740..f302630a0c 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -31,18 +31,7 @@ #define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP4_CONFIG)) #define NM_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) -struct _NMIP4ConfigPrivate; - -struct _NMIP4Config { - NMExportedObject parent; - - /* private */ - struct _NMIP4ConfigPrivate *priv; -}; - -typedef struct { - NMExportedObjectClass parent; -} NMIP4ConfigClass; +typedef struct _NMIP4ConfigClass NMIP4ConfigClass; /* internal */ #define NM_IP4_CONFIG_IFINDEX "ifindex" @@ -55,6 +44,7 @@ typedef struct { #define NM_IP4_CONFIG_DOMAINS "domains" #define NM_IP4_CONFIG_SEARCHES "searches" #define NM_IP4_CONFIG_DNS_OPTIONS "dns-options" +#define NM_IP4_CONFIG_DNS_PRIORITY "dns-priority" #define NM_IP4_CONFIG_WINS_SERVERS "wins-servers" /* deprecated */ @@ -137,6 +127,10 @@ void nm_ip4_config_del_dns_option (NMIP4Config *config, guint i); guint32 nm_ip4_config_get_num_dns_options (const NMIP4Config *config); const char * nm_ip4_config_get_dns_option (const NMIP4Config *config, guint i); +/* DNS priority */ +void nm_ip4_config_set_dns_priority (NMIP4Config *config, gint priority); +gint nm_ip4_config_get_dns_priority (const NMIP4Config *config); + /* MSS */ void nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss); guint32 nm_ip4_config_get_mss (const NMIP4Config *config); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 8e7bd22cc1..89975f8207 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -28,17 +28,14 @@ #include "nm-utils.h" #include "nm-platform.h" +#include "nm-platform-utils.h" #include "nm-route-manager.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nmdbus-ip6-config.h" -G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_EXPORTED_OBJECT) - -#define NM_IP6_CONFIG_GET_PRIVATE(o) ((o)->priv) - -typedef struct _NMIP6ConfigPrivate { +typedef struct { gboolean never_default; struct in6_addr gateway; GArray *addresses; @@ -50,8 +47,32 @@ typedef struct _NMIP6ConfigPrivate { guint32 mss; int ifindex; gint64 route_metric; + gint dns_priority; } NMIP6ConfigPrivate; +struct _NMIP6Config { + NMExportedObject parent; + NMIP6ConfigPrivate _priv; +}; + +struct _NMIP6ConfigClass { + NMExportedObjectClass parent; +}; + +G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_EXPORTED_OBJECT) + +#define NM_IP6_CONFIG_GET_PRIVATE(self) \ + ({ \ + /* preserve the const-ness of self. Unfortunately, that + * way, @self cannot be a void pointer */ \ + typeof (self) _self = (self); \ + \ + /* Get compiler error if variable is of wrong type */ \ + _nm_unused const NMIP6Config *_self2 = (_self); \ + \ + nm_assert (NM_IS_IP6_CONFIG (_self)); \ + &_self->_priv; \ + }) NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config, PROP_IFINDEX, @@ -64,6 +85,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config, PROP_DOMAINS, PROP_SEARCHES, PROP_DNS_OPTIONS, + PROP_DNS_PRIORITY, ); NMIP6Config * @@ -240,8 +262,8 @@ _addresses_sort_cmp (gconstpointer a, gconstpointer b, gpointer user_data) } /* Sort the addresses based on their source. */ - if (a1->source != a2->source) - return a1->source > a2->source ? -1 : 1; + if (a1->addr_source != a2->addr_source) + return a1->addr_source > a2->addr_source ? -1 : 1; /* sort permanent addresses before non-permanent. */ perm1 = (a1->n_ifa_flags & IFA_F_PERMANENT); @@ -372,7 +394,7 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co gboolean nm_ip6_config_commit (const NMIP6Config *config, int ifindex, gboolean routes_full_sync) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); int i; gboolean success; @@ -414,7 +436,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu NMIP6ConfigPrivate *priv; guint naddresses, nroutes, nnameservers, nsearches; const char *gateway_str; - int i; + int i, priority; if (!setting) return; @@ -457,7 +479,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu nm_assert (address.plen <= 128); address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT; address.preferred = NM_PLATFORM_LIFETIME_PERMANENT; - address.source = NM_IP_CONFIG_SOURCE_USER; + address.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_address (config, &address); } @@ -482,7 +504,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu route.metric = default_route_metric; else route.metric = nm_ip_route_get_metric (s_route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_route (config, &route); } @@ -508,6 +530,10 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu i++; } + priority = nm_setting_ip_config_get_dns_priority (setting); + if (priority) + nm_ip6_config_set_dns_priority (config, priority); + g_object_thaw_notify (G_OBJECT (config)); } @@ -596,7 +622,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config) continue; /* Ignore routes provided by external sources */ - if (route->source != NM_IP_CONFIG_SOURCE_USER) + if (route->rt_source != nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER)) continue; s_route = nm_ip_route_new_binary (AF_INET6, @@ -624,6 +650,10 @@ nm_ip6_config_create_setting (const NMIP6Config *config) nm_setting_ip_config_add_dns_option (s_ip6, option); } + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + nm_ip6_config_get_dns_priority (config), + NULL); return NM_SETTING (s_ip6); } @@ -633,7 +663,8 @@ nm_ip6_config_create_setting (const NMIP6Config *config) void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFlags merge_flags) { - NMIP6ConfigPrivate *dst_priv, *src_priv; + NMIP6ConfigPrivate *dst_priv; + const NMIP6ConfigPrivate *src_priv; guint32 i; g_return_if_fail (src != NULL); @@ -690,6 +721,10 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl if (nm_ip6_config_get_mss (src)) nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src)); + /* DNS priority */ + if (nm_ip6_config_get_dns_priority (src)) + nm_ip6_config_set_dns_priority (dst, nm_ip6_config_get_dns_priority (src)); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -719,7 +754,7 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6 static int _addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->addresses->len; i++) { @@ -734,7 +769,7 @@ _addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr) static int _nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->nameservers->len; i++) { @@ -749,7 +784,7 @@ _nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns) static int _routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->routes->len; i++) { @@ -764,7 +799,7 @@ _routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route) static int _domains_get_index (const NMIP6Config *self, const char *domain) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->domains->len; i++) { @@ -779,7 +814,7 @@ _domains_get_index (const NMIP6Config *self, const char *domain) static int _searches_get_index (const NMIP6Config *self, const char *search) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->searches->len; i++) { @@ -794,7 +829,7 @@ _searches_get_index (const NMIP6Config *self, const char *search) static int _dns_options_get_index (const NMIP6Config *self, const char *option) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); guint i; for (i = 0; i < priv->dns_options->len; i++) { @@ -883,6 +918,10 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst)) nm_ip6_config_set_mss (dst, 0); + /* DNS priority */ + if (nm_ip6_config_get_dns_priority (src) == nm_ip6_config_get_dns_priority (dst)) + nm_ip6_config_set_dns_priority (dst, 0); + g_object_thaw_notify (G_OBJECT (dst)); } @@ -958,7 +997,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev #endif gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal; guint i, num; - NMIP6ConfigPrivate *dst_priv, *src_priv; + NMIP6ConfigPrivate *dst_priv; + const NMIP6ConfigPrivate *src_priv; const NMPlatformIP6Address *dst_addr, *src_addr; const NMPlatformIP6Route *dst_route, *src_route; @@ -1129,6 +1169,12 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev has_minor_changes = TRUE; } + /* DNS priority */ + if (src_priv->dns_priority != dst_priv->dns_priority) { + nm_ip6_config_set_dns_priority (dst, src_priv->dns_priority); + has_minor_changes = TRUE; + } + #if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ @@ -1189,6 +1235,8 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail) for (i = 0; i < nm_ip6_config_get_num_dns_options (config); i++) g_message (" dnsopt: %s", nm_ip6_config_get_dns_option (config, i)); + g_message (" dnspri: %d", nm_ip6_config_get_dns_priority (config)); + g_message (" mss: %"G_GUINT32_FORMAT, nm_ip6_config_get_mss (config)); g_message (" n-dflt: %d", nm_ip6_config_get_never_default (config)); } @@ -1206,7 +1254,7 @@ nm_ip6_config_set_never_default (NMIP6Config *config, gboolean never_default) gboolean nm_ip6_config_get_never_default (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->never_default; } @@ -1231,7 +1279,7 @@ nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway) const struct in6_addr * nm_ip6_config_get_gateway (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return IN6_IS_ADDR_UNSPECIFIED (&priv->gateway) ? NULL : &priv->gateway; } @@ -1239,7 +1287,7 @@ nm_ip6_config_get_gateway (const NMIP6Config *config) gint64 nm_ip6_config_get_route_metric (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->route_metric; } @@ -1290,14 +1338,14 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new) *item = *new; /* But restore highest priority source */ - item->source = MAX (item_old.source, new->source); + item->addr_source = MAX (item_old.addr_source, new->addr_source); /* for addresses that we read from the kernel, we keep the timestamps as defined * by the previous source (item_old). The reason is, that the other source configured the lifetimes * with "what should be" and the kernel values are "what turned out after configuring it". * * For other sources, the longer lifetime wins. */ - if ( (new->source == NM_IP_CONFIG_SOURCE_KERNEL && new->source != item_old.source) + if ( (new->addr_source == NM_IP_CONFIG_SOURCE_KERNEL && new->addr_source != item_old.addr_source) || nm_platform_ip_address_cmp_expiry ((const NMPlatformIPAddress *) &item_old, (const NMPlatformIPAddress *) new) > 0) { item->timestamp = item_old.timestamp; item->lifetime = item_old.lifetime; @@ -1330,7 +1378,7 @@ nm_ip6_config_del_address (NMIP6Config *config, guint i) guint nm_ip6_config_get_num_addresses (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->addresses->len; } @@ -1338,7 +1386,7 @@ nm_ip6_config_get_num_addresses (const NMIP6Config *config) const NMPlatformIP6Address * nm_ip6_config_get_address (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return &g_array_index (priv->addresses, NMPlatformIP6Address, i); } @@ -1353,7 +1401,7 @@ nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address * nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolean linklocal) { - NMIP6ConfigPrivate *priv; + const NMIP6ConfigPrivate *priv; guint i; g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); @@ -1373,6 +1421,47 @@ nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolea return NULL; } +/** + * nm_ip6_config_has_dad_pending_addresses + * @self: configuration containing the addresses to check + * @candidates: configuration with the list of addresses we are + * interested in + * + * Check whether there are addresses with DAD pending in @self, that + * are also contained in @candidates. + * + * Returns: %TRUE if at least one matching address was found, %FALSE + * otherwise + */ +gboolean +nm_ip6_config_has_any_dad_pending (const NMIP6Config *self, + const NMIP6Config *candidates) +{ + const NMPlatformIP6Address *addr, *addr_c; + guint i, j, num, num_c; + + num = nm_ip6_config_get_num_addresses (self); + + for (i = 0; i < num; i++) { + addr = nm_ip6_config_get_address (self, i); + if ( NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_TENTATIVE) + && !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_DADFAILED) + && !NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_OPTIMISTIC)) { + + num_c = nm_ip6_config_get_num_addresses (candidates); + + for (j = 0; j < num_c; j++) { + addr_c = nm_ip6_config_get_address (candidates, j); + if ( addresses_are_duplicate (addr, addr_c) + && addr->plen == addr_c->plen) + return TRUE; + } + } + } + + return FALSE; +} + /******************************************************************/ void @@ -1414,10 +1503,10 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) if (routes_are_duplicate (item, new, FALSE)) { if (nm_platform_ip6_route_cmp (item, new) == 0) return; - old_source = item->source; + old_source = item->rt_source; *item = *new; /* Restore highest priority source */ - item->source = MAX (old_source, new->source); + item->rt_source = MAX (old_source, new->rt_source); item->ifindex = priv->ifindex; goto NOTIFY; } @@ -1445,7 +1534,7 @@ nm_ip6_config_del_route (NMIP6Config *config, guint i) guint nm_ip6_config_get_num_routes (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->routes->len; } @@ -1453,7 +1542,7 @@ nm_ip6_config_get_num_routes (const NMIP6Config *config) const NMPlatformIP6Route * nm_ip6_config_get_route (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return &g_array_index (priv->routes, NMPlatformIP6Route, i); } @@ -1461,7 +1550,7 @@ nm_ip6_config_get_route (const NMIP6Config *config, guint i) const NMPlatformIP6Route * nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); guint i; NMPlatformIP6Route *best_route = NULL; @@ -1492,7 +1581,7 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct const NMPlatformIP6Address * nm_ip6_config_get_subnet_for_host (const NMIP6Config *config, const struct in6_addr *host) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); guint i; NMPlatformIP6Address *subnet = NULL; struct in6_addr subnet2, host2; @@ -1559,7 +1648,7 @@ nm_ip6_config_del_nameserver (NMIP6Config *config, guint i) guint32 nm_ip6_config_get_num_nameservers (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->nameservers->len; } @@ -1567,7 +1656,7 @@ nm_ip6_config_get_num_nameservers (const NMIP6Config *config) const struct in6_addr * nm_ip6_config_get_nameserver (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return &g_array_index (priv->nameservers, struct in6_addr, i); } @@ -1616,7 +1705,7 @@ nm_ip6_config_del_domain (NMIP6Config *config, guint i) guint32 nm_ip6_config_get_num_domains (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->domains->len; } @@ -1624,7 +1713,7 @@ nm_ip6_config_get_num_domains (const NMIP6Config *config) const char * nm_ip6_config_get_domain (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->domains, i); } @@ -1688,7 +1777,7 @@ nm_ip6_config_del_search (NMIP6Config *config, guint i) guint32 nm_ip6_config_get_num_searches (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->searches->len; } @@ -1696,7 +1785,7 @@ nm_ip6_config_get_num_searches (const NMIP6Config *config) const char * nm_ip6_config_get_search (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->searches, i); } @@ -1745,7 +1834,7 @@ nm_ip6_config_del_dns_option (NMIP6Config *config, guint i) guint32 nm_ip6_config_get_num_dns_options (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->dns_options->len; } @@ -1753,7 +1842,7 @@ nm_ip6_config_get_num_dns_options (const NMIP6Config *config) const char * nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return g_ptr_array_index (priv->dns_options, i); } @@ -1761,6 +1850,27 @@ nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i) /******************************************************************/ void +nm_ip6_config_set_dns_priority (NMIP6Config *config, gint priority) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + if (priority != priv->dns_priority) { + priv->dns_priority = priority; + _notify (config, PROP_DNS_PRIORITY); + } +} + +gint +nm_ip6_config_get_dns_priority (const NMIP6Config *config) +{ + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + + return priv->dns_priority; +} + +/******************************************************************/ + +void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); @@ -1771,7 +1881,7 @@ nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss) guint32 nm_ip6_config_get_mss (const NMIP6Config *config) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); return priv->mss; } @@ -1839,7 +1949,6 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only s = nm_ip6_config_get_dns_option (config, i); g_checksum_update (sum, (const guint8 *) s, strlen (s)); } - } /** @@ -1887,10 +1996,7 @@ nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b) static void nm_ip6_config_init (NMIP6Config *config) { - NMIP6ConfigPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (config, NM_TYPE_IP6_CONFIG, NMIP6ConfigPrivate); - config->priv = priv; + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); priv->addresses = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Address)); priv->routes = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Route)); @@ -2079,6 +2185,9 @@ get_property (GObject *object, guint prop_id, case PROP_DNS_OPTIONS: nm_utils_g_value_set_strv (value, priv->dns_options); break; + case PROP_DNS_PRIORITY: + g_value_set_int (value, priv->dns_priority); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2110,8 +2219,6 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class) GObjectClass *object_class = G_OBJECT_CLASS (config_class); NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (config_class); - g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate)); - exported_object_class->export_path = NM_DBUS_PATH "/IP6Config/%u"; /* virtual methods */ @@ -2176,6 +2283,11 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class) G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DNS_PRIORITY] = + g_param_spec_int (NM_IP6_CONFIG_DNS_PRIORITY, "", "", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 5e66d500e4..c3f8d9f879 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -33,18 +33,7 @@ #define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP6_CONFIG)) #define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) -struct _NMIP6ConfigPrivate; - -struct _NMIP6Config { - NMExportedObject parent; - - /* private */ - struct _NMIP6ConfigPrivate *priv; -}; - -typedef struct { - NMExportedObjectClass parent; -} NMIP6ConfigClass; +typedef struct _NMIP6ConfigClass NMIP6ConfigClass; /* internal */ #define NM_IP6_CONFIG_IFINDEX "ifindex" @@ -57,6 +46,7 @@ typedef struct { #define NM_IP6_CONFIG_DOMAINS "domains" #define NM_IP6_CONFIG_SEARCHES "searches" #define NM_IP6_CONFIG_DNS_OPTIONS "dns-options" +#define NM_IP6_CONFIG_DNS_PRIORITY "dns-priority" /* deprecated */ #define NM_IP6_CONFIG_ADDRESSES "addresses" @@ -100,6 +90,8 @@ const NMPlatformIP6Address *nm_ip6_config_get_address (const NMIP6Config *config const NMPlatformIP6Address *nm_ip6_config_get_address_first_nontentative (const NMIP6Config *config, gboolean linklocal); gboolean nm_ip6_config_address_exists (const NMIP6Config *config, const NMPlatformIP6Address *address); gboolean nm_ip6_config_addresses_sort (NMIP6Config *config, NMSettingIP6ConfigPrivacy use_temporary); +gboolean nm_ip6_config_has_any_dad_pending (const NMIP6Config *self, + const NMIP6Config *candidates); /* Routes */ void nm_ip6_config_reset_routes (NMIP6Config *config); @@ -139,6 +131,10 @@ void nm_ip6_config_del_dns_option (NMIP6Config *config, guint i); guint32 nm_ip6_config_get_num_dns_options (const NMIP6Config *config); const char * nm_ip6_config_get_dns_option (const NMIP6Config *config, guint i); +/* DNS priority */ +void nm_ip6_config_set_dns_priority (NMIP6Config *config, gint priority); +gint nm_ip6_config_get_dns_priority (const NMIP6Config *config); + /* MSS */ void nm_ip6_config_set_mss (NMIP6Config *config, guint32 mss); guint32 nm_ip6_config_get_mss (const NMIP6Config *config); diff --git a/src/nm-logging.c b/src/nm-logging.c index 935b34a8e3..4d9b3fbd45 100644 --- a/src/nm-logging.c +++ b/src/nm-logging.c @@ -93,16 +93,31 @@ typedef struct { typedef struct { const char *name; const char *level_str; + + /* nm-logging uses syslog internally. Note that the three most-verbose syslog levels + * are LOG_DEBUG, LOG_INFO and LOG_NOTICE. Journal already highlights LOG_NOTICE + * as special. + * + * On the other hand, we have three levels LOGL_TRACE, LOGL_DEBUG and LOGL_INFO, + * which are regular messages not to be highlighted. For that reason, we must map + * LOGL_TRACE and LOGL_DEBUG both to syslog level LOG_DEBUG. */ int syslog_level; + GLogLevelFlags g_log_level; LogFormatFlags log_format_level; } LogLevelDesc; +NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = { + /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */ + [LOGL_INFO] = LOGD_DEFAULT, + [LOGL_WARN] = LOGD_DEFAULT, + [LOGL_ERR] = LOGD_DEFAULT, +}; + static struct { NMLogLevel log_level; - NMLogDomain logging[_LOGL_N_REAL]; - gboolean logging_set_up; LogFormatFlags log_format_flags; + bool uses_syslog:1; enum { LOG_BACKEND_GLIB, LOG_BACKEND_SYSLOG, @@ -111,17 +126,18 @@ static struct { char *logging_domains_to_string; const LogLevelDesc level_desc[_LOGL_N]; -#define _DOMAIN_DESC_LEN 37 +#define _DOMAIN_DESC_LEN 38 /* Would be nice to use C99 flexible array member here, * but that feature doesn't seem well supported. */ const LogDesc domain_desc[_DOMAIN_DESC_LEN]; } global = { + /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */ .log_level = LOGL_INFO, .log_backend = LOG_BACKEND_GLIB, .log_format_flags = _LOG_FORMAT_FLAG_DEFAULT, .level_desc = { [LOGL_TRACE] = { "TRACE", "<trace>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, _LOG_FORMAT_FLAG_LEVEL_DEBUG }, - [LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_INFO, G_LOG_LEVEL_DEBUG, _LOG_FORMAT_FLAG_LEVEL_DEBUG }, + [LOGL_DEBUG] = { "DEBUG", "<debug>", LOG_DEBUG, G_LOG_LEVEL_DEBUG, _LOG_FORMAT_FLAG_LEVEL_DEBUG }, [LOGL_INFO] = { "INFO", "<info>", LOG_INFO, G_LOG_LEVEL_INFO, _LOG_FORMAT_FLAG_LEVEL_INFO }, [LOGL_WARN] = { "WARN", "<warn>", LOG_WARNING, G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_INFO }, [LOGL_ERR] = { "ERR", "<error>", LOG_ERR, G_LOG_LEVEL_MESSAGE, _LOG_FORMAT_FLAG_LEVEL_ERROR }, @@ -165,6 +181,7 @@ static struct { { LOGD_DISPATCH, "DISPATCH" }, { LOGD_AUDIT, "AUDIT" }, { LOGD_SYSTEMD, "SYSTEMD" }, + { LOGD_VPN_PLUGIN,"VPN_PLUGIN" }, { 0, NULL } /* keep _DOMAIN_DESC_LEN in sync */ }, @@ -185,19 +202,6 @@ static char *_domains_to_string (gboolean include_level_override); /************************************************************************/ -static void -_ensure_initialized (void) -{ - if (G_UNLIKELY (!global.logging_set_up)) { - int errsv = errno; - - nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); - - /* must ensure that errno is not modified. */ - errno = errsv; - } -} - static gboolean match_log_level (const char *level, NMLogLevel *out_level, @@ -224,7 +228,7 @@ nm_logging_setup (const char *level, GError **error) { GString *unrecognized = NULL; - NMLogDomain new_logging[G_N_ELEMENTS (global.logging)]; + NMLogDomain new_logging[G_N_ELEMENTS (_nm_logging_enabled_state)]; NMLogLevel new_log_level = global.log_level; char **tmp, **iter; int i; @@ -235,13 +239,8 @@ nm_logging_setup (const char *level, g_return_val_if_fail (!error || !*error, FALSE); /* domains */ - if (!domains || !*domains) { - domains = global.logging_set_up - ? (domains_free = _domains_to_string (FALSE)) - : LOGD_DEFAULT_STRING; - } - - global.logging_set_up = TRUE; + if (!domains || !*domains) + domains = (domains_free = _domains_to_string (FALSE)); for (i = 0; i < G_N_ELEMENTS (new_logging); i++) new_logging[i] = 0; @@ -253,7 +252,7 @@ nm_logging_setup (const char *level, if (new_log_level == _LOGL_KEEP) { new_log_level = global.log_level; for (i = 0; i < G_N_ELEMENTS (new_logging); i++) - new_logging[i] = global.logging[i]; + new_logging[i] = _nm_logging_enabled_state[i]; } } @@ -321,7 +320,7 @@ nm_logging_setup (const char *level, if (domain_log_level == _LOGL_KEEP) { for (i = 0; i < G_N_ELEMENTS (new_logging); i++) - new_logging[i] = (new_logging[i] & ~bits) | (global.logging[i] & bits); + new_logging[i] = (new_logging[i] & ~bits) | (_nm_logging_enabled_state[i] & bits); } else { for (i = 0; i < G_N_ELEMENTS (new_logging); i++) { if (i < domain_log_level) @@ -339,7 +338,7 @@ nm_logging_setup (const char *level, global.log_level = new_log_level; for (i = 0; i < G_N_ELEMENTS (new_logging); i++) - global.logging[i] = new_logging[i]; + _nm_logging_enabled_state[i] = new_logging[i]; if ( had_platform_debug && _nm_logging_clear_platform_logging_cache @@ -384,8 +383,6 @@ nm_logging_all_levels_to_string (void) const char * nm_logging_domains_to_string (void) { - _ensure_initialized (); - if (G_UNLIKELY (!global.logging_domains_to_string)) global.logging_domains_to_string = _domains_to_string (TRUE); @@ -406,7 +403,7 @@ _domains_to_string (gboolean include_level_override) str = g_string_sized_new (75); for (diter = &global.domain_desc[0]; diter->name; diter++) { /* If it's set for any lower level, it will also be set for LOGL_ERR */ - if (!(diter->num & global.logging[LOGL_ERR])) + if (!(diter->num & _nm_logging_enabled_state[LOGL_ERR])) continue; if (str->len) @@ -418,15 +415,15 @@ _domains_to_string (gboolean include_level_override) /* Check if it's logging at a lower level than the default. */ for (i = 0; i < global.log_level; i++) { - if (diter->num & global.logging[i]) { + if (diter->num & _nm_logging_enabled_state[i]) { g_string_append_printf (str, ":%s", global.level_desc[i].name); break; } } /* Check if it's logging at a higher level than the default. */ - if (!(diter->num & global.logging[global.log_level])) { - for (i = global.log_level + 1; i < G_N_ELEMENTS (global.logging); i++) { - if (diter->num & global.logging[i]) { + if (!(diter->num & _nm_logging_enabled_state[global.log_level])) { + for (i = global.log_level + 1; i < G_N_ELEMENTS (_nm_logging_enabled_state); i++) { + if (diter->num & _nm_logging_enabled_state[i]) { g_string_append_printf (str, ":%s", global.level_desc[i].name); break; } @@ -459,16 +456,25 @@ nm_logging_all_domains_to_string (void) return str->str; } -gboolean -nm_logging_enabled (NMLogLevel level, NMLogDomain domain) +/** + * nm_logging_get_level: + * @domain: find the lowest enabled logging level for the + * given domain. If this is a set of multiple + * domains, the most verbose level will be returned. + * + * Returns: the lowest (most verbose) logging level for the + * give @domain, or %_LOGL_OFF if it is disabled. + **/ +NMLogLevel +nm_logging_get_level (NMLogDomain domain) { - if ((guint) level >= G_N_ELEMENTS (global.logging)) - g_return_val_if_reached (FALSE); - - /* This function is guaranteed not to modify errno. */ - _ensure_initialized (); + NMLogLevel sl = _LOGL_OFF; - return !!(global.logging[level] & domain); + G_STATIC_ASSERT (LOGL_TRACE == 0); + while ( sl > LOGL_TRACE + && nm_logging_enabled (sl - 1, domain)) + sl--; + return sl; } #if SYSTEMD_JOURNAL @@ -515,12 +521,10 @@ _nm_log_impl (const char *file, char s_buf_location[1024]; GTimeVal tv; - if ((guint) level >= G_N_ELEMENTS (global.logging)) + if ((guint) level >= G_N_ELEMENTS (_nm_logging_enabled_state)) g_return_if_reached (); - _ensure_initialized (); - - if (!(global.logging[level] & domain)) + if (!(_nm_logging_enabled_state[level] & domain)) return; /* Make sure that %m maps to the specified error */ @@ -609,7 +613,7 @@ _nm_log_impl (const char *file, const char *s_domain_1 = NULL; GString *s_domain_all = NULL; NMLogDomain dom_all = domain; - NMLogDomain dom = dom_all & global.logging[level]; + NMLogDomain dom = dom_all & _nm_logging_enabled_state[level]; for (diter = &global.domain_desc[0]; diter->name; diter++) { if (!NM_FLAGS_HAS (dom_all, diter->num)) @@ -744,6 +748,12 @@ nm_log_handler (const gchar *log_domain, } } +gboolean +nm_logging_syslog_enabled (void) +{ + return global.uses_syslog; +} + void nm_logging_syslog_openlog (const char *logging_backend) { @@ -763,6 +773,7 @@ nm_logging_syslog_openlog (const char *logging_backend) #if SYSTEMD_JOURNAL } else if (strcmp (logging_backend, "syslog") != 0) { global.log_backend = LOG_BACKEND_JOURNAL; + global.uses_syslog = TRUE; /* ensure we read a monotonic timestamp. Reading the timestamp the first * time causes a logging message. We don't want to do that during _nm_log_impl. */ @@ -770,6 +781,7 @@ nm_logging_syslog_openlog (const char *logging_backend) #endif } else { global.log_backend = LOG_BACKEND_SYSLOG; + global.uses_syslog = TRUE; openlog (G_LOG_DOMAIN, LOG_PID, LOG_DAEMON); } diff --git a/src/nm-logging.h b/src/nm-logging.h index 27f89f5d5b..f49f6ec67b 100644 --- a/src/nm-logging.h +++ b/src/nm-logging.h @@ -65,12 +65,16 @@ typedef enum { /*< skip >*/ LOGD_DISPATCH = (1LL << 33), LOGD_AUDIT = (1LL << 34), LOGD_SYSTEMD = (1LL << 35), + LOGD_VPN_PLUGIN = (1LL << 36), __LOGD_MAX, - LOGD_ALL = ((__LOGD_MAX - 1LL) << 1) - 1LL, + LOGD_ALL = (((__LOGD_MAX - 1LL) << 1) - 1LL) & ~( + LOGD_VPN_PLUGIN | /*not even part of ALL, because it might expose sensitive information. */ + 0), LOGD_DEFAULT = LOGD_ALL & ~( LOGD_DBUS_PROPS | LOGD_WIFI_SCAN | + LOGD_VPN_PLUGIN | 0), /* aliases: */ @@ -158,7 +162,17 @@ void _nm_log_impl (const char *file, const char *nm_logging_level_to_string (void); const char *nm_logging_domains_to_string (void); -gboolean nm_logging_enabled (NMLogLevel level, NMLogDomain domain); + +extern NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL]; +static inline gboolean +nm_logging_enabled (NMLogLevel level, NMLogDomain domain) +{ + nm_assert (((guint) level) < G_N_ELEMENTS (_nm_logging_enabled_state)); + return (((guint) level) < G_N_ELEMENTS (_nm_logging_enabled_state)) + && !!(_nm_logging_enabled_state[level] & domain); +} + +NMLogLevel nm_logging_get_level (NMLogDomain domain); const char *nm_logging_all_levels_to_string (void); const char *nm_logging_all_domains_to_string (void); @@ -168,6 +182,7 @@ gboolean nm_logging_setup (const char *level, char **bad_domains, GError **error); void nm_logging_syslog_openlog (const char *logging_backend); +gboolean nm_logging_syslog_enabled (void); /*****************************************************************************/ diff --git a/src/nm-manager.c b/src/nm-manager.c index b4e832dfb0..333e47366f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -21,13 +21,14 @@ #include "nm-default.h" +#include "nm-manager.h" + #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <unistd.h> -#include "nm-manager.h" #include "nm-bus-manager.h" #include "nm-vpn-manager.h" #include "nm-device.h" @@ -45,7 +46,6 @@ #include "nm-sleep-monitor.h" #include "nm-connectivity.h" #include "nm-policy.h" -#include "nm-connection-provider.h" #include "nm-session-monitor.h" #include "nm-activation-request.h" #include "nm-core-internal.h" @@ -90,15 +90,13 @@ typedef struct { gboolean sw_enabled; gboolean hw_enabled; RfKillType rtype; + NMConfigRunStatePropertyType key; const char *desc; - const char *key; const char *prop; const char *hw_prop; } RadioState; typedef struct { - char *state_file; - GSList *active_connections; GSList *authorizing_connections; guint ac_cleanup_id; @@ -144,7 +142,16 @@ typedef struct { gboolean devices_inited; } NMManagerPrivate; -#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) +struct _NMManager { + NMExportedObject parent; + NMManagerPrivate priv; +}; + +typedef struct { + NMExportedObjectClass parent; +} NMManagerClass; + +#define NM_MANAGER_GET_PRIVATE(o) ({ nm_assert (NM_IS_MANAGER (o)); &((o)->priv); }) G_DEFINE_TYPE (NMManager, nm_manager, NM_TYPE_EXPORTED_OBJECT) @@ -167,7 +174,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; NM_GOBJECT_PROPERTIES_DEFINE (NMManager, PROP_VERSION, PROP_STATE, - PROP_STATE_FILE, PROP_STARTUP, PROP_NETWORKING_ENABLED, PROP_WIRELESS_ENABLED, @@ -401,7 +407,7 @@ find_ac_for_connection (NMManager *manager, NMConnection *connection) } /* Filter out connections that are already active. - * nm_settings_get_connections() returns sorted list. We need to preserve the + * nm_settings_get_connections_sorted() returns sorted list. We need to preserve the * order so that we didn't change auto-activation order (recent timestamps * are first). * Caller is responsible for freeing the returned list with g_slist_free(). @@ -410,7 +416,7 @@ GSList * nm_manager_get_activatable_connections (NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - GSList *all_connections = nm_settings_get_connections (priv->settings); + GSList *all_connections = nm_settings_get_connections_sorted (priv->settings); GSList *connections = NULL, *iter; NMSettingsConnection *connection; @@ -1125,7 +1131,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection) } /* Create backing resources if the device has any autoconnect connections */ - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *candidate = iter->data; NMSettingConnection *s_con; @@ -1160,7 +1166,7 @@ retry_connections_for_parent_device (NMManager *self, NMDevice *device) g_return_if_fail (device); - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *candidate = iter->data; gs_free_error GError *error = NULL; @@ -1229,7 +1235,7 @@ system_unmanaged_devices_changed_cb (NMSettings *settings, unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings); for (iter = priv->devices; iter; iter = g_slist_next (iter)) - nm_device_set_unmanaged_by_user_config (NM_DEVICE (iter->data), unmanaged_specs); + nm_device_set_unmanaged_by_user_settings (NM_DEVICE (iter->data), unmanaged_specs); } static void @@ -1268,54 +1274,6 @@ system_hostname_changed_cb (NMSettings *settings, /* General NMManager stuff */ /*******************************************************************/ -/* Store value into key-file; supported types: boolean, int, string */ -static gboolean -write_value_to_state_file (const char *filename, - const char *group, - const char *key, - GType value_type, - gpointer value, - GError **error) -{ - GKeyFile *key_file; - char *data; - gsize len = 0; - gboolean ret = FALSE; - - g_return_val_if_fail (filename != NULL, FALSE); - g_return_val_if_fail (group != NULL, FALSE); - g_return_val_if_fail (key != NULL, FALSE); - g_return_val_if_fail (value_type == G_TYPE_BOOLEAN || - value_type == G_TYPE_INT || - value_type == G_TYPE_STRING, - FALSE); - - key_file = g_key_file_new (); - - g_key_file_set_list_separator (key_file, ','); - g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS, NULL); - switch (value_type) { - case G_TYPE_BOOLEAN: - g_key_file_set_boolean (key_file, group, key, *((gboolean *) value)); - break; - case G_TYPE_INT: - g_key_file_set_integer (key_file, group, key, *((gint *) value)); - break; - case G_TYPE_STRING: - g_key_file_set_string (key_file, group, key, *((const gchar **) value)); - break; - } - - data = g_key_file_to_data (key_file, &len, NULL); - if (data) { - ret = g_file_set_contents (filename, data, len, error); - g_free (data); - } - g_key_file_free (key_file); - - return ret; -} - static gboolean radio_enabled_for_rstate (RadioState *rstate, gboolean check_changeable) { @@ -1944,7 +1902,7 @@ add_device (NMManager *self, NMDevice *device, GError **error) type_desc = nm_device_get_type_desc (device); g_assert (type_desc); - nm_device_set_unmanaged_by_user_config (device, nm_settings_get_unmanaged_specs (priv->settings)); + nm_device_set_unmanaged_by_user_settings (device, nm_settings_get_unmanaged_specs (priv->settings)); nm_device_set_unmanaged_flags (device, NM_UNMANAGED_SLEEPING, @@ -1999,11 +1957,12 @@ factory_component_added_cb (NMDeviceFactory *factory, GObject *component, gpointer user_data) { + NMManager *self = user_data; GSList *iter; - g_return_val_if_fail (NM_IS_MANAGER (user_data), FALSE); + g_return_val_if_fail (self, FALSE); - for (iter = NM_MANAGER_GET_PRIVATE (user_data)->devices; iter; iter = iter->next) { + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = iter->next) { if (nm_device_notify_component_added ((NMDevice *) iter->data, component)) return TRUE; } @@ -2079,6 +2038,9 @@ platform_link_added (NMManager *self, if (!ignore) { _LOGW (LOGD_HW, "%s: factory failed to create device: %s", plink->name, error->message); + } else { + _LOGD (LOGD_HW, "%s: factory failed to create device: %s", + plink->name, error->message); } return; } @@ -2641,7 +2603,7 @@ find_slaves (NMManager *manager, * even if a slave was already active, it might be deactivated during * master reactivation. */ - all_connections = nm_settings_get_connections (priv->settings); + all_connections = nm_settings_get_connections_sorted (priv->settings); for (iter = all_connections; iter; iter = iter->next) { NMSettingsConnection *master_connection = NULL; NMDevice *master_device = NULL; @@ -3375,7 +3337,7 @@ _activation_auth_done (NMActiveConnection *active, g_dbus_method_invocation_return_value (context, g_variant_new ("(o)", nm_exported_object_get_path (NM_EXPORTED_OBJECT (active)))); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, TRUE, NULL, subject, NULL); g_object_unref (active); return; @@ -3387,7 +3349,7 @@ _activation_auth_done (NMActiveConnection *active, } g_assert (error); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, subject, error->message); _internal_activation_failed (self, active, error->message); @@ -3475,7 +3437,7 @@ impl_manager_activate_connection (NMManager *self, error: if (connection) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, NULL, subject, error->message); } g_clear_object (&active); @@ -3524,6 +3486,7 @@ activation_add_done (NMSettings *settings, nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, nm_active_connection_get_settings_connection (active), TRUE, + NULL, nm_active_connection_get_subject (active), NULL); return; @@ -3538,6 +3501,7 @@ activation_add_done (NMSettings *settings, nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, + NULL, nm_active_connection_get_subject (active), error->message); g_clear_error (&local); @@ -3582,6 +3546,7 @@ _add_and_activate_auth_done (NMActiveConnection *active, nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, + NULL, nm_active_connection_get_subject (active), error->message); g_dbus_method_invocation_take_error (context, error); @@ -3633,7 +3598,7 @@ impl_manager_add_and_activate_connection (NMManager *self, if (!subject) goto error; - all_connections = nm_settings_get_connections (priv->settings); + all_connections = nm_settings_get_connections_sorted (priv->settings); if (vpn) { /* Try to fill the VPN's connection setting and name at least */ if (!nm_connection_get_setting_vpn (connection)) { @@ -3683,7 +3648,7 @@ impl_manager_add_and_activate_connection (NMManager *self, return; error: - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, subject, error->message); + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE, NULL, FALSE, NULL, subject, error->message); g_clear_object (&connection); g_slist_free (all_connections); g_clear_object (&subject); @@ -3779,6 +3744,7 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, nm_active_connection_get_settings_connection (active), !error, + NULL, nm_auth_chain_get_subject (chain), error ? error->message : NULL); } @@ -3852,7 +3818,7 @@ impl_manager_deactivate_connection (NMManager *self, done: if (error) { if (connection) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, connection, FALSE, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DEACTIVATE, connection, FALSE, NULL, subject, error->message); } g_dbus_method_invocation_take_error (context, error); @@ -4192,21 +4158,9 @@ static void _internal_enable (NMManager *self, gboolean enable) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *error = NULL; - /* Update "NetworkingEnabled" key in state file */ - if (priv->state_file) { - if (!write_value_to_state_file (priv->state_file, - "main", "NetworkingEnabled", - G_TYPE_BOOLEAN, (gpointer) &enable, - &error)) { - /* Not a hard error */ - _LOGW (LOGD_SUSPEND, "writing to state file %s failed: %s", - priv->state_file, - error->message); - g_clear_error (&error); - } - } + nm_config_state_set (priv->config, TRUE, FALSE, + NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED, enable); _LOGI (LOGD_SUSPEND, "%s requested (sleeping: %s enabled: %s)", enable ? "enable" : "disable", @@ -4592,7 +4546,7 @@ nm_manager_start (NMManager *self, GError **error) * connection-added signals thus devices have to be created manually. */ _LOGD (LOGD_CORE, "creating virtual devices..."); - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = iter->next) connection_changed (self, NM_CONNECTION (iter->data)); g_slist_free (connections); @@ -5144,7 +5098,6 @@ manager_radio_user_toggled (NMManager *self, gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GError *error = NULL; gboolean old_enabled, new_enabled; /* Don't touch devices if asleep/networking disabled */ @@ -5158,17 +5111,8 @@ manager_radio_user_toggled (NMManager *self, } /* Update enabled key in state file */ - if (priv->state_file) { - if (!write_value_to_state_file (priv->state_file, - "main", rstate->key, - G_TYPE_BOOLEAN, (gpointer) &enabled, - &error)) { - _LOGW (LOGD_CORE, "writing to state file %s failed: %s", - priv->state_file, - error->message); - g_clear_error (&error); - } - } + nm_config_state_set (priv->config, TRUE, FALSE, + rstate->key, enabled); /* When the user toggles the radio, their request should override any * daemon (like ModemManager) enabled state that can be changed. For WWAN @@ -5230,34 +5174,22 @@ nm_manager_get (void) return singleton_instance; } -NMConnectionProvider * -nm_connection_provider_get (void) +NMSettings * +nm_settings_get (void) { - NMConnectionProvider *p; - g_return_val_if_fail (singleton_instance, NULL); - p = NM_CONNECTION_PROVIDER (NM_MANAGER_GET_PRIVATE (singleton_instance)->settings); - g_return_val_if_fail (p, NULL); - return p; + return NM_MANAGER_GET_PRIVATE (singleton_instance)->settings; } NMManager * -nm_manager_setup (const char *state_file, - gboolean initial_net_enabled, - gboolean initial_wifi_enabled, - gboolean initial_wwan_enabled) +nm_manager_setup (void) { NMManager *self; g_return_val_if_fail (!singleton_instance, singleton_instance); - self = g_object_new (NM_TYPE_MANAGER, - NM_MANAGER_NETWORKING_ENABLED, initial_net_enabled, - NM_MANAGER_WIRELESS_ENABLED, initial_wifi_enabled, - NM_MANAGER_WWAN_ENABLED, initial_wwan_enabled, - NM_MANAGER_STATE_FILE, state_file, - NULL); + self = g_object_new (NM_TYPE_MANAGER, NULL); nm_assert (NM_IS_MANAGER (self)); singleton_instance = self; @@ -5275,6 +5207,7 @@ constructed (GObject *object) NMManager *self = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMConfigData *config_data; + const NMConfigState *state; G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object); @@ -5320,6 +5253,13 @@ constructed (GObject *object) g_signal_connect (priv->connectivity, "notify::" NM_CONNECTIVITY_STATE, G_CALLBACK (connectivity_changed), self); + state = nm_config_state_get (priv->config); + + priv->net_enabled = state->net_enabled; + + priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = state->wifi_enabled; + priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = state->wwan_enabled; + priv->rfkill_mgr = nm_rfkill_manager_new (); g_signal_connect (priv->rfkill_mgr, "rfkill-changed", @@ -5346,14 +5286,14 @@ nm_manager_init (NMManager *self) memset (priv->radio_states, 0, sizeof (priv->radio_states)); priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WLAN].key = "WirelessEnabled"; + priv->radio_states[RFKILL_TYPE_WLAN].key = NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].prop = NM_MANAGER_WIRELESS_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].hw_prop = NM_MANAGER_WIRELESS_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WLAN].desc = "WiFi"; priv->radio_states[RFKILL_TYPE_WLAN].rtype = RFKILL_TYPE_WLAN; priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = TRUE; - priv->radio_states[RFKILL_TYPE_WWAN].key = "WWANEnabled"; + priv->radio_states[RFKILL_TYPE_WWAN].key = NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; @@ -5516,33 +5456,15 @@ set_property (GObject *object, guint prop_id, GError *error = NULL; switch (prop_id) { - case PROP_STATE_FILE: - /* construct-only */ - priv->state_file = g_value_dup_string (value); - break; - case PROP_NETWORKING_ENABLED: - /* construct-only */ - priv->net_enabled = g_value_get_boolean (value); - break; case PROP_WIRELESS_ENABLED: - if (!priv->rfkill_mgr) { - /* called during object construction. */ - priv->radio_states[RFKILL_TYPE_WLAN].user_enabled = g_value_get_boolean (value); - } else { - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WLAN], - g_value_get_boolean (value)); - } + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WLAN], + g_value_get_boolean (value)); break; case PROP_WWAN_ENABLED: - if (!priv->rfkill_mgr) { - /* called during object construction. */ - priv->radio_states[RFKILL_TYPE_WWAN].user_enabled = g_value_get_boolean (value); - } else { - manager_radio_user_toggled (NM_MANAGER (object), - &priv->radio_states[RFKILL_TYPE_WWAN], - g_value_get_boolean (value)); - } + manager_radio_user_toggled (NM_MANAGER (object), + &priv->radio_states[RFKILL_TYPE_WWAN], + g_value_get_boolean (value)); break; case PROP_WIMAX_ENABLED: /* WIMAX is depreacted. This does nothing. */ @@ -5620,7 +5542,6 @@ dispose (GObject *object) g_clear_object (&priv->settings); } - g_clear_pointer (&priv->state_file, g_free); g_clear_object (&priv->vpn_manager); /* Unregister property filter */ @@ -5665,8 +5586,6 @@ nm_manager_class_init (NMManagerClass *manager_class) GObjectClass *object_class = G_OBJECT_CLASS (manager_class); NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (manager_class); - g_type_class_add_private (manager_class, sizeof (NMManagerPrivate)); - exported_object_class->export_path = NM_DBUS_PATH; /* virtual methods */ @@ -5682,13 +5601,6 @@ nm_manager_class_init (NMManagerClass *manager_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_STATE_FILE] = - g_param_spec_string (NM_MANAGER_STATE_FILE, "", "", - NULL, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_properties[PROP_STATE] = g_param_spec_uint (NM_MANAGER_STATE, "", "", 0, NM_STATE_DISCONNECTED, 0, @@ -5704,14 +5616,13 @@ nm_manager_class_init (NMManagerClass *manager_class) obj_properties[PROP_NETWORKING_ENABLED] = g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "", TRUE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); obj_properties[PROP_WIRELESS_ENABLED] = g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); obj_properties[PROP_WIRELESS_HARDWARE_ENABLED] = @@ -5724,7 +5635,6 @@ nm_manager_class_init (NMManagerClass *manager_class) g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "", TRUE, G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); obj_properties[PROP_WWAN_HARDWARE_ENABLED] = @@ -5844,8 +5754,7 @@ nm_manager_class_init (NMManagerClass *manager_class) g_signal_new (NM_MANAGER_DEVICE_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, device_added), - NULL, NULL, NULL, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, NM_TYPE_DEVICE); /* Emitted for both realized devices and placeholder devices */ @@ -5861,8 +5770,7 @@ nm_manager_class_init (NMManagerClass *manager_class) g_signal_new (NM_MANAGER_DEVICE_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, device_removed), - NULL, NULL, NULL, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, NM_TYPE_DEVICE); /* Emitted for both realized devices and placeholder devices */ @@ -5877,8 +5785,7 @@ nm_manager_class_init (NMManagerClass *manager_class) g_signal_new (NM_MANAGER_STATE_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMManagerClass, state_changed), - NULL, NULL, NULL, + 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); signals[CHECK_PERMISSIONS] = diff --git a/src/nm-manager.h b/src/nm-manager.h index 5401b002c1..d436f0516b 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -55,7 +55,6 @@ /* Not exported */ #define NM_MANAGER_HOSTNAME "hostname" #define NM_MANAGER_SLEEPING "sleeping" -#define NM_MANAGER_STATE_FILE "state-file" /* signals */ #define NM_MANAGER_CHECK_PERMISSIONS "check-permissions" @@ -72,26 +71,10 @@ #define NM_MANAGER_INTERNAL_DEVICE_REMOVED "internal-device-removed" -struct _NMManager { - NMExportedObject parent; -}; - -typedef struct { - NMExportedObjectClass parent; - - /* Signals */ - void (*device_added) (NMManager *manager, NMDevice *device); - void (*device_removed) (NMManager *manager, NMDevice *device); - void (*state_changed) (NMManager *manager, guint state); -} NMManagerClass; - GType nm_manager_get_type (void); /* nm_manager_setup() should only be used by main.c */ -NMManager * nm_manager_setup (const char *state_file, - gboolean initial_net_enabled, - gboolean initial_wifi_enabled, - gboolean initial_wwan_enabled); +NMManager * nm_manager_setup (void); NMManager * nm_manager_get (void); diff --git a/src/nm-policy.c b/src/nm-policy.c index 9695ad605c..0c63b1cba6 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -862,7 +862,7 @@ reset_autoconnect_all (NMPolicy *self, NMDevice *device) } else _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections"); - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { if (!device || nm_device_check_connection_compatible (device, iter->data)) { nm_settings_connection_reset_autoconnect_retries (iter->data); @@ -880,7 +880,7 @@ reset_autoconnect_for_failed_secrets (NMPolicy *self) _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections with failed secrets"); - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMSettingsConnection *connection = NM_SETTINGS_CONNECTION (iter->data); @@ -908,7 +908,7 @@ block_autoconnect_for_device (NMPolicy *self, NMDevice *device) if (!nm_device_is_software (device)) return; - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { if (nm_device_check_connection_compatible (device, iter->data)) { nm_settings_connection_set_autoconnect_blocked_reason (NM_SETTINGS_CONNECTION (iter->data), @@ -991,7 +991,7 @@ reset_connections_retries (gpointer user_data) min_stamp = 0; now = nm_utils_get_monotonic_timestamp_s (); - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMSettingsConnection *connection = NM_SETTINGS_CONNECTION (iter->data); @@ -1044,7 +1044,7 @@ activate_slave_connections (NMPolicy *self, NMDevice *device) } } - connections = nm_settings_get_connections (priv->settings); + connections = nm_settings_get_connections_sorted (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *slave; NMSettingConnection *s_slave_con; @@ -1442,7 +1442,7 @@ vpn_connection_activated (NMPolicy *self, NMVpnConnection *vpn) nm_dns_manager_begin_updates (priv->dns_manager, __func__); - ip_iface = nm_vpn_connection_get_ip_iface (vpn); + ip_iface = nm_vpn_connection_get_ip_iface (vpn, TRUE); /* Add the VPN connection's IP configs from DNS */ diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c index 05e28c7426..2d4c7d9595 100644 --- a/src/nm-route-manager.c +++ b/src/nm-route-manager.c @@ -873,7 +873,7 @@ next: || !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route, *p_effective_metric)) { if (!vtable->vt->route_add (priv->platform, ifindex, cur_ipx_route, *p_effective_metric)) { - if (cur_ipx_route->rx.source < NM_IP_CONFIG_SOURCE_USER) { + if (cur_ipx_route->rx.rt_source < NM_IP_CONFIG_SOURCE_USER) { _LOGD (vtable->vt->addr_family, "ignore error adding IPv%c route to kernel: %s", vtable->vt->is_ip4 ? '4' : '6', @@ -1024,7 +1024,7 @@ _ip4_device_routes_ip4_route_changed (NMPlatform *platform, if (change_type == NM_PLATFORM_SIGNAL_REMOVED) return; - if ( route->source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL + if ( route->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL || route->metric != 0) { /* we don't have an automatically created device route at hand. Bail out early. */ return; diff --git a/src/nm-session-monitor.c b/src/nm-session-monitor.c index 467094270b..279a888672 100644 --- a/src/nm-session-monitor.c +++ b/src/nm-session-monitor.c @@ -279,45 +279,6 @@ ck_finalize (NMSessionMonitor *monitor) NM_DEFINE_SINGLETON_GETTER (NMSessionMonitor, nm_session_monitor_get, NM_TYPE_SESSION_MONITOR); /** - * nm_session_monitor_connect: - * @self: the session monitor - * @callback: The callback. - * @user_data: User data for the callback. - * - * Connect a callback to the session monitor. - * - * Returns: Handler ID to be used with nm_session_monitor_disconnect(). - */ -gulong -nm_session_monitor_connect (NMSessionMonitor *self, - NMSessionCallback callback, - gpointer user_data) -{ - g_return_val_if_fail (NM_IS_SESSION_MONITOR (self), 0); - - return g_signal_connect (self, - NM_SESSION_MONITOR_CHANGED, - G_CALLBACK (callback), - user_data); -} - -/** - * nm_session_monitor_disconnect: - * @self: the session monitor - * @handler_id: Handler ID returned by nm_session_monitor-connect(). - * - * Disconnect callback from the session handler. - */ -void -nm_session_monitor_disconnect (NMSessionMonitor *self, - gulong handler_id) -{ - g_return_if_fail (NM_IS_SESSION_MONITOR (self)); - - g_signal_handler_disconnect (self, handler_id); -} - -/** * nm_session_monitor_uid_to_user: * @uid: UID. * @out_user: Return location for user name. diff --git a/src/nm-session-monitor.h b/src/nm-session-monitor.h index af50b71ba3..e776ef25ab 100644 --- a/src/nm-session-monitor.h +++ b/src/nm-session-monitor.h @@ -43,12 +43,6 @@ GType nm_session_monitor_get_type (void) G_GNUC_CONST; NMSessionMonitor *nm_session_monitor_get (void); -gulong nm_session_monitor_connect (NMSessionMonitor *self, - NMSessionCallback callback, - gpointer user_data); -void nm_session_monitor_disconnect (NMSessionMonitor *self, - gulong handler_id); - gboolean nm_session_monitor_uid_to_user (uid_t uid, const char **out_user); gboolean nm_session_monitor_user_to_uid (const char *user, uid_t *out_uid); gboolean nm_session_monitor_session_exists (NMSessionMonitor *self, diff --git a/src/nm-test-utils-core.h b/src/nm-test-utils-core.h new file mode 100644 index 0000000000..8fd3be55ae --- /dev/null +++ b/src/nm-test-utils-core.h @@ -0,0 +1,296 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 - 2016 Red Hat, Inc. + */ + +#ifndef __NM_TEST_UTILS_CORE_H__ +#define __NM_TEST_UTILS_CORE_H__ + +#include "NetworkManagerUtils.h" +#include "nm-keyfile-internal.h" + +#define _NMTST_INSIDE_CORE 1 + +#include "nm-test-utils.h" + +/*****************************************************************************/ + +inline static void +nmtst_init_with_logging (int *argc, char ***argv, const char *log_level, const char *log_domains) +{ + __nmtst_init (argc, argv, FALSE, log_level, log_domains, NULL); +} +inline static void +nmtst_init_assert_logging (int *argc, char ***argv, const char *log_level, const char *log_domains) +{ + gboolean set_logging; + + __nmtst_init (argc, argv, TRUE, NULL, NULL, &set_logging); + + if (!set_logging) { + gboolean success; + + success = nm_logging_setup (log_level, log_domains, NULL, NULL); + g_assert (success); + } +} + +/*****************************************************************************/ + +#ifdef __NETWORKMANAGER_PLATFORM_H__ + +inline static NMPlatformIP4Address * +nmtst_platform_ip4_address (const char *address, const char *peer_address, guint plen) +{ + static NMPlatformIP4Address addr; + + g_assert (plen <= 32); + + memset (&addr, 0, sizeof (addr)); + addr.address = nmtst_inet4_from_string (address); + if (peer_address) + addr.peer_address = nmtst_inet4_from_string (peer_address); + else + addr.peer_address = addr.address; + addr.plen = plen; + + return &addr; +} + +inline static NMPlatformIP4Address * +nmtst_platform_ip4_address_full (const char *address, const char *peer_address, guint plen, + int ifindex, NMIPConfigSource source, guint32 timestamp, + guint32 lifetime, guint32 preferred, guint32 flags, + const char *label) +{ + NMPlatformIP4Address *addr = nmtst_platform_ip4_address (address, peer_address, plen); + + G_STATIC_ASSERT (IFNAMSIZ == sizeof (addr->label)); + g_assert (!label || strlen (label) < IFNAMSIZ); + + addr->ifindex = ifindex; + addr->addr_source = source; + addr->timestamp = timestamp; + addr->lifetime = lifetime; + addr->preferred = preferred; + addr->n_ifa_flags = flags; + if (label) + g_strlcpy (addr->label, label, sizeof (addr->label)); + + return addr; +} + +inline static NMPlatformIP6Address * +nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen) +{ + static NMPlatformIP6Address addr; + + g_assert (plen <= 128); + + memset (&addr, 0, sizeof (addr)); + addr.address = *nmtst_inet6_from_string (address); + addr.peer_address = *nmtst_inet6_from_string (peer_address); + addr.plen = plen; + + return &addr; +} + +inline static NMPlatformIP6Address * +nmtst_platform_ip6_address_full (const char *address, const char *peer_address, guint plen, + int ifindex, NMIPConfigSource source, guint32 timestamp, + guint32 lifetime, guint32 preferred, guint32 flags) +{ + NMPlatformIP6Address *addr = nmtst_platform_ip6_address (address, peer_address, plen); + + addr->ifindex = ifindex; + addr->addr_source = source; + addr->timestamp = timestamp; + addr->lifetime = lifetime; + addr->preferred = preferred; + addr->n_ifa_flags = flags; + + return addr; +} + +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway) +{ + static NMPlatformIP4Route route; + + g_assert (plen <= 32); + + memset (&route, 0, sizeof (route)); + route.network = nmtst_inet4_from_string (network); + route.plen = plen; + route.gateway = nmtst_inet4_from_string (gateway); + + return &route; +} + +inline static NMPlatformIP4Route * +nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway, + int ifindex, NMIPConfigSource source, + guint metric, guint mss, + guint8 scope, + const char *pref_src) +{ + NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway); + + route->ifindex = ifindex; + route->rt_source = source; + route->metric = metric; + route->mss = mss; + route->scope_inv = nm_platform_route_scope_inv (scope); + route->pref_src = nmtst_inet4_from_string (pref_src); + + return route; +} + +inline static NMPlatformIP6Route * +nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) +{ + static NMPlatformIP6Route route; + + nm_assert (plen <= 128); + + memset (&route, 0, sizeof (route)); + route.network = *nmtst_inet6_from_string (network); + route.plen = plen; + route.gateway = *nmtst_inet6_from_string (gateway); + + return &route; +} + +inline static NMPlatformIP6Route * +nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway, + int ifindex, NMIPConfigSource source, + guint metric, guint mss) +{ + NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway); + + route->ifindex = ifindex; + route->rt_source = source; + route->metric = metric; + route->mss = mss; + + return route; +} + +inline static int +_nmtst_platform_ip4_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data) +{ + return nm_platform_ip4_route_cmp ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b); +} + +inline static void +nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len, gboolean ignore_order) +{ + gsize i; + gs_free const NMPlatformIP4Route *c_a = NULL, *c_b = NULL; + + g_assert (a); + g_assert (b); + + if (ignore_order) { + a = c_a = g_memdup (a, sizeof (NMPlatformIP4Route) * len); + b = c_b = g_memdup (b, sizeof (NMPlatformIP4Route) * len); + g_qsort_with_data (c_a, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL); + g_qsort_with_data (c_b, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL); + } + + for (i = 0; i < len; i++) { + if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) { + char buf[sizeof (_nm_utils_to_string_buffer)]; + + g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (long unsigned) i, + nm_platform_ip4_route_to_string (&a[i], NULL, 0), + nm_platform_ip4_route_to_string (&b[i], buf, sizeof (buf))); + g_assert_not_reached (); + } + } +} + +inline static int +_nmtst_platform_ip6_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data) +{ + return nm_platform_ip6_route_cmp ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b); +} + +inline static void +nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len, gboolean ignore_order) +{ + gsize i; + gs_free const NMPlatformIP6Route *c_a = NULL, *c_b = NULL; + + g_assert (a); + g_assert (b); + + if (ignore_order) { + a = c_a = g_memdup (a, sizeof (NMPlatformIP6Route) * len); + b = c_b = g_memdup (b, sizeof (NMPlatformIP6Route) * len); + g_qsort_with_data (c_a, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL); + g_qsort_with_data (c_b, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL); + } + + for (i = 0; i < len; i++) { + if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) { + char buf[sizeof (_nm_utils_to_string_buffer)]; + + g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (long unsigned) i, + nm_platform_ip6_route_to_string (&a[i], NULL, 0), + nm_platform_ip6_route_to_string (&b[i], buf, sizeof (buf))); + g_assert_not_reached (); + } + } +} + +#endif + + +#ifdef __NETWORKMANAGER_IP4_CONFIG_H__ + +inline static NMIP4Config * +nmtst_ip4_config_clone (NMIP4Config *config) +{ + NMIP4Config *copy = nm_ip4_config_new (-1); + + g_assert (copy); + g_assert (config); + nm_ip4_config_replace (copy, config, NULL); + return copy; +} + +#endif + + +#ifdef __NETWORKMANAGER_IP6_CONFIG_H__ + +inline static NMIP6Config * +nmtst_ip6_config_clone (NMIP6Config *config) +{ + NMIP6Config *copy = nm_ip6_config_new (-1); + + g_assert (copy); + g_assert (config); + nm_ip6_config_replace (copy, config, NULL); + return copy; +} + +#endif + +#endif /* __NM_TEST_UTILS_CORE_H__ */ diff --git a/src/nm-types.h b/src/nm-types.h index 997723e607..fa70372c43 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -54,13 +54,20 @@ typedef struct _NMLldpListener NMLldpListener; typedef enum { /* In priority order; higher number == higher priority */ - NM_IP_CONFIG_SOURCE_UNKNOWN, - /* platform internal flag used to mark routes with RTM_F_CLONED. */ - _NM_IP_CONFIG_SOURCE_RTM_F_CLONED, + NM_IP_CONFIG_SOURCE_UNKNOWN = 0, - /* routes from platform with protocol RTPROT_KERNEL. */ - NM_IP_CONFIG_SOURCE_RTPROT_KERNEL, + /* for routes, the source is mapped to the uint8 field rtm_protocol. + * Reserve the range [1,0x100] for native RTPROT values. */ + + NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC = 1 + 0, + NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT = 1 + 1, + NM_IP_CONFIG_SOURCE_RTPROT_KERNEL = 1 + 2, + NM_IP_CONFIG_SOURCE_RTPROT_BOOT = 1 + 3, + NM_IP_CONFIG_SOURCE_RTPROT_STATIC = 1 + 4, + NM_IP_CONFIG_SOURCE_RTPROT_RA = 1 + 9, + NM_IP_CONFIG_SOURCE_RTPROT_DHCP = 1 + 16, + _NM_IP_CONFIG_SOURCE_RTPROT_LAST = 1 + 0xFF, NM_IP_CONFIG_SOURCE_KERNEL, NM_IP_CONFIG_SOURCE_SHARED, @@ -73,6 +80,12 @@ typedef enum { NM_IP_CONFIG_SOURCE_USER, } NMIPConfigSource; +inline static gboolean +NM_IS_IP_CONFIG_SOURCE_RTPROT (NMIPConfigSource source) +{ + return source > NM_IP_CONFIG_SOURCE_UNKNOWN && source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST; +} + /* platform */ typedef struct _NMPlatform NMPlatform; typedef struct _NMPlatformIP4Address NMPlatformIP4Address; diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 7b54507696..d0fb277462 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -31,9 +31,10 @@ #include "nm-utils.h" #include "nm-core-utils.h" +#include "nm-platform-utils.h" #include "nmp-object.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /*********************************************************************************************/ @@ -709,12 +710,13 @@ static gboolean infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) { NMFakePlatformLink *device, *parent_device; - gs_free char *name = NULL; + char name[IFNAMSIZ]; parent_device = link_get (platform, parent); g_return_val_if_fail (parent_device != NULL, FALSE); - name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key); + nm_utils_new_infiniband_name (name, parent_device->link.name, p_key); + if (!link_add (platform, name, NM_LINK_TYPE_INFINIBAND, NULL, 0, out_link)) return FALSE; @@ -726,7 +728,6 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMP device->lnk->lnk_infiniband.p_key = p_key; device->lnk->lnk_infiniband.mode = "datagram"; device->link.parent = parent; - return TRUE; } @@ -739,7 +740,7 @@ infiniband_partition_delete (NMPlatform *platform, int parent, int p_key) parent_device = link_get (platform, parent); g_return_val_if_fail (parent_device != NULL, FALSE); - name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key); + nm_utils_new_infiniband_name (name, parent_device->link.name, p_key); return link_delete (platform, nm_platform_link_get_ifindex (platform, name)); } @@ -911,7 +912,7 @@ ip4_address_add (NMPlatform *platform, int i; memset (&address, 0, sizeof (address)); - address.source = NM_IP_CONFIG_SOURCE_KERNEL; + address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = peer_addr; @@ -962,7 +963,7 @@ ip6_address_add (NMPlatform *platform, int i; memset (&address, 0, sizeof (address)); - address.source = NM_IP_CONFIG_SOURCE_KERNEL; + address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = (IN6_IS_ADDR_UNSPECIFIED (&peer_addr) || IN6_ARE_ADDR_EQUAL (&addr, &peer_addr)) ? in6addr_any : peer_addr; @@ -1207,9 +1208,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE; memset (&route, 0, sizeof (route)); - route.source = NM_IP_CONFIG_SOURCE_KERNEL; route.ifindex = ifindex; - route.source = source; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source); route.network = nm_utils_ip4_address_clear_host_address (network, plen); route.plen = plen; route.gateway = gateway; @@ -1273,9 +1273,8 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, metric = nm_utils_ip6_route_metric_normalize (metric); memset (&route, 0, sizeof (route)); - route.source = NM_IP_CONFIG_SOURCE_KERNEL; route.ifindex = ifindex; - route.source = source; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source); nm_utils_ip6_address_clear_host_address (&route.network, &network, plen); route.plen = plen; route.gateway = gateway; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 3eb7ff3f8d..4e41bc9b27 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -176,6 +176,11 @@ * Forward declarations and enums ******************************************************************/ +typedef enum { + INFINIBAND_ACTION_CREATE_CHILD, + INFINIBAND_ACTION_DELETE_CHILD, +} InfinibandAction; + enum { DELAYED_ACTION_IDX_REFRESH_ALL_LINKS, DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES, @@ -303,23 +308,6 @@ _support_user_ipv6ll_detect (struct nlattr **tb) * Various utilities ******************************************************************/ -static void -clear_host_address (int family, const void *network, guint8 plen, void *dst) -{ - g_return_if_fail (network); - - switch (family) { - case AF_INET: - *((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen); - break; - case AF_INET6: - nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen); - break; - default: - g_assert_not_reached (); - } -} - static int _vlan_qos_mapping_cmp_from (gconstpointer a, gconstpointer b, gpointer user_data) { @@ -588,12 +576,17 @@ _lookup_cached_link (const NMPCache *cache, int ifindex, gboolean *completed_fro #define DEVTYPE_PREFIX "DEVTYPE=" static char * -_linktype_read_devtype (const char *sysfs_path) +_linktype_read_devtype (const char *ifname) { - gs_free char *uevent = g_strdup_printf ("%s/uevent", sysfs_path); + char uevent[NM_STRLEN ("/sys/class/net/123456789012345/uevent\0") + 100 /*safety*/]; char *contents = NULL; char *cont, *end; + nm_sprintf_buf (uevent, + "/sys/class/net/%s/uevent", + NM_ASSERT_VALID_PATH_COMPONENT (ifname)); + nm_assert (strlen (uevent) < sizeof (uevent) - 1); + if (!g_file_get_contents (uevent, &contents, NULL, NULL)) return NULL; for (cont = contents; cont; cont = end) { @@ -690,9 +683,8 @@ _linktype_get_type (NMPlatform *platform, return NM_LINK_TYPE_IP6TNL; if (ifname) { + char anycast_mask[NM_STRLEN ("/sys/class/net/123456789012345/anycast_mask\0") + 100 /*safety*/]; gs_free char *driver = NULL; - gs_free char *sysfs_path = NULL; - gs_free char *anycast_mask = NULL; gs_free char *devtype = NULL; /* Fallback OVS detection for kernel <= 3.16 */ @@ -709,12 +701,15 @@ _linktype_get_type (NMPlatform *platform, } } - sysfs_path = g_strdup_printf ("/sys/class/net/%s", ifname); - anycast_mask = g_strdup_printf ("%s/anycast_mask", sysfs_path); + nm_sprintf_buf (anycast_mask, + "/sys/class/net/%s/anycast_mask", + NM_ASSERT_VALID_PATH_COMPONENT (ifname)); + nm_assert (strlen (anycast_mask) < sizeof (anycast_mask) - 1); + if (g_file_test (anycast_mask, G_FILE_TEST_EXISTS)) return NM_LINK_TYPE_OLPC_MESH; - devtype = _linktype_read_devtype (sysfs_path); + devtype = _linktype_read_devtype (ifname); for (i = 0; devtype && i < G_N_ELEMENTS (linktypes); i++) { if (g_strcmp0 (devtype, linktypes[i].devtype) == 0) { if (linktypes[i].nm_type == NM_LINK_TYPE_BNEP) { @@ -729,7 +724,7 @@ _linktype_get_type (NMPlatform *platform, } /* Fallback for drivers that don't call SET_NETDEV_DEVTYPE() */ - if (wifi_utils_is_wifi (ifname, sysfs_path)) + if (wifi_utils_is_wifi (ifname)) return NM_LINK_TYPE_WIFI; if (arptype == ARPHRD_ETHER) { @@ -803,9 +798,10 @@ _nl_nlmsg_type_to_str (guint16 type, char *buf, gsize len) static gboolean _parse_af_inet6 (NMPlatform *platform, struct nlattr *attr, - NMUtilsIPv6IfaceId *out_iid, - guint8 *out_iid_is_valid, - guint8 *out_addr_gen_mode_inv) + NMUtilsIPv6IfaceId *out_token, + gboolean *out_token_valid, + guint8 *out_addr_gen_mode_inv, + gboolean *out_addr_gen_mode_valid) { static struct nla_policy policy[IFLA_INET6_MAX+1] = { [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, @@ -819,7 +815,8 @@ _parse_af_inet6 (NMPlatform *platform, struct nlattr *tb[IFLA_INET6_MAX+1]; int err; struct in6_addr i6_token; - gboolean iid_is_valid = FALSE; + gboolean token_valid = FALSE; + gboolean addr_gen_mode_valid = FALSE; guint8 i6_addr_gen_mode_inv = 0; gboolean success = FALSE; @@ -836,8 +833,7 @@ _parse_af_inet6 (NMPlatform *platform, if (_check_addr_or_errout (tb, IFLA_INET6_TOKEN, sizeof (struct in6_addr))) { nla_memcpy (&i6_token, tb[IFLA_INET6_TOKEN], sizeof (struct in6_addr)); - if (!IN6_IS_ADDR_UNSPECIFIED (&i6_token)) - iid_is_valid = TRUE; + token_valid = TRUE; } /* Hack to detect support addrgenmode of the kernel. We only parse @@ -852,21 +848,18 @@ _parse_af_inet6 (NMPlatform *platform, * to signal "unset". */ goto errout; } + addr_gen_mode_valid = TRUE; } success = TRUE; - if (iid_is_valid) { - out_iid->id_u8[7] = i6_token.s6_addr[15]; - out_iid->id_u8[6] = i6_token.s6_addr[14]; - out_iid->id_u8[5] = i6_token.s6_addr[13]; - out_iid->id_u8[4] = i6_token.s6_addr[12]; - out_iid->id_u8[3] = i6_token.s6_addr[11]; - out_iid->id_u8[2] = i6_token.s6_addr[10]; - out_iid->id_u8[1] = i6_token.s6_addr[9]; - out_iid->id_u8[0] = i6_token.s6_addr[8]; - *out_iid_is_valid = TRUE; + if (token_valid) { + *out_token_valid = token_valid; + nm_utils_ipv6_interface_identifier_get_from_addr (out_token, &i6_token); + } + if (addr_gen_mode_valid) { + *out_addr_gen_mode_valid = addr_gen_mode_valid; + *out_addr_gen_mode_inv = i6_addr_gen_mode_inv; } - *out_addr_gen_mode_inv = i6_addr_gen_mode_inv; errout: return success; } @@ -1441,6 +1434,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr NMPObject *lnk_data = NULL; gboolean address_complete_from_cache = TRUE; gboolean lnk_data_complete_from_cache = TRUE; + gboolean af_inet6_token_valid = FALSE; + gboolean af_inet6_addr_gen_mode_valid = FALSE; if (!nlmsg_valid_hdr (nlh, sizeof (*ifi))) return NULL; @@ -1517,9 +1512,10 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case AF_INET6: _parse_af_inet6 (platform, af_attr, - &obj->link.inet6_token.iid, - &obj->link.inet6_token.is_valid, - &obj->link.inet6_addr_gen_mode_inv); + &obj->link.inet6_token, + &af_inet6_token_valid, + &obj->link.inet6_addr_gen_mode_inv, + &af_inet6_addr_gen_mode_valid); break; } } @@ -1561,7 +1557,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr if ( completed_from_cache && ( lnk_data_complete_from_cache - || address_complete_from_cache)) { + || address_complete_from_cache + || !af_inet6_token_valid + || !af_inet6_addr_gen_mode_valid)) { _lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached); if (link_cached) { if ( lnk_data_complete_from_cache @@ -1580,6 +1578,10 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr } if (address_complete_from_cache) obj->link.addr = link_cached->link.addr; + if (!af_inet6_token_valid) + obj->link.inet6_token = link_cached->link.inet6_token; + if (!af_inet6_addr_gen_mode_valid) + obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv; } } @@ -1666,7 +1668,7 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only) } } - obj->ip_address.source = NM_IP_CONFIG_SOURCE_KERNEL; + obj->ip_address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; obj->ip_address.n_ifa_flags = tb[IFA_FLAGS] ? nla_get_u32 (tb[IFA_FLAGS]) @@ -1896,9 +1898,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only) * * This happens, because this route is not nmp_object_is_alive(). * */ - obj->ip_route.source = _NM_IP_CONFIG_SOURCE_RTM_F_CLONED; - } else - obj->ip_route.source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol); + obj->ip_route.rt_cloned = TRUE; + } + + obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol); obj_result = obj; obj = NULL; @@ -1951,7 +1954,8 @@ nmp_object_new_from_nl (NMPlatform *platform, const NMPCache *cache, struct nl_m static gboolean _nl_msg_new_link_set_afspec (struct nl_msg *msg, - int addr_gen_mode) + int addr_gen_mode, + NMUtilsIPv6IfaceId *iid) { struct nlattr *af_spec; struct nlattr *af_attr; @@ -1961,11 +1965,19 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg, if (!(af_spec = nla_nest_start (msg, IFLA_AF_SPEC))) goto nla_put_failure; - if (addr_gen_mode >= 0) { + if (addr_gen_mode >= 0 || iid) { if (!(af_attr = nla_nest_start (msg, AF_INET6))) goto nla_put_failure; - NLA_PUT_U8 (msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode); + if (addr_gen_mode >= 0) + NLA_PUT_U8 (msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode); + + if (iid) { + struct in6_addr i6_token = { .s6_addr = { 0, } }; + + nm_utils_ipv6_addr_set_interface_identifier (&i6_token, *iid); + NLA_PUT (msg, IFLA_INET6_TOKEN, sizeof (struct in6_addr), &i6_token); + } nla_nest_end (msg, af_attr); } @@ -2258,7 +2270,7 @@ _nl_msg_new_route (int nlmsg_type, .rtm_family = family, .rtm_tos = 0, .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */ - .rtm_protocol = nmp_utils_ip_config_source_to_rtprot (source), + .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source), .rtm_scope = scope, .rtm_type = RTN_UNICAST, .rtm_flags = 0, @@ -2282,7 +2294,7 @@ _nl_msg_new_route (int nlmsg_type, addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr); - clear_host_address (family, network, plen, &network_clean); + nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen); NLA_PUT (msg, RTA_DST, addr_len, &network_clean); NLA_PUT_U32 (msg, RTA_PRIORITY, metric); @@ -2485,6 +2497,7 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value) gsize len; char *actual; gs_free char *actual_free = NULL; + int errsv; g_return_val_if_fail (path != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); @@ -2495,18 +2508,22 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value) /* Don't write to suspicious locations */ g_assert (!strstr (path, "/../")); - if (!nm_platform_netns_push (platform, &netns)) + if (!nm_platform_netns_push (platform, &netns)) { + errno = ENETDOWN; return FALSE; + } fd = open (path, O_WRONLY | O_TRUNC); if (fd == -1) { - if (errno == ENOENT) { + errsv = errno; + if (errsv == ENOENT) { _LOGD ("sysctl: failed to open '%s': (%d) %s", - path, errno, strerror (errno)); + path, errsv, strerror (errsv)); } else { _LOGE ("sysctl: failed to open '%s': (%d) %s", - path, errno, strerror (errno)); + path, errsv, strerror (errsv)); } + errno = errsv; return FALSE; } @@ -2527,26 +2544,43 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value) actual[len] = '\0'; /* Try to write the entire value three times if a partial write occurs */ + errsv = 0; for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) { nwrote = write (fd, actual, len); if (nwrote == -1) { - if (errno == EINTR) { + errsv = errno; + if (errsv == EINTR) { _LOGD ("sysctl: interrupted, will try again"); continue; } break; } } - if (nwrote == -1 && errno != EEXIST) { + if (nwrote == -1 && errsv != EEXIST) { _LOGE ("sysctl: failed to set '%s' to '%s': (%d) %s", - path, value, errno, strerror (errno)); + path, value, errsv, strerror (errsv)); } else if (nwrote < len) { _LOGE ("sysctl: failed to set '%s' to '%s' after three attempts", path, value); } - close (fd); - return (nwrote == len); + if (nwrote != len) { + if (close (fd) != 0) { + if (errsv != 0) + errno = errsv; + } else if (errsv != 0) + errno = errsv; + else + errno = EIO; + return FALSE; + } + if (close (fd) != 0) { + /* errno is already properly set. */ + return FALSE; + } + + /* success. errno is undefined (no need to set). */ + return TRUE; } static GSList *sysctl_clear_cache_list; @@ -3724,6 +3758,16 @@ cache_lookup_link (NMPlatform *platform, int ifindex) return obj_cache; } +const NMPlatformObject *const* +nm_linux_platform_lookup (NMPlatform *platform, const NMPCacheId *cache_id, guint *out_len) +{ + g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), NULL); + g_return_val_if_fail (cache_id, NULL); + + return nmp_cache_lookup_multi (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, + cache_id, out_len); +} + static GArray * link_get_all (NMPlatform *platform) { @@ -4294,8 +4338,22 @@ link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enable 0, 0); if ( !nlmsg - || !_nl_msg_new_link_set_afspec (nlmsg, - mode)) + || !_nl_msg_new_link_set_afspec (nlmsg, mode, NULL)) + g_return_val_if_reached (FALSE); + + return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS; +} + +static gboolean +link_set_token (NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId iid) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + + _LOGD ("link: change %d: token: set IPv6 address generation token to %s", + ifindex, nm_utils_inet6_interface_identifier_to_token (iid, NULL)); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, NULL, 0, 0); + if (!nlmsg || !_nl_msg_new_link_set_afspec (nlmsg, -1, &iid)) g_return_val_if_reached (FALSE); return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS; @@ -5095,57 +5153,67 @@ link_release (NMPlatform *platform, int master, int slave) /******************************************************************/ static gboolean -_infiniband_partition_action (NMPlatform *platform, int parent, int p_key, const char *action, char **ifname) +_infiniband_partition_action (NMPlatform *platform, + InfinibandAction action, + int parent, + int p_key, + const NMPlatformLink **out_link) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); const NMPObject *obj_parent; - gs_free char *path = NULL; - gs_free char *id = NULL; + const NMPObject *obj; + char path[NM_STRLEN ("/sys/class/net/%s/%s") + IFNAMSIZ + 100]; + char id[20]; + char name[IFNAMSIZ]; + gboolean success; + + nm_assert (NM_IN_SET (action, INFINIBAND_ACTION_CREATE_CHILD, INFINIBAND_ACTION_DELETE_CHILD)); + nm_assert (p_key > 0 && p_key <= 0xffff && p_key != 0x8000); obj_parent = nmp_cache_lookup_link (priv->cache, parent); - if (!obj_parent || !obj_parent->link.name[0]) - g_return_val_if_reached (FALSE); + if (!obj_parent || !obj_parent->link.name[0]) { + errno = ENOENT; + return FALSE; + } - *ifname = g_strdup_printf ("%s.%04x", obj_parent->link.name, p_key); + nm_sprintf_buf (path, + "/sys/class/net/%s/%s", + NM_ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name), + (action == INFINIBAND_ACTION_CREATE_CHILD + ? "create_child" + : "delete_child")); + nm_sprintf_buf (id, "0x%04x", p_key); + success = nm_platform_sysctl_set (platform, path, id); + if (!success) { + if ( action == INFINIBAND_ACTION_DELETE_CHILD + && errno == ENODEV) + return TRUE; + return FALSE; + } - path = g_strdup_printf ("/sys/class/net/%s/%s", - NM_ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name), - action); - id = g_strdup_printf ("0x%04x", p_key); + nm_utils_new_infiniband_name (name, obj_parent->link.name, p_key); + do_request_link (platform, 0, name); - return nm_platform_sysctl_set (platform, path, id); -} + if (action == INFINIBAND_ACTION_DELETE_CHILD) + return TRUE; + obj = nmp_cache_lookup_link_full (priv->cache, 0, name, FALSE, + NM_LINK_TYPE_INFINIBAND, NULL, NULL); + if (out_link) + *out_link = obj ? &obj->link : NULL; + return !!obj; +} static gboolean infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link) { - const NMPObject *obj; - gs_free char *ifname = NULL; - - if (!_infiniband_partition_action (platform, parent, p_key, "create_child", &ifname)) - return FALSE; - - do_request_link (platform, 0, ifname); - - obj = nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, - 0, ifname, FALSE, NM_LINK_TYPE_INFINIBAND, NULL, NULL); - if (out_link) - *out_link = obj ? &obj->link : NULL; - return !!obj; + return _infiniband_partition_action (platform, INFINIBAND_ACTION_CREATE_CHILD, parent, p_key, out_link); } static gboolean infiniband_partition_delete (NMPlatform *platform, int parent, int p_key) { - gs_free char *ifname = NULL; - - if (!_infiniband_partition_action (platform, parent, p_key, "delete_child", &ifname)) { - if (errno != ENODEV) - return FALSE; - } - - return TRUE; + return _infiniband_partition_action (platform, INFINIBAND_ACTION_DELETE_CHILD, parent, p_key, NULL); } /******************************************************************/ @@ -5570,7 +5638,7 @@ ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NM nm_assert (NMP_OBJECT_GET_CLASS (NMP_OBJECT_UP_CAST (routes[i])) == klass); if ( with_rtprot_kernel - || routes[i]->source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) + || routes[i]->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) g_array_append_vals (array, routes[i], 1); } return array; @@ -6397,6 +6465,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->link_get_udev_device = link_get_udev_device; platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled; + platform_class->link_set_token = link_set_token; platform_class->link_set_address = link_set_address; platform_class->link_get_permanent_address = link_get_permanent_address; diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h index 4ae2fd1400..3b2a440e52 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/platform/nm-linux-platform.h @@ -52,4 +52,10 @@ NMPlatform *nm_linux_platform_new (gboolean netns_support); void nm_linux_platform_setup (void); +struct _NMPCacheId; + +const NMPlatformObject *const *nm_linux_platform_lookup (NMPlatform *platform, + const struct _NMPCacheId *cache_id, + guint *out_len); + #endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index b4542adf8d..068801ee69 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -144,8 +144,7 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname, struct ethtool_perm_addr e; guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1]; } edata; - static const guint8 zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 }; - static guint8 ones[NM_UTILS_HWADDR_LEN_MAX] = { 0 }; + guint i; if (!ifname) return FALSE; @@ -157,18 +156,23 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname, if (!ethtool_get (ifname, &edata.e)) return FALSE; - g_assert (edata.e.size <= NM_UTILS_HWADDR_LEN_MAX); - - /* Some drivers might return a permanent address of all zeros. - * Reject that (rh#1264024) */ - if (memcmp (edata.e.data, zeros, edata.e.size) == 0) + if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX) + return FALSE; + if (edata.e.size < 1) return FALSE; - /* Some drivers return a permanent address of all ones. Reject that too */ - if (G_UNLIKELY (ones[0] != 0xFF)) - memset (ones, 0xFF, sizeof (ones)); - if (memcmp (edata.e.data, ones, edata.e.size) == 0) + if (NM_IN_SET (edata.e.data[0], 0, 0xFF)) { + /* Some drivers might return a permanent address of all zeros. + * Reject that (rh#1264024) + * + * Some drivers return a permanent address of all ones. Reject that too */ + for (i = 1; i < edata.e.size; i++) { + if (edata.e.data[0] != edata.e.data[i]) + goto not_all_0or1; + } return FALSE; + } +not_all_0or1: memcpy (buf, edata.e.data, edata.e.size); *length = edata.e.size; @@ -433,14 +437,35 @@ nmp_utils_device_exists (const char *name) return g_file_test (sysdir, G_FILE_TEST_EXISTS); } -guint -nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source) +NMIPConfigSource +nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) { - switch (source) { - case NM_IP_CONFIG_SOURCE_UNKNOWN: + return ((int) rtprot) + 1; +} + +NMIPConfigSource +nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) +{ + /* when adding a route to kernel for a give @source, the resulting route + * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*. + * This function returns that. */ + return nmp_utils_ip_config_source_from_rtprot (nmp_utils_ip_config_source_coerce_to_rtprot (source)); +} + +guint8 +nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) +{ + /* when adding a route to kernel, we coerce the @source field + * to rtm_protocol. This is not lossless as we map different + * source values to the same RTPROT uint8 value. */ + if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN) return RTPROT_UNSPEC; + + if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST) + return source - 1; + + switch (source) { case NM_IP_CONFIG_SOURCE_KERNEL: - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: return RTPROT_KERNEL; case NM_IP_CONFIG_SOURCE_DHCP: return RTPROT_DHCP; @@ -453,18 +478,32 @@ nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source) } NMIPConfigSource -nmp_utils_ip_config_source_from_rtprot (guint rtprot) +nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source) { - switch (rtprot) { - case RTPROT_UNSPEC: + /* When we receive a route from kernel and put it into the platform cache, + * we preserve the protocol field by converting it to a NMIPConfigSource + * via nmp_utils_ip_config_source_from_rtprot(). + * + * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot(). + * Instead, to go back to the original value, you need another step: + * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)). + * + * This might partly restore the original source value, but of course that + * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot() + * is not injective. + * */ + switch (source) { + case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: return NM_IP_CONFIG_SOURCE_UNKNOWN; - case RTPROT_KERNEL: - return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL; - case RTPROT_REDIRECT: + + case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: + case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: return NM_IP_CONFIG_SOURCE_KERNEL; - case RTPROT_RA: + + case NM_IP_CONFIG_SOURCE_RTPROT_RA: return NM_IP_CONFIG_SOURCE_RDISC; - case RTPROT_DHCP: + + case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: return NM_IP_CONFIG_SOURCE_DHCP; default: @@ -472,3 +511,50 @@ nmp_utils_ip_config_source_from_rtprot (guint rtprot) } } +const char * +nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len) +{ + const char *s = NULL; + nm_utils_to_string_buffer_init (&buf, &len); \ + + if (!len) + return buf; + + switch (source) { + case NM_IP_CONFIG_SOURCE_UNKNOWN: s = "unknown"; break; + + case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: s = "rt-unspec"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: s = "rt-redirect"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: s = "rt-kernel"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_BOOT: s = "rt-boot"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_STATIC: s = "rt-static"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: s = "rt-dhcp"; break; + case NM_IP_CONFIG_SOURCE_RTPROT_RA: s = "rt-ra"; break; + + case NM_IP_CONFIG_SOURCE_KERNEL: s = "kernel"; break; + case NM_IP_CONFIG_SOURCE_SHARED: s = "shared"; break; + case NM_IP_CONFIG_SOURCE_IP4LL: s = "ipv4ll"; break; + case NM_IP_CONFIG_SOURCE_PPP: s = "ppp"; break; + case NM_IP_CONFIG_SOURCE_WWAN: s = "wwan"; break; + case NM_IP_CONFIG_SOURCE_VPN: s = "vpn"; break; + case NM_IP_CONFIG_SOURCE_DHCP: s = "dhcp"; break; + case NM_IP_CONFIG_SOURCE_RDISC: s = "rdisc"; break; + case NM_IP_CONFIG_SOURCE_USER: s = "user"; break; + default: + break; + } + + if (source >= 1 && source <= 0x100) { + if (s) + g_snprintf (buf, len, "%s", s); + else + g_snprintf (buf, len, "rt-%d", ((int) source) - 1); + } else { + if (s) + g_strlcpy (buf, s, len); + else + g_snprintf (buf, len, "(%d)", source); + } + return buf; +} + diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h index f259474719..456c08652d 100644 --- a/src/platform/nm-platform-utils.h +++ b/src/platform/nm-platform-utils.h @@ -54,7 +54,10 @@ const char *nmp_utils_udev_get_driver (GUdevDevice *device); gboolean nmp_utils_device_exists (const char *name); -guint nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source); -NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint rtprot); +NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) _nm_const; +guint8 nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) _nm_const; +NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source) _nm_const; +NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) _nm_const; +const char * nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len); #endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 26ac766d63..a6afcf33a9 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -387,6 +387,20 @@ nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *path, guint ba /******************************************************************/ +static int +_link_get_all_presort (gconstpointer p_a, + gconstpointer p_b) +{ + const NMPlatformLink *a = p_a; + const NMPlatformLink *b = p_b; + + if (a->ifindex < b->ifindex) + return -1; + if (a->ifindex > b->ifindex) + return 1; + return 0; +} + /** * nm_platform_link_get_all: * self: platform instance @@ -409,15 +423,17 @@ nm_platform_link_get_all (NMPlatform *self) if (!links || links->len == 0) return links; + /* first sort the links by their ifindex. Below we will sort further by moving + * children/slaves to the end. */ + g_array_sort (links, _link_get_all_presort); + unseen = g_hash_table_new (g_direct_hash, g_direct_equal); for (i = 0; i < links->len; i++) { item = &g_array_index (links, NMPlatformLink, i); - _LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item, NULL, 0)); - - nm_assert (item->ifindex > 0 && !g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))); - - g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL); + nm_assert (item->ifindex > 0); + if (!nm_g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL)) + nm_assert_not_reached (); } #ifndef G_DISABLE_ASSERT @@ -468,8 +484,6 @@ nm_platform_link_get_all (NMPlatform *self) if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent))) continue; - _LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item, NULL, 0)); - g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; item->ifindex = 0; @@ -481,8 +495,6 @@ nm_platform_link_get_all (NMPlatform *self) * This can happen for veth pairs where each peer is parent of the other end. */ item = &g_array_index (links, NMPlatformLink, first_idx); - _LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item, NULL, 0)); - g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex)); g_array_index (result, NMPlatformLink, j++) = *item; item->ifindex = 0; @@ -888,33 +900,25 @@ nm_platform_link_uses_arp (NMPlatform *self, int ifindex) } /** - * nm_platform_link_get_ipv6_token: + * nm_platform_link_set_ipv6_token: * @self: platform instance * @ifindex: Interface index * @iid: Tokenized interface identifier * - * Returns IPv6 tokenized interface identifier. If the platform or OS doesn't - * support IPv6 tokenized interface identifiers, or the token is not set - * this call will fail and return %FALSE. + * Sets then IPv6 tokenized interface identifier. * * Returns: %TRUE a tokenized identifier was available */ gboolean -nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid) +nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid) { - const NMPlatformLink *pllink; - _CHECK_SELF (self, klass, FALSE); g_return_val_if_fail (ifindex >= 0, FALSE); - g_return_val_if_fail (iid, FALSE); - + g_return_val_if_fail (iid.id, FALSE); - pllink = nm_platform_link_get (self, ifindex); - if (pllink && pllink->inet6_token.is_valid) { - *iid = pllink->inet6_token.iid; - return TRUE; - } + if (klass->link_set_token) + return klass->link_set_token (self, ifindex, iid); return FALSE; } @@ -1895,21 +1899,27 @@ _infiniband_add_add_or_delete (NMPlatform *self, gboolean add, const NMPlatformLink **out_link) { - gs_free char *parent_name = NULL; - gs_free char *name = NULL; + char name[IFNAMSIZ]; + const NMPlatformLink *parent_link; NMPlatformError plerr; _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); g_return_val_if_fail (parent >= 0, NM_PLATFORM_ERROR_BUG); - g_return_val_if_fail (p_key >= 0, NM_PLATFORM_ERROR_BUG); + g_return_val_if_fail (p_key >= 0 && p_key <= 0xffff, NM_PLATFORM_ERROR_BUG); + + /* the special keys 0x0000 and 0x8000 are not allowed. */ + if (NM_IN_SET (p_key, 0, 0x8000)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + + parent_link = nm_platform_link_get (self, parent); + if (!parent_link) + return NM_PLATFORM_ERROR_NOT_FOUND; - parent_name = g_strdup (nm_platform_link_get_name (self, parent)); - if ( !parent_name - || nm_platform_link_get_type (self, parent) != NM_LINK_TYPE_INFINIBAND) + if (parent_link->type != NM_LINK_TYPE_INFINIBAND) return NM_PLATFORM_ERROR_WRONG_TYPE; - name = g_strdup_printf ("%s.%04x", parent_name, p_key); + nm_utils_new_infiniband_name (name, parent_link->name, p_key); if (add) { plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_INFINIBAND, out_link); @@ -1917,7 +1927,7 @@ _infiniband_add_add_or_delete (NMPlatform *self, return plerr; _LOGD ("link: adding infiniband partition %s for parent '%s' (%d), key %d", - name, parent_name, parent, p_key); + name, parent_link->name, parent, p_key); if (!klass->infiniband_partition_add (self, parent, p_key, out_link)) return NM_PLATFORM_ERROR_UNSPECIFIED; } else { @@ -2894,7 +2904,7 @@ nm_platform_ip4_route_add (NMPlatform *self, NMPlatformIP4Route route = { 0 }; route.ifindex = ifindex; - route.source = source; + route.rt_source = source; route.network = network; route.plen = plen; route.gateway = gateway; @@ -2921,7 +2931,7 @@ nm_platform_ip6_route_add (NMPlatform *self, NMPlatformIP6Route route = { 0 }; route.ifindex = ifindex; - route.source = source; + route.rt_source = source; route.network = network; route.plen = plen; route.gateway = gateway; @@ -3012,38 +3022,6 @@ nm_platform_vlan_qos_mapping_to_string (const char *name, } static const char * -source_to_string (NMIPConfigSource source) -{ - switch (source) { - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: - return "rtprot-kernel"; - case _NM_IP_CONFIG_SOURCE_RTM_F_CLONED: - return "rtm-f-cloned"; - case NM_IP_CONFIG_SOURCE_KERNEL: - return "kernel"; - case NM_IP_CONFIG_SOURCE_SHARED: - return "shared"; - case NM_IP_CONFIG_SOURCE_IP4LL: - return "ipv4ll"; - case NM_IP_CONFIG_SOURCE_PPP: - return "ppp"; - case NM_IP_CONFIG_SOURCE_WWAN: - return "wwan"; - case NM_IP_CONFIG_SOURCE_VPN: - return "vpn"; - case NM_IP_CONFIG_SOURCE_DHCP: - return "dhcp"; - case NM_IP_CONFIG_SOURCE_RDISC: - return "rdisc"; - case NM_IP_CONFIG_SOURCE_USER: - return "user"; - default: - break; - } - return "unknown"; -} - -static const char * _lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size) { if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT) @@ -3081,7 +3059,7 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) GString *str_flags; char str_addrmode[30]; gs_free char *str_addr = NULL; - gs_free char *str_inet6_token = NULL; + char str_inet6_token[NM_UTILS_INET_ADDRSTRLEN]; const char *str_link_type; if (!nm_utils_to_string_buffer_init_null (link, &buf, &len)) @@ -3118,8 +3096,6 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) if (link->addr.len) str_addr = nm_utils_hwaddr_ntoa (link->addr.data, MIN (link->addr.len, sizeof (link->addr.data))); - if (link->inet6_token.is_valid) - str_inet6_token = nm_utils_hwaddr_ntoa (&link->inet6_token.iid, sizeof (link->inet6_token.iid)); str_link_type = nm_link_type_to_string (link->type); @@ -3153,8 +3129,8 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv), str_addrmode, sizeof (str_addrmode)) : "", str_addr ? " addr " : "", str_addr ? str_addr : "", - str_inet6_token ? " inet6token " : "", - str_inet6_token ? str_inet6_token : "", + link->inet6_token.id ? " inet6token " : "", + link->inet6_token.id ? nm_utils_inet6_interface_identifier_to_token (link->inet6_token, str_inet6_token) : "", link->driver ? " driver " : "", link->driver ? link->driver : ""); g_string_free (str_flags, TRUE); @@ -3471,7 +3447,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu char s_peer[INET_ADDRSTRLEN]; char str_dev[TO_STRING_DEV_BUF_SIZE]; char str_label[32]; - char str_lft[30], str_pref[30], str_time[50]; + char str_lft[30], str_pref[30], str_time[50], s_source[50]; char *str_peer = NULL; const char *str_lft_p, *str_pref_p, *str_time_p; gint32 now = nm_utils_get_monotonic_timestamp_s (); @@ -3510,7 +3486,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu str_dev, _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), str_label, - source_to_string (address->source)); + nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source))); g_free (str_peer); return buf; } @@ -3582,7 +3558,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE]; char s_address[INET6_ADDRSTRLEN]; char s_peer[INET6_ADDRSTRLEN]; - char str_lft[30], str_pref[30], str_time[50]; + char str_lft[30], str_pref[30], str_time[50], s_source[50]; char str_dev[TO_STRING_DEV_BUF_SIZE]; char *str_peer = NULL; const char *str_lft_p, *str_pref_p, *str_time_p; @@ -3616,7 +3592,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu str_peer ? str_peer : "", str_dev, _to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)), - source_to_string (address->source)); + nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source))); g_free (str_peer); return buf; } @@ -3639,7 +3615,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN]; char s_pref_src[INET_ADDRSTRLEN]; char str_dev[TO_STRING_DEV_BUF_SIZE]; - char str_scope[30]; + char str_scope[30], s_source[50]; if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) return buf; @@ -3656,6 +3632,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi " metric %"G_GUINT32_FORMAT " mss %"G_GUINT32_FORMAT " src %s" /* source */ + "%s" /* cloned */ "%s%s" /* scope */ "%s%s" /* pref-src */ "", @@ -3665,7 +3642,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi str_dev, route->metric, route->mss, - source_to_string (route->source), + nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), + route->rt_cloned ? " cloned" : "", route->scope_inv ? " scope " : "", route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "", route->pref_src ? " pref-src " : "", @@ -3689,7 +3667,7 @@ const char * nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len) { char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN]; - char str_dev[TO_STRING_DEV_BUF_SIZE]; + char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50]; if (!nm_utils_to_string_buffer_init_null (route, &buf, &len)) return buf; @@ -3706,6 +3684,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi " metric %"G_GUINT32_FORMAT " mss %"G_GUINT32_FORMAT " src %s" /* source */ + "%s" /* cloned */ "", s_network, route->plen, @@ -3713,7 +3692,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi str_dev, route->metric, route->mss, - source_to_string (route->source)); + nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)), + route->rt_cloned ? " cloned" : ""); return buf; } @@ -3808,13 +3788,11 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) _CMP_FIELD (a, b, arptype); _CMP_FIELD (a, b, addr.len); _CMP_FIELD (a, b, inet6_addr_gen_mode_inv); - _CMP_FIELD (a, b, inet6_token.is_valid); _CMP_FIELD_STR_INTERNED (a, b, kind); _CMP_FIELD_STR_INTERNED (a, b, driver); if (a->addr.len) _CMP_FIELD_MEMCMP_LEN (a, b, addr.data, a->addr.len); - if (a->inet6_token.is_valid) - _CMP_FIELD_MEMCMP (a, b, inet6_token.iid); + _CMP_FIELD_MEMCMP (a, b, inet6_token); return 0; } @@ -3935,10 +3913,10 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A { _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); - _CMP_FIELD (a, b, source); _CMP_FIELD (a, b, address); _CMP_FIELD (a, b, plen); _CMP_FIELD (a, b, peer_address); + _CMP_FIELD (a, b, addr_source); _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); _CMP_FIELD (a, b, preferred); @@ -3954,14 +3932,12 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); - _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, address); - + _CMP_FIELD (a, b, plen); p_a = nm_platform_ip6_address_get_peer (a); p_b = nm_platform_ip6_address_get_peer (b); _CMP_DIRECT_MEMCMP (p_a, p_b, sizeof (*p_a)); - - _CMP_FIELD (a, b, plen); + _CMP_FIELD (a, b, addr_source); _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); _CMP_FIELD (a, b, preferred); @@ -3974,14 +3950,15 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route { _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); - _CMP_FIELD (a, b, source); _CMP_FIELD (a, b, network); _CMP_FIELD (a, b, plen); - _CMP_FIELD (a, b, gateway); _CMP_FIELD (a, b, metric); + _CMP_FIELD (a, b, gateway); + _CMP_FIELD (a, b, rt_source); _CMP_FIELD (a, b, mss); _CMP_FIELD (a, b, scope_inv); _CMP_FIELD (a, b, pref_src); + _CMP_FIELD (a, b, rt_cloned); return 0; } @@ -3990,12 +3967,13 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route { _CMP_SELF (a, b); _CMP_FIELD (a, b, ifindex); - _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, network); _CMP_FIELD (a, b, plen); - _CMP_FIELD_MEMCMP (a, b, gateway); _CMP_FIELD (a, b, metric); + _CMP_FIELD_MEMCMP (a, b, gateway); + _CMP_FIELD (a, b, rt_source); _CMP_FIELD (a, b, mss); + _CMP_FIELD (a, b, rt_cloned); return 0; } @@ -4128,7 +4106,7 @@ _vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout { return nm_platform_ip4_route_add (self, ifindex > 0 ? ifindex : route->rx.ifindex, - route->rx.source, + route->rx.rt_source, route->r4.network, route->rx.plen, route->r4.gateway, @@ -4142,7 +4120,7 @@ _vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout { return nm_platform_ip6_route_add (self, ifindex > 0 ? ifindex : route->rx.ifindex, - route->rx.source, + route->rx.rt_source, route->r6.network, route->rx.plen, route->r6.gateway, diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 19724f1c19..72f4f6720a 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -49,8 +49,6 @@ /******************************************************************/ -typedef struct _NMPlatform NMPlatform; - /* workaround for older libnl version, that does not define these flags. */ #ifndef IFA_F_MANAGETEMPADDR #define IFA_F_MANAGETEMPADDR 0x100 @@ -98,6 +96,11 @@ typedef struct { guint8 addr_ptr[1]; in_addr_t addr4; struct in6_addr addr6; + + /* NMIPAddr is really a union for IP addresses. + * However, as ethernet addresses fit in here nicely, ruse + * it also for an ethernet MAC address. */ + guint8 addr_eth[6 /*ETH_ALEN*/]; }; } NMIPAddr; @@ -144,11 +147,8 @@ struct _NMPlatformLink { guint8 len; } addr; - /* rtnl_link_inet6_get_token() */ - struct { - NMUtilsIPv6IfaceId iid; - guint8 is_valid; - } inet6_token; + /* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */ + NMUtilsIPv6IfaceId inet6_token; /* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse * to have a default of 0 -- meaning: unspecified. That way, a struct @@ -200,7 +200,7 @@ typedef struct { #define __NMPlatformIPAddress_COMMON \ __NMPlatformObject_COMMON; \ - NMIPConfigSource source; \ + NMIPConfigSource addr_source; \ \ /* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*(). * @@ -303,8 +303,21 @@ typedef union { #define __NMPlatformIPRoute_COMMON \ __NMPlatformObject_COMMON; \ - NMIPConfigSource source; \ + \ + /* The NMIPConfigSource. For routes that we receive from cache this corresponds + * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values). + * When adding a route, the source will be coerced to the protocol using + * nmp_utils_ip_config_source_coerce_to_rtprot(). */ \ + NMIPConfigSource rt_source; \ + \ guint8 plen; \ + \ + /* the route has rtm_flags set to RTM_F_CLONED. Such a route + * is hidden by platform and does not exist from the point-of-view + * of platform users. This flag is internal to track those hidden + * routes. Such a route is not alive, according to nmp_object_is_alive(). */ \ + bool rt_cloned:1; \ + \ guint32 metric; \ guint32 mss; \ ; @@ -507,6 +520,7 @@ typedef struct { GObject *(*link_get_udev_device) (NMPlatform *self, int ifindex); gboolean (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled); + gboolean (*link_set_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId iid); gboolean (*link_get_permanent_address) (NMPlatform *, int ifindex, @@ -717,7 +731,6 @@ gboolean nm_platform_link_is_up (NMPlatform *self, int ifindex); gboolean nm_platform_link_is_connected (NMPlatform *self, int ifindex); gboolean nm_platform_link_uses_arp (NMPlatform *self, int ifindex); guint32 nm_platform_link_get_mtu (NMPlatform *self, int ifindex); -gboolean nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid); gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex); gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length); int nm_platform_link_get_master (NMPlatform *self, int slave); @@ -741,6 +754,7 @@ const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex); GObject *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex); gboolean nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled); +gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid); gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length); gboolean nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index eb7e1ca401..55ffd7cffb 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -915,12 +915,12 @@ _vt_cmd_obj_is_alive_ipx_route (const NMPObject *obj) * * If nmp_object_from_nl() would just return NULL, we couldn't look * into the cache to see if it contains a route that now disappears - * (because it is cloned). + * (because it changed to be cloned). * * Instead we create a dead object, and nmp_cache_update_netlink() * will remove the old version of the update. **/ - return obj->object.ifindex > 0 && (obj->ip_route.source != _NM_IP_CONFIG_SOURCE_RTM_F_CLONED); + return obj->object.ifindex > 0 && !obj->ip_route.rt_cloned; } gboolean diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index c5241037d5..d295f7a078 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -94,9 +94,9 @@ typedef enum { /*< skip >*/ NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1, } NMPCacheIdType; -typedef struct _NMPObject NMPObject; +typedef struct _NMPCacheId NMPCacheId; -typedef struct { +struct _NMPCacheId { union { NMMultiIndexId base; guint8 _id_type; /* NMPCacheIdType as guint8 */ @@ -136,7 +136,7 @@ typedef struct { struct in6_addr _misaligned_network; } routes_by_destination_ip6; }; -} NMPCacheId; +}; extern NMPCacheId _nmp_cache_id_static; #define NMP_CACHE_ID_STATIC (&_nmp_cache_id_static) diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c index 3af34be42c..937eea1154 100644 --- a/src/platform/tests/monitor.c +++ b/src/platform/tests/monitor.c @@ -25,7 +25,7 @@ #include "nm-linux-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" NMTST_DEFINE (); diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 0e3cf10ba4..143b9b5272 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -8,7 +8,7 @@ #include "nm-fake-platform.h" #include "nm-linux-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #define DEVICE_NAME "nm-test-device" diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c index d8d925614b..f67f00892f 100644 --- a/src/platform/tests/test-general.c +++ b/src/platform/tests/test-general.c @@ -25,7 +25,7 @@ #include "nm-platform-utils.h" #include "nm-linux-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /******************************************************************/ diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 9d548aabdb..db8ad5a2e1 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -30,7 +30,7 @@ #include "nm-platform-utils.h" #include "test-common.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #define LO_INDEX 1 #define LO_NAME "lo" @@ -1861,7 +1861,7 @@ _test_netns_setup (gpointer fixture, gconstpointer test_data) { /* the singleton platform instance has netns support disabled. * Destroy the instance before the test and re-create it afterwards. */ - g_object_unref (nm_platform_get ()); + g_object_unref (NM_PLATFORM_GET); } static void diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index d77170b364..9d4f69de4c 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -22,7 +22,7 @@ #include "nmp-object.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" struct { GList *udev_devices; diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index a50392a66f..360404e944 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -23,9 +23,9 @@ #include <linux/rtnetlink.h> #include "nm-core-utils.h" -#include "test-common.h" +#include "nm-platform-utils.h" -#include "nm-test-utils.h" +#include "test-common.h" #define DEVICE_NAME "nm-test-device" @@ -178,7 +178,7 @@ test_ip4_route (void) /* Test route listing */ routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); memset (rts, 0, sizeof (rts)); - rts[0].source = NM_IP_CONFIG_SOURCE_USER; + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[0].network = gateway; rts[0].plen = 32; rts[0].ifindex = ifindex; @@ -186,7 +186,7 @@ test_ip4_route (void) rts[0].metric = metric; rts[0].mss = mss; rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK); - rts[1].source = NM_IP_CONFIG_SOURCE_USER; + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; @@ -194,7 +194,7 @@ test_ip4_route (void) rts[1].metric = metric; rts[1].mss = mss; rts[1].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE); - rts[2].source = NM_IP_CONFIG_SOURCE_USER; + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[2].network = 0; rts[2].plen = 0; rts[2].ifindex = ifindex; @@ -265,21 +265,21 @@ test_ip6_route (void) /* Test route listing */ routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); memset (rts, 0, sizeof (rts)); - rts[0].source = NM_IP_CONFIG_SOURCE_USER; + rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[0].network = gateway; rts[0].plen = 128; rts[0].ifindex = ifindex; rts[0].gateway = in6addr_any; rts[0].metric = nm_utils_ip6_route_metric_normalize (metric); rts[0].mss = mss; - rts[1].source = NM_IP_CONFIG_SOURCE_USER; + rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; rts[1].gateway = gateway; rts[1].metric = nm_utils_ip6_route_metric_normalize (metric); rts[1].mss = mss; - rts[2].source = NM_IP_CONFIG_SOURCE_USER; + rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[2].network = in6addr_any; rts[2].plen = 0; rts[2].ifindex = ifindex; diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c index 38e5a0545e..9b981f3b38 100644 --- a/src/platform/wifi/wifi-utils.c +++ b/src/platform/wifi/wifi-utils.c @@ -21,16 +21,18 @@ #include "nm-default.h" +#include "wifi-utils.h" + #include <sys/stat.h> #include <stdio.h> #include <string.h> -#include "wifi-utils.h" #include "wifi-utils-private.h" #include "wifi-utils-nl80211.h" #if HAVE_WEXT #include "wifi-utils-wext.h" #endif +#include "nm-core-utils.h" gpointer wifi_data_new (const char *iface, int ifindex, gsize len) @@ -162,19 +164,20 @@ wifi_utils_deinit (WifiData *data) } gboolean -wifi_utils_is_wifi (const char *iface, const char *sysfs_path) +wifi_utils_is_wifi (const char *iface) { - char phy80211_path[255]; + char phy80211_path[NM_STRLEN ("/sys/class/net/123456789012345/phy80211\0") + 100 /*safety*/]; struct stat s; g_return_val_if_fail (iface != NULL, FALSE); - if (sysfs_path) { - /* Check for nl80211 sysfs paths */ - g_snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", sysfs_path); - if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR))) - return TRUE; - } + nm_sprintf_buf (phy80211_path, + "/sys/class/net/%s/phy80211", + NM_ASSERT_VALID_PATH_COMPONENT (iface)); + nm_assert (strlen (phy80211_path) < sizeof (phy80211_path) - 1); + + if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR))) + return TRUE; #if HAVE_WEXT if (wifi_wext_is_wifi (iface)) diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h index 21dac9e9cc..f0a5a7e7f1 100644 --- a/src/platform/wifi/wifi-utils.h +++ b/src/platform/wifi/wifi-utils.h @@ -29,7 +29,7 @@ typedef struct WifiData WifiData; -gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path); +gboolean wifi_utils_is_wifi (const char *iface); WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan); diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 89a7addf84..a51f7cfa6c 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -482,7 +482,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, address.plen = u32; if (address.address && address.plen && address.plen <= 32) { - address.source = NM_IP_CONFIG_SOURCE_PPP; + address.addr_source = NM_IP_CONFIG_SOURCE_PPP; nm_ip4_config_add_address (config, &address); } else { _LOGE ("invalid IPv4 address received!"); @@ -540,7 +540,7 @@ iid_value_to_ll6_addr (GVariant *dict, out_addr->s6_addr16[0] = htons (0xfe80); memcpy (out_addr->s6_addr + 8, &iid, sizeof (iid)); if (out_iid) - nm_utils_ipv6_interface_identfier_get_from_addr (out_iid, out_addr); + nm_utils_ipv6_interface_identifier_get_from_addr (out_iid, out_addr); return TRUE; } @@ -1028,7 +1028,7 @@ nm_ppp_manager_start (NMPPPManager *manager, NMPPPManagerPrivate *priv; NMConnection *connection; NMSettingPpp *s_ppp; - gboolean s_ppp_created = FALSE; + gs_unref_object NMSettingPpp *s_ppp_free = NULL; NMSettingPppoe *pppoe_setting; NMSettingAdsl *adsl_setting; NMCmdLine *ppp_cmd; @@ -1056,24 +1056,21 @@ nm_ppp_manager_start (NMPPPManager *manager, nm_utils_modprobe (NULL, FALSE, "ppp_generic", NULL); connection = nm_act_request_get_applied_connection (req); - g_assert (connection); + g_return_val_if_fail (connection, FALSE); s_ppp = nm_connection_get_setting_ppp (connection); if (!s_ppp) { /* If the PPP settings are all default we may not have a PPP setting yet, * so just make a default one here. */ - s_ppp = NM_SETTING_PPP (nm_setting_ppp_new ()); - s_ppp_created = TRUE; + s_ppp = s_ppp_free = NM_SETTING_PPP (nm_setting_ppp_new ()); } - + pppoe_setting = nm_connection_get_setting_pppoe (connection); if (pppoe_setting) { /* We can't modify the applied connection's setting, make a copy */ - if (!s_ppp_created) { - s_ppp = NM_SETTING_PPP (nm_setting_duplicate ((NMSetting *) s_ppp)); - s_ppp_created = TRUE; - } + if (!s_ppp_free) + s_ppp = s_ppp_free = NM_SETTING_PPP (nm_setting_duplicate ((NMSetting *) s_ppp)); pppoe_fill_defaults (s_ppp); } @@ -1106,9 +1103,6 @@ nm_ppp_manager_start (NMPPPManager *manager, priv->act_req = g_object_ref (req); out: - if (s_ppp_created) - g_object_unref (s_ppp); - if (ppp_cmd) nm_cmd_line_destroy (ppp_cmd); diff --git a/src/ppp-manager/nm-pppd-plugin.c b/src/ppp-manager/nm-pppd-plugin.c index 4c16f1f0f1..9c47c339a3 100644 --- a/src/ppp-manager/nm-pppd-plugin.c +++ b/src/ppp-manager/nm-pppd-plugin.c @@ -19,7 +19,7 @@ * Copyright (C) 2008 Red Hat, Inc. */ -#include "config.h" +#include <config.h> #define ___CONFIG_H__ #include <string.h> diff --git a/src/rdisc/nm-rdisc.c b/src/rdisc/nm-rdisc.c index 12e3962b0d..85c803dc79 100644 --- a/src/rdisc/nm-rdisc.c +++ b/src/rdisc/nm-rdisc.c @@ -161,7 +161,7 @@ complete_address (NMRDisc *rdisc, NMRDiscAddress *addr) if (addr->address.s6_addr32[2] == 0x0 && addr->address.s6_addr32[3] == 0x0) { _LOGD ("complete-address: adding an EUI-64 address"); - nm_utils_ipv6_addr_set_interface_identfier (&addr->address, rdisc->iid); + nm_utils_ipv6_addr_set_interface_identifier (&addr->address, rdisc->iid); return TRUE; } diff --git a/src/rdisc/tests/test-rdisc-fake.c b/src/rdisc/tests/test-rdisc-fake.c index 1c514b9042..dec698d6bf 100644 --- a/src/rdisc/tests/test-rdisc-fake.c +++ b/src/rdisc/tests/test-rdisc-fake.c @@ -28,7 +28,7 @@ #include "nm-fake-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static NMFakeRDisc * rdisc_new (void) diff --git a/src/rdisc/tests/test-rdisc-linux.c b/src/rdisc/tests/test-rdisc-linux.c index e22eb1ade1..c3eadf4eab 100644 --- a/src/rdisc/tests/test-rdisc-linux.c +++ b/src/rdisc/tests/test-rdisc-linux.c @@ -28,7 +28,7 @@ #include "nm-linux-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" NMTST_DEFINE (); diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 26d1be63cb..ebcf17f888 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -91,7 +91,7 @@ typedef struct { NMAgentManager *agent_mgr; NMSessionMonitor *session_monitor; - guint session_changed_id; + gulong session_changed_id; NMSettingsConnectionFlags flags; gboolean ready; @@ -1527,6 +1527,7 @@ typedef struct { NMAuthSubject *subject; NMConnection *new_settings; gboolean save_to_disk; + char *audit_args; } UpdateInfo; typedef struct { @@ -1598,12 +1599,13 @@ update_complete (NMSettingsConnection *self, else g_dbus_method_invocation_return_value (info->context, NULL); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, self, !error, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, self, !error, info->audit_args, info->subject, error ? error->message : NULL); g_clear_object (&info->subject); g_clear_object (&info->agent_mgr); g_clear_object (&info->new_settings); + g_free (info->audit_args); memset (info, 0, sizeof (*info)); g_free (info); } @@ -1635,6 +1637,49 @@ con_update_cb (NMSettingsConnection *self, update_complete (self, info, error); } +static char * +con_list_changed_props (NMConnection *old, NMConnection *new) +{ + gs_unref_hashtable GHashTable *diff = NULL; + GHashTable *setting_diff; + char *setting_name, *prop_name; + GHashTableIter iter, iter2; + gboolean same; + GString *str; + + same = nm_connection_diff (old, new, + NM_SETTING_COMPARE_FLAG_EXACT | + NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, + &diff); + + if (same || !diff) + return NULL; + + str = g_string_sized_new (32); + g_hash_table_iter_init (&iter, diff); + + while (g_hash_table_iter_next (&iter, + (gpointer *) &setting_name, + (gpointer *) &setting_diff)) { + if (!setting_diff) + continue; + + g_hash_table_iter_init (&iter2, setting_diff); + + while (g_hash_table_iter_next (&iter2, (gpointer *) &prop_name, NULL)) { + g_string_append (str, setting_name); + g_string_append_c (str, '.'); + g_string_append (str, prop_name); + g_string_append_c (str, ','); + } + } + + if (str->len) + str->str[str->len - 1] = '\0'; + + return g_string_free (str, FALSE); +} + static void update_auth_cb (NMSettingsConnection *self, GDBusMethodInvocation *context, @@ -1664,6 +1709,9 @@ update_auth_cb (NMSettingsConnection *self, update_agent_secrets_cache (self, info->new_settings); } + if (nm_audit_manager_audit_enabled (nm_audit_manager_get ())) + info->audit_args = con_list_changed_props (NM_CONNECTION (self), info->new_settings); + if (info->save_to_disk) { nm_settings_connection_replace_and_commit (self, info->new_settings, @@ -1767,7 +1815,7 @@ settings_connection_update_helper (NMSettingsConnection *self, return; error: - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, self, FALSE, subject, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_UPDATE, self, FALSE, NULL, subject, error->message); g_clear_object (&tmp); @@ -1816,7 +1864,7 @@ con_delete_cb (NMSettingsConnection *self, g_dbus_method_invocation_return_value (info->context, NULL); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, self, - !error, info->subject, error ? error->message : NULL); + !error, NULL, info->subject, error ? error->message : NULL); g_free (info); } @@ -1830,7 +1878,7 @@ delete_auth_cb (NMSettingsConnection *self, CallbackInfo *info; if (error) { - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, self, FALSE, subject, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, self, FALSE, NULL, subject, error->message); g_dbus_method_invocation_return_gerror (context, error); return; @@ -1879,7 +1927,7 @@ impl_settings_connection_delete (NMSettingsConnection *self, return; out_err: - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, self, FALSE, subject, error->message); + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_DELETE, self, FALSE, NULL, subject, error->message); g_dbus_method_invocation_take_error (context, error); } @@ -1972,7 +2020,7 @@ clear_secrets_cb (NMSettingsConnection *self, g_dbus_method_invocation_return_value (info->context, NULL); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, self, - !error, info->subject, error ? error->message : NULL); + !error, NULL, info->subject, error ? error->message : NULL); g_free (info); } @@ -1989,7 +2037,7 @@ dbus_clear_secrets_auth_cb (NMSettingsConnection *self, if (error) { g_dbus_method_invocation_return_gerror (context, error); nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, self, - FALSE, subject, error->message); + FALSE, NULL, subject, error->message); } else { /* Clear secrets in connection and caches */ nm_connection_clear_secrets (NM_CONNECTION (self)); @@ -2029,7 +2077,7 @@ impl_settings_connection_clear_secrets (NMSettingsConnection *self, g_object_unref (subject); } else { nm_audit_log_connection_op (NM_AUDIT_OP_CONN_CLEAR_SECRETS, self, - FALSE, NULL, error->message); + FALSE, NULL, NULL, error->message); g_dbus_method_invocation_take_error (context, error); } } @@ -2565,7 +2613,9 @@ nm_settings_connection_init (NMSettingsConnection *self) priv->ready = TRUE; priv->session_monitor = g_object_ref (nm_session_monitor_get ()); - priv->session_changed_id = nm_session_monitor_connect (priv->session_monitor, session_changed_cb, self); + priv->session_changed_id = g_signal_connect (priv->session_monitor, + NM_SESSION_MONITOR_CHANGED, + G_CALLBACK (session_changed_cb), self); priv->agent_mgr = g_object_ref (nm_agent_manager_get ()); @@ -2625,11 +2675,9 @@ dispose (GObject *object) set_visible (self, FALSE); - if (priv->session_monitor) { - nm_session_monitor_disconnect (priv->session_monitor, priv->session_changed_id); - priv->session_changed_id = 0; - g_clear_object (&priv->session_monitor); - } + nm_clear_g_signal_handler (priv->session_monitor, &priv->session_changed_id); + g_clear_object (&priv->session_monitor); + g_clear_object (&priv->agent_mgr); g_clear_pointer (&priv->filename, g_free); diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 8dd5f2bea5..fab5383c79 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -25,6 +25,8 @@ #include "nm-default.h" +#include "nm-settings.h" + #include <unistd.h> #include <sys/stat.h> #include <errno.h> @@ -59,7 +61,6 @@ #include "nm-core-internal.h" #include "nm-device-ethernet.h" -#include "nm-settings.h" #include "nm-settings-connection.h" #include "nm-settings-plugin.h" #include "nm-bus-manager.h" @@ -68,7 +69,6 @@ #include "nm-session-monitor.h" #include "plugins/keyfile/plugin.h" #include "nm-agent-manager.h" -#include "nm-connection-provider.h" #include "nm-config.h" #include "nm-audit-manager.h" #include "NetworkManagerUtils.h" @@ -132,11 +132,11 @@ static void claim_connection (NMSettings *self, static void unmanaged_specs_changed (NMSettingsPlugin *config, gpointer user_data); static void unrecognized_specs_changed (NMSettingsPlugin *config, gpointer user_data); -static void connection_provider_iface_init (NMConnectionProviderInterface *cp_iface); - -G_DEFINE_TYPE_EXTENDED (NMSettings, nm_settings, NM_TYPE_EXPORTED_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION_PROVIDER, connection_provider_iface_init)) +static void connection_ready_changed (NMSettingsConnection *conn, + GParamSpec *pspec, + gpointer user_data); +G_DEFINE_TYPE (NMSettings, nm_settings, NM_TYPE_EXPORTED_OBJECT); typedef struct { NMAgentManager *agent_mgr; @@ -148,9 +148,9 @@ typedef struct { GSList *plugins; gboolean connections_loaded; GHashTable *connections; + NMSettingsConnection **connections_cached_list; GSList *unmanaged_specs; GSList *unrecognized_specs; - GSList *get_connections_cache; gboolean started; gboolean startup_complete; @@ -203,6 +203,11 @@ check_startup_complete (NMSettings *self) return; } + /* the connection_ready_changed signal handler is no longer needed. */ + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &conn)) + g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_ready_changed), self); + priv->startup_complete = TRUE; _notify (self, PROP_STARTUP_COMPLETE); } @@ -257,7 +262,7 @@ load_connections (NMSettings *self) } priv->connections_loaded = TRUE; - g_object_notify (G_OBJECT (self), NM_SETTINGS_CONNECTIONS); + _notify (self, PROP_CONNECTIONS); unmanaged_specs_changed (NULL, self); unrecognized_specs_changed (NULL, self); @@ -274,7 +279,7 @@ nm_settings_for_each_connection (NMSettings *self, g_return_if_fail (NM_IS_SETTINGS (self)); g_return_if_fail (for_each_func != NULL); - + priv = NM_SETTINGS_GET_PRIVATE (self); g_hash_table_iter_init (&iter, priv->connections); @@ -400,13 +405,60 @@ connection_sort (gconstpointer pa, gconstpointer pb) return 1; } +/** + * nm_settings_get_connections: + * @self: the #NMSettings + * @out_len: (out): (allow-none): returns the number of returned + * connections. + * + * Returns: (transfer-none): a list of NMSettingsConnections. The list is + * unsorted and NULL terminated. The result is never %NULL, in case of no + * connections, it returns an empty list. + * The returned list is cached internally, only valid until the next + * NMSettings operation. + */ +NMSettingsConnection *const* +nm_settings_get_connections (NMSettings *self, guint *out_len) +{ + GHashTableIter iter; + NMSettingsPrivate *priv; + guint l, i; + NMSettingsConnection **v; + NMSettingsConnection *con; + + g_return_val_if_fail (NM_IS_SETTINGS (self), NULL); + + priv = NM_SETTINGS_GET_PRIVATE (self); + + if (priv->connections_cached_list) { + NM_SET_OUT (out_len, g_hash_table_size (priv->connections)); + return priv->connections_cached_list; + } + + l = g_hash_table_size (priv->connections); + + v = g_new (NMSettingsConnection *, l + 1); + + i = 0; + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &con)) + v[i++] = con; + v[i] = NULL; + + nm_assert (i == l); + + NM_SET_OUT (out_len, l); + priv->connections_cached_list = v; + return v; +} + /* Returns a list of NMSettingsConnections. * The list is sorted in the order suitable for auto-connecting, i.e. * first go connections with autoconnect=yes and most recent timestamp. * Caller must free the list with g_slist_free(). */ GSList * -nm_settings_get_connections (NMSettings *self) +nm_settings_get_connections_sorted (NMSettings *self) { GHashTableIter iter; gpointer data = NULL; @@ -885,7 +937,6 @@ connection_updated (NMSettingsConnection *connection, gboolean by_user, gpointer 0, connection, by_user); - g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_UPDATED, connection); } static void @@ -919,17 +970,18 @@ connection_removed (NMSettingsConnection *connection, gpointer user_data) g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_removed), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_updated), self); g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_visibility_changed), self); - g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self); + if (!priv->startup_complete) + g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_ready_changed), self); g_object_unref (self); /* Forget about the connection internally */ g_hash_table_remove (priv->connections, (gpointer) cpath); + g_clear_pointer (&priv->connections_cached_list, g_free); /* Notify D-Bus */ g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection); /* Re-emit for listeners like NMPolicy */ - g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_REMOVED, connection); _notify (self, PROP_CONNECTIONS); if (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (connection))) nm_exported_object_unexport (NM_EXPORTED_OBJECT (connection)); @@ -1068,6 +1120,7 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) g_hash_table_insert (priv->connections, (gpointer) nm_connection_get_path (NM_CONNECTION (connection)), g_object_ref (connection)); + g_clear_pointer (&priv->connections_cached_list, g_free); nm_utils_log_connection_diff (NM_CONNECTION (connection), NULL, LOGL_DEBUG, LOGD_CORE, "new connection", "++ "); @@ -1077,7 +1130,6 @@ claim_connection (NMSettings *self, NMSettingsConnection *connection) if (priv->connections_loaded) { /* Internal added signal */ g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); - g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_ADDED, connection); _notify (self, PROP_CONNECTIONS); /* Exported D-Bus signal */ @@ -1153,16 +1205,6 @@ nm_settings_add_connection (NMSettings *self, return NULL; } -static NMConnection * -_nm_connection_provider_add_connection (NMConnectionProvider *provider, - NMConnection *connection, - gboolean save_to_disk, - GError **error) -{ - g_assert (NM_IS_CONNECTION_PROVIDER (provider) && NM_IS_SETTINGS (provider)); - return NM_CONNECTION (nm_settings_add_connection (NM_SETTINGS (provider), connection, save_to_disk, error)); -} - static gboolean secrets_filter_cb (NMSetting *setting, const char *secret, @@ -1410,12 +1452,12 @@ impl_settings_add_connection_add_cb (NMSettings *self, { if (error) { g_dbus_method_invocation_return_gerror (context, error); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, subject, error->message); + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, NULL, subject, error->message); } else { g_dbus_method_invocation_return_value ( context, g_variant_new ("(o)", nm_connection_get_path (NM_CONNECTION (connection)))); - nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, + nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL, subject, NULL); } } @@ -2070,22 +2112,41 @@ nm_settings_sort_connections (gconstpointer a, gconstpointer b) return 0; } -static GSList * -get_best_connections (NMConnectionProvider *provider, - guint max_requested, - const char *ctype1, - const char *ctype2, - NMConnectionFilterFunc func, - gpointer func_data) +/** + * nm_settings_get_best_connections: + * @self: the #NMSetting + * @max_requested: if non-zero, the maximum number of connections to return + * @ctype1: an #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) to + * filter connections against + * @ctype2: a second #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) + * to filter connections against + * @func: caller-supplied function for filtering connections + * @func_data: caller-supplied data passed to @func + * + * Returns: a #GSList of #NMConnection objects in sorted order representing the + * "best" or highest-priority connections filtered by @ctype1 and/or @ctype2, + * and/or @func. Caller is responsible for freeing the returned #GSList, but + * the contained values do not need to be unreffed. + */ +GSList * +nm_settings_get_best_connections (NMSettings *self, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data) { - NMSettings *self = NM_SETTINGS (provider); - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + NMSettingsPrivate *priv; GSList *sorted = NULL; GHashTableIter iter; NMSettingsConnection *connection; guint added = 0; guint64 oldest = 0; + g_return_val_if_fail (NM_IS_SETTINGS (self), NULL); + + priv = NM_SETTINGS_GET_PRIVATE (self); + g_hash_table_iter_init (&iter, priv->connections); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) { guint64 cur_ts = 0; @@ -2094,7 +2155,7 @@ get_best_connections (NMConnectionProvider *provider, continue; if (ctype2 && !nm_connection_is_type (NM_CONNECTION (connection), ctype2)) continue; - if (func && !func (provider, NM_CONNECTION (connection), func_data)) + if (func && !func (self, NM_CONNECTION (connection), func_data)) continue; /* Don't bother with a connection that's older than the oldest one in the list */ @@ -2120,27 +2181,6 @@ get_best_connections (NMConnectionProvider *provider, return g_slist_reverse (sorted); } -static const GSList * -get_connections (NMConnectionProvider *provider) -{ - GSList *list = NULL; - NMSettings *self = NM_SETTINGS (provider); - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - - list = _nm_utils_hash_values_to_slist (priv->connections); - - /* Cache the list every call so we can keep it 'const' for callers */ - g_slist_free (priv->get_connections_cache); - priv->get_connections_cache = list; - return list; -} - -static NMConnection * -cp_get_connection_by_uuid (NMConnectionProvider *provider, const char *uuid) -{ - return NM_CONNECTION (nm_settings_get_connection_by_uuid (NM_SETTINGS (provider), uuid)); -} - /***************************************************************/ gboolean @@ -2189,14 +2229,30 @@ setup_hostname_file_monitors (NMSettings *self) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); GFileMonitor *monitor; + const char *path = HOSTNAME_FILE; + char *link_path = NULL; + struct stat file_stat; GFile *file; priv->hostname.value = nm_settings_get_hostname (self); + /* resolve the path to the hostname file if it is a symbolic link */ + if ( lstat(path, &file_stat) == 0 + && S_ISLNK (file_stat.st_mode) + && (link_path = nm_utils_read_link_absolute (path, NULL))) { + path = link_path; + if ( lstat(link_path, &file_stat) == 0 + && S_ISLNK (file_stat.st_mode)) { + _LOGW ("only one level of symbolic link indirection is allowed when monitoring " + HOSTNAME_FILE); + } + } + /* monitor changes to hostname file */ - file = g_file_new_for_path (HOSTNAME_FILE); + file = g_file_new_for_path (path); monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); + g_free(link_path); if (monitor) { priv->hostname.monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (hostname_file_changed_cb), @@ -2286,15 +2342,6 @@ nm_settings_start (NMSettings *self, GError **error) } static void -connection_provider_iface_init (NMConnectionProviderInterface *cp_iface) -{ - cp_iface->get_best_connections = get_best_connections; - cp_iface->get_connections = get_connections; - cp_iface->add_connection = _nm_connection_provider_add_connection; - cp_iface->get_connection_by_uuid = cp_get_connection_by_uuid; -} - -static void nm_settings_init (NMSettings *self) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); @@ -2358,7 +2405,7 @@ finalize (GObject *object) NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); g_hash_table_destroy (priv->connections); - g_slist_free (priv->get_connections_cache); + g_clear_pointer (&priv->connections_cached_list, g_free); g_slist_free_full (priv->unmanaged_specs, g_free); g_slist_free_full (priv->unrecognized_specs, g_free); diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h index 5d41e5bc92..a0be42eef3 100644 --- a/src/settings/nm-settings.h +++ b/src/settings/nm-settings.h @@ -49,6 +49,18 @@ #define NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED "connection-visibility-changed" #define NM_SETTINGS_SIGNAL_AGENT_REGISTERED "agent-registered" +/** + * NMConnectionFilterFunc: + * @settings: The #NMSettings requesting the filtering + * @connection: the connection to be filtered + * @func_data: the caller-provided data pointer + * + * Returns: %TRUE to allow the connection, %FALSE to ignore it + */ +typedef gboolean (*NMConnectionFilterFunc) (NMSettings *settings, + NMConnection *connection, + gpointer func_data); + struct _NMSettings { NMExportedObject parent_instance; }; @@ -61,6 +73,9 @@ typedef void (*NMSettingsSetHostnameCb) (const char *name, gboolean result, gpoi GType nm_settings_get_type (void); +NMSettings *nm_settings_get (void); +#define NM_SETTINGS_GET (nm_settings_get ()) + NMSettings *nm_settings_new (void); gboolean nm_settings_start (NMSettings *self, GError **error); @@ -86,10 +101,16 @@ void nm_settings_add_connection_dbus (NMSettings *self, NMSettingsAddCallback callback, gpointer user_data); -/* Returns a list of NMSettingsConnections. Caller must free the list with - * g_slist_free(). - */ -GSList *nm_settings_get_connections (NMSettings *settings); +NMSettingsConnection *const* nm_settings_get_connections (NMSettings *settings, guint *out_len); + +GSList *nm_settings_get_connections_sorted (NMSettings *settings); + +GSList *nm_settings_get_best_connections (NMSettings *self, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data); NMSettingsConnection *nm_settings_add_connection (NMSettings *settings, NMConnection *connection, diff --git a/src/settings/plugins/ibft/tests/test-ibft.c b/src/settings/plugins/ibft/tests/test-ibft.c index 9c98d8912c..cab468dec9 100644 --- a/src/settings/plugins/ibft/tests/test-ibft.c +++ b/src/settings/plugins/ibft/tests/test-ibft.c @@ -34,7 +34,7 @@ #include "reader.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static GPtrArray * read_block (const char *iscsiadm_path, const char *expected_mac) diff --git a/src/settings/plugins/ifcfg-rh/common.h b/src/settings/plugins/ifcfg-rh/common.h index 5d6ebe6d65..d850ac4e75 100644 --- a/src/settings/plugins/ifcfg-rh/common.h +++ b/src/settings/plugins/ifcfg-rh/common.h @@ -21,8 +21,6 @@ #ifndef __COMMON_H__ #define __COMMON_H__ -#include "nm-default.h" - #define IFCFG_TAG "ifcfg-" #define KEYS_TAG "keys-" #define ROUTE_TAG "route-" @@ -38,7 +36,7 @@ #define AUGNEW_TAG ".augnew" #define AUGTMP_TAG ".augtmp" -#define IFCFG_DIR SYSCONFDIR"/sysconfig/network-scripts" +#define IFCFG_DIR SYSCONFDIR "/sysconfig/network-scripts" #define IFCFG_PLUGIN_NAME "ifcfg-rh" #define IFCFG_PLUGIN_INFO "(c) 2007 - 2015 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index b9bbf6d5b0..3efd99a4c5 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -20,6 +20,8 @@ #include "nm-default.h" +#include "nm-ifcfg-connection.h" + #include <string.h> #include <glib/gstdio.h> @@ -37,7 +39,6 @@ #include "common.h" #include "nm-config.h" -#include "nm-ifcfg-connection.h" #include "reader.h" #include "writer.h" #include "nm-inotify-helper.h" diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h index 44e0298772..57db059b00 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.h @@ -21,10 +21,8 @@ #ifndef __NETWORKMANAGER_IFCFG_CONNECTION_H__ #define __NETWORKMANAGER_IFCFG_CONNECTION_H__ -G_BEGIN_DECLS - -#include <nm-dbus-interface.h> -#include <nm-settings-connection.h> +#include "nm-dbus-interface.h" +#include "nm-settings-connection.h" #define NM_TYPE_IFCFG_CONNECTION (nm_ifcfg_connection_get_type ()) #define NM_IFCFG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnection)) @@ -58,6 +56,4 @@ gboolean nm_ifcfg_connection_update (NMIfcfgConnection *self, GHashTable *new_settings, GError **error); -G_END_DECLS - #endif /* __NETWORKMANAGER_IFCFG_CONNECTION_H__ */ diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 1fb6b78947..1c0ce918b1 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -23,6 +23,8 @@ #include "nm-default.h" +#include "plugin.h" + #include <string.h> #include <unistd.h> #include <errno.h> @@ -31,20 +33,19 @@ #include <gmodule.h> +#include "nm-dbus-compat.h" #include "nm-setting-connection.h" -#include "common.h" -#include "plugin.h" #include "nm-settings-plugin.h" #include "nm-config.h" #include "NetworkManagerUtils.h" #include "nm-ifcfg-connection.h" #include "shvar.h" +#include "common.h" #include "reader.h" #include "writer.h" #include "utils.h" -#include "nm-dbus-compat.h" #include "nm-exported-object.h" #include "nmdbus-ifcfg-rh.h" @@ -61,8 +62,6 @@ _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ } G_STMT_END -#define ERR_GET_MSG(err) (((err) && (err)->message) ? (err)->message : "(unknown)") - static NMIfcfgConnection *update_connection (SettingsPluginIfcfg *plugin, NMConnection *source, diff --git a/src/settings/plugins/ifcfg-rh/plugin.h b/src/settings/plugins/ifcfg-rh/plugin.h index eba734cff8..74c4b00a04 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.h +++ b/src/settings/plugins/ifcfg-rh/plugin.h @@ -24,8 +24,6 @@ #ifndef _PLUGIN_H_ #define _PLUGIN_H_ -#include "nm-exported-object.h" - #define SETTINGS_TYPE_PLUGIN_IFCFG (settings_plugin_ifcfg_get_type ()) #define SETTINGS_PLUGIN_IFCFG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfg)) #define SETTINGS_PLUGIN_IFCFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgClass)) @@ -46,5 +44,5 @@ struct _SettingsPluginIfcfgClass { GType settings_plugin_ifcfg_get_type (void); -#endif /* _PLUGIN_H_ */ +#endif /* _PLUGIN_H_ */ diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 39e981f959..b933e1a5fa 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -20,6 +20,8 @@ #include "nm-default.h" +#include "reader.h" + #include <stdlib.h> #include <string.h> #include <sys/types.h> @@ -57,35 +59,31 @@ #include "shvar.h" #include "utils.h" -#include "reader.h" +/*****************************************************************************/ -#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg) +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG_PREFIX_NAME "ifcfg-rh" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), (_NMLOG_DOMAIN), \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END -static gboolean -get_int (const char *str, int *value) -{ - char *e; - long int tmp; +#define PARSE_WARNING(...) _LOGW ("%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), " " _NM_UTILS_MACRO_REST(__VA_ARGS__)) - errno = 0; - tmp = strtol (str, &e, 0); - if (errno || *e != '\0' || tmp > G_MAXINT || tmp < G_MININT) - return FALSE; - *value = (int) tmp; - return TRUE; -} +/*****************************************************************************/ static gboolean get_uint (const char *str, guint32 *value) { - char *e; - long unsigned int tmp; + gint64 tmp; - errno = 0; - tmp = strtoul (str, &e, 0); - if (errno || *e != '\0') + tmp = _nm_utils_ascii_str_to_int64 (str, 0, 0, G_MAXUINT32, -1); + if (tmp == -1) return FALSE; - *value = (guint32) tmp; + *value = tmp; return TRUE; } @@ -242,15 +240,12 @@ make_connection_setting (const char *file, value = svGetValue (ifcfg, "GATEWAY_PING_TIMEOUT", FALSE); if (value) { - long int tmp; - guint32 timeout; + gint64 tmp; - errno = 0; - tmp = strtol (value, NULL, 10); - if (errno == 0 && tmp >= 0 && tmp < G_MAXINT32) { - timeout = (guint32) tmp; - g_object_set (s_con, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, timeout, NULL); - } else + tmp = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT32 - 1, -1); + if (tmp >= 0) + g_object_set (s_con, NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, (guint) tmp, NULL); + else PARSE_WARNING ("invalid GATEWAY_PING_TIMEOUT time"); g_free (value); } @@ -541,7 +536,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError * char **lines = NULL, **iter; GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric; GMatchInfo *match_info; - gint64 prefix_int, metric_int; + int prefix_int; + gint64 metric_int; gboolean success = FALSE; const char *pattern_empty = "^\\s*(\\#.*)?$"; @@ -609,9 +605,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError * g_match_info_free (match_info); prefix_int = 32; if (prefix) { - errno = 0; - prefix_int = strtol (prefix, NULL, 10); - if (errno || prefix_int <= 0 || prefix_int > 32) { + prefix_int = _nm_utils_ascii_str_to_int64 (prefix, 10, 1, 32, -1); + if (prefix_int == -1) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP4 route destination prefix '%s'", prefix); g_free (prefix); @@ -641,9 +636,8 @@ read_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError * metric_int = -1; if (g_match_info_matches (match_info)) { metric = g_match_info_fetch (match_info, 1); - errno = 0; - metric_int = strtol (metric, NULL, 10); - if (errno || metric_int < 0) { + metric_int = _nm_utils_ascii_str_to_int64 (metric, 10, 0, G_MAXUINT32, -1); + if (metric_int == -1) { g_match_info_free (match_info); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP4 route metric '%s'", metric); @@ -766,7 +760,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric; GMatchInfo *match_info; char *dest = NULL, *prefix = NULL, *next_hop = NULL, *metric = NULL; - gint64 prefix_int, metric_int; + int prefix_int; + gint64 metric_int; gboolean success = FALSE; const char *pattern_empty = "^\\s*(\\#.*)?$"; @@ -828,9 +823,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error g_match_info_free (match_info); prefix_int = 128; if (prefix) { - errno = 0; - prefix_int = strtol (prefix, NULL, 10); - if (errno || prefix_int <= 0 || prefix_int > 128) { + prefix_int = _nm_utils_ascii_str_to_int64 (prefix, 10, 1, 128, -1); + if (prefix_int == -1) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP6 route destination prefix '%s'", prefix); g_free (dest); @@ -864,9 +858,8 @@ read_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **error metric_int = -1; if (g_match_info_matches (match_info)) { metric = g_match_info_fetch (match_info, 1); - errno = 0; - metric_int = strtol (metric, NULL, 10); - if (errno || metric_int < 0 || metric_int > G_MAXUINT32) { + metric_int = _nm_utils_ascii_str_to_int64 (metric, 10, 0, G_MAXUINT32, -1); + if (metric_int == -1) { g_match_info_free (match_info); g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid IP6 route metric '%s'", metric); @@ -919,6 +912,7 @@ make_ip4_setting (shvarFile *ifcfg, shvarFile *route_ifcfg; gboolean never_default = FALSE; gint64 timeout; + gint priority; s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new (); @@ -984,6 +978,8 @@ make_ip4_setting (shvarFile *ifcfg, goto done; (void) nm_setting_ip_config_add_address (s_ip4, addr); nm_ip_address_unref (addr); + if (never_default) + PARSE_WARNING ("GATEWAY will be ignored when DEFROUTE is disabled"); g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); } return NM_SETTING (s_ip4); @@ -1082,6 +1078,9 @@ make_ip4_setting (shvarFile *ifcfg, } g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway, NULL); + if (gateway && never_default) + PARSE_WARNING ("GATEWAY will be ignored when DEFROUTE is disabled"); + /* DNS servers * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ @@ -1136,6 +1135,13 @@ make_ip4_setting (shvarFile *ifcfg, g_free (dns_options); dns_options = NULL; + /* DNS priority */ + priority = svGetValueInt64 (ifcfg, "IPV4_DNS_PRIORITY", 10, G_MININT32, G_MAXINT32, 0); + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + priority, + NULL); + /* Static routes - route-<name> file */ route_path = utils_get_route_path (ifcfg->fileName); @@ -1318,6 +1324,7 @@ make_ip6_setting (shvarFile *ifcfg, char *ipv6addr, *ipv6addr_secondaries; char **list = NULL, **iter; guint32 i; + gint priority; shvarFile *network_ifcfg; gboolean never_default = FALSE; gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip; @@ -1520,6 +1527,13 @@ make_ip6_setting (shvarFile *ifcfg, NULL); } + /* IPv6 tokenized interface identifier */ + tmp = svGetValue (ifcfg, "IPV6_TOKEN", FALSE); + if (tmp) { + g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, tmp, NULL); + g_free (tmp); + } + /* DNS servers * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ @@ -1567,6 +1581,13 @@ make_ip6_setting (shvarFile *ifcfg, g_free (value); g_free (dns_options); + /* DNS priority */ + priority = svGetValueInt64 (ifcfg, "IPV6_DNS_PRIORITY", 10, G_MININT32, G_MAXINT32, 0); + g_object_set (s_ip6, + NM_SETTING_IP_CONFIG_DNS_PRIORITY, + priority, + NULL); + return NM_SETTING (s_ip6); error: @@ -1676,10 +1697,9 @@ read_dcb_app (shvarFile *ifcfg, tmp = g_strdup_printf ("DCB_APP_%s_PRIORITY", app); val = svGetValue (ifcfg, tmp, FALSE); if (val) { - success = get_int (val, &priority); - if (success) - success = (priority >= 0 && priority <= 7); - if (!success) { + priority = _nm_utils_ascii_str_to_int64 (val, 0, 0, 7, -1); + if (priority < 0) { + success = FALSE; g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid %s value '%s' (expected 0 - 7)", tmp, val); @@ -1819,7 +1839,6 @@ read_dcb_percent_array (shvarFile *ifcfg, char *val; gboolean success = FALSE; char **split = NULL, **iter; - int tmp; guint i, sum = 0; val = svGetValue (ifcfg, prop, FALSE); @@ -1842,7 +1861,10 @@ read_dcb_percent_array (shvarFile *ifcfg, } for (iter = split, i = 0; iter && *iter; iter++, i++) { - if (!get_int (*iter, &tmp) || tmp < 0 || tmp > 100) { + int tmp; + + tmp = _nm_utils_ascii_str_to_int64 (*iter, 0, 0, 100, -1); + if (tmp < 0) { PARSE_WARNING ("invalid %s percentage value '%s'", prop, *iter); g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "invalid percent element"); @@ -2164,7 +2186,7 @@ make_wep_setting (shvarFile *ifcfg, char *value; shvarFile *keys_ifcfg = NULL; int default_key_idx = 0; - gboolean has_default_key = FALSE, success; + gboolean has_default_key = FALSE; NMSettingSecretFlags key_flags; s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ()); @@ -2172,18 +2194,17 @@ make_wep_setting (shvarFile *ifcfg, value = svGetValue (ifcfg, "DEFAULTKEY", FALSE); if (value) { - success = get_int (value, &default_key_idx); - if (success && (default_key_idx >= 1) && (default_key_idx <= 4)) { - has_default_key = TRUE; - default_key_idx--; /* convert to [0...3] */ - g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, default_key_idx, NULL); - } else { + default_key_idx = _nm_utils_ascii_str_to_int64 (value, 0, 1, 4, 0); + if (default_key_idx == 0) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid default WEP key '%s'", value); - g_free (value); + g_free (value); goto error; } - g_free (value); + has_default_key = TRUE; + default_key_idx--; /* convert to [0...3] */ + g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, (guint) default_key_idx, NULL); + g_free (value); } /* Read WEP key flags */ @@ -3484,17 +3505,16 @@ make_wireless_setting (shvarFile *ifcfg, value = svGetValue (ifcfg, "MTU", FALSE); if (value) { - long int mtu; + int mtu; - errno = 0; - mtu = strtol (value, NULL, 10); - if (errno || mtu < 0 || mtu > 50000) { + mtu = _nm_utils_ascii_str_to_int64 (value, 10, 0, 50000, -1); + if (mtu == -1) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid wireless MTU '%s'", value); g_free (value); goto error; } - g_object_set (s_wireless, NM_SETTING_WIRELESS_MTU, (guint32) mtu, NULL); + g_object_set (s_wireless, NM_SETTING_WIRELESS_MTU, (guint) mtu, NULL); g_free (value); } @@ -3756,20 +3776,19 @@ make_wired_setting (shvarFile *ifcfg, { NMSettingWired *s_wired; char *value = NULL; - int mtu; char *nettype; s_wired = NM_SETTING_WIRED (nm_setting_wired_new ()); value = svGetValue (ifcfg, "MTU", FALSE); if (value) { - if (get_int (value, &mtu)) { - if (mtu >= 0 && mtu < 65536) - g_object_set (s_wired, NM_SETTING_WIRED_MTU, mtu, NULL); - } else { - /* Shouldn't be fatal... */ + int mtu; + + mtu = _nm_utils_ascii_str_to_int64 (value, 0, 0, 65535, -1); + if (mtu >= 0) + g_object_set (s_wired, NM_SETTING_WIRED_MTU, (guint) mtu, NULL); + else PARSE_WARNING ("invalid MTU '%s'", value); - } g_free (value); } @@ -3940,9 +3959,9 @@ parse_infiniband_p_key (shvarFile *ifcfg, char **out_parent, GError **error) { - char *device = NULL, *physdev = NULL, *pkey_id = NULL, *end; + char *device = NULL, *physdev = NULL, *pkey_id = NULL; char *ifname = NULL; - guint32 id = G_MAXUINT32; + int id; gboolean ret = FALSE; device = svGetValue (ifcfg, "DEVICE", FALSE); @@ -3963,19 +3982,14 @@ parse_infiniband_p_key (shvarFile *ifcfg, goto done; } - if (g_str_has_prefix (pkey_id, "0x")) - id = strtoul (pkey_id, &end, 16); - else if (!g_str_has_prefix (pkey_id, "0")) - id = strtoul (pkey_id, &end, 10); - else - end = pkey_id; - if (end == pkey_id || *end || id > 0xFFFF) { + id = _nm_utils_ascii_str_to_int64 (pkey_id, 0, 0, 0xFFFF, -1); + if (id == -1) { PARSE_WARNING ("invalid InfiniBand PKEY_ID '%s'", pkey_id); goto done; } id = (id | 0x8000); - ifname = g_strdup_printf ("%s.%04x", physdev, id); + ifname = g_strdup_printf ("%s.%04x", physdev, (unsigned) id); if (strcmp (device, ifname) != 0) { PARSE_WARNING ("InfiniBand DEVICE (%s) does not match PHYSDEV+PKEY_ID (%s)", device, ifname); @@ -4007,19 +4021,18 @@ make_infiniband_setting (shvarFile *ifcfg, { NMSettingInfiniband *s_infiniband; char *value = NULL; - int mtu; s_infiniband = NM_SETTING_INFINIBAND (nm_setting_infiniband_new ()); value = svGetValue (ifcfg, "MTU", FALSE); if (value) { - if (get_int (value, &mtu)) { - if (mtu >= 0 && mtu < 65536) - g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, mtu, NULL); - } else { - /* Shouldn't be fatal... */ + int mtu; + + mtu = _nm_utils_ascii_str_to_int64 (value, 0, 0, 65535, -1); + if (mtu >= 0) + g_object_set (s_infiniband, NM_SETTING_INFINIBAND_MTU, (guint) mtu, NULL); + else PARSE_WARNING ("invalid MTU '%s'", value); - } g_free (value); } @@ -4643,16 +4656,14 @@ make_vlan_setting (shvarFile *ifcfg, char *iface_name = NULL; char *parent = NULL; const char *p = NULL; - char *end = NULL; - gint vlan_id = -1; + int vlan_id = -1; guint32 vlan_flags = 0; gint gvrp, reorder_hdr; value = svGetValue (ifcfg, "VLAN_ID", FALSE); if (value) { - errno = 0; - vlan_id = (gint) g_ascii_strtoll (value, NULL, 10); - if (vlan_id < 0 || vlan_id > 4096 || errno) { + vlan_id = _nm_utils_ascii_str_to_int64 (value, 10, 0, 4095, -1); + if (vlan_id == -1) { g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, "Invalid VLAN_ID '%s'", value); g_free (value); @@ -4696,12 +4707,13 @@ make_vlan_setting (shvarFile *ifcfg, } if (p) { + int device_vlan_id; + /* Grab VLAN ID from interface name; this takes precedence over the * separate VLAN_ID property for backwards compat. */ - - gint device_vlan_id = (gint) g_ascii_strtoll (p, &end, 10); - if (device_vlan_id >= 0 && device_vlan_id <= 4095 && end != p && !*end) + device_vlan_id = _nm_utils_ascii_str_to_int64 (p, 10, 0, 4095, -1); + if (device_vlan_id != -1) vlan_id = device_vlan_id; } } diff --git a/src/settings/plugins/ifcfg-rh/reader.h b/src/settings/plugins/ifcfg-rh/reader.h index 88f9a72007..35464474f2 100644 --- a/src/settings/plugins/ifcfg-rh/reader.h +++ b/src/settings/plugins/ifcfg-rh/reader.h @@ -21,10 +21,7 @@ #ifndef __READER_H__ #define __READER_H__ -#include <nm-connection.h> - -#include "nm-default.h" -#include "shvar.h" +#include "nm-connection.h" NMConnection *connection_from_file (const char *filename, char **out_unhandled, diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 4e756349ca..75b19d5383 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -25,6 +25,8 @@ #include "nm-default.h" +#include "shvar.h" + #include <errno.h> #include <fcntl.h> #include <stdio.h> @@ -34,12 +36,8 @@ #include <sys/stat.h> #include <unistd.h> -#include "shvar.h" - #include "nm-core-internal.h" -#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg) - /* Open the file <name>, returning a shvarFile on success and NULL on failure. * Add a wrinkle to let the caller specify whether or not to create the file * (actually, return a structure anyway) if it doesn't exist. @@ -273,26 +271,23 @@ svGetValueFull (shvarFile *s, const char *key, gboolean verbatim) { char *value = NULL; char *line; - char *keyString; - int len; + guint len; g_return_val_if_fail (s != NULL, NULL); g_return_val_if_fail (key != NULL, NULL); - keyString = g_strdup_printf ("%s=", key); - len = strlen (keyString); + len = strlen (key); for (s->current = s->lineList; s->current; s->current = s->current->next) { line = s->current->data; - if (!strncmp (keyString, line, len)) { + if (!strncmp (key, line, len) && line[len] == '=') { /* Strip trailing spaces before unescaping to preserve spaces quoted whitespace */ - value = g_strchomp (g_strdup (line + len)); + value = g_strchomp (g_strdup (line + len + 1)); if (!verbatim) svUnescape (value); break; } } - g_free (keyString); return value; } @@ -373,11 +368,10 @@ svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 m result = _nm_utils_ascii_str_to_int64 (tmp, base, min, max, fallback); errsv = errno; - if (errsv != 0) - PARSE_WARNING ("Error reading '%s' value '%s' as integer (%d)", key, tmp, errsv); g_free (tmp); + errno = errsv; return result; } diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 227a44db17..97df81284a 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -31,10 +31,6 @@ #ifndef _SHVAR_H #define _SHVAR_H -#include "nm-default.h" - -G_BEGIN_DECLS - typedef struct _shvarFile shvarFile; struct _shvarFile { char *fileName; /* read-only */ @@ -95,6 +91,4 @@ const char *svEscape (const char *s, char **to_free); /* Unescape a string in-place */ void svUnescape (char *s); -G_END_DECLS - -#endif /* ! _SHVAR_H */ +#endif /* _SHVAR_H */ diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c index 5a0f6451a4..d2a348bb8b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c @@ -28,7 +28,7 @@ #include "common.h" #include "utils.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static void test_get_ifcfg_name (const char *desc, 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 5ed25fda10..c7e741f996 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -55,7 +55,7 @@ #include "writer.h" #include "utils.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /*****************************************************************************/ diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c index fda900b20e..b602a7d7c3 100644 --- a/src/settings/plugins/ifcfg-rh/utils.c +++ b/src/settings/plugins/ifcfg-rh/utils.c @@ -27,7 +27,8 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "shvar.h" + +#include "common.h" /* * utils_single_quote_string diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h index 752d08a60b..b8b172e7ce 100644 --- a/src/settings/plugins/ifcfg-rh/utils.h +++ b/src/settings/plugins/ifcfg-rh/utils.h @@ -21,10 +21,9 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#include <nm-connection.h> -#include "nm-default.h" +#include "nm-connection.h" + #include "shvar.h" -#include "common.h" #define NM_IFCFG_CONNECTION_LOG_PATH(path) ((path) ?: "in-memory") #define NM_IFCFG_CONNECTION_LOG_FMT "%s (%s,\"%s\")" diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index c17824d6fc..2864078a48 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -42,7 +42,6 @@ #include "nm-setting-vlan.h" #include "nm-setting-team.h" #include "nm-setting-team-port.h" -#include "nm-core-internal.h" #include "nm-utils.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" @@ -51,8 +50,20 @@ #include "shvar.h" #include "reader.h" #include "utils.h" -#include "crypto.h" +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_SETTINGS +#define _NMLOG_PREFIX_NAME "ifcfg-rh" +#define _NMLOG(level, ...) \ + G_STMT_START { \ + nm_log ((level), (_NMLOG_DOMAIN), \ + "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME": " \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } G_STMT_END + +/*****************************************************************************/ static void save_secret_flags (shvarFile *ifcfg, @@ -100,7 +111,7 @@ set_secret (shvarFile *ifcfg, { shvarFile *keyfile; GError *error = NULL; - + /* Clear the secret from the ifcfg and the associated "keys" file */ svSetValue (ifcfg, key, NULL, FALSE); @@ -109,7 +120,7 @@ set_secret (shvarFile *ifcfg, keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE); if (!keyfile) { - nm_log_warn (LOGD_SETTINGS, " could not create ifcfg file for '%s'", ifcfg->fileName); + _LOGW ("could not create ifcfg file for '%s'", ifcfg->fileName); goto error; } @@ -121,8 +132,8 @@ set_secret (shvarFile *ifcfg, svSetValue (keyfile, key, value, verbatim); if (!svWriteFile (keyfile, 0600, &error)) { - nm_log_warn (LOGD_SETTINGS, " could not update ifcfg file '%s': %s", - keyfile->fileName, error->message); + _LOGW ("could not update ifcfg file '%s': %s", + keyfile->fileName, error->message); g_clear_error (&error); svCloseFile (keyfile); goto error; @@ -715,7 +726,7 @@ write_wireless_security_setting (NMConnection *connection, key = ascii_key; } } else { - nm_log_warn (LOGD_SETTINGS, " invalid WEP key '%s'", key); + _LOGW ("invalid WEP key '%s'", key); tmp = NULL; } @@ -1970,6 +1981,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) gint32 j; guint32 i, n, num; gint64 route_metric; + gint priority; int timeout; GString *searches; gboolean success = FALSE; @@ -2281,6 +2293,12 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) svSetValueInt64 (ifcfg, "ARPING_WAIT", (timeout - 1) / 1000 + 1); } + priority = nm_setting_ip_config_get_dns_priority (s_ip4); + if (priority) + svSetValueInt64 (ifcfg, "IPV4_DNS_PRIORITY", priority); + else + svSetValue (ifcfg, "IPV4_DNS_PRIORITY", NULL, FALSE); + success = TRUE; out: @@ -2440,6 +2458,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) char *addr_key; char *tmp; guint32 i, num, num4; + gint priority; GString *searches; NMIPAddress *addr; const char *dns; @@ -2604,8 +2623,20 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) addr_gen_mode); svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", tmp, FALSE); g_free (tmp); + } else { + svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", NULL, FALSE); } + /* IPv6 tokenized interface identifier */ + value = nm_setting_ip6_config_get_token (NM_SETTING_IP6_CONFIG (s_ip6)); + svSetValue (ifcfg, "IPV6_TOKEN", value, FALSE); + + priority = nm_setting_ip_config_get_dns_priority (s_ip6); + if (priority) + svSetValueInt64 (ifcfg, "IPV6_DNS_PRIORITY", priority); + else + svSetValue (ifcfg, "IPV6_DNS_PRIORITY", NULL, FALSE); + /* Static routes go to route6-<dev> file */ route6_path = utils_get_route6_path (ifcfg->fileName); if (!route6_path) { diff --git a/src/settings/plugins/ifcfg-rh/writer.h b/src/settings/plugins/ifcfg-rh/writer.h index 69389361c9..97a9f25252 100644 --- a/src/settings/plugins/ifcfg-rh/writer.h +++ b/src/settings/plugins/ifcfg-rh/writer.h @@ -21,11 +21,7 @@ #ifndef _WRITER_H_ #define _WRITER_H_ -#include <sys/types.h> - -#include <nm-connection.h> - -#include "nm-default.h" +#include "nm-connection.h" gboolean writer_can_write_connection (NMConnection *connection, GError **error); diff --git a/src/settings/plugins/ifnet/tests/test-ifnet.c b/src/settings/plugins/ifnet/tests/test-ifnet.c index 3035fdb156..89df9af806 100644 --- a/src/settings/plugins/ifnet/tests/test-ifnet.c +++ b/src/settings/plugins/ifnet/tests/test-ifnet.c @@ -38,7 +38,7 @@ #include "connection_parser.h" #include "nm-config.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /* Fake NMConfig handling; the values it returns don't matter, so this * is easier than forcing it to read our own config file, etc. diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index f383821c39..ad483fa856 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -26,7 +26,7 @@ #include "interface_parser.h" #include "parser.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" typedef struct { char *key; diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 6003c7457f..c5598fc5b4 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -26,7 +26,6 @@ #include <sys/types.h> #include <string.h> -#include <gmodule.h> #include <glib/gstdio.h> #include "nm-connection.h" diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index 7b66e19861..00ab140bef 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -34,7 +34,7 @@ #include "writer.h" #include "utils.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static void check_ip_address (NMSettingIPConfig *config, int idx, const char *address, int plen) diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index 881f44f6bf..fd603f3b81 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -35,7 +35,7 @@ #include "nm-supplicant-config.h" #include "nm-supplicant-settings-verify.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static gboolean validate_opt (const char *detail, diff --git a/src/systemd/src/basic/ether-addr-util.c b/src/systemd/src/basic/ether-addr-util.c index 0219300da9..a793219cc2 100644 --- a/src/systemd/src/basic/ether-addr-util.c +++ b/src/systemd/src/basic/ether-addr-util.c @@ -25,6 +25,7 @@ #include "ether-addr-util.h" #include "macro.h" +#include "string-util.h" char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) { assert(addr); @@ -56,3 +57,71 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b) { a->ether_addr_octet[4] == b->ether_addr_octet[4] && a->ether_addr_octet[5] == b->ether_addr_octet[5]; } + +int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset) { + size_t pos = 0, n, field; + char sep = '\0'; + const char *hex = HEXDIGITS, *hexoff; + size_t x; + bool touched; + +#define parse_fields(v) \ + for (field = 0; field < ELEMENTSOF(v); field++) { \ + touched = false; \ + for (n = 0; n < (2 * sizeof(v[0])); n++) { \ + if (s[pos] == '\0') \ + break; \ + hexoff = strchr(hex, s[pos]); \ + if (hexoff == NULL) \ + break; \ + assert(hexoff >= hex); \ + x = hexoff - hex; \ + if (x >= 16) \ + x -= 6; /* A-F */ \ + assert(x < 16); \ + touched = true; \ + v[field] <<= 4; \ + v[field] += x; \ + pos++; \ + } \ + if (!touched) \ + return -EINVAL; \ + if (field < (ELEMENTSOF(v)-1)) { \ + if (s[pos] != sep) \ + return -EINVAL; \ + else \ + pos++; \ + } \ + } + + assert(s); + assert(ret); + + sep = s[strspn(s, hex)]; + if (sep == '\n') + return -EINVAL; + if (strchr(":.-", sep) == NULL) + return -EINVAL; + + if (sep == '.') { + uint16_t shorts[3] = { 0 }; + + parse_fields(shorts); + + for (n = 0; n < ELEMENTSOF(shorts); n++) { + ret->ether_addr_octet[2*n] = ((shorts[n] & (uint16_t)0xff00) >> 8); + ret->ether_addr_octet[2*n + 1] = (shorts[n] & (uint16_t)0x00ff); + } + } else { + struct ether_addr out = { .ether_addr_octet = { 0 } }; + + parse_fields(out.ether_addr_octet); + + for (n = 0; n < ELEMENTSOF(out.ether_addr_octet); n++) + ret->ether_addr_octet[n] = out.ether_addr_octet[n]; + } + + if (offset) + *offset = pos; + return 0; +} diff --git a/src/systemd/src/basic/ether-addr-util.h b/src/systemd/src/basic/ether-addr-util.h index 074363793e..74e125a95f 100644 --- a/src/systemd/src/basic/ether-addr-util.h +++ b/src/systemd/src/basic/ether-addr-util.h @@ -35,3 +35,5 @@ bool ether_addr_equal(const struct ether_addr *a, const struct ether_addr *b); static inline bool ether_addr_is_null(const struct ether_addr *addr) { return ether_addr_equal(addr, ÐER_ADDR_NULL); } + +int ether_addr_from_string(const char *s, struct ether_addr *ret, size_t *offset); diff --git a/src/systemd/src/basic/extract-word.c b/src/systemd/src/basic/extract-word.c new file mode 100644 index 0000000000..eb54daa355 --- /dev/null +++ b/src/systemd/src/basic/extract-word.c @@ -0,0 +1,302 @@ +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "nm-sd-adapt.h" + +#include <errno.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include "alloc-util.h" +#include "escape.h" +#include "extract-word.h" +#include "log.h" +#include "macro.h" +#include "string-util.h" +#include "utf8.h" + +int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) { + _cleanup_free_ char *s = NULL; + size_t allocated = 0, sz = 0; + char c; + int r; + + char quote = 0; /* 0 or ' or " */ + bool backslash = false; /* whether we've just seen a backslash */ + + assert(p); + assert(ret); + + /* Bail early if called after last value or with no input */ + if (!*p) + goto finish_force_terminate; + c = **p; + + if (!separators) + separators = WHITESPACE; + + /* Parses the first word of a string, and returns it in + * *ret. Removes all quotes in the process. When parsing fails + * (because of an uneven number of quotes or similar), leaves + * the pointer *p at the first invalid character. */ + + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { + (*p)++; + goto finish_force_next; + } + } else { + /* We found a non-blank character, so we will always + * want to return a string (even if it is empty), + * allocate it here. */ + if (!GREEDY_REALLOC(s, allocated, sz+1)) + return -ENOMEM; + break; + } + } + + for (;; (*p)++, c = **p) { + if (backslash) { + if (!GREEDY_REALLOC(s, allocated, sz+7)) + return -ENOMEM; + + if (c == 0) { + if ((flags & EXTRACT_CUNESCAPE_RELAX) && + (!quote || flags & EXTRACT_RELAX)) { + /* If we find an unquoted trailing backslash and we're in + * EXTRACT_CUNESCAPE_RELAX mode, keep it verbatim in the + * output. + * + * Unbalanced quotes will only be allowed in EXTRACT_RELAX + * mode, EXTRACT_CUNESCAPE_RELAX mode does not allow them. + */ + s[sz++] = '\\'; + goto finish_force_terminate; + } + if (flags & EXTRACT_RELAX) + goto finish_force_terminate; + return -EINVAL; + } + + if (flags & EXTRACT_CUNESCAPE) { + bool eight_bit = false; + char32_t u; + + r = cunescape_one(*p, (size_t) -1, &u, &eight_bit); + if (r < 0) { + if (flags & EXTRACT_CUNESCAPE_RELAX) { + s[sz++] = '\\'; + s[sz++] = c; + } else + return -EINVAL; + } else { + (*p) += r - 1; + + if (eight_bit) + s[sz++] = u; + else + sz += utf8_encode_unichar(s + sz, u); + } + } else + s[sz++] = c; + + backslash = false; + + } else if (quote) { /* inside either single or double quotes */ + for (;; (*p)++, c = **p) { + if (c == 0) { + if (flags & EXTRACT_RELAX) + goto finish_force_terminate; + return -EINVAL; + } else if (c == quote) { /* found the end quote */ + quote = 0; + break; + } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { + backslash = true; + break; + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } + } + + } else { + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + else if ((c == '\'' || c == '"') && (flags & EXTRACT_QUOTES)) { + quote = c; + break; + } else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) { + backslash = true; + break; + } else if (strchr(separators, c)) { + if (flags & EXTRACT_DONT_COALESCE_SEPARATORS) { + (*p)++; + goto finish_force_next; + } + /* Skip additional coalesced separators. */ + for (;; (*p)++, c = **p) { + if (c == 0) + goto finish_force_terminate; + if (!strchr(separators, c)) + break; + } + goto finish; + + } else { + if (!GREEDY_REALLOC(s, allocated, sz+2)) + return -ENOMEM; + + s[sz++] = c; + } + } + } + } + +finish_force_terminate: + *p = NULL; +finish: + if (!s) { + *p = NULL; + *ret = NULL; + return 0; + } + +finish_force_next: + s[sz] = 0; + *ret = s; + s = NULL; + + return 1; +} + +#if 0 /* NM_IGNORED */ +int extract_first_word_and_warn( + const char **p, + char **ret, + const char *separators, + ExtractFlags flags, + const char *unit, + const char *filename, + unsigned line, + const char *rvalue) { + + /* Try to unquote it, if it fails, warn about it and try again + * but this time using EXTRACT_CUNESCAPE_RELAX to keep the + * backslashes verbatim in invalid escape sequences. */ + + const char *save; + int r; + + save = *p; + r = extract_first_word(p, ret, separators, flags); + if (r >= 0) + return r; + + if (r == -EINVAL && !(flags & EXTRACT_CUNESCAPE_RELAX)) { + + /* Retry it with EXTRACT_CUNESCAPE_RELAX. */ + *p = save; + r = extract_first_word(p, ret, separators, flags|EXTRACT_CUNESCAPE_RELAX); + if (r >= 0) { + /* It worked this time, hence it must have been an invalid escape sequence we could correct. */ + log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "Invalid escape sequences in line, correcting: \"%s\"", rvalue); + return r; + } + + /* If it's still EINVAL; then it must be unbalanced quoting, report this. */ + if (r == -EINVAL) + return log_syntax(unit, LOG_ERR, filename, line, r, "Unbalanced quoting, ignoring: \"%s\"", rvalue); + } + + /* Can be any error, report it */ + return log_syntax(unit, LOG_ERR, filename, line, r, "Unable to decode word \"%s\", ignoring: %m", rvalue); +} + +int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) { + va_list ap; + char **l; + int n = 0, i, c, r; + + /* Parses a number of words from a string, stripping any + * quotes if necessary. */ + + assert(p); + + /* Count how many words are expected */ + va_start(ap, flags); + for (;;) { + if (!va_arg(ap, char **)) + break; + n++; + } + va_end(ap); + + if (n <= 0) + return 0; + + /* Read all words into a temporary array */ + l = newa0(char*, n); + for (c = 0; c < n; c++) { + + r = extract_first_word(p, &l[c], separators, flags); + if (r < 0) { + int j; + + for (j = 0; j < c; j++) + free(l[j]); + + return r; + } + + if (r == 0) + break; + } + + /* If we managed to parse all words, return them in the passed + * in parameters */ + va_start(ap, flags); + for (i = 0; i < n; i++) { + char **v; + + v = va_arg(ap, char **); + assert(v); + + *v = l[i]; + } + va_end(ap); + + return c; +} +#endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/extract-word.h b/src/systemd/src/basic/extract-word.h new file mode 100644 index 0000000000..21db5ef33f --- /dev/null +++ b/src/systemd/src/basic/extract-word.h @@ -0,0 +1,35 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "macro.h" + +typedef enum ExtractFlags { + EXTRACT_RELAX = 1, + EXTRACT_CUNESCAPE = 2, + EXTRACT_CUNESCAPE_RELAX = 4, + EXTRACT_QUOTES = 8, + EXTRACT_DONT_COALESCE_SEPARATORS = 16, + EXTRACT_RETAIN_ESCAPE = 32, +} ExtractFlags; + +int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags); +int extract_first_word_and_warn(const char **p, char **ret, const char *separators, ExtractFlags flags, const char *unit, const char *filename, unsigned line, const char *rvalue); +int extract_many_words(const char **p, const char *separators, ExtractFlags flags, ...) _sentinel_; diff --git a/src/systemd/src/basic/fd-util.c b/src/systemd/src/basic/fd-util.c index e92b3740c8..7a13d28f8c 100644 --- a/src/systemd/src/basic/fd-util.c +++ b/src/systemd/src/basic/fd-util.c @@ -27,6 +27,7 @@ #include <unistd.h> #include "fd-util.h" +#include "fs-util.h" #include "macro.h" #if 0 /* NM_IGNORED */ #include "missing.h" @@ -34,6 +35,7 @@ #include "parse-util.h" #include "path-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "util.h" int close_nointr(int fd) { @@ -234,7 +236,7 @@ int close_all_fds(const int except[], unsigned n_except) { while ((de = readdir(d))) { int fd = -1; - if (hidden_file(de->d_name)) + if (hidden_or_backup_file(de->d_name)) continue; if (safe_atoi(de->d_name, &fd) < 0) @@ -362,3 +364,17 @@ bool fdname_is_valid(const char *s) { return p - s < 256; } + +int fd_get_path(int fd, char **ret) { + char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + int r; + + xsprintf(procfs_path, "/proc/self/fd/%i", fd); + + r = readlink_malloc(procfs_path, ret); + + if (r == -ENOENT) /* If the file doesn't exist the fd is invalid */ + return -EBADF; + + return r; +} diff --git a/src/systemd/src/basic/fd-util.h b/src/systemd/src/basic/fd-util.h index 44528c6e35..b86e41698a 100644 --- a/src/systemd/src/basic/fd-util.h +++ b/src/systemd/src/basic/fd-util.h @@ -72,6 +72,8 @@ void cmsg_close_all(struct msghdr *mh); bool fdname_is_valid(const char *s); +int fd_get_path(int fd, char **ret); + /* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */ #define ERRNO_IS_DISCONNECT(r) \ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) diff --git a/src/systemd/src/basic/fileio.c b/src/systemd/src/basic/fileio.c index e940e10e70..b07cb9cb2d 100644 --- a/src/systemd/src/basic/fileio.c +++ b/src/systemd/src/basic/fileio.c @@ -1087,30 +1087,6 @@ int mkostemp_safe(char *pattern, int flags) { return fd; } -int open_tmpfile(const char *path, int flags) { - char *p; - int fd; - - assert(path); - -#ifdef O_TMPFILE - /* Try O_TMPFILE first, if it is supported */ - fd = open(path, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); - if (fd >= 0) - return fd; -#endif - - /* Fall back to unguessable name + unlinking */ - p = strjoina(path, "/systemd-tmp-XXXXXX"); - - fd = mkostemp_safe(p, flags); - if (fd < 0) - return fd; - - unlink(p); - return fd; -} - int tempfn_xxxxxx(const char *p, const char *extra, char **ret) { const char *fn; char *t; @@ -1234,7 +1210,6 @@ int write_timestamp_file_atomic(const char *fn, usec_t n) { return write_string_file(fn, ln, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC); } -#endif /* NM_IGNORED */ int read_timestamp_file(const char *fn, usec_t *ret) { _cleanup_free_ char *ln = NULL; @@ -1255,6 +1230,7 @@ int read_timestamp_file(const char *fn, usec_t *ret) { *ret = (usec_t) t; return 0; } +#endif /* NM_IGNORED */ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) { int r; @@ -1284,3 +1260,105 @@ int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) return fputs(s, f); } + +#if 0 /* NM_IGNORED */ +int open_tmpfile_unlinkable(const char *directory, int flags) { + char *p; + int fd; + + assert(directory); + + /* Returns an unlinked temporary file that cannot be linked into the file system anymore */ + +#ifdef O_TMPFILE + /* Try O_TMPFILE first, if it is supported */ + fd = open(directory, flags|O_TMPFILE|O_EXCL, S_IRUSR|S_IWUSR); + if (fd >= 0) + return fd; +#endif + + /* Fall back to unguessable name + unlinking */ + p = strjoina(directory, "/systemd-tmp-XXXXXX"); + + fd = mkostemp_safe(p, flags); + if (fd < 0) + return fd; + + (void) unlink(p); + + return fd; +} + +int open_tmpfile_linkable(const char *target, int flags, char **ret_path) { + _cleanup_free_ char *tmp = NULL; + int r, fd; + + assert(target); + assert(ret_path); + + /* Don't allow O_EXCL, as that has a special meaning for O_TMPFILE */ + assert((flags & O_EXCL) == 0); + + /* Creates a temporary file, that shall be renamed to "target" later. If possible, this uses O_TMPFILE – in + * which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in + * "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */ + +#ifdef O_TMPFILE + { + _cleanup_free_ char *dn = NULL; + + dn = dirname_malloc(target); + if (!dn) + return -ENOMEM; + + fd = open(dn, O_TMPFILE|flags, 0640); + if (fd >= 0) { + *ret_path = NULL; + return fd; + } + + log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn); + } +#endif + + r = tempfn_random(target, NULL, &tmp); + if (r < 0) + return r; + + fd = open(tmp, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|flags, 0640); + if (fd < 0) + return -errno; + + *ret_path = tmp; + tmp = NULL; + + return fd; +} + +int link_tmpfile(int fd, const char *path, const char *target) { + + assert(fd >= 0); + assert(target); + + /* Moves a temporary file created with open_tmpfile() above into its final place. if "path" is NULL an fd + * created with O_TMPFILE is assumed, and linkat() is used. Otherwise it is assumed O_TMPFILE is not supported + * on the directory, and renameat2() is used instead. + * + * Note that in both cases we will not replace existing files. This is because linkat() does not support this + * operation currently (renameat2() does), and there is no nice way to emulate this. */ + + if (path) { + if (rename_noreplace(AT_FDCWD, path, AT_FDCWD, target) < 0) + return -errno; + } else { + char proc_fd_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(fd) + 1]; + + xsprintf(proc_fd_path, "/proc/self/fd/%i", fd); + + if (linkat(AT_FDCWD, proc_fd_path, AT_FDCWD, target, AT_SYMLINK_FOLLOW) < 0) + return -errno; + } + + return 0; +} +#endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/fileio.h b/src/systemd/src/basic/fileio.h index 8084895ff3..58dbc80c24 100644 --- a/src/systemd/src/basic/fileio.h +++ b/src/systemd/src/basic/fileio.h @@ -72,7 +72,6 @@ int fflush_and_check(FILE *f); int fopen_temporary(const char *path, FILE **_f, char **_temp_path); int mkostemp_safe(char *pattern, int flags); -int open_tmpfile(const char *path, int flags); int tempfn_xxxxxx(const char *p, const char *extra, char **ret); int tempfn_random(const char *p, const char *extra, char **ret); @@ -82,3 +81,8 @@ int write_timestamp_file_atomic(const char *fn, usec_t n); int read_timestamp_file(const char *fn, usec_t *ret); int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space); + +int open_tmpfile_unlinkable(const char *directory, int flags); +int open_tmpfile_linkable(const char *target, int flags, char **ret_path); + +int link_tmpfile(int fd, const char *path, const char *target); diff --git a/src/systemd/src/basic/fs-util.c b/src/systemd/src/basic/fs-util.c index 9a84364420..1e09366f20 100644 --- a/src/systemd/src/basic/fs-util.c +++ b/src/systemd/src/basic/fs-util.c @@ -44,6 +44,7 @@ #endif /* NM_IGNORED */ #include "parse-util.h" #include "path-util.h" +#include "stdio-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -151,6 +152,7 @@ int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char return 0; } +#endif /* NM_IGNORED */ int readlinkat_malloc(int fd, const char *p, char **ret) { size_t l = 100; @@ -189,6 +191,7 @@ int readlink_malloc(const char *p, char **ret) { return readlinkat_malloc(AT_FDCWD, p, ret); } +#if 0 /* NM_IGNORED */ int readlink_value(const char *p, char **ret) { _cleanup_free_ char *link = NULL; char *value; @@ -504,4 +507,18 @@ int get_files_in_directory(const char *path, char ***list) { return n; } + +int inotify_add_watch_fd(int fd, int what, uint32_t mask) { + char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; + int r; + + /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */ + xsprintf(path, "/proc/self/fd/%i", what); + + r = inotify_add_watch(fd, path, mask); + if (r < 0) + return -errno; + + return r; +} #endif /* NM_IGNORED */ diff --git a/src/systemd/src/basic/fs-util.h b/src/systemd/src/basic/fs-util.h index 0d23f8635f..517b599d6f 100644 --- a/src/systemd/src/basic/fs-util.h +++ b/src/systemd/src/basic/fs-util.h @@ -72,3 +72,5 @@ union inotify_event_buffer { struct inotify_event ev; uint8_t raw[INOTIFY_EVENT_MAX]; }; + +int inotify_add_watch_fd(int fd, int what, uint32_t mask); diff --git a/src/systemd/src/basic/hashmap.c b/src/systemd/src/basic/hashmap.c index 4df3ae73ef..d76ee3fabd 100644 --- a/src/systemd/src/basic/hashmap.c +++ b/src/systemd/src/basic/hashmap.c @@ -1777,20 +1777,18 @@ int set_consume(Set *s, void *value) { int set_put_strdup(Set *s, const char *p) { char *c; - int r; assert(s); assert(p); + if (set_contains(s, (char*) p)) + return 0; + c = strdup(p); if (!c) return -ENOMEM; - r = set_consume(s, c); - if (r == -EEXIST) - return 0; - - return r; + return set_consume(s, c); } int set_put_strdupv(Set *s, char **l) { diff --git a/src/systemd/src/basic/hostname-util.c b/src/systemd/src/basic/hostname-util.c index ee48b86dd2..480f9d9de6 100644 --- a/src/systemd/src/basic/hostname-util.c +++ b/src/systemd/src/basic/hostname-util.c @@ -180,16 +180,16 @@ bool is_localhost(const char *hostname) { assert(hostname); /* This tries to identify local host and domain names - * described in RFC6761 plus the redhatism of .localdomain */ + * described in RFC6761 plus the redhatism of localdomain */ return strcaseeq(hostname, "localhost") || strcaseeq(hostname, "localhost.") || - strcaseeq(hostname, "localdomain.") || - strcaseeq(hostname, "localdomain") || + strcaseeq(hostname, "localhost.localdomain") || + strcaseeq(hostname, "localhost.localdomain.") || endswith_no_case(hostname, ".localhost") || endswith_no_case(hostname, ".localhost.") || - endswith_no_case(hostname, ".localdomain") || - endswith_no_case(hostname, ".localdomain."); + endswith_no_case(hostname, ".localhost.localdomain") || + endswith_no_case(hostname, ".localhost.localdomain."); } #if 0 /* NM_IGNORED */ diff --git a/src/systemd/src/basic/io-util.c b/src/systemd/src/basic/io-util.c index aaf414f400..61b667f062 100644 --- a/src/systemd/src/basic/io-util.c +++ b/src/systemd/src/basic/io-util.c @@ -35,6 +35,11 @@ int flush_fd(int fd) { .events = POLLIN, }; + /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything + * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read + * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used + * was set to non-blocking too. */ + for (;;) { char buf[LINE_MAX]; ssize_t l; diff --git a/src/systemd/src/basic/parse-util.c b/src/systemd/src/basic/parse-util.c index eb53c42d75..57893aa523 100644 --- a/src/systemd/src/basic/parse-util.c +++ b/src/systemd/src/basic/parse-util.c @@ -28,9 +28,7 @@ #include <xlocale.h> #include "alloc-util.h" -#if 0 /* NM_IGNORED */ #include "extract-word.h" -#endif /* NM_IGNORED */ #include "macro.h" #include "parse-util.h" #include "string-util.h" diff --git a/src/systemd/src/basic/parse-util.h b/src/systemd/src/basic/parse-util.h index d8dc26a36e..7dc579a159 100644 --- a/src/systemd/src/basic/parse-util.h +++ b/src/systemd/src/basic/parse-util.h @@ -90,6 +90,18 @@ static inline int safe_atoli(const char *s, long int *ret_u) { } #endif +#if SIZE_MAX == UINT_MAX +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(unsigned)); + return safe_atou(s, (unsigned *) ret_u); +} +#else +static inline int safe_atozu(const char *s, size_t *ret_u) { + assert_cc(sizeof(size_t) == sizeof(long unsigned)); + return safe_atolu(s, ret_u); +} +#endif + int safe_atod(const char *s, double *ret_d); int parse_fractional_part_u(const char **s, size_t digits, unsigned *res); diff --git a/src/systemd/src/basic/path-util.c b/src/systemd/src/basic/path-util.c index c3b7d187a0..8c4dec5b6c 100644 --- a/src/systemd/src/basic/path-util.c +++ b/src/systemd/src/basic/path-util.c @@ -34,9 +34,7 @@ #undef basename #include "alloc-util.h" -#if 0 /* NM_IGNORED */ #include "extract-word.h" -#endif /* NM_IGNORED */ #include "fs-util.h" #include "log.h" #include "macro.h" @@ -580,10 +578,10 @@ static int binary_is_good(const char *binary) { if (r < 0) return r; - return !path_equal(d, "true") && - !path_equal(d, "/bin/true") && - !path_equal(d, "/usr/bin/true") && - !path_equal(d, "/dev/null"); + return !PATH_IN_SET(d, "true" + "/bin/true", + "/usr/bin/true", + "/dev/null"); } int fsck_exists(const char *fstype) { @@ -769,34 +767,53 @@ char *file_in_same_dir(const char *path, const char *filename) { return ret; } -bool hidden_file_allow_backup(const char *filename) { - assert(filename); - - return - filename[0] == '.' || - streq(filename, "lost+found") || - streq(filename, "aquota.user") || - streq(filename, "aquota.group") || - endswith(filename, ".rpmnew") || - endswith(filename, ".rpmsave") || - endswith(filename, ".rpmorig") || - endswith(filename, ".dpkg-old") || - endswith(filename, ".dpkg-new") || - endswith(filename, ".dpkg-tmp") || - endswith(filename, ".dpkg-dist") || - endswith(filename, ".dpkg-bak") || - endswith(filename, ".dpkg-backup") || - endswith(filename, ".dpkg-remove") || - endswith(filename, ".swp"); -} +bool hidden_or_backup_file(const char *filename) { + const char *p; -bool hidden_file(const char *filename) { assert(filename); - if (endswith(filename, "~")) + if (filename[0] == '.' || + streq(filename, "lost+found") || + streq(filename, "aquota.user") || + streq(filename, "aquota.group") || + endswith(filename, "~")) return true; - return hidden_file_allow_backup(filename); + p = strrchr(filename, '.'); + if (!p) + return false; + + /* Please, let's not add more entries to the list below. If external projects think it's a good idea to come up + * with always new suffixes and that everybody else should just adjust to that, then it really should be on + * them. Hence, in future, let's not add any more entries. Instead, let's ask those packages to instead adopt + * one of the generic suffixes/prefixes for hidden files or backups, possibly augmented with an additional + * string. Specifically: there's now: + * + * The generic suffixes "~" and ".bak" for backup files + * The generic prefix "." for hidden files + * + * Thus, if a new package manager "foopkg" wants its own set of ".foopkg-new", ".foopkg-old", ".foopkg-dist" + * or so registered, let's refuse that and ask them to use ".foopkg.new", ".foopkg.old" or ".foopkg~" instead. + */ + + return STR_IN_SET(p + 1, + "rpmnew", + "rpmsave", + "rpmorig", + "dpkg-old", + "dpkg-new", + "dpkg-tmp", + "dpkg-dist", + "dpkg-bak", + "dpkg-backup", + "dpkg-remove", + "ucf-new", + "ucf-old", + "ucf-dist", + "swp", + "bak", + "old", + "new"); } bool is_device_path(const char *path) { diff --git a/src/systemd/src/basic/path-util.h b/src/systemd/src/basic/path-util.h index 2c2f87a9f2..a27c13fcc3 100644 --- a/src/systemd/src/basic/path-util.h +++ b/src/systemd/src/basic/path-util.h @@ -48,6 +48,23 @@ bool path_equal(const char *a, const char *b) _pure_; bool path_equal_or_files_same(const char *a, const char *b); char* path_join(const char *root, const char *path, const char *rest); +static inline bool path_equal_ptr(const char *a, const char *b) { + return !!a == !!b && (!a || path_equal(a, b)); +} + +/* Note: the search terminates on the first NULL item. */ +#define PATH_IN_SET(p, ...) \ + ({ \ + char **s; \ + bool _found = false; \ + STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \ + if (path_equal(p, *s)) { \ + _found = true; \ + break; \ + } \ + _found; \ + }) + int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *prefix); char** path_strv_resolve_uniq(char **l, const char *prefix); @@ -105,7 +122,6 @@ bool path_is_safe(const char *p) _pure_; char *file_in_same_dir(const char *path, const char *filename); -bool hidden_file_allow_backup(const char *filename); -bool hidden_file(const char *filename) _pure_; +bool hidden_or_backup_file(const char *filename) _pure_; bool is_device_path(const char *path); diff --git a/src/systemd/src/basic/signal-util.h b/src/systemd/src/basic/signal-util.h new file mode 100644 index 0000000000..dfd6eb564d --- /dev/null +++ b/src/systemd/src/basic/signal-util.h @@ -0,0 +1,56 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010-2015 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <signal.h> + +#include "macro.h" + +int reset_all_signal_handlers(void); +int reset_signal_mask(void); + +int ignore_signals(int sig, ...); +int default_signals(int sig, ...); +int sigaction_many(const struct sigaction *sa, ...); + +int sigset_add_many(sigset_t *ss, ...); +int sigprocmask_many(int how, sigset_t *old, ...); + +const char *signal_to_string(int i) _const_; +int signal_from_string(const char *s) _pure_; + +int signal_from_string_try_harder(const char *s); + +void nop_signal_handler(int sig); + +static inline void block_signals_reset(sigset_t *ss) { + assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); +} + +#define BLOCK_SIGNALS(...) \ + _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ + sigset_t t; \ + assert_se(sigprocmask_many(SIG_BLOCK, &t, __VA_ARGS__, -1) >= 0); \ + t; \ + }) + +static inline bool SIGNAL_VALID(int signo) { + return signo > 0 && signo < _NSIG; +} diff --git a/src/systemd/src/basic/socket-util.c b/src/systemd/src/basic/socket-util.c index c68db7c32f..f4fa37127a 100644 --- a/src/systemd/src/basic/socket-util.c +++ b/src/systemd/src/basic/socket-util.c @@ -25,6 +25,7 @@ #include <net/if.h> #include <netdb.h> #include <netinet/ip.h> +#include <poll.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -48,9 +49,11 @@ #include "socket-util.h" #include "string-table.h" #include "string-util.h" +#include "strv.h" #if 0 /* NM_IGNORED */ #include "user-util.h" #endif /* NM_IGNORED */ +#include "utf8.h" #include "util.h" #if 0 /* NM_IGNORED */ @@ -803,6 +806,42 @@ static const char* const ip_tos_table[] = { DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff); +bool ifname_valid(const char *p) { + bool numeric = true; + + /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources + * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We + * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */ + + if (isempty(p)) + return false; + + if (strlen(p) >= IFNAMSIZ) + return false; + + if (STR_IN_SET(p, ".", "..")) + return false; + + while (*p) { + if ((unsigned char) *p >= 127U) + return false; + + if ((unsigned char) *p <= 32U) + return false; + + if (*p == ':' || *p == '/') + return false; + + numeric = numeric && (*p >= '0' && *p <= '9'); + p++; + } + + if (numeric) + return false; + + return true; +} + int getpeercred(int fd, struct ucred *ucred) { socklen_t n = sizeof(struct ucred); struct ucred u; @@ -980,3 +1019,42 @@ fallback: return (ssize_t) k; } + +int flush_accept(int fd) { + + struct pollfd pollfd = { + .fd = fd, + .events = POLLIN, + }; + int r; + + + /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */ + + for (;;) { + int cfd; + + r = poll(&pollfd, 1, 0); + if (r < 0) { + if (errno == EINTR) + continue; + + return -errno; + + } else if (r == 0) + return 0; + + cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); + if (cfd < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return 0; + + return -errno; + } + + close(cfd); + } +} diff --git a/src/systemd/src/basic/socket-util.h b/src/systemd/src/basic/socket-util.h index d17a2f35f8..e9230e4a9f 100644 --- a/src/systemd/src/basic/socket-util.h +++ b/src/systemd/src/basic/socket-util.h @@ -123,6 +123,8 @@ int fd_inc_rcvbuf(int fd, size_t n); int ip_tos_to_string_alloc(int i, char **s); int ip_tos_from_string(const char *s); +bool ifname_valid(const char *p); + int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); @@ -135,5 +137,18 @@ int receive_one_fd(int transport_fd, int flags); ssize_t next_datagram_size_fd(int fd); +int flush_accept(int fd); + #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) + +/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */ +#define SOCKADDR_UN_LEN(sa) \ + ({ \ + const struct sockaddr_un *_sa = &(sa); \ + assert(_sa->sun_family == AF_UNIX); \ + offsetof(struct sockaddr_un, sun_path) + \ + (_sa->sun_path[0] == 0 ? \ + 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \ + strnlen(_sa->sun_path, sizeof(_sa->sun_path))); \ + }) diff --git a/src/systemd/src/basic/string-table.h b/src/systemd/src/basic/string-table.h index b180488fe8..d88625fca7 100644 --- a/src/systemd/src/basic/string-table.h +++ b/src/systemd/src/basic/string-table.h @@ -56,26 +56,8 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k return (type) string_table_lookup(name##_table, ELEMENTSOF(name##_table), s); \ } -#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ - _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ - struct __useless_struct_to_allow_trailing_semicolon__ - -#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) -#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) - -#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) - -/* For string conversions where numbers are also acceptable */ -#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ - int name##_to_string_alloc(type i, char **str) { \ +#define _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,scope) \ + scope int name##_to_string_alloc(type i, char **str) { \ char *s; \ if (i < 0 || i > max) \ return -ERANGE; \ @@ -89,7 +71,9 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k } \ *str = s; \ return 0; \ - } \ + } + +#define _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,scope) \ type name##_from_string(const char *s) { \ type i; \ unsigned u = 0; \ @@ -102,4 +86,32 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k return (type) u; \ return (type) -1; \ } \ + + +#define _DEFINE_STRING_TABLE_LOOKUP(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ + +#define _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,scope) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_WITH_BOOLEAN(name,type,yes,scope) \ + struct __useless_struct_to_allow_trailing_semicolon__ + +#define DEFINE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP(name,type) _DEFINE_STRING_TABLE_LOOKUP(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_TO_STRING(name,type,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(name,type) _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING(name,type,static) + +#define DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes) _DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(name,type,yes,) + +/* For string conversions where numbers are also acceptable */ +#define DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,) \ struct __useless_struct_to_allow_trailing_semicolon__ + +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(name,type,max,static) +#define DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max) \ + _DEFINE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(name,type,max,static) diff --git a/src/systemd/src/basic/string-util.h b/src/systemd/src/basic/string-util.h index ad0c813761..139cc8c91b 100644 --- a/src/systemd/src/basic/string-util.h +++ b/src/systemd/src/basic/string-util.h @@ -37,6 +37,7 @@ #define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS #define ALPHANUMERICAL LETTERS DIGITS +#define HEXDIGITS DIGITS "abcdefABCDEF" #define streq(a,b) (strcmp((a),(b)) == 0) #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) diff --git a/src/systemd/src/basic/strv.c b/src/systemd/src/basic/strv.c index e885c5981e..4ee2e5cd69 100644 --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -28,9 +28,7 @@ #include "alloc-util.h" #include "escape.h" -#if 0 /* NM_IGNORED */ #include "extract-word.h" -#endif /* NM_IGNORED */ #include "fileio.h" #include "string-util.h" #include "strv.h" @@ -564,6 +562,42 @@ int strv_extend(char ***l, const char *value) { return strv_consume(l, v); } +int strv_extend_front(char ***l, const char *value) { + size_t n, m; + char *v, **c; + + assert(l); + + /* Like strv_extend(), but prepends rather than appends the new entry */ + + if (!value) + return 0; + + n = strv_length(*l); + + /* Increase and overflow check. */ + m = n + 2; + if (m < n) + return -ENOMEM; + + v = strdup(value); + if (!v) + return -ENOMEM; + + c = realloc_multiply(*l, sizeof(char*), m); + if (!c) { + free(v); + return -ENOMEM; + } + + memmove(c+1, c, n * sizeof(char*)); + c[0] = v; + c[n+1] = NULL; + + *l = c; + return 0; +} + char **strv_uniq(char **l) { char **i; diff --git a/src/systemd/src/basic/strv.h b/src/systemd/src/basic/strv.h index 4a93818a42..f61bbb5386 100644 --- a/src/systemd/src/basic/strv.h +++ b/src/systemd/src/basic/strv.h @@ -25,9 +25,7 @@ #include <stddef.h> #include "alloc-util.h" -#if 0 /* NM_IGNORED */ #include "extract-word.h" -#endif /* NM_IGNORED */ #include "macro.h" #include "util.h" @@ -52,6 +50,7 @@ int strv_extend_strv(char ***a, char **b, bool filter_duplicates); int strv_extend_strv_concat(char ***a, char **b, const char *suffix); int strv_extend(char ***l, const char *value); int strv_extendf(char ***l, const char *format, ...) _printf_(2,0); +int strv_extend_front(char ***l, const char *value); int strv_push(char ***l, char *value); int strv_push_pair(char ***l, char *a, char *b); int strv_push_prepend(char ***l, char *value); @@ -81,9 +80,7 @@ static inline bool strv_isempty(char * const *l) { char **strv_split(const char *s, const char *separator); char **strv_split_newlines(const char *s); -#if 0 /* NM_IGNORED */ int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); -#endif /* NM_IGNORED */ char *strv_join(char **l, const char *separator); char *strv_join_quoted(char **l); diff --git a/src/systemd/src/basic/time-util.c b/src/systemd/src/basic/time-util.c index 5b2b2180d8..ecff608712 100644 --- a/src/systemd/src/basic/time-util.c +++ b/src/systemd/src/basic/time-util.c @@ -49,15 +49,12 @@ static clockid_t map_clock_id(clockid_t c) { /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will * fail for them. Since they are essentially the same as their non-ALARM pendants (their only difference is * when timers are set on them), let's just map them accordingly. This way, we can get the correct time even on - * those archs. - * - * Also, older kernels don't support CLOCK_BOOTTIME: fall back to CLOCK_MONOTONIC. */ + * those archs. */ switch (c) { - case CLOCK_BOOTTIME: case CLOCK_BOOTTIME_ALARM: - return clock_boottime_or_monotonic (); + return CLOCK_BOOTTIME; case CLOCK_REALTIME_ALARM: return CLOCK_REALTIME; @@ -1089,22 +1086,31 @@ bool timezone_is_valid(const char *name) { return true; } -clockid_t clock_boottime_or_monotonic(void) { - static clockid_t clock = -1; - int fd; - - if (clock != -1) - return clock; - - fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); - if (fd < 0) - clock = CLOCK_MONOTONIC; - else { - safe_close(fd); - clock = CLOCK_BOOTTIME; +bool clock_boottime_supported(void) { + static int supported = -1; + + /* Note that this checks whether CLOCK_BOOTTIME is available in general as well as available for timerfds()! */ + + if (supported < 0) { + int fd; + + fd = timerfd_create(CLOCK_BOOTTIME, TFD_NONBLOCK|TFD_CLOEXEC); + if (fd < 0) + supported = false; + else { + safe_close(fd); + supported = true; + } } - return clock; + return supported; +} + +clockid_t clock_boottime_or_monotonic(void) { + if (clock_boottime_supported()) + return CLOCK_BOOTTIME; + else + return CLOCK_MONOTONIC; } #if 0 /* NM_IGNORED */ diff --git a/src/systemd/src/basic/time-util.h b/src/systemd/src/basic/time-util.h index 77e3cd08d4..a5e3f567ec 100644 --- a/src/systemd/src/basic/time-util.h +++ b/src/systemd/src/basic/time-util.h @@ -112,6 +112,7 @@ bool ntp_synced(void); int get_timezones(char ***l); bool timezone_is_valid(const char *name); +bool clock_boottime_supported(void); clockid_t clock_boottime_or_monotonic(void); #define xstrftime(buf, fmt, tm) \ diff --git a/src/systemd/src/basic/util.c b/src/systemd/src/basic/util.c index 6d641a4a3d..39eb79e360 100644 --- a/src/systemd/src/basic/util.c +++ b/src/systemd/src/basic/util.c @@ -60,13 +60,14 @@ #include "process-util.h" #endif /* NM_IGNORED */ #include "set.h" -#if 0 /* NM_IGNORED */ #include "signal-util.h" +#if 0 /* NM_IGNORED */ #include "stat-util.h" #endif /* NM_IGNORED */ #include "string-util.h" #include "strv.h" #include "time-util.h" +#include "umask-util.h" #if 0 /* NM_IGNORED */ #include "user-util.h" #endif /* NM_IGNORED */ @@ -436,13 +437,17 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa _exit(EXIT_FAILURE); } - if (!stdout_is_tty) - dup2(fd, STDOUT_FILENO); + if (!stdout_is_tty && dup2(fd, STDOUT_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } - if (!stderr_is_tty) - dup2(fd, STDERR_FILENO); + if (!stderr_is_tty && dup2(fd, STDERR_FILENO) < 0) { + log_error_errno(errno, "Failed to dup2 /dev/tty: %m"); + _exit(EXIT_FAILURE); + } - if (fd > 2) + if (fd > STDERR_FILENO) close(fd); } @@ -534,7 +539,7 @@ int on_ac_power(void) { if (!de) break; - if (hidden_file(de->d_name)) + if (hidden_or_backup_file(de->d_name)) continue; device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY); @@ -790,15 +795,25 @@ uint64_t physical_memory(void) { return (uint64_t) mem * (uint64_t) page_size(); } -int update_reboot_param_file(const char *param) { - int r = 0; +int update_reboot_parameter_and_warn(const char *param) { + int r; + + if (isempty(param)) { + if (unlink("/run/systemd/reboot-param") < 0) { + if (errno == ENOENT) + return 0; + + return log_warning_errno(errno, "Failed to unlink reboot parameter file: %m"); + } + + return 0; + } - if (param) { - r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE); + RUN_WITH_UMASK(0022) { + r = write_string_file("/run/systemd/reboot-param", param, WRITE_STRING_FILE_CREATE); if (r < 0) - return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m"); - } else - (void) unlink(REBOOT_PARAM_FILE); + return log_warning_errno(r, "Failed to write reboot parameter file: %m"); + } return 0; } diff --git a/src/systemd/src/basic/util.h b/src/systemd/src/basic/util.h index 3225269acd..4b927e2e26 100644 --- a/src/systemd/src/basic/util.h +++ b/src/systemd/src/basic/util.h @@ -188,6 +188,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int uint64_t physical_memory(void); -int update_reboot_param_file(const char *param); +int update_reboot_parameter_and_warn(const char *param); int version(void); diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/systemd/src/libsystemd-network/dhcp-identifier.c index c7a3eac5b7..69eecd0234 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.c @@ -39,6 +39,37 @@ #define SYSTEMD_PEN 43793 #define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09) +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { + struct duid d; + + assert_cc(sizeof(d.raw) >= MAX_DUID_LEN); + if (duid_len > MAX_DUID_LEN) + return -EINVAL; + + switch (duid_type) { + case DUID_TYPE_LLT: + if (duid_len <= sizeof(d.llt)) + return -EINVAL; + break; + case DUID_TYPE_EN: + if (duid_len != sizeof(d.en)) + return -EINVAL; + break; + case DUID_TYPE_LL: + if (duid_len <= sizeof(d.ll)) + return -EINVAL; + break; + case DUID_TYPE_UUID: + if (duid_len != sizeof(d.uuid)) + return -EINVAL; + break; + default: + /* accept unknown type in order to be forward compatible */ + break; + } + return 0; +} + int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) { sd_id128_t machine_id; uint64_t hash; diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/systemd/src/libsystemd-network/dhcp-identifier.h index babae15c5b..1cc0f9fb71 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/systemd/src/libsystemd-network/dhcp-identifier.h @@ -26,7 +26,6 @@ #include "unaligned.h" typedef enum DUIDType { - DUID_TYPE_RAW = 0, DUID_TYPE_LLT = 1, DUID_TYPE_EN = 2, DUID_TYPE_LL = 3, @@ -40,27 +39,28 @@ typedef enum DUIDType { */ #define MAX_DUID_LEN 128 +/* https://tools.ietf.org/html/rfc3315#section-9.1 */ struct duid { be16_t type; union { struct { - /* DHCP6_DUID_LLT */ + /* DUID_TYPE_LLT */ uint16_t htype; uint32_t time; uint8_t haddr[0]; } _packed_ llt; struct { - /* DHCP6_DUID_EN */ + /* DUID_TYPE_EN */ uint32_t pen; uint8_t id[8]; } _packed_ en; struct { - /* DHCP6_DUID_LL */ + /* DUID_TYPE_LL */ int16_t htype; uint8_t haddr[0]; } _packed_ ll; struct { - /* DHCP6_DUID_UUID */ + /* DUID_TYPE_UUID */ sd_id128_t uuid; } _packed_ uuid; struct { @@ -69,34 +69,6 @@ struct duid { }; } _packed_; +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len); int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id); - -static inline int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { - struct duid d; - - assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); - - switch (duid_type) { - case DUID_TYPE_LLT: - if (duid_len <= sizeof(d.llt)) - return -EINVAL; - break; - case DUID_TYPE_EN: - if (duid_len != sizeof(d.en)) - return -EINVAL; - break; - case DUID_TYPE_LL: - if (duid_len <= sizeof(d.ll)) - return -EINVAL; - break; - case DUID_TYPE_UUID: - if (duid_len != sizeof(d.uuid)) - return -EINVAL; - break; - default: - /* accept unknown type in order to be forward compatible */ - break; - } - return 0; -} diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index 4662b0d847..99f690897d 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -65,4 +65,5 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum); #define DHCP_CLIENT_DONT_DESTROY(client) \ _cleanup_(sd_dhcp_client_unrefp) _unused_ sd_dhcp_client *_dont_destroy_##client = sd_dhcp_client_ref(client) -#define log_dhcp_client(client, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) +#define log_dhcp_client_errno(client, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCP CLIENT (0x%x): " fmt, client->xid, ##__VA_ARGS__) +#define log_dhcp_client(client, fmt, ...) log_dhcp_client_errno(client, 0, fmt, ##__VA_ARGS__) diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/systemd/src/libsystemd-network/dhcp-protocol.h index 3e32484c1d..5cf7abbff9 100644 --- a/src/systemd/src/libsystemd-network/dhcp-protocol.h +++ b/src/systemd/src/libsystemd-network/dhcp-protocol.h @@ -59,7 +59,7 @@ typedef struct DHCPPacket DHCPPacket; #define DHCP_IP_UDP_SIZE (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE) #define DHCP_MESSAGE_SIZE (int32_t)(sizeof(DHCPMessage)) #define DHCP_DEFAULT_MIN_SIZE 576 /* the minimum internet hosts must be able to receive */ -#define DHCP_MIN_OPTIONS_SIZE DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE +#define DHCP_MIN_OPTIONS_SIZE (DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE) #define DHCP_MAGIC_COOKIE (uint32_t)(0x63825363) enum { diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h index 749086d33a..945c3b9721 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h @@ -55,7 +55,8 @@ struct DHCP6IA { typedef struct DHCP6IA DHCP6IA; -#define log_dhcp6_client(p, fmt, ...) log_internal(LOG_DEBUG, 0, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) +#define log_dhcp6_client_errno(p, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "DHCPv6 CLIENT: " fmt, ##__VA_ARGS__) +#define log_dhcp6_client(p, fmt, ...) log_dhcp6_client_errno(p, 0, fmt, ##__VA_ARGS__) int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval); diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 55fcc1da03..25bad0f54b 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -31,11 +31,13 @@ #include "conf-parser.h" #endif /* NM_IGNORED */ #include "dhcp-lease-internal.h" +#include "ether-addr-util.h" #include "hexdecoct.h" #include "log.h" #include "network-internal.h" #include "parse-util.h" #include "siphash24.h" +#include "socket-util.h" #include "string-util.h" #include "strv.h" #include "utf8.h" @@ -180,58 +182,19 @@ int config_parse_net_condition(const char *unit, return 0; } -int config_parse_ifname(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - char **s = data; - _cleanup_free_ char *n = NULL; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - n = strdup(rvalue); - if (!n) - return log_oom(); - - if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue); - return 0; - } - - free(*s); - if (*n) { - *s = n; - n = NULL; - } else - *s = NULL; - - return 0; -} - -int config_parse_ifnames(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_ifnames( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { char ***sv = data; - const char *word, *state; - size_t l; int r; assert(filename); @@ -239,22 +202,27 @@ int config_parse_ifnames(const char *unit, assert(rvalue); assert(data); - FOREACH_WORD(word, l, rvalue, state) { - char *n; + for (;;) { + _cleanup_free_ char *word = NULL; - n = strndup(word, l); - if (!n) - return log_oom(); + r = extract_first_word(&rvalue, &word, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse interface name list: %s", rvalue); + return 0; + } + if (r == 0) + break; - if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue); - free(n); + if (!ifname_valid(word)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Interface name is not valid or too long, ignoring assignment: %s", rvalue); return 0; } - r = strv_consume(sv, n); + r = strv_push(sv, word); if (r < 0) return log_oom(); + + word = NULL; } return 0; @@ -310,6 +278,8 @@ int config_parse_hwaddr(const char *unit, void *userdata) { struct ether_addr **hwaddr = data; struct ether_addr *n; + const char *start; + size_t offset; int r; assert(filename); @@ -321,14 +291,10 @@ int config_parse_hwaddr(const char *unit, if (!n) return log_oom(); - r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - &n->ether_addr_octet[0], - &n->ether_addr_octet[1], - &n->ether_addr_octet[2], - &n->ether_addr_octet[3], - &n->ether_addr_octet[4], - &n->ether_addr_octet[5]); - if (r != 6) { + start = rvalue + strspn(rvalue, WHITESPACE); + r = ether_addr_from_string(start, n, &offset); + + if (r || (start[offset + strspn(start + offset, WHITESPACE)] != '\0')) { log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue); free(n); return 0; @@ -360,8 +326,9 @@ int config_parse_iaid(const char *unit, r = safe_atou32(rvalue, &iaid); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Unable to read IAID: %s", rvalue); - return r; + log_syntax(unit, LOG_ERR, filename, line, r, + "Unable to read IAID, ignoring assignment: %s", rvalue); + return 0; } *((uint32_t *)data) = iaid; @@ -385,28 +352,28 @@ void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) { int deserialize_in_addrs(struct in_addr **ret, const char *string) { _cleanup_free_ struct in_addr *addresses = NULL; int size = 0; - const char *word, *state; - size_t len; assert(ret); assert(string); - FOREACH_WORD(word, len, string, state) { - _cleanup_free_ char *addr_str = NULL; + for (;;) { + _cleanup_free_ char *word = NULL; struct in_addr *new_addresses; int r; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr)); if (!new_addresses) return -ENOMEM; else addresses = new_addresses; - addr_str = strndup(word, len); - if (!addr_str) - return -ENOMEM; - - r = inet_pton(AF_INET, addr_str, &(addresses[size])); + r = inet_pton(AF_INET, word, &(addresses[size])); if (r <= 0) continue; @@ -436,28 +403,28 @@ void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { _cleanup_free_ struct in6_addr *addresses = NULL; int size = 0; - const char *word, *state; - size_t len; assert(ret); assert(string); - FOREACH_WORD(word, len, string, state) { - _cleanup_free_ char *addr_str = NULL; + for (;;) { + _cleanup_free_ char *word = NULL; struct in6_addr *new_addresses; int r; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr)); if (!new_addresses) return -ENOMEM; else addresses = new_addresses; - addr_str = strndup(word, len); - if (!addr_str) - return -ENOMEM; - - r = inet_pton(AF_INET6, addr_str, &(addresses[size])); + r = inet_pton(AF_INET6, word, &(addresses[size])); if (r <= 0) continue; @@ -498,29 +465,29 @@ void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, siz int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { _cleanup_free_ struct sd_dhcp_route *routes = NULL; size_t size = 0, allocated = 0; - const char *word, *state; - size_t len; assert(ret); assert(ret_size); assert(ret_allocated); assert(string); - FOREACH_WORD(word, len, string, state) { - /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ - _cleanup_free_ char* entry = NULL; + /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ + for (;;) { + _cleanup_free_ char *word = NULL; char *tok, *tok_end; unsigned n; int r; - if (!GREEDY_REALLOC(routes, allocated, size + 1)) - return -ENOMEM; + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; - entry = strndup(word, len); - if (!entry) + if (!GREEDY_REALLOC(routes, allocated, size + 1)) return -ENOMEM; - tok = entry; + tok = word; /* get the subnet */ tok_end = strchr(tok, '/'); diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 955cc89870..e91d3d2918 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -51,10 +51,6 @@ int config_parse_hwaddr(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_ifname(const char *unit, const char *filename, unsigned line, - const char *section, unsigned section_line, const char *lvalue, - int ltype, const char *rvalue, void *data, void *userdata); - int config_parse_ifnames(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 758dba4b66..f740075a12 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -55,7 +55,7 @@ struct sd_dhcp_client { sd_event *event; int event_priority; sd_event_source *timeout_resend; - int index; + int ifindex; int fd; union sockaddr_union link; sd_event_source *receive_message; @@ -103,7 +103,7 @@ struct sd_dhcp_client { sd_event_source *timeout_t1; sd_event_source *timeout_t2; sd_event_source *timeout_expire; - sd_dhcp_client_callback_t cb; + sd_dhcp_client_callback_t callback; void *userdata; sd_dhcp_lease *lease; usec_t start_delay; @@ -117,17 +117,26 @@ static const uint8_t default_req_opts[] = { SD_DHCP_OPTION_DOMAIN_NAME_SERVER, }; -static int client_receive_message_raw(sd_event_source *s, int fd, - uint32_t revents, void *userdata); -static int client_receive_message_udp(sd_event_source *s, int fd, - uint32_t revents, void *userdata); +static int client_receive_message_raw( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata); +static int client_receive_message_udp( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata); static void client_stop(sd_dhcp_client *client, int error); -int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, - void *userdata) { +int sd_dhcp_client_set_callback( + sd_dhcp_client *client, + sd_dhcp_client_callback_t cb, + void *userdata) { + assert_return(client, -EINVAL); - client->cb = cb; + client->callback = cb; client->userdata = userdata; return 0; @@ -145,10 +154,10 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { size_t i; assert_return(client, -EINVAL); - assert_return (IN_SET(client->state, DHCP_STATE_INIT, - DHCP_STATE_STOPPED), -EBUSY); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); switch(option) { + case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_OVERLOAD: case SD_DHCP_OPTION_MESSAGE_TYPE: @@ -173,11 +182,12 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { return 0; } -int sd_dhcp_client_set_request_address(sd_dhcp_client *client, - const struct in_addr *last_addr) { +int sd_dhcp_client_set_request_address( + sd_dhcp_client *client, + const struct in_addr *last_addr) { + assert_return(client, -EINVAL); - assert_return (IN_SET(client->state, DHCP_STATE_INIT, - DHCP_STATE_STOPPED), -EBUSY); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); if (last_addr) client->last_addr = last_addr->s_addr; @@ -187,19 +197,22 @@ int sd_dhcp_client_set_request_address(sd_dhcp_client *client, return 0; } -int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) { - assert_return(client, -EINVAL); - assert_return (IN_SET(client->state, DHCP_STATE_INIT, - DHCP_STATE_STOPPED), -EBUSY); - assert_return(interface_index > 0, -EINVAL); +int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) { - client->index = interface_index; + assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); + assert_return(ifindex > 0, -EINVAL); + client->ifindex = ifindex; return 0; } -int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, - size_t addr_len, uint16_t arp_type) { +int sd_dhcp_client_set_mac( + sd_dhcp_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type) { + DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; @@ -220,8 +233,7 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, return 0; if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { - log_dhcp_client(client, "Changing MAC address on running DHCP " - "client, restarting"); + log_dhcp_client(client, "Changing MAC address on running DHCP client, restarting"); need_restart = true; client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); } @@ -236,8 +248,11 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, return 0; } -int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, - const uint8_t **data, size_t *data_len) { +int sd_dhcp_client_get_client_id( + sd_dhcp_client *client, + uint8_t *type, + const uint8_t **data, + size_t *data_len) { assert_return(client, -EINVAL); assert_return(type, -EINVAL); @@ -256,8 +271,12 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, return 0; } -int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, - const uint8_t *data, size_t data_len) { +int sd_dhcp_client_set_client_id( + sd_dhcp_client *client, + uint8_t type, + const uint8_t *data, + size_t data_len) { + DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; @@ -266,14 +285,17 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); switch (type) { + case ARPHRD_ETHER: if (data_len != ETH_ALEN) return -EINVAL; break; + case ARPHRD_INFINIBAND: if (data_len != INFINIBAND_ALEN) return -EINVAL; break; + default: break; } @@ -301,18 +323,37 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, } #if 0 /* NM_IGNORED */ -int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, - uint16_t duid_type, uint8_t *duid, size_t duid_len) { +/** + * Sets IAID and DUID. If duid is non-null, the DUID is set to duid_type + duid + * without further modification. Otherwise, if duid_type is supported, DUID + * is set based on that type. Otherwise, an error is returned. + */ +int sd_dhcp_client_set_iaid_duid( + sd_dhcp_client *client, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + DHCP_CLIENT_DONT_DESTROY(client); int r; + size_t len; + assert_return(client, -EINVAL); - zero(client->client_id); + assert_return(duid_len == 0 || duid != NULL, -EINVAL); + if (duid != NULL) { + r = dhcp_validate_duid_len(duid_type, duid_len); + if (r < 0) + return r; + } + + zero(client->client_id); client->client_id.type = 255; /* If IAID is not configured, generate it. */ if (iaid == 0) { - r = dhcp_identifier_set_iaid(client->index, client->mac_addr, + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid); if (r < 0) @@ -320,22 +361,18 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, } else client->client_id.ns.iaid = htobe32(iaid); - /* If DUID is not configured, generate DUID-EN. */ - if (duid_len == 0) { - r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, - &duid_len); - if (r < 0) - return r; - } else { - r = dhcp_validate_duid_len(client->client_id.type, duid_len); - if (r < 0) - return r; + if (duid != NULL) { client->client_id.ns.duid.type = htobe16(duid_type); memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len); - duid_len += sizeof(client->client_id.ns.duid.type); - } + len = sizeof(client->client_id.ns.duid.type) + duid_len; + } else if (duid_type == DUID_TYPE_EN) { + r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); + if (r < 0) + return r; + } else + return -EOPNOTSUPP; - client->client_id_len = sizeof(client->client_id.type) + duid_len + + client->client_id_len = sizeof(client->client_id.type) + len + sizeof(client->client_id.ns.iaid); if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { @@ -348,8 +385,10 @@ int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, } #endif /* NM_IGNORED */ -int sd_dhcp_client_set_hostname(sd_dhcp_client *client, - const char *hostname) { +int sd_dhcp_client_set_hostname( + sd_dhcp_client *client, + const char *hostname) { + char *new_hostname = NULL; assert_return(client, -EINVAL); @@ -372,8 +411,10 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client, return 0; } -int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, - const char *vci) { +int sd_dhcp_client_set_vendor_class_identifier( + sd_dhcp_client *client, + const char *vci) { + char *new_vci = NULL; assert_return(client, -EINVAL); @@ -400,28 +441,29 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) { int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { assert_return(client, -EINVAL); - assert_return(ret, -EINVAL); if (client->state != DHCP_STATE_BOUND && client->state != DHCP_STATE_RENEWING && client->state != DHCP_STATE_REBINDING) return -EADDRNOTAVAIL; - *ret = client->lease; + if (ret) + *ret = client->lease; return 0; } static void client_notify(sd_dhcp_client *client, int event) { - if (client->cb) - client->cb(client, event, client->userdata); + assert(client); + + if (client->callback) + client->callback(client, event, client->userdata); } static int client_initialize(sd_dhcp_client *client) { assert_return(client, -EINVAL); - client->receive_message = - sd_event_source_unref(client->receive_message); + client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); @@ -456,8 +498,13 @@ static void client_stop(sd_dhcp_client *client, int error) { client_initialize(client); } -static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, - uint8_t type, size_t *_optlen, size_t *_optoffset) { +static int client_message_init( + sd_dhcp_client *client, + DHCPPacket **ret, + uint8_t type, + size_t *_optlen, + size_t *_optoffset) { + _cleanup_free_ DHCPPacket *packet = NULL; size_t optlen, optoffset, size; be16_t max_size; @@ -525,7 +572,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, client->client_id.type = 255; - r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid); + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid); if (r < 0) return r; @@ -598,8 +645,12 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret, return 0; } -static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset, - const char *fqdn) { +static int client_append_fqdn_option( + DHCPMessage *message, + size_t optlen, + size_t *optoffset, + const char *fqdn) { + uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; int r; @@ -616,8 +667,11 @@ static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t return r; } -static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet, - size_t len) { +static int dhcp_client_send_raw( + sd_dhcp_client *client, + DHCPPacket *packet, + size_t len) { + dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT, INADDR_BROADCAST, DHCP_PORT_SERVER, len); @@ -704,8 +758,9 @@ static int client_send_request(sd_dhcp_client *client) { size_t optoffset, optlen; int r; - r = client_message_init(client, &request, DHCP_REQUEST, - &optlen, &optoffset); + assert(client); + + r = client_message_init(client, &request, DHCP_REQUEST, &optlen, &optoffset); if (r < 0) return r; @@ -802,18 +857,23 @@ static int client_send_request(sd_dhcp_client *client) { return r; switch (client->state) { + case DHCP_STATE_REQUESTING: log_dhcp_client(client, "REQUEST (requesting)"); break; + case DHCP_STATE_INIT_REBOOT: log_dhcp_client(client, "REQUEST (init-reboot)"); break; + case DHCP_STATE_RENEWING: log_dhcp_client(client, "REQUEST (renewing)"); break; + case DHCP_STATE_REBINDING: log_dhcp_client(client, "REQUEST (rebinding)"); break; + default: log_dhcp_client(client, "REQUEST (invalid)"); break; @@ -824,8 +884,11 @@ static int client_send_request(sd_dhcp_client *client) { static int client_start(sd_dhcp_client *client); -static int client_timeout_resend(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_resend( + sd_event_source *s, + uint64_t usec, + void *userdata) { + sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); usec_t next_timeout = 0; @@ -842,6 +905,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, goto error; switch (client->state) { + case DHCP_STATE_RENEWING: time_left = (client->lease->t2 - client->lease->t1) / 2; @@ -969,8 +1033,10 @@ error: return 0; } -static int client_initialize_io_events(sd_dhcp_client *client, - sd_event_io_handler_t io_callback) { +static int client_initialize_io_events( + sd_dhcp_client *client, + sd_event_io_handler_t io_callback) { + int r; assert(client); @@ -1037,8 +1103,7 @@ error: } -static int client_initialize_events(sd_dhcp_client *client, - sd_event_io_handler_t io_callback) { +static int client_initialize_events(sd_dhcp_client *client, sd_event_io_handler_t io_callback) { client_initialize_io_events(client, io_callback); client_initialize_time_events(client); @@ -1050,15 +1115,14 @@ static int client_start_delayed(sd_dhcp_client *client) { assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); - assert_return(client->index > 0, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); assert_return(client->fd < 0, -EBUSY); assert_return(client->xid == 0, -EINVAL); - assert_return(client->state == DHCP_STATE_INIT || - client->state == DHCP_STATE_INIT_REBOOT, -EBUSY); + assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_INIT_REBOOT), -EBUSY); client->xid = random_u32(); - r = dhcp_network_bind_raw_socket(client->index, &client->link, + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, client->mac_addr, client->mac_addr_len, client->arp_type); if (r < 0) { @@ -1078,8 +1142,7 @@ static int client_start(sd_dhcp_client *client) { return client_start_delayed(client); } -static int client_timeout_expire(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); @@ -1101,13 +1164,15 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) DHCP_CLIENT_DONT_DESTROY(client); int r; + assert(client); + client->receive_message = sd_event_source_unref(client->receive_message); client->fd = asynchronous_close(client->fd); client->state = DHCP_STATE_REBINDING; client->attempt = 1; - r = dhcp_network_bind_raw_socket(client->index, &client->link, + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, client->mac_addr, client->mac_addr_len, client->arp_type); if (r < 0) { @@ -1119,8 +1184,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) return client_initialize_events(client, client_receive_message_raw); } -static int client_timeout_t1(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); @@ -1130,8 +1194,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, return client_initialize_time_events(client); } -static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, - size_t len) { +static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_t len) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; int r; @@ -1182,8 +1245,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, return 0; } -static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, - size_t len) { +static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, size_t len) { int r; r = dhcp_option_parse(force, len, NULL, NULL, NULL); @@ -1195,8 +1257,7 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, return 0; } -static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, - size_t len) { +static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t len) { _cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; _cleanup_free_ char *error_message = NULL; int r; @@ -1424,8 +1485,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return 0; } -static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, - int len) { +static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, int len) { DHCP_CLIENT_DONT_DESTROY(client); char time_string[FORMAT_TIMESPAN_MAX]; int r = 0, notify_event = 0; @@ -1571,11 +1631,15 @@ error: return r; } -static int client_receive_message_udp(sd_event_source *s, int fd, - uint32_t revents, void *userdata) { +static int client_receive_message_udp( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + sd_dhcp_client *client = userdata; _cleanup_free_ DHCPMessage *message = NULL; - const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } }; + const struct ether_addr zero_mac = {}; const struct ether_addr *expected_chaddr = NULL; uint8_t expected_hlen = 0; ssize_t len, buflen; @@ -1591,14 +1655,14 @@ static int client_receive_message_udp(sd_event_source *s, int fd, if (!message) return -ENOMEM; - len = read(fd, message, buflen); + len = recv(fd, message, buflen, 0); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; - log_dhcp_client(client, "Could not receive message from UDP socket: %m"); - return -errno; - } else if ((size_t)len < sizeof(DHCPMessage)) { + return log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket: %m"); + } + if ((size_t) len < sizeof(DHCPMessage)) { log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); return 0; } @@ -1649,8 +1713,12 @@ static int client_receive_message_udp(sd_event_source *s, int fd, return client_handle_message(client, message, len); } -static int client_receive_message_raw(sd_event_source *s, int fd, - uint32_t revents, void *userdata) { +static int client_receive_message_raw( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + sd_dhcp_client *client = userdata; _cleanup_free_ DHCPPacket *packet = NULL; uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; @@ -1725,7 +1793,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) { r = client_start(client); if (r >= 0) - log_dhcp_client(client, "STARTED on ifindex %i", client->index); + log_dhcp_client(client, "STARTED on ifindex %i", client->ifindex); return r; } @@ -1769,8 +1837,7 @@ int sd_dhcp_client_detach_event(sd_dhcp_client *client) { } sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { - if (!client) - return NULL; + assert_return(client, NULL); return client->event; } @@ -1826,13 +1893,12 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) { client->n_ref = 1; client->state = DHCP_STATE_INIT; - client->index = -1; + client->ifindex = -1; client->fd = -1; client->attempt = 1; client->mtu = DHCP_DEFAULT_MIN_SIZE; client->req_opts_size = ELEMENTSOF(default_req_opts); - client->req_opts = memdup(default_req_opts, client->req_opts_size); if (!client->req_opts) return -ENOMEM; diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index 8fa1822f2d..a05bde637a 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -47,7 +47,7 @@ struct sd_dhcp6_client { enum DHCP6State state; sd_event *event; int event_priority; - int index; + int ifindex; struct in6_addr local_address; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; @@ -66,7 +66,7 @@ struct sd_dhcp6_client { uint8_t retransmit_count; sd_event_source *timeout_resend; sd_event_source *timeout_resend_expire; - sd_dhcp6_client_callback_t cb; + sd_dhcp6_client_callback_t callback; void *userdata; struct duid duid; size_t duid_len; @@ -113,27 +113,33 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); static int client_start(sd_dhcp6_client *client, enum DHCP6State state); -int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_callback_t cb, void *userdata) { +int sd_dhcp6_client_set_callback( + sd_dhcp6_client *client, + sd_dhcp6_client_callback_t cb, + void *userdata) { + assert_return(client, -EINVAL); - client->cb = cb; + client->callback = cb; client->userdata = userdata; return 0; } -int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) { - assert_return(client, -EINVAL); - assert_return(interface_index >= -1, -EINVAL); +int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) { + assert_return(client, -EINVAL); + assert_return(ifindex >= -1, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - client->index = interface_index; - + client->ifindex = ifindex; return 0; } -int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) { +int sd_dhcp6_client_set_local_address( + sd_dhcp6_client *client, + const struct in6_addr *local_address) { + assert_return(client, -EINVAL); assert_return(local_address, -EINVAL); assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL); @@ -182,20 +188,38 @@ static int client_ensure_duid(sd_dhcp6_client *client) { return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); } -int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type, - uint8_t *duid, size_t duid_len) { +/** + * Sets DUID. If duid is non-null, the DUID is set to duid_type + duid + * without further modification. Otherwise, if duid_type is supported, DUID + * is set based on that type. Otherwise, an error is returned. + */ +int sd_dhcp6_client_set_duid( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len) { + int r; assert_return(client, -EINVAL); + assert_return(duid_len == 0 || duid != NULL, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); - if (duid_len > 0) { + if (duid != NULL) { r = dhcp_validate_duid_len(duid_type, duid_len); if (r < 0) return r; + } + + if (duid != NULL) { client->duid.type = htobe16(duid_type); memcpy(&client->duid.raw.data, duid, duid_len); - client->duid_len = duid_len + sizeof(client->duid.type); - } + client->duid_len = sizeof(client->duid.type) + duid_len; + } else if (duid_type == DUID_TYPE_EN) { + r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); + if (r < 0) + return r; + } else + return -EOPNOTSUPP; return 0; } @@ -236,6 +260,7 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); switch(option) { + case SD_DHCP6_OPTION_DNS_SERVERS: case SD_DHCP6_OPTION_DOMAIN_LIST: case SD_DHCP6_OPTION_SNTP_SERVERS: @@ -272,20 +297,25 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) { } static void client_notify(sd_dhcp6_client *client, int event) { - if (client->cb) - client->cb(client, event, client->userdata); + assert(client); + + if (client->callback) + client->callback(client, event, client->userdata); } static void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) { + assert(client); + if (client->lease) { dhcp6_lease_clear_timers(&client->lease->ia); sd_dhcp6_lease_unref(client->lease); } + client->lease = lease; } static int client_reset(sd_dhcp6_client *client) { - assert_return(client, -EINVAL); + assert(client); client_set_lease(client, NULL); @@ -333,6 +363,8 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { usec_t elapsed_usec; be16_t elapsed_time; + assert(client); + len = sizeof(DHCP6Message) + optlen; message = malloc0(len); @@ -431,13 +463,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return 0; } -static int client_timeout_t2(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; - assert_return(s, -EINVAL); - assert_return(client, -EINVAL); - assert_return(client->lease, -EINVAL); + assert(s); + assert(client); + assert(client->lease); client->lease->ia.timeout_t2 = sd_event_source_unref(client->lease->ia.timeout_t2); @@ -449,13 +480,12 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, return 0; } -static int client_timeout_t1(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; - assert_return(s, -EINVAL); - assert_return(client, -EINVAL); - assert_return(client->lease, -EINVAL); + assert(s); + assert(client); + assert(client->lease); client->lease->ia.timeout_t1 = sd_event_source_unref(client->lease->ia.timeout_t1); @@ -467,8 +497,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, return 0; } -static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); enum DHCP6State state; @@ -494,8 +523,7 @@ static usec_t client_timeout_compute_random(usec_t val) { (random_u32() % (2 * USEC_PER_SEC)) * val / 10 / USEC_PER_SEC; } -static int client_timeout_resend(sd_event_source *s, uint64_t usec, - void *userdata) { +static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userdata) { int r = 0; sd_dhcp6_client *client = userdata; usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0; @@ -655,16 +683,18 @@ static int client_ensure_iaid(sd_dhcp6_client *client) { if (client->ia_na.id) return 0; - r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id); + r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->ia_na.id); if (r < 0) return r; return 0; } -static int client_parse_message(sd_dhcp6_client *client, - DHCP6Message *message, size_t len, - sd_dhcp6_lease *lease) { +static int client_parse_message( + sd_dhcp6_client *client, + DHCP6Message *message, + size_t len, + sd_dhcp6_lease *lease) { int r; uint8_t *optval, *option, *id = NULL; uint16_t optcode, status; @@ -672,6 +702,11 @@ static int client_parse_message(sd_dhcp6_client *client, bool clientid = false; be32_t iaid_lease; + assert(client); + assert(message); + assert(len >= sizeof(DHCP6Message)); + assert(lease); + option = (uint8_t *)message + sizeof(DHCP6Message); len -= sizeof(DHCP6Message); @@ -816,9 +851,12 @@ static int client_parse_message(sd_dhcp6_client *client, } static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { - int r; _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; bool rapid_commit; + int r; + + assert(client); + assert(reply); if (reply->type != DHCP6_REPLY) return 0; @@ -847,9 +885,9 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si } static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) { - int r; _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; uint8_t pref_advertise = 0, pref_lease = 0; + int r; if (advertise->type != DHCP6_ADVERTISE) return 0; @@ -880,7 +918,12 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver return r; } -static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) { +static int client_receive_message( + sd_event_source *s, + int fd, uint32_t + revents, + void *userdata) { + sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); _cleanup_free_ DHCP6Message *message = NULL; @@ -899,16 +942,18 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, if (!message) return -ENOMEM; - len = read(fd, message, buflen); + len = recv(fd, message, buflen, 0); if (len < 0) { if (errno == EAGAIN || errno == EINTR) return 0; - log_dhcp6_client(client, "Could not receive message from UDP socket: %m"); + return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m"); - return -errno; - } else if ((size_t)len < sizeof(DHCP6Message)) + } + if ((size_t) len < sizeof(DHCP6Message)) { + log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); return 0; + } switch(message->type) { case DHCP6_SOLICIT: @@ -929,8 +974,7 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, break; default: - log_dhcp6_client(client, "unknown message type %d", - message->type); + log_dhcp6_client(client, "Unknown message type %d", message->type); return 0; } @@ -989,10 +1033,9 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents, return 0; } - if (r >= 0) { + if (r >= 0) log_dhcp6_client(client, "Recv %s", dhcp6_message_type_to_string(message->type)); - } return 0; } @@ -1004,7 +1047,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); - assert_return(client->index > 0, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); assert_return(client->state != state, -EINVAL); client->timeout_resend_expire = @@ -1045,7 +1088,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { if (client->lease->ia.lifetime_t1 == 0xffffffff || client->lease->ia.lifetime_t2 == 0xffffffff) { - log_dhcp6_client(client, "infinite T1 0x%08x or T2 0x%08x", + log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x", be32toh(client->lease->ia.lifetime_t1), be32toh(client->lease->ia.lifetime_t2)); @@ -1137,12 +1180,12 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { } int sd_dhcp6_client_start(sd_dhcp6_client *client) { - int r = 0; enum DHCP6State state = DHCP6_STATE_SOLICITATION; + int r = 0; assert_return(client, -EINVAL); assert_return(client->event, -EINVAL); - assert_return(client->index > 0, -EINVAL); + assert_return(client->ifindex > 0, -EINVAL); assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL); if (!IN_SET(client->state, DHCP6_STATE_STOPPED)) @@ -1160,9 +1203,14 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { if (r < 0) return r; - r = dhcp6_network_bind_udp_socket(client->index, &client->local_address); - if (r < 0) - return r; + r = dhcp6_network_bind_udp_socket(client->ifindex, &client->local_address); + if (r < 0) { + _cleanup_free_ char *p = NULL; + + (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) &client->local_address, &p); + return log_dhcp6_client_errno(client, r, + "Failed to bind to UDP socket at address %s: %m", strna(p)); + } client->fd = r; @@ -1178,7 +1226,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { goto error; r = sd_event_source_set_description(client->receive_message, - "dhcp6-receive-message"); + "dhcp6-receive-message"); if (r < 0) goto error; @@ -1186,8 +1234,8 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { state = DHCP6_STATE_INFORMATION_REQUEST; log_dhcp6_client(client, "Started in %s mode", - client->information_request? "Information request": - "Managed"); + client->information_request? "Information request": + "Managed"); return client_start(client, state); @@ -1224,8 +1272,7 @@ int sd_dhcp6_client_detach_event(sd_dhcp6_client *client) { } sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { - if (!client) - return NULL; + assert_return(client, NULL); return client->event; } @@ -1273,15 +1320,11 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) { return -ENOMEM; client->n_ref = 1; - client->ia_na.type = SD_DHCP6_OPTION_IA_NA; - - client->index = -1; - + client->ifindex = -1; client->fd = -1; client->req_opts_len = ELEMENTSOF(default_req_opts); - client->req_opts = new0(be16_t, client->req_opts_len); if (!client->req_opts) return -ENOMEM; diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index 9b5ce7200c..598307951f 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -30,45 +30,30 @@ #include "alloc-util.h" #include "arp-util.h" +#include "ether-addr-util.h" #include "fd-util.h" #include "in-addr-util.h" #include "list.h" #include "random-util.h" -#include "refcnt.h" #include "siphash24.h" +#include "string-util.h" #include "util.h" /* Constants from the RFC */ -#define PROBE_WAIT 1 -#define PROBE_NUM 3 -#define PROBE_MIN 1 -#define PROBE_MAX 2 -#define ANNOUNCE_WAIT 2 -#define ANNOUNCE_NUM 2 -#define ANNOUNCE_INTERVAL 2 -#define MAX_CONFLICTS 10 -#define RATE_LIMIT_INTERVAL 60 -#define DEFEND_INTERVAL 10 - -#define IPV4ACD_NETWORK 0xA9FE0000L -#define IPV4ACD_NETMASK 0xFFFF0000L - -#define log_ipv4acd_full(ll, level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "ACD: " fmt, ##__VA_ARGS__) - -#define log_ipv4acd_debug(ll, ...) log_ipv4acd_full(ll, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_ipv4acd_info(ll, ...) log_ipv4acd_full(ll, LOG_INFO, 0, ##__VA_ARGS__) -#define log_ipv4acd_notice(ll, ...) log_ipv4acd_full(ll, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_ipv4acd_warning(ll, ...) log_ipv4acd_full(ll, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_ipv4acd_error(ll, ...) log_ipv4acd_full(ll, LOG_ERR, 0, ##__VA_ARGS__) - -#define log_ipv4acd_debug_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_ipv4acd_info_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_INFO, error, ##__VA_ARGS__) -#define log_ipv4acd_notice_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_ipv4acd_warning_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_WARNING, error, ##__VA_ARGS__) -#define log_ipv4acd_error_errno(ll, error, ...) log_ipv4acd_full(ll, LOG_ERR, error, ##__VA_ARGS__) +#define PROBE_WAIT_USEC (1U * USEC_PER_SEC) +#define PROBE_NUM 3U +#define PROBE_MIN_USEC (1U * USEC_PER_SEC) +#define PROBE_MAX_USEC (2U * USEC_PER_SEC) +#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC) +#define ANNOUNCE_NUM 2U +#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC) +#define MAX_CONFLICTS 10U +#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC) +#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC) typedef enum IPv4ACDState { IPV4ACD_STATE_INIT, + IPV4ACD_STATE_STARTED, IPV4ACD_STATE_WAITING_PROBE, IPV4ACD_STATE_PROBING, IPV4ACD_STATE_WAITING_ANNOUNCE, @@ -79,156 +64,164 @@ typedef enum IPv4ACDState { } IPv4ACDState; struct sd_ipv4acd { - RefCount n_ref; + unsigned n_ref; IPv4ACDState state; - int index; + int ifindex; int fd; - int iteration; - int conflict; - sd_event_source *receive_message; - sd_event_source *timer; + + unsigned n_iteration; + unsigned n_conflict; + + sd_event_source *receive_message_event_source; + sd_event_source *timer_event_source; + usec_t defend_window; be32_t address; + /* External */ struct ether_addr mac_addr; + sd_event *event; int event_priority; - sd_ipv4acd_callback_t cb; + sd_ipv4acd_callback_t callback; void* userdata; }; -sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll) { - if (ll) - assert_se(REFCNT_INC(ll->n_ref) >= 2); +#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__) +#define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) + +static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { + assert(acd); + assert(st < _IPV4ACD_STATE_MAX); + + if (st == acd->state && !reset_counter) + acd->n_iteration++; + else { + acd->state = st; + acd->n_iteration = 0; + } +} + +static void ipv4acd_reset(sd_ipv4acd *acd) { + assert(acd); + + acd->timer_event_source = sd_event_source_unref(acd->timer_event_source); + acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source); + + acd->fd = safe_close(acd->fd); + + ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true); +} + +sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd) { + if (!acd) + return NULL; + + assert_se(acd->n_ref >= 1); + acd->n_ref++; - return ll; + return acd; } -sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll) { - if (!ll || REFCNT_DEC(ll->n_ref) > 0) +sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) { + if (!acd) return NULL; - ll->receive_message = sd_event_source_unref(ll->receive_message); - ll->fd = safe_close(ll->fd); + assert_se(acd->n_ref >= 1); + acd->n_ref--; - ll->timer = sd_event_source_unref(ll->timer); + if (acd->n_ref > 0) + return NULL; - sd_ipv4acd_detach_event(ll); + ipv4acd_reset(acd); + sd_ipv4acd_detach_event(acd); - free(ll); + free(acd); return NULL; } int sd_ipv4acd_new(sd_ipv4acd **ret) { - _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *ll = NULL; + _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL; assert_return(ret, -EINVAL); - ll = new0(sd_ipv4acd, 1); - if (!ll) + acd = new0(sd_ipv4acd, 1); + if (!acd) return -ENOMEM; - ll->n_ref = REFCNT_INIT; - ll->state = IPV4ACD_STATE_INIT; - ll->index = -1; - ll->fd = -1; + acd->n_ref = 1; + acd->state = IPV4ACD_STATE_INIT; + acd->ifindex = -1; + acd->fd = -1; - *ret = ll; - ll = NULL; + *ret = acd; + acd = NULL; return 0; } -static void ipv4acd_set_state(sd_ipv4acd *ll, IPv4ACDState st, bool reset_counter) { - - assert(ll); - assert(st < _IPV4ACD_STATE_MAX); - - if (st == ll->state && !reset_counter) - ll->iteration++; - else { - ll->state = st; - ll->iteration = 0; - } -} +static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { + assert(acd); -static void ipv4acd_client_notify(sd_ipv4acd *ll, int event) { - assert(ll); + if (!acd->callback) + return; - if (ll->cb) - ll->cb(ll, event, ll->userdata); + acd->callback(acd, event, acd->userdata); } -static void ipv4acd_stop(sd_ipv4acd *ll) { - assert(ll); +int sd_ipv4acd_stop(sd_ipv4acd *acd) { + assert_return(acd, -EINVAL); - ll->receive_message = sd_event_source_unref(ll->receive_message); - ll->fd = safe_close(ll->fd); + ipv4acd_reset(acd); - ll->timer = sd_event_source_unref(ll->timer); + log_ipv4acd(acd, "STOPPED"); - log_ipv4acd_debug(ll, "STOPPED"); - - ipv4acd_set_state (ll, IPV4ACD_STATE_INIT, true); -} - -int sd_ipv4acd_stop(sd_ipv4acd *ll) { - assert_return(ll, -EINVAL); - - ipv4acd_stop(ll); - - ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_STOP); + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); return 0; } static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata); -static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) { +static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) { _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL; - usec_t next_timeout; - usec_t time_now; + usec_t next_timeout, time_now; int r; - assert(sec >= 0); - assert(random_sec >= 0); - assert(ll); + assert(acd); - next_timeout = sec * USEC_PER_SEC; + next_timeout = usec; - if (random_sec) - next_timeout += random_u32() % (random_sec * USEC_PER_SEC); + if (random_usec > 0) + next_timeout += (usec_t) random_u64() % random_usec; - assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0); + assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0); - r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(), - time_now + next_timeout, 0, ipv4acd_on_timeout, ll); + r = sd_event_add_time(acd->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, acd); if (r < 0) return r; - r = sd_event_source_set_priority(timer, ll->event_priority); + r = sd_event_source_set_priority(timer, acd->event_priority); if (r < 0) return r; - r = sd_event_source_set_description(timer, "ipv4acd-timer"); - if (r < 0) - return r; + (void) sd_event_source_set_description(timer, "ipv4acd-timer"); - ll->timer = sd_event_source_unref(ll->timer); - ll->timer = timer; + sd_event_source_unref(acd->timer_event_source); + acd->timer_event_source = timer; timer = NULL; return 0; } -static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) { - assert(ll); +static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) { + assert(acd); assert(arp); /* see the BPF */ - if (memcmp(arp->arp_spa, &ll->address, sizeof(ll->address)) == 0) + if (memcmp(arp->arp_spa, &acd->address, sizeof(acd->address)) == 0) return true; /* the TPA matched instead of the SPA, this is not a conflict */ @@ -236,294 +229,300 @@ static bool ipv4acd_arp_conflict(sd_ipv4acd *ll, struct ether_arp *arp) { } static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { - sd_ipv4acd *ll = userdata; + sd_ipv4acd *acd = userdata; int r = 0; - assert(ll); + assert(acd); + + switch (acd->state) { - switch (ll->state) { - case IPV4ACD_STATE_INIT: + case IPV4ACD_STATE_STARTED: + ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); - ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_PROBE, true); + if (acd->n_conflict >= MAX_CONFLICTS) { + char ts[FORMAT_TIMESPAN_MAX]; + log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0)); - if (ll->conflict >= MAX_CONFLICTS) { - log_ipv4acd_notice(ll, "Max conflicts reached, delaying by %us", RATE_LIMIT_INTERVAL); - r = ipv4acd_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT); + r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); if (r < 0) - goto out; + goto fail; - ll->conflict = 0; + acd->n_conflict = 0; } else { - r = ipv4acd_set_next_wakeup(ll, 0, PROBE_WAIT); + r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); if (r < 0) - goto out; + goto fail; } break; + case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: /* Send a probe */ - r = arp_send_probe(ll->fd, ll->index, ll->address, &ll->mac_addr); + r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { - log_ipv4acd_error_errno(ll, r, "Failed to send ARP probe: %m"); - goto out; + log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); + goto fail; } else { _cleanup_free_ char *address = NULL; - union in_addr_union addr = { .in.s_addr = ll->address }; + union in_addr_union addr = { .in.s_addr = acd->address }; - r = in_addr_to_string(AF_INET, &addr, &address); - if (r >= 0) - log_ipv4acd_debug(ll, "Probing %s", address); + (void) in_addr_to_string(AF_INET, &addr, &address); + log_ipv4acd(acd, "Probing %s", strna(address)); } - if (ll->iteration < PROBE_NUM - 2) { - ipv4acd_set_state(ll, IPV4ACD_STATE_PROBING, false); + if (acd->n_iteration < PROBE_NUM - 2) { + ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); - r = ipv4acd_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN)); + r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); if (r < 0) - goto out; + goto fail; } else { - ipv4acd_set_state(ll, IPV4ACD_STATE_WAITING_ANNOUNCE, true); + ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); - r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_WAIT, 0); + r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); if (r < 0) - goto out; + goto fail; } break; case IPV4ACD_STATE_ANNOUNCING: - if (ll->iteration >= ANNOUNCE_NUM - 1) { - ipv4acd_set_state(ll, IPV4ACD_STATE_RUNNING, false); - + if (acd->n_iteration >= ANNOUNCE_NUM - 1) { + ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); break; } + + /* fall through */ + case IPV4ACD_STATE_WAITING_ANNOUNCE: /* Send announcement packet */ - r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); + r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { - log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); - goto out; + log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); + goto fail; } else - log_ipv4acd_debug(ll, "ANNOUNCE"); + log_ipv4acd(acd, "ANNOUNCE"); - ipv4acd_set_state(ll, IPV4ACD_STATE_ANNOUNCING, false); + ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); - r = ipv4acd_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0); + r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); if (r < 0) - goto out; + goto fail; - if (ll->iteration == 0) { - ll->conflict = 0; - ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_BIND); + if (acd->n_iteration == 0) { + acd->n_conflict = 0; + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); } break; + default: assert_not_reached("Invalid state."); } -out: - if (r < 0) - sd_ipv4acd_stop(ll); + return 0; - return 1; +fail: + sd_ipv4acd_stop(acd); + return 0; } -static void ipv4acd_on_conflict(sd_ipv4acd *ll) { +static void ipv4acd_on_conflict(sd_ipv4acd *acd) { _cleanup_free_ char *address = NULL; - union in_addr_union addr = { .in.s_addr = ll->address }; - int r; + union in_addr_union addr = { .in.s_addr = acd->address }; - assert(ll); + assert(acd); - ll->conflict++; + acd->n_conflict++; - r = in_addr_to_string(AF_INET, &addr, &address); - if (r >= 0) - log_ipv4acd_debug(ll, "Conflict on %s (%u)", address, ll->conflict); + (void) in_addr_to_string(AF_INET, &addr, &address); + log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict); - ipv4acd_stop(ll); - - ipv4acd_client_notify(ll, SD_IPV4ACD_EVENT_CONFLICT); + ipv4acd_reset(acd); + ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); } -static int ipv4acd_on_packet(sd_event_source *s, int fd, - uint32_t revents, void *userdata) { - sd_ipv4acd *ll = userdata; +static int ipv4acd_on_packet( + sd_event_source *s, + int fd, + uint32_t revents, + void *userdata) { + + sd_ipv4acd *acd = userdata; struct ether_arp packet; + ssize_t n; int r; - assert(ll); + assert(s); + assert(acd); assert(fd >= 0); - r = read(fd, &packet, sizeof(struct ether_arp)); - if (r < (int) sizeof(struct ether_arp)) - goto out; + n = recv(fd, &packet, sizeof(struct ether_arp), 0); + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; + + log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); + goto fail; + } + if ((size_t) n != sizeof(struct ether_arp)) { + log_ipv4acd(acd, "Ignoring too short ARP packet."); + return 0; + } + + switch (acd->state) { - switch (ll->state) { case IPV4ACD_STATE_ANNOUNCING: case IPV4ACD_STATE_RUNNING: - if (ipv4acd_arp_conflict(ll, &packet)) { + + if (ipv4acd_arp_conflict(acd, &packet)) { usec_t ts; - assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &ts) >= 0); + assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0); /* Defend address */ - if (ts > ll->defend_window) { - ll->defend_window = ts + DEFEND_INTERVAL * USEC_PER_SEC; - r = arp_send_announcement(ll->fd, ll->index, ll->address, &ll->mac_addr); + if (ts > acd->defend_window) { + acd->defend_window = ts + DEFEND_INTERVAL_USEC; + r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) { - log_ipv4acd_error_errno(ll, r, "Failed to send ARP announcement: %m"); - goto out; + log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); + goto fail; } else - log_ipv4acd_debug(ll, "DEFEND"); + log_ipv4acd(acd, "DEFEND"); } else - ipv4acd_on_conflict(ll); + ipv4acd_on_conflict(acd); } - break; + case IPV4ACD_STATE_WAITING_PROBE: case IPV4ACD_STATE_PROBING: case IPV4ACD_STATE_WAITING_ANNOUNCE: /* BPF ensures this packet indicates a conflict */ - ipv4acd_on_conflict(ll); - + ipv4acd_on_conflict(acd); break; + default: assert_not_reached("Invalid state."); } -out: - if (r < 0) - sd_ipv4acd_stop(ll); + return 0; - return 1; +fail: + sd_ipv4acd_stop(acd); + return 0; } -int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index) { - assert_return(ll, -EINVAL); - assert_return(interface_index > 0, -EINVAL); - assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); +int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { + assert_return(acd, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - ll->index = interface_index; + acd->ifindex = ifindex; return 0; } -int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr) { - assert_return(ll, -EINVAL); +int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { + assert_return(acd, -EINVAL); assert_return(addr, -EINVAL); - assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - memcpy(&ll->mac_addr, addr, ETH_ALEN); + acd->mac_addr = *addr; return 0; } -int sd_ipv4acd_detach_event(sd_ipv4acd *ll) { - assert_return(ll, -EINVAL); +int sd_ipv4acd_detach_event(sd_ipv4acd *acd) { + assert_return(acd, -EINVAL); - ll->event = sd_event_unref(ll->event); + acd->event = sd_event_unref(acd->event); return 0; } -int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority) { +int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) { int r; - assert_return(ll, -EINVAL); - assert_return(!ll->event, -EBUSY); + assert_return(acd, -EINVAL); + assert_return(!acd->event, -EBUSY); if (event) - ll->event = sd_event_ref(event); + acd->event = sd_event_ref(event); else { - r = sd_event_default(&ll->event); + r = sd_event_default(&acd->event); if (r < 0) return r; } - ll->event_priority = priority; + acd->event_priority = priority; return 0; } -int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata) { - assert_return(ll, -EINVAL); +int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) { + assert_return(acd, -EINVAL); - ll->cb = cb; - ll->userdata = userdata; + acd->callback = cb; + acd->userdata = userdata; return 0; } -int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address) { - assert_return(ll, -EINVAL); +int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { + assert_return(acd, -EINVAL); assert_return(address, -EINVAL); - assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - ll->address = address->s_addr; + acd->address = address->s_addr; return 0; } -int sd_ipv4acd_is_running(sd_ipv4acd *ll) { - assert_return(ll, false); +int sd_ipv4acd_is_running(sd_ipv4acd *acd) { + assert_return(acd, false); - return ll->state != IPV4ACD_STATE_INIT; + return acd->state != IPV4ACD_STATE_INIT; } -static bool ether_addr_is_nul(const struct ether_addr *addr) { - const struct ether_addr nul_addr = {}; - - assert(addr); - - return memcmp(addr, &nul_addr, sizeof(struct ether_addr)) == 0; -} - -#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) - -int sd_ipv4acd_start(sd_ipv4acd *ll) { +int sd_ipv4acd_start(sd_ipv4acd *acd) { int r; - assert_return(ll, -EINVAL); - assert_return(ll->event, -EINVAL); - assert_return(ll->index > 0, -EINVAL); - assert_return(ll->address != 0, -EINVAL); - assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL); - assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY); + assert_return(acd, -EINVAL); + assert_return(acd->event, -EINVAL); + assert_return(acd->ifindex > 0, -EINVAL); + assert_return(acd->address != 0, -EINVAL); + assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL); + assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - ll->defend_window = 0; - - r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr); + r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr); if (r < 0) - goto out; + return r; - ll->fd = safe_close(ll->fd); - ll->fd = r; + safe_close(acd->fd); + acd->fd = r; + acd->defend_window = 0; + acd->n_conflict = 0; - r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd, - EPOLLIN, ipv4acd_on_packet, ll); + r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd); if (r < 0) - goto out; + goto fail; - r = sd_event_source_set_priority(ll->receive_message, ll->event_priority); + r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority); if (r < 0) - goto out; + goto fail; - r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message"); - if (r < 0) - goto out; + (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message"); - r = ipv4acd_set_next_wakeup(ll, 0, 0); + r = ipv4acd_set_next_wakeup(acd, 0, 0); if (r < 0) - goto out; -out: - if (r < 0) { - ipv4acd_stop(ll); - return r; - } + goto fail; + ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); return 0; + +fail: + ipv4acd_reset(acd); + return r; } diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index 391be15a36..dc2fa370b4 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -30,16 +30,17 @@ #include "sd-ipv4ll.h" #include "alloc-util.h" +#include "ether-addr-util.h" #include "in-addr-util.h" #include "list.h" #include "random-util.h" -#include "refcnt.h" #include "siphash24.h" #include "sparse-endian.h" +#include "string-util.h" #include "util.h" -#define IPV4LL_NETWORK 0xA9FE0000L -#define IPV4LL_NETMASK 0xFFFF0000L +#define IPV4LL_NETWORK UINT32_C(0xA9FE0000) +#define IPV4LL_NETMASK UINT32_C(0xFFFF0000) #define IPV4LL_DONT_DESTROY(ll) \ _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll) @@ -48,16 +49,28 @@ struct sd_ipv4ll { unsigned n_ref; sd_ipv4acd *acd; + be32_t address; /* the address pushed to ACD */ - struct random_data *random_data; - char *random_data_state; + struct ether_addr mac; + + struct { + le64_t value; + le64_t generation; + } seed; + bool seed_set; /* External */ be32_t claimed_address; - sd_ipv4ll_callback_t cb; + + sd_ipv4ll_callback_t callback; void* userdata; }; +#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__) +#define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) + +static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); + sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) { if (!ll) return NULL; @@ -79,16 +92,11 @@ sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) { return NULL; sd_ipv4acd_unref(ll->acd); - - free(ll->random_data); - free(ll->random_data_state); free(ll); return NULL; } -static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); - int sd_ipv4ll_new(sd_ipv4ll **ret) { _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL; int r; @@ -116,44 +124,32 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) { } int sd_ipv4ll_stop(sd_ipv4ll *ll) { - int r; - assert_return(ll, -EINVAL); - r = sd_ipv4acd_stop(ll->acd); - if (r < 0) - return r; - - return 0; + return sd_ipv4acd_stop(ll->acd); } -int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index) { +int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) { assert_return(ll, -EINVAL); + assert_return(ifindex > 0, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - return sd_ipv4acd_set_index(ll->acd, interface_index); + return sd_ipv4acd_set_ifindex(ll->acd, ifindex); } -#define HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) - int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { int r; assert_return(ll, -EINVAL); + assert_return(addr, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - if (!ll->random_data) { - uint64_t seed; - - /* If no random data is set, generate some from the MAC */ - seed = siphash24(&addr->ether_addr_octet, ETH_ALEN, HASH_KEY.bytes); - - assert_cc(sizeof(unsigned) <= 8); - - r = sd_ipv4ll_set_address_seed(ll, (unsigned) htole64(seed)); - if (r < 0) - return r; - } + r = sd_ipv4acd_set_mac(ll->acd, addr); + if (r < 0) + return r; - return sd_ipv4acd_set_mac(ll->acd, addr); + ll->mac = *addr; + return 0; } int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { @@ -163,21 +159,15 @@ int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { } int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) { - int r; - assert_return(ll, -EINVAL); - r = sd_ipv4acd_attach_event(ll->acd, event, priority); - if (r < 0) - return r; - - return 0; + return sd_ipv4acd_attach_event(ll->acd, event, priority); } int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) { assert_return(ll, -EINVAL); - ll->cb = cb; + ll->callback = cb; ll->userdata = userdata; return 0; @@ -195,32 +185,12 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) { return 0; } -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed) { - _cleanup_free_ struct random_data *random_data = NULL; - _cleanup_free_ char *random_data_state = NULL; - int r; - +int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) { assert_return(ll, -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - random_data = new0(struct random_data, 1); - if (!random_data) - return -ENOMEM; - - random_data_state = new0(char, 128); - if (!random_data_state) - return -ENOMEM; - - r = initstate_r(seed, random_data_state, 128, random_data); - if (r < 0) - return r; - - free(ll->random_data); - ll->random_data = random_data; - random_data = NULL; - - free(ll->random_data_state); - ll->random_data_state = random_data_state; - random_data_state = NULL; + ll->seed.value = htole64(seed); + ll->seed_set = true; return 0; } @@ -232,20 +202,12 @@ int sd_ipv4ll_is_running(sd_ipv4ll *ll) { } static bool ipv4ll_address_is_valid(const struct in_addr *address) { - uint32_t addr; - assert(address); if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address)) return false; - addr = be32toh(address->s_addr); - - if ((addr & 0x0000FF00) == 0x0000 || - (addr & 0x0000FF00) == 0xFF00) - return false; - - return true; + return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U); } int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { @@ -264,48 +226,67 @@ int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { return 0; } +#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b) + static int ipv4ll_pick_address(sd_ipv4ll *ll) { - struct in_addr in_addr; + _cleanup_free_ char *address = NULL; be32_t addr; - int r; - int32_t random; assert(ll); - assert(ll->random_data); do { - r = random_r(ll->random_data, &random); - if (r < 0) - return r; - addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK); - } while (addr == ll->address || - (ntohl(addr) & 0x0000FF00) == 0x0000 || - (ntohl(addr) & 0x0000FF00) == 0xFF00); + uint64_t h; - in_addr.s_addr = addr; + h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes); - r = sd_ipv4ll_set_address(ll, &in_addr); - if (r < 0) - return r; + /* Increase the generation counter by one */ + ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1); - return 0; + addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK); + } while (addr == ll->address || + IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U)); + + (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address); + log_ipv4ll(ll, "Picked new IP address %s.", strna(address)); + + return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr }); } +#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) + int sd_ipv4ll_start(sd_ipv4ll *ll) { int r; + bool picked_address = false; assert_return(ll, -EINVAL); - assert_return(ll->random_data, -EINVAL); + assert_return(!ether_addr_is_null(&ll->mac), -EINVAL); + assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); + + /* If no random seed is set, generate some from the MAC address */ + if (!ll->seed_set) + ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes)); + + /* Restart the generation counter. */ + ll->seed.generation = 0; if (ll->address == 0) { r = ipv4ll_pick_address(ll); if (r < 0) return r; + + picked_address = true; } r = sd_ipv4acd_start(ll->acd); - if (r < 0) + if (r < 0) { + + /* We couldn't start? If so, let's forget the picked address again, the user might make a change and + * retry, and we want the new data to take effect when picking an address. */ + if (picked_address) + ll->address = 0; + return r; + } return 0; } @@ -313,8 +294,8 @@ int sd_ipv4ll_start(sd_ipv4ll *ll) { static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { assert(ll); - if (ll->cb) - ll->cb(ll, event, ll->userdata); + if (ll->callback) + ll->callback(ll, event, ll->userdata); } void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { @@ -326,17 +307,17 @@ void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { assert(ll); switch (event) { + case SD_IPV4ACD_EVENT_STOP: ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); - ll->claimed_address = 0; - break; + case SD_IPV4ACD_EVENT_BIND: ll->claimed_address = ll->address; ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); - break; + case SD_IPV4ACD_EVENT_CONFLICT: /* if an address was already bound we must call up to the user to handle this, otherwise we just try again */ @@ -355,6 +336,7 @@ void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { } break; + default: assert_not_reached("Invalid IPv4ACD event."); } diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index 31e8e7fa66..eba12b749a 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -42,9 +42,7 @@ #include "process-util.h" #endif #include "set.h" -#if 0 /* NM_IGNORED */ #include "signal-util.h" -#endif #include "string-table.h" #include "string-util.h" #include "time-util.h" @@ -1082,6 +1080,10 @@ _public_ int sd_event_add_time( assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && + !clock_boottime_supported()) + return -EOPNOTSUPP; + if (!callback) callback = time_exit_callback; @@ -1156,8 +1158,7 @@ _public_ int sd_event_add_signal( int r; assert_return(e, -EINVAL); - assert_return(sig > 0, -EINVAL); - assert_return(sig < _NSIG, -EINVAL); + assert_return(SIGNAL_VALID(sig), -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -2212,7 +2213,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { if (_unlikely_(n != sizeof(si))) return -EIO; - assert(si.ssi_signo < _NSIG); + assert(SIGNAL_VALID(si.ssi_signo)); read_one = true; @@ -2540,7 +2541,8 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { } dual_timestamp_get(&e->timestamp); - e->timestamp_boottime = now(CLOCK_BOOTTIME); + if (clock_boottime_supported()) + e->timestamp_boottime = now(CLOCK_BOOTTIME); for (i = 0; i < m; i++) { @@ -2774,6 +2776,9 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM), -EOPNOTSUPP); + if (IN_SET(clock, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM) && !clock_boottime_supported()) + return -EOPNOTSUPP; + if (!dual_timestamp_is_set(&e->timestamp)) { /* Implicitly fall back to now() if we never ran * before and thus have no cached time. */ diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index 374ff8774e..9a90c2ed42 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -84,28 +84,57 @@ enum { typedef struct sd_dhcp_client sd_dhcp_client; -typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, - void *userdata); -int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_callback_t cb, - void *userdata); - -int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option); -int sd_dhcp_client_set_request_address(sd_dhcp_client *client, - const struct in_addr *last_address); -int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast); -int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index); -int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr, - size_t addr_len, uint16_t arp_type); -int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type, - const uint8_t *data, size_t data_len); -int sd_dhcp_client_set_iaid_duid(sd_dhcp_client *client, uint32_t iaid, - uint16_t duid_type, uint8_t *duid, size_t duid_len); -int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type, - const uint8_t **data, size_t *data_len); -int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu); -int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname); -int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci); -int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret); +typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata); +int sd_dhcp_client_set_callback( + sd_dhcp_client *client, + sd_dhcp_client_callback_t cb, + void *userdata); + +int sd_dhcp_client_set_request_option( + sd_dhcp_client *client, + uint8_t option); +int sd_dhcp_client_set_request_address( + sd_dhcp_client *client, + const struct in_addr *last_address); +int sd_dhcp_client_set_request_broadcast( + sd_dhcp_client *client, + int broadcast); +int sd_dhcp_client_set_ifindex( + sd_dhcp_client *client, + int interface_index); +int sd_dhcp_client_set_mac( + sd_dhcp_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type); +int sd_dhcp_client_set_client_id( + sd_dhcp_client *client, + uint8_t type, + const uint8_t *data, + size_t data_len); +int sd_dhcp_client_set_iaid_duid( + sd_dhcp_client *client, + uint32_t iaid, + uint16_t duid_type, + const void *duid, + size_t duid_len); +int sd_dhcp_client_get_client_id( + sd_dhcp_client *client, + uint8_t *type, + const uint8_t **data, + size_t *data_len); +int sd_dhcp_client_set_mtu( + sd_dhcp_client *client, + uint32_t mtu); +int sd_dhcp_client_set_hostname( + sd_dhcp_client *client, + const char *hostname); +int sd_dhcp_client_set_vendor_class_identifier( + sd_dhcp_client *client, + const char *vci); +int sd_dhcp_client_get_lease( + sd_dhcp_client *client, + sd_dhcp_lease **ret); int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); @@ -115,7 +144,10 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); int sd_dhcp_client_new(sd_dhcp_client **ret); -int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority); +int sd_dhcp_client_attach_event( + sd_dhcp_client *client, + sd_event *event, + int64_t priority); int sd_dhcp_client_detach_event(sd_dhcp_client *client); sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client); diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 4604cb6382..7819f0d2de 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -76,29 +76,52 @@ enum { typedef struct sd_dhcp6_client sd_dhcp6_client; -typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, - void *userdata); -int sd_dhcp6_client_set_callback(sd_dhcp6_client *client, - sd_dhcp6_client_callback_t cb, void *userdata); - -int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index); -int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address); -int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr, - size_t addr_len, uint16_t arp_type); -int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t duid_type, - uint8_t *duid, size_t duid_len); -int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid); -int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled); -int sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled); -int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, - uint16_t option); - -int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret); +typedef void (*sd_dhcp6_client_callback_t)(sd_dhcp6_client *client, int event, void *userdata); +int sd_dhcp6_client_set_callback( + sd_dhcp6_client *client, + sd_dhcp6_client_callback_t cb, + void *userdata); + +int sd_dhcp6_client_set_ifindex( + sd_dhcp6_client *client, + int interface_index); +int sd_dhcp6_client_set_local_address( + sd_dhcp6_client *client, + const struct in6_addr *local_address); +int sd_dhcp6_client_set_mac( + sd_dhcp6_client *client, + const uint8_t *addr, + size_t addr_len, + uint16_t arp_type); +int sd_dhcp6_client_set_duid( + sd_dhcp6_client *client, + uint16_t duid_type, + const void *duid, + size_t duid_len); +int sd_dhcp6_client_set_iaid( + sd_dhcp6_client *client, + uint32_t iaid); +int sd_dhcp6_client_set_information_request( + sd_dhcp6_client *client, + int enabled); +int sd_dhcp6_client_get_information_request( + sd_dhcp6_client *client, + int *enabled); +int sd_dhcp6_client_set_request_option( + sd_dhcp6_client *client, + uint16_t option); + +int sd_dhcp6_client_get_lease( + sd_dhcp6_client *client, + sd_dhcp6_lease **ret); int sd_dhcp6_client_stop(sd_dhcp6_client *client); int sd_dhcp6_client_start(sd_dhcp6_client *client); int sd_dhcp6_client_is_running(sd_dhcp6_client *client); -int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority); +int sd_dhcp6_client_attach_event( + sd_dhcp6_client *client, + sd_event *event, + int64_t priority); int sd_dhcp6_client_detach_event(sd_dhcp6_client *client); sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client); sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client); diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/systemd/src/systemd/sd-ipv4acd.h index 9e3e14a30c..16d99983a8 100644 --- a/src/systemd/src/systemd/sd-ipv4acd.h +++ b/src/systemd/src/systemd/sd-ipv4acd.h @@ -37,20 +37,20 @@ enum { }; typedef struct sd_ipv4acd sd_ipv4acd; -typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *ll, int event, void *userdata); - -int sd_ipv4acd_detach_event(sd_ipv4acd *ll); -int sd_ipv4acd_attach_event(sd_ipv4acd *ll, sd_event *event, int64_t priority); -int sd_ipv4acd_get_address(sd_ipv4acd *ll, struct in_addr *address); -int sd_ipv4acd_set_callback(sd_ipv4acd *ll, sd_ipv4acd_callback_t cb, void *userdata); -int sd_ipv4acd_set_mac(sd_ipv4acd *ll, const struct ether_addr *addr); -int sd_ipv4acd_set_index(sd_ipv4acd *ll, int interface_index); -int sd_ipv4acd_set_address(sd_ipv4acd *ll, const struct in_addr *address); -int sd_ipv4acd_is_running(sd_ipv4acd *ll); -int sd_ipv4acd_start(sd_ipv4acd *ll); -int sd_ipv4acd_stop(sd_ipv4acd *ll); -sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *ll); -sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *ll); +typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata); + +int sd_ipv4acd_detach_event(sd_ipv4acd *acd); +int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority); +int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address); +int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata); +int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr); +int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index); +int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address); +int sd_ipv4acd_is_running(sd_ipv4acd *acd); +int sd_ipv4acd_start(sd_ipv4acd *acd); +int sd_ipv4acd_stop(sd_ipv4acd *acd); +sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd); +sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd); int sd_ipv4acd_new(sd_ipv4acd **ret); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref); diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/systemd/src/systemd/sd-ipv4ll.h index 6fa38a2243..1109ec52e0 100644 --- a/src/systemd/src/systemd/sd-ipv4ll.h +++ b/src/systemd/src/systemd/sd-ipv4ll.h @@ -43,15 +43,15 @@ int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority); int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); -int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index); +int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index); int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed); +int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed); int sd_ipv4ll_is_running(sd_ipv4ll *ll); int sd_ipv4ll_start(sd_ipv4ll *ll); int sd_ipv4ll_stop(sd_ipv4ll *ll); sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll); sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll); -int sd_ipv4ll_new (sd_ipv4ll **ret); +int sd_ipv4ll_new(sd_ipv4ll **ret); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref); diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/systemd/src/systemd/sd-lldp.h index 4f2a3b50c0..5772d5794a 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/systemd/src/systemd/sd-lldp.h @@ -33,20 +33,18 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_lldp sd_lldp; typedef struct sd_lldp_neighbor sd_lldp_neighbor; -#define SD_LLDP_MULTICAST_ADDR { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } - /* IEEE 802.3AB Clause 9: TLV Types */ enum { - SD_LLDP_TYPE_END = 0, - SD_LLDP_TYPE_CHASSIS_ID = 1, - SD_LLDP_TYPE_PORT_ID = 2, - SD_LLDP_TYPE_TTL = 3, - SD_LLDP_TYPE_PORT_DESCRIPTION = 4, - SD_LLDP_TYPE_SYSTEM_NAME = 5, - SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6, - SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7, - SD_LLDP_TYPE_MGMT_ADDRESS = 8, - SD_LLDP_TYPE_PRIVATE = 127, + SD_LLDP_TYPE_END = 0, + SD_LLDP_TYPE_CHASSIS_ID = 1, + SD_LLDP_TYPE_PORT_ID = 2, + SD_LLDP_TYPE_TTL = 3, + SD_LLDP_TYPE_PORT_DESCRIPTION = 4, + SD_LLDP_TYPE_SYSTEM_NAME = 5, + SD_LLDP_TYPE_SYSTEM_DESCRIPTION = 6, + SD_LLDP_TYPE_SYSTEM_CAPABILITIES = 7, + SD_LLDP_TYPE_MGMT_ADDRESS = 8, + SD_LLDP_TYPE_PRIVATE = 127, }; /* IEEE 802.3AB Clause 9.5.2: Chassis subtypes */ @@ -63,28 +61,28 @@ enum { /* IEEE 802.3AB Clause 9.5.3: Port subtype */ enum { - SD_LLDP_PORT_SUBTYPE_RESERVED = 0, - SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, - SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, - SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, - SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4, - SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, - SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, - SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, + SD_LLDP_PORT_SUBTYPE_RESERVED = 0, + SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS = 1, + SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT = 2, + SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS = 3, + SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS = 4, + SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME = 5, + SD_LLDP_PORT_SUBTYPE_AGENT_CIRCUIT_ID = 6, + SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED = 7, }; enum { - SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, - SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, - SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, - SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3, - SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4, - SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5, - SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6, - SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7, - SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, - SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, - SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, + SD_LLDP_SYSTEM_CAPABILITIES_OTHER = 1 << 0, + SD_LLDP_SYSTEM_CAPABILITIES_REPEATER = 1 << 1, + SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE = 1 << 2, + SD_LLDP_SYSTEM_CAPABILITIES_WLAN_AP = 1 << 3, + SD_LLDP_SYSTEM_CAPABILITIES_ROUTER = 1 << 4, + SD_LLDP_SYSTEM_CAPABILITIES_PHONE = 1 << 5, + SD_LLDP_SYSTEM_CAPABILITIES_DOCSIS = 1 << 6, + SD_LLDP_SYSTEM_CAPABILITIES_STATION = 1 << 7, + SD_LLDP_SYSTEM_CAPABILITIES_CVLAN = 1 << 8, + SD_LLDP_SYSTEM_CAPABILITIES_SVLAN = 1 << 9, + SD_LLDP_SYSTEM_CAPABILITIES_TPMR = 1 << 10, }; #define SD_LLDP_SYSTEM_CAPABILITIES_ALL ((uint16_t) -1) @@ -100,18 +98,17 @@ enum { SD_LLDP_SYSTEM_CAPABILITIES_SVLAN| \ SD_LLDP_SYSTEM_CAPABILITIES_TPMR)) - #define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 } #define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f } enum { - SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, - SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2, - SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3, - SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4, - SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5, - SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6, - SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7, + SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1, + SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID = 2, + SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME = 3, + SD_LLDP_OUI_802_1_SUBTYPE_PROTOCOL_IDENTITY = 4, + SD_LLDP_OUI_802_1_SUBTYPE_VID_USAGE_DIGEST = 5, + SD_LLDP_OUI_802_1_SUBTYPE_MANAGEMENT_VID = 6, + SD_LLDP_OUI_802_1_SUBTYPE_LINK_AGGREGATION = 7, }; typedef enum sd_lldp_event { diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/systemd/src/systemd/sd-ndisc.h index 29bcbe8e3e..2b774233b8 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/systemd/src/systemd/sd-ndisc.h @@ -49,7 +49,7 @@ int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_prefix_autonomous_callback_t pacb, sd_ndisc_callback_t cb, void *userdata); -int sd_ndisc_set_index(sd_ndisc *nd, int interface_index); +int sd_ndisc_set_ifindex(sd_ndisc *nd, int interface_index); int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); int sd_ndisc_attach_event(sd_ndisc *nd, sd_event *event, int64_t priority); diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index e1734b6d1b..70eb25bfd1 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -1,5 +1,7 @@ SUBDIRS = config +@GNOME_CODE_COVERAGE_RULES@ + AM_CPPFLAGS = \ -I$(top_srcdir)/shared \ -I$(top_builddir)/shared \ @@ -12,7 +14,10 @@ AM_CPPFLAGS = \ -I$(top_builddir)/src \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(CODE_COVERAGE_CFLAGS) + +AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS) noinst_PROGRAMS = \ test-general \ @@ -47,6 +52,7 @@ test_ip6_config_LDADD = \ test_route_manager_fake_CPPFLAGS = \ $(AM_CPPFLAGS) \ + $(GUDEV_CFLAGS) \ -I$(top_srcdir)/src/platform/tests \ -DSETUP=nm_fake_platform_setup \ -DKERNEL_HACKS=0 @@ -64,6 +70,7 @@ test_route_manager_linux_SOURCES = \ test_route_manager_linux_CPPFLAGS = \ $(AM_CPPFLAGS) \ + $(GUDEV_CFLAGS) \ -I$(top_srcdir)/src/platform/tests \ -DSETUP=nm_linux_platform_setup \ -DKERNEL_HACKS=1 diff --git a/src/tests/config/Makefile.am b/src/tests/config/Makefile.am index 17876e4d00..ee8254bab3 100644 --- a/src/tests/config/Makefile.am +++ b/src/tests/config/Makefile.am @@ -9,8 +9,8 @@ AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\""NetworkManager"\" \ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ $(GLIB_CFLAGS) \ - -DSRCDIR=\""$(srcdir)"\" \ - -DBUILDDIR=\""$(builddir)"\" + -DSRCDIR=\""$(abs_srcdir)"\" \ + -DBUILDDIR=\""$(abs_builddir)"\" noinst_PROGRAMS = \ test-config @@ -28,6 +28,7 @@ TESTS = test-config EXTRA_DIST = \ NetworkManager.conf \ + NetworkManager.state \ bad.conf \ global-dns-invalid.conf \ conf.d/00-overrides.conf \ diff --git a/src/tests/config/NetworkManager.state b/src/tests/config/NetworkManager.state new file mode 100644 index 0000000000..1b9d604ac5 --- /dev/null +++ b/src/tests/config/NetworkManager.state @@ -0,0 +1,4 @@ +[main] +NetworkingEnabled=true +WirelessEnabled=true +WWANEnabled=true diff --git a/src/tests/config/test-config.c b/src/tests/config/test-config.c index d83ff4b5c5..defead0540 100644 --- a/src/tests/config/test-config.c +++ b/src/tests/config/test-config.c @@ -27,7 +27,7 @@ #include "nm-fake-platform.h" #include "nm-bus-manager.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /********************************************************************************/ @@ -930,6 +930,65 @@ test_config_enable (void) /*****************************************************************************/ +static void +test_config_state_file (void) +{ + NMConfig *config; + const NMConfigState *state; + gs_free_error GError *error = NULL; + gboolean ret; + gs_free char *file_data = NULL; + gsize file_size; + const char *const TMP_FILE = BUILDDIR "/tmp.state"; + + ret = g_file_get_contents (SRCDIR "/NetworkManager.state", &file_data, &file_size, &error); + nmtst_assert_success (ret, error); + ret = g_file_set_contents (TMP_FILE, file_data, file_size, &error); + nmtst_assert_success (ret, error); + + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL, SRCDIR "/conf.d", "", + "--state-file", TMP_FILE, NULL); + g_assert (config); + + state = nm_config_state_get (config); + g_assert (state); + + g_assert_cmpint (state->net_enabled, ==, TRUE); + g_assert_cmpint (state->wifi_enabled, ==, TRUE); + g_assert_cmpint (state->wwan_enabled, ==, TRUE); + + nm_config_state_set (config, TRUE, TRUE, + NM_CONFIG_STATE_PROPERTY_NETWORKING_ENABLED, FALSE, + NM_CONFIG_STATE_PROPERTY_WIFI_ENABLED, TRUE, + NM_CONFIG_STATE_PROPERTY_WWAN_ENABLED, FALSE); + + state = nm_config_state_get (config); + g_assert (state); + + g_assert_cmpint (state->net_enabled, ==, FALSE); + g_assert_cmpint (state->wifi_enabled, ==, TRUE); + g_assert_cmpint (state->wwan_enabled, ==, FALSE); + + g_object_unref (config); + + /* Reload configuration */ + config = setup_config (NULL, SRCDIR "/NetworkManager.conf", "", NULL, SRCDIR "/conf.d", "", + "--state-file", TMP_FILE, NULL); + g_assert (config); + + state = nm_config_state_get (config); + g_assert (state); + + g_assert_cmpint (state->net_enabled, ==, FALSE); + g_assert_cmpint (state->wifi_enabled, ==, TRUE); + g_assert_cmpint (state->wwan_enabled, ==, FALSE); + + g_object_unref (config); + unlink (TMP_FILE); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -960,6 +1019,8 @@ main (int argc, char **argv) g_test_add_func ("/config/enable", test_config_enable); + g_test_add_func ("/config/state-file", test_config_state_file); + /* This one has to come last, because it leaves its values in * nm-config.c's global variables, and there's no way to reset * those to NULL. diff --git a/src/tests/test-dcb.c b/src/tests/test-dcb.c index e8e1ec860b..0a133de369 100644 --- a/src/tests/test-dcb.c +++ b/src/tests/test-dcb.c @@ -24,7 +24,7 @@ #include "nm-dcb.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" typedef struct { guint num; diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c index 64b47bd38c..ab2b15b5f2 100644 --- a/src/tests/test-general-with-expect.c +++ b/src/tests/test-general-with-expect.c @@ -30,7 +30,7 @@ #include "NetworkManagerUtils.h" #include "nm-multi-index.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" #ifndef CLOCK_BOOTTIME #define CLOCK_BOOTTIME 7 diff --git a/src/tests/test-general.c b/src/tests/test-general.c index a45357e810..d29cdc0eed 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -26,7 +26,7 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /* Reference implementation for nm_utils_ip6_address_clear_host_address. * Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c diff --git a/src/tests/test-ip4-config.c b/src/tests/test-ip4-config.c index 9d38dc27b7..95b221bc0c 100644 --- a/src/tests/test-ip4-config.c +++ b/src/tests/test-ip4-config.c @@ -26,7 +26,7 @@ #include "nm-ip4-config.h" #include "nm-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static NMIP4Config * build_test_config (void) @@ -161,18 +161,18 @@ test_compare_with_source (void) /* Address */ addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_address (a, &addr); - addr.source = NM_IP_CONFIG_SOURCE_VPN; + addr.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip4_config_add_address (b, &addr); /* Route */ route = *nmtst_platform_ip4_route ("10.0.0.0", 8, "192.168.1.1"); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_route (a, &route); - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip4_config_add_route (b, &route); /* Assert that the configs are basically the same, eg that the source is ignored */ @@ -193,31 +193,31 @@ test_add_address_with_source (void) /* Test that a higher priority source is not overwritten */ addr = *nmtst_platform_ip4_address ("1.2.3.4", NULL, 24); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_address (a, &addr); test_addr = nm_ip4_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); - addr.source = NM_IP_CONFIG_SOURCE_VPN; + addr.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip4_config_add_address (a, &addr); test_addr = nm_ip4_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); /* Test that a lower priority address source is overwritten */ nm_ip4_config_del_address (a, 0); - addr.source = NM_IP_CONFIG_SOURCE_KERNEL; + addr.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; nm_ip4_config_add_address (a, &addr); test_addr = nm_ip4_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_KERNEL); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_KERNEL); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_address (a, &addr); test_addr = nm_ip4_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); g_object_unref (a); } @@ -233,31 +233,31 @@ test_add_route_with_source (void) /* Test that a higher priority source is not overwritten */ route = *nmtst_platform_ip4_route ("1.2.3.4", 24, "1.2.3.1"); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_route (a, &route); test_route = nm_ip4_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip4_config_add_route (a, &route); test_route = nm_ip4_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); /* Test that a lower priority address source is overwritten */ nm_ip4_config_del_route (a, 0); - route.source = NM_IP_CONFIG_SOURCE_KERNEL; + route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL; nm_ip4_config_add_route (a, &route); test_route = nm_ip4_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_KERNEL); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip4_config_add_route (a, &route); test_route = nm_ip4_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); g_object_unref (a); } diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index 5a2bb58905..3eceec0cbe 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -26,7 +26,7 @@ #include "nm-ip6-config.h" #include "nm-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static NMIP6Config * build_test_config (void) @@ -132,18 +132,18 @@ test_compare_with_source (void) /* Address */ addr = *nmtst_platform_ip6_address ("1122:3344:5566::7788", NULL, 64); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_address (a, &addr); - addr.source = NM_IP_CONFIG_SOURCE_VPN; + addr.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip6_config_add_address (b, &addr); /* Route */ route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2"); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_route (a, &route); - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip6_config_add_route (b, &route); /* Assert that the configs are basically the same, eg that the source is ignored */ @@ -164,31 +164,31 @@ test_add_address_with_source (void) /* Test that a higher priority source is not overwritten */ addr = *nmtst_platform_ip6_address ("1122:3344:5566::7788", NULL, 64); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_address (a, &addr); test_addr = nm_ip6_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); - addr.source = NM_IP_CONFIG_SOURCE_VPN; + addr.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip6_config_add_address (a, &addr); test_addr = nm_ip6_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); /* Test that a lower priority address source is overwritten */ nm_ip6_config_del_address (a, 0); - addr.source = NM_IP_CONFIG_SOURCE_KERNEL; + addr.addr_source = NM_IP_CONFIG_SOURCE_KERNEL; nm_ip6_config_add_address (a, &addr); test_addr = nm_ip6_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_KERNEL); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_KERNEL); - addr.source = NM_IP_CONFIG_SOURCE_USER; + addr.addr_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_address (a, &addr); test_addr = nm_ip6_config_get_address (a, 0); - g_assert_cmpint (test_addr->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_addr->addr_source, ==, NM_IP_CONFIG_SOURCE_USER); g_object_unref (a); } @@ -204,31 +204,31 @@ test_add_route_with_source (void) /* Test that a higher priority source is not overwritten */ route = *nmtst_platform_ip6_route ("abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2"); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_route (a, &route); test_route = nm_ip6_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip6_config_add_route (a, &route); test_route = nm_ip6_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); /* Test that a lower priority address source is overwritten */ nm_ip6_config_del_route (a, 0); - route.source = NM_IP_CONFIG_SOURCE_KERNEL; + route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL; nm_ip6_config_add_route (a, &route); test_route = nm_ip6_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_KERNEL); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = NM_IP_CONFIG_SOURCE_USER; nm_ip6_config_add_route (a, &route); test_route = nm_ip6_config_get_route (a, 0); - g_assert_cmpint (test_route->source, ==, NM_IP_CONFIG_SOURCE_USER); + g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); g_object_unref (a); } diff --git a/src/tests/test-resolvconf-capture.c b/src/tests/test-resolvconf-capture.c index 31b6e1777f..32bc97342a 100644 --- a/src/tests/test-resolvconf-capture.c +++ b/src/tests/test-resolvconf-capture.c @@ -28,7 +28,7 @@ #include "nm-ip6-config.h" #include "nm-platform.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static void test_capture_empty (void) diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c index c753174d8e..b81c263c08 100644 --- a/src/tests/test-route-manager.c +++ b/src/tests/test-route-manager.c @@ -23,12 +23,11 @@ #include <arpa/inet.h> #include <linux/rtnetlink.h> -#include "test-common.h" - #include "nm-platform.h" +#include "nm-platform-utils.h" #include "nm-route-manager.h" -#include "nm-test-utils.h" +#include "test-common.h" typedef struct { int ifindex0, ifindex1; @@ -45,7 +44,7 @@ setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_ route.ifindex = ifindex; route.mss = 0; - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "6.6.6.0", &route.network); route.plen = 24; route.gateway = INADDR_ANY; @@ -53,7 +52,7 @@ setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_ route.mss = mss_of_first_route; g_array_append_val (routes, route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "7.0.0.0", &route.network); route.plen = 8; inet_pton (AF_INET, "6.6.6.1", &route.gateway); @@ -87,21 +86,21 @@ setup_dev1_ip4 (int ifindex) route.mss)) g_assert_not_reached (); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "6.6.6.0", &route.network); route.plen = 24; route.gateway = INADDR_ANY; route.metric = 20; g_array_append_val (routes, route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "7.0.0.0", &route.network); route.plen = 8; route.gateway = INADDR_ANY; route.metric = 22; g_array_append_val (routes, route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "8.0.0.0", &route.network); route.plen = 8; inet_pton (AF_INET, "6.6.6.2", &route.gateway); @@ -121,14 +120,14 @@ update_dev0_ip4 (int ifindex) route.ifindex = ifindex; route.mss = 0; - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "6.6.6.0", &route.network); route.plen = 24; route.gateway = INADDR_ANY; route.metric = 20; g_array_append_val (routes, route); - route.source = NM_IP_CONFIG_SOURCE_USER; + route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); inet_pton (AF_INET, "7.0.0.0", &route.network); route.plen = 8; route.gateway = INADDR_ANY; @@ -163,7 +162,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP4Route state1[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex0, @@ -173,7 +172,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("7.0.0.0"), .plen = 8, .ifindex = fixture->ifindex0, @@ -183,7 +182,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("7.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -193,7 +192,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex1, @@ -203,7 +202,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("8.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -216,7 +215,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP4Route state2[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex0, @@ -226,7 +225,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("7.0.0.0"), .plen = 8, .ifindex = fixture->ifindex0, @@ -236,7 +235,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("7.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -246,7 +245,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex1, @@ -256,7 +255,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("8.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -269,7 +268,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP4Route state3[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("7.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -279,7 +278,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex1, @@ -289,7 +288,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("8.0.0.0"), .plen = 8, .ifindex = fixture->ifindex1, @@ -299,7 +298,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data) .scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE), }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = nmtst_inet4_from_string ("6.6.6.0"), .plen = 24, .ifindex = fixture->ifindex1, @@ -542,7 +541,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP6Route state1[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex0, @@ -551,7 +550,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex0, @@ -560,7 +559,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), .plen = 64, .ifindex = fixture->ifindex0, @@ -569,7 +568,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -578,7 +577,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -587,7 +586,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -596,7 +595,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:d34d::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -608,7 +607,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP6Route state2[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex0, @@ -617,7 +616,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex0, @@ -626,7 +625,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), .plen = 64, .ifindex = fixture->ifindex0, @@ -635,7 +634,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -644,7 +643,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -653,7 +652,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -662,7 +661,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:d34d::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -674,7 +673,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) NMPlatformIP6Route state3[] = { { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -683,7 +682,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -692,7 +691,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -701,7 +700,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:1337::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -710,7 +709,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:8086::"), .plen = 48, .ifindex = fixture->ifindex1, @@ -719,7 +718,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data) .mss = 0, }, { - .source = NM_IP_CONFIG_SOURCE_USER, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), .network = *nmtst_inet6_from_string ("2001:db8:d34d::"), .plen = 64, .ifindex = fixture->ifindex1, @@ -787,6 +786,7 @@ static void _assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NMPlatformIPXRoute *route) { const NMPlatformIPXRoute *r; + NMPlatformIPXRoute c; g_assert (route); @@ -800,11 +800,18 @@ _assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NM } else { char buf[sizeof (_nm_utils_to_string_buffer)]; - if (!r || vtable->route_cmp (route, r) != 0) + if (r) { + if (vtable->is_ip4) + c.r4 = route->r4; + else + c.r6 = route->r6; + c.rx.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (c.rx.rt_source); + } + if (!r || vtable->route_cmp (r, &c) != 0) { g_error ("Invalid route. Expect %s, has %s", - vtable->route_to_string (route, NULL, 0), + vtable->route_to_string (&c, NULL, 0), vtable->route_to_string (r, buf, sizeof (buf))); - g_assert (r); + } } } diff --git a/src/tests/test-systemd.c b/src/tests/test-systemd.c index 936bff204f..2dcb7af632 100644 --- a/src/tests/test-systemd.c +++ b/src/tests/test-systemd.c @@ -25,7 +25,7 @@ #include "sd-lldp.h" #include "sd-event.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" /*****************************************************************************/ diff --git a/src/tests/test-utils.c b/src/tests/test-utils.c index 6fc3978b9c..2cd8b8588d 100644 --- a/src/tests/test-utils.c +++ b/src/tests/test-utils.c @@ -26,7 +26,7 @@ #include "nm-core-utils.c" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static void test_stable_privacy (void) diff --git a/src/tests/test-wired-defname.c b/src/tests/test-wired-defname.c index 6edd5ff246..3ae3a19d95 100644 --- a/src/tests/test-wired-defname.c +++ b/src/tests/test-wired-defname.c @@ -24,7 +24,7 @@ #include "nm-setting-connection.h" #include "nm-device-ethernet-utils.h" -#include "nm-test-utils.h" +#include "nm-test-utils-core.h" static NMConnection * _new_connection (const char *id) @@ -41,12 +41,28 @@ _new_connection (const char *id) /*******************************************/ +static char * +_get_default_wired_name (GSList *list) +{ + gs_free NMConnection **v = NULL; + guint l, i; + + l = g_slist_length (list); + v = g_new0 (NMConnection *, l + 1); + for (i = 0; list; list = list->next, i++) + v[i] = NM_CONNECTION (list->data); + g_assert (i == l); + return nm_device_ethernet_utils_get_default_wired_name (v); +} + +/*******************************************/ + static void test_defname_no_connections (void) { gs_free char *name = NULL; - name = nm_device_ethernet_utils_get_default_wired_name (NULL); + name = _get_default_wired_name (NULL); g_assert_cmpstr (name, ==, "Wired connection 1"); } @@ -62,7 +78,7 @@ test_defname_no_conflict (void) list = g_slist_append (list, _new_connection ("work wifi")); list = g_slist_append (list, _new_connection ("random gsm connection")); - name = nm_device_ethernet_utils_get_default_wired_name (list); + name = _get_default_wired_name (list); g_assert_cmpstr (name, ==, "Wired connection 1"); g_slist_free_full (list, g_object_unref); @@ -80,7 +96,7 @@ test_defname_conflict (void) list = g_slist_append (list, _new_connection ("Wired connection 1")); list = g_slist_append (list, _new_connection ("random gsm connection")); - name = nm_device_ethernet_utils_get_default_wired_name (list); + name = _get_default_wired_name (list); g_assert_cmpstr (name, ==, "Wired connection 2"); g_slist_free_full (list, g_object_unref); @@ -102,7 +118,7 @@ test_defname_multiple_conflicts (void) list = g_slist_append (list, _new_connection ("work wifi")); list = g_slist_append (list, _new_connection ("a vpn")); - name = nm_device_ethernet_utils_get_default_wired_name (list); + name = _get_default_wired_name (list); g_assert_cmpstr (name, ==, "Wired connection 4"); g_slist_free_full (list, g_object_unref); diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 31b94752af..b2aa8f6bc6 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -27,6 +27,8 @@ #include <arpa/inet.h> #include <errno.h> #include <stdlib.h> +#include <unistd.h> +#include <syslog.h> #include "nm-vpn-connection.h" #include "nm-ip4-config.h" @@ -44,6 +46,7 @@ #include "nm-config.h" #include "nm-vpn-plugin-info.h" #include "nm-vpn-manager.h" +#include "nm-dns-manager.h" #include "nmdbus-vpn-connection.h" @@ -192,14 +195,14 @@ __LOG_create_prefix (char *buf, NMVpnConnection *self) "%s%s" /*con-uuid*/ "%s%s%s%s" /*con-id*/ ",%d" /*ifindex*/ - "%s%s%s%s" /*iface*/ + "%s%s%s" /*iface*/ "]", _NMLOG_PREFIX_NAME, self, con ? "," : "--", con ? (nm_connection_get_uuid (con) ?: "??") : "", con ? "," : "", NM_PRINT_FMT_QUOTED (id, "\"", id, "\"", con ? "??" : ""), priv->ip_ifindex, - priv->ip_iface ? ":" : "", NM_PRINT_FMT_QUOTED (priv->ip_iface, "(", priv->ip_iface, ")", "") + NM_PRINT_FMT_QUOTED (priv->ip_iface, ":(", priv->ip_iface, ")", "") ); return buf; @@ -680,7 +683,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32 if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32)) route.gateway = 0; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; route.metric = route_metric; nm_ip4_config_add_route (config, &route); @@ -692,7 +695,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32 memset (&route, 0, sizeof (route)); route.network = parent_gw; route.plen = 32; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; route.metric = route_metric; nm_ip4_config_add_route (config, &route); @@ -732,7 +735,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config, if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128)) route.gateway = in6addr_any; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; route.metric = route_metric; nm_ip6_config_add_route (config, &route); @@ -744,7 +747,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config, memset (&route, 0, sizeof (route)); route.network = *parent_gw; route.plen = 128; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; route.metric = route_metric; nm_ip6_config_add_route (config, &route); @@ -909,7 +912,7 @@ print_vpn_config (NMVpnConnection *self) nm_utils_inet6_ntop (priv->ip6_external_gw, NULL)); } - _LOGI ("Data: Tunnel Device: %s", priv->ip_iface ? priv->ip_iface : "(none)"); + _LOGI ("Data: Tunnel Device: %s%s%s", NM_PRINT_FMT_QUOTE_STRING (priv->ip_iface)); if (priv->ip4_config) { _LOGI ("Data: IPv4 configuration:"); @@ -1218,6 +1221,8 @@ process_generic_config (NMVpnConnection *self, GVariant *dict) } g_clear_pointer (&priv->ip_iface, g_free); + priv->ip_ifindex = 0; + if (g_variant_lookup (dict, NM_VPN_PLUGIN_CONFIG_TUNDEV, "&s", &str)) { /* Backwards compat with NM-openswan */ if (g_strcmp0 (str, "_none_") != 0) @@ -1228,7 +1233,13 @@ process_generic_config (NMVpnConnection *self, GVariant *dict) /* Grab the interface index for address/routing operations */ priv->ip_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); if (priv->ip_ifindex <= 0) { + nm_platform_process_events (NM_PLATFORM_GET); + priv->ip_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); + } + if (priv->ip_ifindex <= 0) { _LOGE ("failed to look up VPN interface index for \"%s\"", priv->ip_iface); + g_clear_pointer (&priv->ip_iface, g_free); + priv->ip_ifindex = 0; nm_vpn_connection_config_maybe_complete (self, FALSE); return FALSE; } @@ -1329,7 +1340,6 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) const char *str; GVariant *v; gboolean b; - int ifindex; g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT)); @@ -1357,13 +1367,8 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) priv->has_ip6 = FALSE; } - if (priv->ip_ifindex > 0) { - ifindex = priv->ip_ifindex; - } else { - NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self)); - ifindex = nm_device_get_ip_ifindex (parent_dev); - } - config = nm_ip4_config_new (ifindex); + config = nm_ip4_config_new (nm_vpn_connection_get_ip_ifindex (self, TRUE)); + nm_ip4_config_set_dns_priority (config, NM_DNS_PRIORITY_DEFAULT_VPN); memset (&address, 0, sizeof (address)); address.plen = 24; @@ -1386,7 +1391,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) address.plen = u32; if (address.address && address.plen && address.plen <= 32) { - address.source = NM_IP_CONFIG_SOURCE_VPN; + address.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip4_config_add_address (config, &address); } else { _LOGW ("invalid IP4 config received!"); @@ -1435,7 +1440,7 @@ nm_vpn_connection_ip4_config_get (NMVpnConnection *self, GVariant *dict) g_variant_get_child (v, 2, "u", &route.gateway); /* 4th item is unused route metric */ route.metric = route_metric; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; if (route.plen > 32) break; @@ -1497,6 +1502,7 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict) } config = nm_ip6_config_new (priv->ip_ifindex); + nm_ip6_config_set_dns_priority (config, NM_DNS_PRIORITY_DEFAULT_VPN); memset (&address, 0, sizeof (address)); address.plen = 128; @@ -1523,7 +1529,7 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict) address.plen = u32; if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen && address.plen <= 128) { - address.source = NM_IP_CONFIG_SOURCE_VPN; + address.addr_source = NM_IP_CONFIG_SOURCE_VPN; nm_ip6_config_add_address (config, &address); } else { _LOGW ("invalid IP6 config received!"); @@ -1575,7 +1581,7 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict) route.plen = prefix; ip6_addr_from_variant (next_hop, &route.gateway); route.metric = route_metric; - route.source = NM_IP_CONFIG_SOURCE_VPN; + route.rt_source = NM_IP_CONFIG_SOURCE_VPN; /* Ignore host routes to the VPN gateway since NM adds one itself. * Since NM knows more about the routing situation than the VPN @@ -1919,6 +1925,41 @@ _daemon_exec_timeout (gpointer data) return G_SOURCE_REMOVE; } +static int +_get_log_level (void) +{ + NMLogLevel level; + + /* curiously enough, nm-logging also uses syslog. But it + * maps NMLogLevel differently to the syslog levels then we + * do here. + * + * The reason is, that LOG_NOTICE is already something worth + * highlighting in the journal, but we have 3 levels that are + * lower then LOG_NOTICE (LOGL_TRACE, LOGL_DEBUG, LOGL_INFO), + * On the other hand, syslog only defines LOG_DEBUG and LOG_INFO. + * Thus, we must map them differently. + * + * Inside the VPN plugin, you might want to treat LOG_NOTICE as + * as low severity, not worthy to be highlighted (like NM does). */ + + level = nm_logging_get_level (LOGD_VPN_PLUGIN); + if (level != _LOGL_OFF) { + if (level <= LOGL_TRACE) + return LOG_DEBUG; + if (level <= LOGL_DEBUG) + return LOG_INFO; + if (level <= LOGL_INFO) + return LOG_NOTICE; + if (level <= LOGL_WARN) + return LOG_WARNING; + if (level <= LOGL_ERR) + return LOG_ERR; + } + + return LOG_EMERG; +} + static gboolean nm_vpn_service_daemon_exec (NMVpnConnection *self, GError **error) { @@ -1927,20 +1968,50 @@ nm_vpn_service_daemon_exec (NMVpnConnection *self, GError **error) char *vpn_argv[4]; gboolean success = FALSE; GError *spawn_error = NULL; - int i = 0; + guint i, j, n_environ; + gs_free char **envp = NULL; + char env_log_level[NM_STRLEN ("NM_VPN_LOG_LEVEL=") + 100]; + char env_log_syslog[NM_STRLEN ("NM_VPN_LOG_SYSLOG=") + 10]; + const int N_ENVIRON_EXTRA = 3; + char **p_environ; g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), FALSE); + priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + i = 0; vpn_argv[i++] = (char *) nm_vpn_plugin_info_get_program (priv->plugin_info); + g_return_val_if_fail (vpn_argv[0], FALSE); if (nm_vpn_plugin_info_supports_multiple (priv->plugin_info)) { vpn_argv[i++] = "--bus-name"; vpn_argv[i++] = priv->bus_name; } - vpn_argv[i] = NULL; - g_assert (vpn_argv[0]); + vpn_argv[i++] = NULL; + + /* we include <unistd.h> and "config.h" defines _GNU_SOURCE for us. So, we have @environ. */ + p_environ = environ; + n_environ = p_environ ? g_strv_length (p_environ) : 0; + envp = g_new (char *, n_environ + N_ENVIRON_EXTRA); + for (i = 0, j = 0; j < n_environ; j++) { + if ( g_str_has_prefix (p_environ[j], "NM_VPN_LOG_LEVEL=") + || g_str_has_prefix (p_environ[j], "NM_VPN_LOG_SYSLOG=")) + continue; + envp[i++] = p_environ[j]; + } - success = g_spawn_async (NULL, vpn_argv, NULL, 0, nm_utils_setpgid, NULL, &pid, &spawn_error); + /* NM_VPN_LOG_LEVEL: the syslog logging level for the plugin. */ + envp[i++] = nm_sprintf_buf (env_log_level, "NM_VPN_LOG_LEVEL=%d", _get_log_level ()); + + /* NM_VPN_LOG_SYSLOG: whether to log to stdout or syslog. If NetworkManager itself runs in + * foreground, we also want the plugin to log to stdout. + * If the plugin runs in background, the plugin should prefer logging to syslog. Otherwise + * logging messages will be lost (unless using journald, in which case it wouldn't matter). */ + envp[i++] = nm_sprintf_buf (env_log_syslog, "NM_VPN_LOG_SYSLOG=%c", nm_logging_syslog_enabled () ? '1' : '0'); + + envp[i++] = NULL; + nm_assert (i <= n_environ + N_ENVIRON_EXTRA); + + success = g_spawn_async (NULL, vpn_argv, envp, 0, nm_utils_setpgid, NULL, &pid, &spawn_error); if (success) { _LOGI ("Started the VPN service, PID %ld", (long int) pid); @@ -2016,10 +2087,8 @@ nm_vpn_connection_activate (NMVpnConnection *self, s_vpn = nm_connection_get_setting_vpn (_get_applied_connection (self)); g_return_if_fail (s_vpn); - service = nm_vpn_plugin_info_lookup_property (plugin_info, - NM_VPN_PLUGIN_INFO_KF_GROUP_CONNECTION, - "service"); - g_return_if_fail (service); + service = nm_vpn_plugin_info_get_service (plugin_info); + nm_assert (service); if (nm_vpn_plugin_info_supports_multiple (plugin_info)) { const char *path; @@ -2082,20 +2151,67 @@ nm_vpn_connection_get_ip6_config (NMVpnConnection *self) return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip6_config; } +static int +_get_ip_iface_for_device (NMVpnConnection *self, const char **out_iface) +{ + NMDevice *parent_dev; + int ifindex; + const char *iface; + + nm_assert (NM_IS_VPN_CONNECTION (self)); + + /* the ifindex and the ifname in this case should come together. + * They either must be both set, or none. */ + + parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self)); + if (!parent_dev) + goto none; + ifindex = nm_device_get_ip_ifindex (parent_dev); + if (ifindex <= 0) + goto none; + iface = nm_device_get_ip_iface (parent_dev); + if (!iface) + goto none; + + NM_SET_OUT (out_iface, iface); + return ifindex; +none: + NM_SET_OUT (out_iface, NULL); + return 0; +} + const char * -nm_vpn_connection_get_ip_iface (NMVpnConnection *self) +nm_vpn_connection_get_ip_iface (NMVpnConnection *self, gboolean fallback_device) { + NMVpnConnectionPrivate *priv; + const char *iface; + g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), NULL); - return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip_iface; + priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->ip_iface || !fallback_device) + return priv->ip_iface; + + _get_ip_iface_for_device (self, &iface); + return iface; } int -nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self) +nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self, gboolean fallback_device) { - g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), -1); + NMVpnConnectionPrivate *priv; + + g_return_val_if_fail (NM_IS_VPN_CONNECTION (self), 0); + + priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->ip_ifindex > 0) + return priv->ip_ifindex; + if (!fallback_device) + return 0; - return NM_VPN_CONNECTION_GET_PRIVATE (self)->ip_ifindex; + return _get_ip_iface_for_device (self, NULL); } guint32 diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index 19b0eb3feb..6837432926 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -91,8 +91,8 @@ void nm_vpn_connection_disconnect (NMVpnConnection *self, NMIP4Config * nm_vpn_connection_get_ip4_config (NMVpnConnection *self); NMIP6Config * nm_vpn_connection_get_ip6_config (NMVpnConnection *self); -const char * nm_vpn_connection_get_ip_iface (NMVpnConnection *self); -int nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self); +const char * nm_vpn_connection_get_ip_iface (NMVpnConnection *self, gboolean fallback_device); +int nm_vpn_connection_get_ip_ifindex (NMVpnConnection *self, gboolean fallback_device); guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVpnConnection *self); struct in6_addr * nm_vpn_connection_get_ip6_internal_gateway (NMVpnConnection *self); |