#include "local-addresses.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "networkd-link-bus.h"
#include "networkd-manager.h"
+#include "networkd-speed-meter.h"
#include "ordered-set.h"
#include "path-util.h"
#include "set.h"
}
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
- uint8_t tos = 0, to_prefixlen = 0, from_prefixlen = 0, protocol = 0;
- struct fib_rule_port_range sport = {}, dport = {};
- union in_addr_union to = IN_ADDR_NULL, from = IN_ADDR_NULL;
+ _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
RoutingPolicyRule *rule = NULL;
- uint32_t fwmark = 0, table = 0;
const char *iif = NULL, *oif = NULL;
Manager *m = userdata;
+ unsigned flags;
uint16_t type;
- int family;
int r;
assert(rtnl);
return 0;
}
- r = sd_rtnl_message_get_family(message, &family);
+ r = routing_policy_rule_new(&tmp);
+ if (r < 0) {
+ log_oom();
+ return 0;
+ }
+
+ r = sd_rtnl_message_get_family(message, &tmp->family);
if (r < 0) {
log_warning_errno(r, "rtnl: could not get rule family, ignoring: %m");
return 0;
- } else if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_debug("rtnl: received address with invalid family %u, ignoring", family);
+ } else if (!IN_SET(tmp->family, AF_INET, AF_INET6)) {
+ log_debug("rtnl: received address with invalid family %u, ignoring", tmp->family);
return 0;
}
- switch (family) {
+ switch (tmp->family) {
case AF_INET:
- r = sd_netlink_message_read_in_addr(message, FRA_SRC, &from.in);
+ r = sd_netlink_message_read_in_addr(message, FRA_SRC, &tmp->from.in);
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, &from_prefixlen);
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: failed to retrieve rule from prefix length, ignoring: %m");
return 0;
}
}
- r = sd_netlink_message_read_in_addr(message, FRA_DST, &to.in);
+ r = sd_netlink_message_read_in_addr(message, FRA_DST, &tmp->to.in);
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, &to_prefixlen);
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: failed to retrieve rule to prefix length, ignoring: %m");
return 0;
break;
case AF_INET6:
- r = sd_netlink_message_read_in6_addr(message, FRA_SRC, &from.in6);
+ 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, &from_prefixlen);
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(message, &tmp->from_prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: failed to retrieve rule from prefix length, ignoring: %m");
return 0;
}
}
- r = sd_netlink_message_read_in6_addr(message, FRA_DST, &to.in6);
+ 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, &to_prefixlen);
+ r = sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(message, &tmp->to_prefixlen);
if (r < 0) {
log_warning_errno(r, "rtnl: failed to retrieve rule to prefix length, ignoring: %m");
return 0;
assert_not_reached("Received unsupported address family");
}
- if (from_prefixlen == 0 && to_prefixlen == 0)
+ if (tmp->from_prefixlen == 0 && tmp->to_prefixlen == 0)
return 0;
- r = sd_netlink_message_read_u32(message, FRA_FWMARK, &fwmark);
+ r = sd_rtnl_message_routing_policy_rule_get_flags(message, &flags);
+ if (r < 0) {
+ log_warning_errno(r, "rtnl: could not get flag, ignoring: %m");
+ return 0;
+ }
+ tmp->invert_rule = flags & FIB_RULE_INVERT;
+
+ r = sd_netlink_message_read_u32(message, FRA_FWMARK, &tmp->fwmark);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_FWMARK attribute, ignoring: %m");
return 0;
}
- r = sd_netlink_message_read_u32(message, FRA_TABLE, &table);
+ r = sd_netlink_message_read_u32(message, FRA_FWMASK, &tmp->fwmask);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_FWMASK attribute, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_u32(message, FRA_PRIORITY, &tmp->priority);
+ if (r < 0 && r != -ENODATA) {
+ log_warning_errno(r, "rtnl: could not get FRA_PRIORITY attribute, ignoring: %m");
+ return 0;
+ }
+
+ r = sd_netlink_message_read_u32(message, FRA_TABLE, &tmp->table);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_TABLE attribute, ignoring: %m");
return 0;
}
- r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tos);
+ r = sd_rtnl_message_routing_policy_rule_get_tos(message, &tmp->tos);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get ip rule TOS, ignoring: %m");
return 0;
log_warning_errno(r, "rtnl: could not get FRA_IIFNAME attribute, ignoring: %m");
return 0;
}
+ r = free_and_strdup(&tmp->iif, iif);
+ if (r < 0)
+ return log_oom();
r = sd_netlink_message_read_string(message, FRA_OIFNAME, &oif);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_OIFNAME attribute, ignoring: %m");
return 0;
}
+ r = free_and_strdup(&tmp->oif, oif);
+ if (r < 0)
+ return log_oom();
- r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &protocol);
+ r = sd_netlink_message_read_u8(message, FRA_IP_PROTO, &tmp->protocol);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_IP_PROTO attribute, ignoring: %m");
return 0;
}
- r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(sport), (void *) &sport);
+ r = sd_netlink_message_read(message, FRA_SPORT_RANGE, sizeof(tmp->sport), &tmp->sport);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_SPORT_RANGE attribute, ignoring: %m");
return 0;
}
- r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(dport), (void *) &dport);
+ r = sd_netlink_message_read(message, FRA_DPORT_RANGE, sizeof(tmp->dport), &tmp->dport);
if (r < 0 && r != -ENODATA) {
log_warning_errno(r, "rtnl: could not get FRA_DPORT_RANGE attribute, ignoring: %m");
return 0;
}
- (void) routing_policy_rule_get(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, &sport, &dport, &rule);
+ (void) routing_policy_rule_get(m, tmp, &rule);
switch (type) {
case RTM_NEWRULE:
if (!rule) {
- r = routing_policy_rule_add_foreign(m, family, &from, from_prefixlen, &to, to_prefixlen, tos, fwmark, table, iif, oif, protocol, &sport, &dport, &rule);
+ r = routing_policy_rule_add_foreign(m, tmp, &rule);
if (r < 0) {
log_warning_errno(r, "Could not add rule, ignoring: %m");
return 0;
Link *link;
Iterator i;
_cleanup_free_ char *temp_path = NULL;
+ _cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
- const char *operstate_str;
+ LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
+ LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
+ const char *operstate_str, *carrier_state_str, *address_state_str;
int r;
assert(m);
if (link->operstate > operstate)
operstate = link->operstate;
+ if (link->carrier_state > carrier_state)
+ carrier_state = link->carrier_state;
+
+ if (link->address_state > address_state)
+ address_state = link->address_state;
+
if (!link->network)
continue;
}
}
+ if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
+ carrier_state = LINK_CARRIER_STATE_CARRIER;
+
operstate_str = link_operstate_to_string(operstate);
assert(operstate_str);
+ carrier_state_str = link_carrier_state_to_string(carrier_state);
+ assert(carrier_state_str);
+
+ address_state_str = link_address_state_to_string(address_state);
+ assert(address_state_str);
+
r = fopen_temporary(m->state_file, &f, &temp_path);
if (r < 0)
return r;
fprintf(f,
"# This is private data. Do not parse.\n"
- "OPER_STATE=%s\n", operstate_str);
+ "OPER_STATE=%s\n"
+ "CARRIER_STATE=%s\n"
+ "ADDRESS_STATE=%s\n",
+ operstate_str, carrier_state_str, address_state_str);
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
if (m->operational_state != operstate) {
m->operational_state = operstate;
- r = manager_send_changed(m, "OperationalState", NULL);
+ if (strv_extend(&p, "OperationalState") < 0)
+ log_oom();
+ }
+
+ if (m->carrier_state != carrier_state) {
+ m->carrier_state = carrier_state;
+ if (strv_extend(&p, "CarrierState") < 0)
+ log_oom();
+ }
+
+ if (m->address_state != address_state) {
+ m->address_state = address_state;
+ if (strv_extend(&p, "AddressState") < 0)
+ log_oom();
+ }
+
+ if (p) {
+ r = manager_send_changed_strv(m, p);
if (r < 0)
- log_error_errno(r, "Could not emit changed OperationalState: %m");
+ log_error_errno(r, "Could not emit changed properties: %m");
}
m->dirty = false;
_cleanup_(manager_freep) Manager *m = NULL;
int r;
- m = new0(Manager, 1);
+ m = new(Manager, 1);
if (!m)
return -ENOMEM;
+ *m = (Manager) {
+ .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
+ };
+
m->state_file = strdup("/run/systemd/netif/state");
if (!m->state_file)
return -ENOMEM;
- m->sysctl_ipv6_enabled = -1;
-
r = sd_event_default(&m->event);
if (r < 0)
return r;
if (link->dhcp6_client)
(void) dhcp6_lease_pd_prefix_lost(link->dhcp6_client, link);
- link_stop_clients(link);
+ (void) link_stop_clients(link, true);
link_unref(link);
}
sd_netlink_unref(m->genl);
sd_resolve_unref(m->resolve);
+ sd_event_source_unref(m->speed_meter_event_source);
sd_event_unref(m->event);
sd_device_monitor_unref(m->device_monitor);
int manager_start(Manager *m) {
Link *link;
Iterator i;
+ int r;
assert(m);
+ r = manager_start_speed_meter(m);
+ if (r < 0)
+ return log_error_errno(r, "Failed to initialize speed meter: %m");
+
/* The dirty handler will deal with future serialization, but the first one
must be done explicitly. */
return 0;
}
-
-int manager_sysctl_ipv6_enabled(Manager *manager) {
- _cleanup_free_ char *value = NULL;
- int r;
-
- if (manager->sysctl_ipv6_enabled >= 0)
- return manager->sysctl_ipv6_enabled;
-
- r = sysctl_read_ip_property(AF_INET6, "all", "disable_ipv6", &value);
- if (r < 0)
- return log_warning_errno(r, "Failed to read net.ipv6.conf.all.disable_ipv6 sysctl property: %m");
-
- manager->sysctl_ipv6_enabled = value[0] == '0';
- return manager->sysctl_ipv6_enabled;
-}