From 6599680e2d33597f0f11a99e1c3c957b42418568 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Fri, 10 Apr 2015 15:59:00 +0300 Subject: sd-dhcp6: Add support for DHCPv6 NTP Server Option Support NTP server and multicast addresses and NTP server domain names as specified in RFC 5908. --- src/libsystemd-network/dhcp6-lease-internal.h | 7 +++ src/libsystemd-network/dhcp6-protocol.h | 6 ++ src/libsystemd-network/sd-dhcp6-client.c | 7 +++ src/libsystemd-network/sd-dhcp6-lease.c | 81 +++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) (limited to 'src/libsystemd-network') diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 37e7001320..ac7f84366d 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -46,6 +46,11 @@ struct sd_dhcp6_lease { size_t dns_allocated; char **domains; size_t domains_count; + struct in6_addr *ntp; + size_t ntp_count; + size_t ntp_allocated; + char **ntp_fqdn; + size_t ntp_fqdn_count; }; int dhcp6_lease_clear_timers(DHCP6IA *ia); @@ -65,6 +70,8 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid); int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen); + int dhcp6_lease_new(sd_dhcp6_lease **ret); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_lease*, sd_dhcp6_lease_unref); diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h index 3e0f339237..9330f239b5 100644 --- a/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libsystemd-network/dhcp6-protocol.h @@ -133,6 +133,12 @@ enum { /* option codes 144-65535 are unassigned */ }; +enum { + DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, + DHCP6_NTP_SUBOPTION_MC_ADDR = 2, + DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, +}; + enum { DHCP6_STATUS_SUCCESS = 0, DHCP6_STATUS_UNSPEC_FAIL = 1, diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 6eaae1bd9f..986958d8ad 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -768,7 +768,14 @@ static int client_parse_message(sd_dhcp6_client *client, break; + case DHCP6_OPTION_NTP_SERVER: + r = dhcp6_lease_set_ntp(lease, optval, optlen); + if (r < 0) + return r; + + break; } + } if (r == -ENOMSG) diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index ca638009f1..8631aabc40 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -26,6 +26,7 @@ #include "util.h" #include "dhcp6-lease-internal.h" +#include "dhcp6-protocol.h" int dhcp6_lease_clear_timers(DHCP6IA *ia) { assert_return(ia, -EINVAL); @@ -246,6 +247,83 @@ int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains) { return -ENOENT; } +int dhcp6_lease_set_ntp(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen) +{ + int r; + uint16_t subopt; + size_t sublen; + uint8_t *subval; + + assert_return(lease, -EINVAL); + assert_return(optval, -EINVAL); + + 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; + + lease->ntp_fqdn = strv_free(lease->ntp_fqdn); + lease->ntp_fqdn = servers; + lease->ntp_fqdn_count = r; + + break; + } + } + + if (r != -ENOMSG) + return r; + + return 0; +} + +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; +} + sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) { if (lease) assert_se(REFCNT_INC(lease->n_ref) >= 2); @@ -262,6 +340,9 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { lease->domains = strv_free(lease->domains); + free(lease->ntp); + + lease->ntp_fqdn = strv_free(lease->ntp_fqdn); free(lease); } -- cgit v1.2.3-54-g00ecf