LCOV - code coverage report
Current view: top level - resolve - resolvconf-compat.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 119 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 4 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 104 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <getopt.h>
       4                 :            : #include <net/if.h>
       5                 :            : 
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "def.h"
       8                 :            : #include "dns-domain.h"
       9                 :            : #include "extract-word.h"
      10                 :            : #include "fileio.h"
      11                 :            : #include "parse-util.h"
      12                 :            : #include "pretty-print.h"
      13                 :            : #include "resolvconf-compat.h"
      14                 :            : #include "resolvectl.h"
      15                 :            : #include "resolved-def.h"
      16                 :            : #include "string-util.h"
      17                 :            : #include "strv.h"
      18                 :            : #include "terminal-util.h"
      19                 :            : 
      20                 :          0 : static int resolvconf_help(void) {
      21                 :          0 :         _cleanup_free_ char *link = NULL;
      22                 :            :         int r;
      23                 :            : 
      24                 :          0 :         r = terminal_urlify_man("resolvectl", "1", &link);
      25         [ #  # ]:          0 :         if (r < 0)
      26                 :          0 :                 return log_oom();
      27                 :            : 
      28                 :          0 :         printf("%1$s -a INTERFACE < FILE\n"
      29                 :            :                "%1$s -d INTERFACE\n"
      30                 :            :                "\n"
      31                 :            :                "Register DNS server and domain configuration with systemd-resolved.\n\n"
      32                 :            :                "  -h --help     Show this help\n"
      33                 :            :                "     --version  Show package version\n"
      34                 :            :                "  -a            Register per-interface DNS server and domain data\n"
      35                 :            :                "  -d            Unregister per-interface DNS server and domain data\n"
      36                 :            :                "  -f            Ignore if specified interface does not exist\n"
      37                 :            :                "  -x            Send DNS traffic preferably over this interface\n"
      38                 :            :                "\n"
      39                 :            :                "This is a compatibility alias for the resolvectl(1) tool, providing native\n"
      40                 :            :                "command line compatibility with the resolvconf(8) tool of various Linux\n"
      41                 :            :                "distributions and BSD systems. Some options supported by other implementations\n"
      42                 :            :                "are not supported and are ignored: -m, -p. Various options supported by other\n"
      43                 :            :                "implementations are not supported and will cause the invocation to fail: -u,\n"
      44                 :            :                "-I, -i, -l, -R, -r, -v, -V, --enable-updates, --disable-updates,\n"
      45                 :            :                "--updates-are-enabled.\n"
      46                 :            :                "\nSee the %2$s for details.\n"
      47                 :            :                , program_invocation_short_name
      48                 :            :                , link
      49                 :            :         );
      50                 :            : 
      51                 :          0 :         return 0;
      52                 :            : }
      53                 :            : 
      54                 :          0 : static int parse_nameserver(const char *string) {
      55                 :            :         int r;
      56                 :            : 
      57         [ #  # ]:          0 :         assert(string);
      58                 :            : 
      59                 :          0 :         for (;;) {
      60      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
      61                 :            : 
      62                 :          0 :                 r = extract_first_word(&string, &word, NULL, 0);
      63         [ #  # ]:          0 :                 if (r < 0)
      64                 :          0 :                         return r;
      65         [ #  # ]:          0 :                 if (r == 0)
      66                 :          0 :                         break;
      67                 :            : 
      68         [ #  # ]:          0 :                 if (strv_push(&arg_set_dns, word) < 0)
      69                 :          0 :                         return log_oom();
      70                 :            : 
      71                 :          0 :                 word = NULL;
      72                 :            :         }
      73                 :            : 
      74                 :          0 :         return 0;
      75                 :            : }
      76                 :            : 
      77                 :          0 : static int parse_search_domain(const char *string) {
      78                 :            :         int r;
      79                 :            : 
      80         [ #  # ]:          0 :         assert(string);
      81                 :            : 
      82                 :          0 :         for (;;) {
      83      [ #  #  # ]:          0 :                 _cleanup_free_ char *word = NULL;
      84                 :            : 
      85                 :          0 :                 r = extract_first_word(&string, &word, NULL, EXTRACT_UNQUOTE);
      86         [ #  # ]:          0 :                 if (r < 0)
      87                 :          0 :                         return r;
      88         [ #  # ]:          0 :                 if (r == 0)
      89                 :          0 :                         break;
      90                 :            : 
      91         [ #  # ]:          0 :                 if (strv_push(&arg_set_domain, word) < 0)
      92                 :          0 :                         return log_oom();
      93                 :            : 
      94                 :          0 :                 word = NULL;
      95                 :            :         }
      96                 :            : 
      97                 :          0 :         return 0;
      98                 :            : }
      99                 :            : 
     100                 :          0 : int resolvconf_parse_argv(int argc, char *argv[]) {
     101                 :            : 
     102                 :            :         enum {
     103                 :            :                 ARG_VERSION = 0x100,
     104                 :            :                 ARG_ENABLE_UPDATES,
     105                 :            :                 ARG_DISABLE_UPDATES,
     106                 :            :                 ARG_UPDATES_ARE_ENABLED,
     107                 :            :         };
     108                 :            : 
     109                 :            :         static const struct option options[] = {
     110                 :            :                 { "help",                no_argument, NULL, 'h'                     },
     111                 :            :                 { "version",             no_argument, NULL, ARG_VERSION             },
     112                 :            : 
     113                 :            :                 /* The following are specific to Debian's original resolvconf */
     114                 :            :                 { "enable-updates",      no_argument, NULL, ARG_ENABLE_UPDATES      },
     115                 :            :                 { "disable-updates",     no_argument, NULL, ARG_DISABLE_UPDATES     },
     116                 :            :                 { "updates-are-enabled", no_argument, NULL, ARG_UPDATES_ARE_ENABLED },
     117                 :            :                 {}
     118                 :            :         };
     119                 :            : 
     120                 :            :         enum {
     121                 :            :                 TYPE_REGULAR,
     122                 :            :                 TYPE_PRIVATE,   /* -p: Not supported, treated identically to TYPE_REGULAR */
     123                 :            :                 TYPE_EXCLUSIVE, /* -x */
     124                 :          0 :         } type = TYPE_REGULAR;
     125                 :            : 
     126                 :            :         int c, r;
     127                 :            : 
     128         [ #  # ]:          0 :         assert(argc >= 0);
     129         [ #  # ]:          0 :         assert(argv);
     130                 :            : 
     131                 :            :         /* openresolv checks these environment variables */
     132         [ #  # ]:          0 :         if (getenv("IF_EXCLUSIVE"))
     133                 :          0 :                 type = TYPE_EXCLUSIVE;
     134         [ #  # ]:          0 :         if (getenv("IF_PRIVATE"))
     135                 :          0 :                 type = TYPE_PRIVATE; /* not actually supported */
     136                 :            : 
     137                 :          0 :         arg_mode = _MODE_INVALID;
     138                 :            : 
     139         [ #  # ]:          0 :         while ((c = getopt_long(argc, argv, "hadxpfm:uIi:l:Rr:vV", options, NULL)) >= 0)
     140   [ #  #  #  #  :          0 :                 switch(c) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     141                 :            : 
     142                 :          0 :                 case 'h':
     143                 :          0 :                         return resolvconf_help();
     144                 :            : 
     145                 :          0 :                 case ARG_VERSION:
     146                 :          0 :                         return version();
     147                 :            : 
     148                 :            :                 /* -a and -d is what everybody can agree on */
     149                 :          0 :                 case 'a':
     150                 :          0 :                         arg_mode = MODE_SET_LINK;
     151                 :          0 :                         break;
     152                 :            : 
     153                 :          0 :                 case 'd':
     154                 :          0 :                         arg_mode = MODE_REVERT_LINK;
     155                 :          0 :                         break;
     156                 :            : 
     157                 :            :                 /* The exclusive/private/force stuff is an openresolv invention, we support in some skewed way */
     158                 :          0 :                 case 'x':
     159                 :          0 :                         type = TYPE_EXCLUSIVE;
     160                 :          0 :                         break;
     161                 :            : 
     162                 :          0 :                 case 'p':
     163                 :          0 :                         type = TYPE_PRIVATE; /* not actually supported */
     164                 :          0 :                         break;
     165                 :            : 
     166                 :          0 :                 case 'f':
     167                 :          0 :                         arg_ifindex_permissive = true;
     168                 :          0 :                         break;
     169                 :            : 
     170                 :            :                 /* The metrics stuff is an openresolv invention we ignore (and don't really need) */
     171                 :          0 :                 case 'm':
     172         [ #  # ]:          0 :                         log_debug("Switch -%c ignored.", c);
     173                 :          0 :                         break;
     174                 :            : 
     175                 :            :                 /* Everybody else can agree on the existence of -u but we don't support it. */
     176                 :          0 :                 case 'u':
     177                 :            : 
     178                 :            :                 /* The following options are openresolv inventions we don't support. */
     179                 :            :                 case 'I':
     180                 :            :                 case 'i':
     181                 :            :                 case 'l':
     182                 :            :                 case 'R':
     183                 :            :                 case 'r':
     184                 :            :                 case 'v':
     185                 :            :                 case 'V':
     186         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     187                 :            :                                                "Switch -%c not supported.", c);
     188                 :            : 
     189                 :            :                 /* The Debian resolvconf commands we don't support. */
     190                 :          0 :                 case ARG_ENABLE_UPDATES:
     191         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     192                 :            :                                                "Switch --enable-updates not supported.");
     193                 :          0 :                 case ARG_DISABLE_UPDATES:
     194         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     195                 :            :                                                "Switch --disable-updates not supported.");
     196                 :          0 :                 case ARG_UPDATES_ARE_ENABLED:
     197         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     198                 :            :                                                "Switch --updates-are-enabled not supported.");
     199                 :            : 
     200                 :          0 :                 case '?':
     201                 :          0 :                         return -EINVAL;
     202                 :            : 
     203                 :          0 :                 default:
     204                 :          0 :                         assert_not_reached("Unhandled option");
     205                 :            :                 }
     206                 :            : 
     207         [ #  # ]:          0 :         if (arg_mode == _MODE_INVALID)
     208         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     209                 :            :                                        "Expected either -a or -d on the command line.");
     210                 :            : 
     211         [ #  # ]:          0 :         if (optind+1 != argc)
     212         [ #  # ]:          0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     213                 :            :                                        "Expected interface name as argument.");
     214                 :            : 
     215                 :          0 :         r = ifname_mangle(argv[optind]);
     216         [ #  # ]:          0 :         if (r <= 0)
     217                 :          0 :                 return r;
     218                 :            : 
     219                 :          0 :         optind++;
     220                 :            : 
     221         [ #  # ]:          0 :         if (arg_mode == MODE_SET_LINK) {
     222                 :          0 :                 unsigned n = 0;
     223                 :            : 
     224                 :          0 :                 for (;;) {
     225   [ #  #  #  # ]:          0 :                         _cleanup_free_ char *line = NULL;
     226                 :            :                         const char *a, *l;
     227                 :            : 
     228                 :          0 :                         r = read_line(stdin, LONG_LINE_MAX, &line);
     229         [ #  # ]:          0 :                         if (r < 0)
     230         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to read from stdin: %m");
     231         [ #  # ]:          0 :                         if (r == 0)
     232                 :          0 :                                 break;
     233                 :            : 
     234                 :          0 :                         n++;
     235                 :            : 
     236                 :          0 :                         l = strstrip(line);
     237   [ #  #  #  # ]:          0 :                         if (IN_SET(*l, '#', ';', 0))
     238                 :          0 :                                 continue;
     239                 :            : 
     240                 :          0 :                         a = first_word(l, "nameserver");
     241         [ #  # ]:          0 :                         if (a) {
     242                 :          0 :                                 (void) parse_nameserver(a);
     243                 :          0 :                                 continue;
     244                 :            :                         }
     245                 :            : 
     246                 :          0 :                         a = first_word(l, "domain");
     247         [ #  # ]:          0 :                         if (!a)
     248                 :          0 :                                 a = first_word(l, "search");
     249         [ #  # ]:          0 :                         if (a) {
     250                 :          0 :                                 (void) parse_search_domain(a);
     251                 :          0 :                                 continue;
     252                 :            :                         }
     253                 :            : 
     254         [ #  # ]:          0 :                         log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", l);
     255                 :            :                 }
     256                 :            : 
     257         [ #  # ]:          0 :                 if (type == TYPE_EXCLUSIVE) {
     258                 :            : 
     259                 :            :                         /* If -x mode is selected, let's preferably route non-suffixed lookups to this interface. This
     260                 :            :                          * somewhat matches the original -x behaviour */
     261                 :            : 
     262                 :          0 :                         r = strv_extend(&arg_set_domain, "~.");
     263         [ #  # ]:          0 :                         if (r < 0)
     264                 :          0 :                                 return log_oom();
     265                 :            : 
     266         [ #  # ]:          0 :                 } else if (type == TYPE_PRIVATE)
     267         [ #  # ]:          0 :                         log_debug("Private DNS server data not supported, ignoring.");
     268                 :            : 
     269         [ #  # ]:          0 :                 if (!arg_set_dns)
     270         [ #  # ]:          0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
     271                 :            :                                                "No DNS servers specified, refusing operation.");
     272                 :            :         }
     273                 :            : 
     274                 :          0 :         return 1; /* work to do */
     275                 :            : }

Generated by: LCOV version 1.14