mirror of
https://github.com/systemd/systemd
synced 2026-03-06 13:15:06 +01:00
Compare commits
14 Commits
23d8003bb6
...
e81a44bf5f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e81a44bf5f | ||
|
|
e3284031ae | ||
|
|
e1f3685750 | ||
|
|
e82b77e984 | ||
|
|
bcdb3b7d50 | ||
|
|
c18c53c36e | ||
|
|
ea81208f03 | ||
|
|
40424f1ad9 | ||
|
|
18f2ee3310 | ||
|
|
1db01a3339 | ||
|
|
24f50382af | ||
|
|
4055ec9323 | ||
|
|
167a5561cd | ||
|
|
ad6df71759 |
@ -91,6 +91,12 @@
|
|||||||
<varname>PollIntervalMaxSec=</varname> defaults to 2048 seconds.</para></listitem>
|
<varname>PollIntervalMaxSec=</varname> defaults to 2048 seconds.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ConnectionRetrySec=</varname></term>
|
||||||
|
<listitem><para>Specifies the delaying attempts to contact servers after network is online. Takes a time value (in seconds).
|
||||||
|
Defaults to 30 seconds and must not be smaller than 1 seconds.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@ -893,7 +893,7 @@ void emit_bpf_firewall_warning(Unit *u) {
|
|||||||
static bool warned = false;
|
static bool warned = false;
|
||||||
|
|
||||||
if (!warned) {
|
if (!warned) {
|
||||||
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container();
|
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container() > 0;
|
||||||
|
|
||||||
log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
|
log_unit_full_errno(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
|
||||||
"unit configures an IP firewall, but %s.\n"
|
"unit configures an IP firewall, but %s.\n"
|
||||||
|
|||||||
@ -405,7 +405,8 @@ static int address_drop(Address *address) {
|
|||||||
bool ready;
|
bool ready;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(address);
|
if (!address)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ready = address_is_ready(address);
|
ready = address_is_ready(address);
|
||||||
link = address->link;
|
link = address->link;
|
||||||
@ -466,6 +467,34 @@ int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
|
|||||||
return address_get(link, a, NULL) >= 0;
|
return address_get(link, a, NULL) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log_address_debug(const Address *address, const char *str, const Link *link) {
|
||||||
|
assert(address);
|
||||||
|
assert(str);
|
||||||
|
assert(link);
|
||||||
|
|
||||||
|
if (DEBUG_LOGGING) {
|
||||||
|
_cleanup_free_ char *addr = NULL, *peer = NULL;
|
||||||
|
char valid_buf[FORMAT_TIMESPAN_MAX];
|
||||||
|
const char *valid_str = NULL;
|
||||||
|
bool has_peer;
|
||||||
|
|
||||||
|
(void) in_addr_to_string(address->family, &address->in_addr, &addr);
|
||||||
|
has_peer = in_addr_is_null(address->family, &address->in_addr_peer) == 0;
|
||||||
|
if (has_peer)
|
||||||
|
(void) in_addr_to_string(address->family, &address->in_addr_peer, &peer);
|
||||||
|
|
||||||
|
if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
|
||||||
|
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
|
||||||
|
address->cinfo.ifa_valid * USEC_PER_SEC,
|
||||||
|
USEC_PER_SEC);
|
||||||
|
|
||||||
|
log_link_debug(link, "%s address: %s%s%s/%u (valid %s%s)",
|
||||||
|
str, strnull(addr), has_peer ? " peer " : "",
|
||||||
|
has_peer ? strnull(peer) : "", address->prefixlen,
|
||||||
|
valid_str ? "for " : "forever", strempty(valid_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -500,12 +529,7 @@ int address_remove(
|
|||||||
assert(link->manager);
|
assert(link->manager);
|
||||||
assert(link->manager->rtnl);
|
assert(link->manager->rtnl);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
log_address_debug(address, "Removing", link);
|
||||||
_cleanup_free_ char *b = NULL;
|
|
||||||
|
|
||||||
(void) in_addr_to_string(address->family, &address->in_addr, &b);
|
|
||||||
log_link_debug(link, "Removing address %s", strna(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
|
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
|
||||||
link->ifindex, address->family);
|
link->ifindex, address->family);
|
||||||
@ -807,12 +831,7 @@ int address_configure(
|
|||||||
if (acquired_address)
|
if (acquired_address)
|
||||||
address = acquired_address;
|
address = acquired_address;
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
log_address_debug(address, update ? "Updating" : "Configuring", link);
|
||||||
_cleanup_free_ char *str = NULL;
|
|
||||||
|
|
||||||
(void) in_addr_to_string(address->family, &address->in_addr, &str);
|
|
||||||
log_link_debug(link, "%s address: %s", update ? "Updating" : "Configuring", strna(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
|
r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
|
||||||
@ -1058,15 +1077,11 @@ int link_set_addresses(Link *link) {
|
|||||||
|
|
||||||
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_(address_freep) Address *tmp = NULL;
|
_cleanup_(address_freep) Address *tmp = NULL;
|
||||||
_cleanup_free_ char *buf = NULL, *buf_peer = NULL;
|
|
||||||
Link *link = NULL;
|
Link *link = NULL;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
unsigned char flags;
|
unsigned char flags;
|
||||||
Address *address = NULL;
|
Address *address = NULL;
|
||||||
char valid_buf[FORMAT_TIMESPAN_MAX];
|
|
||||||
const char *valid_str = NULL;
|
|
||||||
int ifindex, r;
|
int ifindex, r;
|
||||||
bool has_peer = false;
|
|
||||||
|
|
||||||
assert(rtnl);
|
assert(rtnl);
|
||||||
assert(message);
|
assert(message);
|
||||||
@ -1154,8 +1169,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
} else if (r >= 0) {
|
} else if (r >= 0) {
|
||||||
if (in4_addr_equal(&tmp->in_addr.in, &tmp->in_addr_peer.in))
|
if (in4_addr_equal(&tmp->in_addr.in, &tmp->in_addr_peer.in))
|
||||||
tmp->in_addr_peer = IN_ADDR_NULL;
|
tmp->in_addr_peer = IN_ADDR_NULL;
|
||||||
else
|
|
||||||
has_peer = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_read_in_addr(message, IFA_BROADCAST, &tmp->broadcast);
|
r = sd_netlink_message_read_in_addr(message, IFA_BROADCAST, &tmp->broadcast);
|
||||||
@ -1182,7 +1195,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
log_link_warning_errno(link, r, "rtnl: could not get peer address from address message, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: could not get peer address from address message, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
has_peer = true;
|
|
||||||
} else if (r == -ENODATA) {
|
} else if (r == -ENODATA) {
|
||||||
/* Does not have peer address. */
|
/* Does not have peer address. */
|
||||||
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &tmp->in_addr.in6);
|
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &tmp->in_addr.in6);
|
||||||
@ -1201,39 +1213,28 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
assert_not_reached("Received unsupported address family");
|
assert_not_reached("Received unsupported address family");
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->in_addr, &buf);
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->in_addr_peer, &buf_peer);
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &tmp->cinfo);
|
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &tmp->cinfo);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (r >= 0 && tmp->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
|
}
|
||||||
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
|
|
||||||
tmp->cinfo.ifa_valid * USEC_PER_SEC,
|
|
||||||
USEC_PER_SEC);
|
|
||||||
|
|
||||||
(void) address_get(link, tmp, &address);
|
(void) address_get(link, tmp, &address);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR:
|
||||||
if (address)
|
log_address_debug(tmp, address ? "Remembering updated" : "Remembering foreign", link);
|
||||||
log_link_debug(link, "Remembering updated address: %s%s%s/%u (valid %s%s)",
|
if (!address) {
|
||||||
strnull(buf), has_peer ? " peer " : "",
|
|
||||||
has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
|
|
||||||
valid_str ? "for " : "forever", strempty(valid_str));
|
|
||||||
else {
|
|
||||||
/* An address appeared that we did not request */
|
/* An address appeared that we did not request */
|
||||||
r = address_add_foreign(link, tmp, &address);
|
r = address_add_foreign(link, tmp, &address);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
|
_cleanup_free_ char *buf = NULL;
|
||||||
|
|
||||||
|
(void) in_addr_to_string(tmp->family, &tmp->in_addr, &buf);
|
||||||
log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m",
|
log_link_warning_errno(link, r, "Failed to remember foreign address %s/%u, ignoring: %m",
|
||||||
strnull(buf), tmp->prefixlen);
|
strnull(buf), tmp->prefixlen);
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
}
|
||||||
log_link_debug(link, "Remembering foreign address: %s%s%s/%u (valid %s%s)",
|
|
||||||
strnull(buf), has_peer ? " peer " : "",
|
|
||||||
has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
|
|
||||||
valid_str ? "for " : "forever", strempty(valid_str));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* address_update() logs internally, so we don't need to here. */
|
/* address_update() logs internally, so we don't need to here. */
|
||||||
@ -1244,17 +1245,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_DELADDR:
|
case RTM_DELADDR:
|
||||||
if (address) {
|
log_address_debug(tmp, address ? "Forgetting" : "Kernel removed unknown", link);
|
||||||
log_link_debug(link, "Forgetting address: %s%s%s/%u (valid %s%s)",
|
(void) address_drop(address);
|
||||||
strnull(buf), has_peer ? " peer " : "",
|
|
||||||
has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
|
|
||||||
valid_str ? "for " : "forever", strempty(valid_str));
|
|
||||||
(void) address_drop(address);
|
|
||||||
} else
|
|
||||||
log_link_debug(link, "Kernel removed an address we don't remember: %s%s%s/%u (valid %s%s), ignoring.",
|
|
||||||
strnull(buf), has_peer ? " peer " : "",
|
|
||||||
has_peer ? strnull(buf_peer) : "", tmp->prefixlen,
|
|
||||||
valid_str ? "for " : "forever", strempty(valid_str));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@ -83,7 +83,6 @@ typedef struct Link {
|
|||||||
unsigned route_messages;
|
unsigned route_messages;
|
||||||
unsigned nexthop_messages;
|
unsigned nexthop_messages;
|
||||||
unsigned routing_policy_rule_messages;
|
unsigned routing_policy_rule_messages;
|
||||||
unsigned routing_policy_rule_remove_messages;
|
|
||||||
unsigned tc_messages;
|
unsigned tc_messages;
|
||||||
unsigned sr_iov_messages;
|
unsigned sr_iov_messages;
|
||||||
unsigned enslaving;
|
unsigned enslaving;
|
||||||
|
|||||||
@ -581,6 +581,37 @@ static bool route_type_is_reject(const Route *route) {
|
|||||||
return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW);
|
return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log_route_debug(const Route *route, const char *str, const Link *link) {
|
||||||
|
assert(route);
|
||||||
|
assert(str);
|
||||||
|
|
||||||
|
/* link may be NULL. */
|
||||||
|
|
||||||
|
if (DEBUG_LOGGING) {
|
||||||
|
_cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
|
||||||
|
char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
|
||||||
|
|
||||||
|
if (!in_addr_is_null(route->family, &route->dst)) {
|
||||||
|
(void) in_addr_to_string(route->family, &route->dst, &dst);
|
||||||
|
(void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen);
|
||||||
|
}
|
||||||
|
if (!in_addr_is_null(route->family, &route->src))
|
||||||
|
(void) in_addr_to_string(route->family, &route->src, &src);
|
||||||
|
if (!in_addr_is_null(route->gw_family, &route->gw))
|
||||||
|
(void) in_addr_to_string(route->gw_family, &route->gw, &gw);
|
||||||
|
if (!in_addr_is_null(route->family, &route->prefsrc))
|
||||||
|
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
|
||||||
|
|
||||||
|
log_link_debug(link,
|
||||||
|
"%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
|
||||||
|
str, strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
|
||||||
|
format_route_scope(route->scope, scope, sizeof(scope)),
|
||||||
|
format_route_table(route->table, table, sizeof(table)),
|
||||||
|
format_route_protocol(route->protocol, protocol, sizeof(protocol)),
|
||||||
|
strna(route_type_to_string(route->type)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) {
|
static int route_set_netlink_message(const Route *route, sd_netlink_message *req, Link *link) {
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
int r;
|
int r;
|
||||||
@ -717,35 +748,14 @@ int route_remove(
|
|||||||
manager = link->manager;
|
manager = link->manager;
|
||||||
/* link may be NULL! */
|
/* link may be NULL! */
|
||||||
|
|
||||||
|
log_route_debug(route, "Removing", link);
|
||||||
|
|
||||||
r = sd_rtnl_message_new_route(manager->rtnl, &req,
|
r = sd_rtnl_message_new_route(manager->rtnl, &req,
|
||||||
RTM_DELROUTE, route->family,
|
RTM_DELROUTE, route->family,
|
||||||
route->protocol);
|
route->protocol);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
|
return log_link_error_errno(link, r, "Could not create RTM_DELROUTE message: %m");
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
|
||||||
_cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
|
|
||||||
char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
|
|
||||||
|
|
||||||
if (!in_addr_is_null(route->family, &route->dst)) {
|
|
||||||
(void) in_addr_to_string(route->family, &route->dst, &dst);
|
|
||||||
(void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen);
|
|
||||||
}
|
|
||||||
if (!in_addr_is_null(route->family, &route->src))
|
|
||||||
(void) in_addr_to_string(route->family, &route->src, &src);
|
|
||||||
if (!in_addr_is_null(route->gw_family, &route->gw))
|
|
||||||
(void) in_addr_to_string(route->gw_family, &route->gw, &gw);
|
|
||||||
if (!in_addr_is_null(route->family, &route->prefsrc))
|
|
||||||
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
|
|
||||||
|
|
||||||
log_link_debug(link, "Removing route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
|
|
||||||
strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
|
|
||||||
format_route_scope(route->scope, scope, sizeof(scope)),
|
|
||||||
format_route_table(route->table, table, sizeof(table)),
|
|
||||||
format_route_protocol(route->protocol, protocol, sizeof(protocol)),
|
|
||||||
strna(route_type_to_string(route->type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
r = route_set_netlink_message(route, req, link);
|
r = route_set_netlink_message(route, req, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -777,7 +787,7 @@ static bool link_has_route(const Link *link, const Route *route) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool links_have_route(Manager *manager, const Route *route, const Link *except) {
|
static bool links_have_route(const Manager *manager, const Route *route, const Link *except) {
|
||||||
Link *link;
|
Link *link;
|
||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
@ -793,19 +803,21 @@ static bool links_have_route(Manager *manager, const Route *route, const Link *e
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_drop_foreign_routes(Manager *manager) {
|
static int manager_drop_routes_internal(Manager *manager, bool foreign, const Link *except) {
|
||||||
Route *route;
|
Route *route;
|
||||||
int k, r = 0;
|
int k, r = 0;
|
||||||
|
Set *routes;
|
||||||
|
|
||||||
assert(manager);
|
assert(manager);
|
||||||
|
|
||||||
SET_FOREACH(route, manager->routes_foreign) {
|
routes = foreign ? manager->routes_foreign : manager->routes;
|
||||||
/* do not touch routes managed by the kernel */
|
SET_FOREACH(route, routes) {
|
||||||
|
/* Do not touch routes managed by the kernel */
|
||||||
if (route->protocol == RTPROT_KERNEL)
|
if (route->protocol == RTPROT_KERNEL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (links_have_route(manager, route, NULL))
|
/* The route will be configured later, or already configured by a link */
|
||||||
/* The route will be configured later. */
|
if (links_have_route(manager, route, except))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* The existing links do not have the route. Let's drop this now. It may by
|
/* The existing links do not have the route. Let's drop this now. It may by
|
||||||
@ -818,29 +830,12 @@ static int manager_drop_foreign_routes(Manager *manager) {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int manager_drop_routes(Manager *manager, Link *except) {
|
static int manager_drop_foreign_routes(Manager *manager) {
|
||||||
Route *route;
|
return manager_drop_routes_internal(manager, true, NULL);
|
||||||
int k, r = 0;
|
}
|
||||||
|
|
||||||
assert(manager);
|
static int manager_drop_routes(Manager *manager, const Link *except) {
|
||||||
|
return manager_drop_routes_internal(manager, false, except);
|
||||||
SET_FOREACH(route, manager->routes) {
|
|
||||||
/* do not touch routes managed by the kernel */
|
|
||||||
if (route->protocol == RTPROT_KERNEL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (links_have_route(manager, route, except))
|
|
||||||
/* The route will be configured later. */
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* The existing links do not have the route. Let's drop this now. It may by
|
|
||||||
* re-configured later. */
|
|
||||||
k = route_remove(route, manager, NULL, NULL);
|
|
||||||
if (k < 0 && r >= 0)
|
|
||||||
r = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int link_drop_foreign_routes(Link *link) {
|
int link_drop_foreign_routes(Link *link) {
|
||||||
@ -1068,28 +1063,7 @@ int route_configure(
|
|||||||
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
|
return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
|
||||||
"Too many routes are configured, refusing: %m");
|
"Too many routes are configured, refusing: %m");
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
log_route_debug(route, "Configuring", link);
|
||||||
_cleanup_free_ char *dst = NULL, *dst_prefixlen = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL;
|
|
||||||
char scope[ROUTE_SCOPE_STR_MAX], table[ROUTE_TABLE_STR_MAX], protocol[ROUTE_PROTOCOL_STR_MAX];
|
|
||||||
|
|
||||||
if (!in_addr_is_null(route->family, &route->dst)) {
|
|
||||||
(void) in_addr_to_string(route->family, &route->dst, &dst);
|
|
||||||
(void) asprintf(&dst_prefixlen, "/%u", route->dst_prefixlen);
|
|
||||||
}
|
|
||||||
if (!in_addr_is_null(route->family, &route->src))
|
|
||||||
(void) in_addr_to_string(route->family, &route->src, &src);
|
|
||||||
if (!in_addr_is_null(route->gw_family, &route->gw))
|
|
||||||
(void) in_addr_to_string(route->gw_family, &route->gw, &gw);
|
|
||||||
if (!in_addr_is_null(route->family, &route->prefsrc))
|
|
||||||
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
|
|
||||||
|
|
||||||
log_link_debug(link, "Configuring route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
|
|
||||||
strna(dst), strempty(dst_prefixlen), strna(src), strna(gw), strna(prefsrc),
|
|
||||||
format_route_scope(route->scope, scope, sizeof(scope)),
|
|
||||||
format_route_table(route->table, table, sizeof(table)),
|
|
||||||
format_route_protocol(route->protocol, protocol, sizeof(protocol)),
|
|
||||||
strna(route_type_to_string(route->type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
|
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
|
||||||
RTM_NEWROUTE, route->family,
|
RTM_NEWROUTE, route->family,
|
||||||
@ -1308,50 +1282,29 @@ static int process_route_one(Manager *manager, Link *link, uint16_t type, const
|
|||||||
|
|
||||||
(void) route_get(manager, link, tmp, &route);
|
(void) route_get(manager, link, tmp, &route);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
|
||||||
_cleanup_free_ char *buf_dst = NULL, *buf_dst_prefixlen = NULL,
|
|
||||||
*buf_src = NULL, *buf_gw = NULL, *buf_prefsrc = NULL;
|
|
||||||
char buf_scope[ROUTE_SCOPE_STR_MAX], buf_table[ROUTE_TABLE_STR_MAX],
|
|
||||||
buf_protocol[ROUTE_PROTOCOL_STR_MAX];
|
|
||||||
|
|
||||||
if (!in_addr_is_null(tmp->family, &tmp->dst)) {
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->dst, &buf_dst);
|
|
||||||
(void) asprintf(&buf_dst_prefixlen, "/%u", tmp->dst_prefixlen);
|
|
||||||
}
|
|
||||||
if (!in_addr_is_null(tmp->family, &tmp->src))
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->src, &buf_src);
|
|
||||||
if (!in_addr_is_null(tmp->gw_family, &tmp->gw))
|
|
||||||
(void) in_addr_to_string(tmp->gw_family, &tmp->gw, &buf_gw);
|
|
||||||
if (!in_addr_is_null(tmp->family, &tmp->prefsrc))
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->prefsrc, &buf_prefsrc);
|
|
||||||
|
|
||||||
log_link_debug(link,
|
|
||||||
"%s route: dst: %s%s, src: %s, gw: %s, prefsrc: %s, scope: %s, table: %s, proto: %s, type: %s",
|
|
||||||
(!route && !manager->manage_foreign_routes) ? "Ignoring received foreign" :
|
|
||||||
type == RTM_DELROUTE ? "Forgetting" :
|
|
||||||
route ? "Received remembered" : "Remembering",
|
|
||||||
strna(buf_dst), strempty(buf_dst_prefixlen),
|
|
||||||
strna(buf_src), strna(buf_gw), strna(buf_prefsrc),
|
|
||||||
format_route_scope(tmp->scope, buf_scope, sizeof buf_scope),
|
|
||||||
format_route_table(tmp->table, buf_table, sizeof buf_table),
|
|
||||||
format_route_protocol(tmp->protocol, buf_protocol, sizeof buf_protocol),
|
|
||||||
strna(route_type_to_string(tmp->type)));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RTM_NEWROUTE:
|
case RTM_NEWROUTE:
|
||||||
if (!route && manager->manage_foreign_routes) {
|
if (!route) {
|
||||||
/* A route appeared that we did not request */
|
if (!manager->manage_foreign_routes)
|
||||||
r = route_add_foreign(manager, link, tmp, NULL);
|
log_route_debug(tmp, "Ignoring received foreign", link);
|
||||||
if (r < 0) {
|
else {
|
||||||
log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
|
/* A route appeared that we did not request */
|
||||||
return 0;
|
log_route_debug(tmp, "Remembering foreign", link);
|
||||||
|
r = route_add_foreign(manager, link, tmp, NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
log_link_warning_errno(link, r, "Failed to remember foreign route, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
log_route_debug(tmp, "Received remembered", link);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTM_DELROUTE:
|
case RTM_DELROUTE:
|
||||||
|
log_route_debug(tmp,
|
||||||
|
route ? "Forgetting" :
|
||||||
|
manager->manage_foreign_routes ? "Kernel removed unknown" : "Ignoring received foreign", link);
|
||||||
route_free(route);
|
route_free(route);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1370,7 +1323,6 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
|
|||||||
uint32_t ifindex;
|
uint32_t ifindex;
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
unsigned char table;
|
unsigned char table;
|
||||||
RouteVia via;
|
|
||||||
size_t rta_len;
|
size_t rta_len;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -1434,20 +1386,20 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tmp->family) {
|
r = netlink_message_read_in_addr_union(message, RTA_DST, tmp->family, &tmp->dst);
|
||||||
case AF_INET:
|
if (r < 0 && r != -ENODATA) {
|
||||||
r = sd_netlink_message_read_in_addr(message, RTA_DST, &tmp->dst.in);
|
log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
|
||||||
if (r < 0 && r != -ENODATA) {
|
return 0;
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &tmp->gw.in);
|
r = netlink_message_read_in_addr_union(message, RTA_GATEWAY, tmp->family, &tmp->gw);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (r >= 0)
|
} else if (r >= 0)
|
||||||
tmp->gw_family = AF_INET;
|
tmp->gw_family = tmp->family;
|
||||||
|
else if (tmp->family == AF_INET) {
|
||||||
|
RouteVia via;
|
||||||
|
|
||||||
r = sd_netlink_message_read(message, RTA_VIA, sizeof(via), &via);
|
r = sd_netlink_message_read(message, RTA_VIA, sizeof(via), &via);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
@ -1457,51 +1409,17 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Ma
|
|||||||
tmp->gw_family = via.family;
|
tmp->gw_family = via.family;
|
||||||
tmp->gw = via.address;
|
tmp->gw = via.address;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_read_in_addr(message, RTA_SRC, &tmp->src.in);
|
r = netlink_message_read_in_addr_union(message, RTA_SRC, tmp->family, &tmp->src);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &tmp->prefsrc.in);
|
r = netlink_message_read_in_addr_union(message, RTA_PREFSRC, tmp->family, &tmp->prefsrc);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
|
log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, RTA_DST, &tmp->dst.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid destination, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &tmp->gw.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid gateway, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (r >= 0)
|
|
||||||
tmp->gw_family = AF_INET6;
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &tmp->src.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid source, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &tmp->prefsrc.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_link_warning_errno(link, r, "rtnl: received route message without valid preferred source, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Received route message with unsupported address family");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -264,6 +264,16 @@ static int routing_policy_rule_compare_func(const RoutingPolicyRule *a, const Ro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool routing_policy_rule_equal(const RoutingPolicyRule *rule1, const RoutingPolicyRule *rule2) {
|
||||||
|
if (rule1 == rule2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!rule1 || !rule2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return routing_policy_rule_compare_func(rule1, rule2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||||
routing_policy_rule_hash_ops,
|
routing_policy_rule_hash_ops,
|
||||||
RoutingPolicyRule,
|
RoutingPolicyRule,
|
||||||
@ -337,12 +347,33 @@ static int routing_policy_rule_add_foreign(Manager *m, RoutingPolicyRule *rule,
|
|||||||
return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret);
|
return routing_policy_rule_add_internal(m, &m->rules_foreign, rule, rule->family, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link) {
|
||||||
|
assert(rule);
|
||||||
|
assert(IN_SET(family, AF_INET, AF_INET6));
|
||||||
|
assert(str);
|
||||||
|
|
||||||
|
/* link may be NULL. */
|
||||||
|
|
||||||
|
if (DEBUG_LOGGING) {
|
||||||
|
_cleanup_free_ char *from = NULL, *to = NULL;
|
||||||
|
|
||||||
|
(void) in_addr_to_string(family, &rule->from, &from);
|
||||||
|
(void) in_addr_to_string(family, &rule->to, &to);
|
||||||
|
|
||||||
|
log_link_debug(link,
|
||||||
|
"%s routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
||||||
|
str, rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen,
|
||||||
|
strna(rule->iif), strna(rule->oif), rule->table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) {
|
static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_netlink_message *m, Link *link) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(rule);
|
assert(rule);
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(link);
|
|
||||||
|
/* link may be NULL. */
|
||||||
|
|
||||||
if (in_addr_is_null(rule->family, &rule->from) == 0) {
|
if (in_addr_is_null(rule->family, &rule->from) == 0) {
|
||||||
r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
|
r = netlink_message_append_in_addr_union(m, FRA_SRC, rule->family, &rule->from);
|
||||||
@ -447,62 +478,42 @@ static int routing_policy_rule_set_netlink_message(RoutingPolicyRule *rule, sd_n
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(link);
|
|
||||||
assert(link->ifname);
|
|
||||||
|
|
||||||
link->routing_policy_rule_remove_messages--;
|
|
||||||
|
|
||||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
r = sd_netlink_message_get_errno(m);
|
r = sd_netlink_message_get_errno(m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_link_message_warning_errno(link, m, r, "Could not drop routing policy rule");
|
log_message_warning_errno(m, r, "Could not drop routing policy rule");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int routing_policy_rule_remove(RoutingPolicyRule *rule, Link *link) {
|
static int routing_policy_rule_remove(RoutingPolicyRule *rule, Manager *manager) {
|
||||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(rule);
|
assert(rule);
|
||||||
assert(link);
|
assert(manager);
|
||||||
assert(link->manager);
|
assert(manager->rtnl);
|
||||||
assert(link->manager->rtnl);
|
|
||||||
assert(link->ifindex > 0);
|
|
||||||
assert(IN_SET(rule->family, AF_INET, AF_INET6));
|
assert(IN_SET(rule->family, AF_INET, AF_INET6));
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
log_routing_policy_rule_debug(rule, rule->family, "Removing", NULL);
|
||||||
_cleanup_free_ char *from = NULL, *to = NULL;
|
|
||||||
|
|
||||||
(void) in_addr_to_string(rule->family, &rule->from, &from);
|
r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family);
|
||||||
(void) in_addr_to_string(rule->family, &rule->to, &to);
|
|
||||||
|
|
||||||
log_link_debug(link,
|
|
||||||
"Removing routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
|
||||||
rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_DELRULE, rule->family);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not allocate RTM_DELRULE message: %m");
|
return log_error_errno(r, "Could not allocate RTM_DELRULE message: %m");
|
||||||
|
|
||||||
r = routing_policy_rule_set_netlink_message(rule, m, link);
|
r = routing_policy_rule_set_netlink_message(rule, m, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = netlink_call_async(link->manager->rtnl, NULL, m,
|
r = sd_netlink_call_async(manager->rtnl, NULL, m,
|
||||||
routing_policy_rule_remove_handler,
|
routing_policy_rule_remove_handler,
|
||||||
link_netlink_destroy_callback, link);
|
NULL, NULL, 0, __func__);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
|
return log_error_errno(r, "Could not send rtnetlink message: %m");
|
||||||
|
|
||||||
link_ref(link);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -547,16 +558,7 @@ static int routing_policy_rule_configure_internal(RoutingPolicyRule *rule, int f
|
|||||||
assert(link->manager);
|
assert(link->manager);
|
||||||
assert(link->manager->rtnl);
|
assert(link->manager->rtnl);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
log_routing_policy_rule_debug(rule, family, "Configuring", link);
|
||||||
_cleanup_free_ char *from = NULL, *to = NULL;
|
|
||||||
|
|
||||||
(void) in_addr_to_string(family, &rule->from, &from);
|
|
||||||
(void) in_addr_to_string(family, &rule->to, &to);
|
|
||||||
|
|
||||||
log_link_debug(link,
|
|
||||||
"Configuring routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
|
||||||
rule->priority, strna(from), rule->from_prefixlen, strna(to), rule->to_prefixlen, strna(rule->iif), strna(rule->oif), rule->table);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
|
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -616,19 +618,18 @@ static bool manager_links_have_routing_policy_rule(Manager *m, RoutingPolicyRule
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
HASHMAP_FOREACH(link_rule, link->network->rules_by_section)
|
HASHMAP_FOREACH(link_rule, link->network->rules_by_section)
|
||||||
if (routing_policy_rule_compare_func(link_rule, rule) == 0)
|
if (routing_policy_rule_equal(link_rule, rule))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void routing_policy_rule_purge(Manager *m, Link *link) {
|
static void routing_policy_rule_purge(Manager *m) {
|
||||||
RoutingPolicyRule *rule;
|
RoutingPolicyRule *rule;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(link);
|
|
||||||
|
|
||||||
SET_FOREACH(rule, m->rules_saved) {
|
SET_FOREACH(rule, m->rules_saved) {
|
||||||
RoutingPolicyRule *existing;
|
RoutingPolicyRule *existing;
|
||||||
@ -643,14 +644,12 @@ static void routing_policy_rule_purge(Manager *m, Link *link) {
|
|||||||
/* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
|
/* Existing links do not have the saved rule. Let's drop the rule now, and re-configure it
|
||||||
* later when it is requested. */
|
* later when it is requested. */
|
||||||
|
|
||||||
r = routing_policy_rule_remove(existing, link);
|
r = routing_policy_rule_remove(existing, m);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_warning_errno(r, "Could not remove routing policy rules: %m");
|
log_warning_errno(r, "Could not remove routing policy rules: %m");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
link->routing_policy_rule_remove_messages++;
|
|
||||||
|
|
||||||
assert_se(set_remove(m->rules_foreign, existing) == existing);
|
assert_se(set_remove(m->rules_foreign, existing) == existing);
|
||||||
routing_policy_rule_free(existing);
|
routing_policy_rule_free(existing);
|
||||||
}
|
}
|
||||||
@ -690,7 +689,7 @@ int link_set_routing_policy_rules(Link *link) {
|
|||||||
return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
|
return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
routing_policy_rule_purge(link->manager, link);
|
routing_policy_rule_purge(link->manager);
|
||||||
if (link->routing_policy_rule_messages == 0)
|
if (link->routing_policy_rule_messages == 0)
|
||||||
link->routing_policy_rules_configured = true;
|
link->routing_policy_rules_configured = true;
|
||||||
else {
|
else {
|
||||||
@ -703,7 +702,6 @@ int link_set_routing_policy_rules(Link *link) {
|
|||||||
|
|
||||||
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||||
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
|
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
|
||||||
_cleanup_free_ char *from = NULL, *to = NULL;
|
|
||||||
RoutingPolicyRule *rule = NULL;
|
RoutingPolicyRule *rule = NULL;
|
||||||
const char *iif = NULL, *oif = NULL;
|
const char *iif = NULL, *oif = NULL;
|
||||||
uint32_t suppress_prefixlen;
|
uint32_t suppress_prefixlen;
|
||||||
@ -746,63 +744,28 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tmp->family) {
|
r = netlink_message_read_in_addr_union(message, FRA_SRC, tmp->family, &tmp->from);
|
||||||
case AF_INET:
|
if (r < 0 && r != -ENODATA) {
|
||||||
r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in);
|
log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
|
||||||
if (r < 0 && r != -ENODATA) {
|
return 0;
|
||||||
log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
|
} else if (r >= 0) {
|
||||||
|
r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (r >= 0) {
|
|
||||||
r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in);
|
r = netlink_message_read_in_addr_union(message, FRA_DST, tmp->family, &tmp->to);
|
||||||
if (r < 0 && r != -ENODATA) {
|
if (r < 0 && r != -ENODATA) {
|
||||||
log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
|
log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
|
||||||
|
return 0;
|
||||||
|
} else if (r >= 0) {
|
||||||
|
r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
|
||||||
return 0;
|
return 0;
|
||||||
} else if (r >= 0) {
|
|
||||||
r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AF_INET6:
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &tmp->from.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_warning_errno(r, "rtnl: could not get FRA_SRC attribute, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (r >= 0) {
|
|
||||||
r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: received rule message without valid source prefix length, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_netlink_message_read_in6_addr(message, FRA_DST, &tmp->to.in6);
|
|
||||||
if (r < 0 && r != -ENODATA) {
|
|
||||||
log_warning_errno(r, "rtnl: could not get FRA_DST attribute, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
} else if (r >= 0) {
|
|
||||||
r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
|
|
||||||
if (r < 0) {
|
|
||||||
log_warning_errno(r, "rtnl: received rule message without valid destination prefix length, ignoring: %m");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert_not_reached("Received rule message with unsupported address family");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
|
r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
|
||||||
@ -894,19 +857,12 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
|
|||||||
|
|
||||||
(void) routing_policy_rule_get(m, tmp, &rule);
|
(void) routing_policy_rule_get(m, tmp, &rule);
|
||||||
|
|
||||||
if (DEBUG_LOGGING) {
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->from, &from);
|
|
||||||
(void) in_addr_to_string(tmp->family, &tmp->to, &to);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case RTM_NEWRULE:
|
case RTM_NEWRULE:
|
||||||
if (rule)
|
if (rule)
|
||||||
log_debug("Received remembered routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL);
|
||||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
|
||||||
else {
|
else {
|
||||||
log_debug("Remembering foreign routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL);
|
||||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
|
||||||
r = routing_policy_rule_add_foreign(m, tmp, &rule);
|
r = routing_policy_rule_add_foreign(m, tmp, &rule);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
|
log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
|
||||||
@ -916,12 +872,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
|
|||||||
break;
|
break;
|
||||||
case RTM_DELRULE:
|
case RTM_DELRULE:
|
||||||
if (rule) {
|
if (rule) {
|
||||||
log_debug("Forgetting routing policy rule: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32,
|
log_routing_policy_rule_debug(tmp, tmp->family, "Forgetting", NULL);
|
||||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
|
||||||
routing_policy_rule_free(rule);
|
routing_policy_rule_free(rule);
|
||||||
} else
|
} else
|
||||||
log_debug("Kernel removed a routing policy rule we don't remember: priority: %"PRIu32", %s/%u -> %s/%u, iif: %s, oif: %s, table: %"PRIu32", ignoring.",
|
log_routing_policy_rule_debug(tmp, tmp->family, "Kernel removed unknown", NULL);
|
||||||
tmp->priority, strna(from), tmp->from_prefixlen, strna(to), tmp->to_prefixlen, strna(tmp->iif), strna(tmp->oif), tmp->table);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -124,5 +124,10 @@ int manager_parse_config_file(Manager *m) {
|
|||||||
m->poll_interval_max_usec = MAX(NTP_POLL_INTERVAL_MAX_USEC, m->poll_interval_min_usec * 32);
|
m->poll_interval_max_usec = MAX(NTP_POLL_INTERVAL_MAX_USEC, m->poll_interval_min_usec * 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m->connection_retry_usec < 1 * USEC_PER_SEC) {
|
||||||
|
log_warning("Invalid ConnectionRetrySec=. Using default value.");
|
||||||
|
m->connection_retry_usec = DEFAULT_CONNECTION_RETRY_USEC;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,10 @@ struct ConfigPerfItem;
|
|||||||
%struct-type
|
%struct-type
|
||||||
%includes
|
%includes
|
||||||
%%
|
%%
|
||||||
Time.NTP, config_parse_servers, SERVER_SYSTEM, 0
|
Time.NTP, config_parse_servers, SERVER_SYSTEM, 0
|
||||||
Time.Servers, config_parse_servers, SERVER_SYSTEM, 0
|
Time.Servers, config_parse_servers, SERVER_SYSTEM, 0
|
||||||
Time.FallbackNTP, config_parse_servers, SERVER_FALLBACK, 0
|
Time.FallbackNTP, config_parse_servers, SERVER_FALLBACK, 0
|
||||||
Time.RootDistanceMaxSec, config_parse_sec, 0, offsetof(Manager, max_root_distance_usec)
|
Time.RootDistanceMaxSec, config_parse_sec, 0, offsetof(Manager, max_root_distance_usec)
|
||||||
Time.PollIntervalMinSec, config_parse_sec, 0, offsetof(Manager, poll_interval_min_usec)
|
Time.PollIntervalMinSec, config_parse_sec, 0, offsetof(Manager, poll_interval_min_usec)
|
||||||
Time.PollIntervalMaxSec, config_parse_sec, 0, offsetof(Manager, poll_interval_max_usec)
|
Time.PollIntervalMaxSec, config_parse_sec, 0, offsetof(Manager, poll_interval_max_usec)
|
||||||
|
Time.ConnectionRetrySec, config_parse_sec, 0, offsetof(Manager, connection_retry_usec)
|
||||||
|
|||||||
@ -50,7 +50,6 @@
|
|||||||
/* Maximum number of missed replies before selecting another source. */
|
/* Maximum number of missed replies before selecting another source. */
|
||||||
#define NTP_MAX_MISSED_REPLIES 2
|
#define NTP_MAX_MISSED_REPLIES 2
|
||||||
|
|
||||||
#define RETRY_USEC (30*USEC_PER_SEC)
|
|
||||||
#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
|
#define RATELIMIT_INTERVAL_USEC (10*USEC_PER_SEC)
|
||||||
#define RATELIMIT_BURST 10
|
#define RATELIMIT_BURST 10
|
||||||
|
|
||||||
@ -787,7 +786,8 @@ int manager_connect(Manager *m) {
|
|||||||
if (!ratelimit_below(&m->ratelimit)) {
|
if (!ratelimit_below(&m->ratelimit)) {
|
||||||
log_debug("Delaying attempts to contact servers.");
|
log_debug("Delaying attempts to contact servers.");
|
||||||
|
|
||||||
r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), RETRY_USEC, 0, manager_retry_connect, m);
|
r = sd_event_add_time_relative(m->event, &m->event_retry, clock_boottime_or_monotonic(), m->connection_retry_usec,
|
||||||
|
0, manager_retry_connect, m);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to create retry timer: %m");
|
return log_error_errno(r, "Failed to create retry timer: %m");
|
||||||
|
|
||||||
@ -1085,6 +1085,8 @@ int manager_new(Manager **ret) {
|
|||||||
m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
|
m->poll_interval_min_usec = NTP_POLL_INTERVAL_MIN_USEC;
|
||||||
m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC;
|
m->poll_interval_max_usec = NTP_POLL_INTERVAL_MAX_USEC;
|
||||||
|
|
||||||
|
m->connection_retry_usec = DEFAULT_CONNECTION_RETRY_USEC;
|
||||||
|
|
||||||
m->server_socket = m->clock_watch_fd = -1;
|
m->server_socket = m->clock_watch_fd = -1;
|
||||||
|
|
||||||
m->ratelimit = (RateLimit) { RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST };
|
m->ratelimit = (RateLimit) { RATELIMIT_INTERVAL_USEC, RATELIMIT_BURST };
|
||||||
|
|||||||
@ -27,6 +27,8 @@ typedef struct Manager Manager;
|
|||||||
#define NTP_RETRY_INTERVAL_MIN_USEC (15 * USEC_PER_SEC)
|
#define NTP_RETRY_INTERVAL_MIN_USEC (15 * USEC_PER_SEC)
|
||||||
#define NTP_RETRY_INTERVAL_MAX_USEC (6 * 60 * USEC_PER_SEC) /* 6 minutes */
|
#define NTP_RETRY_INTERVAL_MAX_USEC (6 * 60 * USEC_PER_SEC) /* 6 minutes */
|
||||||
|
|
||||||
|
#define DEFAULT_CONNECTION_RETRY_USEC (30*USEC_PER_SEC)
|
||||||
|
|
||||||
struct Manager {
|
struct Manager {
|
||||||
sd_bus *bus;
|
sd_bus *bus;
|
||||||
sd_event *event;
|
sd_event *event;
|
||||||
@ -60,6 +62,7 @@ struct Manager {
|
|||||||
struct timespec trans_time_mon;
|
struct timespec trans_time_mon;
|
||||||
struct timespec trans_time;
|
struct timespec trans_time;
|
||||||
usec_t retry_interval;
|
usec_t retry_interval;
|
||||||
|
usec_t connection_retry_usec;
|
||||||
bool pending;
|
bool pending;
|
||||||
|
|
||||||
/* poll timer */
|
/* poll timer */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user