Export DHCPv6 server address to env
authorSteven Barth <steven@midlink.org>
Mon, 6 Oct 2014 08:29:43 +0000 (10:29 +0200)
committerSteven Barth <steven@midlink.org>
Mon, 6 Oct 2014 08:29:43 +0000 (10:29 +0200)
src/dhcpv6.c
src/odhcp6c.c
src/odhcp6c.h
src/script.c

index b7fccaca62e78e9a048b8da5151677523ef69dcd..30c9fb2678f16ecd384b697a5c0635b919c7c2e3 100644 (file)
@@ -551,10 +551,12 @@ int dhcpv6_request(enum dhcpv6_msg type)
                                round_start = odhcp6c_get_milli_time()) {
                        uint8_t buf[1536], cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
                        struct iovec iov = {buf, sizeof(buf)};
-                       struct msghdr msg = {NULL, 0, &iov, 1,
+                       struct sockaddr_in6 addr;
+                       struct msghdr msg = {&addr, sizeof(addr), &iov, 1,
                                        cmsg_buf, sizeof(cmsg_buf), 0};
                        struct in6_pktinfo *pktinfo = NULL;
 
+
                        // Check for pending signal
                        if (odhcp6c_signal_process())
                                return -1;
@@ -599,7 +601,7 @@ int dhcpv6_request(enum dhcpv6_msg type)
                                        "%llums", (unsigned long long)elapsed);
 
                        if (retx->handler_reply)
-                               len = retx->handler_reply(type, rc, opt, opt_end);
+                               len = retx->handler_reply(type, rc, opt, opt_end, &addr);
 
                        if (len > 0 && round_end - round_start > 1000)
                                round_end = 1000 + round_start;
@@ -729,7 +731,7 @@ int dhcpv6_poll_reconfigure(void)
 
 
 static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig, const int rc,
-               const void *opt, const void *end)
+               const void *opt, const void *end, _unused const struct sockaddr_in6 *from)
 {
        uint16_t otype, olen;
        uint8_t *odata, msg = DHCPV6_MSG_RENEW;
@@ -739,14 +741,14 @@ static int dhcpv6_handle_reconfigure(_unused enum dhcpv6_msg orig, const int rc,
                                odata[0] == DHCPV6_MSG_INFO_REQ))
                        msg = odata[0];
 
-       dhcpv6_handle_reply(DHCPV6_MSG_UNKNOWN, rc, NULL, NULL);
+       dhcpv6_handle_reply(DHCPV6_MSG_UNKNOWN, rc, NULL, NULL, NULL);
        return msg;
 }
 
 
 // Collect all advertised servers
 static int dhcpv6_handle_advert(enum dhcpv6_msg orig, const int rc,
-               const void *opt, const void *end)
+               const void *opt, const void *end, _unused const struct sockaddr_in6 *from)
 {
        uint16_t olen, otype;
        uint8_t *odata, pref = 0;
@@ -854,18 +856,18 @@ static int dhcpv6_commit_advert(void)
 
 
 static int dhcpv6_handle_rebind_reply(enum dhcpv6_msg orig, const int rc,
-               const void *opt, const void *end)
+               const void *opt, const void *end, const struct sockaddr_in6 *from)
 {
-       dhcpv6_handle_advert(orig, rc, opt, end);
+       dhcpv6_handle_advert(orig, rc, opt, end, from);
        if (dhcpv6_commit_advert() < 0)
                return -1;
 
-       return dhcpv6_handle_reply(orig, rc, opt, end);
+       return dhcpv6_handle_reply(orig, rc, opt, end, from);
 }
 
 
 static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
-               const void *opt, const void *end)
+               const void *opt, const void *end, const struct sockaddr_in6 *from)
 {
        uint8_t *odata;
        uint16_t otype, olen;
@@ -1090,6 +1092,11 @@ static int dhcpv6_handle_reply(enum dhcpv6_msg orig, _unused const int rc,
                        default :
                                break;
                        }
+
+                       if (orig == DHCPV6_MSG_REBIND || orig == DHCPV6_MSG_REQUEST) {
+                               odhcp6c_clear_state(STATE_SERVER_ADDR);
+                               odhcp6c_add_state(STATE_SERVER_ADDR, &from->sin6_addr, 16);
+                       }
                }
        }
        else if (ret > 0) {
index 2357a9a9aa577b7b58819c599c341b4c85e9abc8..c76c81316fc8e917099bfbdc6dad70ce24ffbe00 100644 (file)
@@ -266,6 +266,7 @@ int main(_unused int argc, char* const argv[])
 
        while (!signal_term) { // Main logic
                odhcp6c_clear_state(STATE_SERVER_ID);
+               odhcp6c_clear_state(STATE_SERVER_ADDR);
                odhcp6c_clear_state(STATE_IA_NA);
                odhcp6c_clear_state(STATE_IA_PD);
                odhcp6c_clear_state(STATE_SNTP_IP);
@@ -365,6 +366,7 @@ int main(_unused int argc, char* const argv[])
                                }
 
                                odhcp6c_clear_state(STATE_SERVER_ID); // Remove binding
+                               odhcp6c_clear_state(STATE_SERVER_ADDR);
 
                                size_t ia_pd_len, ia_na_len;
                                odhcp6c_get_state(STATE_IA_PD, &ia_pd_len);
index 59c4a42b973d2b53c142f1e320d720ce5a98f2b4..a4343b19216ec8293388922da74b6eb30da30e3a 100644 (file)
@@ -123,7 +123,7 @@ enum dhcpv6_config {
 };
 
 typedef int(reply_handler)(enum dhcpv6_msg orig, const int rc,
-               const void *opt, const void *end);
+               const void *opt, const void *end, const struct sockaddr_in6 *from);
 
 // retransmission strategy
 struct dhcpv6_retx {
@@ -246,6 +246,7 @@ enum odhcp6c_state {
        STATE_CLIENT_ID,
        STATE_SERVER_ID,
        STATE_SERVER_CAND,
+       STATE_SERVER_ADDR,
        STATE_ORO,
        STATE_DNS,
        STATE_SEARCH,
index d443ede71a229e41ca0da7c0623186bdfa0ae01e..e389cc933640afe364b379b0ffbef15ee62d91de 100644 (file)
@@ -354,7 +354,7 @@ void script_delay_call(const char *status, int timeout)
 void script_call(const char *status)
 {
        size_t dns_len, search_len, custom_len, sntp_ip_len, ntp_ip_len, ntp_dns_len;
-       size_t sip_ip_len, sip_fqdn_len, aftr_name_len, cer_len;
+       size_t sip_ip_len, sip_fqdn_len, aftr_name_len, cer_len, addr_len;
        size_t s46_mapt_len, s46_mape_len, s46_lw_len, passthru_len;
 
        odhcp6c_expire();
@@ -363,6 +363,7 @@ void script_call(const char *status)
                dont_delay = true;
        }
 
+       struct in6_addr *addr = odhcp6c_get_state(STATE_SERVER_ADDR, &addr_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);
@@ -387,6 +388,7 @@ void script_call(const char *status)
 
        // Don't set environment before forking, because env is leaky.
        if (fork() == 0) {
+               ipv6_to_env("SERVER", addr, addr_len / sizeof(*addr));
                ipv6_to_env("RDNSS", dns, dns_len / sizeof(*dns));
                ipv6_to_env("SNTP_IP", sntp, sntp_ip_len / sizeof(*sntp));
                ipv6_to_env("NTP_IP", ntp, ntp_ip_len / sizeof(*ntp));