LCOV - code coverage report
Current view: top level - network - networkd-link.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 193 1347 14.3 %
Date: 2015-07-29 18:47:03 Functions: 14 74 18.9 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2013 Tom Gundersen <teg@jklm.no>
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : #include <netinet/ether.h>
      23             : #include <linux/if.h>
      24             : #include <unistd.h>
      25             : 
      26             : #include "util.h"
      27             : #include "virt.h"
      28             : #include "fileio.h"
      29             : #include "socket-util.h"
      30             : #include "bus-util.h"
      31             : #include "udev-util.h"
      32             : #include "network-internal.h"
      33             : #include "networkd-link.h"
      34             : #include "networkd-netdev.h"
      35             : 
      36           0 : bool link_dhcp6_enabled(Link *link) {
      37           0 :         if (link->flags & IFF_LOOPBACK)
      38           0 :                 return false;
      39             : 
      40           0 :         if (!link->network)
      41           0 :                 return false;
      42             : 
      43           0 :         return link->network->dhcp & ADDRESS_FAMILY_IPV6;
      44             : }
      45             : 
      46           0 : bool link_dhcp4_enabled(Link *link) {
      47           0 :         if (link->flags & IFF_LOOPBACK)
      48           0 :                 return false;
      49             : 
      50           0 :         if (!link->network)
      51           0 :                 return false;
      52             : 
      53           0 :         return link->network->dhcp & ADDRESS_FAMILY_IPV4;
      54             : }
      55             : 
      56           0 : bool link_dhcp4_server_enabled(Link *link) {
      57           0 :         if (link->flags & IFF_LOOPBACK)
      58           0 :                 return false;
      59             : 
      60           0 :         if (!link->network)
      61           0 :                 return false;
      62             : 
      63           0 :         return link->network->dhcp_server;
      64             : }
      65             : 
      66           0 : bool link_ipv4ll_enabled(Link *link) {
      67           0 :         if (link->flags & IFF_LOOPBACK)
      68           0 :                 return false;
      69             : 
      70           0 :         if (!link->network)
      71           0 :                 return false;
      72             : 
      73           0 :         return link->network->link_local & ADDRESS_FAMILY_IPV4;
      74             : }
      75             : 
      76           0 : bool link_ipv6ll_enabled(Link *link) {
      77           0 :         if (link->flags & IFF_LOOPBACK)
      78           0 :                 return false;
      79             : 
      80           0 :         if (!link->network)
      81           0 :                 return false;
      82             : 
      83           0 :         return link->network->link_local & ADDRESS_FAMILY_IPV6;
      84             : }
      85             : 
      86           0 : bool link_lldp_enabled(Link *link) {
      87           0 :         if (link->flags & IFF_LOOPBACK)
      88           0 :                 return false;
      89             : 
      90           0 :         if (!link->network)
      91           0 :                 return false;
      92             : 
      93           0 :         if (link->network->bridge)
      94           0 :                 return false;
      95             : 
      96           0 :         return link->network->lldp;
      97             : }
      98             : 
      99           0 : static bool link_ipv4_forward_enabled(Link *link) {
     100           0 :         if (link->flags & IFF_LOOPBACK)
     101           0 :                 return false;
     102             : 
     103           0 :         if (!link->network)
     104           0 :                 return false;
     105             : 
     106           0 :         return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
     107             : }
     108             : 
     109           0 : static bool link_ipv6_forward_enabled(Link *link) {
     110           0 :         if (link->flags & IFF_LOOPBACK)
     111           0 :                 return false;
     112             : 
     113           0 :         if (!link->network)
     114           0 :                 return false;
     115             : 
     116           0 :         return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
     117             : }
     118             : 
     119           0 : static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
     120           0 :         if (link->flags & IFF_LOOPBACK)
     121           0 :                 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
     122             : 
     123           0 :         if (!link->network)
     124           0 :                 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
     125             : 
     126           0 :         return link->network->ipv6_privacy_extensions;
     127             : }
     128             : 
     129             : #define FLAG_STRING(string, flag, old, new) \
     130             :         (((old ^ new) & flag) \
     131             :                 ? ((old & flag) ? (" -" string) : (" +" string)) \
     132             :                 : "")
     133             : 
     134           8 : static int link_update_flags(Link *link, sd_netlink_message *m) {
     135             :         unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
     136             :         uint8_t operstate;
     137             :         int r;
     138             : 
     139           8 :         assert(link);
     140             : 
     141           8 :         r = sd_rtnl_message_link_get_flags(m, &flags);
     142           8 :         if (r < 0)
     143           0 :                 return log_link_warning_errno(link, r, "Could not get link flags: %m");
     144             : 
     145           8 :         r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate);
     146           8 :         if (r < 0)
     147             :                 /* if we got a message without operstate, take it to mean
     148             :                    the state was unchanged */
     149           0 :                 operstate = link->kernel_operstate;
     150             : 
     151           8 :         if ((link->flags == flags) && (link->kernel_operstate == operstate))
     152           4 :                 return 0;
     153             : 
     154           4 :         if (link->flags != flags) {
     155           4 :                 log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
     156             :                                FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
     157             :                                FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
     158             :                                FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
     159             :                                FLAG_STRING("UP", IFF_UP, link->flags, flags),
     160             :                                FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
     161             :                                FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
     162             :                                FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
     163             :                                FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
     164             :                                FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
     165             :                                FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
     166             :                                FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
     167             :                                FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
     168             :                                FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
     169             :                                FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
     170             :                                FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
     171             :                                FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
     172             :                                FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
     173             :                                FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
     174             :                                FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
     175             : 
     176           4 :                 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
     177             :                                   IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
     178             :                                   IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
     179             :                                   IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
     180             :                                   IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
     181             :                                   IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
     182           4 :                 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
     183           4 :                 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
     184             : 
     185             :                 /* link flags are currently at most 18 bits, let's align to
     186             :                  * printing 20 */
     187           4 :                 if (unknown_flags_added)
     188           0 :                         log_link_debug(link,
     189             :                                        "Unknown link flags gained: %#.5x (ignoring)",
     190             :                                        unknown_flags_added);
     191             : 
     192           4 :                 if (unknown_flags_removed)
     193           0 :                         log_link_debug(link,
     194             :                                        "Unknown link flags lost: %#.5x (ignoring)",
     195             :                                        unknown_flags_removed);
     196             :         }
     197             : 
     198           4 :         link->flags = flags;
     199           4 :         link->kernel_operstate = operstate;
     200             : 
     201           4 :         link_save(link);
     202             : 
     203           4 :         return 0;
     204             : }
     205             : 
     206           4 : static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
     207           8 :         _cleanup_link_unref_ Link *link = NULL;
     208             :         uint16_t type;
     209             :         const char *ifname;
     210             :         int r, ifindex;
     211             : 
     212           4 :         assert(manager);
     213           4 :         assert(message);
     214           4 :         assert(ret);
     215             : 
     216           4 :         r = sd_netlink_message_get_type(message, &type);
     217           4 :         if (r < 0)
     218           0 :                 return r;
     219           4 :         else if (type != RTM_NEWLINK)
     220           0 :                 return -EINVAL;
     221             : 
     222           4 :         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
     223           4 :         if (r < 0)
     224           0 :                 return r;
     225           4 :         else if (ifindex <= 0)
     226           0 :                 return -EINVAL;
     227             : 
     228           4 :         r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
     229           4 :         if (r < 0)
     230           0 :                 return r;
     231             : 
     232           4 :         link = new0(Link, 1);
     233           4 :         if (!link)
     234           0 :                 return -ENOMEM;
     235             : 
     236           4 :         link->n_ref = 1;
     237           4 :         link->manager = manager;
     238           4 :         link->state = LINK_STATE_PENDING;
     239           4 :         link->rtnl_extended_attrs = true;
     240           4 :         link->ifindex = ifindex;
     241           4 :         link->ifname = strdup(ifname);
     242           4 :         if (!link->ifname)
     243           0 :                 return -ENOMEM;
     244             : 
     245           4 :         r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
     246           4 :         if (r < 0)
     247           1 :                 log_link_debug(link, "MAC address not found for new device, continuing without");
     248             : 
     249           4 :         r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
     250           4 :                      link->ifindex);
     251           4 :         if (r < 0)
     252           0 :                 return -ENOMEM;
     253             : 
     254           4 :         r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
     255           4 :                      link->ifindex);
     256           4 :         if (r < 0)
     257           0 :                 return -ENOMEM;
     258             : 
     259           4 :         r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
     260           4 :                      link->ifindex);
     261           4 :         if (r < 0)
     262           0 :                 return -ENOMEM;
     263             : 
     264             : 
     265           4 :         r = hashmap_ensure_allocated(&manager->links, NULL);
     266           4 :         if (r < 0)
     267           0 :                 return r;
     268             : 
     269           4 :         r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
     270           4 :         if (r < 0)
     271           0 :                 return r;
     272             : 
     273           4 :         r = link_update_flags(link, message);
     274           4 :         if (r < 0)
     275           0 :                 return r;
     276             : 
     277           4 :         *ret = link;
     278           4 :         link = NULL;
     279             : 
     280           4 :         return 0;
     281             : }
     282             : 
     283           4 : static void link_free(Link *link) {
     284             :         Address *address;
     285             :         Iterator i;
     286             :         Link *carrier;
     287             : 
     288           4 :         if (!link)
     289           0 :                 return;
     290             : 
     291           8 :         while ((address = link->addresses)) {
     292           0 :                 LIST_REMOVE(addresses, link->addresses, address);
     293           0 :                 address_free(address);
     294             :         }
     295             : 
     296           8 :         while ((address = link->pool_addresses)) {
     297           0 :                 LIST_REMOVE(addresses, link->pool_addresses, address);
     298           0 :                 address_free(address);
     299             :         }
     300             : 
     301           4 :         sd_dhcp_server_unref(link->dhcp_server);
     302           4 :         sd_dhcp_client_unref(link->dhcp_client);
     303           4 :         sd_dhcp_lease_unref(link->dhcp_lease);
     304             : 
     305           4 :         free(link->lease_file);
     306             : 
     307           4 :         sd_lldp_free(link->lldp);
     308             : 
     309           4 :         free(link->lldp_file);
     310             : 
     311           4 :         sd_ipv4ll_unref(link->ipv4ll);
     312           4 :         sd_dhcp6_client_unref(link->dhcp6_client);
     313           4 :         sd_icmp6_nd_unref(link->icmp6_router_discovery);
     314             : 
     315           4 :         if (link->manager)
     316           4 :                 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
     317             : 
     318           4 :         free(link->ifname);
     319             : 
     320           4 :         free(link->state_file);
     321             : 
     322           4 :         udev_device_unref(link->udev_device);
     323             : 
     324           8 :         HASHMAP_FOREACH (carrier, link->bound_to_links, i)
     325           0 :                 hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
     326           4 :         hashmap_free(link->bound_to_links);
     327             : 
     328           8 :         HASHMAP_FOREACH (carrier, link->bound_by_links, i)
     329           0 :                 hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
     330           4 :         hashmap_free(link->bound_by_links);
     331             : 
     332           4 :         free(link);
     333             : }
     334             : 
     335           8 : Link *link_unref(Link *link) {
     336           8 :         if (link && (-- link->n_ref <= 0))
     337           4 :                 link_free(link);
     338             : 
     339           8 :         return NULL;
     340             : }
     341             : 
     342           4 : Link *link_ref(Link *link) {
     343           4 :         if (link)
     344           4 :                 assert_se(++ link->n_ref >= 2);
     345             : 
     346           4 :         return link;
     347             : }
     348             : 
     349           4 : int link_get(Manager *m, int ifindex, Link **ret) {
     350             :         Link *link;
     351             : 
     352           4 :         assert(m);
     353           4 :         assert(ifindex);
     354           4 :         assert(ret);
     355             : 
     356           4 :         link = hashmap_get(m->links, INT_TO_PTR(ifindex));
     357           4 :         if (!link)
     358           4 :                 return -ENODEV;
     359             : 
     360           0 :         *ret = link;
     361             : 
     362           0 :         return 0;
     363             : }
     364             : 
     365           0 : static void link_set_state(Link *link, LinkState state) {
     366           0 :         assert(link);
     367             : 
     368           0 :         if (link->state == state)
     369           0 :                 return;
     370             : 
     371           0 :         link->state = state;
     372             : 
     373           0 :         link_send_changed(link, "AdministrativeState", NULL);
     374             : 
     375           0 :         return;
     376             : }
     377             : 
     378           0 : static void link_enter_unmanaged(Link *link) {
     379           0 :         assert(link);
     380             : 
     381           0 :         log_link_debug(link, "Unmanaged");
     382             : 
     383           0 :         link_set_state(link, LINK_STATE_UNMANAGED);
     384             : 
     385           0 :         link_save(link);
     386           0 : }
     387             : 
     388           0 : static int link_stop_clients(Link *link) {
     389           0 :         int r = 0, k;
     390             : 
     391           0 :         assert(link);
     392           0 :         assert(link->manager);
     393           0 :         assert(link->manager->event);
     394             : 
     395           0 :         if (!link->network)
     396           0 :                 return 0;
     397             : 
     398           0 :         if (link->dhcp_client) {
     399           0 :                 k = sd_dhcp_client_stop(link->dhcp_client);
     400           0 :                 if (k < 0)
     401           0 :                         r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
     402             :         }
     403             : 
     404           0 :         if (link->ipv4ll) {
     405           0 :                 k = sd_ipv4ll_stop(link->ipv4ll);
     406           0 :                 if (k < 0)
     407           0 :                         r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
     408             :         }
     409             : 
     410           0 :         if(link->icmp6_router_discovery) {
     411           0 :                 if (link->dhcp6_client) {
     412           0 :                         k = sd_dhcp6_client_stop(link->dhcp6_client);
     413           0 :                         if (k < 0)
     414           0 :                                 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
     415             :                 }
     416             : 
     417           0 :                 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
     418           0 :                 if (k < 0)
     419           0 :                         r = log_link_warning_errno(link, r, "Could not stop ICMPv6 router discovery: %m");
     420             :         }
     421             : 
     422           0 :         if (link->lldp) {
     423           0 :                 k = sd_lldp_stop(link->lldp);
     424           0 :                 if (k < 0)
     425           0 :                         r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
     426             :         }
     427             : 
     428           0 :         return r;
     429             : }
     430             : 
     431           0 : void link_enter_failed(Link *link) {
     432           0 :         assert(link);
     433             : 
     434           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     435           0 :                 return;
     436             : 
     437           0 :         log_link_warning(link, "Failed");
     438             : 
     439           0 :         link_set_state(link, LINK_STATE_FAILED);
     440             : 
     441           0 :         link_stop_clients(link);
     442             : 
     443           0 :         link_save(link);
     444             : }
     445             : 
     446           0 : static Address* link_find_dhcp_server_address(Link *link) {
     447             :         Address *address;
     448             : 
     449           0 :         assert(link);
     450           0 :         assert(link->network);
     451             : 
     452             :         /* The first statically configured address if there is any */
     453           0 :         LIST_FOREACH(addresses, address, link->network->static_addresses) {
     454             : 
     455           0 :                 if (address->family != AF_INET)
     456           0 :                         continue;
     457             : 
     458           0 :                 if (in_addr_is_null(address->family, &address->in_addr))
     459           0 :                         continue;
     460             : 
     461           0 :                 return address;
     462             :         }
     463             : 
     464             :         /* If that didn't work, find a suitable address we got from the pool */
     465           0 :         LIST_FOREACH(addresses, address, link->pool_addresses) {
     466           0 :                 if (address->family != AF_INET)
     467           0 :                         continue;
     468             : 
     469           0 :                 return address;
     470             :         }
     471             : 
     472           0 :         return NULL;
     473             : }
     474             : 
     475           0 : static int link_enter_configured(Link *link) {
     476           0 :         assert(link);
     477           0 :         assert(link->network);
     478           0 :         assert(link->state == LINK_STATE_SETTING_ROUTES);
     479             : 
     480           0 :         log_link_info(link, "Configured");
     481             : 
     482           0 :         link_set_state(link, LINK_STATE_CONFIGURED);
     483             : 
     484           0 :         link_save(link);
     485             : 
     486           0 :         return 0;
     487             : }
     488             : 
     489           0 : void link_client_handler(Link *link) {
     490           0 :         assert(link);
     491           0 :         assert(link->network);
     492             : 
     493           0 :         if (!link->static_configured)
     494           0 :                 return;
     495             : 
     496           0 :         if (link_ipv4ll_enabled(link))
     497           0 :                 if (!link->ipv4ll_address ||
     498           0 :                     !link->ipv4ll_route)
     499           0 :                         return;
     500             : 
     501           0 :         if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
     502           0 :                         return;
     503             : 
     504           0 :         if (link->state != LINK_STATE_CONFIGURED)
     505           0 :                 link_enter_configured(link);
     506             : 
     507           0 :         return;
     508             : }
     509             : 
     510           0 : static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     511           0 :         _cleanup_link_unref_ Link *link = userdata;
     512             :         int r;
     513             : 
     514           0 :         assert(link->link_messages > 0);
     515           0 :         assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
     516             :                       LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
     517             :                       LINK_STATE_LINGER));
     518             : 
     519           0 :         link->link_messages --;
     520             : 
     521           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     522           0 :                 return 1;
     523             : 
     524           0 :         r = sd_netlink_message_get_errno(m);
     525           0 :         if (r < 0 && r != -EEXIST)
     526           0 :                 log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
     527             : 
     528           0 :         if (link->link_messages == 0) {
     529           0 :                 log_link_debug(link, "Routes set");
     530           0 :                 link->static_configured = true;
     531           0 :                 link_client_handler(link);
     532             :         }
     533             : 
     534           0 :         return 1;
     535             : }
     536             : 
     537           0 : static int link_enter_set_routes(Link *link) {
     538             :         Route *rt;
     539             :         int r;
     540             : 
     541           0 :         assert(link);
     542           0 :         assert(link->network);
     543           0 :         assert(link->state == LINK_STATE_SETTING_ADDRESSES);
     544             : 
     545           0 :         link_set_state(link, LINK_STATE_SETTING_ROUTES);
     546             : 
     547           0 :         LIST_FOREACH(routes, rt, link->network->static_routes) {
     548           0 :                 r = route_configure(rt, link, &route_handler);
     549           0 :                 if (r < 0) {
     550           0 :                         log_link_warning_errno(link, r, "Could not set routes: %m");
     551           0 :                         link_enter_failed(link);
     552           0 :                         return r;
     553             :                 }
     554             : 
     555           0 :                 link->link_messages ++;
     556             :         }
     557             : 
     558           0 :         if (link->link_messages == 0) {
     559           0 :                 link->static_configured = true;
     560           0 :                 link_client_handler(link);
     561             :         } else
     562           0 :                 log_link_debug(link, "Setting routes");
     563             : 
     564           0 :         return 0;
     565             : }
     566             : 
     567           0 : int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     568           0 :         _cleanup_link_unref_ Link *link = userdata;
     569             :         int r;
     570             : 
     571           0 :         assert(m);
     572           0 :         assert(link);
     573           0 :         assert(link->ifname);
     574             : 
     575           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     576           0 :                 return 1;
     577             : 
     578           0 :         r = sd_netlink_message_get_errno(m);
     579           0 :         if (r < 0 && r != -ESRCH)
     580           0 :                 log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
     581             : 
     582           0 :         return 1;
     583             : }
     584             : 
     585           0 : static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     586           0 :         _cleanup_link_unref_ Link *link = userdata;
     587             :         int r;
     588             : 
     589           0 :         assert(rtnl);
     590           0 :         assert(m);
     591           0 :         assert(link);
     592           0 :         assert(link->ifname);
     593           0 :         assert(link->link_messages > 0);
     594           0 :         assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
     595             :                LINK_STATE_FAILED, LINK_STATE_LINGER));
     596             : 
     597           0 :         link->link_messages --;
     598             : 
     599           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     600           0 :                 return 1;
     601             : 
     602           0 :         r = sd_netlink_message_get_errno(m);
     603           0 :         if (r < 0 && r != -EEXIST)
     604           0 :                 log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
     605           0 :         else if (r >= 0)
     606           0 :                 link_rtnl_process_address(rtnl, m, link->manager);
     607             : 
     608           0 :         if (link->link_messages == 0) {
     609           0 :                 log_link_debug(link, "Addresses set");
     610           0 :                 link_enter_set_routes(link);
     611             :         }
     612             : 
     613           0 :         return 1;
     614             : }
     615             : 
     616           0 : static int link_enter_set_addresses(Link *link) {
     617             :         Address *ad;
     618             :         int r;
     619             : 
     620           0 :         assert(link);
     621           0 :         assert(link->network);
     622           0 :         assert(link->state != _LINK_STATE_INVALID);
     623             : 
     624           0 :         link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
     625             : 
     626           0 :         LIST_FOREACH(addresses, ad, link->network->static_addresses) {
     627           0 :                 r = address_configure(ad, link, &address_handler);
     628           0 :                 if (r < 0) {
     629           0 :                         log_link_warning_errno(link, r, "Could not set addresses: %m");
     630           0 :                         link_enter_failed(link);
     631           0 :                         return r;
     632             :                 }
     633             : 
     634           0 :                 link->link_messages ++;
     635             :         }
     636             : 
     637             :         /* now that we can figure out a default address for the dhcp server,
     638             :            start it */
     639           0 :         if (link_dhcp4_server_enabled(link)) {
     640             :                 struct in_addr pool_start;
     641             :                 Address *address;
     642             : 
     643           0 :                 address = link_find_dhcp_server_address(link);
     644           0 :                 if (!address) {
     645           0 :                         log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
     646           0 :                         link_enter_failed(link);
     647           0 :                         return 0;
     648             :                 }
     649             : 
     650           0 :                 r = sd_dhcp_server_set_address(link->dhcp_server,
     651             :                                                &address->in_addr.in,
     652           0 :                                                address->prefixlen);
     653           0 :                 if (r < 0)
     654           0 :                         return r;
     655             : 
     656             :                 /* offer 32 addresses starting from the address following the server address */
     657           0 :                 pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
     658           0 :                 r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
     659             :                                                   &pool_start, 32);
     660           0 :                 if (r < 0)
     661           0 :                         return r;
     662             : 
     663             :                 /* TODO:
     664             :                 r = sd_dhcp_server_set_router(link->dhcp_server,
     665             :                                               &main_address->in_addr.in);
     666             :                 if (r < 0)
     667             :                         return r;
     668             : 
     669             :                 r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
     670             :                                                  main_address->prefixlen);
     671             :                 if (r < 0)
     672             :                         return r;
     673             :                 */
     674             : 
     675           0 :                 r = sd_dhcp_server_start(link->dhcp_server);
     676           0 :                 if (r < 0) {
     677           0 :                         log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
     678             : 
     679           0 :                         link_enter_failed(link);
     680             : 
     681           0 :                         return 0;
     682             :                 }
     683             : 
     684           0 :                 log_link_debug(link, "Offering DHCPv4 leases");
     685             :         }
     686             : 
     687           0 :         if (link->link_messages == 0)
     688           0 :                 link_enter_set_routes(link);
     689             :         else
     690           0 :                 log_link_debug(link, "Setting addresses");
     691             : 
     692           0 :         return 0;
     693             : }
     694             : 
     695           0 : int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     696           0 :         _cleanup_link_unref_ Link *link = userdata;
     697             :         int r;
     698             : 
     699           0 :         assert(m);
     700           0 :         assert(link);
     701           0 :         assert(link->ifname);
     702             : 
     703           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     704           0 :                 return 1;
     705             : 
     706           0 :         r = sd_netlink_message_get_errno(m);
     707           0 :         if (r < 0 && r != -EADDRNOTAVAIL)
     708           0 :                 log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
     709             : 
     710           0 :         return 1;
     711             : }
     712             : 
     713           0 : static int link_set_bridge_fdb(Link *const link) {
     714             :         FdbEntry *fdb_entry;
     715           0 :         int r = 0;
     716             : 
     717           0 :         LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
     718           0 :                 r = fdb_entry_configure(link, fdb_entry);
     719           0 :                 if(r < 0) {
     720           0 :                         log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
     721           0 :                         break;
     722             :                 }
     723             :         }
     724             : 
     725           0 :         return r;
     726             : }
     727             : 
     728           0 : static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     729           0 :         _cleanup_link_unref_ Link *link = userdata;
     730             :         int r;
     731             : 
     732           0 :         log_link_debug(link, "Set link");
     733             : 
     734           0 :         r = sd_netlink_message_get_errno(m);
     735           0 :         if (r < 0 && r != -EEXIST) {
     736           0 :                 log_link_error_errno(link, r, "Could not join netdev: %m");
     737           0 :                 link_enter_failed(link);
     738           0 :                 return 1;
     739             :         }
     740             : 
     741           0 :         return 0;
     742             : }
     743             : 
     744           0 : static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
     745           0 :         _cleanup_link_unref_ Link *link = userdata;
     746             :         int r;
     747             : 
     748           0 :         assert(m);
     749           0 :         assert(link);
     750             : 
     751           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     752           0 :                 return 1;
     753             : 
     754           0 :         r = sd_bus_message_get_errno(m);
     755           0 :         if (r > 0)
     756           0 :                 log_link_warning_errno(link, r, "Could not set hostname: %m");
     757             : 
     758           0 :         return 1;
     759             : }
     760             : 
     761           0 : int link_set_hostname(Link *link, const char *hostname) {
     762           0 :         int r = 0;
     763             : 
     764           0 :         assert(link);
     765           0 :         assert(link->manager);
     766           0 :         assert(hostname);
     767             : 
     768           0 :         log_link_debug(link, "Setting transient hostname: '%s'", hostname);
     769             : 
     770           0 :         if (!link->manager->bus) {
     771             :                 /* TODO: replace by assert when we can rely on kdbus */
     772           0 :                 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
     773           0 :                 return 0;
     774             :         }
     775             : 
     776           0 :         r = sd_bus_call_method_async(
     777           0 :                         link->manager->bus,
     778             :                         NULL,
     779             :                         "org.freedesktop.hostname1",
     780             :                         "/org/freedesktop/hostname1",
     781             :                         "org.freedesktop.hostname1",
     782             :                         "SetHostname",
     783             :                         set_hostname_handler,
     784             :                         link,
     785             :                         "sb",
     786             :                         hostname,
     787             :                         false);
     788             : 
     789           0 :         if (r < 0)
     790           0 :                 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
     791             : 
     792           0 :         link_ref(link);
     793             : 
     794           0 :         return 0;
     795             : }
     796             : 
     797           0 : static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     798           0 :         _cleanup_link_unref_ Link *link = userdata;
     799             :         int r;
     800             : 
     801           0 :         assert(m);
     802           0 :         assert(link);
     803           0 :         assert(link->ifname);
     804             : 
     805           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     806           0 :                 return 1;
     807             : 
     808           0 :         r = sd_netlink_message_get_errno(m);
     809           0 :         if (r < 0)
     810           0 :                 log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
     811             : 
     812           0 :         return 1;
     813             : }
     814             : 
     815           0 : int link_set_mtu(Link *link, uint32_t mtu) {
     816           0 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
     817             :         int r;
     818             : 
     819           0 :         assert(link);
     820           0 :         assert(link->manager);
     821           0 :         assert(link->manager->rtnl);
     822             : 
     823           0 :         log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
     824             : 
     825           0 :         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
     826           0 :         if (r < 0)
     827           0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
     828             : 
     829           0 :         r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
     830           0 :         if (r < 0)
     831           0 :                 return log_link_error_errno(link, r, "Could not append MTU: %m");
     832             : 
     833           0 :         r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
     834           0 :         if (r < 0)
     835           0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
     836             : 
     837           0 :         link_ref(link);
     838             : 
     839           0 :         return 0;
     840             : }
     841             : 
     842           0 : static int link_set_bridge(Link *link) {
     843           0 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
     844             :         int r;
     845             : 
     846           0 :         assert(link);
     847           0 :         assert(link->network);
     848             : 
     849           0 :         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
     850           0 :         if (r < 0)
     851           0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
     852             : 
     853           0 :         r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
     854           0 :         if (r < 0)
     855           0 :                 return log_link_error_errno(link, r, "Could not set message family: %m");
     856             : 
     857           0 :         r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
     858           0 :         if (r < 0)
     859           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
     860             : 
     861           0 :         r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
     862           0 :         if (r < 0)
     863           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
     864             : 
     865           0 :         r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
     866           0 :         if (r < 0)
     867           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
     868             : 
     869           0 :         r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
     870           0 :         if (r < 0)
     871           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
     872             : 
     873           0 :         r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
     874           0 :         if (r < 0)
     875           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
     876             : 
     877           0 :         r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
     878           0 :         if (r < 0)
     879           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
     880             : 
     881           0 :         if(link->network->cost != 0) {
     882           0 :                 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
     883           0 :                 if (r < 0)
     884           0 :                         return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
     885             :         }
     886             : 
     887           0 :         r = sd_netlink_message_close_container(req);
     888           0 :         if (r < 0)
     889           0 :                 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
     890             : 
     891           0 :         r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
     892           0 :         if (r < 0)
     893           0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
     894             : 
     895           0 :         link_ref(link);
     896             : 
     897           0 :         return r;
     898             : }
     899             : 
     900           0 : static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
     901           0 :         Link *link = userdata;
     902             :         int r;
     903             : 
     904           0 :         assert(link);
     905           0 :         assert(link->network);
     906           0 :         assert(link->manager);
     907             : 
     908           0 :         if (event != UPDATE_INFO)
     909           0 :                 return;
     910             : 
     911           0 :         r = sd_lldp_save(link->lldp, link->lldp_file);
     912           0 :         if (r < 0)
     913           0 :                 log_link_warning_errno(link, r, "Could not save LLDP: %m");
     914             : 
     915             : }
     916             : 
     917           0 : static int link_acquire_conf(Link *link) {
     918             :         int r;
     919             : 
     920           0 :         assert(link);
     921           0 :         assert(link->network);
     922           0 :         assert(link->manager);
     923           0 :         assert(link->manager->event);
     924             : 
     925           0 :         if (link_ipv4ll_enabled(link)) {
     926           0 :                 assert(link->ipv4ll);
     927             : 
     928           0 :                 log_link_debug(link, "Acquiring IPv4 link-local address");
     929             : 
     930           0 :                 r = sd_ipv4ll_start(link->ipv4ll);
     931           0 :                 if (r < 0)
     932           0 :                         return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
     933             :         }
     934             : 
     935           0 :         if (link_dhcp4_enabled(link)) {
     936           0 :                 assert(link->dhcp_client);
     937             : 
     938           0 :                 log_link_debug(link, "Acquiring DHCPv4 lease");
     939             : 
     940           0 :                 r = sd_dhcp_client_start(link->dhcp_client);
     941           0 :                 if (r < 0)
     942           0 :                         return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
     943             :         }
     944             : 
     945           0 :         if (link_dhcp6_enabled(link)) {
     946           0 :                 assert(link->icmp6_router_discovery);
     947             : 
     948           0 :                 log_link_debug(link, "Discovering IPv6 routers");
     949             : 
     950           0 :                 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
     951           0 :                 if (r < 0)
     952           0 :                         return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m");
     953             :         }
     954             : 
     955           0 :         if (link_lldp_enabled(link)) {
     956           0 :                 assert(link->lldp);
     957             : 
     958           0 :                 log_link_debug(link, "Starting LLDP");
     959             : 
     960           0 :                 r = sd_lldp_start(link->lldp);
     961           0 :                 if (r < 0)
     962           0 :                         return log_link_warning_errno(link, r, "Could not start LLDP: %m");
     963             :         }
     964             : 
     965           0 :         return 0;
     966             : }
     967             : 
     968          12 : bool link_has_carrier(Link *link) {
     969             :         /* see Documentation/networking/operstates.txt in the kernel sources */
     970             : 
     971          12 :         if (link->kernel_operstate == IF_OPER_UP)
     972           3 :                 return true;
     973             : 
     974           9 :         if (link->kernel_operstate == IF_OPER_UNKNOWN)
     975             :                 /* operstate may not be implemented, so fall back to flags */
     976           6 :                 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
     977           6 :                         return true;
     978             : 
     979           3 :         return false;
     980             : }
     981             : 
     982           0 : static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
     983           0 :         _cleanup_link_unref_ Link *link = userdata;
     984             :         int r;
     985             : 
     986           0 :         assert(link);
     987             : 
     988           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     989           0 :                 return 1;
     990             : 
     991           0 :         r = sd_netlink_message_get_errno(m);
     992           0 :         if (r < 0)
     993             :                 /* we warn but don't fail the link, as it may be
     994             :                    brought up later */
     995           0 :                 log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
     996             : 
     997           0 :         return 1;
     998             : }
     999             : 
    1000           0 : static int link_up(Link *link) {
    1001           0 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
    1002             :         uint8_t ipv6ll_mode;
    1003             :         int r;
    1004             : 
    1005           0 :         assert(link);
    1006           0 :         assert(link->network);
    1007           0 :         assert(link->manager);
    1008           0 :         assert(link->manager->rtnl);
    1009             : 
    1010           0 :         log_link_debug(link, "Bringing link up");
    1011             : 
    1012           0 :         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
    1013           0 :         if (r < 0)
    1014           0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
    1015             : 
    1016           0 :         r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
    1017           0 :         if (r < 0)
    1018           0 :                 return log_link_error_errno(link, r, "Could not set link flags: %m");
    1019             : 
    1020           0 :         if (link->network->mac) {
    1021           0 :                 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
    1022           0 :                 if (r < 0)
    1023           0 :                         return log_link_error_errno(link, r, "Could not set MAC address: %m");
    1024             :         }
    1025             : 
    1026           0 :         if (link->network->mtu) {
    1027           0 :                 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
    1028           0 :                 if (r < 0)
    1029           0 :                         return log_link_error_errno(link, r, "Could not set MTU: %m");
    1030             :         }
    1031             : 
    1032           0 :         r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
    1033           0 :         if (r < 0)
    1034           0 :                 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
    1035             : 
    1036           0 :         if (socket_ipv6_is_supported()) {
    1037             :                 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
    1038           0 :                 r = sd_netlink_message_open_container(req, AF_INET6);
    1039           0 :                 if (r < 0)
    1040           0 :                         return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
    1041             : 
    1042           0 :                 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
    1043           0 :                 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
    1044           0 :                 if (r < 0)
    1045           0 :                         return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
    1046             : 
    1047           0 :                 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
    1048           0 :                         r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
    1049           0 :                         if (r < 0)
    1050           0 :                                 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
    1051             :                 }
    1052             : 
    1053           0 :                 r = sd_netlink_message_close_container(req);
    1054           0 :                 if (r < 0)
    1055           0 :                         return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
    1056             :         }
    1057             : 
    1058           0 :         r = sd_netlink_message_close_container(req);
    1059           0 :         if (r < 0)
    1060           0 :                 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
    1061             : 
    1062           0 :         r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
    1063           0 :         if (r < 0)
    1064           0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
    1065             : 
    1066           0 :         link_ref(link);
    1067             : 
    1068           0 :         return 0;
    1069             : }
    1070             : 
    1071           0 : static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
    1072           0 :         _cleanup_link_unref_ Link *link = userdata;
    1073             :         int r;
    1074             : 
    1075           0 :         assert(link);
    1076             : 
    1077           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
    1078           0 :                 return 1;
    1079             : 
    1080           0 :         r = sd_netlink_message_get_errno(m);
    1081           0 :         if (r < 0)
    1082           0 :                 log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
    1083             : 
    1084           0 :         return 1;
    1085             : }
    1086             : 
    1087           0 : static int link_down(Link *link) {
    1088           0 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
    1089             :         int r;
    1090             : 
    1091           0 :         assert(link);
    1092           0 :         assert(link->manager);
    1093           0 :         assert(link->manager->rtnl);
    1094             : 
    1095           0 :         log_link_debug(link, "Bringing link down");
    1096             : 
    1097           0 :         r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
    1098             :                                      RTM_SETLINK, link->ifindex);
    1099           0 :         if (r < 0)
    1100           0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
    1101             : 
    1102           0 :         r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
    1103           0 :         if (r < 0)
    1104           0 :                 return log_link_error_errno(link, r, "Could not set link flags: %m");
    1105             : 
    1106           0 :         r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link,  0, NULL);
    1107           0 :         if (r < 0)
    1108           0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
    1109             : 
    1110           0 :         link_ref(link);
    1111             : 
    1112           0 :         return 0;
    1113             : }
    1114             : 
    1115           0 : static int link_handle_bound_to_list(Link *link) {
    1116             :         Link *l;
    1117             :         Iterator i;
    1118             :         int r;
    1119           0 :         bool required_up = false;
    1120           0 :         bool link_is_up = false;
    1121             : 
    1122           0 :         assert(link);
    1123             : 
    1124           0 :         if (hashmap_isempty(link->bound_to_links))
    1125           0 :                 return 0;
    1126             : 
    1127           0 :         if (link->flags & IFF_UP)
    1128           0 :                 link_is_up = true;
    1129             : 
    1130           0 :         HASHMAP_FOREACH (l, link->bound_to_links, i)
    1131           0 :                 if (link_has_carrier(l)) {
    1132           0 :                         required_up = true;
    1133           0 :                         break;
    1134             :                 }
    1135             : 
    1136           0 :         if (!required_up && link_is_up) {
    1137           0 :                 r = link_down(link);
    1138           0 :                 if (r < 0)
    1139           0 :                         return r;
    1140           0 :         } else if (required_up && !link_is_up) {
    1141           0 :                 r = link_up(link);
    1142           0 :                 if (r < 0)
    1143           0 :                         return r;
    1144             :         }
    1145             : 
    1146           0 :         return 0;
    1147             : }
    1148             : 
    1149           0 : static int link_handle_bound_by_list(Link *link) {
    1150             :         Iterator i;
    1151             :         Link *l;
    1152             :         int r;
    1153             : 
    1154           0 :         assert(link);
    1155             : 
    1156           0 :         if (hashmap_isempty(link->bound_by_links))
    1157           0 :                 return 0;
    1158             : 
    1159           0 :         HASHMAP_FOREACH (l, link->bound_by_links, i) {
    1160           0 :                 r = link_handle_bound_to_list(l);
    1161           0 :                 if (r < 0)
    1162           0 :                         return r;
    1163             :         }
    1164             : 
    1165           0 :         return 0;
    1166             : }
    1167             : 
    1168           0 : static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
    1169             :         int r;
    1170             : 
    1171           0 :         assert(link);
    1172           0 :         assert(carrier);
    1173             : 
    1174           0 :         if (link == carrier)
    1175           0 :                 return 0;
    1176             : 
    1177           0 :         if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
    1178           0 :                 return 0;
    1179             : 
    1180           0 :         r = hashmap_ensure_allocated(h, NULL);
    1181           0 :         if (r < 0)
    1182           0 :                 return r;
    1183             : 
    1184           0 :         r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
    1185           0 :         if (r < 0)
    1186           0 :                 return r;
    1187             : 
    1188           0 :         return 0;
    1189             : }
    1190             : 
    1191           0 : static int link_new_bound_by_list(Link *link) {
    1192             :         Manager *m;
    1193             :         Link *carrier;
    1194             :         Iterator i;
    1195             :         int r;
    1196           0 :         bool list_updated = false;
    1197             : 
    1198           0 :         assert(link);
    1199           0 :         assert(link->manager);
    1200             : 
    1201           0 :         m = link->manager;
    1202             : 
    1203           0 :         HASHMAP_FOREACH (carrier, m->links, i) {
    1204           0 :                 if (!carrier->network)
    1205           0 :                         continue;
    1206             : 
    1207           0 :                 if (strv_isempty(carrier->network->bind_carrier))
    1208           0 :                         continue;
    1209             : 
    1210           0 :                 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
    1211           0 :                         r = link_put_carrier(link, carrier, &link->bound_by_links);
    1212           0 :                         if (r < 0)
    1213           0 :                                 return r;
    1214             : 
    1215           0 :                         list_updated = true;
    1216             :                 }
    1217             :         }
    1218             : 
    1219           0 :         if (list_updated)
    1220           0 :                 link_save(link);
    1221             : 
    1222           0 :         HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
    1223           0 :                 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
    1224           0 :                 if (r < 0)
    1225           0 :                         return r;
    1226             : 
    1227           0 :                 link_save(carrier);
    1228             :         }
    1229             : 
    1230           0 :         return 0;
    1231             : }
    1232             : 
    1233           0 : static int link_new_bound_to_list(Link *link) {
    1234             :         Manager *m;
    1235             :         Link *carrier;
    1236             :         Iterator i;
    1237             :         int r;
    1238           0 :         bool list_updated = false;
    1239             : 
    1240           0 :         assert(link);
    1241           0 :         assert(link->manager);
    1242             : 
    1243           0 :         if (!link->network)
    1244           0 :                 return 0;
    1245             : 
    1246           0 :         if (strv_isempty(link->network->bind_carrier))
    1247           0 :                 return 0;
    1248             : 
    1249           0 :         m = link->manager;
    1250             : 
    1251           0 :         HASHMAP_FOREACH (carrier, m->links, i) {
    1252           0 :                 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
    1253           0 :                         r = link_put_carrier(link, carrier, &link->bound_to_links);
    1254           0 :                         if (r < 0)
    1255           0 :                                 return r;
    1256             : 
    1257           0 :                         list_updated = true;
    1258             :                 }
    1259             :         }
    1260             : 
    1261           0 :         if (list_updated)
    1262           0 :                 link_save(link);
    1263             : 
    1264           0 :         HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
    1265           0 :                 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
    1266           0 :                 if (r < 0)
    1267           0 :                         return r;
    1268             : 
    1269           0 :                 link_save(carrier);
    1270             :         }
    1271             : 
    1272           0 :         return 0;
    1273             : }
    1274             : 
    1275           0 : static int link_new_carrier_maps(Link *link) {
    1276             :         int r;
    1277             : 
    1278           0 :         r = link_new_bound_by_list(link);
    1279           0 :         if (r < 0)
    1280           0 :                 return r;
    1281             : 
    1282           0 :         r = link_handle_bound_by_list(link);
    1283           0 :         if (r < 0)
    1284           0 :                 return r;
    1285             : 
    1286           0 :         r = link_new_bound_to_list(link);
    1287           0 :         if (r < 0)
    1288           0 :                 return r;
    1289             : 
    1290           0 :         r = link_handle_bound_to_list(link);
    1291           0 :         if (r < 0)
    1292           0 :                 return r;
    1293             : 
    1294           0 :         return 0;
    1295             : }
    1296             : 
    1297           0 : static void link_free_bound_to_list(Link *link) {
    1298             :         Link *bound_to;
    1299             :         Iterator i;
    1300             : 
    1301           0 :         HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
    1302           0 :                 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
    1303             : 
    1304           0 :                 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
    1305           0 :                         link_save(bound_to);
    1306             :         }
    1307             : 
    1308           0 :         return;
    1309             : }
    1310             : 
    1311           0 : static void link_free_bound_by_list(Link *link) {
    1312             :         Link *bound_by;
    1313             :         Iterator i;
    1314             : 
    1315           0 :         HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
    1316           0 :                 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
    1317             : 
    1318           0 :                 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
    1319           0 :                         link_save(bound_by);
    1320           0 :                         link_handle_bound_to_list(bound_by);
    1321             :                 }
    1322             :         }
    1323             : 
    1324           0 :         return;
    1325             : }
    1326             : 
    1327           0 : static void link_free_carrier_maps(Link *link) {
    1328           0 :         bool list_updated = false;
    1329             : 
    1330           0 :         assert(link);
    1331             : 
    1332           0 :         if (!hashmap_isempty(link->bound_to_links)) {
    1333           0 :                 link_free_bound_to_list(link);
    1334           0 :                 list_updated = true;
    1335             :         }
    1336             : 
    1337           0 :         if (!hashmap_isempty(link->bound_by_links)) {
    1338           0 :                 link_free_bound_by_list(link);
    1339           0 :                 list_updated = true;
    1340             :         }
    1341             : 
    1342           0 :         if (list_updated)
    1343           0 :                 link_save(link);
    1344             : 
    1345           0 :         return;
    1346             : }
    1347             : 
    1348           0 : void link_drop(Link *link) {
    1349           0 :         if (!link || link->state == LINK_STATE_LINGER)
    1350           0 :                 return;
    1351             : 
    1352           0 :         link_set_state(link, LINK_STATE_LINGER);
    1353             : 
    1354           0 :         link_free_carrier_maps(link);
    1355             : 
    1356           0 :         log_link_debug(link, "Link removed");
    1357             : 
    1358           0 :         link_unref(link);
    1359             : 
    1360           0 :         return;
    1361             : }
    1362             : 
    1363           0 : static int link_joined(Link *link) {
    1364             :         int r;
    1365             : 
    1366           0 :         assert(link);
    1367           0 :         assert(link->network);
    1368             : 
    1369           0 :         if (!hashmap_isempty(link->bound_to_links)) {
    1370           0 :                 r = link_handle_bound_to_list(link);
    1371           0 :                 if (r < 0)
    1372           0 :                         return r;
    1373           0 :         } else if (!(link->flags & IFF_UP)) {
    1374           0 :                 r = link_up(link);
    1375           0 :                 if (r < 0) {
    1376           0 :                         link_enter_failed(link);
    1377           0 :                         return r;
    1378             :                 }
    1379             :         }
    1380             : 
    1381           0 :         if(link->network->bridge) {
    1382           0 :                 r = link_set_bridge(link);
    1383           0 :                 if (r < 0)
    1384           0 :                         log_link_error_errno(link, r, "Could not set bridge message: %m");
    1385             :         }
    1386             : 
    1387           0 :         return link_enter_set_addresses(link);
    1388             : }
    1389             : 
    1390           0 : static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
    1391           0 :         _cleanup_link_unref_ Link *link = userdata;
    1392             :         int r;
    1393             : 
    1394           0 :         assert(link);
    1395           0 :         assert(link->network);
    1396             : 
    1397           0 :         link->enslaving --;
    1398             : 
    1399           0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
    1400           0 :                 return 1;
    1401             : 
    1402           0 :         r = sd_netlink_message_get_errno(m);
    1403           0 :         if (r < 0 && r != -EEXIST) {
    1404           0 :                 log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
    1405           0 :                 link_enter_failed(link);
    1406           0 :                 return 1;
    1407             :         } else
    1408           0 :                 log_link_debug(link, "Joined netdev");
    1409             : 
    1410           0 :         if (link->enslaving <= 0)
    1411           0 :                 link_joined(link);
    1412             : 
    1413           0 :         return 1;
    1414             : }
    1415             : 
    1416           0 : static int link_enter_join_netdev(Link *link) {
    1417             :         NetDev *netdev;
    1418             :         Iterator i;
    1419             :         int r;
    1420             : 
    1421           0 :         assert(link);
    1422           0 :         assert(link->network);
    1423           0 :         assert(link->state == LINK_STATE_PENDING);
    1424             : 
    1425           0 :         link_set_state(link, LINK_STATE_ENSLAVING);
    1426             : 
    1427           0 :         link_save(link);
    1428             : 
    1429           0 :         if (!link->network->bridge &&
    1430           0 :             !link->network->bond &&
    1431           0 :             hashmap_isempty(link->network->stacked_netdevs))
    1432           0 :                 return link_joined(link);
    1433             : 
    1434           0 :         if (link->network->bond) {
    1435           0 :                 log_struct(LOG_DEBUG,
    1436             :                            LOG_LINK_INTERFACE(link),
    1437             :                            LOG_NETDEV_INTERFACE(link->network->bond),
    1438             :                            LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
    1439             :                            NULL);
    1440             : 
    1441           0 :                 r = netdev_join(link->network->bond, link, netdev_join_handler);
    1442           0 :                 if (r < 0) {
    1443           0 :                         log_struct_errno(LOG_WARNING, r,
    1444             :                                          LOG_LINK_INTERFACE(link),
    1445             :                                          LOG_NETDEV_INTERFACE(link->network->bond),
    1446             :                                          LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
    1447             :                                          NULL);
    1448             : 
    1449           0 :                         link_enter_failed(link);
    1450           0 :                         return r;
    1451             :                 }
    1452             : 
    1453           0 :                 link->enslaving ++;
    1454             :         }
    1455             : 
    1456           0 :         if (link->network->bridge) {
    1457           0 :                 log_struct(LOG_DEBUG,
    1458             :                            LOG_LINK_INTERFACE(link),
    1459             :                            LOG_NETDEV_INTERFACE(link->network->bridge),
    1460             :                            LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
    1461             :                            NULL);
    1462             : 
    1463           0 :                 r = netdev_join(link->network->bridge, link, netdev_join_handler);
    1464           0 :                 if (r < 0) {
    1465           0 :                         log_struct_errno(LOG_WARNING, r,
    1466             :                                          LOG_LINK_INTERFACE(link),
    1467             :                                          LOG_NETDEV_INTERFACE(link->network->bridge),
    1468             :                                          LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
    1469             :                                          NULL),
    1470           0 :                         link_enter_failed(link);
    1471           0 :                         return r;
    1472             :                 }
    1473             : 
    1474           0 :                 link->enslaving ++;
    1475             :         }
    1476             : 
    1477           0 :         HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
    1478             : 
    1479           0 :                 log_struct(LOG_DEBUG,
    1480             :                            LOG_LINK_INTERFACE(link),
    1481             :                            LOG_NETDEV_INTERFACE(netdev),
    1482             :                            LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
    1483             :                            NULL);
    1484             : 
    1485           0 :                 r = netdev_join(netdev, link, netdev_join_handler);
    1486           0 :                 if (r < 0) {
    1487           0 :                         log_struct_errno(LOG_WARNING, r,
    1488             :                                          LOG_LINK_INTERFACE(link),
    1489             :                                          LOG_NETDEV_INTERFACE(netdev),
    1490             :                                          LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
    1491             :                                          NULL);
    1492           0 :                         link_enter_failed(link);
    1493           0 :                         return r;
    1494             :                 }
    1495             : 
    1496           0 :                 link->enslaving ++;
    1497             :         }
    1498             : 
    1499           0 :         return 0;
    1500             : }
    1501             : 
    1502           0 : static int link_set_ipv4_forward(Link *link) {
    1503           0 :         const char *p = NULL, *v;
    1504             :         int r;
    1505             : 
    1506           0 :         if (link->flags & IFF_LOOPBACK)
    1507           0 :                 return 0;
    1508             : 
    1509           0 :         if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
    1510           0 :                 return 0;
    1511             : 
    1512           0 :         p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
    1513           0 :         v = one_zero(link_ipv4_forward_enabled(link));
    1514             : 
    1515           0 :         r = write_string_file(p, v, 0);
    1516           0 :         if (r < 0) {
    1517             :                 /* If the right value is set anyway, don't complain */
    1518           0 :                 if (verify_one_line_file(p, v) > 0)
    1519           0 :                         return 0;
    1520             : 
    1521           0 :                 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
    1522             :         }
    1523             : 
    1524           0 :         return 0;
    1525             : }
    1526             : 
    1527           0 : static int link_set_ipv6_forward(Link *link) {
    1528           0 :         const char *p = NULL, *v = NULL;
    1529             :         int r;
    1530             : 
    1531             :         /* Make this a NOP if IPv6 is not available */
    1532           0 :         if (!socket_ipv6_is_supported())
    1533           0 :                 return 0;
    1534             : 
    1535           0 :         if (link->flags & IFF_LOOPBACK)
    1536           0 :                 return 0;
    1537             : 
    1538           0 :         if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
    1539           0 :                 return 0;
    1540             : 
    1541           0 :         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
    1542           0 :         v = one_zero(link_ipv6_forward_enabled(link));
    1543             : 
    1544           0 :         r = write_string_file(p, v, 0);
    1545           0 :         if (r < 0) {
    1546             :                 /* If the right value is set anyway, don't complain */
    1547           0 :                 if (verify_one_line_file(p, v) > 0)
    1548           0 :                         return 0;
    1549             : 
    1550           0 :                 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
    1551             :         }
    1552             : 
    1553           0 :         return 0;
    1554             : }
    1555             : 
    1556           0 : static int link_set_ipv6_privacy_extensions(Link *link) {
    1557             :         char buf[DECIMAL_STR_MAX(unsigned) + 1];
    1558             :         IPv6PrivacyExtensions s;
    1559           0 :         const char *p = NULL;
    1560             :         int r;
    1561             : 
    1562             :         /* Make this a NOP if IPv6 is not available */
    1563           0 :         if (!socket_ipv6_is_supported())
    1564           0 :                 return 0;
    1565             : 
    1566           0 :         s = link_ipv6_privacy_extensions(link);
    1567           0 :         if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
    1568           0 :                 return 0;
    1569             : 
    1570           0 :         p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
    1571           0 :         xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
    1572             : 
    1573           0 :         r = write_string_file(p, buf, 0);
    1574           0 :         if (r < 0) {
    1575             :                 /* If the right value is set anyway, don't complain */
    1576           0 :                 if (verify_one_line_file(p, buf) > 0)
    1577           0 :                         return 0;
    1578             : 
    1579           0 :                 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
    1580             :         }
    1581             : 
    1582           0 :         return 0;
    1583             : }
    1584             : 
    1585           0 : static int link_configure(Link *link) {
    1586             :         int r;
    1587             : 
    1588           0 :         assert(link);
    1589           0 :         assert(link->network);
    1590           0 :         assert(link->state == LINK_STATE_PENDING);
    1591             : 
    1592           0 :         r = link_set_bridge_fdb(link);
    1593           0 :         if (r < 0)
    1594           0 :                 return r;
    1595             : 
    1596           0 :         r = link_set_ipv4_forward(link);
    1597           0 :         if (r < 0)
    1598           0 :                 return r;
    1599             : 
    1600           0 :         r = link_set_ipv6_forward(link);
    1601           0 :         if (r < 0)
    1602           0 :                 return r;
    1603             : 
    1604           0 :         r = link_set_ipv6_privacy_extensions(link);
    1605           0 :         if (r < 0)
    1606           0 :                 return r;
    1607             : 
    1608           0 :         if (link_ipv4ll_enabled(link)) {
    1609           0 :                 r = ipv4ll_configure(link);
    1610           0 :                 if (r < 0)
    1611           0 :                         return r;
    1612             :         }
    1613             : 
    1614           0 :         if (link_dhcp4_enabled(link)) {
    1615           0 :                 r = dhcp4_configure(link);
    1616           0 :                 if (r < 0)
    1617           0 :                         return r;
    1618             :         }
    1619             : 
    1620           0 :         if (link_dhcp4_server_enabled(link)) {
    1621           0 :                 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
    1622           0 :                 if (r < 0)
    1623           0 :                         return r;
    1624             : 
    1625           0 :                 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
    1626           0 :                 if (r < 0)
    1627           0 :                         return r;
    1628             :         }
    1629             : 
    1630           0 :         if (link_dhcp6_enabled(link)) {
    1631           0 :                 r = icmp6_configure(link);
    1632           0 :                 if (r < 0)
    1633           0 :                         return r;
    1634             :         }
    1635             : 
    1636           0 :         if (link_lldp_enabled(link)) {
    1637           0 :                 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
    1638           0 :                 if (r < 0)
    1639           0 :                         return r;
    1640             : 
    1641           0 :                 r = sd_lldp_attach_event(link->lldp, NULL, 0);
    1642           0 :                 if (r < 0)
    1643           0 :                         return r;
    1644             : 
    1645           0 :                 r = sd_lldp_set_callback(link->lldp,
    1646             :                                          lldp_handler, link);
    1647           0 :                 if (r < 0)
    1648           0 :                         return r;
    1649             :         }
    1650             : 
    1651           0 :         if (link_has_carrier(link)) {
    1652           0 :                 r = link_acquire_conf(link);
    1653           0 :                 if (r < 0)
    1654           0 :                         return r;
    1655             :         }
    1656             : 
    1657           0 :         return link_enter_join_netdev(link);
    1658             : }
    1659             : 
    1660           0 : static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
    1661             :                                        void *userdata) {
    1662           0 :         _cleanup_link_unref_ Link *link = userdata;
    1663             :         Network *network;
    1664             :         int r;
    1665             : 
    1666           0 :         assert(link);
    1667           0 :         assert(link->ifname);
    1668           0 :         assert(link->manager);
    1669             : 
    1670           0 :         if (link->state != LINK_STATE_PENDING)
    1671           0 :                 return 1;
    1672             : 
    1673           0 :         log_link_debug(link, "Link state is up-to-date");
    1674             : 
    1675           0 :         r = link_new_bound_by_list(link);
    1676           0 :         if (r < 0)
    1677           0 :                 return r;
    1678             : 
    1679           0 :         r = link_handle_bound_by_list(link);
    1680           0 :         if (r < 0)
    1681           0 :                 return r;
    1682             : 
    1683           0 :         r = network_get(link->manager, link->udev_device, link->ifname,
    1684           0 :                         &link->mac, &network);
    1685           0 :         if (r == -ENOENT) {
    1686           0 :                 link_enter_unmanaged(link);
    1687           0 :                 return 1;
    1688           0 :         } else if (r < 0)
    1689           0 :                 return r;
    1690             : 
    1691           0 :         if (link->flags & IFF_LOOPBACK) {
    1692           0 :                 if (network->link_local != ADDRESS_FAMILY_NO)
    1693           0 :                         log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
    1694             : 
    1695           0 :                 if (network->dhcp != ADDRESS_FAMILY_NO)
    1696           0 :                         log_link_debug(link, "Ignoring DHCP clients for loopback link");
    1697             : 
    1698           0 :                 if (network->dhcp_server)
    1699           0 :                         log_link_debug(link, "Ignoring DHCP server for loopback link");
    1700             :         }
    1701             : 
    1702           0 :         r = network_apply(link->manager, network, link);
    1703           0 :         if (r < 0)
    1704           0 :                 return r;
    1705             : 
    1706           0 :         r = link_new_bound_to_list(link);
    1707           0 :         if (r < 0)
    1708           0 :                 return r;
    1709             : 
    1710           0 :         r = link_configure(link);
    1711           0 :         if (r < 0)
    1712           0 :                 return r;
    1713             : 
    1714           0 :         return 1;
    1715             : }
    1716             : 
    1717           4 : int link_initialized(Link *link, struct udev_device *device) {
    1718           8 :         _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
    1719             :         int r;
    1720             : 
    1721           4 :         assert(link);
    1722           4 :         assert(link->manager);
    1723           4 :         assert(link->manager->rtnl);
    1724           4 :         assert(device);
    1725             : 
    1726           4 :         if (link->state != LINK_STATE_PENDING)
    1727           0 :                 return 0;
    1728             : 
    1729           4 :         if (link->udev_device)
    1730           0 :                 return 0;
    1731             : 
    1732           4 :         log_link_debug(link, "udev initialized link");
    1733             : 
    1734           4 :         link->udev_device = udev_device_ref(device);
    1735             : 
    1736             :         /* udev has initialized the link, but we don't know if we have yet
    1737             :          * processed the NEWLINK messages with the latest state. Do a GETLINK,
    1738             :          * when it returns we know that the pending NEWLINKs have already been
    1739             :          * processed and that we are up-to-date */
    1740             : 
    1741           4 :         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
    1742             :                                      link->ifindex);
    1743           4 :         if (r < 0)
    1744           0 :                 return r;
    1745             : 
    1746           4 :         r = sd_netlink_call_async(link->manager->rtnl, req,
    1747             :                                link_initialized_and_synced, link, 0, NULL);
    1748           4 :         if (r < 0)
    1749           0 :                 return r;
    1750             : 
    1751           4 :         link_ref(link);
    1752             : 
    1753           4 :         return 0;
    1754             : }
    1755             : 
    1756           0 : static Address* link_get_equal_address(Link *link, Address *needle) {
    1757             :         Address *i;
    1758             : 
    1759           0 :         assert(link);
    1760           0 :         assert(needle);
    1761             : 
    1762           0 :         LIST_FOREACH(addresses, i, link->addresses)
    1763           0 :                 if (address_equal(i, needle))
    1764           0 :                         return i;
    1765             : 
    1766           0 :         return NULL;
    1767             : }
    1768             : 
    1769           0 : int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
    1770           0 :         Manager *m = userdata;
    1771           0 :         Link *link = NULL;
    1772             :         uint16_t type;
    1773           0 :         _cleanup_address_free_ Address *address = NULL;
    1774             :         unsigned char flags;
    1775             :         Address *existing;
    1776             :         char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
    1777           0 :         const char *valid_str = NULL;
    1778             :         int r, ifindex;
    1779             : 
    1780           0 :         assert(rtnl);
    1781           0 :         assert(message);
    1782           0 :         assert(m);
    1783             : 
    1784           0 :         if (sd_netlink_message_is_error(message)) {
    1785           0 :                 r = sd_netlink_message_get_errno(message);
    1786           0 :                 if (r < 0)
    1787           0 :                         log_warning_errno(r, "rtnl: failed to receive address: %m");
    1788             : 
    1789           0 :                 return 0;
    1790             :         }
    1791             : 
    1792           0 :         r = sd_netlink_message_get_type(message, &type);
    1793           0 :         if (r < 0) {
    1794           0 :                 log_warning_errno(r, "rtnl: could not get message type: %m");
    1795           0 :                 return 0;
    1796           0 :         } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
    1797           0 :                 log_warning("rtnl: received unexpected message type when processing address");
    1798           0 :                 return 0;
    1799             :         }
    1800             : 
    1801           0 :         r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
    1802           0 :         if (r < 0) {
    1803           0 :                 log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
    1804           0 :                 return 0;
    1805           0 :         } else if (ifindex <= 0) {
    1806           0 :                 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
    1807           0 :                 return 0;
    1808             :         } else {
    1809           0 :                 r = link_get(m, ifindex, &link);
    1810           0 :                 if (r < 0 || !link) {
    1811             :                         /* when enumerating we might be out of sync, but we will
    1812             :                          * get the address again, so just ignore it */
    1813           0 :                         if (!m->enumerating)
    1814           0 :                                 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
    1815           0 :                         return 0;
    1816             :                 }
    1817             :         }
    1818             : 
    1819           0 :         r = address_new_dynamic(&address);
    1820           0 :         if (r < 0)
    1821           0 :                 return r;
    1822             : 
    1823           0 :         r = sd_rtnl_message_addr_get_family(message, &address->family);
    1824           0 :         if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
    1825           0 :                 log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
    1826           0 :                 return 0;
    1827             :         }
    1828             : 
    1829           0 :         r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
    1830           0 :         if (r < 0) {
    1831           0 :                 log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
    1832           0 :                 return 0;
    1833             :         }
    1834             : 
    1835           0 :         r = sd_rtnl_message_addr_get_scope(message, &address->scope);
    1836           0 :         if (r < 0) {
    1837           0 :                 log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
    1838           0 :                 return 0;
    1839             :         }
    1840             : 
    1841           0 :         r = sd_rtnl_message_addr_get_flags(message, &flags);
    1842           0 :         if (r < 0) {
    1843           0 :                 log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
    1844           0 :                 return 0;
    1845             :         }
    1846           0 :         address->flags = flags;
    1847             : 
    1848           0 :         switch (address->family) {
    1849             :         case AF_INET:
    1850           0 :                 r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
    1851           0 :                 if (r < 0) {
    1852           0 :                         log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
    1853           0 :                         return 0;
    1854             :                 }
    1855             : 
    1856           0 :                 break;
    1857             : 
    1858             :         case AF_INET6:
    1859           0 :                 r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
    1860           0 :                 if (r < 0) {
    1861           0 :                         log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
    1862           0 :                         return 0;
    1863             :                 }
    1864             : 
    1865           0 :                 break;
    1866             : 
    1867             :         default:
    1868           0 :                 assert_not_reached("invalid address family");
    1869             :         }
    1870             : 
    1871           0 :         if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
    1872           0 :                 log_link_warning(link, "Could not print address");
    1873           0 :                 return 0;
    1874             :         }
    1875             : 
    1876           0 :         r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
    1877           0 :         if (r >= 0) {
    1878           0 :                 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
    1879           0 :                         valid_str = "ever";
    1880             :                 else
    1881           0 :                         valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
    1882           0 :                                                     address->cinfo.ifa_valid * USEC_PER_SEC,
    1883             :                                                     USEC_PER_SEC);
    1884             :         }
    1885             : 
    1886           0 :         existing = link_get_equal_address(link, address);
    1887             : 
    1888           0 :         switch (type) {
    1889             :         case RTM_NEWADDR:
    1890           0 :                 if (existing) {
    1891           0 :                         log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
    1892             : 
    1893             : 
    1894           0 :                         existing->scope = address->scope;
    1895           0 :                         existing->flags = address->flags;
    1896           0 :                         existing->cinfo = address->cinfo;
    1897             : 
    1898             :                 } else {
    1899           0 :                         log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
    1900             : 
    1901           0 :                         LIST_PREPEND(addresses, link->addresses, address);
    1902           0 :                         address_establish(address, link);
    1903             : 
    1904           0 :                         address = NULL;
    1905             : 
    1906           0 :                         link_save(link);
    1907             :                 }
    1908             : 
    1909           0 :                 break;
    1910             : 
    1911             :         case RTM_DELADDR:
    1912             : 
    1913           0 :                 if (existing) {
    1914           0 :                         log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
    1915           0 :                         address_release(existing, link);
    1916           0 :                         LIST_REMOVE(addresses, link->addresses, existing);
    1917           0 :                         address_free(existing);
    1918             :                 } else
    1919           0 :                         log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
    1920             : 
    1921           0 :                 break;
    1922             :         default:
    1923           0 :                 assert_not_reached("Received invalid RTNL message type");
    1924             :         }
    1925             : 
    1926           0 :         return 1;
    1927             : }
    1928             : 
    1929           4 : int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
    1930             :         Link *link;
    1931           8 :         _cleanup_udev_device_unref_ struct udev_device *device = NULL;
    1932             :         char ifindex_str[2 + DECIMAL_STR_MAX(int)];
    1933             :         int r;
    1934             : 
    1935           4 :         assert(m);
    1936           4 :         assert(m->rtnl);
    1937           4 :         assert(message);
    1938           4 :         assert(ret);
    1939             : 
    1940           4 :         r = link_new(m, message, ret);
    1941           4 :         if (r < 0)
    1942           0 :                 return r;
    1943             : 
    1944           4 :         link = *ret;
    1945             : 
    1946           4 :         log_link_debug(link, "Link %d added", link->ifindex);
    1947             : 
    1948           4 :         if (detect_container(NULL) <= 0) {
    1949             :                 /* not in a container, udev will be around */
    1950           4 :                 sprintf(ifindex_str, "n%d", link->ifindex);
    1951           4 :                 device = udev_device_new_from_device_id(m->udev, ifindex_str);
    1952           4 :                 if (!device)
    1953           0 :                         return log_link_warning_errno(link, errno, "Could not find udev device: %m");
    1954             : 
    1955           4 :                 if (udev_device_get_is_initialized(device) <= 0) {
    1956             :                         /* not yet ready */
    1957           0 :                         log_link_debug(link, "link pending udev initialization...");
    1958           0 :                         return 0;
    1959             :                 }
    1960             : 
    1961           4 :                 r = link_initialized(link, device);
    1962           4 :                 if (r < 0)
    1963           0 :                         return r;
    1964             :         } else {
    1965             :                 /* we are calling a callback directly, so must take a ref */
    1966           0 :                 link_ref(link);
    1967             : 
    1968           0 :                 r = link_initialized_and_synced(m->rtnl, NULL, link);
    1969           0 :                 if (r < 0)
    1970           0 :                         return r;
    1971             :         }
    1972             : 
    1973           4 :         return 0;
    1974             : }
    1975             : 
    1976           0 : static int link_carrier_gained(Link *link) {
    1977             :         int r;
    1978             : 
    1979           0 :         assert(link);
    1980             : 
    1981           0 :         if (link->network) {
    1982           0 :                 r = link_acquire_conf(link);
    1983           0 :                 if (r < 0) {
    1984           0 :                         link_enter_failed(link);
    1985           0 :                         return r;
    1986             :                 }
    1987             :         }
    1988             : 
    1989           0 :         r = link_handle_bound_by_list(link);
    1990           0 :         if (r < 0)
    1991           0 :                 return r;
    1992             : 
    1993           0 :         return 0;
    1994             : }
    1995             : 
    1996           0 : static int link_carrier_lost(Link *link) {
    1997             :         int r;
    1998             : 
    1999           0 :         assert(link);
    2000             : 
    2001           0 :         r = link_stop_clients(link);
    2002           0 :         if (r < 0) {
    2003           0 :                 link_enter_failed(link);
    2004           0 :                 return r;
    2005             :         }
    2006             : 
    2007           0 :         r = link_handle_bound_by_list(link);
    2008           0 :         if (r < 0)
    2009           0 :                 return r;
    2010             : 
    2011           0 :         return 0;
    2012             : }
    2013             : 
    2014           0 : int link_carrier_reset(Link *link) {
    2015             :         int r;
    2016             : 
    2017           0 :         assert(link);
    2018             : 
    2019           0 :         if (link_has_carrier(link)) {
    2020           0 :                 r = link_carrier_lost(link);
    2021           0 :                 if (r < 0)
    2022           0 :                         return r;
    2023             : 
    2024           0 :                 r = link_carrier_gained(link);
    2025           0 :                 if (r < 0)
    2026           0 :                         return r;
    2027             : 
    2028           0 :                 log_link_info(link, "Reset carrier");
    2029             :         }
    2030             : 
    2031           0 :         return 0;
    2032             : }
    2033             : 
    2034             : 
    2035           4 : int link_update(Link *link, sd_netlink_message *m) {
    2036             :         struct ether_addr mac;
    2037             :         const char *ifname;
    2038             :         uint32_t mtu;
    2039             :         bool had_carrier, carrier_gained, carrier_lost;
    2040             :         int r;
    2041             : 
    2042           4 :         assert(link);
    2043           4 :         assert(link->ifname);
    2044           4 :         assert(m);
    2045             : 
    2046           4 :         if (link->state == LINK_STATE_LINGER) {
    2047           0 :                 link_ref(link);
    2048           0 :                 log_link_info(link, "Link readded");
    2049           0 :                 link_set_state(link, LINK_STATE_ENSLAVING);
    2050             : 
    2051           0 :                 r = link_new_carrier_maps(link);
    2052           0 :                 if (r < 0)
    2053           0 :                         return r;
    2054             :         }
    2055             : 
    2056           4 :         r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
    2057           4 :         if (r >= 0 && !streq(ifname, link->ifname)) {
    2058           0 :                 log_link_info(link, "Renamed to %s", ifname);
    2059             : 
    2060           0 :                 link_free_carrier_maps(link);
    2061             : 
    2062           0 :                 free(link->ifname);
    2063           0 :                 link->ifname = strdup(ifname);
    2064           0 :                 if (!link->ifname)
    2065           0 :                         return -ENOMEM;
    2066             : 
    2067           0 :                 r = link_new_carrier_maps(link);
    2068           0 :                 if (r < 0)
    2069           0 :                         return r;
    2070             :         }
    2071             : 
    2072           4 :         r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
    2073           4 :         if (r >= 0 && mtu > 0) {
    2074           4 :                 link->mtu = mtu;
    2075           4 :                 if (!link->original_mtu) {
    2076           4 :                         link->original_mtu = mtu;
    2077           4 :                         log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
    2078             :                 }
    2079             : 
    2080           4 :                 if (link->dhcp_client) {
    2081           0 :                         r = sd_dhcp_client_set_mtu(link->dhcp_client,
    2082             :                                                    link->mtu);
    2083           0 :                         if (r < 0) {
    2084           0 :                                 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
    2085           0 :                                 return r;
    2086             :                         }
    2087             :                 }
    2088             :         }
    2089             : 
    2090             :         /* The kernel may broadcast NEWLINK messages without the MAC address
    2091             :            set, simply ignore them. */
    2092           4 :         r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
    2093           4 :         if (r >= 0) {
    2094           3 :                 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
    2095             :                            ETH_ALEN)) {
    2096             : 
    2097           0 :                         memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
    2098             :                                ETH_ALEN);
    2099             : 
    2100           0 :                         log_link_debug(link, "MAC address: "
    2101             :                                        "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
    2102             :                                        mac.ether_addr_octet[0],
    2103             :                                        mac.ether_addr_octet[1],
    2104             :                                        mac.ether_addr_octet[2],
    2105             :                                        mac.ether_addr_octet[3],
    2106             :                                        mac.ether_addr_octet[4],
    2107             :                                        mac.ether_addr_octet[5]);
    2108             : 
    2109           0 :                         if (link->ipv4ll) {
    2110           0 :                                 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
    2111           0 :                                 if (r < 0)
    2112           0 :                                         return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
    2113             :                         }
    2114             : 
    2115           0 :                         if (link->dhcp_client) {
    2116           0 :                                 r = sd_dhcp_client_set_mac(link->dhcp_client,
    2117           0 :                                                            (const uint8_t *) &link->mac,
    2118             :                                                            sizeof (link->mac),
    2119             :                                                            ARPHRD_ETHER);
    2120           0 :                                 if (r < 0)
    2121           0 :                                         return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
    2122             :                         }
    2123             : 
    2124           0 :                         if (link->dhcp6_client) {
    2125           0 :                                 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
    2126           0 :                                                             (const uint8_t *) &link->mac,
    2127             :                                                             sizeof (link->mac),
    2128             :                                                             ARPHRD_ETHER);
    2129           0 :                                 if (r < 0)
    2130           0 :                                         return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
    2131             :                         }
    2132             :                 }
    2133             :         }
    2134             : 
    2135           4 :         had_carrier = link_has_carrier(link);
    2136             : 
    2137           4 :         r = link_update_flags(link, m);
    2138           4 :         if (r < 0)
    2139           0 :                 return r;
    2140             : 
    2141           4 :         carrier_gained = !had_carrier && link_has_carrier(link);
    2142           4 :         carrier_lost = had_carrier && !link_has_carrier(link);
    2143             : 
    2144           4 :         if (carrier_gained) {
    2145           0 :                 log_link_info(link, "Gained carrier");
    2146             : 
    2147           0 :                 r = link_carrier_gained(link);
    2148           0 :                 if (r < 0)
    2149           0 :                         return r;
    2150           4 :         } else if (carrier_lost) {
    2151           0 :                 log_link_info(link, "Lost carrier");
    2152             : 
    2153           0 :                 r = link_carrier_lost(link);
    2154           0 :                 if (r < 0)
    2155           0 :                         return r;
    2156             : 
    2157             :         }
    2158             : 
    2159           4 :         return 0;
    2160             : }
    2161             : 
    2162           4 : static void link_update_operstate(Link *link) {
    2163             :         LinkOperationalState operstate;
    2164           4 :         assert(link);
    2165             : 
    2166           4 :         if (link->kernel_operstate == IF_OPER_DORMANT)
    2167           0 :                 operstate = LINK_OPERSTATE_DORMANT;
    2168           4 :         else if (link_has_carrier(link)) {
    2169             :                 Address *address;
    2170           3 :                 uint8_t scope = RT_SCOPE_NOWHERE;
    2171             : 
    2172             :                 /* if we have carrier, check what addresses we have */
    2173           3 :                 LIST_FOREACH(addresses, address, link->addresses) {
    2174           0 :                         if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
    2175           0 :                                 continue;
    2176             : 
    2177           0 :                         if (address->scope < scope)
    2178           0 :                                 scope = address->scope;
    2179             :                 }
    2180             : 
    2181           3 :                 if (scope < RT_SCOPE_SITE)
    2182             :                         /* universally accessible addresses found */
    2183           0 :                         operstate = LINK_OPERSTATE_ROUTABLE;
    2184           3 :                 else if (scope < RT_SCOPE_HOST)
    2185             :                         /* only link or site local addresses found */
    2186           0 :                         operstate = LINK_OPERSTATE_DEGRADED;
    2187             :                 else
    2188             :                         /* no useful addresses found */
    2189           3 :                         operstate = LINK_OPERSTATE_CARRIER;
    2190           1 :         } else if (link->flags & IFF_UP)
    2191           1 :                 operstate = LINK_OPERSTATE_NO_CARRIER;
    2192             :         else
    2193           0 :                 operstate = LINK_OPERSTATE_OFF;
    2194             : 
    2195           4 :         if (link->operstate != operstate) {
    2196           4 :                 link->operstate = operstate;
    2197           4 :                 link_send_changed(link, "OperationalState", NULL);
    2198             :         }
    2199           4 : }
    2200             : 
    2201           4 : int link_save(Link *link) {
    2202           8 :         _cleanup_free_ char *temp_path = NULL;
    2203           8 :         _cleanup_fclose_ FILE *f = NULL;
    2204             :         const char *admin_state, *oper_state;
    2205             :         int r;
    2206             : 
    2207           4 :         assert(link);
    2208           4 :         assert(link->state_file);
    2209           4 :         assert(link->lease_file);
    2210           4 :         assert(link->manager);
    2211             : 
    2212           4 :         link_update_operstate(link);
    2213             : 
    2214           4 :         r = manager_save(link->manager);
    2215           4 :         if (r < 0)
    2216           4 :                 return r;
    2217             : 
    2218           0 :         if (link->state == LINK_STATE_LINGER) {
    2219           0 :                 unlink(link->state_file);
    2220           0 :                 return 0;
    2221             :         }
    2222             : 
    2223           0 :         admin_state = link_state_to_string(link->state);
    2224           0 :         assert(admin_state);
    2225             : 
    2226           0 :         oper_state = link_operstate_to_string(link->operstate);
    2227           0 :         assert(oper_state);
    2228             : 
    2229           0 :         r = fopen_temporary(link->state_file, &f, &temp_path);
    2230           0 :         if (r < 0)
    2231           0 :                 goto fail;
    2232             : 
    2233           0 :         fchmod(fileno(f), 0644);
    2234             : 
    2235           0 :         fprintf(f,
    2236             :                 "# This is private data. Do not parse.\n"
    2237             :                 "ADMIN_STATE=%s\n"
    2238             :                 "OPER_STATE=%s\n",
    2239             :                 admin_state, oper_state);
    2240             : 
    2241           0 :         if (link->network) {
    2242             :                 char **address, **domain;
    2243             :                 bool space;
    2244             : 
    2245           0 :                 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
    2246             : 
    2247           0 :                 fputs("DNS=", f);
    2248           0 :                 space = false;
    2249           0 :                 STRV_FOREACH(address, link->network->dns) {
    2250           0 :                         if (space)
    2251           0 :                                 fputc(' ', f);
    2252           0 :                         fputs(*address, f);
    2253           0 :                         space = true;
    2254             :                 }
    2255             : 
    2256           0 :                 if (link->network->dhcp_dns &&
    2257           0 :                     link->dhcp_lease) {
    2258             :                         const struct in_addr *addresses;
    2259             : 
    2260           0 :                         r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
    2261           0 :                         if (r > 0) {
    2262           0 :                                 if (space)
    2263           0 :                                         fputc(' ', f);
    2264           0 :                                 serialize_in_addrs(f, addresses, r);
    2265             :                         }
    2266             :                 }
    2267             : 
    2268           0 :                 fputs("\n", f);
    2269             : 
    2270           0 :                 fprintf(f, "NTP=");
    2271           0 :                 space = false;
    2272           0 :                 STRV_FOREACH(address, link->network->ntp) {
    2273           0 :                         if (space)
    2274           0 :                                 fputc(' ', f);
    2275           0 :                         fputs(*address, f);
    2276           0 :                         space = true;
    2277             :                 }
    2278             : 
    2279           0 :                 if (link->network->dhcp_ntp &&
    2280           0 :                     link->dhcp_lease) {
    2281             :                         const struct in_addr *addresses;
    2282             : 
    2283           0 :                         r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
    2284           0 :                         if (r > 0) {
    2285           0 :                                 if (space)
    2286           0 :                                         fputc(' ', f);
    2287           0 :                                 serialize_in_addrs(f, addresses, r);
    2288             :                         }
    2289             :                 }
    2290             : 
    2291           0 :                 fputs("\n", f);
    2292             : 
    2293           0 :                 fprintf(f, "DOMAINS=");
    2294           0 :                 space = false;
    2295           0 :                 STRV_FOREACH(domain, link->network->domains) {
    2296           0 :                         if (space)
    2297           0 :                                 fputc(' ', f);
    2298           0 :                         fputs(*domain, f);
    2299           0 :                         space = true;
    2300             :                 }
    2301             : 
    2302           0 :                 if (link->network->dhcp_domains &&
    2303           0 :                     link->dhcp_lease) {
    2304             :                         const char *domainname;
    2305             : 
    2306           0 :                         r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
    2307           0 :                         if (r >= 0) {
    2308           0 :                                 if (space)
    2309           0 :                                         fputc(' ', f);
    2310           0 :                                 fputs(domainname, f);
    2311             :                         }
    2312             :                 }
    2313             : 
    2314           0 :                 fputs("\n", f);
    2315             : 
    2316           0 :                 fprintf(f, "WILDCARD_DOMAIN=%s\n",
    2317           0 :                         yes_no(link->network->wildcard_domain));
    2318             : 
    2319           0 :                 fprintf(f, "LLMNR=%s\n",
    2320           0 :                         llmnr_support_to_string(link->network->llmnr));
    2321             :         }
    2322             : 
    2323           0 :         if (!hashmap_isempty(link->bound_to_links)) {
    2324             :                 Link *carrier;
    2325             :                 Iterator i;
    2326           0 :                 bool space = false;
    2327             : 
    2328           0 :                 fputs("CARRIER_BOUND_TO=", f);
    2329           0 :                 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
    2330           0 :                         if (space)
    2331           0 :                                 fputc(' ', f);
    2332           0 :                         fputs(carrier->ifname, f);
    2333           0 :                         space = true;
    2334             :                 }
    2335             : 
    2336           0 :                 fputs("\n", f);
    2337             :         }
    2338             : 
    2339           0 :         if (!hashmap_isempty(link->bound_by_links)) {
    2340             :                 Link *carrier;
    2341             :                 Iterator i;
    2342           0 :                 bool space = false;
    2343             : 
    2344           0 :                 fputs("CARRIER_BOUND_BY=", f);
    2345           0 :                 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
    2346           0 :                         if (space)
    2347           0 :                                 fputc(' ', f);
    2348           0 :                         fputs(carrier->ifname, f);
    2349           0 :                         space = true;
    2350             :                 }
    2351             : 
    2352           0 :                 fputs("\n", f);
    2353             :         }
    2354             : 
    2355           0 :         if (link->dhcp_lease) {
    2356           0 :                 assert(link->network);
    2357             : 
    2358           0 :                 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
    2359           0 :                 if (r < 0)
    2360           0 :                         goto fail;
    2361             : 
    2362           0 :                 fprintf(f,
    2363             :                         "DHCP_LEASE=%s\n",
    2364             :                         link->lease_file);
    2365             :         } else
    2366           0 :                 unlink(link->lease_file);
    2367             : 
    2368           0 :         if (link->lldp) {
    2369           0 :                 assert(link->network);
    2370             : 
    2371           0 :                 r = sd_lldp_save(link->lldp, link->lldp_file);
    2372           0 :                 if (r < 0)
    2373           0 :                         goto fail;
    2374             : 
    2375           0 :                 fprintf(f,
    2376             :                         "LLDP_FILE=%s\n",
    2377             :                         link->lldp_file);
    2378             :         } else
    2379           0 :                 unlink(link->lldp_file);
    2380             : 
    2381           0 :         r = fflush_and_check(f);
    2382           0 :         if (r < 0)
    2383           0 :                 goto fail;
    2384             : 
    2385           0 :         if (rename(temp_path, link->state_file) < 0) {
    2386           0 :                 r = -errno;
    2387           0 :                 goto fail;
    2388             :         }
    2389             : 
    2390           0 :         return 0;
    2391             : fail:
    2392           0 :         log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
    2393           0 :         (void) unlink(link->state_file);
    2394             : 
    2395           0 :         if (temp_path)
    2396           0 :                 (void) unlink(temp_path);
    2397             : 
    2398           0 :         return r;
    2399             : }
    2400             : 
    2401             : static const char* const link_state_table[_LINK_STATE_MAX] = {
    2402             :         [LINK_STATE_PENDING] = "pending",
    2403             :         [LINK_STATE_ENSLAVING] = "configuring",
    2404             :         [LINK_STATE_SETTING_ADDRESSES] = "configuring",
    2405             :         [LINK_STATE_SETTING_ROUTES] = "configuring",
    2406             :         [LINK_STATE_CONFIGURED] = "configured",
    2407             :         [LINK_STATE_UNMANAGED] = "unmanaged",
    2408             :         [LINK_STATE_FAILED] = "failed",
    2409             :         [LINK_STATE_LINGER] = "linger",
    2410             : };
    2411             : 
    2412           0 : DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
    2413             : 
    2414             : static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
    2415             :         [LINK_OPERSTATE_OFF] = "off",
    2416             :         [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
    2417             :         [LINK_OPERSTATE_DORMANT] = "dormant",
    2418             :         [LINK_OPERSTATE_CARRIER] = "carrier",
    2419             :         [LINK_OPERSTATE_DEGRADED] = "degraded",
    2420             :         [LINK_OPERSTATE_ROUTABLE] = "routable",
    2421             : };
    2422             : 
    2423          20 : DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);

Generated by: LCOV version 1.11