LCOV - code coverage report
Current view: top level - network - networkd-dhcp-server.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 179 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "sd-dhcp-server.h"
       4             : 
       5             : #include "networkd-dhcp-server.h"
       6             : #include "networkd-link.h"
       7             : #include "networkd-manager.h"
       8             : #include "networkd-network.h"
       9             : #include "strv.h"
      10             : 
      11           0 : static Address* link_find_dhcp_server_address(Link *link) {
      12             :         Address *address;
      13             : 
      14           0 :         assert(link);
      15           0 :         assert(link->network);
      16             : 
      17             :         /* The first statically configured address if there is any */
      18           0 :         LIST_FOREACH(addresses, address, link->network->static_addresses) {
      19             : 
      20           0 :                 if (address->family != AF_INET)
      21           0 :                         continue;
      22             : 
      23           0 :                 if (in_addr_is_null(address->family, &address->in_addr))
      24           0 :                         continue;
      25             : 
      26           0 :                 return address;
      27             :         }
      28             : 
      29             :         /* If that didn't work, find a suitable address we got from the pool */
      30           0 :         LIST_FOREACH(addresses, address, link->pool_addresses) {
      31           0 :                 if (address->family != AF_INET)
      32           0 :                         continue;
      33             : 
      34           0 :                 return address;
      35             :         }
      36             : 
      37           0 :         return NULL;
      38             : }
      39             : 
      40           0 : static int link_push_uplink_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
      41           0 :         _cleanup_free_ struct in_addr *addresses = NULL;
      42           0 :         size_t n_addresses = 0, n_allocated = 0;
      43             :         unsigned i;
      44             : 
      45           0 :         log_debug("Copying DNS server information from %s", link->ifname);
      46             : 
      47           0 :         if (!link->network)
      48           0 :                 return 0;
      49             : 
      50           0 :         for (i = 0; i < link->network->n_dns; i++) {
      51             :                 struct in_addr ia;
      52             : 
      53             :                 /* Only look for IPv4 addresses */
      54           0 :                 if (link->network->dns[i].family != AF_INET)
      55           0 :                         continue;
      56             : 
      57           0 :                 ia = link->network->dns[i].address.in;
      58             : 
      59             :                 /* Never propagate obviously borked data */
      60           0 :                 if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
      61           0 :                         continue;
      62             : 
      63           0 :                 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
      64           0 :                         return log_oom();
      65             : 
      66           0 :                 addresses[n_addresses++] = ia;
      67             :         }
      68             : 
      69           0 :         if (link->network->dhcp_use_dns && link->dhcp_lease) {
      70           0 :                 const struct in_addr *da = NULL;
      71             :                 int j, n;
      72             : 
      73           0 :                 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
      74           0 :                 if (n > 0) {
      75             : 
      76           0 :                         if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
      77           0 :                                 return log_oom();
      78             : 
      79           0 :                         for (j = 0; j < n; j++)
      80           0 :                                 if (in4_addr_is_non_local(&da[j]))
      81           0 :                                         addresses[n_addresses++] = da[j];
      82             :                 }
      83             :         }
      84             : 
      85           0 :         if (n_addresses <= 0)
      86           0 :                 return 0;
      87             : 
      88           0 :         return sd_dhcp_server_set_dns(s, addresses, n_addresses);
      89             : }
      90             : 
      91           0 : static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
      92           0 :         _cleanup_free_ struct in_addr *addresses = NULL;
      93           0 :         size_t n_addresses = 0, n_allocated = 0;
      94             :         char **a;
      95             : 
      96           0 :         if (!link->network)
      97           0 :                 return 0;
      98             : 
      99           0 :         log_debug("Copying NTP server information from %s", link->ifname);
     100             : 
     101           0 :         STRV_FOREACH(a, link->network->ntp) {
     102             :                 union in_addr_union ia;
     103             : 
     104             :                 /* Only look for IPv4 addresses */
     105           0 :                 if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
     106           0 :                         continue;
     107             : 
     108             :                 /* Never propagate obviously borked data */
     109           0 :                 if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
     110           0 :                         continue;
     111             : 
     112           0 :                 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
     113           0 :                         return log_oom();
     114             : 
     115           0 :                 addresses[n_addresses++] = ia.in;
     116             :         }
     117             : 
     118           0 :         if (link->network->dhcp_use_ntp && link->dhcp_lease) {
     119           0 :                 const struct in_addr *da = NULL;
     120             :                 int j, n;
     121             : 
     122           0 :                 n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
     123           0 :                 if (n > 0) {
     124             : 
     125           0 :                         if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
     126           0 :                                 return log_oom();
     127             : 
     128           0 :                         for (j = 0; j < n; j++)
     129           0 :                                 if (in4_addr_is_non_local(&da[j]))
     130           0 :                                         addresses[n_addresses++] = da[j];
     131             :                 }
     132             :         }
     133             : 
     134           0 :         if (n_addresses <= 0)
     135           0 :                 return 0;
     136             : 
     137           0 :         return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
     138             : }
     139             : 
     140           0 : int dhcp4_server_configure(Link *link) {
     141             :         Address *address;
     142           0 :         Link *uplink = NULL;
     143           0 :         bool acquired_uplink = false;
     144             :         int r;
     145             : 
     146           0 :         address = link_find_dhcp_server_address(link);
     147           0 :         if (!address)
     148           0 :                 return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBUSY),
     149             :                                               "Failed to find suitable address for DHCPv4 server instance.");
     150             : 
     151             :         /* use the server address' subnet as the pool */
     152           0 :         r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
     153           0 :                                           link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
     154           0 :         if (r < 0)
     155           0 :                 return r;
     156             : 
     157             :         /* TODO:
     158             :         r = sd_dhcp_server_set_router(link->dhcp_server, &main_address->in_addr.in);
     159             :         if (r < 0)
     160             :                 return r;
     161             :         */
     162             : 
     163           0 :         if (link->network->dhcp_server_max_lease_time_usec > 0) {
     164           0 :                 r = sd_dhcp_server_set_max_lease_time(link->dhcp_server,
     165           0 :                                                       DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
     166           0 :                 if (r < 0)
     167           0 :                         return r;
     168             :         }
     169             : 
     170           0 :         if (link->network->dhcp_server_default_lease_time_usec > 0) {
     171           0 :                 r = sd_dhcp_server_set_default_lease_time(link->dhcp_server,
     172           0 :                                                           DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
     173           0 :                 if (r < 0)
     174           0 :                         return r;
     175             :         }
     176             : 
     177           0 :         if (link->network->dhcp_server_emit_dns) {
     178           0 :                 if (link->network->n_dhcp_server_dns > 0)
     179           0 :                         r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
     180             :                 else {
     181           0 :                         uplink = manager_find_uplink(link->manager, link);
     182           0 :                         acquired_uplink = true;
     183             : 
     184           0 :                         if (!uplink) {
     185           0 :                                 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
     186           0 :                                 r = 0;
     187             :                         } else
     188           0 :                                 r = link_push_uplink_dns_to_dhcp_server(uplink, link->dhcp_server);
     189             :                 }
     190           0 :                 if (r < 0)
     191           0 :                         log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
     192             :         }
     193             : 
     194           0 :         if (link->network->dhcp_server_emit_ntp) {
     195           0 :                 if (link->network->n_dhcp_server_ntp > 0)
     196           0 :                         r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
     197             :                 else {
     198           0 :                         if (!acquired_uplink)
     199           0 :                                 uplink = manager_find_uplink(link->manager, link);
     200             : 
     201           0 :                         if (!uplink) {
     202           0 :                                 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
     203           0 :                                 r = 0;
     204             :                         } else
     205           0 :                                 r = link_push_uplink_ntp_to_dhcp_server(uplink, link->dhcp_server);
     206             : 
     207             :                 }
     208           0 :                 if (r < 0)
     209           0 :                         log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
     210             :         }
     211             : 
     212           0 :         r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router);
     213           0 :         if (r < 0)
     214           0 :                 return log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m");
     215             : 
     216           0 :         if (link->network->dhcp_server_emit_timezone) {
     217           0 :                 _cleanup_free_ char *buffer = NULL;
     218             :                 const char *tz;
     219             : 
     220           0 :                 if (link->network->dhcp_server_timezone)
     221           0 :                         tz = link->network->dhcp_server_timezone;
     222             :                 else {
     223           0 :                         r = get_timezone(&buffer);
     224           0 :                         if (r < 0)
     225           0 :                                 return log_warning_errno(r, "Failed to determine timezone: %m");
     226             : 
     227           0 :                         tz = buffer;
     228             :                 }
     229             : 
     230           0 :                 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
     231           0 :                 if (r < 0)
     232           0 :                         return r;
     233             :         }
     234           0 :         if (!sd_dhcp_server_is_running(link->dhcp_server)) {
     235           0 :                 r = sd_dhcp_server_start(link->dhcp_server);
     236           0 :                 if (r < 0)
     237           0 :                         return log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
     238             :         }
     239             : 
     240           0 :         return 0;
     241             : }
     242             : 
     243           0 : int config_parse_dhcp_server_dns(
     244             :                 const char *unit,
     245             :                 const char *filename,
     246             :                 unsigned line,
     247             :                 const char *section,
     248             :                 unsigned section_line,
     249             :                 const char *lvalue,
     250             :                 int ltype,
     251             :                 const char *rvalue,
     252             :                 void *data,
     253             :                 void *userdata) {
     254             : 
     255           0 :         Network *n = data;
     256           0 :         const char *p = rvalue;
     257             :         int r;
     258             : 
     259           0 :         assert(filename);
     260           0 :         assert(lvalue);
     261           0 :         assert(rvalue);
     262             : 
     263           0 :         for (;;) {
     264           0 :                 _cleanup_free_ char *w = NULL;
     265             :                 union in_addr_union a;
     266             :                 struct in_addr *m;
     267             : 
     268           0 :                 r = extract_first_word(&p, &w, NULL, 0);
     269           0 :                 if (r == -ENOMEM)
     270           0 :                         return log_oom();
     271           0 :                 if (r < 0) {
     272           0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     273             :                                    "Failed to extract word, ignoring: %s", rvalue);
     274           0 :                         return 0;
     275             :                 }
     276           0 :                 if (r == 0)
     277           0 :                         break;
     278             : 
     279           0 :                 r = in_addr_from_string(AF_INET, w, &a);
     280           0 :                 if (r < 0) {
     281           0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     282             :                                    "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
     283           0 :                         continue;
     284             :                 }
     285             : 
     286           0 :                 m = reallocarray(n->dhcp_server_dns, n->n_dhcp_server_dns + 1, sizeof(struct in_addr));
     287           0 :                 if (!m)
     288           0 :                         return log_oom();
     289             : 
     290           0 :                 m[n->n_dhcp_server_dns++] = a.in;
     291           0 :                 n->dhcp_server_dns = m;
     292             :         }
     293             : 
     294           0 :         return 0;
     295             : }
     296             : 
     297           0 : int config_parse_dhcp_server_ntp(
     298             :                 const char *unit,
     299             :                 const char *filename,
     300             :                 unsigned line,
     301             :                 const char *section,
     302             :                 unsigned section_line,
     303             :                 const char *lvalue,
     304             :                 int ltype,
     305             :                 const char *rvalue,
     306             :                 void *data,
     307             :                 void *userdata) {
     308             : 
     309           0 :         Network *n = data;
     310           0 :         const char *p = rvalue;
     311             :         int r;
     312             : 
     313           0 :         assert(filename);
     314           0 :         assert(lvalue);
     315           0 :         assert(rvalue);
     316             : 
     317           0 :         for (;;) {
     318           0 :                 _cleanup_free_ char *w = NULL;
     319             :                 union in_addr_union a;
     320             :                 struct in_addr *m;
     321             : 
     322           0 :                 r = extract_first_word(&p, &w, NULL, 0);
     323           0 :                 if (r == -ENOMEM)
     324           0 :                         return log_oom();
     325           0 :                 if (r < 0) {
     326           0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     327             :                                    "Failed to extract word, ignoring: %s", rvalue);
     328           0 :                         return 0;
     329             :                 }
     330           0 :                 if (r == 0)
     331           0 :                         return 0;
     332             : 
     333           0 :                 r = in_addr_from_string(AF_INET, w, &a);
     334           0 :                 if (r < 0) {
     335           0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     336             :                                    "Failed to parse NTP server address '%s', ignoring: %m", w);
     337           0 :                         continue;
     338             :                 }
     339             : 
     340           0 :                 m = reallocarray(n->dhcp_server_ntp, n->n_dhcp_server_ntp + 1, sizeof(struct in_addr));
     341           0 :                 if (!m)
     342           0 :                         return log_oom();
     343             : 
     344           0 :                 m[n->n_dhcp_server_ntp++] = a.in;
     345           0 :                 n->dhcp_server_ntp = m;
     346             :         }
     347             : }

Generated by: LCOV version 1.14