summaryrefslogtreecommitdiff
path: root/src/network/networkd-route.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-11-11 13:16:46 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2021-11-14 14:41:37 +0900
commit344b3cff36ecb9b30c56cc924d14676952660664 (patch)
tree67039d1448ded9951f4201020e88320d8a02e1f0 /src/network/networkd-route.c
parent10b1c3cd24f5f95e6e72caebdd6896e2eaf8b853 (diff)
downloadsystemd-344b3cff36ecb9b30c56cc924d14676952660664.tar.gz
network: split networkd-route.[ch]
Diffstat (limited to 'src/network/networkd-route.c')
-rw-r--r--src/network/networkd-route.c383
1 files changed, 1 insertions, 382 deletions
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index ed8c113a54..946c69621f 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -13,166 +13,13 @@
#include "networkd-network.h"
#include "networkd-nexthop.h"
#include "networkd-queue.h"
+#include "networkd-route-util.h"
#include "networkd-route.h"
#include "parse-util.h"
-#include "string-table.h"
#include "string-util.h"
#include "strv.h"
-#include "strxcpyx.h"
-#include "sysctl-util.h"
#include "vrf.h"
-#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
-
-static const char * const route_type_table[__RTN_MAX] = {
- [RTN_UNICAST] = "unicast",
- [RTN_LOCAL] = "local",
- [RTN_BROADCAST] = "broadcast",
- [RTN_ANYCAST] = "anycast",
- [RTN_MULTICAST] = "multicast",
- [RTN_BLACKHOLE] = "blackhole",
- [RTN_UNREACHABLE] = "unreachable",
- [RTN_PROHIBIT] = "prohibit",
- [RTN_THROW] = "throw",
- [RTN_NAT] = "nat",
- [RTN_XRESOLVE] = "xresolve",
-};
-
-assert_cc(__RTN_MAX <= UCHAR_MAX);
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_type, int);
-
-static const char * const route_scope_table[] = {
- [RT_SCOPE_UNIVERSE] = "global",
- [RT_SCOPE_SITE] = "site",
- [RT_SCOPE_LINK] = "link",
- [RT_SCOPE_HOST] = "host",
- [RT_SCOPE_NOWHERE] = "nowhere",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(route_scope, int);
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(route_scope, int, UINT8_MAX);
-
-static const char * const route_table_table[] = {
- [RT_TABLE_DEFAULT] = "default",
- [RT_TABLE_MAIN] = "main",
- [RT_TABLE_LOCAL] = "local",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP(route_table, int);
-
-int manager_get_route_table_from_string(const Manager *m, const char *s, uint32_t *ret) {
- uint32_t t;
- int r;
-
- assert(m);
- assert(s);
- assert(ret);
-
- r = route_table_from_string(s);
- if (r >= 0) {
- *ret = (uint32_t) r;
- return 0;
- }
-
- t = PTR_TO_UINT32(hashmap_get(m->route_table_numbers_by_name, s));
- if (t != 0) {
- *ret = t;
- return 0;
- }
-
- r = safe_atou32(s, &t);
- if (r < 0)
- return r;
-
- if (t == 0)
- return -ERANGE;
-
- *ret = t;
- return 0;
-}
-
-int manager_get_route_table_to_string(const Manager *m, uint32_t table, char **ret) {
- _cleanup_free_ char *str = NULL;
- const char *s;
- int r;
-
- assert(m);
- assert(ret);
-
- if (table == 0)
- return -EINVAL;
-
- s = route_table_to_string(table);
- if (!s)
- s = hashmap_get(m->route_table_names_by_number, UINT32_TO_PTR(table));
-
- if (s)
- /* Currently, this is only used in debugging logs. To not confuse any bug
- * reports, let's include the table number. */
- r = asprintf(&str, "%s(%" PRIu32 ")", s, table);
- else
- r = asprintf(&str, "%" PRIu32, table);
- if (r < 0)
- return -ENOMEM;
-
- *ret = TAKE_PTR(str);
- return 0;
-}
-
-static const char * const route_protocol_table[] = {
- [RTPROT_KERNEL] = "kernel",
- [RTPROT_BOOT] = "boot",
- [RTPROT_STATIC] = "static",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING_FALLBACK(route_protocol, int, UINT8_MAX);
-
-static const char * const route_protocol_full_table[] = {
- [RTPROT_REDIRECT] = "redirect",
- [RTPROT_KERNEL] = "kernel",
- [RTPROT_BOOT] = "boot",
- [RTPROT_STATIC] = "static",
- [RTPROT_GATED] = "gated",
- [RTPROT_RA] = "ra",
- [RTPROT_MRT] = "mrt",
- [RTPROT_ZEBRA] = "zebra",
- [RTPROT_BIRD] = "bird",
- [RTPROT_DNROUTED] = "dnrouted",
- [RTPROT_XORP] = "xorp",
- [RTPROT_NTK] = "ntk",
- [RTPROT_DHCP] = "dhcp",
- [RTPROT_MROUTED] = "mrouted",
- [RTPROT_BABEL] = "babel",
- [RTPROT_BGP] = "bgp",
- [RTPROT_ISIS] = "isis",
- [RTPROT_OSPF] = "ospf",
- [RTPROT_RIP] = "rip",
- [RTPROT_EIGRP] = "eigrp",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING_FALLBACK(route_protocol_full, int, UINT8_MAX);
-
-static unsigned routes_max(void) {
- static thread_local unsigned cached = 0;
- _cleanup_free_ char *s4 = NULL, *s6 = NULL;
- unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;
-
- if (cached > 0)
- return cached;
-
- if (sysctl_read_ip_property(AF_INET, NULL, "route/max_size", &s4) >= 0)
- if (safe_atou(s4, &val4) >= 0 && val4 == 2147483647U)
- /* This is the default "no limit" value in the kernel */
- val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
-
- if (sysctl_read_ip_property(AF_INET6, NULL, "route/max_size", &s6) >= 0)
- (void) safe_atou(s6, &val6);
-
- cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
- MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
- return cached;
-}
-
int route_new(Route **ret) {
_cleanup_(route_freep) Route *route = NULL;
@@ -695,112 +542,6 @@ void link_mark_routes(Link *link, NetworkConfigSource source, const struct in6_a
}
}
-static bool link_address_is_reachable(Link *link, int family, const union in_addr_union *address) {
- Route *route;
- Address *a;
-
- assert(link);
- assert(link->manager);
- assert(IN_SET(family, AF_INET, AF_INET6));
- assert(address);
-
- SET_FOREACH(route, link->routes) {
- if (!route_exists(route))
- continue;
- if (route->family != family)
- continue;
- if (!in_addr_is_set(route->family, &route->dst))
- continue;
- if (in_addr_prefix_covers(family, &route->dst, route->dst_prefixlen, address) > 0)
- return true;
- }
-
- if (link->manager->manage_foreign_routes)
- return false;
-
- /* If we do not manage foreign routes, then there may exist a prefix route we do not know,
- * which was created on configuring an address. Hence, also check the addresses. */
- SET_FOREACH(a, link->addresses) {
- if (!address_is_ready(a))
- continue;
- if (a->family != family)
- continue;
- if (FLAGS_SET(a->flags, IFA_F_NOPREFIXROUTE))
- continue;
- if (in_addr_is_set(a->family, &a->in_addr_peer))
- continue;
- if (in_addr_prefix_covers(family, &a->in_addr, a->prefixlen, address) > 0)
- return true;
- }
-
- return false;
-}
-
-static Route *link_find_default_gateway(Link *link, int family, Route *gw) {
- Route *route;
-
- assert(link);
-
- SET_FOREACH(route, link->routes) {
- if (!route_exists(route))
- continue;
- if (family != AF_UNSPEC && route->family != family)
- continue;
- if (route->dst_prefixlen != 0)
- continue;
- if (route->src_prefixlen != 0)
- continue;
- if (route->table != RT_TABLE_MAIN)
- continue;
- if (route->type != RTN_UNICAST)
- continue;
- if (route->scope != RT_SCOPE_UNIVERSE)
- continue;
- if (!in_addr_is_set(route->gw_family, &route->gw))
- continue;
- if (gw) {
- if (route->gw_weight > gw->gw_weight)
- continue;
- if (route->priority >= gw->priority)
- continue;
- }
- gw = route;
- }
-
- return gw;
-}
-
-int manager_find_uplink(Manager *m, int family, Link *exclude, Link **ret) {
- Route *gw = NULL;
- Link *link;
-
- assert(m);
- assert(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6));
-
- /* Looks for a suitable "uplink", via black magic: an interface that is up and where the
- * default route with the highest priority points to. */
-
- HASHMAP_FOREACH(link, m->links_by_index) {
- if (link == exclude)
- continue;
-
- if (link->state != LINK_STATE_CONFIGURED)
- continue;
-
- gw = link_find_default_gateway(link, family, gw);
- }
-
- if (!gw)
- return -ENOENT;
-
- if (ret) {
- assert(gw->link);
- *ret = gw->link;
- }
-
- return 0;
-}
-
static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *manager) {
_cleanup_free_ char *state = NULL, *dst = NULL, *src = NULL, *gw_alloc = NULL, *prefsrc = NULL,
*table = NULL, *scope = NULL, *proto = NULL;
@@ -1628,22 +1369,6 @@ int link_request_static_routes(Link *link, bool only_ipv4) {
return 0;
}
-bool gateway_is_ready(Link *link, bool onlink, int family, const union in_addr_union *gw) {
- assert(link);
- assert(gw);
-
- if (onlink)
- return true;
-
- if (!in_addr_is_set(family, gw))
- return true;
-
- if (family == AF_INET6 && in6_addr_is_link_local(&gw->in6))
- return true;
-
- return link_address_is_reachable(link, family, gw);
-}
-
static int route_is_ready_to_configure(const Route *route, Link *link) {
int r;
@@ -2958,112 +2683,6 @@ int config_parse_multipath_route(
return 0;
}
-int config_parse_route_table_names(
- 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) {
-
- Manager *m = userdata;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(userdata);
-
- if (isempty(rvalue)) {
- m->route_table_names_by_number = hashmap_free(m->route_table_names_by_number);
- m->route_table_numbers_by_name = hashmap_free(m->route_table_numbers_by_name);
- return 0;
- }
-
- for (const char *p = rvalue;;) {
- _cleanup_free_ char *name = NULL;
- uint32_t table;
- char *num;
-
- r = extract_first_word(&p, &name, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Invalid RouteTable=, ignoring assignment: %s", rvalue);
- return 0;
- }
- if (r == 0)
- return 0;
-
- num = strchr(name, ':');
- if (!num) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid route table name and number pair, ignoring assignment: %s", name);
- continue;
- }
-
- *num++ = '\0';
-
- if (STR_IN_SET(name, "default", "main", "local")) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Route table name %s already predefined. Ignoring assignment: %s:%s", name, name, num);
- continue;
- }
-
- r = safe_atou32(num, &table);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse route table number '%s', ignoring assignment: %s:%s", num, name, num);
- continue;
- }
- if (table == 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Invalid route table number, ignoring assignment: %s:%s", name, num);
- continue;
- }
-
- r = hashmap_ensure_put(&m->route_table_numbers_by_name, &string_hash_ops_free, name, UINT32_TO_PTR(table));
- if (r == -ENOMEM)
- return log_oom();
- if (r == -EEXIST) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Specified route table name and number pair conflicts with others, ignoring assignment: %s:%s", name, num);
- continue;
- }
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to store route table name and number pair, ignoring assignment: %s:%s", name, num);
- continue;
- }
- if (r == 0)
- /* The entry is duplicated. It should not be added to route_table_names_by_number hashmap. */
- continue;
-
- r = hashmap_ensure_put(&m->route_table_names_by_number, NULL, UINT32_TO_PTR(table), name);
- if (r < 0) {
- hashmap_remove(m->route_table_numbers_by_name, name);
-
- if (r == -ENOMEM)
- return log_oom();
- if (r == -EEXIST)
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Specified route table name and number pair conflicts with others, ignoring assignment: %s:%s", name, num);
- else
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to store route table name and number pair, ignoring assignment: %s:%s", name, num);
- continue;
- }
- assert(r > 0);
-
- TAKE_PTR(name);
- }
-}
-
static int route_section_verify(Route *route, Network *network) {
if (section_is_invalid(route->section))
return -EINVAL;