Blame SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch

61c145
From 03936d309782da038a2982b08fce7be85d884f0e Mon Sep 17 00:00:00 2001
61c145
From: Vladislav Grishenko <themiron@mail.ru>
61c145
Date: Sun, 8 Mar 2020 15:34:34 +0000
61c145
Subject: [PATCH] Add DHCPv6 ntp-server (56) option handling.
61c145
61c145
There was discussion in the past regarding DHCPv6 NTP server option
61c145
which needs special subclassing per RFC5908.
61c145
61c145
Patch adds support for unicast, multicast IPv6 address and for FQDN string,
61c145
preserving possibly used (as suggested earlier) hex value.
61c145
61c145
Unfortunately it's still not fully free from limitations - only address list or
61c145
only fqdn value list is possible, not mixed due current
61c145
state option parsing & flagging.
61c145
61c145
(cherry picked from commit dded78b2338147daf69064d6d48c16b12744e441)
61c145
---
61c145
 src/dhcp-common.c    |  2 +-
61c145
 src/dhcp6-protocol.h |  4 ++++
61c145
 src/option.c         | 19 ++++++++++++++++---
61c145
 src/rfc3315.c        | 24 ++++++++++++++++++++----
61c145
 4 files changed, 41 insertions(+), 8 deletions(-)
