LCOV - code coverage report
Current view: top level - libsystemd-network - network-internal.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 119 245 48.6 %
Date: 2015-07-29 18:47:03 Functions: 6 13 46.2 %

          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 (C) 2013 Tom Gundersen <teg@jklm.no>
       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             : #include <netinet/ether.h>
      23             : #include <linux/if.h>
      24             : #include <arpa/inet.h>
      25             : 
      26             : #include "strv.h"
      27             : #include "siphash24.h"
      28             : #include "dhcp-lease-internal.h"
      29             : #include "log.h"
      30             : #include "utf8.h"
      31             : #include "util.h"
      32             : #include "conf-parser.h"
      33             : #include "condition.h"
      34             : #include "network-internal.h"
      35             : 
      36           0 : const char *net_get_name(struct udev_device *device) {
      37             :         const char *name, *field;
      38             : 
      39           0 :         assert(device);
      40             : 
      41             :         /* fetch some persistent data unique (on this machine) to this device */
      42           0 :         FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
      43           0 :                 name = udev_device_get_property_value(device, field);
      44           0 :                 if (name)
      45           0 :                         return name;
      46             :         }
      47             : 
      48           0 :         return NULL;
      49             : }
      50             : 
      51             : #define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
      52             : 
      53           0 : int net_get_unique_predictable_data(struct udev_device *device, uint8_t result[8]) {
      54           0 :         size_t l, sz = 0;
      55           0 :         const char *name = NULL;
      56             :         int r;
      57             :         uint8_t *v;
      58             : 
      59           0 :         assert(device);
      60             : 
      61           0 :         name = net_get_name(device);
      62           0 :         if (!name)
      63           0 :                 return -ENOENT;
      64             : 
      65           0 :         l = strlen(name);
      66           0 :         sz = sizeof(sd_id128_t) + l;
      67           0 :         v = alloca(sz);
      68             : 
      69             :         /* fetch some persistent data unique to this machine */
      70           0 :         r = sd_id128_get_machine((sd_id128_t*) v);
      71           0 :         if (r < 0)
      72           0 :                  return r;
      73           0 :         memcpy(v + sizeof(sd_id128_t), name, l);
      74             : 
      75             :         /* Let's hash the machine ID plus the device name. We
      76             :         * use a fixed, but originally randomly created hash
      77             :         * key here. */
      78           0 :         siphash24(result, v, sz, HASH_KEY.bytes);
      79             : 
      80           0 :         return 0;
      81             : }
      82             : 
      83           3 : bool net_match_config(const struct ether_addr *match_mac,
      84             :                       char * const *match_paths,
      85             :                       char * const *match_drivers,
      86             :                       char * const *match_types,
      87             :                       char * const *match_names,
      88             :                       Condition *match_host,
      89             :                       Condition *match_virt,
      90             :                       Condition *match_kernel,
      91             :                       Condition *match_arch,
      92             :                       const struct ether_addr *dev_mac,
      93             :                       const char *dev_path,
      94             :                       const char *dev_parent_driver,
      95             :                       const char *dev_driver,
      96             :                       const char *dev_type,
      97             :                       const char *dev_name) {
      98             : 
      99           3 :         if (match_host && !condition_test(match_host))
     100           0 :                 return false;
     101             : 
     102           3 :         if (match_virt && !condition_test(match_virt))
     103           1 :                 return false;
     104             : 
     105           2 :         if (match_kernel && !condition_test(match_kernel))
     106           0 :                 return false;
     107             : 
     108           2 :         if (match_arch && !condition_test(match_arch))
     109           0 :                 return false;
     110             : 
     111           2 :         if (match_mac && (!dev_mac || memcmp(match_mac, dev_mac, ETH_ALEN)))
     112           0 :                 return false;
     113             : 
     114           2 :         if (!strv_isempty(match_paths) &&
     115           0 :             (!dev_path || !strv_fnmatch(match_paths, dev_path, 0)))
     116           0 :                 return false;
     117             : 
     118           2 :         if (!strv_isempty(match_drivers) &&
     119           0 :             (!dev_driver || !strv_fnmatch(match_drivers, dev_driver, 0)))
     120           1 :                 return false;
     121             : 
     122           1 :         if (!strv_isempty(match_types) &&
     123           0 :             (!dev_type || !strv_fnmatch_or_empty(match_types, dev_type, 0)))
     124           0 :                 return false;
     125             : 
     126           1 :         if (!strv_isempty(match_names) &&
     127           1 :             (!dev_name || !strv_fnmatch_or_empty(match_names, dev_name, 0)))
     128           1 :                 return false;
     129             : 
     130           0 :         return true;
     131             : }
     132             : 
     133           1 : int config_parse_net_condition(const char *unit,
     134             :                                const char *filename,
     135             :                                unsigned line,
     136             :                                const char *section,
     137             :                                unsigned section_line,
     138             :                                const char *lvalue,
     139             :                                int ltype,
     140             :                                const char *rvalue,
     141             :                                void *data,
     142             :                                void *userdata) {
     143             : 
     144           1 :         ConditionType cond = ltype;
     145           1 :         Condition **ret = data;
     146             :         bool negate;
     147             :         Condition *c;
     148           2 :         _cleanup_free_ char *s = NULL;
     149             : 
     150           1 :         assert(filename);
     151           1 :         assert(lvalue);
     152           1 :         assert(rvalue);
     153           1 :         assert(data);
     154             : 
     155           1 :         negate = rvalue[0] == '!';
     156           1 :         if (negate)
     157           0 :                 rvalue++;
     158             : 
     159           1 :         s = strdup(rvalue);
     160           1 :         if (!s)
     161           0 :                 return log_oom();
     162             : 
     163           1 :         c = condition_new(cond, s, false, negate);
     164           1 :         if (!c)
     165           0 :                 return log_oom();
     166             : 
     167           1 :         if (*ret)
     168           0 :                 condition_free(*ret);
     169             : 
     170           1 :         *ret = c;
     171           1 :         return 0;
     172             : }
     173             : 
     174           0 : int config_parse_ifname(const char *unit,
     175             :                         const char *filename,
     176             :                         unsigned line,
     177             :                         const char *section,
     178             :                         unsigned section_line,
     179             :                         const char *lvalue,
     180             :                         int ltype,
     181             :                         const char *rvalue,
     182             :                         void *data,
     183             :                         void *userdata) {
     184             : 
     185           0 :         char **s = data;
     186           0 :         _cleanup_free_ char *n = NULL;
     187             : 
     188           0 :         assert(filename);
     189           0 :         assert(lvalue);
     190           0 :         assert(rvalue);
     191           0 :         assert(data);
     192             : 
     193           0 :         n = strdup(rvalue);
     194           0 :         if (!n)
     195           0 :                 return log_oom();
     196             : 
     197           0 :         if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
     198           0 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
     199             :                            "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
     200           0 :                 return 0;
     201             :         }
     202             : 
     203           0 :         free(*s);
     204           0 :         if (*n) {
     205           0 :                 *s = n;
     206           0 :                 n = NULL;
     207             :         } else
     208           0 :                 *s = NULL;
     209             : 
     210           0 :         return 0;
     211             : }
     212             : 
     213           3 : int config_parse_ifnames(const char *unit,
     214             :                         const char *filename,
     215             :                         unsigned line,
     216             :                         const char *section,
     217             :                         unsigned section_line,
     218             :                         const char *lvalue,
     219             :                         int ltype,
     220             :                         const char *rvalue,
     221             :                         void *data,
     222             :                         void *userdata) {
     223             : 
     224           3 :         char ***sv = data;
     225             :         const char *word, *state;
     226             :         size_t l;
     227             :         int r;
     228             : 
     229           3 :         assert(filename);
     230           3 :         assert(lvalue);
     231           3 :         assert(rvalue);
     232           3 :         assert(data);
     233             : 
     234           6 :         FOREACH_WORD(word, l, rvalue, state) {
     235             :                 char *n;
     236             : 
     237           3 :                 n = strndup(word, l);
     238           3 :                 if (!n)
     239           0 :                         return log_oom();
     240             : 
     241           3 :                 if (!ascii_is_valid(n) || strlen(n) >= IFNAMSIZ) {
     242           0 :                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
     243             :                                    "Interface name is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
     244           0 :                         free(n);
     245           0 :                         return 0;
     246             :                 }
     247             : 
     248           3 :                 r = strv_consume(sv, n);
     249           3 :                 if (r < 0)
     250           0 :                         return log_oom();
     251             :         }
     252             : 
     253           3 :         return 0;
     254             : }
     255             : 
     256           0 : int config_parse_ifalias(const char *unit,
     257             :                          const char *filename,
     258             :                          unsigned line,
     259             :                          const char *section,
     260             :                          unsigned section_line,
     261             :                          const char *lvalue,
     262             :                          int ltype,
     263             :                          const char *rvalue,
     264             :                          void *data,
     265             :                          void *userdata) {
     266             : 
     267           0 :         char **s = data;
     268           0 :         _cleanup_free_ char *n = NULL;
     269             : 
     270           0 :         assert(filename);
     271           0 :         assert(lvalue);
     272           0 :         assert(rvalue);
     273           0 :         assert(data);
     274             : 
     275           0 :         n = strdup(rvalue);
     276           0 :         if (!n)
     277           0 :                 return log_oom();
     278             : 
     279           0 :         if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) {
     280           0 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
     281             :                            "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
     282           0 :                 return 0;
     283             :         }
     284             : 
     285           0 :         free(*s);
     286           0 :         if (*n) {
     287           0 :                 *s = n;
     288           0 :                 n = NULL;
     289             :         } else
     290           0 :                 *s = NULL;
     291             : 
     292           0 :         return 0;
     293             : }
     294             : 
     295           0 : int config_parse_hwaddr(const char *unit,
     296             :                         const char *filename,
     297             :                         unsigned line,
     298             :                         const char *section,
     299             :                         unsigned section_line,
     300             :                         const char *lvalue,
     301             :                         int ltype,
     302             :                         const char *rvalue,
     303             :                         void *data,
     304             :                         void *userdata) {
     305           0 :         struct ether_addr **hwaddr = data;
     306             :         struct ether_addr *n;
     307             :         int r;
     308             : 
     309           0 :         assert(filename);
     310           0 :         assert(lvalue);
     311           0 :         assert(rvalue);
     312           0 :         assert(data);
     313             : 
     314           0 :         n = new0(struct ether_addr, 1);
     315           0 :         if (!n)
     316           0 :                 return log_oom();
     317             : 
     318           0 :         r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
     319             :                    &n->ether_addr_octet[0],
     320             :                    &n->ether_addr_octet[1],
     321             :                    &n->ether_addr_octet[2],
     322             :                    &n->ether_addr_octet[3],
     323             :                    &n->ether_addr_octet[4],
     324             :                    &n->ether_addr_octet[5]);
     325           0 :         if (r != 6) {
     326           0 :                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
     327             :                            "Not a valid MAC address, ignoring assignment: %s", rvalue);
     328           0 :                 free(n);
     329           0 :                 return 0;
     330             :         }
     331             : 
     332           0 :         free(*hwaddr);
     333           0 :         *hwaddr = n;
     334             : 
     335           0 :         return 0;
     336             : }
     337             : 
     338           0 : void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size) {
     339             :         unsigned i;
     340             : 
     341           0 :         assert(f);
     342           0 :         assert(addresses);
     343           0 :         assert(size);
     344             : 
     345           0 :         for (i = 0; i < size; i++)
     346           0 :                 fprintf(f, "%s%s", inet_ntoa(addresses[i]),
     347           0 :                         (i < (size - 1)) ? " ": "");
     348           0 : }
     349             : 
     350           1 : int deserialize_in_addrs(struct in_addr **ret, const char *string) {
     351           2 :         _cleanup_free_ struct in_addr *addresses = NULL;
     352           1 :         int size = 0;
     353             :         const char *word, *state;
     354             :         size_t len;
     355             : 
     356           1 :         assert(ret);
     357           1 :         assert(string);
     358             : 
     359           7 :         FOREACH_WORD(word, len, string, state) {
     360          12 :                 _cleanup_free_ char *addr_str = NULL;
     361             :                 struct in_addr *new_addresses;
     362             :                 int r;
     363             : 
     364           6 :                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in_addr));
     365           6 :                 if (!new_addresses)
     366           0 :                         return -ENOMEM;
     367             :                 else
     368           6 :                         addresses = new_addresses;
     369             : 
     370           6 :                 addr_str = strndup(word, len);
     371           6 :                 if (!addr_str)
     372           0 :                         return -ENOMEM;
     373             : 
     374           6 :                 r = inet_pton(AF_INET, addr_str, &(addresses[size]));
     375           6 :                 if (r <= 0)
     376           3 :                         continue;
     377             : 
     378           3 :                 size ++;
     379             :         }
     380             : 
     381           1 :         *ret = addresses;
     382           1 :         addresses = NULL;
     383             : 
     384           1 :         return size;
     385             : }
     386             : 
     387           1 : int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
     388           2 :         _cleanup_free_ struct in6_addr *addresses = NULL;
     389           1 :         int size = 0;
     390             :         const char *word, *state;
     391             :         size_t len;
     392             : 
     393           1 :         assert(ret);
     394           1 :         assert(string);
     395             : 
     396           7 :         FOREACH_WORD(word, len, string, state) {
     397          12 :                 _cleanup_free_ char *addr_str = NULL;
     398             :                 struct in6_addr *new_addresses;
     399             :                 int r;
     400             : 
     401           6 :                 new_addresses = realloc(addresses, (size + 1) * sizeof(struct in6_addr));
     402           6 :                 if (!new_addresses)
     403           0 :                         return -ENOMEM;
     404             :                 else
     405           6 :                         addresses = new_addresses;
     406             : 
     407           6 :                 addr_str = strndup(word, len);
     408           6 :                 if (!addr_str)
     409           0 :                         return -ENOMEM;
     410             : 
     411           6 :                 r = inet_pton(AF_INET6, addr_str, &(addresses[size]));
     412           6 :                 if (r <= 0)
     413           3 :                         continue;
     414             : 
     415           3 :                 size++;
     416             :         }
     417             : 
     418           1 :         *ret = addresses;
     419           1 :         addresses = NULL;
     420             : 
     421           1 :         return size;
     422             : }
     423             : 
     424           0 : void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size) {
     425             :         unsigned i;
     426             : 
     427           0 :         assert(f);
     428           0 :         assert(key);
     429           0 :         assert(routes);
     430           0 :         assert(size);
     431             : 
     432           0 :         fprintf(f, "%s=", key);
     433             : 
     434           0 :         for (i = 0; i < size; i++) {
     435           0 :                 fprintf(f, "%s/%" PRIu8, inet_ntoa(routes[i].dst_addr),
     436           0 :                         routes[i].dst_prefixlen);
     437           0 :                 fprintf(f, ",%s%s", inet_ntoa(routes[i].gw_addr),
     438           0 :                         (i < (size - 1)) ? " ": "");
     439             :         }
     440             : 
     441           0 :         fputs("\n", f);
     442           0 : }
     443             : 
     444           4 : int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) {
     445           8 :         _cleanup_free_ struct sd_dhcp_route *routes = NULL;
     446           4 :         size_t size = 0, allocated = 0;
     447             :         const char *word, *state;
     448             :         size_t len;
     449             : 
     450           4 :         assert(ret);
     451           4 :         assert(ret_size);
     452           4 :         assert(ret_allocated);
     453           4 :         assert(string);
     454             : 
     455          13 :         FOREACH_WORD(word, len, string, state) {
     456             :                 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
     457          18 :                 _cleanup_free_ char* entry = NULL;
     458             :                 char *tok, *tok_end;
     459             :                 unsigned n;
     460             :                 int r;
     461             : 
     462           9 :                 if (!GREEDY_REALLOC(routes, allocated, size + 1))
     463           0 :                         return -ENOMEM;
     464             : 
     465           9 :                 entry = strndup(word, len);
     466           9 :                 if(!entry)
     467           0 :                         return -ENOMEM;
     468             : 
     469           9 :                 tok = entry;
     470             : 
     471             :                 /* get the subnet */
     472           9 :                 tok_end = strchr(tok, '/');
     473           9 :                 if (!tok_end)
     474           2 :                         continue;
     475           7 :                 *tok_end = '\0';
     476             : 
     477           7 :                 r = inet_aton(tok, &routes[size].dst_addr);
     478           7 :                 if (r == 0)
     479           0 :                         continue;
     480             : 
     481           7 :                 tok = tok_end + 1;
     482             : 
     483             :                 /* get the prefixlen */
     484           7 :                 tok_end = strchr(tok, ',');
     485           7 :                 if (!tok_end)
     486           0 :                         continue;
     487             : 
     488           7 :                 *tok_end = '\0';
     489             : 
     490           7 :                 r = safe_atou(tok, &n);
     491           7 :                 if (r < 0 || n > 32)
     492           1 :                         continue;
     493             : 
     494           6 :                 routes[size].dst_prefixlen = (uint8_t) n;
     495           6 :                 tok = tok_end + 1;
     496             : 
     497             :                 /* get the gateway */
     498           6 :                 r = inet_aton(tok, &routes[size].gw_addr);
     499           6 :                 if (r == 0)
     500           1 :                         continue;
     501             : 
     502           5 :                 size++;
     503             :         }
     504             : 
     505           4 :         *ret_size = size;
     506           4 :         *ret_allocated = allocated;
     507           4 :         *ret = routes;
     508           4 :         routes = NULL;
     509             : 
     510           4 :         return 0;
     511             : }

Generated by: LCOV version 1.11