mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-24 21:34:08 +03:00
Merge pull request #8296 from poettering/resolvconf
resolvconf(8) compat interface
This commit is contained in:
commit
99eae076eb
@ -614,7 +614,7 @@ manpages = [
|
|||||||
'ENABLE_RANDOMSEED'],
|
'ENABLE_RANDOMSEED'],
|
||||||
['systemd-rc-local-generator', '8', [], ''],
|
['systemd-rc-local-generator', '8', [], ''],
|
||||||
['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
|
['systemd-remount-fs.service', '8', ['systemd-remount-fs'], ''],
|
||||||
['systemd-resolve', '1', [], 'ENABLE_RESOLVE'],
|
['systemd-resolve', '1', ['resolvconf'], 'ENABLE_RESOLVE'],
|
||||||
['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'],
|
['systemd-resolved.service', '8', ['systemd-resolved'], 'ENABLE_RESOLVE'],
|
||||||
['systemd-rfkill.service',
|
['systemd-rfkill.service',
|
||||||
'8',
|
'8',
|
||||||
|
@ -47,7 +47,8 @@
|
|||||||
|
|
||||||
<refnamediv>
|
<refnamediv>
|
||||||
<refname>systemd-resolve</refname>
|
<refname>systemd-resolve</refname>
|
||||||
<refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services</refpurpose>
|
<refname>resolvconf</refname>
|
||||||
|
<refpurpose>Resolve domain names, IPV4 and IPv6 addresses, DNS resource records, and services; introspect and reconfigure the DNS resolver</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
@ -134,6 +135,18 @@
|
|||||||
<command> --revert</command>
|
<command> --revert</command>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
|
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>resolvconf</command>
|
||||||
|
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||||
|
<command> -a <replaceable>INTERFACE</replaceable> < <replaceable>FILE</replaceable></command>
|
||||||
|
</cmdsynopsis>
|
||||||
|
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>resolvconf</command>
|
||||||
|
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||||
|
<command> -d <replaceable>INTERFACE</replaceable></command>
|
||||||
|
</cmdsynopsis>
|
||||||
|
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@ -399,6 +412,82 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Compatibility with <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry></title>
|
||||||
|
|
||||||
|
<para><command>systemd-resolve</command> is a multi-call binary. When invoked as <literal>resolvconf</literal>
|
||||||
|
(generally achieved by means of a symbolic link of this name to the <command>systemd-resolve</command> binary) it
|
||||||
|
is run in a limited <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
|
compatibility mode. It accepts mostly the same arguments and pushes all data into
|
||||||
|
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
similar to how <option>--set-dns=</option> and <option>--set-domain=</option> operate. Note that
|
||||||
|
<command>systemd-resolved.service</command> is the only supported backend, which is different from other
|
||||||
|
implementations of this command. Note that not all operations supported by other implementations are supported
|
||||||
|
natively. Specifically:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-a</option></term>
|
||||||
|
<listitem><para>Registers per-interface DNS configuration data with
|
||||||
|
<command>systemd-resolved</command>. Expects a network interface name as only command line argument. Reads
|
||||||
|
<citerefentry><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> compatible DNS
|
||||||
|
configuration data from its standard input. Relevant fields are <literal>nameserver</literal> and
|
||||||
|
<literal>domain</literal>/<literal>search</literal>. This command is mostly identical to invoking
|
||||||
|
<command>systemd-resolve</command> with a combination of <option>--set-dns=</option> and
|
||||||
|
<option>--set-domain=</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-d</option></term>
|
||||||
|
<listitem><para>Unregisters per-interface DNS configuration data with <command>systemd-resolved</command>. This
|
||||||
|
command is mostly identical to invoking <command>systemd-resolve</command> with
|
||||||
|
<option>--revert</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-f</option></term>
|
||||||
|
|
||||||
|
<listitem><para>When specified <option>-a</option> and <option>-d</option> will not complain about missing
|
||||||
|
network interfaces and will silently execute no operation in that case.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-x</option></term>
|
||||||
|
|
||||||
|
<listitem><para>This switch for "exclusive" operation is supported only partially. It is mapped to an
|
||||||
|
additional configured search domain of <literal>~.</literal> — i.e. ensures that DNS traffic is preferably
|
||||||
|
routed to the DNS servers on this interface, unless there are other, more specific domains configured on other
|
||||||
|
interfaces.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-m</option></term>
|
||||||
|
<term><option>-p</option></term>
|
||||||
|
|
||||||
|
<listitem><para>These switches are not supported and are silently ignored.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-u</option></term>
|
||||||
|
<term><option>-I</option></term>
|
||||||
|
<term><option>-i</option></term>
|
||||||
|
<term><option>-l</option></term>
|
||||||
|
<term><option>-R</option></term>
|
||||||
|
<term><option>-r</option></term>
|
||||||
|
<term><option>-v</option></term>
|
||||||
|
<term><option>-V</option></term>
|
||||||
|
<term><option>--enable-updates</option></term>
|
||||||
|
<term><option>--disable-updates</option></term>
|
||||||
|
<term><option>--are-updates-enabled</option></term>
|
||||||
|
|
||||||
|
<listitem><para>These switches are not supported and the command will fail if used.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para>See <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details on this command line options.</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
|
|
||||||
@ -477,7 +566,8 @@ _443._tcp.fedoraproject.org IN TLSA 0 0 1 19400be5b7a31fb733917700789d2f0a2471c0
|
|||||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd.dnssd</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
<citerefentry><refentrytitle>systemd.dnssd</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
@ -1632,6 +1632,10 @@ if conf.get('ENABLE_RESOLVE') == 1
|
|||||||
install_rpath : rootlibexecdir,
|
install_rpath : rootlibexecdir,
|
||||||
install : true)
|
install : true)
|
||||||
public_programs += [exe]
|
public_programs += [exe]
|
||||||
|
|
||||||
|
meson.add_install_script(meson_make_symlink,
|
||||||
|
join_paths(bindir, 'systemd-resolve'),
|
||||||
|
join_paths(rootsbindir, 'resolvconf'))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if conf.get('ENABLE_LOGIND') == 1
|
if conf.get('ENABLE_LOGIND') == 1
|
||||||
|
@ -80,7 +80,12 @@ systemd_resolved_sources = files('''
|
|||||||
resolved-etc-hosts.c
|
resolved-etc-hosts.c
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
systemd_resolve_sources = files('resolve-tool.c')
|
systemd_resolve_sources = files('''
|
||||||
|
resolvconf-compat.c
|
||||||
|
resolvconf-compat.h
|
||||||
|
resolve-tool.c
|
||||||
|
resolve-tool.h
|
||||||
|
'''.split())
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
|
|
||||||
|
312
src/resolve/resolvconf-compat.c
Normal file
312
src/resolve/resolvconf-compat.c
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
#include "alloc-util.h"
|
||||||
|
#include "def.h"
|
||||||
|
#include "dns-domain.h"
|
||||||
|
#include "extract-word.h"
|
||||||
|
#include "fileio.h"
|
||||||
|
#include "parse-util.h"
|
||||||
|
#include "resolvconf-compat.h"
|
||||||
|
#include "resolve-tool.h"
|
||||||
|
#include "resolved-def.h"
|
||||||
|
#include "string-util.h"
|
||||||
|
#include "strv.h"
|
||||||
|
|
||||||
|
static void resolvconf_help(void) {
|
||||||
|
printf("%1$s -a INTERFACE < FILE\n"
|
||||||
|
"%1$s -d INTERFACE\n"
|
||||||
|
"\n"
|
||||||
|
"Register DNS server and domain configuration with systemd-resolved.\n\n"
|
||||||
|
" -h --help Show this help\n"
|
||||||
|
" --version Show package version\n"
|
||||||
|
" -a Register per-interface DNS server and domain data\n"
|
||||||
|
" -d Unregister per-interface DNS server and domain data\n"
|
||||||
|
" -f Ignore if specified interface does not exist\n"
|
||||||
|
" -x Send DNS traffic preferably over this interface\n"
|
||||||
|
"\n"
|
||||||
|
"This is a compatibility alias for the systemd-resolve(1) tool, providing native\n"
|
||||||
|
"command line compatibility with the resolvconf(8) tool of various Linux\n"
|
||||||
|
"distributions and BSD systems. Some options supported by other implementations\n"
|
||||||
|
"are not supported and are ignored: -m, -p. Various options supported by other\n"
|
||||||
|
"implementations are not supported and will cause the invocation to fail: -u,\n"
|
||||||
|
"-I, -i, -l, -R, -r, -v, -V, --enable-updates, --disable-updates,\n"
|
||||||
|
"--updates-are-enabled.\n"
|
||||||
|
, program_invocation_short_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_nameserver(const char *string) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(string);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *word = NULL;
|
||||||
|
struct in_addr_data data, *n;
|
||||||
|
int ifindex = 0;
|
||||||
|
|
||||||
|
r = extract_first_word(&string, &word, NULL, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = in_addr_ifindex_from_string_auto(word, &data.family, &data.address, &ifindex);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse name server '%s': %m", word);
|
||||||
|
|
||||||
|
if (ifindex > 0 && ifindex != arg_ifindex) {
|
||||||
|
log_error("Name server interface '%s' does not match selected interface: %m", word);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some superficial filtering */
|
||||||
|
if (in_addr_is_null(data.family, &data.address))
|
||||||
|
continue;
|
||||||
|
if (data.family == AF_INET && data.address.in.s_addr == htobe32(INADDR_DNS_STUB)) /* resolved's own stub? */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
n = reallocarray(arg_set_dns, arg_n_set_dns + 1, sizeof(struct in_addr_data));
|
||||||
|
if (!n)
|
||||||
|
return log_oom();
|
||||||
|
arg_set_dns = n;
|
||||||
|
|
||||||
|
arg_set_dns[arg_n_set_dns++] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_search_domain(const char *string) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(string);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *word = NULL;
|
||||||
|
|
||||||
|
r = extract_first_word(&string, &word, NULL, EXTRACT_QUOTES);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = dns_name_is_valid(word);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to validate specified domain '%s': %m", word);
|
||||||
|
if (r == 0) {
|
||||||
|
log_error("Domain not valid: %s", word);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strv_push(&arg_set_domain, word) < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
word = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int resolvconf_parse_argv(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARG_VERSION = 0x100,
|
||||||
|
ARG_ENABLE_UPDATES,
|
||||||
|
ARG_DISABLE_UPDATES,
|
||||||
|
ARG_UPDATES_ARE_ENABLED,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct option options[] = {
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
|
|
||||||
|
/* The following are specific to Debian's original resolvconf */
|
||||||
|
{ "enable-updates", no_argument, NULL, ARG_ENABLE_UPDATES },
|
||||||
|
{ "disable-updates", no_argument, NULL, ARG_DISABLE_UPDATES },
|
||||||
|
{ "updates-are-enabled", no_argument, NULL, ARG_UPDATES_ARE_ENABLED },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TYPE_REGULAR,
|
||||||
|
TYPE_PRIVATE, /* -p: Not supported, treated identically to TYPE_REGULAR */
|
||||||
|
TYPE_EXCLUSIVE, /* -x */
|
||||||
|
} type = TYPE_REGULAR;
|
||||||
|
|
||||||
|
const char *dot, *iface;
|
||||||
|
int c, r;
|
||||||
|
|
||||||
|
assert(argc >= 0);
|
||||||
|
assert(argv);
|
||||||
|
|
||||||
|
/* openresolv checks these environment variables */
|
||||||
|
if (getenv("IF_EXCLUSIVE"))
|
||||||
|
type = TYPE_EXCLUSIVE;
|
||||||
|
if (getenv("IF_PRIVATE"))
|
||||||
|
type = TYPE_PRIVATE; /* not actually supported */
|
||||||
|
|
||||||
|
arg_mode = _MODE_INVALID;
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "hadxpfm:uIi:l:Rr:vV", options, NULL)) >= 0)
|
||||||
|
switch(c) {
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
resolvconf_help();
|
||||||
|
return 0; /* done */;
|
||||||
|
|
||||||
|
case ARG_VERSION:
|
||||||
|
return version();
|
||||||
|
|
||||||
|
/* -a and -d is what everybody can agree on */
|
||||||
|
case 'a':
|
||||||
|
arg_mode = MODE_SET_LINK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
arg_mode = MODE_REVERT_LINK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* The exclusive/private/force stuff is an openresolv invention, we support in some skewed way */
|
||||||
|
case 'x':
|
||||||
|
type = TYPE_EXCLUSIVE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
type = TYPE_PRIVATE; /* not actually supported */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
arg_ifindex_permissive = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* The metrics stuff is an openresolv invention we ignore (and don't really need) */
|
||||||
|
case 'm':
|
||||||
|
log_debug("Switch -%c ignored.", c);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Everybody else can agree on the existance of -u but we don't support it. */
|
||||||
|
case 'u':
|
||||||
|
|
||||||
|
/* The following options are openresolv inventions we don't support. */
|
||||||
|
case 'I':
|
||||||
|
case 'i':
|
||||||
|
case 'l':
|
||||||
|
case 'R':
|
||||||
|
case 'r':
|
||||||
|
case 'v':
|
||||||
|
case 'V':
|
||||||
|
log_error("Switch -%c not supported.", c);
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* The Debian resolvconf commands we don't support. */
|
||||||
|
case ARG_ENABLE_UPDATES:
|
||||||
|
log_error("Switch --enable-updates not supported.");
|
||||||
|
return -EINVAL;
|
||||||
|
case ARG_DISABLE_UPDATES:
|
||||||
|
log_error("Switch --disable-updates not supported.");
|
||||||
|
return -EINVAL;
|
||||||
|
case ARG_UPDATES_ARE_ENABLED:
|
||||||
|
log_error("Switch --updates-are-enabled not supported.");
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached("Unhandled option");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_mode == _MODE_INVALID) {
|
||||||
|
log_error("Expected either -a or -d on the command line.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind+1 != argc) {
|
||||||
|
log_error("Expected interface name as argument.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dot = strchr(argv[optind], '.');
|
||||||
|
if (dot) {
|
||||||
|
iface = strndupa(argv[optind], dot - argv[optind]);
|
||||||
|
log_debug("Ignoring protocol specifier '%s'.", dot + 1);
|
||||||
|
} else
|
||||||
|
iface = argv[optind];
|
||||||
|
optind++;
|
||||||
|
|
||||||
|
if (parse_ifindex(iface, &arg_ifindex) < 0) {
|
||||||
|
int ifi;
|
||||||
|
|
||||||
|
ifi = if_nametoindex(iface);
|
||||||
|
if (ifi <= 0) {
|
||||||
|
if (errno == ENODEV && arg_ifindex_permissive) {
|
||||||
|
log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
|
||||||
|
return 0; /* done */
|
||||||
|
}
|
||||||
|
|
||||||
|
return log_error_errno(errno, "Unknown interface '%s': %m", iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
arg_ifindex = ifi;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_mode == MODE_SET_LINK) {
|
||||||
|
unsigned n = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *line = NULL;
|
||||||
|
const char *a, *l;
|
||||||
|
|
||||||
|
r = read_line(stdin, LONG_LINE_MAX, &line);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to read from stdin: %m");
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n++;
|
||||||
|
|
||||||
|
l = strstrip(line);
|
||||||
|
if (IN_SET(*l, '#', ';', 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
a = first_word(l, "nameserver");
|
||||||
|
if (a) {
|
||||||
|
(void) parse_nameserver(a);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = first_word(l, "domain");
|
||||||
|
if (!a)
|
||||||
|
a = first_word(l, "search");
|
||||||
|
if (a) {
|
||||||
|
(void) parse_search_domain(a);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_syntax(NULL, LOG_DEBUG, "stdin", n, 0, "Ignoring resolv.conf line: %s", l);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == TYPE_EXCLUSIVE) {
|
||||||
|
|
||||||
|
/* If -x mode is selected, let's preferably route non-suffixed lookups to this interface. This
|
||||||
|
* somewhat matches the original -x behaviour */
|
||||||
|
|
||||||
|
r = strv_extend(&arg_set_domain, "~.");
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
} else if (type == TYPE_PRIVATE)
|
||||||
|
log_debug("Private DNS server data not supported, ignoring.");
|
||||||
|
|
||||||
|
if (arg_n_set_dns == 0) {
|
||||||
|
log_error("No DNS servers specified, refusing operation.");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* work to do */
|
||||||
|
}
|
3
src/resolve/resolvconf-compat.h
Normal file
3
src/resolve/resolvconf-compat.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
int resolvconf_parse_argv(int argc, char *argv[]);
|
@ -36,18 +36,21 @@
|
|||||||
#include "netlink-util.h"
|
#include "netlink-util.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
#include "resolvconf-compat.h"
|
||||||
|
#include "resolve-tool.h"
|
||||||
#include "resolved-def.h"
|
#include "resolved-def.h"
|
||||||
#include "resolved-dns-packet.h"
|
#include "resolved-dns-packet.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
|
|
||||||
static int arg_family = AF_UNSPEC;
|
static int arg_family = AF_UNSPEC;
|
||||||
static int arg_ifindex = 0;
|
int arg_ifindex = 0;
|
||||||
static uint16_t arg_type = 0;
|
static uint16_t arg_type = 0;
|
||||||
static uint16_t arg_class = 0;
|
static uint16_t arg_class = 0;
|
||||||
static bool arg_legend = true;
|
static bool arg_legend = true;
|
||||||
static uint64_t arg_flags = 0;
|
static uint64_t arg_flags = 0;
|
||||||
static bool arg_no_pager = false;
|
static bool arg_no_pager = false;
|
||||||
|
bool arg_ifindex_permissive = false; /* If true, don't generate an error if the specified interface index doesn't exist */
|
||||||
|
|
||||||
typedef enum ServiceFamily {
|
typedef enum ServiceFamily {
|
||||||
SERVICE_FAMILY_TCP,
|
SERVICE_FAMILY_TCP,
|
||||||
@ -64,24 +67,11 @@ typedef enum RawType {
|
|||||||
} RawType;
|
} RawType;
|
||||||
static RawType arg_raw = RAW_NONE;
|
static RawType arg_raw = RAW_NONE;
|
||||||
|
|
||||||
static enum {
|
ExecutionMode arg_mode = MODE_RESOLVE_HOST;
|
||||||
MODE_RESOLVE_HOST,
|
|
||||||
MODE_RESOLVE_RECORD,
|
|
||||||
MODE_RESOLVE_SERVICE,
|
|
||||||
MODE_RESOLVE_OPENPGP,
|
|
||||||
MODE_RESOLVE_TLSA,
|
|
||||||
MODE_STATISTICS,
|
|
||||||
MODE_RESET_STATISTICS,
|
|
||||||
MODE_FLUSH_CACHES,
|
|
||||||
MODE_RESET_SERVER_FEATURES,
|
|
||||||
MODE_STATUS,
|
|
||||||
MODE_SET_LINK,
|
|
||||||
MODE_REVERT_LINK,
|
|
||||||
} arg_mode = MODE_RESOLVE_HOST;
|
|
||||||
|
|
||||||
static struct in_addr_data *arg_set_dns = NULL;
|
struct in_addr_data *arg_set_dns = NULL;
|
||||||
static size_t arg_n_set_dns = 0;
|
size_t arg_n_set_dns = 0;
|
||||||
static char **arg_set_domain = NULL;
|
char **arg_set_domain = NULL;
|
||||||
static char *arg_set_llmnr = NULL;
|
static char *arg_set_llmnr = NULL;
|
||||||
static char *arg_set_mdns = NULL;
|
static char *arg_set_mdns = NULL;
|
||||||
static char *arg_set_dnssec = NULL;
|
static char *arg_set_dnssec = NULL;
|
||||||
@ -1609,6 +1599,9 @@ static int set_link(sd_bus *bus) {
|
|||||||
if (q < 0) {
|
if (q < 0) {
|
||||||
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
|
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
|
||||||
goto is_managed;
|
goto is_managed;
|
||||||
|
if (arg_ifindex_permissive &&
|
||||||
|
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
log_error_errno(q, "Failed to set DNS configuration: %s", bus_error_message(&error, q));
|
log_error_errno(q, "Failed to set DNS configuration: %s", bus_error_message(&error, q));
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -1655,6 +1648,9 @@ static int set_link(sd_bus *bus) {
|
|||||||
if (q < 0) {
|
if (q < 0) {
|
||||||
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
|
if (sd_bus_error_has_name(&error, BUS_ERROR_LINK_BUSY))
|
||||||
goto is_managed;
|
goto is_managed;
|
||||||
|
if (arg_ifindex_permissive &&
|
||||||
|
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
log_error_errno(q, "Failed to set domain configuration: %s", bus_error_message(&error, q));
|
log_error_errno(q, "Failed to set domain configuration: %s", bus_error_message(&error, q));
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
@ -1777,8 +1773,13 @@ static int revert_link(sd_bus *bus) {
|
|||||||
&error,
|
&error,
|
||||||
NULL,
|
NULL,
|
||||||
"i", arg_ifindex);
|
"i", arg_ifindex);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
if (arg_ifindex_permissive &&
|
||||||
|
sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_LINK))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
|
return log_error_errno(r, "Failed to revert interface configuration: %s", bus_error_message(&error, r));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1815,7 +1816,7 @@ static void help_dns_classes(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void help(void) {
|
static void native_help(void) {
|
||||||
printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
|
printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
|
||||||
"%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
|
"%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
|
||||||
"%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
|
"%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
|
||||||
@ -1858,7 +1859,7 @@ static void help(void) {
|
|||||||
, program_invocation_short_name);
|
, program_invocation_short_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_argv(int argc, char *argv[]) {
|
static int native_parse_argv(int argc, char *argv[]) {
|
||||||
enum {
|
enum {
|
||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LEGEND,
|
ARG_LEGEND,
|
||||||
@ -1926,7 +1927,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
switch(c) {
|
switch(c) {
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
native_help();
|
||||||
return 0; /* done */;
|
return 0; /* done */;
|
||||||
|
|
||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
@ -2234,7 +2235,10 @@ int main(int argc, char **argv) {
|
|||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
if (streq(program_invocation_short_name, "resolvconf"))
|
||||||
|
r = resolvconf_parse_argv(argc, argv);
|
||||||
|
else
|
||||||
|
r = native_parse_argv(argc, argv);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
@ -2435,6 +2439,9 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
r = revert_link(bus);
|
r = revert_link(bus);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case _MODE_INVALID:
|
||||||
|
assert_not_reached("invalid mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
30
src/resolve/resolve-tool.h
Normal file
30
src/resolve/resolve-tool.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
|
#include <in-addr-util.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
extern int arg_ifindex;
|
||||||
|
extern bool arg_ifindex_permissive;
|
||||||
|
|
||||||
|
typedef enum ExecutionMode {
|
||||||
|
MODE_RESOLVE_HOST,
|
||||||
|
MODE_RESOLVE_RECORD,
|
||||||
|
MODE_RESOLVE_SERVICE,
|
||||||
|
MODE_RESOLVE_OPENPGP,
|
||||||
|
MODE_RESOLVE_TLSA,
|
||||||
|
MODE_STATISTICS,
|
||||||
|
MODE_RESET_STATISTICS,
|
||||||
|
MODE_FLUSH_CACHES,
|
||||||
|
MODE_RESET_SERVER_FEATURES,
|
||||||
|
MODE_STATUS,
|
||||||
|
MODE_SET_LINK,
|
||||||
|
MODE_REVERT_LINK,
|
||||||
|
_MODE_INVALID = -1,
|
||||||
|
} ExecutionMode;
|
||||||
|
|
||||||
|
extern ExecutionMode arg_mode;
|
||||||
|
|
||||||
|
extern struct in_addr_data *arg_set_dns;
|
||||||
|
extern size_t arg_n_set_dns;
|
||||||
|
extern char **arg_set_domain;
|
@ -41,3 +41,6 @@
|
|||||||
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
|
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
|
||||||
|
|
||||||
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
|
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
|
||||||
|
|
||||||
|
/* 127.0.0.53 in native endian */
|
||||||
|
#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
|
||||||
|
@ -22,8 +22,5 @@
|
|||||||
|
|
||||||
#include "resolved-manager.h"
|
#include "resolved-manager.h"
|
||||||
|
|
||||||
/* 127.0.0.53 in native endian */
|
|
||||||
#define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
|
|
||||||
|
|
||||||
void manager_dns_stub_stop(Manager *m);
|
void manager_dns_stub_stop(Manager *m);
|
||||||
int manager_dns_stub_start(Manager *m);
|
int manager_dns_stub_start(Manager *m);
|
||||||
|
Loading…
Reference in New Issue
Block a user