61c145
61c145
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
61c145
index 368d686..242a5a1 100644
61c145
--- a/src/dhcp-common.c
61c145
+++ b/src/dhcp-common.c
61c145
@@ -642,7 +642,7 @@ static const struct opttab_t opttab6[] = {
61c145
   { "sntp-server", 31,  OT_ADDR_LIST },
61c145
   { "information-refresh-time", 32, OT_TIME },
61c145
   { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
61c145
-  { "ntp-server", 56,  0 },
61c145
+  { "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ },
61c145
   { "bootfile-url", 59, OT_NAME },
61c145
   { "bootfile-param", 60, OT_CSTRING },
61c145
   { "client-arch", 61, 2 | OT_DEC }, /* RFC 5970 */
61c145
diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h
61c145
index fee5d28..05560e8 100644
61c145
--- a/src/dhcp6-protocol.h
61c145
+++ b/src/dhcp6-protocol.h
61c145
@@ -59,12 +59,16 @@
61c145
 #define OPTION6_REMOTE_ID       37
61c145
 #define OPTION6_SUBSCRIBER_ID   38
61c145
 #define OPTION6_FQDN            39
61c145
+#define OPTION6_NTP_SERVER      56
61c145
 #define OPTION6_CLIENT_MAC      79
61c145
 
61c145
 /* replace this with the real number when allocated.
61c145
    defining this also enables the relevant code. */ 
61c145
 /* #define OPTION6_PREFIX_CLASS    99 */
61c145
 
61c145
+#define NTP_SUBOPTION_SRV_ADDR  1
61c145
+#define NTP_SUBOPTION_MC_ADDR   2
61c145
+#define NTP_SUBOPTION_SRV_FQDN  3
61c145
 
61c145
 #define DHCP6SUCCESS     0
61c145
 #define DHCP6UNSPEC      1
61c145
diff --git a/src/option.c b/src/option.c
61c145
index 6fa7bbd..1382c55 100644
61c145
--- a/src/option.c
61c145
+++ b/src/option.c
61c145
@@ -1245,6 +1245,12 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
61c145
       if (!found_dig)
61c145
 	is_dec = is_addr = 0;
61c145
      
61c145
+#ifdef HAVE_DHCP6
61c145
+      /* NTP server option takes hex, addresses or FQDN */
61c145
+      if (is6 && new->opt == OPTION6_NTP_SERVER && !is_hex)
61c145
+	opt_len |= is_addr6 ? OT_ADDR_LIST : OT_RFC1035_NAME;
61c145
+#endif
61c145
+     
61c145
       /* We know that some options take addresses */
61c145
       if (opt_len & OT_ADDR_LIST)
61c145
 	{
61c145
@@ -1505,8 +1511,9 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
61c145
 	    }
61c145
 	  else if (comma && (opt_len & OT_RFC1035_NAME))
61c145
 	    {
61c145
-	      unsigned char *p = NULL, *newp, *end;
61c145
+	      unsigned char *p = NULL, *q, *newp, *end;
61c145
 	      int len = 0;
61c145
+	      int header_size = (is6 && new->opt == OPTION6_NTP_SERVER) ? 4 : 0;
61c145
 	      arg = comma;
61c145
 	      comma = split(arg);
61c145
 	      
61c145
@@ -1516,7 +1523,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
61c145
 		  if (!dom)
61c145
 		    goto_err(_("bad domain in dhcp-option"));
61c145
 		    		  
61c145
-		  newp = opt_malloc(len + strlen(dom) + 2);
61c145
+		  newp = opt_malloc(len + header_size + strlen(dom) + 2);
61c145
 		  
61c145
 		  if (p)
61c145
 		    {
61c145
@@ -1525,8 +1532,14 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
61c145
 		    }
61c145
 		  
61c145
 		  p = newp;
61c145
-		  end = do_rfc1035_name(p + len, dom, NULL);
61c145
+		  q = p + len;
61c145
+		  end = do_rfc1035_name(q + header_size, dom, NULL);
61c145
 		  *end++ = 0;
61c145
+		  if (is6 && new->opt == OPTION6_NTP_SERVER)
61c145
+		    {
61c145
+		      PUTSHORT(NTP_SUBOPTION_SRV_FQDN, q);
61c145
+		      PUTSHORT(end - q - 2, q);
61c145
+		    }
61c145
 		  len = end - p;
61c145
 		  free(dom);
61c145
 
61c145
diff --git a/src/rfc3315.c b/src/rfc3315.c
61c145
index 1f1aad8..0fa12ad 100644
61c145
--- a/src/rfc3315.c
61c145
+++ b/src/rfc3315.c
61c145
@@ -1380,23 +1380,39 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
61c145
 	      	  
61c145
 	      for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
61c145
 		{
61c145
+		  struct in6_addr *p = NULL;
61c145
+
61c145
 		  if (IN6_IS_ADDR_UNSPECIFIED(a))
61c145
 		    {
61c145
 		      if (!add_local_addrs(state->context))
61c145
-			put_opt6(state->fallback, IN6ADDRSZ);
61c145
+			p = state->fallback;
61c145
 		    }
61c145
 		  else if (IN6_IS_ADDR_ULA_ZERO(a))
61c145
 		    {
61c145
 		      if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
61c145
-			put_opt6(state->ula_addr, IN6ADDRSZ);
61c145
+			p = state->ula_addr;
61c145
 		    }
61c145
 		  else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
61c145
 		    {
61c145
 		      if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
61c145
-			put_opt6(state->ll_addr, IN6ADDRSZ);
61c145
+			p = state->ll_addr;
61c145
+		    }
61c145
+		  else
61c145
+		    p = a;
61c145
+
61c145
+		  if (!p)
61c145
+		    continue;
61c145
+		  else if (opt_cfg->opt == OPTION6_NTP_SERVER)
61c145
+		    {
61c145
+		      if (IN6_IS_ADDR_MULTICAST(p))
61c145
+			o1 = new_opt6(NTP_SUBOPTION_MC_ADDR);
61c145
+		      else
61c145
+			o1 = new_opt6(NTP_SUBOPTION_SRV_ADDR);
61c145
+		      put_opt6(p, IN6ADDRSZ);
61c145
+		      end_opt6(o1);
61c145
 		    }
61c145
 		  else
61c145
-		    put_opt6(a, IN6ADDRSZ);
61c145
+		    put_opt6(p, IN6ADDRSZ);
61c145
 		}
61c145
 
61c145
 	      end_opt6(o);
61c145
-- 
61c145
2.36.1
61c145