Append user-specified options from --dhcpv6-opt to DHCPv6 reply
messages. Options are parsed from the stored string value at reply
time using dhcpv6_opt_parse(), and skipped with a debug message if
they exceed the available space.
Link: https://bugs.passt.top/show_bug.cgi?id=192
Signed-off-by: Anshu Kumari
---
v2:
- Updated dhcpv6_custom_opts_fill() to parse str at reply time
using dhcpv6_opt_parse() instead of copying cached val/len.
---
dhcpv6.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/dhcpv6.c b/dhcpv6.c
index 1e1dd0d..6b1e90b 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -748,6 +748,49 @@ static size_t dhcpv6_client_fqdn_fill(const struct iov_tail *data,
return offset + sizeof(struct opt_hdr) + opt_len;
}
+/**
+ * dhcpv6_custom_opts_fill() - Append user-specified custom options to reply
+ * @c: Execution context
+ * @buf: Response message buffer
+ * @offset: Current offset in buffer
+ *
+ * Return: updated offset after appending custom options
+ */
+static size_t dhcpv6_custom_opts_fill(const struct ctx *c,
+ char *buf, int offset)
+{
+ int i;
+
+ for (i = 0; i < c->dhcpv6_opts_count; i++) {
+ uint16_t code = c->dhcpv6_opts[i].code;
+ struct opt_hdr *hdr;
+ uint8_t val[255];
+ int vlen;
+
+ vlen = dhcpv6_opt_parse(code, c->dhcpv6_opts[i].str,
+ val, sizeof(val));
+ if (vlen < 0)
+ continue;
+
+ if ((size_t)offset + sizeof(struct opt_hdr) + vlen >
+ OPT_MAX_SIZE) {
+ debug("DHCPv6: custom option %u doesn't fit,"
+ " skipping", code);
+ continue;
+ }
+
+ hdr = (struct opt_hdr *)(buf + offset);
+ hdr->t = htons(code);
+ hdr->l = htons(vlen);
+ offset += sizeof(struct opt_hdr);
+
+ memcpy(buf + offset, val, vlen);
+ offset += vlen;
+ }
+
+ return offset;
+}
+
/**
* dhcpv6() - Check if this is a DHCPv6 message, reply as needed
* @c: Execution context
@@ -886,6 +929,7 @@ int dhcpv6(struct ctx *c, struct iov_tail *data,
sizeof(struct opt_hdr) + ntohs(client_id->l);
n = dhcpv6_dns_fill(c, (char *)&resp, n);
n = dhcpv6_client_fqdn_fill(data, c, (char *)&resp, n);
+ n = dhcpv6_custom_opts_fill(c, (char *)&resp, n);
resp.hdr.xid = mh->xid;
--
2.54.0