+ // Use source-based routing
+ if ((cur = tb[ROUTE_SOURCE]) != NULL) {
+ char *saveptr, *source = alloca(blobmsg_data_len(cur));
+ memcpy(source, blobmsg_data(cur), blobmsg_data_len(cur));
+
+ const char *addr = strtok_r(source, "/", &saveptr);
+ const char *mask = strtok_r(NULL, "/", &saveptr);
+
+ if (!addr || inet_pton(af, addr, &route->source) < 1) {
+ DPRINTF("Failed to parse route source: %s\n", addr ? addr : "NULL");
+ goto error;
+ }
+
+ route->sourcemask = (mask) ? atoi(mask) : ((af == AF_INET6) ? 128 : 32);
+ }
+
+ if ((cur = tb[ROUTE_ONLINK]) != NULL && blobmsg_get_bool(cur))
+ route->flags |= DEVROUTE_ONLINK;
+
+ if ((cur = tb[ROUTE_TABLE]) != NULL) {
+ if (!system_resolve_rt_table(blobmsg_data(cur), &route->table)) {
+ DPRINTF("Failed to resolve routing table: %s\n", (char *) blobmsg_data(cur));
+ goto error;
+ }
+
+ /* only set the table flag if not using the main (default) table */
+ if (system_is_default_rt_table(route->table))
+ route->table = 0;
+
+ if (route->table)
+ route->flags |= DEVROUTE_TABLE;
+ }
+
+ if ((cur = tb[ROUTE_VALID]) != NULL) {
+ int64_t valid = blobmsg_get_u32(cur);
+ int64_t valid_until = valid + (int64_t)system_get_rtime();
+ if (valid_until <= LONG_MAX && valid != 0xffffffffLL) // Catch overflow
+ route->valid_until = valid_until;
+ }
+
+ if ((cur = tb[ROUTE_TYPE]) != NULL) {
+ if (!system_resolve_rt_type(blobmsg_data(cur), &route->type)) {
+ DPRINTF("Failed to resolve routing type: %s\n", (char *) blobmsg_data(cur));
+ goto error;
+ }
+ route->flags |= DEVROUTE_TYPE;
+ }
+
+ interface_set_route_info(iface, route);
+ vlist_add(&ip->route, &route->node, route);