route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_UNSPEC;
+ route->type = RTN_UNICAST;
route->table = RT_TABLE_MAIN;
route->lifetime = USEC_INFINITY;
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
- unsigned char table,
+ uint32_t table,
Route **ret) {
Route route, *existing;
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
- unsigned char table,
+ uint32_t table,
Route **ret) {
_cleanup_route_free_ Route *route = NULL;
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
- unsigned char table,
+ uint32_t table,
Route **ret) {
return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
- unsigned char table,
+ uint32_t table,
Route **ret) {
Route *route;
const union in_addr_union *gw,
const union in_addr_union *prefsrc,
unsigned char scope,
- unsigned char protocol) {
+ unsigned char protocol,
+ unsigned char type) {
assert(route);
assert(src);
route->prefsrc = *prefsrc;
route->scope = scope;
route->protocol = protocol;
+ route->type = type;
return 0;
}
if (r < 0)
return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
- r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+ r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ return log_error_errno(r, "Could not set route type: %m");
+
+ if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
+ r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ }
r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
if (r < 0)
if (r < 0)
return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
- r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+ r = sd_rtnl_message_route_set_type(req, route->type);
if (r < 0)
- return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ return log_error_errno(r, "Could not set route type: %m");
+
+ if (!IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE)) {
+ r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
+ if (r < 0)
+ return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
+ }
r = sd_netlink_message_open_container(req, RTA_METRICS);
if (r < 0)
Network *network = userdata;
_cleanup_route_free_ Route *n = NULL;
- const char *address, *e;
union in_addr_union buffer;
unsigned char prefixlen;
- int r, f;
+ int r;
assert(filename);
assert(section);
if (r < 0)
return r;
- /* Destination|Source=address/prefixlen */
-
- /* address */
- e = strchr(rvalue, '/');
- if (e)
- address = strndupa(rvalue, e - rvalue);
- else
- address = rvalue;
-
- r = in_addr_from_string_auto(address, &f, &buffer);
+ r = in_addr_prefix_from_string(rvalue, AF_INET, &buffer, &prefixlen);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Destination is invalid, ignoring assignment: %s", address);
- return 0;
- }
-
- if (f != AF_INET && f != AF_INET6) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown address family, ignoring assignment: %s", address);
- return 0;
- }
-
- /* prefixlen */
- if (e) {
- r = safe_atou8(e + 1, &prefixlen);
+ r = in_addr_prefix_from_string(rvalue, AF_INET6, &buffer, &prefixlen);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Route destination prefix length is invalid, ignoring assignment: %s", e + 1);
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Route %s= prefix is invalid, ignoring assignment: %s",
+ lvalue, rvalue);
return 0;
}
- } else {
- switch (f) {
- case AF_INET:
- prefixlen = 32;
- break;
- case AF_INET6:
- prefixlen = 128;
- break;
- }
- }
- n->family = f;
+ n->family = AF_INET6;
+ } else
+ n->family = AF_INET;
+
if (streq(lvalue, "Destination")) {
n->dst = buffer;
n->dst_prefixlen = prefixlen;
return 0;
}
- if (r)
- n->flags |= RTNH_F_ONLINK;
- else
- n->flags &= ~RTNH_F_ONLINK;
+ SET_FLAG(n->flags, RTNH_F_ONLINK, r);
n = NULL;
return 0;
_cleanup_route_free_ Route *n = NULL;
int r;
+ r = route_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
if (streq(rvalue, "low"))
n->pref = ICMPV6_ROUTER_PREF_LOW;
else if (streq(rvalue, "medium"))
return 0;
}
+
+int config_parse_route_protocol(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+ _cleanup_route_free_ Route *n = NULL;
+ int r;
+
+ r = route_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ if (streq(rvalue, "kernel"))
+ n->protocol = RTPROT_KERNEL;
+ else if (streq(rvalue, "boot"))
+ n->protocol = RTPROT_BOOT;
+ else if (streq(rvalue, "static"))
+ n->protocol = RTPROT_STATIC;
+ else {
+ r = safe_atou8(rvalue , &n->protocol);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse route protocol \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
+ }
+ }
+
+ n = NULL;
+
+ return 0;
+}
+
+int config_parse_route_type(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+ _cleanup_route_free_ Route *n = NULL;
+ int r;
+
+ r = route_new_static(network, filename, section_line, &n);
+ if (r < 0)
+ return r;
+
+ if (streq(rvalue, "unicast"))
+ n->type = RTN_UNICAST;
+ else if (streq(rvalue, "blackhole"))
+ n->type = RTN_BLACKHOLE;
+ else if (streq(rvalue, "unreachable"))
+ n->type = RTN_UNREACHABLE;
+ else if (streq(rvalue, "prohibit"))
+ n->type = RTN_PROHIBIT;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse route type \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ n = NULL;
+
+ return 0;
+}