+ TODO: use proper operstates once we start supporting 802.1X
+
+ see Documentation/networking/operstates.txt in the kernel sources
+ */
+ carrier_gained = (((flags_added & IFF_LOWER_UP) && !(flags & IFF_DORMANT)) ||
+ ((flags_removed & IFF_DORMANT) && (flags & IFF_LOWER_UP)));
+ carrier_lost = ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT)) &&
+ ((flags_removed & IFF_LOWER_UP) || (flags_added & IFF_DORMANT));
+
+ link->flags = flags;
+
+ if (!link->network)
+ /* not currently managing this link
+ we track state changes, but don't log them
+ they will be logged if and when a network is
+ applied */
+ return 0;
+
+ if (flags_added & IFF_UP)
+ log_info_link(link, "link is up");
+ else if (flags_removed & IFF_UP)
+ log_info_link(link, "link is down");
+
+ if (flags_added & IFF_LOWER_UP)
+ log_debug_link(link, "link is lower up");
+ else if (flags_removed & IFF_LOWER_UP)
+ log_debug_link(link, "link is lower down");
+
+ if (flags_added & IFF_DORMANT)
+ log_debug_link(link, "link is dormant");
+ else if (flags_removed & IFF_DORMANT)
+ log_debug_link(link, "link is not dormant");
+
+ if (flags_added & IFF_DEBUG)
+ log_debug_link(link, "debugging enabled in the kernel");
+ else if (flags_removed & IFF_DEBUG)
+ log_debug_link(link, "debugging disabled in the kernel");
+
+ if (flags_added & IFF_MULTICAST)
+ log_debug_link(link, "multicast enabled");
+ else if (flags_removed & IFF_MULTICAST)
+ log_debug_link(link, "multicast disabled");
+
+ if (flags_added & IFF_BROADCAST)
+ log_debug_link(link, "broadcast enabled");
+ else if (flags_removed & IFF_BROADCAST)
+ log_debug_link(link, "broadcast disabled");
+
+ if (flags_added & IFF_PROMISC)
+ log_debug_link(link, "promiscuous mode enabled");
+ else if (flags_removed & IFF_PROMISC)
+ log_debug_link(link, "promiscuous mode disabled");
+
+ if (flags_added & IFF_NOARP)
+ log_debug_link(link, "ARP protocol disabled");
+ else if (flags_removed & IFF_NOARP)
+ log_debug_link(link, "ARP protocol enabled");
+
+ if (flags_added & IFF_MASTER)
+ log_debug_link(link, "link is master");
+ else if (flags_removed & IFF_MASTER)
+ log_debug_link(link, "link is no longer master");
+
+ if (flags_added & IFF_SLAVE)
+ log_debug_link(link, "link is slave");
+ else if (flags_removed & IFF_SLAVE)
+ log_debug_link(link, "link is no longer slave");
+
+ /* link flags are currently at most 18 bits, let's default to printing 20 */
+ if (flags_added & generic_flags)
+ log_debug_link(link, "unknown link flags gained: %#.5x (ignoring)",
+ flags_added & generic_flags);
+
+ if (flags_removed & generic_flags)
+ log_debug_link(link, "unknown link flags lost: %#.5x (ignoring)",
+ flags_removed & generic_flags);
+
+ if (carrier_gained) {
+ log_info_link(link, "gained carrier");
+
+ if (link->network->dhcp || link->network->ipv4ll) {
+ r = link_acquire_conf(link);
+ if (r < 0) {
+ log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
+ link_enter_failed(link);
+ return r;
+ }
+ }
+ } else if (carrier_lost) {
+ log_info_link(link, "lost carrier");
+
+ if (link->network->dhcp) {
+ r = sd_dhcp_client_stop(link->dhcp_client);
+ if (r < 0) {
+ log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
+ link_enter_failed(link);
+ return r;