+ prefix.s6_addr32[2] = prefix.s6_addr32[3] = 0;
+ odhcpd_setup_route(&prefix, (a->managed_size) ? addrs[i].prefix : a->length,
+ iface, &a->peer.sin6_addr, 1024, add);
+ }
+}
+
+/* More data was received from TCP connection */
+static void managed_handle_pd_data(struct ustream *s, _unused int bytes_new)
+{
+ struct dhcpv6_assignment *c = container_of(s, struct dhcpv6_assignment, managed_sock);
+ time_t now = odhcpd_time();
+ bool first = c->managed_size < 0;
+
+ for (;;) {
+ int pending;
+ char *data = ustream_get_read_buf(s, &pending);
+ char *end = memmem(data, pending, "\n\n", 2);
+
+ if (!end)
+ break;
+
+ end += 2;
+ end[-1] = 0;
+
+ c->managed_size = 0;
+ if (c->accept_reconf)
+ c->reconf_cnt = 1;
+
+ char *saveptr;
+ for (char *line = strtok_r(data, "\n", &saveptr); line; line = strtok_r(NULL, "\n", &saveptr)) {
+ c->managed = realloc(c->managed, (c->managed_size + 1) * sizeof(*c->managed));
+ struct odhcpd_ipaddr *n = &c->managed[c->managed_size];
+
+ char *saveptr2, *x = strtok_r(line, "/", &saveptr2);
+ if (!x || inet_pton(AF_INET6, x, &n->addr) < 1)
+ continue;
+
+ x = strtok_r(NULL, ",", &saveptr2);
+ if (sscanf(x, "%hhu", &n->prefix) < 1)
+ continue;
+
+ x = strtok_r(NULL, ",", &saveptr2);
+ if (sscanf(x, "%u", &n->preferred) < 1)
+ continue;
+
+ x = strtok_r(NULL, ",", &saveptr2);
+ if (sscanf(x, "%u", &n->valid) < 1)
+ continue;
+
+ if (n->preferred > n->valid)
+ continue;
+
+ if (UINT32_MAX - now < n->preferred)
+ n->preferred = UINT32_MAX;
+ else
+ n->preferred += now;
+
+ if (UINT32_MAX - now < n->valid)
+ n->valid = UINT32_MAX;
+ else
+ n->valid += now;
+
+ n->dprefix = 0;
+
+ ++c->managed_size;
+ }
+
+ ustream_consume(s, end - data);