@@ -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{
@@ -1382,6 +1383,19 @@ static bool register_ia_addr_in_lease_db(struct sockaddr_in6 *source,
13821383 memcpy (lease -> duid , clientid_data , clientid_len );
13831384 lease -> length = 128 ;
13841385
1386+ /* Add optional Client FQDN */
1387+ if (clientfqdn_len > 0 && clientfqdn_data ) {
1388+ char * tmp = realloc (lease -> hostname , clientfqdn_len + 1 );
1389+ if (tmp ) {
1390+ lease -> hostname = tmp ;
1391+ memcpy (lease -> hostname , clientfqdn_data , clientfqdn_len );
1392+ lease -> hostname [clientfqdn_len ] = 0 ;
1393+ lease -> hostname_valid = odhcpd_hostname_valid (lease -> hostname );
1394+ }
1395+ }
1396+
1397+
1398+
13851399 /* Try to find matching interface prefix and extract host ID */
13861400 for (size_t i = 0 ; i < iface -> addr6_len ; i ++ ) {
13871401 if (!valid_addr (& iface -> addr6 [i ], now ))
@@ -1530,6 +1544,8 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15301544
15311545 uint8_t * clientid_data = NULL ;
15321546 uint16_t clientid_len = 0 ;
1547+ char clientfqdn_data [256 ];
1548+ size_t clientfqdn_len = 0 ;
15331549 struct dhcpv6_ia_addr * ia_addr = NULL ;
15341550
15351551 if (len < sizeof (* hdr )) {
@@ -1540,6 +1556,7 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15401556 /* RFC9686 §4.2: Client MUST include Client Identifier option */
15411557 /* RFC9686 §4.2: ADDR-REG-INFORM MUST NOT contain Server Identifier */
15421558 /* RFC9686 §4.2: MUST contain exactly one IA Address option */
1559+ /* RFC9686 §4.2: MAY include other options, such as the Client FQDN option */
15431560
15441561 dhcpv6_for_each_option (opts , opts_end , otype , olen , odata ) {
15451562 switch (otype ) {
@@ -1553,6 +1570,16 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15531570 /* RFC9686 §4.2: Server MUST discard messages with Server ID */
15541571 debug ("ADDR-REG-INFORM: message contains Server Identifier, discarding" );
15551572 return ;
1573+ case DHCPV6_OPT_FQDN :
1574+ if (olen >= 2 && olen <= 255 ) {
1575+ uint8_t fqdn_buf [256 ];
1576+ memcpy (fqdn_buf , odata , olen );
1577+ fqdn_buf [olen ++ ] = 0 ;
1578+
1579+ if (dn_expand (& fqdn_buf [1 ], & fqdn_buf [olen ], & fqdn_buf [1 ], clientfqdn_data , sizeof (clientfqdn_data )) > 0 )
1580+ clientfqdn_len = strcspn (clientfqdn_data , "." );
1581+ }
1582+ break ;
15561583 case DHCPV6_OPT_IA_ADDR :
15571584 if (olen == sizeof (struct dhcpv6_ia_addr ) - 4 ) {
15581585 if (ia_addr != NULL ) {
@@ -1594,7 +1621,8 @@ void handle_ia_addr_reg_inform(struct sockaddr_in6 *source,
15941621 debug ("Got ADDR-REG-INFORM for %s on %s" , addrbuf , iface -> name );
15951622
15961623 /* Register address in lease database */
1597- if (!register_ia_addr_in_lease_db (source , clientid_data , clientid_len , ia_addr , iface ))
1624+ if (!register_ia_addr_in_lease_db (source , clientid_data , clientid_len ,
1625+ clientfqdn_data , clientfqdn_len , ia_addr , iface ))
15981626 return ;
15991627
16001628 /* Send ADDR-REG-REPLY response */
0 commit comments