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

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