Add SNTP option support
authorSteven Barth <steven@midlink.org>
Wed, 2 Jan 2013 10:37:29 +0000 (11:37 +0100)
committerSteven Barth <steven@midlink.org>
Wed, 2 Jan 2013 10:37:29 +0000 (11:37 +0100)
src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h
src/script.c

index f1122bddabbc44333961736a8480fcffb4dfb853..e93d894935122af9cfbbfc3661eed2bff581015c 100644 (file)
@@ -573,11 +573,13 @@ static int dhcpv6_handle_reply(_unused enum dhcpv6_msg orig,
 
        t1 = t2 = t3 = 86400;
 
-       size_t ia_na_len, dns_len, search_len;
+       size_t ia_na_len, dns_len, search_len, sntp_ip_len, sntp_dns_len;
        uint8_t *ia_na = odhcp6c_get_state(STATE_IA_NA, &ia_na_len);
        uint8_t *ia_end;
        odhcp6c_get_state(STATE_DNS, &dns_len);
        odhcp6c_get_state(STATE_SEARCH, &search_len);
+       odhcp6c_get_state(STATE_SNTP_IP, &sntp_ip_len);
+       odhcp6c_get_state(STATE_SNTP_FQDN, &sntp_dns_len);
 
        // Decrease valid and preferred lifetime of prefixes
        size_t ia_pd_len;
@@ -649,6 +651,20 @@ static int dhcpv6_handle_reply(_unused enum dhcpv6_msg orig,
                        odhcp6c_add_state(STATE_DNS, odata, olen);
                } else if (otype == DHCPV6_OPT_DNS_DOMAIN) {
                        odhcp6c_add_state(STATE_SEARCH, odata, olen);
+               } else if (otype == DHCPV6_OPT_NTP_SERVER) {
+                       uint16_t stype, slen;
+                       uint8_t *sdata;
+                       // Test status and bail if error
+                       dhcpv6_for_each_option(odata, odata + olen,
+                                       stype, slen, sdata) {
+                               if (slen == 16 && (stype == NTP_MC_ADDR ||
+                                               stype == NTP_SRV_ADDR))
+                                       odhcp6c_add_state(STATE_SNTP_IP,
+                                                       sdata, slen);
+                               else if (slen > 0 && stype == NTP_SRV_FQDN)
+                                       odhcp6c_add_state(STATE_SNTP_FQDN,
+                                                       sdata, slen);
+                       }
                } else if (otype == DHCPV6_OPT_INFO_REFRESH && olen >= 4) {
                        uint32_t refresh = ntohl(*((uint32_t*)odata));
                        if (refresh < (uint32_t)t1)
@@ -663,6 +679,10 @@ static int dhcpv6_handle_reply(_unused enum dhcpv6_msg orig,
        if (opt) {
                have_update |= odhcp6c_commit_state(STATE_DNS, dns_len);
                have_update |= odhcp6c_commit_state(STATE_SEARCH, search_len);
+               have_update |= odhcp6c_commit_state(STATE_SNTP_IP,
+                               sntp_ip_len);
+               have_update |= odhcp6c_commit_state(STATE_SNTP_FQDN,
+                               sntp_dns_len);
                size_t new_ia_pd_len, new_ia_na_len;
                odhcp6c_get_state(STATE_IA_PD, &new_ia_pd_len);
                odhcp6c_get_state(STATE_IA_NA, &new_ia_na_len);
index 9aaa008881d28067075552256b36b3f006b6a734..f3634d2dd714b9152040e569c6534889d5aa2c17 100644 (file)
@@ -171,6 +171,8 @@ int main(_unused int argc, char* const argv[])
                odhcp6c_clear_state(STATE_SERVER_CAND);
                odhcp6c_clear_state(STATE_IA_PD);
                odhcp6c_clear_state(STATE_IA_PD_LOST);
+               odhcp6c_clear_state(STATE_SNTP_IP);
+               odhcp6c_clear_state(STATE_SNTP_FQDN);
                dhcpv6_set_ia_na_mode(ia_na_mode);
 
                alarm(timeout);
index 2d4fa9065811a7809c7fee188e2f02f453068eca..2b3ce9f2507f08f49a5d3ced4373d8e05ff16884 100644 (file)
@@ -48,6 +48,13 @@ enum dhcvp6_opt {
        DHCPV6_OPT_IA_PREFIX = 26,
        DHCPV6_OPT_INFO_REFRESH = 32,
        DHCPV6_OPT_FQDN = 39,
+       DHCPV6_OPT_NTP_SERVER = 56,
+};
+
+enum dhcpv6_opt_npt {
+       NTP_SRV_ADDR = 1,
+       NTP_MC_ADDR = 2,
+       NTP_SRV_FQDN = 3
 };
 
 enum dhcpv6_msg {
@@ -150,6 +157,8 @@ enum odhcp6c_state {
        STATE_IA_PD,
        STATE_IA_PD_LOST,
        STATE_CUSTOM_OPTS,
+       STATE_SNTP_IP,
+       STATE_SNTP_FQDN,
        _STATE_MAX
 };
 
index 2117aebe1cd4201cdfdf632eb881d143715d07b6..d082ff69fc06b819edc97c1fe6b367fd32424b1d 100644 (file)
@@ -159,10 +159,12 @@ static void prefix_to_env(const char *name, const uint8_t *fqdn, size_t len)
 void script_call(const char *status)
 {
        syslog(LOG_WARNING, "State for %s changed to %s", argv[1], status);
-       size_t dns_len, search_len, custom_len;
+       size_t dns_len, search_len, custom_len, sntp_ip_len, sntp_dns_len;
        struct in6_addr *dns = odhcp6c_get_state(STATE_DNS, &dns_len);
        uint8_t *search = odhcp6c_get_state(STATE_SEARCH, &search_len);
        uint8_t *custom = odhcp6c_get_state(STATE_CUSTOM_OPTS, &custom_len);
+       struct in6_addr *sntp = odhcp6c_get_state(STATE_SNTP_IP, &sntp_ip_len);
+       uint8_t *sntp_dns = odhcp6c_get_state(STATE_SNTP_FQDN, &sntp_dns_len);
 
        size_t prefix_len, lost_pd_len;
        uint8_t *prefix = odhcp6c_get_state(STATE_IA_PD, &prefix_len);
@@ -171,7 +173,9 @@ void script_call(const char *status)
        // Don't set environment before forking, because env is leaky.
        if (fork() == 0) {
                ipv6_to_env("RDNSS", dns, dns_len / sizeof(*dns));
+               ipv6_to_env("SNTP_IP", sntp, sntp_ip_len / sizeof(*sntp));
                fqdn_to_env("DOMAINS", search, search_len);
+               fqdn_to_env("SNTP_FQDN", sntp_dns, sntp_dns_len);
                bin_to_env(custom, custom_len);
                prefix_to_env("PREFIXES", prefix, prefix_len);
                prefix_to_env("PREFIXES_LOST", lost_pd, lost_pd_len);