LCOV - code coverage report
Current view: top level - network - networkd-address-pool.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 23 66 34.8 %
Date: 2019-08-22 15:41:25 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "alloc-util.h"
       4             : #include "networkd-address-pool.h"
       5             : #include "networkd-manager.h"
       6             : #include "set.h"
       7             : #include "string-util.h"
       8             : 
       9             : #define RANDOM_PREFIX_TRIAL_MAX  1024
      10             : 
      11           4 : static int address_pool_new(
      12             :                 Manager *m,
      13             :                 AddressPool **ret,
      14             :                 int family,
      15             :                 const union in_addr_union *u,
      16             :                 unsigned prefixlen) {
      17             : 
      18             :         AddressPool *p;
      19             : 
      20           4 :         assert(m);
      21           4 :         assert(ret);
      22           4 :         assert(u);
      23             : 
      24           4 :         p = new(AddressPool, 1);
      25           4 :         if (!p)
      26           0 :                 return -ENOMEM;
      27             : 
      28           4 :         *p = (AddressPool) {
      29             :                 .manager = m,
      30             :                 .family = family,
      31             :                 .prefixlen = prefixlen,
      32           4 :                 .in_addr = *u,
      33             :         };
      34             : 
      35           4 :         LIST_PREPEND(address_pools, m->address_pools, p);
      36             : 
      37           4 :         *ret = p;
      38           4 :         return 0;
      39             : }
      40             : 
      41           4 : int address_pool_new_from_string(
      42             :                 Manager *m,
      43             :                 AddressPool **ret,
      44             :                 int family,
      45             :                 const char *p,
      46             :                 unsigned prefixlen) {
      47             : 
      48             :         union in_addr_union u;
      49             :         int r;
      50             : 
      51           4 :         assert(m);
      52           4 :         assert(ret);
      53           4 :         assert(p);
      54             : 
      55           4 :         r = in_addr_from_string(family, p, &u);
      56           4 :         if (r < 0)
      57           0 :                 return r;
      58             : 
      59           4 :         return address_pool_new(m, ret, family, &u, prefixlen);
      60             : }
      61             : 
      62           4 : void address_pool_free(AddressPool *p) {
      63             : 
      64           4 :         if (!p)
      65           0 :                 return;
      66             : 
      67           4 :         if (p->manager)
      68           4 :                 LIST_REMOVE(address_pools, p->manager->address_pools, p);
      69             : 
      70           4 :         free(p);
      71             : }
      72             : 
      73           0 : static bool address_pool_prefix_is_taken(
      74             :                 AddressPool *p,
      75             :                 const union in_addr_union *u,
      76             :                 unsigned prefixlen) {
      77             : 
      78             :         Iterator i;
      79             :         Link *l;
      80             :         Network *n;
      81             : 
      82           0 :         assert(p);
      83           0 :         assert(u);
      84             : 
      85           0 :         HASHMAP_FOREACH(l, p->manager->links, i) {
      86             :                 Address *a;
      87             :                 Iterator j;
      88             : 
      89             :                 /* Don't clash with assigned addresses */
      90           0 :                 SET_FOREACH(a, l->addresses, j) {
      91           0 :                         if (a->family != p->family)
      92           0 :                                 continue;
      93             : 
      94           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
      95           0 :                                 return true;
      96             :                 }
      97             : 
      98             :                 /* Don't clash with addresses already pulled from the pool, but not assigned yet */
      99           0 :                 LIST_FOREACH(addresses, a, l->pool_addresses) {
     100           0 :                         if (a->family != p->family)
     101           0 :                                 continue;
     102             : 
     103           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
     104           0 :                                 return true;
     105             :                 }
     106             :         }
     107             : 
     108             :         /* And don't clash with configured but un-assigned addresses either */
     109           0 :         ORDERED_HASHMAP_FOREACH(n, p->manager->networks, i) {
     110             :                 Address *a;
     111             : 
     112           0 :                 LIST_FOREACH(addresses, a, n->static_addresses) {
     113           0 :                         if (a->family != p->family)
     114           0 :                                 continue;
     115             : 
     116           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
     117           0 :                                 return true;
     118             :                 }
     119             :         }
     120             : 
     121           0 :         return false;
     122             : }
     123             : 
     124           0 : int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
     125             :         union in_addr_union u;
     126             :         unsigned i;
     127             :         int r;
     128             : 
     129           0 :         assert(p);
     130           0 :         assert(prefixlen > 0);
     131           0 :         assert(found);
     132             : 
     133           0 :         if (p->prefixlen >= prefixlen)
     134           0 :                 return 0;
     135             : 
     136           0 :         u = p->in_addr;
     137             : 
     138           0 :         for (i = 0; i < RANDOM_PREFIX_TRIAL_MAX; i++) {
     139           0 :                 r = in_addr_random_prefix(p->family, &u, p->prefixlen, prefixlen);
     140           0 :                 if (r <= 0)
     141           0 :                         return r;
     142             : 
     143           0 :                 if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
     144           0 :                         if (DEBUG_LOGGING) {
     145           0 :                                 _cleanup_free_ char *s = NULL;
     146             : 
     147           0 :                                 (void) in_addr_to_string(p->family, &u, &s);
     148           0 :                                 log_debug("Found range %s/%u", strna(s), prefixlen);
     149             :                         }
     150             : 
     151           0 :                         *found = u;
     152           0 :                         return 1;
     153             :                 }
     154             :         }
     155             : 
     156           0 :         return 0;
     157             : }

Generated by: LCOV version 1.14