Merge pull request #29 from mehlis/rework-dhcpv4_assign
authorSteven Barth <steven@midlink.org>
Thu, 19 Feb 2015 14:56:35 +0000 (15:56 +0100)
committerSteven Barth <steven@midlink.org>
Thu, 19 Feb 2015 14:56:35 +0000 (15:56 +0100)
dhcpv4_assign: rework the assignment logic

src/dhcpv6-ia.c
src/dhcpv6.c
src/odhcpd.c
src/odhcpd.h
src/router.c

index b21b39e..d103ecb 100644 (file)
@@ -810,7 +810,8 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status,
                                        n.addr.s6_addr32[3] = htonl(a->assigned);
                                        size_t entrlen = sizeof(n) - 4;
 
-                                       if (!a->accept_reconf && iface->managed < RELAYD_MANAGED_NO_AFLAG)
+                                       if (!a->accept_reconf && iface->managed < RELAYD_MANAGED_NO_AFLAG &&
+                                                       addrs[i].prefix == 64)
                                                n.preferred = htonl(1);
 
 #ifdef DHCPV6_OPT_PREFIX_CLASS
index 30b4d25..7302d5d 100644 (file)
@@ -224,19 +224,19 @@ static void handle_client_request(void *addr, void *data, size_t len,
        } refresh = {htons(DHCPV6_OPT_INFO_REFRESH), htons(sizeof(uint32_t)),
                        htonl(600)};
 
-       struct odhcpd_ipaddr ipaddr;
-       struct in6_addr *dns_addr = iface->dns;
+       struct in6_addr dns_addr, *dns_addr_ptr = iface->dns;
        size_t dns_cnt = iface->dns_cnt;
 
-       if (dns_cnt == 0 && odhcpd_get_interface_addresses(iface->ifindex, &ipaddr, 1) == 1) {
-               dns_addr = &ipaddr.addr;
+       if ((dns_cnt == 0) &&
+               odhcpd_get_preferred_interface_address(iface->ifindex, &dns_addr)) {
+               dns_addr_ptr = &dns_addr;
                dns_cnt = 1;
        }
 
        struct {
                uint16_t type;
                uint16_t len;
-       } dns = {htons(DHCPV6_OPT_DNS_SERVERS), htons(dns_cnt * sizeof(*dns_addr))};
+       } dns = {htons(DHCPV6_OPT_DNS_SERVERS), htons(dns_cnt * sizeof(*dns_addr_ptr))};
 
 
 
@@ -274,7 +274,7 @@ static void handle_client_request(void *addr, void *data, size_t len,
                [IOV_DEST] = {&dest, (uint8_t*)&dest.clientid_type - (uint8_t*)&dest},
                [IOV_MAXRT] = {&maxrt, sizeof(maxrt)},
                [IOV_DNS] = {&dns, (dns_cnt) ? sizeof(dns) : 0},
-               [IOV_DNS_ADDR] = {dns_addr, dns_cnt * sizeof(*dns_addr)},
+               [IOV_DNS_ADDR] = {dns_addr_ptr, dns_cnt * sizeof(*dns_addr_ptr)},
                [IOV_SEARCH] = {&search, (search_len) ? sizeof(search) : 0},
                [IOV_SEARCH_DOMAIN] = {search_domain, search_len},
                [IOV_PDBUF] = {pdbuf, 0},
@@ -333,7 +333,7 @@ static void handle_client_request(void *addr, void *data, size_t len,
                        if (IN6_IS_ADDR_UNSPECIFIED(&cerid.addr)) {
                                struct odhcpd_ipaddr addrs[32];
                                ssize_t len = odhcpd_get_interface_addresses(0, addrs,
-                                               sizeof(addrs) / sizeof(*addrs));
+                                               ARRAY_SIZE(addrs));
 
                                for (ssize_t i = 0; i < len; ++i)
                                        if (IN6_IS_ADDR_UNSPECIFIED(&cerid.addr)
@@ -455,15 +455,15 @@ static void relay_server_response(uint8_t *data, size_t len)
                if (is_authenticated)
                        return; // Impossible to rewrite
 
-               struct odhcpd_ipaddr ip;
                const struct in6_addr *rewrite = iface->dns;
+               struct in6_addr addr;
                size_t rewrite_cnt = iface->dns_cnt;
 
                if (rewrite_cnt == 0) {
-                       if (odhcpd_get_interface_addresses(iface->ifindex, &ip, 1) < 1)
+                       if (odhcpd_get_preferred_interface_address(iface->ifindex, &addr) < 1)
                                return; // Unable to get interface address
 
-                       rewrite = &ip.addr;
+                       rewrite = &addr;
                        rewrite_cnt = 1;
                }
 
index 0edf63e..3c384e8 100644 (file)
@@ -263,6 +263,25 @@ ssize_t odhcpd_get_interface_addresses(int ifindex,
        return ret;
 }
 
+int odhcpd_get_preferred_interface_address(int ifindex, struct in6_addr *addr)
+{
+       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;
+               }
+       }
+
+       return ret;
+}
 
 struct interface* odhcpd_get_interface_by_index(int ifindex)
 {
index c0e509d..bc837d5 100644 (file)
@@ -186,6 +186,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);
 struct interface* odhcpd_get_interface_by_name(const char *name);
 int odhcpd_get_interface_mtu(const char *ifname);
 int odhcpd_get_mac(const struct interface *iface, uint8_t mac[6]);
index 0b15dac..3d26c58 100644 (file)
@@ -537,7 +537,6 @@ static void forward_router_advertisement(uint8_t *data, size_t len)
        struct sockaddr_in6 all_nodes = {AF_INET6, 0, 0, ALL_IPV6_NODES, 0};
        struct iovec iov = {data, len};
 
-       struct odhcpd_ipaddr addr;
        struct interface *iface;
        list_for_each_entry(iface, &interfaces, head) {
                if (iface->ra != RELAYD_RELAY || iface->master)
@@ -550,13 +549,14 @@ static void forward_router_advertisement(uint8_t *data, size_t len)
                // If we have to rewrite DNS entries
                if (iface->always_rewrite_dns && dns_ptr && dns_count > 0) {
                        const struct in6_addr *rewrite = iface->dns;
+                       struct in6_addr addr;
                        size_t rewrite_cnt = iface->dns_cnt;
 
                        if (rewrite_cnt == 0) {
-                               if (odhcpd_get_interface_addresses(iface->ifindex, &addr, 1) < 1)
+                               if (odhcpd_get_preferred_interface_address(iface->ifindex, &addr) < 1)
                                        continue; // Unable to comply
 
-                               rewrite = &addr.addr;
+                               rewrite = &addr;
                                rewrite_cnt = 1;
                        }