@@ -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 */
13311331static 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