+static int lease_parse_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
+ size_t *routes_size, size_t *routes_allocated) {
+
+ struct in_addr addr;
+
+ assert(option);
+ assert(routes);
+ assert(routes_size);
+ assert(routes_allocated);
+
+ if (!len)
+ return 0;
+
+ if (len % 8 != 0)
+ return -EINVAL;
+
+ if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + (len / 8)))
+ return -ENOMEM;
+
+ while (len >= 8) {
+ struct sd_dhcp_route *route = *routes + *routes_size;
+ int r;
+
+ r = in_addr_default_prefixlen((struct in_addr*) option, &route->dst_prefixlen);
+ if (r < 0) {
+ log_error("Failed to determine destination prefix length from class based IP, ignoring");
+ continue;
+ }
+
+ lease_parse_be32(option, 4, &addr.s_addr);
+ route->dst_addr = inet_makeaddr(inet_netof(addr), 0);
+ option += 4;
+
+ lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+ option += 4;
+
+ len -= 8;
+ (*routes_size)++;
+ }
+
+ return 0;
+}
+
+/* parses RFC3442 Classless Static Route Option */
+static int lease_parse_classless_routes(const uint8_t *option, size_t len, struct sd_dhcp_route **routes,
+ size_t *routes_size, size_t *routes_allocated) {
+
+ assert(option);
+ assert(routes);
+ assert(routes_size);
+ assert(routes_allocated);
+
+ /* option format: (subnet-mask-width significant-subnet-octets gateway-ip)* */
+
+ while (len > 0) {
+ uint8_t dst_octets;
+ struct sd_dhcp_route *route;
+
+ if (!GREEDY_REALLOC(*routes, *routes_allocated, *routes_size + 1))
+ return -ENOMEM;
+
+ route = *routes + *routes_size;
+
+ dst_octets = (*option == 0 ? 0 : ((*option - 1) / 8) + 1);
+ route->dst_prefixlen = *option;
+ option++;
+ len--;
+
+ /* can't have more than 4 octets in IPv4 */
+ if (dst_octets > 4 || len < dst_octets)
+ return -EINVAL;
+
+ route->dst_addr.s_addr = 0;
+ memcpy(&route->dst_addr.s_addr, option, dst_octets);
+ option += dst_octets;
+ len -= dst_octets;
+
+ if (len < 4)
+ return -EINVAL;
+
+ lease_parse_be32(option, 4, &route->gw_addr.s_addr);
+ option += 4;
+ len -= 4;
+
+ (*routes_size)++;
+ }
+
+ return 0;
+}
+