Re: [PATCH] Use '@interface' for link-local DNS servers in the dnsmasq config
- From: Dan Williams <dcbw redhat com>
- To: Michael Stapelberg <michael+nm stapelberg de>
- Cc: networkmanager-list gnome org
- Subject: Re: [PATCH] Use '@interface' for link-local DNS servers in the dnsmasq config
- Date: Fri, 19 Aug 2011 17:47:59 -0500
On Fri, 2011-08-12 at 13:50 +0200, Michael Stapelberg wrote:
> Hi,
>
> the attached patch makes the dnsmasq DNS plugin work with IPv6 DNS
> servers with link-local IP addresses. This is similar to commit
> c3893b5325ca61261be1749490352f26b41bd479, where '%interface' is
> appended to the entries in /etc/resolv.conf for link-local DNS servers.
>
> dnsmasq supports link-local IP addresses when using the syntax
> '@interface'. I have talked to the dnsmasq author and he will provide
> '%interface' in future versions.
>
> Please tell me if you need any further information or if I should
> change something. Otherwise, please merge this patch :).
Thanks! Though we do risk buffer overflows because the buffer being
passed into the function is only INET6_ADDRSTRLEN long, so we need to be
more careful here when appending the interface name. I've reworked that
a bit, can you test the attached patch and make sure it does the same
thing yours does? It's compile-tested but not run tested. When I
commit you'll still get credit, of course. Thanks for looking into
this.
Dan
>From b05f137001f310845b43c9230ae144a7ab7b8dd5 Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael stapelberg de>
Date: Fri, 12 Aug 2011 13:43:07 +0200
Subject: [PATCH] dnsmasq: use '@interface' for link-local DNS servers in the
dnsmasq config
dnsmasq doesn't support the standard '%' that inet_ntop() returns,
so use '@' instead and append the interface name.
---
src/dns-manager/nm-dns-bind.c | 3 +-
src/dns-manager/nm-dns-dnsmasq.c | 62 +++++++++++++++++++++++++++++--------
src/dns-manager/nm-dns-manager.c | 3 +-
src/dns-manager/nm-dns-plugin.c | 6 ++-
src/dns-manager/nm-dns-plugin.h | 6 ++-
5 files changed, 60 insertions(+), 20 deletions(-)
diff --git a/src/dns-manager/nm-dns-bind.c b/src/dns-manager/nm-dns-bind.c
index fc7af77..55fce03 100644
--- a/src/dns-manager/nm-dns-bind.c
+++ b/src/dns-manager/nm-dns-bind.c
@@ -297,7 +297,8 @@ update (NMDnsPlugin *plugin,
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
- const char *hostname)
+ const char *hostname,
+ const char *iface)
{
NMDnsBind *self = NM_DNS_BIND (plugin);
NMDnsBindPrivate *priv = NM_DNS_BIND_GET_PRIVATE (self);
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c
index 9cc0197..2600d1b 100644
--- a/src/dns-manager/nm-dns-dnsmasq.c
+++ b/src/dns-manager/nm-dns-dnsmasq.c
@@ -133,23 +133,50 @@ add_ip4_config (GString *str, NMIP4Config *ip4, gboolean split)
return TRUE;
}
-static gboolean
-ip6_addr_to_string (const struct in6_addr *addr, char *buf, size_t buflen)
+#define IP6_ADDR_BUFLEN (INET6_ADDRSTRLEN + 50)
+
+static char *
+ip6_addr_to_string (const struct in6_addr *addr, const char *iface)
{
- memset (buf, 0, buflen);
+ char *buf, *p;
+
+ /* allocate enough space for the address + interface name */
+ buf = g_malloc0 (IP6_ADDR_BUFLEN + 1);
/* inet_ntop is probably supposed to do this for us, but it doesn't */
- if (IN6_IS_ADDR_V4MAPPED (addr))
- return !!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, buflen);
+ if (IN6_IS_ADDR_V4MAPPED (addr)) {
+ if (!inet_ntop (AF_INET, &(addr->s6_addr32[3]), buf, IP6_ADDR_BUFLEN))
+ goto error;
+ return buf;
+ }
- return !!inet_ntop (AF_INET6, addr, buf, buflen);
+ if (!inet_ntop (AF_INET6, addr, buf, IP6_ADDR_BUFLEN))
+ goto error;
+
+ /* dnsmasq only supports @ at the moment so replace the '%' with '@' */
+ p = strchr (buf, '%');
+ if (p) {
+ *p = '@';
+
+ /* Append interface name for link-local DNS servers; this assumes the
+ * '@' is the last character.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL (addr))
+ strncat (buf, iface, (IP6_ADDR_BUFLEN - strlen (buf) - 1));
+ }
+
+ return buf;
+
+error:
+ g_free (buf);
+ return NULL;
}
static gboolean
-add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
+add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split, const char *iface)
{
- char buf[INET6_ADDRSTRLEN + 1];
const struct in6_addr *addr;
+ char *buf;
int n, i;
gboolean added = FALSE;
@@ -159,7 +186,8 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
* the first nameserver here.
*/
addr = nm_ip6_config_get_nameserver (ip6, 0);
- if (!ip6_addr_to_string (addr, &buf[0], sizeof (buf)))
+ buf = ip6_addr_to_string (addr, iface);
+ if (!buf)
return FALSE;
/* searches are preferred over domains */
@@ -181,6 +209,8 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
added = TRUE;
}
}
+
+ g_free (buf);
}
/* If no searches or domains, just add the namservers */
@@ -188,8 +218,11 @@ add_ip6_config (GString *str, NMIP6Config *ip6, gboolean split)
n = nm_ip6_config_get_num_nameservers (ip6);
for (i = 0; i < n; i++) {
addr = nm_ip6_config_get_nameserver (ip6, i);
- if (ip6_addr_to_string (addr, &buf[0], sizeof (buf)))
+ buf = ip6_addr_to_string (addr, iface);
+ if (buf) {
g_string_append_printf (str, "server=%s\n", buf);
+ g_free (buf);
+ }
}
}
@@ -201,7 +234,8 @@ update (NMDnsPlugin *plugin,
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
- const char *hostname)
+ const char *hostname,
+ const char *iface)
{
NMDnsDnsmasq *self = NM_DNS_DNSMASQ (plugin);
GString *conf;
@@ -226,7 +260,7 @@ update (NMDnsPlugin *plugin,
if (NM_IS_IP4_CONFIG (iter->data))
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), TRUE);
else if (NM_IS_IP6_CONFIG (iter->data))
- add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE);
+ add_ip6_config (conf, NM_IP6_CONFIG (iter->data), TRUE, iface);
}
/* Now add interface configs without split DNS */
@@ -234,7 +268,7 @@ update (NMDnsPlugin *plugin,
if (NM_IS_IP4_CONFIG (iter->data))
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
else if (NM_IS_IP6_CONFIG (iter->data))
- add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
+ add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface);
}
/* And any other random configs */
@@ -242,7 +276,7 @@ update (NMDnsPlugin *plugin,
if (NM_IS_IP4_CONFIG (iter->data))
add_ip4_config (conf, NM_IP4_CONFIG (iter->data), FALSE);
else if (NM_IS_IP6_CONFIG (iter->data))
- add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE);
+ add_ip6_config (conf, NM_IP6_CONFIG (iter->data), FALSE, iface);
}
/* Write out the config file */
diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c
index 49cd74e..0203f2b 100644
--- a/src/dns-manager/nm-dns-manager.c
+++ b/src/dns-manager/nm-dns-manager.c
@@ -711,7 +711,8 @@ update_dns (NMDnsManager *self,
vpn_configs,
dev_configs,
other_configs,
- priv->hostname)) {
+ priv->hostname,
+ iface)) {
nm_log_warn (LOGD_DNS, "DNS: plugin %s update failed", plugin_name);
/* If the plugin failed to update, we shouldn't write out a local
diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c
index ae230ad..e997948 100644
--- a/src/dns-manager/nm-dns-plugin.c
+++ b/src/dns-manager/nm-dns-plugin.c
@@ -55,7 +55,8 @@ nm_dns_plugin_update (NMDnsPlugin *self,
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
- const char *hostname)
+ const char *hostname,
+ const char *iface)
{
g_return_val_if_fail (NM_DNS_PLUGIN_GET_CLASS (self)->update != NULL, FALSE);
@@ -63,7 +64,8 @@ nm_dns_plugin_update (NMDnsPlugin *self,
vpn_configs,
dev_configs,
other_configs,
- hostname);
+ hostname,
+ iface);
}
static gboolean
diff --git a/src/dns-manager/nm-dns-plugin.h b/src/dns-manager/nm-dns-plugin.h
index d4298b8..37dd733 100644
--- a/src/dns-manager/nm-dns-plugin.h
+++ b/src/dns-manager/nm-dns-plugin.h
@@ -53,7 +53,8 @@ typedef struct {
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
- const char *hostname);
+ const char *hostname,
+ const char *iface);
/* Subclasses should override and return TRUE if they start a local
* caching nameserver that listens on localhost and would block any
@@ -91,7 +92,8 @@ gboolean nm_dns_plugin_update (NMDnsPlugin *self,
const GSList *vpn_configs,
const GSList *dev_configs,
const GSList *other_configs,
- const char *hostname);
+ const char *hostname,
+ const char *iface);
/* For subclasses/plugins */
--
1.7.6
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]