summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2018-04-17 11:36:32 +0100
committerRoy Marples <roy@marples.name>2018-04-17 11:36:32 +0100
commit86214d2958b9fccbf4e99c73c937fc7e1498f29f (patch)
tree6003e89f52c8b4346cafebb79eedf08a75c657b9
parentcd3ab837c5449d6638eae9bd686dee513a47b677 (diff)
downloaddhcpcd-86214d2958b9fccbf4e99c73c937fc7e1498f29f.tar.xz
DHCPv6: Transpose DHCP userclass option into DHCPv6
-rw-r--r--src/dhcp6.c46
-rw-r--r--src/dhcp6.h1
2 files changed, 47 insertions, 0 deletions
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 89f71d79..e03b156c 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -194,6 +194,48 @@ dhcp6_printoptions(const struct dhcpcd_ctx *ctx,
}
static size_t
+dhcp6_makeuser(void *data, const struct interface *ifp)
+{
+ const struct if_options *ifo = ifp->options;
+ struct dhcp6_option o;
+ uint8_t *p;
+ const uint8_t *up, *ue;
+ uint16_t ulen, unlen;
+ size_t olen;
+
+ /* Convert the DHCPv4 user class option to DHCPv6 */
+ up = ifo->userclass;
+ ulen = *up++;
+ if (ulen == 0)
+ return 0;
+
+ p = data;
+ olen = 0;
+ if (p != NULL)
+ p += sizeof(o);
+
+ ue = up + ulen;
+ for (; up < ue; up += ulen) {
+ ulen = *up++;
+ olen += sizeof(ulen) + ulen;
+ if (data == NULL)
+ continue;
+ unlen = htons(ulen);
+ memcpy(p, &unlen, sizeof(unlen));
+ p += sizeof(unlen);
+ memcpy(p, up, ulen);
+ p += ulen;
+ }
+ if (data != NULL) {
+ o.code = htons(D6_OPTION_USER_CLASS);
+ o.len = htons(olen);
+ memcpy(data, &o, sizeof(o));
+ }
+
+ return sizeof(o) + olen;
+}
+
+static size_t
dhcp6_makevendor(void *data, const struct interface *ifp)
{
const struct if_options *ifo;
@@ -677,6 +719,8 @@ dhcp6_makemessage(struct interface *ifp)
len += sizeof(*state->send);
len += sizeof(o) + ifp->ctx->duid_len;
len += sizeof(o) + sizeof(uint16_t); /* elapsed */
+ if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
+ len += dhcp6_makeuser(NULL, ifp);
if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
len += dhcp6_makevendor(NULL, ifp);
@@ -844,6 +888,8 @@ dhcp6_makemessage(struct interface *ifp)
si_len = 0;
COPYIN(D6_OPTION_ELAPSED, &si_len, sizeof(si_len));
+ if (!has_option_mask(ifo->nomask6, D6_OPTION_USER_CLASS))
+ p += dhcp6_makeuser(p, ifp);
if (!has_option_mask(ifo->nomask6, D6_OPTION_VENDOR_CLASS))
p += dhcp6_makevendor(p, ifp);
diff --git a/src/dhcp6.h b/src/dhcp6.h
index 50b7c9e8..f9f8c403 100644
--- a/src/dhcp6.h
+++ b/src/dhcp6.h
@@ -67,6 +67,7 @@
#define D6_OPTION_UNICAST 12
#define D6_OPTION_STATUS_CODE 13
#define D6_OPTION_RAPID_COMMIT 14
+#define D6_OPTION_USER_CLASS 15
#define D6_OPTION_VENDOR_CLASS 16
#define D6_OPTION_VENDOR_OPTS 17
#define D6_OPTION_INTERFACE_ID 18