if (r < 0)
return -ENOMEM;
+ r = asprintf(&link->lease_file, "/run/systemd/network/leases/%"PRIu64,
+ link->ifindex);
+ if (r < 0)
+ return -ENOMEM;
+
r = hashmap_put(manager->links, &link->ifindex, link);
if (r < 0)
return r;
sd_dhcp_client_unref(link->dhcp_client);
sd_dhcp_lease_unref(link->dhcp_lease);
+ unlink(link->lease_file);
+ free(link->lease_file);
+
sd_ipv4ll_unref(link->ipv4ll);
hashmap_remove(link->manager->links, &link->ifindex);
free(link->ifname);
+
+ unlink(link->state_file);
free(link->state_file);
udev_device_unref(link->udev_device);
return 0;
}
+bool link_has_carrier(unsigned flags, uint8_t operstate) {
+ /* see Documentation/networking/operstates.txt in the kernel sources */
+
+ if (operstate == IF_OPER_UP)
+ return true;
+
+ if (operstate == IF_OPER_UNKNOWN)
+ /* operstate may not be implemented, so fall back to flags */
+ if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT))
+ return true;
+
+ return false;
+}
+
static int link_update_flags(Link *link, sd_rtnl_message *m) {
unsigned flags, flags_added, flags_removed, generic_flags;
uint8_t operstate;
assert(link);
- if (link->state == LINK_STATE_FAILED)
- return 0;
-
r = sd_rtnl_message_link_get_flags(m, &flags);
if (r < 0) {
log_warning_link(link, "Could not get link flags");
link->flags = flags;
link->operstate = operstate;
+ link_save(link);
+
+ if (link->state == LINK_STATE_FAILED ||
+ link->state == LINK_STATE_UNMANAGED)
+ return 0;
+
if (carrier_gained) {
log_info_link(link, "gained carrier");
}
}
- if (link_has_carrier(link->flags, link->operstate))
- {
+ if (link_has_carrier(link->flags, link->operstate)) {
r = link_acquire_conf(link);
if (r < 0)
return r;
assert(link->ifname);
assert(m);
- if (link->state == LINK_STATE_FAILED || link->state == LINK_STATE_UNMANAGED)
- return 0;
-
r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
if (r >= 0 && !streq(ifname, link->ifname)) {
log_info_link(link, "renamed to %s", ifname);
int link_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *state;
+ const char *admin_state, *oper_state = "unknown";
int r;
assert(link);
assert(link->state_file);
+ assert(link->lease_file);
+ assert(link->manager);
- state = link_state_to_string(link->state);
- assert(state);
+ r = manager_save(link->manager);
+ if (r < 0)
+ return r;
+
+ admin_state = link_state_to_string(link->state);
+ assert(admin_state);
+
+ if (link->operstate == IF_OPER_DORMANT)
+ oper_state = "dormant";
+ else if (link_has_carrier(link->flags, link->operstate))
+ oper_state = "carrier";
r = fopen_temporary(link->state_file, &f, &temp_path);
if (r < 0)
fprintf(f,
"# This is private data. Do not parse.\n"
- "STATE=%s\n", state);
+ "ADMIN_STATE=%s\n"
+ "OPER_STATE=%s\n"
+ "FLAGS=%u\n",
+ admin_state, oper_state, link->flags);
if (link->dhcp_lease) {
- _cleanup_free_ char *lease_file = NULL;
-
- r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
- link->ifindex);
- if (r < 0)
- return -ENOMEM;
-
- r = dhcp_lease_save(link->dhcp_lease, lease_file);
+ r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
if (r < 0)
goto finish;
- fprintf(f, "DHCP_LEASE=%s\n", lease_file);
- }
+ fprintf(f, "DHCP_LEASE=%s\n", link->lease_file);
+ } else
+ unlink(link->lease_file);
fflush(f);
finish:
if (r < 0)
- log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
+ log_error("Failed to save link data to %s: %s", link->state_file, strerror(-r));
return r;
}
static const char* const link_state_table[_LINK_STATE_MAX] = {
- [LINK_STATE_INITIALIZING] = "configuring",
+ [LINK_STATE_INITIALIZING] = "initializing",
[LINK_STATE_ENSLAVING] = "configuring",
[LINK_STATE_SETTING_ADDRESSES] = "configuring",
[LINK_STATE_SETTING_ROUTES] = "configuring",