From d6fe99f6d03873e7a670c9b6f26fa03b219422f5 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Mon, 6 Oct 2014 10:29:43 +0200 Subject: [PATCH] Export DHCPv6 server address to env --- src/dhcpv6.c | 25 ++++++++++++++++--------- src/odhcp6c.c | 2 ++ src/odhcp6c.h | 3 ++- src/script.c | 4 +++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index b7fccac..30c9fb2 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -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) { diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 2357a9a..c76c813 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -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); diff --git a/src/odhcp6c.h b/src/odhcp6c.h index 59c4a42..a4343b1 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -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, diff --git a/src/script.c b/src/script.c index d443ede..e389cc9 100644 --- a/src/script.c +++ b/src/script.c @@ -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)); -- 2.39.5