LCOV - code coverage report
Current view: top level - network - networkd-address-pool.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 25 67 37.3 %
Date: 2015-07-29 18:47:03 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
       2             : 
       3             : /***
       4             :   This file is part of systemd.
       5             : 
       6             :   Copyright 2014 Lennart Poettering
       7             : 
       8             :   systemd is free software; you can redistribute it and/or modify it
       9             :   under the terms of the GNU Lesser General Public License as published by
      10             :   the Free Software Foundation; either version 2.1 of the License, or
      11             :   (at your option) any later version.
      12             : 
      13             :   systemd is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      16             :   Lesser General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU Lesser General Public License
      19             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      20             : ***/
      21             : 
      22             : 
      23             : #include "networkd.h"
      24             : #include "networkd-link.h"
      25             : 
      26           4 : int address_pool_new(
      27             :                 Manager *m,
      28             :                 AddressPool **ret,
      29             :                 int family,
      30             :                 const union in_addr_union *u,
      31             :                 unsigned prefixlen) {
      32             : 
      33             :         AddressPool *p;
      34             : 
      35           4 :         assert(m);
      36           4 :         assert(ret);
      37           4 :         assert(u);
      38             : 
      39           4 :         p = new0(AddressPool, 1);
      40           4 :         if (!p)
      41           0 :                 return -ENOMEM;
      42             : 
      43           4 :         p->manager = m;
      44           4 :         p->family = family;
      45           4 :         p->prefixlen = prefixlen;
      46           4 :         p->in_addr = *u;
      47             : 
      48           4 :         LIST_PREPEND(address_pools, m->address_pools, p);
      49             : 
      50           4 :         *ret = p;
      51           4 :         return 0;
      52             : }
      53             : 
      54           4 : int address_pool_new_from_string(
      55             :                 Manager *m,
      56             :                 AddressPool **ret,
      57             :                 int family,
      58             :                 const char *p,
      59             :                 unsigned prefixlen) {
      60             : 
      61             :         union in_addr_union u;
      62             :         int r;
      63             : 
      64           4 :         assert(m);
      65           4 :         assert(ret);
      66           4 :         assert(p);
      67             : 
      68           4 :         r = in_addr_from_string(family, p, &u);
      69           4 :         if (r < 0)
      70           0 :                 return r;
      71             : 
      72           4 :         return address_pool_new(m, ret, family, &u, prefixlen);
      73             : }
      74             : 
      75           4 : void address_pool_free(AddressPool *p) {
      76             : 
      77           4 :         if (!p)
      78           0 :                 return;
      79             : 
      80           4 :         if (p->manager)
      81           4 :                 LIST_REMOVE(address_pools, p->manager->address_pools, p);
      82             : 
      83           4 :         free(p);
      84             : }
      85             : 
      86           0 : static bool address_pool_prefix_is_taken(
      87             :                 AddressPool *p,
      88             :                 const union in_addr_union *u,
      89             :                 unsigned prefixlen) {
      90             : 
      91             :         Iterator i;
      92             :         Link *l;
      93             :         Network *n;
      94             : 
      95           0 :         assert(p);
      96           0 :         assert(u);
      97             : 
      98           0 :         HASHMAP_FOREACH(l, p->manager->links, i) {
      99             :                 Address *a;
     100             : 
     101             :                 /* Don't clash with assigned addresses */
     102           0 :                 LIST_FOREACH(addresses, a, l->addresses) {
     103           0 :                         if (a->family != p->family)
     104           0 :                                 continue;
     105             : 
     106           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
     107           0 :                                 return true;
     108             :                 }
     109             : 
     110             :                 /* Don't clash with addresses already pulled from the pool, but not assigned yet */
     111           0 :                 LIST_FOREACH(addresses, a, l->pool_addresses) {
     112           0 :                         if (a->family != p->family)
     113           0 :                                 continue;
     114             : 
     115           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
     116           0 :                                 return true;
     117             :                 }
     118             :         }
     119             : 
     120             :         /* And don't clash with configured but un-assigned addresses either */
     121           0 :         LIST_FOREACH(networks, n, p->manager->networks) {
     122             :                 Address *a;
     123             : 
     124           0 :                 LIST_FOREACH(addresses, a, n->static_addresses) {
     125           0 :                         if (a->family != p->family)
     126           0 :                                 continue;
     127             : 
     128           0 :                         if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen))
     129           0 :                                 return true;
     130             :                 }
     131             :         }
     132             : 
     133           0 :         return false;
     134             : }
     135             : 
     136           0 : int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) {
     137             :         union in_addr_union u;
     138             : 
     139           0 :         assert(p);
     140           0 :         assert(prefixlen > 0);
     141           0 :         assert(found);
     142             : 
     143           0 :         if (p->prefixlen > prefixlen)
     144           0 :                 return 0;
     145             : 
     146           0 :         u = p->in_addr;
     147             :         for (;;) {
     148           0 :                 if (!address_pool_prefix_is_taken(p, &u, prefixlen)) {
     149           0 :                         _cleanup_free_ char *s = NULL;
     150             : 
     151           0 :                         in_addr_to_string(p->family, &u, &s);
     152           0 :                         log_debug("Found range %s/%u", strna(s), prefixlen);
     153             : 
     154           0 :                         *found = u;
     155           0 :                         return 1;
     156             :                 }
     157             : 
     158           0 :                 if (!in_addr_prefix_next(p->family, &u, prefixlen))
     159           0 :                         return 0;
     160             : 
     161           0 :                 if (!in_addr_prefix_intersect(p->family, &p->in_addr, p->prefixlen, &u, prefixlen))
     162           0 :                         return 0;
     163           0 :         }
     164             : 
     165             :         return 0;
     166             : }

Generated by: LCOV version 1.11