2020-11-09 07:23:58 +03:00
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2014-06-19 16:39:35 +04:00
/***
2018-06-12 18:15:23 +03:00
Copyright © 2014 - 2015 Intel Corporation . All rights reserved .
2014-06-19 16:39:35 +04:00
* * */
# include <errno.h>
2015-10-27 05:01:06 +03:00
# include "alloc-util.h"
2014-06-19 16:39:35 +04:00
# include "dhcp6-lease-internal.h"
2015-04-10 15:59:00 +03:00
# include "dhcp6-protocol.h"
2015-10-27 05:01:06 +03:00
# include "strv.h"
# include "util.h"
2014-06-19 16:39:35 +04:00
2014-06-25 16:37:58 +04:00
int dhcp6_lease_ia_rebind_expire ( const DHCP6IA * ia , uint32_t * expire ) {
DHCP6Address * addr ;
uint32_t valid = 0 , t ;
assert_return ( ia , - EINVAL ) ;
assert_return ( expire , - EINVAL ) ;
LIST_FOREACH ( addresses , addr , ia - > addresses ) {
2014-10-08 12:00:07 +04:00
t = be32toh ( addr - > iaaddr . lifetime_valid ) ;
2014-06-25 16:37:58 +04:00
if ( valid < t )
valid = t ;
}
2018-01-04 16:11:40 +03:00
t = be32toh ( ia - > ia_na . lifetime_t2 ) ;
2014-06-25 16:37:58 +04:00
if ( t > valid )
return - EINVAL ;
* expire = valid - t ;
return 0 ;
}
2014-06-19 16:39:35 +04:00
DHCP6IA * dhcp6_lease_free_ia ( DHCP6IA * ia ) {
DHCP6Address * address ;
if ( ! ia )
return NULL ;
while ( ia - > addresses ) {
address = ia - > addresses ;
LIST_REMOVE ( addresses , ia - > addresses , address ) ;
free ( address ) ;
}
return NULL ;
}
int dhcp6_lease_set_serverid ( sd_dhcp6_lease * lease , const uint8_t * id ,
size_t len ) {
2018-10-18 21:40:30 +03:00
uint8_t * serverid ;
2014-06-19 16:39:35 +04:00
assert_return ( lease , - EINVAL ) ;
assert_return ( id , - EINVAL ) ;
2018-10-18 21:40:30 +03:00
serverid = memdup ( id , len ) ;
if ( ! serverid )
return - ENOMEM ;
2014-06-19 16:39:35 +04:00
2018-10-18 21:40:30 +03:00
free_and_replace ( lease - > serverid , serverid ) ;
2014-06-19 16:39:35 +04:00
lease - > serverid_len = len ;
return 0 ;
}
int dhcp6_lease_get_serverid ( sd_dhcp6_lease * lease , uint8_t * * id , size_t * len ) {
assert_return ( lease , - EINVAL ) ;
2018-02-15 11:37:44 +03:00
if ( ! lease - > serverid )
return - ENOMSG ;
if ( id )
* id = lease - > serverid ;
if ( len )
* len = lease - > serverid_len ;
2014-06-19 16:39:35 +04:00
return 0 ;
}
int dhcp6_lease_set_preference ( sd_dhcp6_lease * lease , uint8_t preference ) {
assert_return ( lease , - EINVAL ) ;
lease - > preference = preference ;
return 0 ;
}
int dhcp6_lease_get_preference ( sd_dhcp6_lease * lease , uint8_t * preference ) {
assert_return ( preference , - EINVAL ) ;
2014-12-10 17:17:31 +03:00
if ( ! lease )
return - EINVAL ;
2014-06-19 16:39:35 +04:00
* preference = lease - > preference ;
return 0 ;
}
2014-06-25 17:54:30 +04:00
int dhcp6_lease_set_rapid_commit ( sd_dhcp6_lease * lease ) {
assert_return ( lease , - EINVAL ) ;
lease - > rapid_commit = true ;
return 0 ;
}
int dhcp6_lease_get_rapid_commit ( sd_dhcp6_lease * lease , bool * rapid_commit ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( rapid_commit , - EINVAL ) ;
* rapid_commit = lease - > rapid_commit ;
return 0 ;
}
2014-06-19 16:39:35 +04:00
int dhcp6_lease_get_iaid ( sd_dhcp6_lease * lease , be32_t * iaid ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( iaid , - EINVAL ) ;
2018-01-04 16:11:40 +03:00
* iaid = lease - > ia . ia_na . id ;
2014-06-19 16:39:35 +04:00
return 0 ;
}
2018-09-07 23:37:56 +03:00
int dhcp6_lease_get_pd_iaid ( sd_dhcp6_lease * lease , be32_t * iaid ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( iaid , - EINVAL ) ;
* iaid = lease - > pd . ia_pd . id ;
return 0 ;
}
2015-01-20 20:35:56 +03:00
int sd_dhcp6_lease_get_address ( sd_dhcp6_lease * lease , struct in6_addr * addr ,
uint32_t * lifetime_preferred ,
uint32_t * lifetime_valid ) {
2014-06-19 16:39:45 +04:00
assert_return ( lease , - EINVAL ) ;
assert_return ( addr , - EINVAL ) ;
assert_return ( lifetime_preferred , - EINVAL ) ;
assert_return ( lifetime_valid , - EINVAL ) ;
if ( ! lease - > addr_iter )
return - ENOMSG ;
2014-10-08 12:00:07 +04:00
memcpy ( addr , & lease - > addr_iter - > iaaddr . address ,
sizeof ( struct in6_addr ) ) ;
* lifetime_preferred =
be32toh ( lease - > addr_iter - > iaaddr . lifetime_preferred ) ;
* lifetime_valid = be32toh ( lease - > addr_iter - > iaaddr . lifetime_valid ) ;
2014-06-19 16:39:45 +04:00
lease - > addr_iter = lease - > addr_iter - > addresses_next ;
return 0 ;
}
2015-01-20 20:35:56 +03:00
void sd_dhcp6_lease_reset_address_iter ( sd_dhcp6_lease * lease ) {
if ( lease )
lease - > addr_iter = lease - > ia . addresses ;
2014-06-19 16:39:45 +04:00
}
2018-01-04 16:11:54 +03:00
int sd_dhcp6_lease_get_pd ( sd_dhcp6_lease * lease , struct in6_addr * prefix ,
uint8_t * prefix_len ,
uint32_t * lifetime_preferred ,
uint32_t * lifetime_valid ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( prefix , - EINVAL ) ;
assert_return ( prefix_len , - EINVAL ) ;
assert_return ( lifetime_preferred , - EINVAL ) ;
assert_return ( lifetime_valid , - EINVAL ) ;
if ( ! lease - > prefix_iter )
return - ENOMSG ;
memcpy ( prefix , & lease - > prefix_iter - > iapdprefix . address ,
sizeof ( struct in6_addr ) ) ;
* prefix_len = lease - > prefix_iter - > iapdprefix . prefixlen ;
* lifetime_preferred =
be32toh ( lease - > prefix_iter - > iapdprefix . lifetime_preferred ) ;
* lifetime_valid =
be32toh ( lease - > prefix_iter - > iapdprefix . lifetime_valid ) ;
lease - > prefix_iter = lease - > prefix_iter - > addresses_next ;
return 0 ;
}
void sd_dhcp6_lease_reset_pd_prefix_iter ( sd_dhcp6_lease * lease ) {
if ( lease )
lease - > prefix_iter = lease - > pd . addresses ;
}
2015-04-02 10:50:16 +03:00
int dhcp6_lease_set_dns ( sd_dhcp6_lease * lease , uint8_t * optval , size_t optlen ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
2021-09-23 19:24:52 +03:00
if ( optlen = = 0 )
2015-04-02 10:50:16 +03:00
return 0 ;
2021-09-23 19:24:52 +03:00
return dhcp6_option_parse_addresses ( optval , optlen , & lease - > dns , & lease - > dns_count ) ;
2015-04-02 10:50:16 +03:00
}
2020-05-24 22:51:39 +03:00
int sd_dhcp6_lease_get_dns ( sd_dhcp6_lease * lease , const struct in6_addr * * addrs ) {
2015-04-02 10:50:16 +03:00
assert_return ( lease , - EINVAL ) ;
assert_return ( addrs , - EINVAL ) ;
if ( lease - > dns_count ) {
* addrs = lease - > dns ;
return lease - > dns_count ;
}
return - ENOENT ;
}
2015-04-02 15:34:12 +03:00
int dhcp6_lease_set_domains ( sd_dhcp6_lease * lease , uint8_t * optval ,
size_t optlen ) {
int r ;
char * * domains ;
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
if ( ! optlen )
return 0 ;
2020-07-28 08:48:11 +03:00
r = dhcp6_option_parse_domainname_list ( optval , optlen , & domains ) ;
2015-04-02 15:34:12 +03:00
if ( r < 0 )
return 0 ;
2018-05-09 18:34:46 +03:00
strv_free_and_replace ( lease - > domains , domains ) ;
2015-04-02 15:34:12 +03:00
lease - > domains_count = r ;
return r ;
}
int sd_dhcp6_lease_get_domains ( sd_dhcp6_lease * lease , char * * * domains ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( domains , - EINVAL ) ;
if ( lease - > domains_count ) {
* domains = lease - > domains ;
return lease - > domains_count ;
}
return - ENOENT ;
}
2015-08-27 18:48:24 +03:00
int dhcp6_lease_set_ntp ( sd_dhcp6_lease * lease , uint8_t * optval , size_t optlen ) {
2015-04-10 15:59:00 +03:00
int r ;
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
2016-01-20 03:50:17 +03:00
lease - > ntp = mfree ( lease - > ntp ) ;
2015-04-10 16:17:22 +03:00
lease - > ntp_count = 0 ;
2021-09-23 08:58:28 +03:00
for ( size_t offset = 0 ; offset < optlen ; ) {
const uint8_t * subval ;
size_t sublen ;
uint16_t subopt ;
r = dhcp6_option_parse ( optval , optlen , & offset , & subopt , & sublen , & subval ) ;
if ( r < 0 )
return r ;
2015-04-10 15:59:00 +03:00
switch ( subopt ) {
case DHCP6_NTP_SUBOPTION_SRV_ADDR :
case DHCP6_NTP_SUBOPTION_MC_ADDR :
if ( sublen ! = 16 )
return 0 ;
2021-09-23 19:24:52 +03:00
r = dhcp6_option_parse_addresses ( subval , sublen , & lease - > ntp , & lease - > ntp_count ) ;
2021-09-23 08:58:28 +03:00
if ( r < 0 )
return r ;
2015-04-10 15:59:00 +03:00
break ;
2021-09-23 08:58:28 +03:00
case DHCP6_NTP_SUBOPTION_SRV_FQDN : {
char * * servers ;
r = dhcp6_option_parse_domainname_list ( subval , sublen , & servers ) ;
2015-04-10 15:59:00 +03:00
if ( r < 0 )
return 0 ;
2018-05-09 18:34:46 +03:00
strv_free_and_replace ( lease - > ntp_fqdn , servers ) ;
2015-04-10 15:59:00 +03:00
lease - > ntp_fqdn_count = r ;
break ;
2021-09-23 08:58:28 +03:00
} }
2015-04-10 15:59:00 +03:00
}
return 0 ;
}
2015-04-10 16:17:22 +03:00
int dhcp6_lease_set_sntp ( sd_dhcp6_lease * lease , uint8_t * optval , size_t optlen ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
2021-09-23 19:24:52 +03:00
if ( optlen = = 0 )
2015-04-10 16:17:22 +03:00
return 0 ;
2021-02-24 12:18:35 +03:00
if ( lease - > ntp | | lease - > ntp_fqdn )
return - EEXIST ;
2015-04-10 16:17:22 +03:00
2021-02-24 12:18:35 +03:00
/* Using deprecated SNTP information */
2015-04-10 16:17:22 +03:00
2021-09-23 19:24:52 +03:00
return dhcp6_option_parse_addresses ( optval , optlen , & lease - > ntp , & lease - > ntp_count ) ;
2015-04-10 16:17:22 +03:00
}
2015-04-10 15:59:00 +03:00
int sd_dhcp6_lease_get_ntp_addrs ( sd_dhcp6_lease * lease ,
2020-05-24 22:51:39 +03:00
const struct in6_addr * * addrs ) {
2015-04-10 15:59:00 +03:00
assert_return ( lease , - EINVAL ) ;
assert_return ( addrs , - EINVAL ) ;
if ( lease - > ntp_count ) {
* addrs = lease - > ntp ;
return lease - > ntp_count ;
}
return - ENOENT ;
}
int sd_dhcp6_lease_get_ntp_fqdn ( sd_dhcp6_lease * lease , char * * * ntp_fqdn ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( ntp_fqdn , - EINVAL ) ;
if ( lease - > ntp_fqdn_count ) {
* ntp_fqdn = lease - > ntp_fqdn ;
return lease - > ntp_fqdn_count ;
}
return - ENOENT ;
}
2020-07-28 08:48:11 +03:00
int dhcp6_lease_set_fqdn ( sd_dhcp6_lease * lease , const uint8_t * optval ,
size_t optlen ) {
int r ;
char * fqdn ;
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
if ( optlen < 2 )
return - ENODATA ;
/* Ignore the flags field, it doesn't carry any useful
information for clients . */
r = dhcp6_option_parse_domainname ( optval + 1 , optlen - 1 , & fqdn ) ;
if ( r < 0 )
return r ;
return free_and_replace ( lease - > fqdn , fqdn ) ;
}
int sd_dhcp6_lease_get_fqdn ( sd_dhcp6_lease * lease , const char * * fqdn ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( fqdn , - EINVAL ) ;
if ( lease - > fqdn ) {
* fqdn = lease - > fqdn ;
return 0 ;
}
return - ENOENT ;
}
2018-08-27 08:01:46 +03:00
static sd_dhcp6_lease * dhcp6_lease_free ( sd_dhcp6_lease * lease ) {
assert ( lease ) ;
2015-04-10 15:59:00 +03:00
2015-08-26 22:05:53 +03:00
free ( lease - > serverid ) ;
dhcp6_lease_free_ia ( & lease - > ia ) ;
2018-01-04 16:11:47 +03:00
dhcp6_lease_free_ia ( & lease - > pd ) ;
2015-08-26 22:05:53 +03:00
free ( lease - > dns ) ;
2020-07-28 08:48:11 +03:00
free ( lease - > fqdn ) ;
2015-08-26 22:05:53 +03:00
lease - > domains = strv_free ( lease - > domains ) ;
free ( lease - > ntp ) ;
lease - > ntp_fqdn = strv_free ( lease - > ntp_fqdn ) ;
2016-10-17 01:28:30 +03:00
return mfree ( lease ) ;
2014-06-19 16:39:35 +04:00
}
2018-08-27 08:01:46 +03:00
DEFINE_TRIVIAL_REF_UNREF_FUNC ( sd_dhcp6_lease , sd_dhcp6_lease , dhcp6_lease_free ) ;
2014-06-19 16:39:35 +04:00
int dhcp6_lease_new ( sd_dhcp6_lease * * ret ) {
sd_dhcp6_lease * lease ;
lease = new0 ( sd_dhcp6_lease , 1 ) ;
if ( ! lease )
return - ENOMEM ;
2015-08-26 22:05:53 +03:00
lease - > n_ref = 1 ;
2014-06-19 16:39:35 +04:00
LIST_HEAD_INIT ( lease - > ia . addresses ) ;
* ret = lease ;
return 0 ;
}