LCOV - code coverage report
Current view: top level - network - networkd-address.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 105 536 19.6 %
Date: 2019-08-23 13:36:53 Functions: 7 26 26.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 79 592 13.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <net/if.h>
       4                 :            : 
       5                 :            : #include "alloc-util.h"
       6                 :            : #include "conf-parser.h"
       7                 :            : #include "firewall-util.h"
       8                 :            : #include "memory-util.h"
       9                 :            : #include "missing_network.h"
      10                 :            : #include "netlink-util.h"
      11                 :            : #include "networkd-address.h"
      12                 :            : #include "networkd-manager.h"
      13                 :            : #include "parse-util.h"
      14                 :            : #include "set.h"
      15                 :            : #include "socket-util.h"
      16                 :            : #include "string-util.h"
      17                 :            : #include "strv.h"
      18                 :            : #include "utf8.h"
      19                 :            : 
      20                 :            : #define ADDRESSES_PER_LINK_MAX 2048U
      21                 :            : #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
      22                 :            : 
      23                 :        108 : int address_new(Address **ret) {
      24                 :        108 :         _cleanup_(address_freep) Address *address = NULL;
      25                 :            : 
      26                 :        108 :         address = new(Address, 1);
      27         [ -  + ]:        108 :         if (!address)
      28                 :          0 :                 return -ENOMEM;
      29                 :            : 
      30                 :        108 :         *address = (Address) {
      31                 :            :                 .family = AF_UNSPEC,
      32                 :            :                 .scope = RT_SCOPE_UNIVERSE,
      33                 :            :                 .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME,
      34                 :            :                 .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME,
      35                 :            :         };
      36                 :            : 
      37                 :        108 :         *ret = TAKE_PTR(address);
      38                 :            : 
      39                 :        108 :         return 0;
      40                 :            : }
      41                 :            : 
      42                 :        100 : static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
      43                 :        100 :         _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
      44                 :        100 :         _cleanup_(address_freep) Address *address = NULL;
      45                 :            :         int r;
      46                 :            : 
      47         [ -  + ]:        100 :         assert(network);
      48         [ -  + ]:        100 :         assert(ret);
      49         [ -  + ]:        100 :         assert(!!filename == (section_line > 0));
      50                 :            : 
      51         [ +  + ]:        100 :         if (filename) {
      52                 :         92 :                 r = network_config_section_new(filename, section_line, &n);
      53         [ -  + ]:         92 :                 if (r < 0)
      54                 :          0 :                         return r;
      55                 :            : 
      56                 :         92 :                 address = hashmap_get(network->addresses_by_section, n);
      57         [ -  + ]:         92 :                 if (address) {
      58                 :          0 :                         *ret = TAKE_PTR(address);
      59                 :            : 
      60                 :          0 :                         return 0;
      61                 :            :                 }
      62                 :            :         }
      63                 :            : 
      64         [ -  + ]:        100 :         if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX)
      65                 :          0 :                 return -E2BIG;
      66                 :            : 
      67                 :        100 :         r = address_new(&address);
      68         [ -  + ]:        100 :         if (r < 0)
      69                 :          0 :                 return r;
      70                 :            : 
      71                 :        100 :         address->network = network;
      72   [ +  -  #  #  :        100 :         LIST_APPEND(addresses, network->static_addresses, address);
          -  +  +  -  -  
                +  #  # ]
      73                 :        100 :         network->n_static_addresses++;
      74                 :            : 
      75         [ +  + ]:        100 :         if (filename) {
      76                 :         92 :                 address->section = TAKE_PTR(n);
      77                 :            : 
      78                 :         92 :                 r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops);
      79         [ -  + ]:         92 :                 if (r < 0)
      80                 :          0 :                         return r;
      81                 :            : 
      82                 :         92 :                 r = hashmap_put(network->addresses_by_section, address->section, address);
      83         [ -  + ]:         92 :                 if (r < 0)
      84                 :          0 :                         return r;
      85                 :            :         }
      86                 :            : 
      87                 :        100 :         *ret = TAKE_PTR(address);
      88                 :            : 
      89                 :        100 :         return 0;
      90                 :            : }
      91                 :            : 
      92                 :        108 : void address_free(Address *address) {
      93         [ -  + ]:        108 :         if (!address)
      94                 :          0 :                 return;
      95                 :            : 
      96         [ +  + ]:        108 :         if (address->network) {
      97   [ -  +  -  +  :        100 :                 LIST_REMOVE(addresses, address->network->static_addresses, address);
             -  +  -  + ]
      98         [ -  + ]:        100 :                 assert(address->network->n_static_addresses > 0);
      99                 :        100 :                 address->network->n_static_addresses--;
     100                 :            : 
     101         [ +  + ]:        100 :                 if (address->section)
     102                 :         92 :                         hashmap_remove(address->network->addresses_by_section, address->section);
     103                 :            :         }
     104                 :            : 
     105         [ -  + ]:        108 :         if (address->link) {
     106                 :          0 :                 set_remove(address->link->addresses, address);
     107                 :          0 :                 set_remove(address->link->addresses_foreign, address);
     108                 :            : 
     109         [ #  # ]:          0 :                 if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
     110         [ #  # ]:          0 :                         memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
     111                 :            :         }
     112                 :            : 
     113                 :        108 :         network_config_section_free(address->section);
     114                 :        108 :         free(address->label);
     115                 :        108 :         free(address);
     116                 :            : }
     117                 :            : 
     118                 :          0 : static void address_hash_func(const Address *a, struct siphash *state) {
     119         [ #  # ]:          0 :         assert(a);
     120                 :            : 
     121                 :          0 :         siphash24_compress(&a->family, sizeof(a->family), state);
     122                 :            : 
     123      [ #  #  # ]:          0 :         switch (a->family) {
     124                 :          0 :         case AF_INET:
     125                 :          0 :                 siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
     126                 :            : 
     127                 :            :                 /* peer prefix */
     128         [ #  # ]:          0 :                 if (a->prefixlen != 0) {
     129                 :            :                         uint32_t prefix;
     130                 :            : 
     131         [ #  # ]:          0 :                         if (a->in_addr_peer.in.s_addr != 0)
     132                 :          0 :                                 prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
     133                 :            :                         else
     134                 :          0 :                                 prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
     135                 :            : 
     136                 :          0 :                         siphash24_compress(&prefix, sizeof(prefix), state);
     137                 :            :                 }
     138                 :            : 
     139                 :            :                 _fallthrough_;
     140                 :            :         case AF_INET6:
     141                 :            :                 /* local address */
     142                 :          0 :                 siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
     143                 :            : 
     144                 :          0 :                 break;
     145                 :          0 :         default:
     146                 :            :                 /* treat any other address family as AF_UNSPEC */
     147                 :          0 :                 break;
     148                 :            :         }
     149                 :          0 : }
     150                 :            : 
     151                 :         52 : static int address_compare_func(const Address *a1, const Address *a2) {
     152                 :            :         int r;
     153                 :            : 
     154         [ +  - ]:         52 :         r = CMP(a1->family, a2->family);
     155         [ +  + ]:         52 :         if (r != 0)
     156                 :          8 :                 return r;
     157                 :            : 
     158      [ +  +  + ]:         44 :         switch (a1->family) {
     159                 :            :         /* use the same notion of equality as the kernel does */
     160                 :         28 :         case AF_INET:
     161         [ +  - ]:         28 :                 r = CMP(a1->prefixlen, a2->prefixlen);
     162         [ +  + ]:         28 :                 if (r != 0)
     163                 :          4 :                         return r;
     164                 :            : 
     165                 :            :                 /* compare the peer prefixes */
     166         [ +  + ]:         24 :                 if (a1->prefixlen != 0) {
     167                 :            :                         /* make sure we don't try to shift by 32.
     168                 :            :                          * See ISO/IEC 9899:TC3 ยง 6.5.7.3. */
     169                 :            :                         uint32_t b1, b2;
     170                 :            : 
     171         [ +  - ]:          4 :                         if (a1->in_addr_peer.in.s_addr != 0)
     172                 :          4 :                                 b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
     173                 :            :                         else
     174                 :          0 :                                 b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen);
     175                 :            : 
     176         [ +  - ]:          4 :                         if (a2->in_addr_peer.in.s_addr != 0)
     177                 :          4 :                                 b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
     178                 :            :                         else
     179                 :          0 :                                 b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen);
     180                 :            : 
     181         [ +  - ]:          4 :                         r = CMP(b1, b2);
     182         [ -  + ]:          4 :                         if (r != 0)
     183                 :          0 :                                 return r;
     184                 :            :                 }
     185                 :            : 
     186                 :            :                 _fallthrough_;
     187                 :            :         case AF_INET6:
     188                 :         36 :                 return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
     189                 :          4 :         default:
     190                 :            :                 /* treat any other address family as AF_UNSPEC */
     191                 :          4 :                 return 0;
     192                 :            :         }
     193                 :            : }
     194                 :            : 
     195                 :            : DEFINE_PRIVATE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
     196                 :            : 
     197                 :         64 : bool address_equal(Address *a1, Address *a2) {
     198         [ +  + ]:         64 :         if (a1 == a2)
     199                 :          4 :                 return true;
     200                 :            : 
     201   [ +  +  +  + ]:         60 :         if (!a1 || !a2)
     202                 :          8 :                 return false;
     203                 :            : 
     204                 :         52 :         return address_compare_func(a1, a2) == 0;
     205                 :            : }
     206                 :            : 
     207                 :          0 : static int address_establish(Address *address, Link *link) {
     208                 :            :         bool masq;
     209                 :            :         int r;
     210                 :            : 
     211         [ #  # ]:          0 :         assert(address);
     212         [ #  # ]:          0 :         assert(link);
     213                 :            : 
     214                 :          0 :         masq = link->network &&
     215         [ #  # ]:          0 :                link->network->ip_masquerade &&
     216   [ #  #  #  # ]:          0 :                address->family == AF_INET &&
     217         [ #  # ]:          0 :                address->scope < RT_SCOPE_LINK;
     218                 :            : 
     219                 :            :         /* Add firewall entry if this is requested */
     220         [ #  # ]:          0 :         if (address->ip_masquerade_done != masq) {
     221                 :          0 :                 union in_addr_union masked = address->in_addr;
     222                 :          0 :                 in_addr_mask(address->family, &masked, address->prefixlen);
     223                 :            : 
     224                 :          0 :                 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
     225         [ #  # ]:          0 :                 if (r < 0)
     226                 :          0 :                         return r;
     227                 :            : 
     228                 :          0 :                 address->ip_masquerade_done = masq;
     229                 :            :         }
     230                 :            : 
     231                 :          0 :         return 0;
     232                 :            : }
     233                 :            : 
     234                 :          0 : static int address_add_internal(Link *link, Set **addresses,
     235                 :            :                                 int family,
     236                 :            :                                 const union in_addr_union *in_addr,
     237                 :            :                                 unsigned char prefixlen,
     238                 :            :                                 Address **ret) {
     239                 :          0 :         _cleanup_(address_freep) Address *address = NULL;
     240                 :            :         int r;
     241                 :            : 
     242         [ #  # ]:          0 :         assert(link);
     243         [ #  # ]:          0 :         assert(addresses);
     244         [ #  # ]:          0 :         assert(in_addr);
     245                 :            : 
     246                 :          0 :         r = address_new(&address);
     247         [ #  # ]:          0 :         if (r < 0)
     248                 :          0 :                 return r;
     249                 :            : 
     250                 :          0 :         address->family = family;
     251                 :          0 :         address->in_addr = *in_addr;
     252                 :          0 :         address->prefixlen = prefixlen;
     253                 :            :         /* Consider address tentative until we get the real flags from the kernel */
     254                 :          0 :         address->flags = IFA_F_TENTATIVE;
     255                 :            : 
     256                 :          0 :         r = set_ensure_allocated(addresses, &address_hash_ops);
     257         [ #  # ]:          0 :         if (r < 0)
     258                 :          0 :                 return r;
     259                 :            : 
     260                 :          0 :         r = set_put(*addresses, address);
     261         [ #  # ]:          0 :         if (r < 0)
     262                 :          0 :                 return r;
     263         [ #  # ]:          0 :         if (r == 0)
     264                 :          0 :                 return -EEXIST;
     265                 :            : 
     266                 :          0 :         address->link = link;
     267                 :            : 
     268         [ #  # ]:          0 :         if (ret)
     269                 :          0 :                 *ret = address;
     270                 :            : 
     271                 :          0 :         address = NULL;
     272                 :            : 
     273                 :          0 :         return 0;
     274                 :            : }
     275                 :            : 
     276                 :          0 : int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
     277                 :          0 :         return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret);
     278                 :            : }
     279                 :            : 
     280                 :          0 : int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
     281                 :            :         Address *address;
     282                 :            :         int r;
     283                 :            : 
     284                 :          0 :         r = address_get(link, family, in_addr, prefixlen, &address);
     285         [ #  # ]:          0 :         if (r == -ENOENT) {
     286                 :            :                 /* Address does not exist, create a new one */
     287                 :          0 :                 r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address);
     288         [ #  # ]:          0 :                 if (r < 0)
     289                 :          0 :                         return r;
     290         [ #  # ]:          0 :         } else if (r == 0) {
     291                 :            :                 /* Take over a foreign address */
     292                 :          0 :                 r = set_ensure_allocated(&link->addresses, &address_hash_ops);
     293         [ #  # ]:          0 :                 if (r < 0)
     294                 :          0 :                         return r;
     295                 :            : 
     296                 :          0 :                 r = set_put(link->addresses, address);
     297         [ #  # ]:          0 :                 if (r < 0)
     298                 :          0 :                         return r;
     299                 :            : 
     300                 :          0 :                 set_remove(link->addresses_foreign, address);
     301         [ #  # ]:          0 :         } else if (r == 1) {
     302                 :            :                 /* Already exists, do nothing */
     303                 :            :                 ;
     304                 :            :         } else
     305                 :          0 :                 return r;
     306                 :            : 
     307         [ #  # ]:          0 :         if (ret)
     308                 :          0 :                 *ret = address;
     309                 :            : 
     310                 :          0 :         return 0;
     311                 :            : }
     312                 :            : 
     313                 :          0 : static int address_release(Address *address) {
     314                 :            :         int r;
     315                 :            : 
     316         [ #  # ]:          0 :         assert(address);
     317         [ #  # ]:          0 :         assert(address->link);
     318                 :            : 
     319                 :            :         /* Remove masquerading firewall entry if it was added */
     320         [ #  # ]:          0 :         if (address->ip_masquerade_done) {
     321                 :          0 :                 union in_addr_union masked = address->in_addr;
     322                 :          0 :                 in_addr_mask(address->family, &masked, address->prefixlen);
     323                 :            : 
     324                 :          0 :                 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
     325         [ #  # ]:          0 :                 if (r < 0)
     326                 :          0 :                         return r;
     327                 :            : 
     328                 :          0 :                 address->ip_masquerade_done = false;
     329                 :            :         }
     330                 :            : 
     331                 :          0 :         return 0;
     332                 :            : }
     333                 :            : 
     334                 :          0 : int address_update(
     335                 :            :                 Address *address,
     336                 :            :                 unsigned char flags,
     337                 :            :                 unsigned char scope,
     338                 :            :                 const struct ifa_cacheinfo *cinfo) {
     339                 :            : 
     340                 :            :         bool ready;
     341                 :            :         int r;
     342                 :            : 
     343         [ #  # ]:          0 :         assert(address);
     344         [ #  # ]:          0 :         assert(cinfo);
     345   [ #  #  #  # ]:          0 :         assert_return(address->link, 1);
     346                 :            : 
     347   [ #  #  #  # ]:          0 :         if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     348                 :          0 :                 return 1;
     349                 :            : 
     350                 :          0 :         ready = address_is_ready(address);
     351                 :            : 
     352                 :          0 :         address->flags = flags;
     353                 :          0 :         address->scope = scope;
     354                 :          0 :         address->cinfo = *cinfo;
     355                 :            : 
     356                 :          0 :         link_update_operstate(address->link, true);
     357                 :          0 :         link_check_ready(address->link);
     358                 :            : 
     359   [ #  #  #  # ]:          0 :         if (!ready &&
     360                 :          0 :             address_is_ready(address) &&
     361   [ #  #  #  # ]:          0 :             address->family == AF_INET6 &&
     362         [ #  # ]:          0 :             in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
     363                 :          0 :             in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
     364                 :            : 
     365                 :          0 :                 r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
     366         [ #  # ]:          0 :                 if (r < 0)
     367                 :          0 :                         return r;
     368                 :            :         }
     369                 :            : 
     370                 :          0 :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :          0 : int address_drop(Address *address) {
     374                 :            :         Link *link;
     375                 :            :         bool ready;
     376                 :            :         int r;
     377                 :            : 
     378         [ #  # ]:          0 :         assert(address);
     379                 :            : 
     380                 :          0 :         ready = address_is_ready(address);
     381                 :          0 :         link = address->link;
     382                 :            : 
     383                 :          0 :         r = address_release(address);
     384         [ #  # ]:          0 :         if (r < 0)
     385   [ #  #  #  # ]:          0 :                 log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m");
     386                 :            : 
     387                 :          0 :         address_free(address);
     388                 :            : 
     389                 :          0 :         link_update_operstate(link, true);
     390                 :            : 
     391   [ #  #  #  # ]:          0 :         if (link && !ready)
     392                 :          0 :                 link_check_ready(link);
     393                 :            : 
     394                 :          0 :         return 0;
     395                 :            : }
     396                 :            : 
     397                 :          0 : int address_get(Link *link,
     398                 :            :                 int family,
     399                 :            :                 const union in_addr_union *in_addr,
     400                 :            :                 unsigned char prefixlen,
     401                 :            :                 Address **ret) {
     402                 :            : 
     403                 :            :         Address address, *existing;
     404                 :            : 
     405         [ #  # ]:          0 :         assert(link);
     406         [ #  # ]:          0 :         assert(in_addr);
     407                 :            : 
     408                 :          0 :         address = (Address) {
     409                 :            :                 .family = family,
     410                 :          0 :                 .in_addr = *in_addr,
     411                 :            :                 .prefixlen = prefixlen,
     412                 :            :         };
     413                 :            : 
     414                 :          0 :         existing = set_get(link->addresses, &address);
     415         [ #  # ]:          0 :         if (existing) {
     416         [ #  # ]:          0 :                 if (ret)
     417                 :          0 :                         *ret = existing;
     418                 :          0 :                 return 1;
     419                 :            :         }
     420                 :            : 
     421                 :          0 :         existing = set_get(link->addresses_foreign, &address);
     422         [ #  # ]:          0 :         if (existing) {
     423         [ #  # ]:          0 :                 if (ret)
     424                 :          0 :                         *ret = existing;
     425                 :          0 :                 return 0;
     426                 :            :         }
     427                 :            : 
     428                 :          0 :         return -ENOENT;
     429                 :            : }
     430                 :            : 
     431                 :          0 : static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
     432                 :            :         int r;
     433                 :            : 
     434         [ #  # ]:          0 :         assert(m);
     435         [ #  # ]:          0 :         assert(link);
     436         [ #  # ]:          0 :         assert(link->ifname);
     437                 :            : 
     438   [ #  #  #  # ]:          0 :         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
     439                 :          0 :                 return 1;
     440                 :            : 
     441                 :          0 :         r = sd_netlink_message_get_errno(m);
     442   [ #  #  #  # ]:          0 :         if (r < 0 && r != -EADDRNOTAVAIL)
     443   [ #  #  #  # ]:          0 :                 log_link_warning_errno(link, r, "Could not drop address: %m");
     444                 :            : 
     445                 :          0 :         return 1;
     446                 :            : }
     447                 :            : 
     448                 :          0 : int address_remove(
     449                 :            :                 Address *address,
     450                 :            :                 Link *link,
     451                 :            :                 link_netlink_message_handler_t callback) {
     452                 :            : 
     453                 :          0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
     454                 :            :         int r;
     455                 :            : 
     456         [ #  # ]:          0 :         assert(address);
     457   [ #  #  #  # ]:          0 :         assert(IN_SET(address->family, AF_INET, AF_INET6));
     458         [ #  # ]:          0 :         assert(link);
     459         [ #  # ]:          0 :         assert(link->ifindex > 0);
     460         [ #  # ]:          0 :         assert(link->manager);
     461         [ #  # ]:          0 :         assert(link->manager->rtnl);
     462                 :            : 
     463         [ #  # ]:          0 :         if (DEBUG_LOGGING) {
     464                 :          0 :                 _cleanup_free_ char *b = NULL;
     465                 :            : 
     466                 :          0 :                 (void) in_addr_to_string(address->family, &address->in_addr, &b);
     467   [ #  #  #  # ]:          0 :                 log_link_debug(link, "Removing address %s", strna(b));
     468                 :            :         }
     469                 :            : 
     470                 :          0 :         r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
     471                 :            :                                      link->ifindex, address->family);
     472         [ #  # ]:          0 :         if (r < 0)
     473   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
     474                 :            : 
     475                 :          0 :         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
     476         [ #  # ]:          0 :         if (r < 0)
     477   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not set prefixlen: %m");
     478                 :            : 
     479                 :          0 :         r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
     480         [ #  # ]:          0 :         if (r < 0)
     481   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
     482                 :            : 
     483         [ #  # ]:          0 :         r = netlink_call_async(link->manager->rtnl, NULL, req,
     484                 :            :                                callback ?: address_remove_handler,
     485                 :            :                                link_netlink_destroy_callback, link);
     486         [ #  # ]:          0 :         if (r < 0)
     487   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
     488                 :            : 
     489                 :          0 :         link_ref(link);
     490                 :            : 
     491                 :          0 :         return 0;
     492                 :            : }
     493                 :            : 
     494                 :          0 : static int address_acquire(Link *link, Address *original, Address **ret) {
     495                 :          0 :         union in_addr_union in_addr = IN_ADDR_NULL;
     496                 :          0 :         struct in_addr broadcast = {};
     497                 :          0 :         _cleanup_(address_freep) Address *na = NULL;
     498                 :            :         int r;
     499                 :            : 
     500         [ #  # ]:          0 :         assert(link);
     501         [ #  # ]:          0 :         assert(original);
     502         [ #  # ]:          0 :         assert(ret);
     503                 :            : 
     504                 :            :         /* Something useful was configured? just use it */
     505                 :          0 :         r = in_addr_is_null(original->family, &original->in_addr);
     506         [ #  # ]:          0 :         if (r <= 0)
     507                 :          0 :                 return r;
     508                 :            : 
     509                 :            :         /* The address is configured to be 0.0.0.0 or [::] by the user?
     510                 :            :          * Then let's acquire something more useful from the pool. */
     511                 :          0 :         r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
     512         [ #  # ]:          0 :         if (r < 0)
     513                 :          0 :                 return r;
     514         [ #  # ]:          0 :         if (r == 0)
     515                 :          0 :                 return -EBUSY;
     516                 :            : 
     517         [ #  # ]:          0 :         if (original->family == AF_INET) {
     518                 :            :                 /* Pick first address in range for ourselves ... */
     519                 :          0 :                 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
     520                 :            : 
     521                 :            :                 /* .. and use last as broadcast address */
     522         [ #  # ]:          0 :                 if (original->prefixlen > 30)
     523                 :          0 :                         broadcast.s_addr = 0;
     524                 :            :                 else
     525                 :          0 :                         broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
     526         [ #  # ]:          0 :         } else if (original->family == AF_INET6)
     527                 :          0 :                 in_addr.in6.s6_addr[15] |= 1;
     528                 :            : 
     529                 :          0 :         r = address_new(&na);
     530         [ #  # ]:          0 :         if (r < 0)
     531                 :          0 :                 return r;
     532                 :            : 
     533                 :          0 :         na->family = original->family;
     534                 :          0 :         na->prefixlen = original->prefixlen;
     535                 :          0 :         na->scope = original->scope;
     536                 :          0 :         na->cinfo = original->cinfo;
     537                 :            : 
     538         [ #  # ]:          0 :         if (original->label) {
     539                 :          0 :                 na->label = strdup(original->label);
     540         [ #  # ]:          0 :                 if (!na->label)
     541                 :          0 :                         return -ENOMEM;
     542                 :            :         }
     543                 :            : 
     544                 :          0 :         na->broadcast = broadcast;
     545                 :          0 :         na->in_addr = in_addr;
     546                 :            : 
     547   [ #  #  #  # ]:          0 :         LIST_PREPEND(addresses, link->pool_addresses, na);
     548                 :            : 
     549                 :          0 :         *ret = TAKE_PTR(na);
     550                 :            : 
     551                 :          0 :         return 0;
     552                 :            : }
     553                 :            : 
     554                 :          0 : int address_configure(
     555                 :            :                 Address *address,
     556                 :            :                 Link *link,
     557                 :            :                 link_netlink_message_handler_t callback,
     558                 :            :                 bool update) {
     559                 :            : 
     560                 :          0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
     561                 :            :         int r;
     562                 :            : 
     563         [ #  # ]:          0 :         assert(address);
     564   [ #  #  #  # ]:          0 :         assert(IN_SET(address->family, AF_INET, AF_INET6));
     565         [ #  # ]:          0 :         assert(link);
     566         [ #  # ]:          0 :         assert(link->ifindex > 0);
     567         [ #  # ]:          0 :         assert(link->manager);
     568         [ #  # ]:          0 :         assert(link->manager->rtnl);
     569         [ #  # ]:          0 :         assert(callback);
     570                 :            : 
     571   [ #  #  #  # ]:          0 :         if (address->family == AF_INET6 && link_sysctl_ipv6_enabled(link) == 0) {
     572   [ #  #  #  # ]:          0 :                 log_link_warning(link, "An IPv6 address is requested, but IPv6 is disabled by sysctl, ignoring.");
     573                 :          0 :                 return 0;
     574                 :            :         }
     575                 :            : 
     576                 :            :         /* If this is a new address, then refuse adding more than the limit */
     577   [ #  #  #  # ]:          0 :         if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
     578                 :          0 :             set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
     579   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
     580                 :            :                                             "Too many addresses are configured, refusing: %m");
     581                 :            : 
     582                 :          0 :         r = address_acquire(link, address, &address);
     583         [ #  # ]:          0 :         if (r < 0)
     584   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
     585                 :            : 
     586         [ #  # ]:          0 :         if (update)
     587                 :          0 :                 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
     588                 :          0 :                                                     link->ifindex, address->family);
     589                 :            :         else
     590                 :          0 :                 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
     591                 :          0 :                                              link->ifindex, address->family);
     592         [ #  # ]:          0 :         if (r < 0)
     593   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
     594                 :            : 
     595                 :          0 :         r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
     596         [ #  # ]:          0 :         if (r < 0)
     597   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not set prefixlen: %m");
     598                 :            : 
     599                 :          0 :         address->flags |= IFA_F_PERMANENT;
     600                 :            : 
     601         [ #  # ]:          0 :         if (address->home_address)
     602                 :          0 :                 address->flags |= IFA_F_HOMEADDRESS;
     603                 :            : 
     604         [ #  # ]:          0 :         if (address->duplicate_address_detection)
     605                 :          0 :                 address->flags |= IFA_F_NODAD;
     606                 :            : 
     607         [ #  # ]:          0 :         if (address->manage_temporary_address)
     608                 :          0 :                 address->flags |= IFA_F_MANAGETEMPADDR;
     609                 :            : 
     610         [ #  # ]:          0 :         if (address->prefix_route)
     611                 :          0 :                 address->flags |= IFA_F_NOPREFIXROUTE;
     612                 :            : 
     613         [ #  # ]:          0 :         if (address->autojoin)
     614                 :          0 :                 address->flags |= IFA_F_MCAUTOJOIN;
     615                 :            : 
     616                 :          0 :         r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
     617         [ #  # ]:          0 :         if (r < 0)
     618   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not set flags: %m");
     619                 :            : 
     620         [ #  # ]:          0 :         if (address->flags & ~0xff) {
     621                 :          0 :                 r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
     622         [ #  # ]:          0 :                 if (r < 0)
     623   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not set extended flags: %m");
     624                 :            :         }
     625                 :            : 
     626                 :          0 :         r = sd_rtnl_message_addr_set_scope(req, address->scope);
     627         [ #  # ]:          0 :         if (r < 0)
     628   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not set scope: %m");
     629                 :            : 
     630                 :          0 :         r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
     631         [ #  # ]:          0 :         if (r < 0)
     632   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
     633                 :            : 
     634         [ #  # ]:          0 :         if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
     635                 :          0 :                 r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
     636         [ #  # ]:          0 :                 if (r < 0)
     637   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
     638   [ #  #  #  # ]:          0 :         } else if (address->family == AF_INET && address->prefixlen <= 30) {
     639                 :          0 :                 r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
     640         [ #  # ]:          0 :                 if (r < 0)
     641   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
     642                 :            :         }
     643                 :            : 
     644         [ #  # ]:          0 :         if (address->label) {
     645                 :          0 :                 r = sd_netlink_message_append_string(req, IFA_LABEL, address->label);
     646         [ #  # ]:          0 :                 if (r < 0)
     647   [ #  #  #  # ]:          0 :                         return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
     648                 :            :         }
     649                 :            : 
     650                 :          0 :         r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
     651         [ #  # ]:          0 :         if (r < 0)
     652   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
     653                 :            : 
     654                 :          0 :         r = address_establish(address, link);
     655         [ #  # ]:          0 :         if (r < 0)
     656   [ #  #  #  # ]:          0 :                 log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m");
     657                 :            : 
     658                 :          0 :         r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
     659         [ #  # ]:          0 :         if (r < 0) {
     660                 :          0 :                 address_release(address);
     661   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
     662                 :            :         }
     663                 :            : 
     664                 :          0 :         link_ref(link);
     665                 :            : 
     666   [ #  #  #  # ]:          0 :         if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
     667                 :          0 :                 r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL);
     668                 :            :         else
     669                 :          0 :                 r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
     670         [ #  # ]:          0 :         if (r < 0) {
     671                 :          0 :                 address_release(address);
     672   [ #  #  #  # ]:          0 :                 return log_link_error_errno(link, r, "Could not add address: %m");
     673                 :            :         }
     674                 :            : 
     675                 :          0 :         return 1;
     676                 :            : }
     677                 :            : 
     678                 :          0 : int config_parse_broadcast(
     679                 :            :                 const char *unit,
     680                 :            :                 const char *filename,
     681                 :            :                 unsigned line,
     682                 :            :                 const char *section,
     683                 :            :                 unsigned section_line,
     684                 :            :                 const char *lvalue,
     685                 :            :                 int ltype,
     686                 :            :                 const char *rvalue,
     687                 :            :                 void *data,
     688                 :            :                 void *userdata) {
     689                 :            : 
     690                 :          0 :         Network *network = userdata;
     691                 :          0 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     692                 :            :         int r;
     693                 :            : 
     694         [ #  # ]:          0 :         assert(filename);
     695         [ #  # ]:          0 :         assert(section);
     696         [ #  # ]:          0 :         assert(lvalue);
     697         [ #  # ]:          0 :         assert(rvalue);
     698         [ #  # ]:          0 :         assert(data);
     699                 :            : 
     700                 :          0 :         r = address_new_static(network, filename, section_line, &n);
     701         [ #  # ]:          0 :         if (r < 0)
     702                 :          0 :                 return r;
     703                 :            : 
     704         [ #  # ]:          0 :         if (n->family == AF_INET6) {
     705         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     706                 :            :                            "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
     707                 :          0 :                 return 0;
     708                 :            :         }
     709                 :            : 
     710                 :          0 :         r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
     711         [ #  # ]:          0 :         if (r < 0) {
     712         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     713                 :            :                            "Broadcast is invalid, ignoring assignment: %s", rvalue);
     714                 :          0 :                 return 0;
     715                 :            :         }
     716                 :            : 
     717                 :          0 :         n->family = AF_INET;
     718                 :          0 :         n = NULL;
     719                 :            : 
     720                 :          0 :         return 0;
     721                 :            : }
     722                 :            : 
     723                 :        100 : int config_parse_address(const char *unit,
     724                 :            :                 const char *filename,
     725                 :            :                 unsigned line,
     726                 :            :                 const char *section,
     727                 :            :                 unsigned section_line,
     728                 :            :                 const char *lvalue,
     729                 :            :                 int ltype,
     730                 :            :                 const char *rvalue,
     731                 :            :                 void *data,
     732                 :            :                 void *userdata) {
     733                 :            : 
     734                 :        100 :         Network *network = userdata;
     735                 :        100 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     736                 :            :         union in_addr_union buffer;
     737                 :            :         unsigned char prefixlen;
     738                 :            :         int r, f;
     739                 :            : 
     740         [ -  + ]:        100 :         assert(filename);
     741         [ -  + ]:        100 :         assert(section);
     742         [ -  + ]:        100 :         assert(lvalue);
     743         [ -  + ]:        100 :         assert(rvalue);
     744         [ -  + ]:        100 :         assert(data);
     745                 :            : 
     746         [ +  + ]:        100 :         if (streq(section, "Network")) {
     747                 :            :                 /* we are not in an Address section, so treat
     748                 :            :                  * this as the special '0' section */
     749                 :          8 :                 r = address_new_static(network, NULL, 0, &n);
     750                 :            :         } else
     751                 :         92 :                 r = address_new_static(network, filename, section_line, &n);
     752                 :            : 
     753         [ -  + ]:        100 :         if (r < 0)
     754                 :          0 :                 return r;
     755                 :            : 
     756                 :            :         /* Address=address/prefixlen */
     757                 :        100 :         r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
     758         [ +  + ]:        100 :         if (r == -ENOANO) {
     759         [ +  - ]:          8 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     760                 :            :                            "An address '%s' is specified without prefix length. "
     761                 :            :                            "The behavior of parsing addresses without prefix length will be changed in the future release. "
     762                 :            :                            "Please specify prefix length explicitly.", rvalue);
     763                 :            : 
     764                 :          8 :                 r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_LEGACY, &f, &buffer, &prefixlen);
     765                 :            :         }
     766         [ +  + ]:        100 :         if (r < 0) {
     767         [ +  - ]:         40 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
     768                 :         40 :                 return 0;
     769                 :            :         }
     770                 :            : 
     771   [ -  +  #  # ]:         60 :         if (n->family != AF_UNSPEC && f != n->family) {
     772         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
     773                 :          0 :                 return 0;
     774                 :            :         }
     775                 :            : 
     776         [ +  + ]:         60 :         if (in_addr_is_null(f, &buffer)) {
     777                 :            :                 /* Will use address from address pool. Note that for ipv6 case, prefix of the address
     778                 :            :                  * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
     779                 :            :                  * let's limit the prefix length to 64 or larger. See RFC4193. */
     780   [ +  -  +  - ]:          8 :                 if ((f == AF_INET && prefixlen < 8) ||
     781   [ -  +  #  # ]:          8 :                     (f == AF_INET6 && prefixlen < 64)) {
     782         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     783                 :            :                                    "Null address with invalid prefixlen='%u', ignoring assignment: %s",
     784                 :            :                                    prefixlen, rvalue);
     785                 :          0 :                         return 0;
     786                 :            :                 }
     787                 :            :         }
     788                 :            : 
     789                 :         60 :         n->family = f;
     790                 :         60 :         n->prefixlen = prefixlen;
     791                 :            : 
     792         [ +  - ]:         60 :         if (streq(lvalue, "Address"))
     793                 :         60 :                 n->in_addr = buffer;
     794                 :            :         else
     795                 :          0 :                 n->in_addr_peer = buffer;
     796                 :            : 
     797   [ +  +  +  -  :         60 :         if (n->family == AF_INET && n->broadcast.s_addr == 0 && n->prefixlen <= 30)
                   +  + ]
     798                 :         24 :                 n->broadcast.s_addr = n->in_addr.in.s_addr | htobe32(0xfffffffflu >> n->prefixlen);
     799                 :            : 
     800                 :         60 :         n = NULL;
     801                 :            : 
     802                 :         60 :         return 0;
     803                 :            : }
     804                 :            : 
     805                 :          0 : int config_parse_label(
     806                 :            :                 const char *unit,
     807                 :            :                 const char *filename,
     808                 :            :                 unsigned line,
     809                 :            :                 const char *section,
     810                 :            :                 unsigned section_line,
     811                 :            :                 const char *lvalue,
     812                 :            :                 int ltype,
     813                 :            :                 const char *rvalue,
     814                 :            :                 void *data,
     815                 :            :                 void *userdata) {
     816                 :            : 
     817                 :          0 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     818                 :          0 :         Network *network = userdata;
     819                 :            :         int r;
     820                 :            : 
     821         [ #  # ]:          0 :         assert(filename);
     822         [ #  # ]:          0 :         assert(section);
     823         [ #  # ]:          0 :         assert(lvalue);
     824         [ #  # ]:          0 :         assert(rvalue);
     825         [ #  # ]:          0 :         assert(data);
     826                 :            : 
     827                 :          0 :         r = address_new_static(network, filename, section_line, &n);
     828         [ #  # ]:          0 :         if (r < 0)
     829                 :          0 :                 return r;
     830                 :            : 
     831         [ #  # ]:          0 :         if (!address_label_valid(rvalue)) {
     832         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     833                 :            :                            "Interface label is too long or invalid, ignoring assignment: %s", rvalue);
     834                 :          0 :                 return 0;
     835                 :            :         }
     836                 :            : 
     837                 :          0 :         r = free_and_strdup(&n->label, rvalue);
     838         [ #  # ]:          0 :         if (r < 0)
     839                 :          0 :                 return log_oom();
     840                 :            : 
     841                 :          0 :         n = NULL;
     842                 :          0 :         return 0;
     843                 :            : }
     844                 :            : 
     845                 :          0 : int config_parse_lifetime(const char *unit,
     846                 :            :                           const char *filename,
     847                 :            :                           unsigned line,
     848                 :            :                           const char *section,
     849                 :            :                           unsigned section_line,
     850                 :            :                           const char *lvalue,
     851                 :            :                           int ltype,
     852                 :            :                           const char *rvalue,
     853                 :            :                           void *data,
     854                 :            :                           void *userdata) {
     855                 :          0 :         Network *network = userdata;
     856                 :          0 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     857                 :            :         unsigned k;
     858                 :            :         int r;
     859                 :            : 
     860         [ #  # ]:          0 :         assert(filename);
     861         [ #  # ]:          0 :         assert(section);
     862         [ #  # ]:          0 :         assert(lvalue);
     863         [ #  # ]:          0 :         assert(rvalue);
     864         [ #  # ]:          0 :         assert(data);
     865                 :            : 
     866                 :          0 :         r = address_new_static(network, filename, section_line, &n);
     867         [ #  # ]:          0 :         if (r < 0)
     868                 :          0 :                 return r;
     869                 :            : 
     870                 :            :         /* We accept only "forever", "infinity", or "0". */
     871         [ #  # ]:          0 :         if (STR_IN_SET(rvalue, "forever", "infinity"))
     872                 :          0 :                 k = CACHE_INFO_INFINITY_LIFE_TIME;
     873         [ #  # ]:          0 :         else if (streq(rvalue, "0"))
     874                 :          0 :                 k = 0;
     875                 :            :         else {
     876         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, 0,
     877                 :            :                            "Invalid PreferredLifetime= value, ignoring: %s", rvalue);
     878                 :          0 :                 return 0;
     879                 :            :         }
     880                 :            : 
     881                 :          0 :         n->cinfo.ifa_prefered = k;
     882                 :          0 :         n = NULL;
     883                 :            : 
     884                 :          0 :         return 0;
     885                 :            : }
     886                 :            : 
     887                 :          0 : int config_parse_address_flags(const char *unit,
     888                 :            :                                const char *filename,
     889                 :            :                                unsigned line,
     890                 :            :                                const char *section,
     891                 :            :                                unsigned section_line,
     892                 :            :                                const char *lvalue,
     893                 :            :                                int ltype,
     894                 :            :                                const char *rvalue,
     895                 :            :                                void *data,
     896                 :            :                                void *userdata) {
     897                 :          0 :         Network *network = userdata;
     898                 :          0 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     899                 :            :         int r;
     900                 :            : 
     901         [ #  # ]:          0 :         assert(filename);
     902         [ #  # ]:          0 :         assert(section);
     903         [ #  # ]:          0 :         assert(lvalue);
     904         [ #  # ]:          0 :         assert(rvalue);
     905         [ #  # ]:          0 :         assert(data);
     906                 :            : 
     907                 :          0 :         r = address_new_static(network, filename, section_line, &n);
     908         [ #  # ]:          0 :         if (r < 0)
     909                 :          0 :                 return r;
     910                 :            : 
     911                 :          0 :         r = parse_boolean(rvalue);
     912         [ #  # ]:          0 :         if (r < 0) {
     913         [ #  # ]:          0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     914                 :            :                            "Failed to parse address flag, ignoring: %s", rvalue);
     915                 :          0 :                 return 0;
     916                 :            :         }
     917                 :            : 
     918         [ #  # ]:          0 :         if (streq(lvalue, "HomeAddress"))
     919                 :          0 :                 n->home_address = r;
     920         [ #  # ]:          0 :         else if (streq(lvalue, "DuplicateAddressDetection"))
     921                 :          0 :                 n->duplicate_address_detection = r;
     922         [ #  # ]:          0 :         else if (streq(lvalue, "ManageTemporaryAddress"))
     923                 :          0 :                 n->manage_temporary_address = r;
     924         [ #  # ]:          0 :         else if (streq(lvalue, "PrefixRoute"))
     925                 :          0 :                 n->prefix_route = r;
     926         [ #  # ]:          0 :         else if (streq(lvalue, "AutoJoin"))
     927                 :          0 :                 n->autojoin = r;
     928                 :            :         else
     929                 :          0 :                 assert_not_reached("Invalid address flag type.");
     930                 :            : 
     931                 :          0 :         n = NULL;
     932                 :          0 :         return 0;
     933                 :            : }
     934                 :            : 
     935                 :          0 : int config_parse_address_scope(const char *unit,
     936                 :            :                                const char *filename,
     937                 :            :                                unsigned line,
     938                 :            :                                const char *section,
     939                 :            :                                unsigned section_line,
     940                 :            :                                const char *lvalue,
     941                 :            :                                int ltype,
     942                 :            :                                const char *rvalue,
     943                 :            :                                void *data,
     944                 :            :                                void *userdata) {
     945                 :          0 :         Network *network = userdata;
     946                 :          0 :         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
     947                 :            :         int r;
     948                 :            : 
     949         [ #  # ]:          0 :         assert(filename);
     950         [ #  # ]:          0 :         assert(section);
     951         [ #  # ]:          0 :         assert(lvalue);
     952         [ #  # ]:          0 :         assert(rvalue);
     953         [ #  # ]:          0 :         assert(data);
     954                 :            : 
     955                 :          0 :         r = address_new_static(network, filename, section_line, &n);
     956         [ #  # ]:          0 :         if (r < 0)
     957                 :          0 :                 return r;
     958                 :            : 
     959         [ #  # ]:          0 :         if (streq(rvalue, "host"))
     960                 :          0 :                 n->scope = RT_SCOPE_HOST;
     961         [ #  # ]:          0 :         else if (streq(rvalue, "link"))
     962                 :          0 :                 n->scope = RT_SCOPE_LINK;
     963         [ #  # ]:          0 :         else if (streq(rvalue, "global"))
     964                 :          0 :                 n->scope = RT_SCOPE_UNIVERSE;
     965                 :            :         else {
     966                 :          0 :                 r = safe_atou8(rvalue , &n->scope);
     967         [ #  # ]:          0 :                 if (r < 0) {
     968         [ #  # ]:          0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     969                 :            :                                    "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue);
     970                 :          0 :                         return 0;
     971                 :            :                 }
     972                 :            :         }
     973                 :            : 
     974                 :          0 :         n = NULL;
     975                 :          0 :         return 0;
     976                 :            : }
     977                 :            : 
     978                 :          0 : bool address_is_ready(const Address *a) {
     979         [ #  # ]:          0 :         assert(a);
     980                 :            : 
     981                 :          0 :         return !(a->flags & IFA_F_TENTATIVE);
     982                 :            : }
     983                 :            : 
     984                 :        100 : int address_section_verify(Address *address) {
     985         [ +  + ]:        100 :         if (section_is_invalid(address->section))
     986                 :         40 :                 return -EINVAL;
     987                 :            : 
     988         [ -  + ]:         60 :         if (address->family == AF_UNSPEC) {
     989         [ #  # ]:          0 :                 assert(address->section);
     990                 :            : 
     991         [ #  # ]:          0 :                 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
     992                 :            :                                          "%s: Address section without Address= field configured. "
     993                 :            :                                          "Ignoring [Address] section from line %u.",
     994                 :            :                                          address->section->filename, address->section->line);
     995                 :            :         }
     996                 :            : 
     997                 :         60 :         return 0;
     998                 :            : }

Generated by: LCOV version 1.14