summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2015-04-10 15:59:00 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2015-08-21 11:23:22 +0300
commit6599680e2d33597f0f11a99e1c3c957b42418568 (patch)
tree8ef4124e7079777abbc9b976499a3d8a8da9becf
parent5da1b97f3c3d15521f2dcfbc18eccd6580122ebc (diff)
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.
-rw-r--r--src/libsystemd-network/dhcp6-lease-internal.h7
-rw-r--r--src/libsystemd-network/dhcp6-protocol.h6
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c7
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c81
-rw-r--r--src/systemd/sd-dhcp6-lease.h3
5 files changed, 104 insertions, 0 deletions
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
@@ -134,6 +134,12 @@ enum {
};
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,
DHCP6_STATUS_NO_ADDRS_AVAIL = 2,
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);
}
diff --git a/src/systemd/sd-dhcp6-lease.h b/src/systemd/sd-dhcp6-lease.h
index 8fdb48edeb..dc3df3bbf7 100644
--- a/src/systemd/sd-dhcp6-lease.h
+++ b/src/systemd/sd-dhcp6-lease.h
@@ -35,6 +35,9 @@ int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease,
int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, struct in6_addr **addrs);
int sd_dhcp6_lease_get_domains(sd_dhcp6_lease *lease, char ***domains);
+int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease,
+ struct in6_addr **addrs);
+int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn);
sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease);
sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease);