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

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