X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=e5a7c0bfff4708b6a7acc3136c315ae76f229dc9;hp=3d9fe831908ac58b0178b71a8d080438b2200fe1;hb=3fcc0814db3773e1295a372ea7a4194e19c62e52;hpb=d02dc222e61e2464bf850a629030c8a8b9b57ee8;ds=sidebyside diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 3d9fe83..e5a7c0b 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -15,7 +15,7 @@ #include "odhcpd.h" #include "dhcpv6.h" #include "dhcpv4.h" -#include "md5.h" +#include "libubox/md5.h" #include #include @@ -63,6 +63,11 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) if (list_empty(&iface->ia_assignments)) { struct dhcpv6_assignment *border = calloc(1, sizeof(*border)); + if (!border) { + syslog(LOG_ERR, "Calloc failed for border on interface %s", iface->ifname); + return -1; + } + border->length = 64; list_add(&border->head, &iface->ia_assignments); } @@ -74,9 +79,20 @@ int setup_dhcpv6_ia_interface(struct interface *iface, bool enable) list_for_each_entry(lease, &leases, head) { // Construct entry struct dhcpv6_assignment *a = calloc(1, sizeof(*a) + lease->duid_len); + if (!a) { + syslog(LOG_ERR, "Calloc failed for static lease assignment on interface %s", + iface->ifname); + return -1; + } + a->clid_len = lease->duid_len; a->length = 128; - a->assigned = lease->hostid; + if (lease->hostid) { + a->assigned = lease->hostid; + } else { + uint32_t i4a = ntohl(lease->ipaddr.s_addr) & 0xff; + a->assigned = ((i4a / 100) << 8) | (((i4a % 100) / 10) << 4) | (i4a % 10); + } odhcpd_urandom(a->key, sizeof(a->key)); memcpy(a->clid_data, lease->duid, a->clid_len); memcpy(a->mac, lease->mac.ether_addr_octet, sizeof(a->mac)); @@ -541,10 +557,6 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, if (a) { uint32_t pref = 3600; uint32_t valid = 3600; - bool have_non_ula = false; - for (size_t i = 0; i < iface->ia_addr_len; ++i) - if ((iface->ia_addr[i].addr.s6_addr[0] & 0xfe) != 0xfc) - have_non_ula = true; for (size_t i = 0; i < iface->ia_addr_len; ++i) { bool match = true; @@ -569,12 +581,6 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, iface->ia_addr[i].preferred <= (uint32_t)now) continue; - // ULA-deprecation compatibility workaround - if ((iface->ia_addr[i].addr.s6_addr[0] & 0xfe) == 0xfc && - a->length == 128 && have_non_ula && - iface->deprecate_ula_if_public_avail) - continue; - if (prefix_pref > 86400) prefix_pref = 86400; @@ -600,7 +606,7 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, .addr = iface->ia_addr[i].addr }; p.addr.s6_addr32[1] |= htonl(a->assigned); - size_t entrlen = sizeof(p); + size_t entrlen = sizeof(p) - 4; #ifdef DHCPV6_OPT_PREFIX_CLASS if (iface->ia_addr[i].has_class) { @@ -609,14 +615,14 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, } #endif - if (datalen + entrlen > buflen || a->assigned == 0) + if (datalen + entrlen + 4 > buflen || a->assigned == 0) continue; memcpy(buf + datalen, &p, sizeof(p)); #ifdef DHCPV6_OPT_PREFIX_CLASS memcpy(buf + datalen + sizeof(p), &pclass, sizeof(pclass)); #endif - datalen += entrlen; + datalen += entrlen + 4; } else { struct dhcpv6_ia_addr n = { .type = htons(DHCPV6_OPT_IA_ADDR), @@ -626,7 +632,7 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, .valid = htonl(prefix_valid) }; n.addr.s6_addr32[3] = htonl(a->assigned); - size_t entrlen = sizeof(n); + size_t entrlen = sizeof(n) - 4; #ifdef DHCPV6_OPT_PREFIX_CLASS if (iface->ia_addr[i].has_class) { @@ -635,14 +641,14 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, } #endif - if (datalen + entrlen > buflen || a->assigned == 0) + if (datalen + entrlen + 4 > buflen || a->assigned == 0) continue; memcpy(buf + datalen, &n, sizeof(n)); #ifdef DHCPV6_OPT_PREFIX_CLASS memcpy(buf + datalen + sizeof(n), &pclass, sizeof(pclass)); #endif - datalen += entrlen; + datalen += entrlen + 4; } // Calculate T1 / T2 based on non-deprecated addresses @@ -882,6 +888,11 @@ size_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, a->peer = *addr; a->reconf_cnt = 0; a->reconf_sent = 0; + a->all_class = class_oro; + a->classes_cnt = classes_cnt; + a->classes = realloc(a->classes, classes_cnt * sizeof(uint16_t)); + if (a->classes) + memcpy(a->classes, classes, classes_cnt * sizeof(uint16_t)); break; } } @@ -893,26 +904,31 @@ size_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (!a && !iface->no_dynamic_dhcp) { // Create new binding a = calloc(1, sizeof(*a) + clid_len); - a->clid_len = clid_len; - a->iaid = ia->iaid; - a->length = reqlen; - a->peer = *addr; - a->assigned = reqhint; - a->all_class = class_oro; - a->classes_cnt = classes_cnt; - a->classes = malloc(classes_cnt * sizeof(uint16_t)); - memcpy(a->classes, classes, classes_cnt * sizeof(uint16_t)); + if (a) { + a->clid_len = clid_len; + a->iaid = ia->iaid; + a->length = reqlen; + a->peer = *addr; + a->assigned = reqhint; + a->all_class = class_oro; + a->classes_cnt = classes_cnt; + if (classes_cnt) { + a->classes = malloc(classes_cnt * sizeof(uint16_t)); + if (a->classes) + memcpy(a->classes, classes, classes_cnt * sizeof(uint16_t)); + } - if (first) - memcpy(a->key, first->key, sizeof(a->key)); - else - odhcpd_urandom(a->key, sizeof(a->key)); - memcpy(a->clid_data, clid_data, clid_len); + if (first) + memcpy(a->key, first->key, sizeof(a->key)); + else + odhcpd_urandom(a->key, sizeof(a->key)); + memcpy(a->clid_data, clid_data, clid_len); - if (is_pd) - while (!(assigned = assign_pd(iface, a)) && ++a->length <= 64); - else - assigned = assign_na(iface, a); + if (is_pd) + while (!(assigned = assign_pd(iface, a)) && ++a->length <= 64); + else + assigned = assign_na(iface, a); + } } if (!assigned || iface->ia_addr_len == 0) { // Set error status @@ -953,8 +969,10 @@ size_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, } else if (assigned && hdr->msg_type == DHCPV6_MSG_REQUEST) { if (hostname_len > 0) { a->hostname = realloc(a->hostname, hostname_len + 1); - memcpy(a->hostname, hostname, hostname_len); - a->hostname[hostname_len] = 0; + if (a->hostname) { + memcpy(a->hostname, hostname, hostname_len); + a->hostname[hostname_len] = 0; + } } a->accept_reconf = accept_reconf; apply_lease(iface, a, true);