From 9711afaf6980542f58383adbe24b58c678163fc6 Mon Sep 17 00:00:00 2001
From: Christof Schulze <christof.schulze@gmx.net>
Date: Mon, 29 Jan 2018 08:21:47 +0100
Subject: [PATCH] gluon-core: allow multiple domain names for next_node-feature

* change type of next_node.name
* create domain entry for each entry and add to dnsmasq configuration

[Matthias Schiffer: reword documentation]
---
 docs/site-example/site.conf                   |  1 +
 docs/user/site.rst                            |  8 ++++++
 package/gluon-core/check_site.lua             |  1 +
 .../luasrc/lib/gluon/upgrade/820-dns-config   | 25 +++++++++----------
 4 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/docs/site-example/site.conf b/docs/site-example/site.conf
index a152eca64..36e769223 100644
--- a/docs/site-example/site.conf
+++ b/docs/site-example/site.conf
@@ -83,6 +83,7 @@
   -- connected to using a known IP address.
   next_node = {
     -- anycast IPs of all nodes
+    -- name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
     ip4 = '10.xxx.0.xxx',
     ip6 = 'fdxx:xxxx:xxxx::xxxx',
   },
diff --git a/docs/user/site.rst b/docs/user/site.rst
index 9e4439609..1ab1b1764 100644
--- a/docs/user/site.rst
+++ b/docs/user/site.rst
@@ -163,6 +163,7 @@ next_node \: package
     ::
 
       next_node = {
+        name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
         ip4 = '10.23.42.1',
         ip6 = 'fdca:ffee:babe:1::1',
         mac = '16:41:95:40:f7:dc'
@@ -174,6 +175,13 @@ next_node \: package
     changed, but it can be adjusted to match existing deployments that use a
     different value.
 
+    When the nodes' next-node address is used as a DNS resolver by clients
+    (by passing it via DHCP or router advertisements), it may be useful to
+    allow resolving a next-node hostname without referring to an upstream DNS
+    server (e.g. to allow reaching the node using such a hostname via HTTP or SSH
+    in isolated mesh segments). This is possible by providing one or more names
+    in the ``name`` field.
+
 mesh \: optional
     Options specific to routing protocols.
 
diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua
index 99cdedac5..6c074c341 100644
--- a/package/gluon-core/check_site.lua
+++ b/package/gluon-core/check_site.lua
@@ -70,6 +70,7 @@ if need_table({'dns'}, nil, false) then
 	need_number({'dns', 'cacheentries'}, false)
 end
 
+need_string_array(in_domain({'next_node', 'name'}), false)
 need_string_match(in_domain({'next_node', 'ip6'}), '^[%x:]+$', false)
 need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false)
 
diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config
index ef12208ee..ea0bf4ac4 100755
--- a/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config
+++ b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config
@@ -25,22 +25,21 @@ if dns.servers then
 	})
 end
 
-if next_node.name and next_node.ip4 then
-	uci:section('dhcp', 'domain', 'nextnode4', {
-		name = next_node.name,
-		ip = next_node.ip4,
+local function set_dns_record(name, ip, sectionname)
+	if not ip then return end
+	uci:section('dhcp', 'domain', sectionname, {
+		name = name,
+		ip = ip,
 	})
-else
-	uci:delete('dhcp', 'domain', 'nextnode4')
 end
 
-if next_node.name and next_node.ip6 then
-	uci:section('dhcp', 'domain', 'nextnode6', {
-		name = next_node.name,
-		ip = next_node.ip6,
-	})
-else
-	uci:delete('dhcp', 'domain', 'nextnode6')
+uci:delete_all('dhcp', 'domain', function(s)
+	return (s['.name'] and string.match(s['.name'], "^nextnode[46]"))
+end)
+
+for i, name in ipairs(next_node.name or {}) do
+	set_dns_record(name, next_node.ip4, 'nextnode4_' .. i)
+	set_dns_record(name, next_node.ip6, 'nextnode6_' .. i)
 end
 
 uci:save('dhcp')
-- 
GitLab