#include "alloc-util.h"
#include "bus-util.h"
#include "dhcp-lease-internal.h"
+#include "event-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "netlink-util.h"
return log_oom();
STRV_FOREACH(route_str, routes_strv) {
+ Route *route;
+ _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+ usec_t lifetime;
char *prefixlen_str;
int family;
unsigned char prefixlen, tos, table;
*prefixlen_str ++ = '\0';
- r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu", &prefixlen, &tos, &priority, &table);
- if (r != 4) {
- log_link_debug(link, "Failed to parse destination prefix length, tos, priority or table %s", prefixlen_str);
+ r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime);
+ if (r != 5) {
+ log_link_debug(link,
+ "Failed to parse destination prefix length, tos, priority, table or expiration %s",
+ prefixlen_str);
continue;
}
continue;
}
- r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, NULL);
+ r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to add route: %m");
+
+ if (lifetime != USEC_INFINITY) {
+ r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime,
+ 0, route_expire_handler, route);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not arm route expiration handler: %m");
+ }
+
+ route->lifetime = lifetime;
+ sd_event_source_unref(route->expire);
+ route->expire = expire;
+ expire = NULL;
}
}
if (r < 0)
goto fail;
- fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu", space ? " " : "", route_str,
- route->dst_prefixlen, route->tos, route->priority, route->table);
+ fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str,
+ route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime);
space = true;
}
#include "alloc-util.h"
#include "conf-parser.h"
+#include "event-util.h"
#include "in-addr-util.h"
#include "netlink-util.h"
#include "networkd-route.h"
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_UNSPEC;
route->table = RT_TABLE_DEFAULT;
+ route->lifetime = USEC_INFINITY;
*ret = route;
route = NULL;
set_remove(route->link->routes_foreign, route);
}
+ sd_event_source_unref(route->expire);
+
free(route);
}
return 0;
}
+int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
+ Route *route = userdata;
+ int r;
+
+ assert(route);
+
+ r = route_remove(route, route->link, NULL);
+ if (r < 0)
+ log_warning_errno(r, "Could not remove route: %m");
+
+ return 1;
+}
+
int route_configure(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
+ _cleanup_event_source_unref_ sd_event_source *expire = NULL;
+ usec_t lifetime;
int r;
assert(link);
link_ref(link);
- r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL);
+ lifetime = route->lifetime;
+
+ r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
if (r < 0)
return log_error_errno(r, "Could not add route: %m");
+ /* TODO: drop expiration handling once it can be pushed into the kernel */
+ route->lifetime = lifetime;
+
+ if (route->lifetime != USEC_INFINITY) {
+ r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
+ route->lifetime, 0, route_expire_handler, route);
+ if (r < 0)
+ return log_error_errno(r, "Could not arm expiration timer: %m");
+ }
+
+ sd_event_source_unref(route->expire);
+ route->expire = expire;
+ expire = NULL;
+
return 0;
}
union in_addr_union src;
union in_addr_union prefsrc;
+ usec_t lifetime;
+ sd_event_source *expire;
+
LIST_FIELDS(Route, routes);
};
int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
void route_drop(Route *route);
+int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
+
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
#define _cleanup_route_free_ _cleanup_(route_freep)