summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2015-08-20 11:33:23 +0200
committerSteven Barth <steven@midlink.org>2015-08-20 11:33:23 +0200
commit5b12eeba475a3301c362cf59f138ec7aa60d2dd9 (patch)
treef0e0e4a98f4585e7c2e514e5020e30a9fa17fabd
parent2fd5d19525699f19186daca9b246dd37a0f547a0 (diff)
router/dhcpv6: use link-local addresses for DNS
-rw-r--r--src/dhcpv6.c4
-rw-r--r--src/odhcpd.c27
-rw-r--r--src/odhcpd.h2
-rw-r--r--src/router.c20
4 files changed, 21 insertions, 32 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c
index c62a08f..9f91162 100644
--- a/src/dhcpv6.c
+++ b/src/dhcpv6.c
@@ -228,7 +228,7 @@ static void handle_client_request(void *addr, void *data, size_t len,
size_t dns_cnt = iface->dns_cnt;
if ((dns_cnt == 0) &&
- odhcpd_get_preferred_interface_address(iface->ifindex, &dns_addr)) {
+ !odhcpd_get_linklocal_interface_address(iface->ifindex, &dns_addr)) {
dns_addr_ptr = &dns_addr;
dns_cnt = 1;
}
@@ -460,7 +460,7 @@ static void relay_server_response(uint8_t *data, size_t len)
size_t rewrite_cnt = iface->dns_cnt;
if (rewrite_cnt == 0) {
- if (odhcpd_get_preferred_interface_address(iface->ifindex, &addr) < 1)
+ if (odhcpd_get_linklocal_interface_address(iface->ifindex, &addr))
return; // Unable to get interface address
rewrite = &addr;
diff --git a/src/odhcpd.c b/src/odhcpd.c
index 5774a4f..9c7f27c 100644
--- a/src/odhcpd.c
+++ b/src/odhcpd.c
@@ -254,24 +254,21 @@ ssize_t odhcpd_get_interface_addresses(int ifindex,
return ret;
}
-int odhcpd_get_preferred_interface_address(int ifindex, struct in6_addr *addr)
+int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr)
{
- struct odhcpd_ipaddr ipaddrs[8];
- ssize_t ip_cnt = odhcpd_get_interface_addresses(ifindex, ipaddrs, ARRAY_SIZE(ipaddrs));
- uint32_t preferred = 0;
- int ret = 0;
-
- for (ssize_t i = 0; i < ip_cnt; i++) {
- struct odhcpd_ipaddr *ipaddr = &ipaddrs[i];
-
- if (ipaddr->preferred > preferred || !preferred) {
- preferred = ipaddr->preferred;
- *addr = ipaddr->addr;
- ret = 1;
+ int status = -1;
+ struct sockaddr_in6 addr = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, ifindex};
+ socklen_t alen = sizeof(addr);
+ int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+
+ if (!connect(sock, (struct sockaddr*)&addr, sizeof(addr)) &&
+ !getsockname(sock, (struct sockaddr*)&addr, &alen)) {
+ *lladdr = addr.sin6_addr;
+ status = 0;
}
- }
- return ret;
+ close(sock);
+ return status;
}
void odhcpd_setup_route(const struct in6_addr *addr, int prefixlen,
diff --git a/src/odhcpd.h b/src/odhcpd.h
index ab24674..81f4bee 100644
--- a/src/odhcpd.h
+++ b/src/odhcpd.h
@@ -185,7 +185,7 @@ ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest,
const struct interface *iface);
ssize_t odhcpd_get_interface_addresses(int ifindex,
struct odhcpd_ipaddr *addrs, size_t cnt);
-int odhcpd_get_preferred_interface_address(int ifindex, struct in6_addr *addr);
+int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr);
struct interface* odhcpd_get_interface_by_name(const char *name);
int odhcpd_get_interface_config(const char *ifname, const char *what);
int odhcpd_get_mac(const struct interface *iface, uint8_t mac[6]);
diff --git a/src/router.c b/src/router.c
index 1ae8d1a..853b9e8 100644
--- a/src/router.c
+++ b/src/router.c
@@ -264,10 +264,11 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
// Construct Prefix Information options
size_t cnt = 0;
- struct in6_addr dns_pref = IN6ADDR_ANY_INIT, *dns_addr = &dns_pref;
- uint32_t dns_time = 0;
+ struct in6_addr dns_pref, *dns_addr = &dns_pref;
size_t dns_cnt = 1;
+ odhcpd_get_linklocal_interface_address(iface->ifindex, &dns_pref);
+
for (ssize_t i = 0; i < ipcnt; ++i) {
struct odhcpd_ipaddr *addr = &addrs[i];
if (addr->prefix > 96 || addr->valid <= (uint32_t)now)
@@ -316,12 +317,6 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
p->nd_opt_pi_preferred_time = htonl(TIME_LEFT(addr->preferred, now));
else if (addr->valid - now < 7200)
p->nd_opt_pi_valid_time = 0;
-
-
- if (TIME_LEFT(addr->preferred, now) > dns_time) {
- dns_time = TIME_LEFT(addr->preferred, now);
- dns_pref = addr->addr;
- }
}
if (!iface->default_router && ntohs(adv.h.nd_ra_router_lifetime) == 1) {
@@ -334,7 +329,6 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
if (iface->dns_cnt > 0) {
dns_addr = iface->dns;
dns_cnt = iface->dns_cnt;
- dns_time = 0;
}
if (!dns_addr || IN6_IS_ADDR_UNSPECIFIED(dns_addr))
@@ -346,7 +340,7 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
uint8_t pad;
uint8_t pad2;
uint32_t lifetime;
- } dns = {ND_OPT_RECURSIVE_DNS, (1 + (2 * dns_cnt)), 0, 0, htonl(dns_time)};
+ } dns = {ND_OPT_RECURSIVE_DNS, (1 + (2 * dns_cnt)), 0, 0, 0};
@@ -440,9 +434,7 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
minival = (maxival * 3) / 4;
search->lifetime = htonl(maxvalid / 1000);
-
- if (!dns.lifetime)
- dns.lifetime = search->lifetime;
+ dns.lifetime = search->lifetime;
odhcpd_urandom(&msecs, sizeof(msecs));
msecs = (labs(msecs) % (maxival - minival)) + minival;
@@ -569,7 +561,7 @@ static void forward_router_advertisement(uint8_t *data, size_t len)
size_t rewrite_cnt = iface->dns_cnt;
if (rewrite_cnt == 0) {
- if (odhcpd_get_preferred_interface_address(iface->ifindex, &addr) < 1)
+ if (odhcpd_get_linklocal_interface_address(iface->ifindex, &addr))
continue; // Unable to comply
rewrite = &addr;