X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=interface-ip.c;h=ea4c3ddbf989b31c22481caee15b8e2f77c8ec6a;hp=183935e4bbf287845ef4bf6f0e05cc1bf5f4ed6f;hb=7496f70e45964d9e4ac870582c8e4e3ce7c56ad6;hpb=4c08f23dfe3ddeb4949d80d84cc20d8117a54898 diff --git a/interface-ip.c b/interface-ip.c index 183935e..ea4c3dd 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -492,7 +492,6 @@ interface_update_prefix_assignments(struct vlist_tree *tree, } else if (node_old) { if (iface) interface_set_prefix_address(iface, false, old); - free(old->name); free(old); } else if (node_new) { struct device_prefix *prefix = new->prefix; @@ -523,14 +522,16 @@ void interface_ip_set_prefix_assignment(struct device_prefix *prefix, struct interface *iface, uint8_t length) { + struct device_prefix_assignment *assignment; + if (!length || length > 64) { - struct device_prefix_assignment *assignment = vlist_find( - prefix->assignments, &iface, assignment, node); + assignment = vlist_find(prefix->assignments, iface->name, assignment, node); if (assignment) interface_set_prefix_address(iface, false, assignment); } else { - uint8_t length = iface->proto_ip.assignment_length; uint64_t want = 1ULL << (64 - length); + char *name; + if (prefix->avail < want && prefix->avail > 0) { do { want = 1ULL << (64 - ++length); @@ -540,11 +541,11 @@ interface_ip_set_prefix_assignment(struct device_prefix *prefix, if (prefix->avail < want) return; - // Assignment - struct device_prefix_assignment *assignment = calloc(1, sizeof(*assignment)); + assignment = calloc_a(sizeof(*assignment), + &name, strlen(iface->name) + 1); assignment->prefix = prefix; assignment->length = length; - assignment->name = strdup(iface->name); + assignment->name = strcpy(name, iface->name); vlist_add(prefix->assignments, &assignment->node, assignment->name); } @@ -574,9 +575,11 @@ interface_update_prefix(struct vlist_tree *tree, // Update all assignments struct device_prefix_assignment *assignment; struct vlist_tree *assignments = prefix_new->assignments; - vlist_for_each_element(assignments, assignment, node) + vlist_for_each_element(assignments, assignment, node) { + assignment->prefix = prefix_new; assignments->update(assignments, &assignment->node, &assignment->node); + } } else if (node_new) { prefix_new->avail = 1ULL << (64 - prefix_new->length); prefix_new->assignments = calloc(1, sizeof(*prefix_new->assignments)); @@ -589,8 +592,6 @@ interface_update_prefix(struct vlist_tree *tree, interface_ip_set_prefix_assignment(prefix_new, iface, iface->proto_ip.assignment_length); - list_add(&prefix_new->head, &prefixes); - // Set null-route to avoid routing loops system_add_route(NULL, &route); } @@ -607,6 +608,9 @@ interface_update_prefix(struct vlist_tree *tree, } free(prefix_old); } + + if (node_new) + list_add(&prefix_new->head, &prefixes); } void @@ -630,12 +634,18 @@ void interface_ip_set_ula_prefix(const char *prefix) { char buf[INET6_ADDRSTRLEN + 4] = {0}, *saveptr; - strncpy(buf, prefix, sizeof(buf) - 1); + if (prefix) + strncpy(buf, prefix, sizeof(buf) - 1); char *prefixaddr = strtok_r(buf, "/", &saveptr); struct in6_addr addr; - if (!prefixaddr || inet_pton(AF_INET6, prefixaddr, &addr) < 1) + if (!prefixaddr || inet_pton(AF_INET6, prefixaddr, &addr) < 1) { + if (ula_prefix) { + interface_update_prefix(NULL, NULL, &ula_prefix->node); + ula_prefix = NULL; + } return; + } int length; char *prefixlen = strtok_r(NULL, ",", &saveptr);