+ bool assigned_any = false;
+ struct {
+ struct avl_node node;
+ } *entry, *n_entry;
+ struct avl_tree assign_later;
+
+ avl_init(&assign_later, prefix_assignment_cmp, false, NULL);
+
+ vlist_for_each_element(&interfaces, iface, node) {
+ if (iface->assignment_length < 48 ||
+ iface->assignment_length > 64)
+ continue;
+
+ // Test whether there is a matching class
+ if (!list_empty(&iface->assignment_classes)) {
+ bool found = false;
+
+ struct interface_assignment_class *c;
+ list_for_each_entry(c, &iface->assignment_classes, head) {
+ if (!strcmp(c->name, prefix->pclass)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ continue;
+ }
+
+ size_t namelen = strlen(iface->name) + 1;
+ c = malloc(sizeof(*c) + namelen);
+ if (!c)
+ continue;
+
+ c->length = iface->assignment_length;
+ c->assigned = iface->assignment_hint;
+ c->weight = iface->assignment_weight;
+ c->addr = in6addr_any;
+ c->enabled = false;
+ memcpy(c->name, iface->name, namelen);
+
+ // First process all custom assignments, put all others in later-list
+ if (c->assigned == -1 || !interface_prefix_assign(&prefix->assignments, c)) {
+ if (c->assigned != -1) {
+ c->assigned = -1;
+ netifd_log_message(L_WARNING, "Failed to assign requested subprefix "
+ "of size %hhu for %s, trying other\n", c->length, c->name);
+ }
+
+ entry = calloc(1, sizeof(*entry));
+ if (!entry)
+ continue;
+
+ entry->node.key = c;
+ avl_insert(&assign_later, &entry->node);
+ }
+
+ if (c->assigned != -1)
+ assigned_any = true;
+ }
+
+ /* Then try to assign all other + failed custom assignments */
+ avl_for_each_element_safe(&assign_later, entry, node, n_entry) {
+ bool assigned = false;
+
+ c = (struct device_prefix_assignment *)entry->node.key;
+ avl_delete(&assign_later, &entry->node);
+
+ do {
+ assigned = interface_prefix_assign(&prefix->assignments, c);
+ } while (!assigned && ++c->length <= 64);
+
+ if (!assigned) {
+ netifd_log_message(L_WARNING, "Failed to assign subprefix "
+ "of size %hhu for %s\n", c->length, c->name);
+ free(c);
+ } else
+ assigned_any = true;
+
+ free(entry);
+ }