From 6bc0cfdb63197040a0f40e4323b3e3c48f3ed6cb Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Mon, 27 Jan 2014 13:43:38 +0100 Subject: [PATCH] add support Vendor Class option This patch adds cli option "-V " which will enable sending of DHCPv6 option 16 ("vendor class"). Based on Patch by Christian Carstensen Contributed by T-Labs, Deutsche Telekom Innovation Laboratories --- src/dhcpv6.c | 25 ++++++++++++++++++------- src/odhcp6c.c | 11 ++++++++++- src/odhcp6c.h | 2 ++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index eab9cbf..9edf055 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -368,6 +368,15 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs) // Request Information Refresh uint16_t oro_refresh = htons(DHCPV6_OPT_INFO_REFRESH); + // Build vendor-class option + size_t vendor_class_len; + struct dhcpv6_vendorclass *vendor_class = odhcp6c_get_state(STATE_VENDORCLASS, &vendor_class_len); + + struct { + uint16_t type; + uint16_t length; + } vendor_class_hdr = {htons(DHCPV6_OPT_VENDOR_CLASS), htons(vendor_class_len)}; + // Prepare Header size_t oro_len; void *oro = odhcp6c_get_state(STATE_ORO, &oro_len); @@ -392,6 +401,8 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs) {&oro_refresh, 0}, {cl_id, cl_id_len}, {srv_id, srv_id_len}, + {&vendor_class_hdr, vendor_class_len ? sizeof(vendor_class_hdr) : 0}, + {vendor_class, vendor_class_len}, {&reconf_accept, sizeof(reconf_accept)}, {&fqdn, fqdn_len}, {&hdr_ia_na, sizeof(hdr_ia_na)}, @@ -401,28 +412,28 @@ static void dhcpv6_send(enum dhcpv6_msg type, uint8_t trid[3], uint32_t ecs) size_t cnt = ARRAY_SIZE(iov); if (type == DHCPV6_MSG_INFO_REQ) { - cnt = 5; + cnt = 7; iov[2].iov_len = sizeof(oro_refresh); hdr.oro_len = htons(oro_len + sizeof(oro_refresh)); } else if (!request_prefix) { - cnt = 9; + cnt = 11; } // Disable IAs if not used if (type != DHCPV6_MSG_SOLICIT) { - iov[5].iov_len = 0; + iov[7].iov_len = 0; if (ia_na_len == 0) - iov[7].iov_len = 0; + iov[9].iov_len = 0; } if (na_mode == IA_MODE_NONE) - iov[7].iov_len = 0; + iov[9].iov_len = 0; if (!(client_options & DHCPV6_ACCEPT_RECONFIGURE)) - iov[5].iov_len = 0; + iov[7].iov_len = 0; if (!(client_options & DHCPV6_CLIENT_FQDN)) - iov[6].iov_len = 0; + iov[8].iov_len = 0; struct sockaddr_in6 srv = {AF_INET6, htons(DHCPV6_SERVER_PORT), 0, ALL_DHCPV6_RELAYS, ifindex}; diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 9334c7a..1e8e2bc 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -76,7 +76,7 @@ int main(_unused int argc, char* const argv[]) int c; unsigned int client_options = DHCPV6_CLIENT_FQDN | DHCPV6_ACCEPT_RECONFIGURE; - while ((c = getopt(argc, argv, "S::N:P:FB:c:i:r:Rs:kt:hedp:fa")) != -1) { + while ((c = getopt(argc, argv, "S::N:V:P:FB:c:i:r:Rs:kt:hedp:fa")) != -1) { switch (c) { case 'S': allow_slaac_only = (optarg) ? atoi(optarg) : -1; @@ -95,6 +95,14 @@ int main(_unused int argc, char* const argv[]) } break; + case 'V': + l = script_unhexlify(buf, sizeof(buf), optarg); + if (!l) + help=true; + + odhcp6c_add_state(STATE_VENDORCLASS, buf, l); + + break; case 'P': if (allow_slaac_only >= 0 && allow_slaac_only < 10) allow_slaac_only = 10; @@ -414,6 +422,7 @@ static int usage(void) " -N Mode for requesting addresses [try|force|none]\n" " -P Request IPv6-Prefix (0 = auto)\n" " -F Force IPv6-Prefix\n" + " -V Set vendor-class option. string length must be a multiple of 2\n" #ifdef EXT_BFD_PING " -B Enable BFD ping check\n" #endif diff --git a/src/odhcp6c.h b/src/odhcp6c.h index 024ebea..4ccbcdd 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -43,6 +43,7 @@ enum dhcvp6_opt { DHCPV6_OPT_AUTH = 11, DHCPV6_OPT_STATUS = 13, DHCPV6_OPT_RAPID_COMMIT = 14, + DHCPV6_OPT_VENDOR_CLASS = 16, DHCPV6_OPT_RECONF_MESSAGE = 19, DHCPV6_OPT_RECONF_ACCEPT = 20, DHCPV6_OPT_DNS_SERVERS = 23, @@ -209,6 +210,7 @@ enum odhcp6c_state { STATE_RA_PREFIX, STATE_RA_DNS, STATE_AFTR_NAME, + STATE_VENDORCLASS, _STATE_MAX }; -- 2.39.2