LCOV - code coverage report
Current view: top level - libsystemd/sd-network - sd-network.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 42 244 17.2 %
Date: 2019-08-23 13:36:53 Functions: 9 41 22.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 15 169 8.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <poll.h>
       5                 :            : #include <string.h>
       6                 :            : #include <sys/inotify.h>
       7                 :            : 
       8                 :            : #include "sd-network.h"
       9                 :            : 
      10                 :            : #include "alloc-util.h"
      11                 :            : #include "env-file.h"
      12                 :            : #include "fd-util.h"
      13                 :            : #include "fs-util.h"
      14                 :            : #include "macro.h"
      15                 :            : #include "parse-util.h"
      16                 :            : #include "stdio-util.h"
      17                 :            : #include "string-util.h"
      18                 :            : #include "strv.h"
      19                 :            : #include "util.h"
      20                 :            : 
      21                 :          0 : static int network_get_string(const char *field, char **ret) {
      22                 :          0 :         _cleanup_free_ char *s = NULL;
      23                 :            :         int r;
      24                 :            : 
      25   [ #  #  #  # ]:          0 :         assert_return(ret, -EINVAL);
      26                 :            : 
      27                 :          0 :         r = parse_env_file(NULL, "/run/systemd/netif/state", field, &s);
      28         [ #  # ]:          0 :         if (r == -ENOENT)
      29                 :          0 :                 return -ENODATA;
      30         [ #  # ]:          0 :         if (r < 0)
      31                 :          0 :                 return r;
      32         [ #  # ]:          0 :         if (isempty(s))
      33                 :          0 :                 return -ENODATA;
      34                 :            : 
      35                 :          0 :         *ret = TAKE_PTR(s);
      36                 :            : 
      37                 :          0 :         return 0;
      38                 :            : }
      39                 :            : 
      40                 :          0 : _public_ int sd_network_get_operational_state(char **state) {
      41                 :          0 :         return network_get_string("OPER_STATE", state);
      42                 :            : }
      43                 :            : 
      44                 :          0 : _public_ int sd_network_get_carrier_state(char **state) {
      45                 :          0 :         return network_get_string("CARRIER_STATE", state);
      46                 :            : }
      47                 :            : 
      48                 :          0 : _public_ int sd_network_get_address_state(char **state) {
      49                 :          0 :         return network_get_string("ADDRESS_STATE", state);
      50                 :            : }
      51                 :            : 
      52                 :          4 : static int network_get_strv(const char *key, char ***ret) {
      53                 :          4 :         _cleanup_strv_free_ char **a = NULL;
      54                 :          4 :         _cleanup_free_ char *s = NULL;
      55                 :            :         int r;
      56                 :            : 
      57   [ -  +  -  + ]:          4 :         assert_return(ret, -EINVAL);
      58                 :            : 
      59                 :          4 :         r = parse_env_file(NULL, "/run/systemd/netif/state", key, &s);
      60         [ +  - ]:          4 :         if (r == -ENOENT)
      61                 :          4 :                 return -ENODATA;
      62         [ #  # ]:          0 :         if (r < 0)
      63                 :          0 :                 return r;
      64         [ #  # ]:          0 :         if (isempty(s)) {
      65                 :          0 :                 *ret = NULL;
      66                 :          0 :                 return 0;
      67                 :            :         }
      68                 :            : 
      69                 :          0 :         a = strv_split(s, " ");
      70         [ #  # ]:          0 :         if (!a)
      71                 :          0 :                 return -ENOMEM;
      72                 :            : 
      73                 :          0 :         strv_uniq(a);
      74                 :          0 :         r = (int) strv_length(a);
      75                 :            : 
      76                 :          0 :         *ret = TAKE_PTR(a);
      77                 :            : 
      78                 :          0 :         return r;
      79                 :            : }
      80                 :            : 
      81                 :          0 : _public_ int sd_network_get_dns(char ***ret) {
      82                 :          0 :         return network_get_strv("DNS", ret);
      83                 :            : }
      84                 :            : 
      85                 :          4 : _public_ int sd_network_get_ntp(char ***ret) {
      86                 :          4 :         return network_get_strv("NTP", ret);
      87                 :            : }
      88                 :            : 
      89                 :          0 : _public_ int sd_network_get_search_domains(char ***ret) {
      90                 :          0 :         return network_get_strv("DOMAINS", ret);
      91                 :            : }
      92                 :            : 
      93                 :          0 : _public_ int sd_network_get_route_domains(char ***ret) {
      94                 :          0 :         return network_get_strv("ROUTE_DOMAINS", ret);
      95                 :            : }
      96                 :            : 
      97                 :          0 : static int network_link_get_string(int ifindex, const char *field, char **ret) {
      98                 :            :         char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
      99                 :          0 :         _cleanup_free_ char *s = NULL;
     100                 :            :         int r;
     101                 :            : 
     102   [ #  #  #  # ]:          0 :         assert_return(ifindex > 0, -EINVAL);
     103   [ #  #  #  # ]:          0 :         assert_return(ret, -EINVAL);
     104                 :            : 
     105         [ #  # ]:          0 :         xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
     106                 :            : 
     107                 :          0 :         r = parse_env_file(NULL, path, field, &s);
     108         [ #  # ]:          0 :         if (r == -ENOENT)
     109                 :          0 :                 return -ENODATA;
     110         [ #  # ]:          0 :         if (r < 0)
     111                 :          0 :                 return r;
     112         [ #  # ]:          0 :         if (isempty(s))
     113                 :          0 :                 return -ENODATA;
     114                 :            : 
     115                 :          0 :         *ret = TAKE_PTR(s);
     116                 :            : 
     117                 :          0 :         return 0;
     118                 :            : }
     119                 :            : 
     120                 :          0 : static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
     121                 :            :         char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
     122                 :          0 :         _cleanup_strv_free_ char **a = NULL;
     123                 :          0 :         _cleanup_free_ char *s = NULL;
     124                 :            :         int r;
     125                 :            : 
     126   [ #  #  #  # ]:          0 :         assert_return(ifindex > 0, -EINVAL);
     127   [ #  #  #  # ]:          0 :         assert_return(ret, -EINVAL);
     128                 :            : 
     129         [ #  # ]:          0 :         xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
     130                 :          0 :         r = parse_env_file(NULL, path, key, &s);
     131         [ #  # ]:          0 :         if (r == -ENOENT)
     132                 :          0 :                 return -ENODATA;
     133         [ #  # ]:          0 :         if (r < 0)
     134                 :          0 :                 return r;
     135         [ #  # ]:          0 :         if (isempty(s)) {
     136                 :          0 :                 *ret = NULL;
     137                 :          0 :                 return 0;
     138                 :            :         }
     139                 :            : 
     140                 :          0 :         a = strv_split(s, " ");
     141         [ #  # ]:          0 :         if (!a)
     142                 :          0 :                 return -ENOMEM;
     143                 :            : 
     144                 :          0 :         strv_uniq(a);
     145                 :          0 :         r = (int) strv_length(a);
     146                 :            : 
     147                 :          0 :         *ret = TAKE_PTR(a);
     148                 :            : 
     149                 :          0 :         return r;
     150                 :            : }
     151                 :            : 
     152                 :          0 : _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
     153                 :          0 :         return network_link_get_string(ifindex, "ADMIN_STATE", state);
     154                 :            : }
     155                 :            : 
     156                 :          0 : _public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
     157                 :          0 :         return network_link_get_string(ifindex, "NETWORK_FILE", filename);
     158                 :            : }
     159                 :            : 
     160                 :          0 : _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
     161                 :          0 :         return network_link_get_string(ifindex, "OPER_STATE", state);
     162                 :            : }
     163                 :            : 
     164                 :          0 : _public_ int sd_network_link_get_carrier_state(int ifindex, char **state) {
     165                 :          0 :         return network_link_get_string(ifindex, "CARRIER_STATE", state);
     166                 :            : }
     167                 :            : 
     168                 :          0 : _public_ int sd_network_link_get_address_state(int ifindex, char **state) {
     169                 :          0 :         return network_link_get_string(ifindex, "ADDRESS_STATE", state);
     170                 :            : }
     171                 :            : 
     172                 :          0 : _public_ int sd_network_link_get_required_for_online(int ifindex) {
     173                 :          0 :         _cleanup_free_ char *s = NULL;
     174                 :            :         int r;
     175                 :            : 
     176                 :          0 :         r = network_link_get_string(ifindex, "REQUIRED_FOR_ONLINE", &s);
     177         [ #  # ]:          0 :         if (r < 0) {
     178                 :            :                 /* Handle -ENODATA as RequiredForOnline=yes, for compatibility */
     179         [ #  # ]:          0 :                 if (r == -ENODATA)
     180                 :          0 :                         return true;
     181                 :          0 :                 return r;
     182                 :            :         }
     183                 :            : 
     184                 :          0 :         return parse_boolean(s);
     185                 :            : }
     186                 :            : 
     187                 :          0 : _public_ int sd_network_link_get_required_operstate_for_online(int ifindex, char **state) {
     188                 :          0 :         _cleanup_free_ char *s = NULL;
     189                 :            :         int r;
     190                 :            : 
     191   [ #  #  #  # ]:          0 :         assert_return(state, -EINVAL);
     192                 :            : 
     193                 :          0 :         r = network_link_get_string(ifindex, "REQUIRED_OPER_STATE_FOR_ONLINE", &s);
     194         [ #  # ]:          0 :         if (r < 0) {
     195         [ #  # ]:          0 :                 if (r != -ENODATA)
     196                 :          0 :                         return r;
     197                 :            : 
     198                 :            :                 /* For compatibility, assuming degraded. */
     199                 :          0 :                 s = strdup("degraded");
     200         [ #  # ]:          0 :                 if (!s)
     201                 :          0 :                         return -ENOMEM;
     202                 :            :         }
     203                 :            : 
     204                 :          0 :         *state = TAKE_PTR(s);
     205                 :          0 :         return 0;
     206                 :            : }
     207                 :            : 
     208                 :          0 : _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
     209                 :          0 :         return network_link_get_string(ifindex, "LLMNR", llmnr);
     210                 :            : }
     211                 :            : 
     212                 :          0 : _public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
     213                 :          0 :         return network_link_get_string(ifindex, "MDNS", mdns);
     214                 :            : }
     215                 :            : 
     216                 :          0 : _public_ int sd_network_link_get_dns_over_tls(int ifindex, char **dns_over_tls) {
     217                 :          0 :         return network_link_get_string(ifindex, "DNS_OVER_TLS", dns_over_tls);
     218                 :            : }
     219                 :            : 
     220                 :          0 : _public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
     221                 :          0 :         return network_link_get_string(ifindex, "DNSSEC", dnssec);
     222                 :            : }
     223                 :            : 
     224                 :          0 : _public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) {
     225                 :          0 :         return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
     226                 :            : }
     227                 :            : 
     228                 :          0 : _public_ int sd_network_link_get_timezone(int ifindex, char **ret) {
     229                 :          0 :         return network_link_get_string(ifindex, "TIMEZONE", ret);
     230                 :            : }
     231                 :            : 
     232                 :          0 : _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
     233                 :          0 :         return network_link_get_strv(ifindex, "DNS", ret);
     234                 :            : }
     235                 :            : 
     236                 :          0 : _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
     237                 :          0 :         return network_link_get_strv(ifindex, "NTP", ret);
     238                 :            : }
     239                 :            : 
     240                 :          0 : _public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) {
     241                 :          0 :         return network_link_get_strv(ifindex, "DOMAINS", ret);
     242                 :            : }
     243                 :            : 
     244                 :          0 : _public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
     245                 :          0 :         return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
     246                 :            : }
     247                 :            : 
     248                 :          0 : _public_ int sd_network_link_get_dns_default_route(int ifindex) {
     249                 :            :         char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
     250                 :          0 :         _cleanup_free_ char *s = NULL;
     251                 :            :         int r;
     252                 :            : 
     253   [ #  #  #  # ]:          0 :         assert_return(ifindex > 0, -EINVAL);
     254                 :            : 
     255         [ #  # ]:          0 :         xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
     256                 :            : 
     257                 :          0 :         r = parse_env_file(NULL, path, "DNS_DEFAULT_ROUTE", &s);
     258         [ #  # ]:          0 :         if (r == -ENOENT)
     259                 :          0 :                 return -ENODATA;
     260         [ #  # ]:          0 :         if (r < 0)
     261                 :          0 :                 return r;
     262         [ #  # ]:          0 :         if (isempty(s))
     263                 :          0 :                 return -ENODATA;
     264                 :          0 :         return parse_boolean(s);
     265                 :            : }
     266                 :            : 
     267                 :          0 : static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) {
     268                 :            :         char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1];
     269                 :          0 :         _cleanup_free_ int *ifis = NULL;
     270                 :          0 :         _cleanup_free_ char *s = NULL;
     271                 :          0 :         size_t allocated = 0, c = 0;
     272                 :            :         const char *x;
     273                 :            :         int r;
     274                 :            : 
     275   [ #  #  #  # ]:          0 :         assert_return(ifindex > 0, -EINVAL);
     276   [ #  #  #  # ]:          0 :         assert_return(ret, -EINVAL);
     277                 :            : 
     278         [ #  # ]:          0 :         xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
     279                 :          0 :         r = parse_env_file(NULL, path, key, &s);
     280         [ #  # ]:          0 :         if (r == -ENOENT)
     281                 :          0 :                 return -ENODATA;
     282         [ #  # ]:          0 :         if (r < 0)
     283                 :          0 :                 return r;
     284                 :            : 
     285                 :          0 :         for (x = s;;) {
     286      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
     287                 :            : 
     288                 :          0 :                 r = extract_first_word(&x, &word, NULL, 0);
     289         [ #  # ]:          0 :                 if (r < 0)
     290                 :          0 :                         return r;
     291         [ #  # ]:          0 :                 if (r == 0)
     292                 :          0 :                         break;
     293                 :            : 
     294                 :          0 :                 r = parse_ifindex(word, &ifindex);
     295         [ #  # ]:          0 :                 if (r < 0)
     296                 :          0 :                         return r;
     297                 :            : 
     298         [ #  # ]:          0 :                 if (!GREEDY_REALLOC(ifis, allocated, c + 2))
     299                 :          0 :                         return -ENOMEM;
     300                 :            : 
     301                 :          0 :                 ifis[c++] = ifindex;
     302                 :            :         }
     303                 :            : 
     304         [ #  # ]:          0 :         if (ifis)
     305                 :          0 :                 ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice */
     306                 :            : 
     307                 :          0 :         *ret = TAKE_PTR(ifis);
     308                 :            : 
     309                 :          0 :         return c;
     310                 :            : }
     311                 :            : 
     312                 :          0 : _public_ int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) {
     313                 :          0 :         return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret);
     314                 :            : }
     315                 :            : 
     316                 :          0 : _public_ int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) {
     317                 :          0 :         return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret);
     318                 :            : }
     319                 :            : 
     320                 :          8 : static int MONITOR_TO_FD(sd_network_monitor *m) {
     321                 :          8 :         return (int) (unsigned long) m - 1;
     322                 :            : }
     323                 :            : 
     324                 :          4 : static sd_network_monitor* FD_TO_MONITOR(int fd) {
     325                 :          4 :         return (sd_network_monitor*) (unsigned long) (fd + 1);
     326                 :            : }
     327                 :            : 
     328                 :          4 : static int monitor_add_inotify_watch(int fd) {
     329                 :            :         int k;
     330                 :            : 
     331                 :          4 :         k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
     332         [ +  - ]:          4 :         if (k >= 0)
     333                 :          4 :                 return 0;
     334         [ #  # ]:          0 :         else if (errno != ENOENT)
     335                 :          0 :                 return -errno;
     336                 :            : 
     337                 :          0 :         k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR);
     338         [ #  # ]:          0 :         if (k >= 0)
     339                 :          0 :                 return 0;
     340         [ #  # ]:          0 :         else if (errno != ENOENT)
     341                 :          0 :                 return -errno;
     342                 :            : 
     343                 :          0 :         k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR);
     344         [ #  # ]:          0 :         if (k < 0)
     345                 :          0 :                 return -errno;
     346                 :            : 
     347                 :          0 :         return 0;
     348                 :            : }
     349                 :            : 
     350                 :          4 : _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
     351                 :          4 :         _cleanup_close_ int fd = -1;
     352                 :            :         int k;
     353                 :          4 :         bool good = false;
     354                 :            : 
     355   [ -  +  -  + ]:          4 :         assert_return(m, -EINVAL);
     356                 :            : 
     357                 :          4 :         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
     358         [ -  + ]:          4 :         if (fd < 0)
     359                 :          0 :                 return -errno;
     360                 :            : 
     361   [ -  +  #  # ]:          4 :         if (!category || streq(category, "links")) {
     362                 :          4 :                 k = monitor_add_inotify_watch(fd);
     363         [ -  + ]:          4 :                 if (k < 0)
     364                 :          0 :                         return k;
     365                 :            : 
     366                 :          4 :                 good = true;
     367                 :            :         }
     368                 :            : 
     369         [ -  + ]:          4 :         if (!good)
     370                 :          0 :                 return -EINVAL;
     371                 :            : 
     372                 :          4 :         *m = FD_TO_MONITOR(fd);
     373                 :          4 :         fd = -1;
     374                 :            : 
     375                 :          4 :         return 0;
     376                 :            : }
     377                 :            : 
     378                 :          4 : _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
     379                 :            :         int fd;
     380                 :            : 
     381         [ +  - ]:          4 :         if (m) {
     382                 :          4 :                 fd = MONITOR_TO_FD(m);
     383                 :          4 :                 close_nointr(fd);
     384                 :            :         }
     385                 :            : 
     386                 :          4 :         return NULL;
     387                 :            : }
     388                 :            : 
     389                 :          0 : _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
     390                 :            :         union inotify_event_buffer buffer;
     391                 :            :         struct inotify_event *e;
     392                 :            :         ssize_t l;
     393                 :            :         int fd, k;
     394                 :            : 
     395   [ #  #  #  # ]:          0 :         assert_return(m, -EINVAL);
     396                 :            : 
     397                 :          0 :         fd = MONITOR_TO_FD(m);
     398                 :            : 
     399                 :          0 :         l = read(fd, &buffer, sizeof(buffer));
     400         [ #  # ]:          0 :         if (l < 0) {
     401   [ #  #  #  # ]:          0 :                 if (IN_SET(errno, EAGAIN, EINTR))
     402                 :          0 :                         return 0;
     403                 :            : 
     404                 :          0 :                 return -errno;
     405                 :            :         }
     406                 :            : 
     407         [ #  # ]:          0 :         FOREACH_INOTIFY_EVENT(e, buffer, l) {
     408         [ #  # ]:          0 :                 if (e->mask & IN_ISDIR) {
     409                 :          0 :                         k = monitor_add_inotify_watch(fd);
     410         [ #  # ]:          0 :                         if (k < 0)
     411                 :          0 :                                 return k;
     412                 :            : 
     413                 :          0 :                         k = inotify_rm_watch(fd, e->wd);
     414         [ #  # ]:          0 :                         if (k < 0)
     415                 :          0 :                                 return -errno;
     416                 :            :                 }
     417                 :            :         }
     418                 :            : 
     419                 :          0 :         return 0;
     420                 :            : }
     421                 :            : 
     422                 :          4 : _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
     423                 :            : 
     424   [ -  +  -  + ]:          4 :         assert_return(m, -EINVAL);
     425                 :            : 
     426                 :          4 :         return MONITOR_TO_FD(m);
     427                 :            : }
     428                 :            : 
     429                 :          4 : _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
     430                 :            : 
     431   [ -  +  -  + ]:          4 :         assert_return(m, -EINVAL);
     432                 :            : 
     433                 :            :         /* For now we will only return POLLIN here, since we don't
     434                 :            :          * need anything else ever for inotify.  However, let's have
     435                 :            :          * this API to keep our options open should we later on need
     436                 :            :          * it. */
     437                 :          4 :         return POLLIN;
     438                 :            : }
     439                 :            : 
     440                 :          0 : _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
     441                 :            : 
     442   [ #  #  #  # ]:          0 :         assert_return(m, -EINVAL);
     443   [ #  #  #  # ]:          0 :         assert_return(timeout_usec, -EINVAL);
     444                 :            : 
     445                 :            :         /* For now we will only return (uint64_t) -1, since we don't
     446                 :            :          * need any timeout. However, let's have this API to keep our
     447                 :            :          * options open should we later on need it. */
     448                 :          0 :         *timeout_usec = (uint64_t) -1;
     449                 :          0 :         return 0;
     450                 :            : }

Generated by: LCOV version 1.14