LCOV - code coverage report
Current view: top level - libsystemd/sd-network - sd-network.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 42 244 17.2 %
Date: 2019-08-22 15:41:25 Functions: 9 41 22.0 %

          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           1 : static int network_get_strv(const char *key, char ***ret) {
      53           1 :         _cleanup_strv_free_ char **a = NULL;
      54           1 :         _cleanup_free_ char *s = NULL;
      55             :         int r;
      56             : 
      57           1 :         assert_return(ret, -EINVAL);
      58             : 
      59           1 :         r = parse_env_file(NULL, "/run/systemd/netif/state", key, &s);
      60           1 :         if (r == -ENOENT)
      61           1 :                 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           1 : _public_ int sd_network_get_ntp(char ***ret) {
      86           1 :         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           2 : static int MONITOR_TO_FD(sd_network_monitor *m) {
     321           2 :         return (int) (unsigned long) m - 1;
     322             : }
     323             : 
     324           1 : static sd_network_monitor* FD_TO_MONITOR(int fd) {
     325           1 :         return (sd_network_monitor*) (unsigned long) (fd + 1);
     326             : }
     327             : 
     328           1 : static int monitor_add_inotify_watch(int fd) {
     329             :         int k;
     330             : 
     331           1 :         k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
     332           1 :         if (k >= 0)
     333           1 :                 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           1 : _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
     351           1 :         _cleanup_close_ int fd = -1;
     352             :         int k;
     353           1 :         bool good = false;
     354             : 
     355           1 :         assert_return(m, -EINVAL);
     356             : 
     357           1 :         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
     358           1 :         if (fd < 0)
     359           0 :                 return -errno;
     360             : 
     361           1 :         if (!category || streq(category, "links")) {
     362           1 :                 k = monitor_add_inotify_watch(fd);
     363           1 :                 if (k < 0)
     364           0 :                         return k;
     365             : 
     366           1 :                 good = true;
     367             :         }
     368             : 
     369           1 :         if (!good)
     370           0 :                 return -EINVAL;
     371             : 
     372           1 :         *m = FD_TO_MONITOR(fd);
     373           1 :         fd = -1;
     374             : 
     375           1 :         return 0;
     376             : }
     377             : 
     378           1 : _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
     379             :         int fd;
     380             : 
     381           1 :         if (m) {
     382           1 :                 fd = MONITOR_TO_FD(m);
     383           1 :                 close_nointr(fd);
     384             :         }
     385             : 
     386           1 :         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           1 : _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
     423             : 
     424           1 :         assert_return(m, -EINVAL);
     425             : 
     426           1 :         return MONITOR_TO_FD(m);
     427             : }
     428             : 
     429           1 : _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
     430             : 
     431           1 :         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           1 :         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