X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fdhcpv6-ia.c;h=7e8e53520036ebab024101705838877c958a04df;hp=be6a2452fc88a92d90c3b554f6baf542ecb3a1f1;hb=33858d341fa7eff6e7245a2486fc42aee64c81ff;hpb=bd3ce421748085ef54959a64e39e1f7c1ba4be0e diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index be6a245..7e8e535 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -219,7 +219,7 @@ void dhcpv6_write_statefile(void) return; lockf(fd, F_LOCK, 0); - ftruncate(fd, 0); + if (ftruncate(fd, 0) < 0) {} FILE *fp = fdopen(fd, "w"); if (!fp) { @@ -254,11 +254,18 @@ void dhcpv6_write_statefile(void) struct in6_addr addr; struct odhcpd_ipaddr *addrs = (c->managed) ? c->managed : iface->ia_addr; size_t addrlen = (c->managed) ? (size_t)c->managed_size : iface->ia_addr_len; + size_t m = 0; + + for (size_t i = 0; i < addrlen; ++i) + if (addrs[i].preferred > addrs[m].preferred || + (addrs[i].preferred == addrs[m].preferred && + memcmp(&addrs[i].addr, &addrs[m].addr, 16) > 0)) + m = i; for (size_t i = 0; i < addrlen; ++i) { - if (addrs[i].prefix > 96) - continue; - if (c->valid_until <= now) + if (addrs[i].prefix > 96 || c->valid_until <= now || + (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && + addrs[i].prefix == 64)) continue; addr = addrs[i].addr; @@ -419,8 +426,6 @@ static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new) else n->valid += now; - n->has_class = false; - n->class = 0; n->dprefix = 0; ++c->managed_size; @@ -524,23 +529,6 @@ static bool assign_pd(struct interface *iface, struct dhcpv6_assignment *assign) static bool assign_na(struct interface *iface, struct dhcpv6_assignment *assign) { - bool match = false; - for (size_t i = 0; i < iface->ia_addr_len; ++i) { - if (!iface->ia_addr[i].has_class) { - match = true; - continue; - } else if (assign->classes_cnt) { - for (size_t j = 0; j < assign->classes_cnt; ++j) - if (assign->classes[j] == iface->ia_addr[i].class) - match = true; - } else if (assign->all_class) { - match = true; - } - } - - if (!match) - return false; - // Seed RNG with checksum of DUID uint32_t seed = 0; for (size_t i = 0; i < assign->clid_len; ++i) @@ -608,7 +596,10 @@ static void update(struct interface *iface) } struct dhcpv6_assignment *border = list_last_entry(&iface->ia_assignments, struct dhcpv6_assignment, head); - border->assigned = 1 << (64 - minprefix); + if (minprefix > 32 && minprefix <= 64) + border->assigned = 1U << (64 - minprefix); + else + border->assigned = 0; bool change = len != (int)iface->ia_addr_len; for (int i = 0; !change && i < len; ++i) @@ -731,44 +722,27 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->ia_addr; size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->ia_addr_len; + size_t m = 0; - for (size_t i = 0; i < addrlen; ++i) { - bool match = true; - if (addrs[i].has_class) { - match = false; - if (a->classes_cnt) { - for (size_t j = 0; j < a->classes_cnt; ++j) - if (a->classes[j] == addrs[i].class) - match = true; - } else if (a->all_class) { - match = true; - } - } + for (size_t i = 0; i < addrlen; ++i) + if (addrs[i].preferred > addrs[m].preferred || + (addrs[i].preferred == addrs[m].preferred && + memcmp(&addrs[i].addr, &addrs[m].addr, 16) > 0)) + m = i; - if (!match) - continue; - - uint32_t prefix_pref = addrs[i].preferred - now; - uint32_t prefix_valid = addrs[i].valid - now; + for (size_t i = 0; i < addrlen; ++i) { + uint32_t prefix_pref = addrs[i].preferred; + uint32_t prefix_valid = addrs[i].valid; if (addrs[i].prefix > 96 || addrs[i].preferred <= (uint32_t)now) continue; - if (prefix_pref > 86400) - prefix_pref = 86400; + if (prefix_pref != UINT32_MAX) + prefix_pref -= now; - if (prefix_valid > 86400) - prefix_valid = 86400; - -#ifdef DHCPV6_OPT_PREFIX_CLASS - struct { - uint16_t code; - uint16_t length; - uint16_t class; - } pclass = {htons(DHCPV6_OPT_PREFIX_CLASS), - htons(2), htons(iface->ia_addr[i].class)}; -#endif + if (prefix_valid != UINT32_MAX) + prefix_valid -= now; if (a->length < 128) { struct dhcpv6_ia_prefix p = { @@ -783,21 +757,11 @@ static size_t append_reply(uint8_t *buf, size_t buflen, uint16_t status, size_t entrlen = sizeof(p) - 4; -#ifdef DHCPV6_OPT_PREFIX_CLASS - if (iface->ia_addr[i].has_class) { - entrlen += sizeof(pclass); - p.len = htons(entrlen); - } -#endif - if (datalen + entrlen + 4 > buflen || (a->assigned == 0 && a->managed_size == 0)) continue; memcpy(buf + datalen, &p, sizeof(p)); -#ifdef DHCPV6_OPT_PREFIX_CLASS - memcpy(buf + datalen + sizeof(p), &pclass, sizeof(pclass)); -#endif datalen += entrlen + 4; } else { struct dhcpv6_ia_addr n = { @@ -810,20 +774,14 @@ 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; -#ifdef DHCPV6_OPT_PREFIX_CLASS - if (iface->ia_addr[i].has_class) { - entrlen += sizeof(pclass); - n.len = htons(entrlen); - } -#endif + if (iface->managed < RELAYD_MANAGED_NO_AFLAG && i != m && + addrs[i].prefix == 64) + continue; 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 + 4; } @@ -977,25 +935,28 @@ static void dhcpv6_log(uint8_t msgtype, struct interface *iface, time_t now, break; } - struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->ia_addr; - size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->ia_addr_len; char leasebuf[256] = ""; - size_t lbsize = 0; - char addrbuf[INET6_ADDRSTRLEN]; - for (size_t i = 0; i < addrlen; ++i) { - if (addrs[i].prefix > 96 || addrs[i].preferred <= now) - continue; + if (a) { + struct odhcpd_ipaddr *addrs = (a->managed) ? a->managed : iface->ia_addr; + size_t addrlen = (a->managed) ? (size_t)a->managed_size : iface->ia_addr_len; + size_t lbsize = 0; + char addrbuf[INET6_ADDRSTRLEN]; - struct in6_addr addr = addrs[i].addr; - int prefix = a->managed ? addrs[i].prefix : a->length; - if (prefix == 128) - addr.s6_addr32[3] = htonl(a->assigned); - else - addr.s6_addr32[1] |= htonl(a->assigned); + for (size_t i = 0; i < addrlen; ++i) { + if (addrs[i].prefix > 96 || addrs[i].preferred <= (uint32_t)now) + continue; + + struct in6_addr addr = addrs[i].addr; + int prefix = a->managed ? addrs[i].prefix : a->length; + if (prefix == 128) + addr.s6_addr32[3] = htonl(a->assigned); + else + addr.s6_addr32[1] |= htonl(a->assigned); - inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf)); - lbsize += snprintf(leasebuf + lbsize, sizeof(leasebuf) - lbsize, "%s/%d ", addrbuf, prefix); + inet_ntop(AF_INET6, &addr, addrbuf, sizeof(addrbuf)); + lbsize += snprintf(leasebuf + lbsize, sizeof(leasebuf) - lbsize, "%s/%d ", addrbuf, prefix); + } } syslog(LOG_WARNING, "DHCPV6 %s %s from %s on %s: %s %s", type, (is_pd) ? "IA_PD" : "IA_NA", @@ -1018,7 +979,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, uint8_t *clid_data = NULL, clid_len = 0, mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; char hostname[256]; size_t hostname_len = 0; - bool class_oro = false; bool notonlink = false; char duidbuf[261]; @@ -1041,14 +1001,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (dn_expand(&fqdn_buf[1], &fqdn_buf[olen], &fqdn_buf[1], hostname, sizeof(hostname)) > 0) hostname_len = strcspn(hostname, "."); - } else if (otype == DHCPV6_OPT_ORO) { -#ifdef DHCPV6_OPT_PREFIX_CLASS - for (size_t i = 0; i + 1 < olen; i += 2) { - if (odata[i] == (DHCPV6_OPT_PREFIX_CLASS >> 8) && - odata[i + 1] == (DHCPV6_OPT_PREFIX_CLASS & 0xff)) - class_oro = true; - } -#endif } else if (otype == DHCPV6_OPT_RECONF_ACCEPT) { accept_reconf = true; } @@ -1072,10 +1024,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, uint8_t reqlen = (is_pd) ? 62 : 128; uint32_t reqhint = 0; - const uint8_t classes_max = 32; - uint8_t classes_cnt = 0; - uint16_t classes[classes_max]; - // Parse request hint for IA-PD if (is_pd) { uint8_t *sdata; @@ -1091,20 +1039,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, if (reqlen > 32 && reqlen <= 64) reqhint &= (1U << (64 - reqlen)) - 1; } - -#ifdef DHCPV6_OPT_PREFIX_CLASS - uint8_t *xdata; - uint16_t xtype, xlen; - dhcpv6_for_each_option(&p[1], sdata + slen, xtype, xlen, xdata) { - if (xtype != DHCPV6_OPT_PREFIX_CLASS || xlen != 2) - continue; - - if (classes_cnt >= classes_max) - continue; - - classes[classes_cnt++] = (uint16_t)xdata[0] << 8 | (uint16_t)xdata[1]; - } -#endif } if (reqlen > 64) @@ -1117,20 +1051,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, continue; ia_addr_present = true; -#ifdef DHCPV6_OPT_PREFIX_CLASS - uint8_t *xdata; - uint16_t xtype, xlen; - struct dhcpv6_ia_addr *p = (struct dhcpv6_ia_addr*)&sdata[-4]; - dhcpv6_for_each_option(&p[1], sdata + slen, xtype, xlen, xdata) { - if (xtype != DHCPV6_OPT_PREFIX_CLASS || xlen != 2) - continue; - - if (classes_cnt >= classes_max) - continue; - - classes[classes_cnt++] = (uint16_t)xdata[0] << 8 | (uint16_t)xdata[1]; - } -#endif } } @@ -1152,11 +1072,6 @@ ssize_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; } } @@ -1176,13 +1091,6 @@ ssize_t dhcpv6_handle_ia(uint8_t *buf, size_t buflen, struct interface *iface, 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));