Commit b40729ca authored by Thomas Haller's avatar Thomas Haller

core: rework tracking config in dns-manager to use ifindex

Don't track the per-device configuration in NMDnsManager by
the ifname, but by the ifindex. We should consistently treat
the ifindex as the ID of a link, like kernel does.

At the few places where we actually need the ifname, resolve
it by looking into the platform cache. That is not necessarily
the same as the ifname that is currently tracked by NMDevice,
because netdev interfaces can be renamed, and NMDevice updates
it's link properties delayed. However, the platform cache has
the most recent notion of the correct interface name for an
ifindex, so if we ever hit a race here, we do it now more
correctly.

This also temporarily drops support for mdns. Will be re-added next,
but differently.
parent fc40d91b
......@@ -149,16 +149,15 @@ ip_addr_to_string (int addr_family, gconstpointer addr, const char *iface, char
{
int n_written;
char buf2[NM_UTILS_INET_ADDRSTRLEN];
char separator;
const char *separator;
nm_assert_addr_family (addr_family);
nm_assert (addr);
nm_assert (iface);
nm_assert (out_buf);
if (addr_family == AF_INET) {
nm_utils_inet_ntop (addr_family, addr, buf2);
separator = '@';
separator = "@";
} else {
if (IN6_IS_ADDR_V4MAPPED (addr))
nm_utils_inet4_ntop (((const struct in6_addr *) addr)->s6_addr32[3], buf2);
......@@ -169,15 +168,15 @@ ip_addr_to_string (int addr_family, gconstpointer addr, const char *iface, char
* supported. Due to a bug, since 2.73 only '%' works properly as "server"
* address.
*/
separator = IN6_IS_ADDR_LINKLOCAL (addr) ? '%' : '@';
separator = IN6_IS_ADDR_LINKLOCAL (addr) ? "%" : "@";
}
n_written = g_snprintf (out_buf,
IP_ADDR_TO_STRING_BUFLEN,
"%s%c%s",
"%s%s%s",
buf2,
separator,
iface);
iface ? separator : "",
iface ?: "");
nm_assert (n_written < IP_ADDR_TO_STRING_BUFLEN);
return out_buf;
}
......@@ -206,11 +205,11 @@ add_global_config (NMDnsDnsmasq *self, GVariantBuilder *dnsmasq_servers, const N
}
}
static gboolean
static void
add_ip_config (NMDnsDnsmasq *self,
GVariantBuilder *servers,
int ifindex,
NMIPConfig *ip_config,
const char *iface,
gboolean split)
{
int addr_family;
......@@ -219,77 +218,79 @@ add_ip_config (NMDnsDnsmasq *self,
guint nnameservers, i_nameserver, n, i;
char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN];
char **domains, **iter;
g_return_val_if_fail (iface, FALSE);
gboolean iface_resolved = FALSE;
const char *iface = NULL;
addr_family = nm_ip_config_get_addr_family (ip_config);
g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), FALSE);
g_return_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6));
nm_assert (ifindex > 0);
nm_assert (ifindex == nm_ip_config_get_ifindex (ip_config));
nnameservers = nm_ip_config_get_num_nameservers (ip_config);
if (split) {
if (nnameservers == 0)
return FALSE;
return;
for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) {
addr = nm_ip_config_get_nameserver (ip_config, i_nameserver);
if (!iface_resolved) {
iface = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
iface_resolved = TRUE;
}
ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf);
if (iface) {
for (i_nameserver = 0; i_nameserver < nnameservers; i_nameserver++) {
addr = nm_ip_config_get_nameserver (ip_config, i_nameserver);
/* searches are preferred over domains */
n = nm_ip_config_get_num_searches (ip_config);
for (i = 0; i < n; i++) {
add_dnsmasq_nameserver (self,
servers,
ip_addr_to_string_buf,
nm_ip_config_get_search (ip_config, i));
added = TRUE;
}
ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf);
if (n == 0) {
/* If not searches, use any domains */
n = nm_ip_config_get_num_domains (ip_config);
/* searches are preferred over domains */
n = nm_ip_config_get_num_searches (ip_config);
for (i = 0; i < n; i++) {
add_dnsmasq_nameserver (self,
servers,
ip_addr_to_string_buf,
nm_ip_config_get_domain (ip_config, i));
nm_ip_config_get_search (ip_config, i));
added = TRUE;
}
}
/* Ensure reverse-DNS works by directing queries for in-addr4.arpa/ip6.arpa
* domains to the split domain's nameserver.
*/
domains = get_ip_rdns_domains (ip_config);
if (domains) {
for (iter = domains; *iter; iter++)
add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, *iter);
g_strfreev (domains);
if (n == 0) {
/* If not searches, use any domains */
n = nm_ip_config_get_num_domains (ip_config);
for (i = 0; i < n; i++) {
add_dnsmasq_nameserver (self,
servers,
ip_addr_to_string_buf,
nm_ip_config_get_domain (ip_config, i));
added = TRUE;
}
}
/* Ensure reverse-DNS works by directing queries for in-addr4.arpa/ip6.arpa
* domains to the split domain's nameserver.
*/
domains = get_ip_rdns_domains (ip_config);
if (domains) {
for (iter = domains; *iter; iter++)
add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, *iter);
g_strfreev (domains);
}
}
}
}
/* If no searches or domains, just add the nameservers */
if (!added) {
for (i = 0; i < nnameservers; i++) {
addr = nm_ip_config_get_nameserver (ip_config, i);
ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf);
add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, NULL);
if (!iface_resolved)
iface = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
if (iface) {
for (i = 0; i < nnameservers; i++) {
addr = nm_ip_config_get_nameserver (ip_config, i);
ip_addr_to_string (addr_family, addr, iface, ip_addr_to_string_buf);
add_dnsmasq_nameserver (self, servers, ip_addr_to_string_buf, NULL);
}
}
}
return TRUE;
}
static gboolean
add_ip_config_data (NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigData *data)
{
return add_ip_config (self,
servers,
data->config,
data->iface,
data->type == NM_DNS_IP_CONFIG_TYPE_VPN);
}
static void
......@@ -477,15 +478,16 @@ start_dnsmasq (NMDnsDnsmasq *self)
static gboolean
update (NMDnsPlugin *plugin,
const GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
{
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
NMDnsDnsmasqPrivate *priv = NM_DNS_DNSMASQ_GET_PRIVATE (self);
GVariantBuilder servers;
guint i;
int prio, first_prio;
const NMDnsIPConfigData *ip_data;
gboolean is_first = TRUE;
start_dnsmasq (self);
......@@ -494,15 +496,18 @@ update (NMDnsPlugin *plugin,
if (global_config)
add_global_config (self, &servers, global_config);
else {
for (i = 0; i < configs->len; i++) {
const NMDnsIPConfigData *data = configs->pdata[i];
prio = nm_ip_config_get_dns_priority (data->config);
if (i == 0)
c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
prio = nm_ip_config_get_dns_priority (ip_data->ip_config);
if (is_first) {
is_first = FALSE;
first_prio = prio;
else if (first_prio < 0 && first_prio != prio)
} else if (first_prio < 0 && first_prio != prio)
break;
add_ip_config_data (self, &servers, data);
add_ip_config (self,
&servers,
ip_data->data->ifindex,
ip_data->ip_config,
ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN);
}
}
......
This diff is collapsed.
......@@ -29,9 +29,11 @@
#include "nm-setting-connection.h"
typedef enum {
NM_DNS_IP_CONFIG_TYPE_REMOVED = -1,
NM_DNS_IP_CONFIG_TYPE_DEFAULT = 0,
NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE,
NM_DNS_IP_CONFIG_TYPE_VPN
NM_DNS_IP_CONFIG_TYPE_VPN,
} NMDnsIPConfigType;
enum {
......@@ -39,17 +41,22 @@ enum {
NM_DNS_PRIORITY_DEFAULT_VPN = 50,
};
struct _NMDnsConfigData;
struct _NMDnsManager;
typedef struct {
gpointer config;
NMDnsIPConfigType type;
char *iface;
struct _NMDnsConfigData *data;
NMIPConfig *ip_config;
CList data_lst;
CList ip_config_lst;
NMDnsIPConfigType ip_config_type;
} NMDnsIPConfigData;
typedef struct {
NMSettingConnectionMdns mdns;
char *iface;
typedef struct _NMDnsConfigData {
struct _NMDnsManager *self;
CList data_lst_head;
int ifindex;
} NMDnsConnectionConfigData;
} NMDnsConfigData;
#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))
......@@ -77,28 +84,15 @@ NMDnsManager * nm_dns_manager_get (void);
void nm_dns_manager_begin_updates (NMDnsManager *self, const char *func);
void nm_dns_manager_end_updates (NMDnsManager *self, const char *func);
gboolean nm_dns_manager_add_ip_config (NMDnsManager *self,
const char *iface,
gpointer config,
NMDnsIPConfigType cfg_type);
gboolean nm_dns_manager_remove_ip_config (NMDnsManager *self, gpointer config);
gboolean nm_dns_manager_set_ip_config (NMDnsManager *self,
NMIPConfig *ip_config,
NMDnsIPConfigType ip_config_type);
void nm_dns_manager_set_initial_hostname (NMDnsManager *self,
const char *hostname);
void nm_dns_manager_set_hostname (NMDnsManager *self,
const char *hostname,
gboolean skip_update);
gboolean nm_dns_manager_add_connection_config (NMDnsManager *self,
const char *iface,
int ifindex,
NMSettingConnectionMdns mdns);
void nm_dns_manager_remove_connection_config (NMDnsManager *self,
const char *iface,
int ifindex);
void nm_dns_manager_update_ifindex (NMDnsManager *self,
const char *ip_iface,
int new_ifindex);
/**
* NMDnsManagerResolvConfManager
......
......@@ -77,30 +77,18 @@ G_DEFINE_TYPE_EXTENDED (NMDnsPlugin, nm_dns_plugin, G_TYPE_OBJECT, G_TYPE_FLAG_A
gboolean
nm_dns_plugin_update (NMDnsPlugin *self,
const GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
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,
configs,
global_config,
ip_config_lst_head,
hostname);
}
gboolean
nm_dns_plugin_update_mdns (NMDnsPlugin *self,
int ifindex,
NMSettingConnectionMdns mdns)
{
g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update_mdns != NULL, FALSE);
return NM_DNS_PLUGIN_GET_CLASS (self)->update_mdns (self,
ifindex,
mdns);
}
static gboolean
is_caching (NMDnsPlugin *self)
{
......
......@@ -50,8 +50,8 @@ typedef struct {
* configuration.
*/
gboolean (*update) (NMDnsPlugin *self,
const GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname);
/* Subclasses should override and return TRUE if they start a local
......@@ -60,11 +60,6 @@ typedef struct {
*/
gboolean (*is_caching) (NMDnsPlugin *self);
/* Subclasses wishing to control interface mDNS status should override. */
gboolean (*update_mdns) (NMDnsPlugin *self,
int ifindex,
NMSettingConnectionMdns mdns);
/* Subclasses should override this and return their plugin name */
const char *(*get_name) (NMDnsPlugin *self);
......@@ -85,14 +80,10 @@ 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 GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname);
gboolean nm_dns_plugin_update_mdns (NMDnsPlugin *self,
int ifindex,
NMSettingConnectionMdns mdns);
void nm_dns_plugin_stop (NMDnsPlugin *self);
/* For subclasses/plugins */
......
......@@ -282,8 +282,8 @@ send_updates (NMDnsSystemdResolved *self)
static gboolean
update (NMDnsPlugin *plugin,
const GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
{
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin);
......@@ -292,23 +292,26 @@ update (NMDnsPlugin *plugin,
guint interfaces_len;
guint i;
int prio, first_prio = 0;
NMDnsIPConfigData *ip_data;
gboolean is_first = TRUE;
interfaces = g_hash_table_new_full (nm_direct_hash, NULL,
NULL, (GDestroyNotify) _interface_config_free);
for (i = 0; i < configs->len; i++) {
const NMDnsIPConfigData *data = configs->pdata[i];
c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
gboolean skip = FALSE;
InterfaceConfig *ic = NULL;
int ifindex;
prio = nm_ip_config_get_dns_priority (data->config);
if (i == 0)
prio = nm_ip_config_get_dns_priority (ip_data->ip_config);
if (is_first) {
is_first = FALSE;
first_prio = prio;
else if (first_prio < 0 && first_prio != prio)
} else if (first_prio < 0 && first_prio != prio)
skip = TRUE;
ifindex = nm_ip_config_get_ifindex (data->config);
ifindex = ip_data->data->ifindex;
nm_assert (ifindex == nm_ip_config_get_ifindex (ip_data->ip_config));
ic = g_hash_table_lookup (interfaces, GINT_TO_POINTER (ifindex));
if (!ic) {
......@@ -320,7 +323,7 @@ update (NMDnsPlugin *plugin,
if (!skip) {
c_list_link_tail (&ic->configs_lst_head,
&nm_c_list_elem_new_stale (data->config)->lst);
&nm_c_list_elem_new_stale (ip_data->ip_config)->lst);
}
}
......@@ -345,45 +348,6 @@ update (NMDnsPlugin *plugin,
return TRUE;
}
static gboolean
update_mdns (NMDnsPlugin *plugin, int ifindex, NMSettingConnectionMdns mdns)
{
NMDnsSystemdResolved *self = NM_DNS_SYSTEMD_RESOLVED (plugin);
NMDnsSystemdResolvedPrivate *priv = NM_DNS_SYSTEMD_RESOLVED_GET_PRIVATE (self);
char *value;
_LOGI ("update_mdns: %i/%d", ifindex, mdns);
nm_clear_g_cancellable (&priv->mdns_cancellable);
if (!priv->resolve)
return FALSE;
priv->mdns_cancellable = g_cancellable_new ();
switch (mdns) {
case NM_SETTING_CONNECTION_MDNS_YES:
value = "yes";
break;
case NM_SETTING_CONNECTION_MDNS_NO:
value = "no";
break;
case NM_SETTING_CONNECTION_MDNS_RESOLVE:
value = "resolve";
break;
default:
/* reset to system default */
value = "";
}
g_dbus_proxy_call (priv->resolve, "SetLinkMulticastDNS",
g_variant_new ("(is)", ifindex, value),
G_DBUS_CALL_FLAGS_NONE,
-1, priv->mdns_cancellable, call_done, self);
return TRUE;
}
/*****************************************************************************/
static gboolean
......@@ -486,6 +450,5 @@ nm_dns_systemd_resolved_class_init (NMDnsSystemdResolvedClass *dns_class)
plugin_class->is_caching = is_caching;
plugin_class->update = update;
plugin_class->update_mdns = update_mdns;
plugin_class->get_name = get_name;
}
......@@ -39,8 +39,8 @@ G_DEFINE_TYPE (NMDnsUnbound, nm_dns_unbound, NM_TYPE_DNS_PLUGIN)
static gboolean
update (NMDnsPlugin *plugin,
const GPtrArray *configs,
const NMGlobalDnsConfig *global_config,
const CList *ip_config_lst_head,
const char *hostname)
{
char *argv[] = { DNSSEC_TRIGGER_SCRIPT, "--async", "--update", NULL };
......
......@@ -379,6 +379,12 @@ nm_ip_config_get_ifindex (const NMIPConfig *self)
_NM_IP_CONFIG_DISPATCH (self, nm_ip4_config_get_ifindex, nm_ip6_config_get_ifindex);
}
static inline void
nm_ip_config_hash (const NMIPConfig *self, GChecksum *sum, gboolean dns_only)
{
_NM_IP_CONFIG_DISPATCH_VOID (self, nm_ip4_config_hash, nm_ip6_config_hash, sum, dns_only);
}
static inline void
nm_ip_config_add_address (NMIPConfig *self, const NMPlatformIPAddress *address)
{
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment