[PATCH] Added support for timezones on dhcp6-client (RFC 4833)

tiggersWelt.net (Support) support at tiggerswelt.net
Wed Jun 21 14:29:55 UTC 2017


Am 20.06.2017 um 22:13 schrieb Bernhard Reutner-Fischer:
[...]
>> Literal String. If otherwise I would have used udhcp's functions for this.
> 
> Did you tell them? They should really fix this on their end..

Absolutely right. I'll put this onto my agenda.

[...]
>> If I understood the "cap"-argument right, I would move the olen-calculation to a
>> more general place and check it accordingly. I'll also rename it to something
>> more catchy.
> 
> please do.
> TIA!

Thank you for your support!

As option-length applies to all option-parsing I've introduced a general check at
the beginning of the loop.

Because option[2] is already expected to be zero there for historical reasons,
I've removed option[2] from all of my length-processing and was therefore able to
remove most of the "olen"-stuff.
"olen" was renamed to "addrs" as it is only used to count number of DNS-Servers
on D6_OPT_DNS_SERVERS. I also renamed "ooff" to "option_offset" for better
understanding of its meaning.

While parsing D6_OPT_DNS_SERVERS I was also able to save one pointer by pushing
the variable to env earlier. There are no error-cases there it should not matter
at which point this is done.
There was also malloc() used - I changed it to xmalloc().

---
 networking/udhcp/d6_common.h |  3 ++
 networking/udhcp/d6_dhcpc.c  | 82 ++++++++++++++++++++++++++++----------------
 2 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/networking/udhcp/d6_common.h b/networking/udhcp/d6_common.h
index fcec8c15a..ca5788390 100644
--- a/networking/udhcp/d6_common.h
+++ b/networking/udhcp/d6_common.h
@@ -89,6 +89,9 @@ struct d6_option {

 #define D6_OPT_CLIENT_FQDN   39

+#define D6_OPT_TZ_POSIX      41
+#define D6_OPT_TZ_NAME       42
+
 /*** Other shared functions ***/

 struct client6_data_t {
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 18a104c61..cf495cefe 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -90,10 +90,12 @@ enum {

 static const char opt_req[] = {
 	(D6_OPT_ORO >> 8), (D6_OPT_ORO & 0xff),
-	0, 6,
+	0, 10,
 	(D6_OPT_DNS_SERVERS >> 8), (D6_OPT_DNS_SERVERS & 0xff),
 	(D6_OPT_DOMAIN_LIST >> 8), (D6_OPT_DOMAIN_LIST & 0xff),
-	(D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff)
+	(D6_OPT_CLIENT_FQDN >> 8), (D6_OPT_CLIENT_FQDN & 0xff),
+	(D6_OPT_TZ_POSIX >> 8), (D6_OPT_TZ_POSIX & 0xff),
+	(D6_OPT_TZ_NAME >> 8), (D6_OPT_TZ_NAME & 0xff)
 };

 static const char opt_fqdn_req[] = {
@@ -154,10 +156,10 @@ static char** new_env(void)
 /* put all the parameters into the environment */
 static void option_to_env(uint8_t *option, uint8_t *option_end)
 {
-	char *dlist, *ptr;
+	char *dlist;
 	/* "length minus 4" */
 	int len_m4 = option_end - option - 4;
-	int olen, ooff;
+	int addrs, option_offset;
 	while (len_m4 >= 0) {
 		uint32_t v32;
 		char ipv6str[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
@@ -165,6 +167,10 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
 		if (option[0] != 0 || option[2] != 0)
 			break;

+		/* check if option-length exceeds size of option */
+		if (option [3] > len_m4)
+			break;
+
 		switch (option[1]) {
 		//case D6_OPT_CLIENTID:
 		//case D6_OPT_SERVERID:
@@ -236,22 +242,26 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
 			*new_env() = xasprintf("ipv6prefix=%s/%u", ipv6str, (unsigned)(option[4 + 4]));
 			break;
 		case D6_OPT_DNS_SERVERS:
-			olen = ((option[2] << 8) | option[3]) / 16;
-			dlist = ptr = malloc (4 + olen * 40 - 1);
-
-			memcpy (ptr, "dns=", 4);
-			ptr += 4;
-			ooff = 0;
-
-			while (olen--) {
-				sprint_nip6(ptr, option + 4 + ooff);
-				ptr += 39;
-				ooff += 16;
-				if (olen)
-					*ptr++ = ' ';
-			}
+			/* Make sure payload-size is a multiple of 16 */
+			if ((option[3] & 0x0F) != 0)
+				break;

-			*new_env() = dlist;
+			/* Get the number of addresses on the option */
+			addrs = option[3] >> 4;
+
+			/* Setup environment-variable */
+			*new_env() = dlist = xmalloc (4 + addrs * 40 - 1);
+			memcpy (dlist, "dns=", 4);
+			dlist += 4;
+			option_offset = 0;
+
+			while (addrs--) {
+				sprint_nip6(dlist, option + 4 + option_offset);
+				dlist += 39;
+				option_offset += 16;
+				if (addrs)
+					*dlist++ = ' ';
+			}

 			break;
 		case D6_OPT_DOMAIN_LIST:
@@ -261,17 +271,18 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
 			*new_env() = dlist;
 			break;
 		case D6_OPT_CLIENT_FQDN:
-			// Work around broken ISC DHCPD6
+			/* Work around broken ISC DHCPD6
+			 * ISC DHCPD6 does not implement RFC 4704 correctly: It says the first
+			 * byte of option-payload should contain flags where the bits 4-8 are
+			 * reserved for future use and MUST be zero. Instead ISC DHCPD6 just
+			 * writes the entire FQDN as string to option-payload. We assume a
+			 * broken server here if any of the reserved bits is set.
+			 */
 			if (option[4] & 0xf8) {
-				olen = ((option[2] << 8) | option[3]);
-				dlist = xmalloc(olen);
-//fixme:
-//- explain
-//- add len error check
-//- merge two allocs into one
-				memcpy(dlist, option + 4, olen);
-				*new_env() = xasprintf("fqdn=%s", dlist);
-				free(dlist);
+				dlist = xmalloc(option[3] + 5);
+				memcpy(dlist,"fqdn=",5);
+				memcpy(dlist + 5, option + 4, option[3]);
+				*new_env() = dlist;
 				break;
 			}
 			dlist = dname_dec(option + 5, ((option[2] << 8) | option[3]) - 1, "fqdn=");
@@ -279,6 +290,19 @@ static void option_to_env(uint8_t *option, uint8_t *option_end)
 				break;
 			*new_env() = dlist;
 			break;
+		/* RFC 4833 Timezones */
+		case D6_OPT_TZ_POSIX:
+			dlist = xmalloc(option[3] + 3);
+			memcpy(dlist, "tz=", 3);
+			memcpy(dlist + 3, option + 4, option[3]);
+			*new_env() = dlist;
+			break;
+		case D6_OPT_TZ_NAME:
+			dlist = xmalloc(option[3] + 8);
+			memcpy(dlist, "tz_name=", 8);
+			memcpy(dlist + 8, option + 4, option[3]);
+			*new_env() = dlist;
+			break;
 		}
 		len_m4 -= 4 + option[3];
 		option += 4 + option[3];
-- 
2.12.2


-- 
    \\\||///
  \\  - -  //
   (  @ @  )
-oOo--( )--oOo-------------------------------------------------------
 tiggersWelt.net                                 www.tiggersWelt.net
 Inhaber Bernd Holzmüller                       info at tiggerswelt.net
                                            Büro: 07 11 / 550 425-90
 Marktstraße 57                              Fax: 07 11 / 550 425-99
 70372 Stuttgart

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3310 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20170621/71fcb937/attachment.p7s>


More information about the busybox mailing list