2017-11-18 19:09:20 +03:00
/* SPDX-License-Identifier: LGPL-2.1+ */
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
int dhcp6_lease_clear_timers ( DHCP6IA * ia ) {
assert_return ( ia , - EINVAL ) ;
ia - > timeout_t1 = sd_event_source_unref ( ia - > timeout_t1 ) ;
ia - > timeout_t2 = sd_event_source_unref ( ia - > timeout_t2 ) ;
return 0 ;
}
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 ;
dhcp6_lease_clear_timers ( ia ) ;
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 ) {
assert_return ( lease , - EINVAL ) ;
assert_return ( id , - EINVAL ) ;
free ( lease - > serverid ) ;
lease - > serverid = memdup ( id , len ) ;
if ( ! lease - > serverid )
return - EINVAL ;
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 ;
}
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 ) {
int r ;
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
if ( ! optlen )
return 0 ;
r = dhcp6_option_parse_ip6addrs ( optval , optlen , & lease - > dns ,
lease - > dns_count ,
& lease - > dns_allocated ) ;
if ( r < 0 ) {
log_dhcp6_client ( client , " Invalid DNS server option: %s " ,
strerror ( - r ) ) ;
return r ;
}
lease - > dns_count = r ;
return 0 ;
}
int sd_dhcp6_lease_get_dns ( sd_dhcp6_lease * lease , struct in6_addr * * addrs ) {
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 ;
r = dhcp6_option_parse_domainname ( optval , optlen , & domains ) ;
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 ;
uint16_t subopt ;
size_t sublen ;
uint8_t * subval ;
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 ;
lease - > ntp_allocated = 0 ;
2015-04-10 15:59:00 +03:00
while ( ( r = dhcp6_option_parse ( & optval , & optlen , & subopt , & sublen ,
& subval ) ) > = 0 ) {
int s ;
char * * servers ;
switch ( subopt ) {
case DHCP6_NTP_SUBOPTION_SRV_ADDR :
case DHCP6_NTP_SUBOPTION_MC_ADDR :
if ( sublen ! = 16 )
return 0 ;
s = dhcp6_option_parse_ip6addrs ( subval , sublen ,
& lease - > ntp ,
lease - > ntp_count ,
& lease - > ntp_allocated ) ;
if ( s < 0 )
return s ;
lease - > ntp_count = s ;
break ;
case DHCP6_NTP_SUBOPTION_SRV_FQDN :
r = dhcp6_option_parse_domainname ( subval , sublen ,
& servers ) ;
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 ;
}
}
if ( r ! = - ENOMSG )
return r ;
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 ) {
int r ;
assert_return ( lease , - EINVAL ) ;
assert_return ( optval , - EINVAL ) ;
if ( ! optlen )
return 0 ;
if ( lease - > ntp | | lease - > ntp_fqdn ) {
log_dhcp6_client ( client , " NTP information already provided " ) ;
return 0 ;
}
log_dhcp6_client ( client , " Using deprecated SNTP information " ) ;
r = dhcp6_option_parse_ip6addrs ( optval , optlen , & lease - > ntp ,
lease - > ntp_count ,
& lease - > ntp_allocated ) ;
if ( r < 0 ) {
log_dhcp6_client ( client , " Invalid SNTP server option: %s " ,
strerror ( - r ) ) ;
return r ;
}
lease - > ntp_count = r ;
return 0 ;
}
2015-04-10 15:59:00 +03:00
int sd_dhcp6_lease_get_ntp_addrs ( sd_dhcp6_lease * lease ,
struct in6_addr * * addrs ) {
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 ;
}
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 ) ;
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 ;
}