Skip to content

Commit 8a75343

Browse files
committed
dhcpv6: implement RFC9686
Add support for the Client FQDN option: RFC9686 §4.2: MAY include ... the Client FQDN option Signed-off-by: Paul Donald <newtwen+github@gmail.com> Link: openwrt#353
1 parent 7499b52 commit 8a75343

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

src/dhcpv6-ia.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,7 @@ ssize_t dhcpv6_ia_handle_IAs(uint8_t *buf, size_t buflen, struct interface *ifac
13301330
/* Register or update address registration in the lease database */
13311331
static bool register_ia_addr_in_lease_db(struct sockaddr_in6 *source,
13321332
const uint8_t *clientid_data, uint16_t clientid_len,
1333+
const char *clientfqdn_data, size_t clientfqdn_len,
13331334
const struct dhcpv6_ia_addr *ia_addr,
13341335
struct interface *iface)
13351336
{
@@ -1389,6 +1390,19 @@ static bool register_ia_addr_in_lease_db(struct sockaddr_in6 *source,
13891390
memcpy(lease->duid, clientid_data, clientid_len);
13901391
lease->length = 128;
13911392

1393+
/* Add optional Client FQDN */
1394+
if (clientfqdn_len > 0 && clientfqdn_data) {
1395+
char *tmp = realloc(lease->hostname, clientfqdn_len + 1);
1396+
if (tmp) {
1397+
lease->hostname = tmp;
1398+
memcpy(lease->hostname, clientfqdn_data, clientfqdn_len);
1399+
lease->hostname[clientfqdn_len] = 0;
1400+
lease->hostname_valid = odhcpd_hostname_valid(lease->hostname);
1401+
}
1402+
}
1403+
1404+
1405+
13921406
/* Try to find matching interface prefix and extract host ID */
13931407
for (size_t i = 0; i < iface->addr6_len; i++) {
13941408
if (!valid_addr(&iface->addr6[i], now))
@@ -1543,6 +1557,8 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15431557

15441558
uint8_t *clientid_data = NULL;
15451559
uint16_t clientid_len = 0;
1560+
char clientfqdn_data[256];
1561+
size_t clientfqdn_len = 0;
15461562
struct dhcpv6_ia_addr *ia_addr = NULL;
15471563

15481564
if (len < sizeof(*hdr)) {
@@ -1553,6 +1569,7 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15531569
/* RFC9686 §4.2: Client MUST include Client Identifier option */
15541570
/* RFC9686 §4.2: ADDR-REG-INFORM MUST NOT contain Server Identifier */
15551571
/* RFC9686 §4.2: MUST contain exactly one IA Address option */
1572+
/* RFC9686 §4.2: MAY include other options, such as the Client FQDN option */
15561573

15571574
dhcpv6_for_each_option(opts, opts_end, otype, olen, odata) {
15581575
switch (otype) {
@@ -1566,6 +1583,16 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15661583
/* RFC9686 §4.2: Server MUST discard messages with Server ID */
15671584
notice("ADDR-REG-INFORM: message contains Server Identifier, discarding");
15681585
return;
1586+
case DHCPV6_OPT_FQDN:
1587+
if (olen >= 2 && olen <= 255) {
1588+
uint8_t fqdn_buf[256];
1589+
memcpy(fqdn_buf, odata, olen);
1590+
fqdn_buf[olen++] = 0;
1591+
1592+
if (dn_expand(&fqdn_buf[1], &fqdn_buf[olen], &fqdn_buf[1], clientfqdn_data, sizeof(clientfqdn_data)) > 0)
1593+
clientfqdn_len = strcspn(clientfqdn_data, ".");
1594+
}
1595+
break;
15691596
case DHCPV6_OPT_IA_ADDR:
15701597
if (olen == sizeof(struct dhcpv6_ia_addr) - 4) {
15711598
if (ia_addr != NULL) {
@@ -1607,7 +1634,8 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
16071634
debug("Got ADDR-REG-INFORM for %s on %s", addrbuf, iface->name);
16081635

16091636
/* Register address in lease database */
1610-
if(!register_ia_addr_in_lease_db(source, clientid_data, clientid_len, ia_addr, iface))
1637+
if(!register_ia_addr_in_lease_db(source, clientid_data, clientid_len,
1638+
clientfqdn_data, clientfqdn_len, ia_addr, iface))
16111639
return;
16121640

16131641
/* Send ADDR-REG-REPLY response */

0 commit comments

Comments
 (0)