LCOV - code coverage report
Current view: top level - network - networkd-address.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 105 536 19.6 %
Date: 2019-08-22 15:41:25 Functions: 7 26 26.9 %

          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          27 : int address_new(Address **ret) {
      24          27 :         _cleanup_(address_freep) Address *address = NULL;
      25             : 
      26          27 :         address = new(Address, 1);
      27          27 :         if (!address)
      28           0 :                 return -ENOMEM;
      29             : 
      30          27 :         *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          27 :         *ret = TAKE_PTR(address);
      38             : 
      39          27 :         return 0;
      40             : }
      41             : 
      42          25 : static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
      43          25 :         _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
      44          25 :         _cleanup_(address_freep) Address *address = NULL;
      45             :         int r;
      46             : 
      47          25 :         assert(network);
      48          25 :         assert(ret);
      49          25 :         assert(!!filename == (section_line > 0));
      50             : 
      51          25 :         if (filename) {
      52          23 :                 r = network_config_section_new(filename, section_line, &n);
      53          23 :                 if (r < 0)
      54           0 :                         return r;
      55             : 
      56          23 :                 address = hashmap_get(network->addresses_by_section, n);
      57          23 :                 if (address) {
      58           0 :                         *ret = TAKE_PTR(address);
      59             : 
      60           0 :                         return 0;
      61             :                 }
      62             :         }
      63             : 
      64          25 :         if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX)
      65           0 :                 return -E2BIG;
      66             : 
      67          25 :         r = address_new(&address);
      68          25 :         if (r < 0)
      69           0 :                 return r;
      70             : 
      71          25 :         address->network = network;
      72          25 :         LIST_APPEND(addresses, network->static_addresses, address);
      73          25 :         network->n_static_addresses++;
      74             : 
      75          25 :         if (filename) {
      76          23 :                 address->section = TAKE_PTR(n);
      77             : 
      78          23 :                 r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops);
      79          23 :                 if (r < 0)
      80           0 :                         return r;
      81             : 
      82          23 :                 r = hashmap_put(network->addresses_by_section, address->section, address);
      83          23 :                 if (r < 0)
      84           0 :                         return r;
      85             :         }
      86             : 
      87          25 :         *ret = TAKE_PTR(address);
      88             : 
      89          25 :         return 0;
      90             : }
      91             : 
      92          27 : void address_free(Address *address) {
      93          27 :         if (!address)
      94           0 :                 return;
      95             : 
      96          27 :         if (address->network) {
      97          25 :                 LIST_REMOVE(addresses, address->network->static_addresses, address);
      98          25 :                 assert(address->network->n_static_addresses > 0);
      99          25 :                 address->network->n_static_addresses--;
     100             : 
     101          25 :                 if (address->section)
     102          23 :                         hashmap_remove(address->network->addresses_by_section, address->section);
     103             :         }
     104             : 
     105          27 :         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          27 :         network_config_section_free(address->section);
     114          27 :         free(address->label);
     115          27 :         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          13 : static int address_compare_func(const Address *a1, const Address *a2) {
     152             :         int r;
     153             : 
     154          13 :         r = CMP(a1->family, a2->family);
     155          13 :         if (r != 0)
     156           2 :                 return r;
     157             : 
     158          11 :         switch (a1->family) {
     159             :         /* use the same notion of equality as the kernel does */
     160           7 :         case AF_INET:
     161           7 :                 r = CMP(a1->prefixlen, a2->prefixlen);
     162           7 :                 if (r != 0)
     163           1 :                         return r;
     164             : 
     165             :                 /* compare the peer prefixes */
     166           6 :                 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           1 :                         if (a1->in_addr_peer.in.s_addr != 0)
     172           1 :                                 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           1 :                         if (a2->in_addr_peer.in.s_addr != 0)
     177           1 :                                 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           1 :                         r = CMP(b1, b2);
     182           1 :                         if (r != 0)
     183           0 :                                 return r;
     184             :                 }
     185             : 
     186             :                 _fallthrough_;
     187             :         case AF_INET6:
     188           9 :                 return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
     189           1 :         default:
     190             :                 /* treat any other address family as AF_UNSPEC */
     191           1 :                 return 0;
     192             :         }
     193             : }
     194             : 
     195             : DEFINE_PRIVATE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
     196             : 
     197          16 : bool address_equal(Address *a1, Address *a2) {
     198          16 :         if (a1 == a2)
     199           1 :                 return true;
     200             : 
     201          15 :         if (!a1 || !a2)
     202           2 :                 return false;
     203             : 
     204          13 :         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          25 : 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          25 :         Network *network = userdata;
     735          25 :         _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          25 :         assert(filename);
     741          25 :         assert(section);
     742          25 :         assert(lvalue);
     743          25 :         assert(rvalue);
     744          25 :         assert(data);
     745             : 
     746          25 :         if (streq(section, "Network")) {
     747             :                 /* we are not in an Address section, so treat
     748             :                  * this as the special '0' section */
     749           2 :                 r = address_new_static(network, NULL, 0, &n);
     750             :         } else
     751          23 :                 r = address_new_static(network, filename, section_line, &n);
     752             : 
     753          25 :         if (r < 0)
     754           0 :                 return r;
     755             : 
     756             :         /* Address=address/prefixlen */
     757          25 :         r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
     758          25 :         if (r == -ENOANO) {
     759           2 :                 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           2 :                 r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_LEGACY, &f, &buffer, &prefixlen);
     765             :         }
     766          25 :         if (r < 0) {
     767          10 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
     768          10 :                 return 0;
     769             :         }
     770             : 
     771          15 :         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          15 :         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           2 :                 if ((f == AF_INET && prefixlen < 8) ||
     781           2 :                     (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          15 :         n->family = f;
     790          15 :         n->prefixlen = prefixlen;
     791             : 
     792          15 :         if (streq(lvalue, "Address"))
     793          15 :                 n->in_addr = buffer;
     794             :         else
     795           0 :                 n->in_addr_peer = buffer;
     796             : 
     797          15 :         if (n->family == AF_INET && n->broadcast.s_addr == 0 && n->prefixlen <= 30)
     798           6 :                 n->broadcast.s_addr = n->in_addr.in.s_addr | htobe32(0xfffffffflu >> n->prefixlen);
     799             : 
     800          15 :         n = NULL;
     801             : 
     802          15 :         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          25 : int address_section_verify(Address *address) {
     985          25 :         if (section_is_invalid(address->section))
     986          10 :                 return -EINVAL;
     987             : 
     988          15 :         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          15 :         return 0;
     998             : }

Generated by: LCOV version 1.14