2020-11-09 05:23:58 +01:00
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2014-07-16 22:55:23 +02:00
# include <getopt.h>
2019-03-27 11:32:41 +01:00
# include <locale.h>
2015-11-16 22:09:36 +01:00
# include <net/if.h>
2014-07-16 22:55:23 +02:00
# include "sd-bus.h"
2016-06-15 21:43:36 +02:00
# include "sd-netlink.h"
2015-09-23 03:01:06 +02:00
# include "af-list.h"
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2017-12-14 20:13:14 +01:00
# include "bus-common-errors.h"
2014-07-16 22:55:23 +02:00
# include "bus-error.h"
2020-06-28 15:59:37 +02:00
# include "bus-locator.h"
2020-06-28 16:08:37 +02:00
# include "bus-map-properties.h"
2020-07-19 05:43:39 +02:00
# include "bus-message-util.h"
2017-12-14 20:13:14 +01:00
# include "dns-domain.h"
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
# include "escape.h"
2020-01-14 10:29:53 +01:00
# include "format-table.h"
2019-05-29 07:18:41 +02:00
# include "format-util.h"
2016-01-29 00:24:27 +01:00
# include "gcrypt-util.h"
2018-11-22 22:00:02 +01:00
# include "main-func.h"
2018-12-06 07:20:07 +01:00
# include "missing_network.h"
2016-06-15 21:43:36 +02:00
# include "netlink-util.h"
# include "pager.h"
2015-10-26 16:18:16 +01:00
# include "parse-util.h"
2018-11-20 15:42:57 +01:00
# include "pretty-print.h"
2018-02-27 17:48:54 +01:00
# include "resolvconf-compat.h"
2018-04-18 20:24:23 +02:00
# include "resolvectl.h"
2014-08-14 01:00:15 +02:00
# include "resolved-def.h"
2015-09-23 03:01:06 +02:00
# include "resolved-dns-packet.h"
2020-01-10 17:22:37 +01:00
# include "socket-netlink.h"
2020-06-02 17:49:22 +02:00
# include "sort-util.h"
2020-01-11 11:37:26 +01:00
# include "stdio-util.h"
2018-05-22 12:10:56 +02:00
# include "string-table.h"
2016-06-15 21:43:36 +02:00
# include "strv.h"
2015-12-23 19:06:36 +01:00
# include "terminal-util.h"
2020-10-11 11:54:18 +02:00
# include "utf8.h"
2018-04-11 03:44:51 +02:00
# include "verbs.h"
2014-07-30 19:23:27 +02:00
2014-07-16 22:55:23 +02:00
static int arg_family = AF_UNSPEC ;
2018-06-26 09:41:22 +02:00
static int arg_ifindex = 0 ;
static char * arg_ifname = NULL ;
2015-12-18 18:53:11 +01:00
static uint16_t arg_type = 0 ;
2014-07-30 19:23:27 +02:00
static uint16_t arg_class = 0 ;
2014-08-01 02:06:30 +02:00
static bool arg_legend = true ;
2014-08-14 01:00:15 +02:00
static uint64_t arg_flags = 0 ;
2018-11-11 12:56:29 +01:00
static PagerFlags arg_pager_flags = 0 ;
2018-02-27 17:48:54 +01:00
bool arg_ifindex_permissive = false ; /* If true, don't generate an error if the specified interface index doesn't exist */
2018-04-11 03:44:51 +02:00
static const char * arg_service_family = NULL ;
2016-02-18 03:08:57 +01:00
2016-01-31 06:06:49 +01:00
typedef enum RawType {
RAW_NONE ,
RAW_PAYLOAD ,
RAW_PACKET ,
} RawType ;
static RawType arg_raw = RAW_NONE ;
2015-12-23 19:06:36 +01:00
2018-02-27 17:48:54 +01:00
ExecutionMode arg_mode = MODE_RESOLVE_HOST ;
2018-04-11 03:44:51 +02:00
char * * arg_set_dns = NULL ;
2018-02-27 17:48:54 +01:00
char * * arg_set_domain = NULL ;
2018-04-11 03:44:51 +02:00
static const char * arg_set_llmnr = NULL ;
static const char * arg_set_mdns = NULL ;
2018-06-13 20:26:24 +02:00
static const char * arg_set_dns_over_tls = NULL ;
2018-04-11 03:44:51 +02:00
static const char * arg_set_dnssec = NULL ;
2017-12-14 20:13:14 +01:00
static char * * arg_set_nta = NULL ;
2018-11-22 22:00:02 +01:00
STATIC_DESTRUCTOR_REGISTER ( arg_ifname , freep ) ;
STATIC_DESTRUCTOR_REGISTER ( arg_set_dns , strv_freep ) ;
STATIC_DESTRUCTOR_REGISTER ( arg_set_domain , strv_freep ) ;
STATIC_DESTRUCTOR_REGISTER ( arg_set_nta , strv_freep ) ;
2018-04-11 03:44:51 +02:00
typedef enum StatusMode {
STATUS_ALL ,
STATUS_DNS ,
STATUS_DOMAIN ,
2018-12-04 13:29:41 +01:00
STATUS_DEFAULT_ROUTE ,
2018-04-11 03:44:51 +02:00
STATUS_LLMNR ,
STATUS_MDNS ,
2018-05-04 17:31:16 +02:00
STATUS_PRIVATE ,
2018-04-11 03:44:51 +02:00
STATUS_DNSSEC ,
STATUS_NTA ,
} StatusMode ;
2020-06-02 17:49:22 +02:00
typedef struct InterfaceInfo {
int index ;
const char * name ;
} InterfaceInfo ;
static int interface_info_compare ( const InterfaceInfo * a , const InterfaceInfo * b ) {
int r ;
r = CMP ( a - > index , b - > index ) ;
if ( r ! = 0 )
return r ;
return strcmp_ptr ( a - > name , b - > name ) ;
}
2018-12-05 14:02:06 +01:00
int ifname_mangle ( const char * s ) {
2018-06-26 09:41:22 +02:00
_cleanup_free_ char * iface = NULL ;
const char * dot ;
2019-12-18 13:54:13 +01:00
int ifi ;
2018-06-26 09:41:22 +02:00
assert ( s ) ;
dot = strchr ( s , ' . ' ) ;
if ( dot ) {
2018-12-05 13:33:31 +01:00
log_debug ( " Ignoring protocol specifier '%s'. " , dot + 1 ) ;
2018-06-26 09:41:22 +02:00
iface = strndup ( s , dot - s ) ;
2018-12-05 13:33:31 +01:00
} else
2018-06-26 09:41:22 +02:00
iface = strdup ( s ) ;
2018-12-05 13:33:31 +01:00
if ( ! iface )
return log_oom ( ) ;
2018-06-26 09:41:22 +02:00
2020-01-11 11:21:01 +01:00
ifi = resolve_interface ( NULL , iface ) ;
2019-12-18 13:54:13 +01:00
if ( ifi < 0 ) {
if ( ifi = = - ENODEV & & arg_ifindex_permissive ) {
2019-05-29 03:56:55 +02:00
log_debug ( " Interface '%s' not found, but -f specified, ignoring. " , iface ) ;
return 0 ; /* done */
2018-06-26 09:41:22 +02:00
}
2019-05-29 03:56:55 +02:00
2020-01-11 11:21:01 +01:00
return log_error_errno ( ifi , " Failed to resolve interface \" %s \" : %m " , iface ) ;
2018-06-26 09:41:22 +02:00
}
2019-04-02 14:51:48 +02:00
if ( arg_ifindex > 0 & & arg_ifindex ! = ifi )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) , " Specified multiple different interfaces. Refusing. " ) ;
2018-06-26 09:41:22 +02:00
2018-12-05 13:33:31 +01:00
arg_ifindex = ifi ;
free_and_replace ( arg_ifname , iface ) ;
2018-06-26 09:41:22 +02:00
return 1 ;
}
2015-08-17 23:54:08 +02:00
static void print_source ( uint64_t flags , usec_t rtt ) {
2015-08-11 22:37:23 +02:00
char rtt_str [ FORMAT_TIMESTAMP_MAX ] ;
2014-08-14 01:00:15 +02:00
if ( ! arg_legend )
return ;
2015-08-17 23:54:08 +02:00
if ( flags = = 0 )
2014-08-14 01:00:15 +02:00
return ;
2018-12-05 18:38:50 +01:00
printf ( " \n %s-- Information acquired via " , ansi_grey ( ) ) ;
2014-08-14 01:00:15 +02:00
2020-11-20 11:39:49 +01:00
printf ( " protocol%s%s%s%s%s " ,
flags & SD_RESOLVED_DNS ? " DNS " : " " ,
flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4 " : " " ,
flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6 " : " " ,
flags & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4 " : " " ,
flags & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6 " : " " ) ;
2014-08-14 01:00:15 +02:00
2015-08-11 22:37:23 +02:00
assert_se ( format_timespan ( rtt_str , sizeof ( rtt_str ) , rtt , 100 ) ) ;
2018-12-05 18:38:50 +01:00
printf ( " in %s.%s \n "
" %s-- Data is authenticated: %s%s \n " ,
rtt_str , ansi_normal ( ) ,
ansi_grey ( ) , yes_no ( flags & SD_RESOLVED_AUTHENTICATED ) , ansi_normal ( ) ) ;
2014-08-14 01:00:15 +02:00
}
2014-07-16 22:55:23 +02:00
2018-12-05 17:31:35 +01:00
static void print_ifindex_comment ( int printed_so_far , int ifindex ) {
2019-05-29 07:18:41 +02:00
char ifname [ IF_NAMESIZE + 1 ] ;
2015-08-11 22:37:23 +02:00
2018-12-05 17:31:35 +01:00
if ( ifindex < = 0 )
return ;
2015-12-03 21:04:52 +01:00
2019-05-29 07:18:41 +02:00
if ( ! format_ifname ( ifindex , ifname ) )
2018-12-05 17:31:35 +01:00
log_warning_errno ( errno , " Failed to resolve interface name for index %i, ignoring: %m " , ifindex ) ;
else
2018-12-05 18:38:50 +01:00
printf ( " %*s%s-- link: %s%s " ,
2018-12-05 17:31:35 +01:00
60 > printed_so_far ? 60 - printed_so_far : 0 , " " , /* Align comment to the 60th column */
2018-12-05 18:38:50 +01:00
ansi_grey ( ) , ifname , ansi_normal ( ) ) ;
2014-08-14 01:00:15 +02:00
}
2014-07-16 22:55:23 +02:00
2014-07-30 17:52:21 +02:00
static int resolve_host ( sd_bus * bus , const char * name ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2014-07-30 17:52:21 +02:00
const char * canonical = NULL ;
2014-07-16 22:55:23 +02:00
unsigned c = 0 ;
2014-08-14 01:00:15 +02:00
uint64_t flags ;
2015-08-11 22:37:23 +02:00
usec_t ts ;
2018-06-26 09:41:22 +02:00
int r ;
2014-07-16 22:55:23 +02:00
assert ( name ) ;
2018-06-26 09:41:22 +02:00
log_debug ( " Resolving %s (family %s, interface %s). " , name , af_to_name ( arg_family ) ? : " * " , isempty ( arg_ifname ) ? " * " : arg_ifname ) ;
2014-07-16 22:55:23 +02:00
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , bus_resolve_mgr , " ResolveHostname " ) ;
2014-07-30 17:11:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2014-07-16 22:55:23 +02:00
2014-08-14 01:00:15 +02:00
r = sd_bus_message_append ( req , " isit " , arg_ifindex , name , arg_family , arg_flags ) ;
2014-07-30 17:11:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2014-07-16 22:55:23 +02:00
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) ;
2018-01-23 01:53:31 +01:00
r = sd_bus_call ( bus , req , SD_RESOLVED_QUERY_TIMEOUT_USEC , & error , & reply ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( r < 0 )
return log_error_errno ( r , " %s: resolve call failed: %s " , name , bus_error_message ( & error , r ) ) ;
2014-07-16 22:55:23 +02:00
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) - ts ;
2015-08-17 23:54:08 +02:00
r = sd_bus_message_enter_container ( reply , ' a ' , " (iiay) " ) ;
2014-07-30 17:11:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-07-16 22:55:23 +02:00
2015-08-17 23:54:08 +02:00
while ( ( r = sd_bus_message_enter_container ( reply , ' r ' , " iiay " ) ) > 0 ) {
2014-07-16 22:55:23 +02:00
_cleanup_free_ char * pretty = NULL ;
2018-12-05 17:31:35 +01:00
int ifindex , family , k ;
2020-07-19 05:43:39 +02:00
union in_addr_union a ;
2015-08-17 23:54:08 +02:00
assert_cc ( sizeof ( int ) = = sizeof ( int32_t ) ) ;
2014-07-16 22:55:23 +02:00
2020-07-19 05:43:39 +02:00
r = sd_bus_message_read ( reply , " i " , & ifindex ) ;
2014-07-30 17:11:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-07-16 22:55:23 +02:00
2020-07-19 05:43:39 +02:00
sd_bus_error_free ( & error ) ;
r = bus_message_read_in_addr_auto ( reply , & error , & family , & a ) ;
if ( r < 0 & & ! sd_bus_error_has_name ( & error , SD_BUS_ERROR_INVALID_ARGS ) )
return log_error_errno ( r , " %s: systemd-resolved returned invalid result: %s " , name , bus_error_message ( & error , r ) ) ;
2014-07-16 22:55:23 +02:00
r = sd_bus_message_exit_container ( reply ) ;
2014-07-30 17:11:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-07-16 22:55:23 +02:00
2020-07-19 05:43:39 +02:00
if ( sd_bus_error_has_name ( & error , SD_BUS_ERROR_INVALID_ARGS ) ) {
log_debug_errno ( r , " %s: systemd-resolved returned invalid result, ignoring: %s " , name , bus_error_message ( & error , r ) ) ;
2014-07-16 22:55:23 +02:00
continue ;
}
2020-07-19 05:43:39 +02:00
r = in_addr_ifindex_to_string ( family , & a , ifindex , & pretty ) ;
2015-08-17 23:54:08 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to print address for %s: %m " , name ) ;
2014-07-16 22:55:23 +02:00
2018-12-05 18:23:48 +01:00
k = printf ( " %*s%s %s%s%s " ,
2018-12-05 17:31:35 +01:00
( int ) strlen ( name ) , c = = 0 ? name : " " , c = = 0 ? " : " : " " ,
2018-12-05 18:23:48 +01:00
ansi_highlight ( ) , pretty , ansi_normal ( ) ) ;
2018-12-05 17:31:35 +01:00
print_ifindex_comment ( k , ifindex ) ;
fputc ( ' \n ' , stdout ) ;
2014-07-16 22:55:23 +02:00
c + + ;
}
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-08-14 01:00:15 +02:00
r = sd_bus_message_read ( reply , " st " , & canonical , & flags ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2015-09-08 23:03:38 +02:00
if ( ! streq ( name , canonical ) )
2014-07-30 17:52:21 +02:00
printf ( " %*s%s (%s) \n " ,
( int ) strlen ( name ) , c = = 0 ? name : " " , c = = 0 ? " : " : " " ,
canonical ) ;
2014-07-16 22:55:23 +02:00
2020-10-09 14:59:44 +02:00
if ( c = = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( ESRCH ) ,
" %s: no addresses found " , name ) ;
2014-07-30 17:52:21 +02:00
2015-08-17 23:54:08 +02:00
print_source ( flags , ts ) ;
2014-08-14 01:00:15 +02:00
2014-07-30 17:52:21 +02:00
return 0 ;
}
static int resolve_address ( sd_bus * bus , int family , const union in_addr_union * address , int ifindex ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2014-07-30 17:52:21 +02:00
_cleanup_free_ char * pretty = NULL ;
2014-08-14 01:00:15 +02:00
uint64_t flags ;
2014-07-30 17:52:21 +02:00
unsigned c = 0 ;
2015-08-11 22:37:23 +02:00
usec_t ts ;
2014-07-30 17:52:21 +02:00
int r ;
assert ( bus ) ;
assert ( IN_SET ( family , AF_INET , AF_INET6 ) ) ;
assert ( address ) ;
2015-08-17 23:54:08 +02:00
if ( ifindex < = 0 )
ifindex = arg_ifindex ;
2016-06-14 23:27:30 +02:00
r = in_addr_ifindex_to_string ( family , address , ifindex , & pretty ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return log_oom ( ) ;
2018-12-05 17:42:09 +01:00
log_debug ( " Resolving %s. " , pretty ) ;
2014-07-30 17:52:21 +02:00
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , bus_resolve_mgr , " ResolveAddress " ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2014-08-14 01:00:15 +02:00
r = sd_bus_message_append ( req , " ii " , ifindex , family ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
r = sd_bus_message_append_array ( req , ' y ' , address , FAMILY_ADDRESS_SIZE ( family ) ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2014-08-14 01:00:15 +02:00
r = sd_bus_message_append ( req , " t " , arg_flags ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) ;
2018-01-23 01:53:31 +01:00
r = sd_bus_call ( bus , req , SD_RESOLVED_QUERY_TIMEOUT_USEC , & error , & reply ) ;
2018-08-07 03:14:30 +02:00
if ( r < 0 )
return log_error_errno ( r , " %s: resolve call failed: %s " , pretty , bus_error_message ( & error , r ) ) ;
2014-07-30 17:52:21 +02:00
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) - ts ;
2015-08-17 23:54:08 +02:00
r = sd_bus_message_enter_container ( reply , ' a ' , " (is) " ) ;
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2015-08-17 23:54:08 +02:00
while ( ( r = sd_bus_message_enter_container ( reply , ' r ' , " is " ) ) > 0 ) {
const char * n ;
2018-12-05 17:42:09 +01:00
int k ;
2015-08-17 23:54:08 +02:00
assert_cc ( sizeof ( int ) = = sizeof ( int32_t ) ) ;
2014-07-30 17:52:21 +02:00
2015-08-17 23:54:08 +02:00
r = sd_bus_message_read ( reply , " is " , & ifindex , & n ) ;
if ( r < 0 )
return r ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return r ;
2018-12-05 18:23:48 +01:00
k = printf ( " %*s%s %s%s%s " ,
( int ) strlen ( pretty ) , c = = 0 ? pretty : " " ,
c = = 0 ? " : " : " " ,
ansi_highlight ( ) , n , ansi_normal ( ) ) ;
2015-08-17 23:54:08 +02:00
2018-12-05 17:42:09 +01:00
print_ifindex_comment ( k , ifindex ) ;
fputc ( ' \n ' , stdout ) ;
2014-07-30 17:52:21 +02:00
c + + ;
2014-07-16 22:55:23 +02:00
}
2014-07-30 17:52:21 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-07-16 22:55:23 +02:00
2014-07-30 17:11:21 +02:00
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-08-14 01:00:15 +02:00
r = sd_bus_message_read ( reply , " t " , & flags ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2020-10-09 14:59:44 +02:00
if ( c = = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( ESRCH ) ,
" %s: no names found " , pretty ) ;
2014-07-30 17:52:21 +02:00
2015-08-17 23:54:08 +02:00
print_source ( flags , ts ) ;
2014-08-14 01:00:15 +02:00
2014-07-30 17:52:21 +02:00
return 0 ;
}
2016-01-31 06:06:49 +01:00
static int output_rr_packet ( const void * d , size_t l , int ifindex ) {
_cleanup_ ( dns_resource_record_unrefp ) DnsResourceRecord * rr = NULL ;
_cleanup_ ( dns_packet_unrefp ) DnsPacket * p = NULL ;
int r ;
2017-10-04 12:35:48 +02:00
r = dns_packet_new ( & p , DNS_PROTOCOL_DNS , 0 , DNS_PACKET_SIZE_MAX ) ;
2016-01-31 06:06:49 +01:00
if ( r < 0 )
return log_oom ( ) ;
p - > refuse_compression = true ;
r = dns_packet_append_blob ( p , d , l , NULL ) ;
if ( r < 0 )
return log_oom ( ) ;
r = dns_packet_read_rr ( p , & rr , NULL , NULL ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse RR: %m " ) ;
if ( arg_raw = = RAW_PAYLOAD ) {
void * data ;
ssize_t k ;
k = dns_resource_record_payload ( rr , & data ) ;
if ( k < 0 )
return log_error_errno ( k , " Cannot dump RR: %m " ) ;
fwrite ( data , 1 , k , stdout ) ;
} else {
const char * s ;
2018-12-05 17:42:09 +01:00
int k ;
2016-01-31 06:06:49 +01:00
s = dns_resource_record_to_string ( rr ) ;
if ( ! s )
return log_oom ( ) ;
2018-12-05 17:42:09 +01:00
k = printf ( " %s " , s ) ;
print_ifindex_comment ( k , ifindex ) ;
fputc ( ' \n ' , stdout ) ;
2016-01-31 06:06:49 +01:00
}
return 0 ;
}
2016-10-08 13:59:34 +02:00
static int resolve_record ( sd_bus * bus , const char * name , uint16_t class , uint16_t type , bool warn_missing ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2014-07-30 19:23:27 +02:00
unsigned n = 0 ;
2014-08-14 01:00:15 +02:00
uint64_t flags ;
2015-08-17 23:54:08 +02:00
int r ;
2015-08-11 22:37:23 +02:00
usec_t ts ;
2016-02-15 21:25:33 +01:00
bool needs_authentication = false ;
2014-07-30 19:23:27 +02:00
assert ( name ) ;
2018-06-26 09:41:22 +02:00
log_debug ( " Resolving %s %s %s (interface %s). " , name , dns_class_to_string ( class ) , dns_type_to_string ( type ) , isempty ( arg_ifname ) ? " * " : arg_ifname ) ;
2014-07-30 19:23:27 +02:00
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , bus_resolve_mgr , " ResolveRecord " ) ;
2014-07-30 19:23:27 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2016-01-03 12:58:26 +01:00
r = sd_bus_message_append ( req , " isqqt " , arg_ifindex , name , class , type , arg_flags ) ;
2014-07-30 19:23:27 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) ;
2018-01-23 01:53:31 +01:00
r = sd_bus_call ( bus , req , SD_RESOLVED_QUERY_TIMEOUT_USEC , & error , & reply ) ;
2014-07-30 19:23:27 +02:00
if ( r < 0 ) {
2016-10-08 13:59:34 +02:00
if ( warn_missing | | r ! = - ENXIO )
log_error ( " %s: resolve call failed: %s " , name , bus_error_message ( & error , r ) ) ;
2014-07-30 19:23:27 +02:00
return r ;
}
2015-08-11 22:37:23 +02:00
ts = now ( CLOCK_MONOTONIC ) - ts ;
2015-08-17 23:54:08 +02:00
r = sd_bus_message_enter_container ( reply , ' a ' , " (iqqay) " ) ;
2014-08-14 01:00:15 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2015-08-17 23:54:08 +02:00
while ( ( r = sd_bus_message_enter_container ( reply , ' r ' , " iqqay " ) ) > 0 ) {
2014-07-30 19:23:27 +02:00
uint16_t c , t ;
2015-08-17 23:54:08 +02:00
int ifindex ;
2014-07-30 19:23:27 +02:00
const void * d ;
size_t l ;
2015-08-17 23:54:08 +02:00
assert_cc ( sizeof ( int ) = = sizeof ( int32_t ) ) ;
r = sd_bus_message_read ( reply , " iqq " , & ifindex , & c , & t ) ;
2014-07-30 19:23:27 +02:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_read_array ( reply , ' y ' , & d , & l ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2016-01-31 06:06:49 +01:00
if ( arg_raw = = RAW_PACKET ) {
uint64_t u64 = htole64 ( l ) ;
2014-07-30 19:23:27 +02:00
2016-01-31 06:06:49 +01:00
fwrite ( & u64 , sizeof ( u64 ) , 1 , stdout ) ;
fwrite ( d , 1 , l , stdout ) ;
2016-01-29 00:24:28 +01:00
} else {
2016-01-31 06:06:49 +01:00
r = output_rr_packet ( d , l , ifindex ) ;
if ( r < 0 )
return r ;
2016-01-29 00:24:28 +01:00
}
2015-08-17 23:54:08 +02:00
2016-02-15 21:25:33 +01:00
if ( dns_type_needs_authentication ( t ) )
needs_authentication = true ;
2014-07-30 19:23:27 +02:00
n + + ;
}
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-08-14 01:00:15 +02:00
r = sd_bus_message_read ( reply , " t " , & flags ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2014-07-30 19:23:27 +02:00
if ( n = = 0 ) {
2016-10-08 13:59:34 +02:00
if ( warn_missing )
log_error ( " %s: no records found " , name ) ;
2014-07-30 19:23:27 +02:00
return - ESRCH ;
}
2015-08-17 23:54:08 +02:00
print_source ( flags , ts ) ;
2014-08-14 01:00:15 +02:00
2016-02-15 21:25:33 +01:00
if ( ( flags & SD_RESOLVED_AUTHENTICATED ) = = 0 & & needs_authentication ) {
fflush ( stdout ) ;
fprintf ( stderr , " \n %s "
" WARNING: The resources shown contain cryptographic key data which could not be \n "
" authenticated. It is not suitable to authenticate any communication. \n "
" This is usually indication that DNSSEC authentication was not enabled \n "
" or is not available for the selected protocol or DNS servers.%s \n " ,
ansi_highlight_red ( ) ,
ansi_normal ( ) ) ;
}
2014-07-30 19:23:27 +02:00
return 0 ;
}
2016-01-03 12:58:26 +01:00
static int resolve_rfc4501 ( sd_bus * bus , const char * name ) {
uint16_t type = 0 , class = 0 ;
const char * p , * q , * n ;
int r ;
assert ( bus ) ;
assert ( name ) ;
assert ( startswith ( name , " dns: " ) ) ;
/* Parse RFC 4501 dns: URIs */
p = name + 4 ;
if ( p [ 0 ] = = ' / ' ) {
const char * e ;
if ( p [ 1 ] ! = ' / ' )
goto invalid ;
e = strchr ( p + 2 , ' / ' ) ;
if ( ! e )
goto invalid ;
if ( e ! = p + 2 )
log_warning ( " DNS authority specification not supported; ignoring specified authority. " ) ;
p = e + 1 ;
}
q = strchr ( p , ' ? ' ) ;
if ( q ) {
n = strndupa ( p , q - p ) ;
q + + ;
for ( ; ; ) {
const char * f ;
f = startswith_no_case ( q , " class= " ) ;
if ( f ) {
_cleanup_free_ char * t = NULL ;
const char * e ;
2018-11-20 23:40:44 +01:00
if ( class ! = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" DNS class specified twice. " ) ;
2016-01-03 12:58:26 +01:00
e = strchrnul ( f , ' ; ' ) ;
t = strndup ( f , e - f ) ;
if ( ! t )
return log_oom ( ) ;
r = dns_class_from_string ( t ) ;
2018-11-20 23:40:44 +01:00
if ( r < 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown DNS class %s. " , t ) ;
2016-01-03 12:58:26 +01:00
class = r ;
if ( * e = = ' ; ' ) {
q = e + 1 ;
continue ;
}
break ;
}
f = startswith_no_case ( q , " type= " ) ;
if ( f ) {
_cleanup_free_ char * t = NULL ;
const char * e ;
2018-11-20 23:40:44 +01:00
if ( type ! = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" DNS type specified twice. " ) ;
2016-01-03 12:58:26 +01:00
e = strchrnul ( f , ' ; ' ) ;
t = strndup ( f , e - f ) ;
if ( ! t )
return log_oom ( ) ;
r = dns_type_from_string ( t ) ;
2018-11-20 23:40:44 +01:00
if ( r < 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown DNS type %s. " , t ) ;
2016-01-03 12:58:26 +01:00
type = r ;
if ( * e = = ' ; ' ) {
q = e + 1 ;
continue ;
}
break ;
}
goto invalid ;
}
} else
n = p ;
if ( class = = 0 )
2016-01-29 00:24:27 +01:00
class = arg_class ? : DNS_CLASS_IN ;
if ( type = = 0 )
type = arg_type ? : DNS_TYPE_A ;
2016-01-03 12:58:26 +01:00
2016-10-08 13:59:34 +02:00
return resolve_record ( bus , n , class , type , true ) ;
2016-01-03 12:58:26 +01:00
invalid :
2018-11-20 23:40:44 +01:00
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Invalid DNS URI: %s " , name ) ;
2016-01-03 12:58:26 +01:00
}
2018-04-11 03:44:51 +02:00
static int verb_query ( int argc , char * * argv , void * userdata ) {
sd_bus * bus = userdata ;
char * * p ;
int q , r = 0 ;
if ( arg_type ! = 0 )
STRV_FOREACH ( p , argv + 1 ) {
q = resolve_record ( bus , * p , arg_class , arg_type , true ) ;
if ( q < 0 )
r = q ;
}
else
STRV_FOREACH ( p , argv + 1 ) {
if ( startswith ( * p , " dns: " ) )
q = resolve_rfc4501 ( bus , * p ) ;
else {
int family , ifindex ;
union in_addr_union a ;
q = in_addr_ifindex_from_string_auto ( * p , & family , & a , & ifindex ) ;
if ( q > = 0 )
q = resolve_address ( bus , family , & a , ifindex ) ;
else
q = resolve_host ( bus , * p ) ;
}
if ( q < 0 )
r = q ;
}
return r ;
}
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
static int resolve_service ( sd_bus * bus , const char * name , const char * type , const char * domain ) {
const char * canonical_name , * canonical_type , * canonical_domain ;
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
size_t indent , sz ;
uint64_t flags ;
const char * p ;
unsigned c ;
usec_t ts ;
int r ;
assert ( bus ) ;
assert ( domain ) ;
2016-05-30 17:59:43 +02:00
name = empty_to_null ( name ) ;
type = empty_to_null ( type ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( name )
2018-06-26 09:41:22 +02:00
log_debug ( " Resolving service \" %s \" of type %s in %s (family %s, interface %s). " , name , type , domain , af_to_name ( arg_family ) ? : " * " , isempty ( arg_ifname ) ? " * " : arg_ifname ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
else if ( type )
2018-06-26 09:41:22 +02:00
log_debug ( " Resolving service type %s of %s (family %s, interface %s). " , type , domain , af_to_name ( arg_family ) ? : " * " , isempty ( arg_ifname ) ? " * " : arg_ifname ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
else
2018-06-26 09:41:22 +02:00
log_debug ( " Resolving service type %s (family %s, interface %s). " , domain , af_to_name ( arg_family ) ? : " * " , isempty ( arg_ifname ) ? " * " : arg_ifname ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , bus_resolve_mgr , " ResolveService " ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
r = sd_bus_message_append ( req , " isssit " , arg_ifindex , name , type , domain , arg_family , arg_flags ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
ts = now ( CLOCK_MONOTONIC ) ;
2018-01-23 01:53:31 +01:00
r = sd_bus_call ( bus , req , SD_RESOLVED_QUERY_TIMEOUT_USEC , & error , & reply ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( r < 0 )
return log_error_errno ( r , " Resolve call failed: %s " , bus_error_message ( & error , r ) ) ;
ts = now ( CLOCK_MONOTONIC ) - ts ;
r = sd_bus_message_enter_container ( reply , ' a ' , " (qqqsa(iiay)s) " ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
indent =
( name ? strlen ( name ) + 1 : 0 ) +
( type ? strlen ( type ) + 1 : 0 ) +
strlen ( domain ) + 2 ;
c = 0 ;
while ( ( r = sd_bus_message_enter_container ( reply , ' r ' , " qqqsa(iiay)s " ) ) > 0 ) {
uint16_t priority , weight , port ;
const char * hostname , * canonical ;
r = sd_bus_message_read ( reply , " qqqs " , & priority , & weight , & port , & hostname ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
if ( name )
printf ( " %*s%s " , ( int ) strlen ( name ) , c = = 0 ? name : " " , c = = 0 ? " / " : " " ) ;
if ( type )
printf ( " %*s%s " , ( int ) strlen ( type ) , c = = 0 ? type : " " , c = = 0 ? " / " : " " ) ;
printf ( " %*s%s %s:%u [priority=%u, weight=%u] \n " ,
( int ) strlen ( domain ) , c = = 0 ? domain : " " ,
c = = 0 ? " : " : " " ,
hostname , port ,
priority , weight ) ;
r = sd_bus_message_enter_container ( reply , ' a ' , " (iiay) " ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
while ( ( r = sd_bus_message_enter_container ( reply , ' r ' , " iiay " ) ) > 0 ) {
_cleanup_free_ char * pretty = NULL ;
2018-12-05 17:42:09 +01:00
int ifindex , family , k ;
2020-07-19 05:43:39 +02:00
union in_addr_union a ; ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
assert_cc ( sizeof ( int ) = = sizeof ( int32_t ) ) ;
2020-07-19 05:43:39 +02:00
r = sd_bus_message_read ( reply , " i " , & ifindex ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2020-07-19 05:43:39 +02:00
sd_bus_error_free ( & error ) ;
r = bus_message_read_in_addr_auto ( reply , & error , & family , & a ) ;
if ( r < 0 & & ! sd_bus_error_has_name ( & error , SD_BUS_ERROR_INVALID_ARGS ) )
return log_error_errno ( r , " %s: systemd-resolved returned invalid result: %s " , name , bus_error_message ( & error , r ) ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2020-07-19 05:43:39 +02:00
if ( sd_bus_error_has_name ( & error , SD_BUS_ERROR_INVALID_ARGS ) ) {
log_debug_errno ( r , " %s: systemd-resolved returned invalid result, ignoring: %s " , name , bus_error_message ( & error , r ) ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
continue ;
}
2020-07-19 05:43:39 +02:00
r = in_addr_ifindex_to_string ( family , & a , ifindex , & pretty ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to print address for %s: %m " , name ) ;
2018-12-05 17:42:09 +01:00
k = printf ( " %*s%s " , ( int ) indent , " " , pretty ) ;
print_ifindex_comment ( k , ifindex ) ;
fputc ( ' \n ' , stdout ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
}
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_read ( reply , " s " , & canonical ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
if ( ! streq ( hostname , canonical ) )
printf ( " %*s(%s) \n " , ( int ) indent , " " , canonical ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
c + + ;
}
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_enter_container ( reply , ' a ' , " ay " ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
while ( ( r = sd_bus_message_read_array ( reply , ' y ' , ( const void * * ) & p , & sz ) ) > 0 ) {
_cleanup_free_ char * escaped = NULL ;
escaped = cescape_length ( p , sz ) ;
if ( ! escaped )
return log_oom ( ) ;
printf ( " %*s%s \n " , ( int ) indent , " " , escaped ) ;
}
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_exit_container ( reply ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
r = sd_bus_message_read ( reply , " ssst " , & canonical_name , & canonical_type , & canonical_domain , & flags ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2016-05-30 17:59:43 +02:00
canonical_name = empty_to_null ( canonical_name ) ;
canonical_type = empty_to_null ( canonical_type ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
if ( ! streq_ptr ( name , canonical_name ) | |
! streq_ptr ( type , canonical_type ) | |
! streq_ptr ( domain , canonical_domain ) ) {
printf ( " %*s( " , ( int ) indent , " " ) ;
if ( canonical_name )
printf ( " %s/ " , canonical_name ) ;
if ( canonical_type )
printf ( " %s/ " , canonical_type ) ;
printf ( " %s) \n " , canonical_domain ) ;
}
print_source ( flags , ts ) ;
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int verb_service ( int argc , char * * argv , void * userdata ) {
sd_bus * bus = userdata ;
if ( argc = = 2 )
return resolve_service ( bus , NULL , NULL , argv [ 1 ] ) ;
else if ( argc = = 3 )
return resolve_service ( bus , NULL , argv [ 1 ] , argv [ 2 ] ) ;
else
return resolve_service ( bus , argv [ 1 ] , argv [ 2 ] , argv [ 3 ] ) ;
}
2016-01-29 00:24:27 +01:00
static int resolve_openpgp ( sd_bus * bus , const char * address ) {
const char * domain , * full ;
int r ;
_cleanup_free_ char * hashed = NULL ;
assert ( bus ) ;
assert ( address ) ;
domain = strrchr ( address , ' @ ' ) ;
2018-11-20 23:40:44 +01:00
if ( ! domain )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Address does not contain '@': \" %s \" " , address ) ;
if ( domain = = address | | domain [ 1 ] = = ' \0 ' )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Address starts or ends with '@': \" %s \" " , address ) ;
2016-01-29 00:24:27 +01:00
domain + + ;
2016-10-08 13:59:34 +02:00
r = string_hashsum_sha256 ( address , domain - 1 - address , & hashed ) ;
2016-01-29 00:24:27 +01:00
if ( r < 0 )
return log_error_errno ( r , " Hashing failed: %m " ) ;
2016-10-08 13:59:34 +02:00
strshorten ( hashed , 56 ) ;
2016-01-29 00:24:27 +01:00
full = strjoina ( hashed , " ._openpgpkey. " , domain ) ;
log_debug ( " Looking up \" %s \" . " , full ) ;
2016-10-08 13:59:34 +02:00
r = resolve_record ( bus , full ,
arg_class ? : DNS_CLASS_IN ,
arg_type ? : DNS_TYPE_OPENPGPKEY , false ) ;
if ( IN_SET ( r , - ENXIO , - ESRCH ) ) { /* NXDOMAIN or NODATA? */
2018-08-16 08:48:06 +02:00
hashed = mfree ( hashed ) ;
2016-10-08 13:59:34 +02:00
r = string_hashsum_sha224 ( address , domain - 1 - address , & hashed ) ;
if ( r < 0 )
return log_error_errno ( r , " Hashing failed: %m " ) ;
full = strjoina ( hashed , " ._openpgpkey. " , domain ) ;
log_debug ( " Looking up \" %s \" . " , full ) ;
return resolve_record ( bus , full ,
arg_class ? : DNS_CLASS_IN ,
arg_type ? : DNS_TYPE_OPENPGPKEY , true ) ;
}
return r ;
2016-01-29 00:24:27 +01:00
}
2018-04-11 03:44:51 +02:00
static int verb_openpgp ( int argc , char * * argv , void * userdata ) {
sd_bus * bus = userdata ;
char * * p ;
int q , r = 0 ;
STRV_FOREACH ( p , argv + 1 ) {
q = resolve_openpgp ( bus , * p ) ;
if ( q < 0 )
r = q ;
}
return r ;
}
2018-05-08 10:52:36 +02:00
static int resolve_tlsa ( sd_bus * bus , const char * family , const char * address ) {
2016-02-18 03:08:57 +01:00
const char * port ;
uint16_t port_num = 443 ;
_cleanup_free_ char * full = NULL ;
int r ;
assert ( bus ) ;
assert ( address ) ;
port = strrchr ( address , ' : ' ) ;
if ( port ) {
2016-12-06 12:21:45 +01:00
r = parse_ip_port ( port + 1 , & port_num ) ;
if ( r < 0 )
2016-02-18 03:08:57 +01:00
return log_error_errno ( r , " Invalid port \" %s \" . " , port + 1 ) ;
address = strndupa ( address , port - address ) ;
}
2018-05-08 10:52:36 +02:00
r = asprintf ( & full , " _%u._%s.%s " ,
2016-02-18 03:08:57 +01:00
port_num ,
2018-05-08 10:52:36 +02:00
family ,
2016-02-18 03:08:57 +01:00
address ) ;
if ( r < 0 )
return log_oom ( ) ;
log_debug ( " Looking up \" %s \" . " , full ) ;
return resolve_record ( bus , full ,
arg_class ? : DNS_CLASS_IN ,
2016-10-08 13:59:34 +02:00
arg_type ? : DNS_TYPE_TLSA , true ) ;
2016-02-18 03:08:57 +01:00
}
2018-05-08 10:52:36 +02:00
static bool service_family_is_valid ( const char * s ) {
return STR_IN_SET ( s , " tcp " , " udp " , " sctp " ) ;
}
2018-04-11 03:44:51 +02:00
static int verb_tlsa ( int argc , char * * argv , void * userdata ) {
sd_bus * bus = userdata ;
char * * p , * * args = argv + 1 ;
2018-05-08 10:52:36 +02:00
const char * family = " tcp " ;
2018-04-11 03:44:51 +02:00
int q , r = 0 ;
2018-05-08 10:52:36 +02:00
if ( service_family_is_valid ( argv [ 1 ] ) ) {
family = argv [ 1 ] ;
2018-04-11 03:44:51 +02:00
args + + ;
2018-05-08 10:52:36 +02:00
}
2018-04-11 03:44:51 +02:00
STRV_FOREACH ( p , args ) {
q = resolve_tlsa ( bus , family , * p ) ;
if ( q < 0 )
r = q ;
}
return r ;
}
static int show_statistics ( int argc , char * * argv , void * userdata ) {
2015-12-23 19:06:36 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * reply = NULL ;
2020-01-14 10:29:53 +01:00
_cleanup_ ( table_unrefp ) Table * table = NULL ;
2018-04-11 03:44:51 +02:00
sd_bus * bus = userdata ;
2015-12-23 19:06:36 +01:00
uint64_t n_current_transactions , n_total_transactions ,
cache_size , n_cache_hit , n_cache_miss ,
n_dnssec_secure , n_dnssec_insecure , n_dnssec_bogus , n_dnssec_indeterminate ;
2016-01-19 17:11:28 +01:00
int r , dnssec_supported ;
2015-12-23 19:06:36 +01:00
assert ( bus ) ;
2020-05-03 08:39:14 +02:00
r = bus_get_property_trivial ( bus , bus_resolve_mgr , " DNSSECSupported " , & error , ' b ' , & dnssec_supported ) ;
2016-01-19 17:11:28 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get DNSSEC supported state: %s " , bus_error_message ( & error , r ) ) ;
printf ( " DNSSEC supported by current servers: %s%s%s \n \n " ,
ansi_highlight ( ) ,
yes_no ( dnssec_supported ) ,
ansi_normal ( ) ) ;
2020-05-03 08:39:14 +02:00
r = bus_get_property ( bus , bus_resolve_mgr , " TransactionStatistics " , & error , & reply , " (tt) " ) ;
2015-12-23 19:06:36 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get transaction statistics: %s " , bus_error_message ( & error , r ) ) ;
r = sd_bus_message_read ( reply , " (tt) " ,
& n_current_transactions ,
& n_total_transactions ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
reply = sd_bus_message_unref ( reply ) ;
2020-05-03 08:39:14 +02:00
r = bus_get_property ( bus , bus_resolve_mgr , " CacheStatistics " , & error , & reply , " (ttt) " ) ;
2015-12-27 23:57:58 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get cache statistics: %s " , bus_error_message ( & error , r ) ) ;
2015-12-23 19:06:36 +01:00
r = sd_bus_message_read ( reply , " (ttt) " ,
& cache_size ,
& n_cache_hit ,
& n_cache_miss ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
reply = sd_bus_message_unref ( reply ) ;
2020-05-03 08:39:14 +02:00
r = bus_get_property ( bus , bus_resolve_mgr , " DNSSECStatistics " , & error , & reply , " (tttt) " ) ;
2015-12-27 23:57:58 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get DNSSEC statistics: %s " , bus_error_message ( & error , r ) ) ;
2015-12-23 19:06:36 +01:00
r = sd_bus_message_read ( reply , " (tttt) " ,
& n_dnssec_secure ,
& n_dnssec_insecure ,
& n_dnssec_bogus ,
& n_dnssec_indeterminate ) ;
if ( r < 0 )
return bus_log_parse_error ( r ) ;
2020-01-14 10:29:53 +01:00
table = table_new ( " key " , " value " ) ;
if ( ! table )
return log_oom ( ) ;
table_set_header ( table , false ) ;
r = table_add_many ( table ,
TABLE_STRING , " Transactions " ,
TABLE_SET_COLOR , ansi_highlight ( ) ,
TABLE_EMPTY ,
TABLE_STRING , " Current Transactions: " ,
TABLE_SET_ALIGN_PERCENT , 100 ,
TABLE_UINT64 , n_current_transactions ,
TABLE_STRING , " Total Transactions: " ,
TABLE_UINT64 , n_total_transactions ,
TABLE_EMPTY , TABLE_EMPTY ,
TABLE_STRING , " Cache " ,
TABLE_SET_COLOR , ansi_highlight ( ) ,
TABLE_SET_ALIGN_PERCENT , 0 ,
TABLE_EMPTY ,
TABLE_STRING , " Current Cache Size: " ,
TABLE_SET_ALIGN_PERCENT , 100 ,
TABLE_UINT64 , cache_size ,
TABLE_STRING , " Cache Hits: " ,
TABLE_UINT64 , n_cache_hit ,
TABLE_STRING , " Cache Misses: " ,
TABLE_UINT64 , n_cache_miss ,
TABLE_EMPTY , TABLE_EMPTY ,
TABLE_STRING , " DNSSEC Verdicts " ,
TABLE_SET_COLOR , ansi_highlight ( ) ,
TABLE_SET_ALIGN_PERCENT , 0 ,
TABLE_EMPTY ,
TABLE_STRING , " Secure: " ,
TABLE_SET_ALIGN_PERCENT , 100 ,
TABLE_UINT64 , n_dnssec_secure ,
TABLE_STRING , " Insecure: " ,
TABLE_UINT64 , n_dnssec_insecure ,
TABLE_STRING , " Bogus: " ,
TABLE_UINT64 , n_dnssec_bogus ,
TABLE_STRING , " Indeterminate: " ,
TABLE_UINT64 , n_dnssec_indeterminate ) ;
if ( r < 0 )
table_log_add_error ( r ) ;
r = table_print ( table , NULL ) ;
if ( r < 0 )
2020-07-08 09:16:52 +02:00
return table_log_print_error ( r ) ;
2015-12-23 19:06:36 +01:00
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int reset_statistics ( int argc , char * * argv , void * userdata ) {
2015-12-23 19:06:36 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-04-11 03:44:51 +02:00
sd_bus * bus = userdata ;
2015-12-23 19:06:36 +01:00
int r ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " ResetStatistics " , & error , NULL , NULL ) ;
2015-12-23 19:06:36 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to reset statistics: %s " , bus_error_message ( & error , r ) ) ;
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int flush_caches ( int argc , char * * argv , void * userdata ) {
2016-06-10 20:40:30 +02:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-04-11 03:44:51 +02:00
sd_bus * bus = userdata ;
2016-06-10 20:40:30 +02:00
int r ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " FlushCaches " , & error , NULL , NULL ) ;
2016-06-10 20:40:30 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to flush caches: %s " , bus_error_message ( & error , r ) ) ;
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int reset_server_features ( int argc , char * * argv , void * userdata ) {
2017-09-29 21:19:54 +02:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-04-11 03:44:51 +02:00
sd_bus * bus = userdata ;
2017-09-29 21:19:54 +02:00
int r ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " ResetServerFeatures " , & error , NULL , NULL ) ;
2017-09-29 21:19:54 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to reset server features: %s " , bus_error_message ( & error , r ) ) ;
return 0 ;
}
2020-07-03 14:24:25 +02:00
static int read_dns_server_one ( sd_bus_message * m , bool with_ifindex , bool extended , char * * ret ) {
2020-07-19 05:43:39 +02:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-05-03 10:06:06 +02:00
_cleanup_free_ char * pretty = NULL ;
2020-07-19 05:43:39 +02:00
int ifindex , family , r , k ;
union in_addr_union a ;
2020-07-03 14:24:25 +02:00
const char * name = NULL ;
uint16_t port = 0 ;
2018-05-03 10:06:06 +02:00
assert ( m ) ;
assert ( ret ) ;
2020-07-03 14:24:25 +02:00
r = sd_bus_message_enter_container ( m , ' r ' , with_ifindex ? ( extended ? " iiayqs " : " iiay " ) : ( extended ? " iayqs " : " iay " ) ) ;
2018-05-03 10:06:06 +02:00
if ( r < = 0 )
return r ;
if ( with_ifindex ) {
r = sd_bus_message_read ( m , " i " , & ifindex ) ;
if ( r < 0 )
return r ;
}
2020-07-19 05:43:39 +02:00
k = bus_message_read_in_addr_auto ( m , & error , & family , & a ) ;
if ( k < 0 & & ! sd_bus_error_has_name ( & error , SD_BUS_ERROR_INVALID_ARGS ) )
return k ;
2018-05-03 10:06:06 +02:00
2020-07-03 14:24:25 +02:00
if ( extended ) {
r = sd_bus_message_read ( m , " q " , & port ) ;
if ( r < 0 )
return r ;
r = sd_bus_message_read ( m , " s " , & name ) ;
if ( r < 0 )
return r ;
}
2018-05-03 10:06:06 +02:00
r = sd_bus_message_exit_container ( m ) ;
if ( r < 0 )
return r ;
2020-07-19 05:43:39 +02:00
if ( k < 0 ) {
log_debug ( " Invalid DNS server, ignoring: %s " , bus_error_message ( & error , k ) ) ;
2018-05-03 10:06:06 +02:00
* ret = NULL ;
return 1 ;
}
2020-07-19 05:43:39 +02:00
if ( with_ifindex & & ifindex ! = 0 ) {
/* only show the global ones here */
2018-05-03 10:06:06 +02:00
* ret = NULL ;
return 1 ;
}
2020-07-19 05:43:39 +02:00
r = in_addr_port_ifindex_name_to_string ( family , & a , port , ifindex , name , & pretty ) ;
2018-05-03 10:06:06 +02:00
if ( r < 0 )
return r ;
* ret = TAKE_PTR ( pretty ) ;
return 1 ;
}
2020-07-03 14:24:25 +02:00
static int map_link_dns_servers_internal ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata , bool extended ) {
2016-06-15 21:43:36 +02:00
char * * * l = userdata ;
int r ;
assert ( bus ) ;
assert ( member ) ;
assert ( m ) ;
assert ( l ) ;
2020-07-03 14:24:25 +02:00
r = sd_bus_message_enter_container ( m , ' a ' , extended ? " (iayqs) " : " (iay) " ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
for ( ; ; ) {
2019-06-24 07:57:58 +02:00
_cleanup_free_ char * pretty = NULL ;
2016-06-15 21:43:36 +02:00
2020-07-03 14:24:25 +02:00
r = read_dns_server_one ( m , false , extended , & pretty ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
if ( r = = 0 )
break ;
2018-05-03 10:06:06 +02:00
if ( isempty ( pretty ) )
2016-06-15 21:43:36 +02:00
continue ;
2019-06-24 07:57:58 +02:00
r = strv_consume ( l , TAKE_PTR ( pretty ) ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
}
r = sd_bus_message_exit_container ( m ) ;
if ( r < 0 )
return r ;
return 0 ;
}
2020-07-03 14:24:25 +02:00
static int map_link_dns_servers ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
return map_link_dns_servers_internal ( bus , member , m , error , userdata , false ) ;
}
static int map_link_dns_servers_ex ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
return map_link_dns_servers_internal ( bus , member , m , error , userdata , true ) ;
}
2018-05-01 15:17:22 +02:00
static int map_link_current_dns_server ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
assert ( m ) ;
assert ( userdata ) ;
2020-07-03 14:24:25 +02:00
return read_dns_server_one ( m , false , false , userdata ) ;
}
static int map_link_current_dns_server_ex ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
assert ( m ) ;
assert ( userdata ) ;
return read_dns_server_one ( m , false , true , userdata ) ;
2018-05-01 15:17:22 +02:00
}
2018-05-03 10:10:02 +02:00
static int read_domain_one ( sd_bus_message * m , bool with_ifindex , char * * ret ) {
_cleanup_free_ char * str = NULL ;
int ifindex , route_only , r ;
const char * domain ;
assert ( m ) ;
assert ( ret ) ;
if ( with_ifindex )
r = sd_bus_message_read ( m , " (isb) " , & ifindex , & domain , & route_only ) ;
else
r = sd_bus_message_read ( m , " (sb) " , & domain , & route_only ) ;
if ( r < = 0 )
return r ;
if ( with_ifindex & & ifindex ! = 0 ) {
/* only show the global ones here */
* ret = NULL ;
return 1 ;
}
if ( route_only )
2019-07-11 19:14:16 +02:00
str = strjoin ( " ~ " , domain ) ;
2018-05-03 10:10:02 +02:00
else
str = strdup ( domain ) ;
if ( ! str )
return - ENOMEM ;
* ret = TAKE_PTR ( str ) ;
return 1 ;
}
2016-06-15 21:43:36 +02:00
static int map_link_domains ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
char * * * l = userdata ;
int r ;
assert ( bus ) ;
assert ( member ) ;
assert ( m ) ;
assert ( l ) ;
r = sd_bus_message_enter_container ( m , ' a ' , " (sb) " ) ;
if ( r < 0 )
return r ;
for ( ; ; ) {
2019-06-24 07:57:58 +02:00
_cleanup_free_ char * pretty = NULL ;
2016-06-15 21:43:36 +02:00
2018-05-03 10:10:02 +02:00
r = read_domain_one ( m , false , & pretty ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
if ( r = = 0 )
break ;
2018-05-03 10:10:02 +02:00
if ( isempty ( pretty ) )
continue ;
2016-06-15 21:43:36 +02:00
2019-06-24 07:57:58 +02:00
r = strv_consume ( l , TAKE_PTR ( pretty ) ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
}
r = sd_bus_message_exit_container ( m ) ;
if ( r < 0 )
return r ;
2020-10-11 12:19:46 +02:00
strv_sort ( * l ) ;
2016-06-15 21:43:36 +02:00
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int status_print_strv_ifindex ( int ifindex , const char * ifname , char * * p ) {
2020-10-11 11:54:18 +02:00
const unsigned indent = strlen ( " Global: " ) ; /* Use the same indentation everywhere to make things nice */
int pos1 , pos2 ;
if ( ifname )
printf ( " %s%nLink %i (%s)%n%s: " , ansi_highlight ( ) , & pos1 , ifindex , ifname , & pos2 , ansi_normal ( ) ) ;
else
printf ( " %s%nGlobal%n%s: " , ansi_highlight ( ) , & pos1 , & pos2 , ansi_normal ( ) ) ;
size_t cols = columns ( ) , position = pos2 - pos1 + 2 ;
2018-04-11 03:44:51 +02:00
char * * i ;
2020-10-11 11:54:18 +02:00
STRV_FOREACH ( i , p ) {
size_t our_len = utf8_console_width ( * i ) ; /* This returns -1 on invalid utf-8 (which shouldn't happen).
* If that happens , we ' ll just print one item per line . */
2018-04-11 03:44:51 +02:00
2020-10-12 13:29:46 +02:00
if ( position < = indent | | size_add ( size_add ( position , 1 ) , our_len ) < cols ) {
2020-10-11 11:54:18 +02:00
printf ( " %s " , * i ) ;
2020-10-12 13:29:46 +02:00
position = size_add ( size_add ( position , 1 ) , our_len ) ;
2020-10-11 11:54:18 +02:00
} else {
printf ( " \n %*s%s " , indent , " " , * i ) ;
2020-10-12 13:29:46 +02:00
position = size_add ( our_len , indent ) ;
2020-10-11 11:54:18 +02:00
}
}
2018-04-11 03:44:51 +02:00
printf ( " \n " ) ;
return 0 ;
}
2020-10-11 11:54:18 +02:00
static int status_print_strv_global ( char * * p ) {
return status_print_strv_ifindex ( 0 , NULL , p ) ;
}
2020-10-11 13:46:53 +02:00
typedef struct LinkInfo {
2018-08-07 03:13:44 +02:00
uint64_t scopes_mask ;
const char * llmnr ;
const char * mdns ;
const char * dns_over_tls ;
const char * dnssec ;
char * current_dns ;
2020-07-03 14:24:25 +02:00
char * current_dns_ex ;
2018-08-07 03:13:44 +02:00
char * * dns ;
2020-07-03 14:24:25 +02:00
char * * dns_ex ;
2018-08-07 03:13:44 +02:00
char * * domains ;
char * * ntas ;
bool dnssec_supported ;
2018-12-04 13:29:41 +01:00
bool default_route ;
2020-10-11 13:46:53 +02:00
} LinkInfo ;
2018-08-07 03:13:44 +02:00
2020-10-11 13:46:53 +02:00
typedef struct GlobalInfo {
char * current_dns ;
char * current_dns_ex ;
char * * dns ;
char * * dns_ex ;
char * * fallback_dns ;
char * * fallback_dns_ex ;
char * * domains ;
char * * ntas ;
const char * llmnr ;
const char * mdns ;
const char * dns_over_tls ;
const char * dnssec ;
const char * resolv_conf_mode ;
bool dnssec_supported ;
} GlobalInfo ;
static void link_info_clear ( LinkInfo * p ) {
free ( p - > current_dns ) ;
free ( p - > current_dns_ex ) ;
strv_free ( p - > dns ) ;
strv_free ( p - > dns_ex ) ;
strv_free ( p - > domains ) ;
strv_free ( p - > ntas ) ;
}
static void global_info_clear ( GlobalInfo * p ) {
2018-08-07 03:13:44 +02:00
free ( p - > current_dns ) ;
2020-07-03 14:24:25 +02:00
free ( p - > current_dns_ex ) ;
2018-08-07 03:13:44 +02:00
strv_free ( p - > dns ) ;
2020-07-03 14:24:25 +02:00
strv_free ( p - > dns_ex ) ;
2020-10-11 13:46:53 +02:00
strv_free ( p - > fallback_dns ) ;
strv_free ( p - > fallback_dns_ex ) ;
2018-08-07 03:13:44 +02:00
strv_free ( p - > domains ) ;
strv_free ( p - > ntas ) ;
}
2016-06-15 21:43:36 +02:00
2020-01-14 10:29:53 +01:00
static int dump_list ( Table * table , const char * prefix , char * const * l ) {
int r ;
if ( strv_isempty ( l ) )
return 0 ;
r = table_add_many ( table ,
TABLE_STRING , prefix ,
2020-10-12 15:54:57 +02:00
TABLE_STRV_WRAPPED , l ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return table_log_add_error ( r ) ;
return 0 ;
}
2020-10-11 16:20:27 +02:00
static int strv_extend_extended_bool ( char * * * strv , const char * name , const char * value ) {
int r ;
if ( value ) {
r = parse_boolean ( value ) ;
if ( r > = 0 )
return strv_extendf ( strv , " %s%s " , plus_minus ( r ) , name ) ;
}
return strv_extendf ( strv , " %s=%s " , name , value ? : " ??? " ) ;
}
2020-10-20 10:50:01 +02:00
static char * * link_protocol_status ( const LinkInfo * info ) {
2020-10-11 16:20:27 +02:00
_cleanup_strv_free_ char * * s = NULL ;
if ( strv_extendf ( & s , " %sDefaultRoute " , plus_minus ( info - > default_route ) ) < 0 )
return NULL ;
if ( strv_extend_extended_bool ( & s , " LLMNR " , info - > llmnr ) < 0 )
return NULL ;
if ( strv_extend_extended_bool ( & s , " mDNS " , info - > mdns ) < 0 )
return NULL ;
if ( strv_extend_extended_bool ( & s , " DNSOverTLS " , info - > dns_over_tls ) < 0 )
return NULL ;
if ( strv_extendf ( & s , " DNSSEC=%s/%s " ,
info - > dnssec ? : " ??? " ,
info - > dnssec_supported ? " supported " : " unsupported " ) < 0 )
return NULL ;
2020-10-20 10:50:01 +02:00
return TAKE_PTR ( s ) ;
2020-10-11 16:20:27 +02:00
}
2020-10-20 10:50:01 +02:00
static char * * global_protocol_status ( const GlobalInfo * info ) {
2020-10-11 16:20:27 +02:00
_cleanup_strv_free_ char * * s = NULL ;
if ( strv_extend_extended_bool ( & s , " LLMNR " , info - > llmnr ) < 0 )
return NULL ;
if ( strv_extend_extended_bool ( & s , " mDNS " , info - > mdns ) < 0 )
return NULL ;
if ( strv_extend_extended_bool ( & s , " DNSOverTLS " , info - > dns_over_tls ) < 0 )
return NULL ;
if ( strv_extendf ( & s , " DNSSEC=%s/%s " ,
info - > dnssec ? : " ??? " ,
info - > dnssec_supported ? " supported " : " unsupported " ) < 0 )
return NULL ;
2020-10-20 10:50:01 +02:00
return TAKE_PTR ( s ) ;
2020-10-11 16:20:27 +02:00
}
2018-08-07 03:13:44 +02:00
static int status_ifindex ( sd_bus * bus , int ifindex , const char * name , StatusMode mode , bool * empty_line ) {
2016-06-15 21:43:36 +02:00
static const struct bus_properties_map property_map [ ] = {
2020-10-11 13:46:53 +02:00
{ " ScopesMask " , " t " , NULL , offsetof ( LinkInfo , scopes_mask ) } ,
{ " DNS " , " a(iay) " , map_link_dns_servers , offsetof ( LinkInfo , dns ) } ,
{ " DNSEx " , " a(iayqs) " , map_link_dns_servers_ex , offsetof ( LinkInfo , dns_ex ) } ,
{ " CurrentDNSServer " , " (iay) " , map_link_current_dns_server , offsetof ( LinkInfo , current_dns ) } ,
{ " CurrentDNSServerEx " , " (iayqs) " , map_link_current_dns_server_ex , offsetof ( LinkInfo , current_dns_ex ) } ,
{ " Domains " , " a(sb) " , map_link_domains , offsetof ( LinkInfo , domains ) } ,
{ " DefaultRoute " , " b " , NULL , offsetof ( LinkInfo , default_route ) } ,
{ " LLMNR " , " s " , NULL , offsetof ( LinkInfo , llmnr ) } ,
{ " MulticastDNS " , " s " , NULL , offsetof ( LinkInfo , mdns ) } ,
{ " DNSOverTLS " , " s " , NULL , offsetof ( LinkInfo , dns_over_tls ) } ,
{ " DNSSEC " , " s " , NULL , offsetof ( LinkInfo , dnssec ) } ,
2020-10-11 12:19:46 +02:00
{ " DNSSECNegativeTrustAnchors " , " as " , bus_map_strv_sort , offsetof ( LinkInfo , ntas ) } ,
2020-10-11 13:46:53 +02:00
{ " DNSSECSupported " , " b " , NULL , offsetof ( LinkInfo , dnssec_supported ) } ,
2016-06-15 21:43:36 +02:00
{ }
} ;
2017-02-08 17:59:58 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-03-19 15:46:29 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * m = NULL ;
2020-10-11 13:46:53 +02:00
_cleanup_ ( link_info_clear ) LinkInfo link_info = { } ;
2020-01-14 10:29:53 +01:00
_cleanup_ ( table_unrefp ) Table * table = NULL ;
2020-01-11 11:37:26 +01:00
_cleanup_free_ char * p = NULL ;
char ifi [ DECIMAL_STR_MAX ( int ) ] , ifname [ IF_NAMESIZE + 1 ] = " " ;
2016-06-15 21:43:36 +02:00
int r ;
assert ( bus ) ;
assert ( ifindex > 0 ) ;
if ( ! name ) {
2019-05-29 07:18:41 +02:00
if ( ! format_ifname ( ifindex , ifname ) )
2016-06-15 21:43:36 +02:00
return log_error_errno ( errno , " Failed to resolve interface name for %i: %m " , ifindex ) ;
name = ifname ;
}
2020-01-11 11:37:26 +01:00
xsprintf ( ifi , " %i " , ifindex ) ;
2016-06-15 21:43:36 +02:00
r = sd_bus_path_encode ( " /org/freedesktop/resolve1/link " , ifi , & p ) ;
if ( r < 0 )
return log_oom ( ) ;
r = bus_map_all_properties ( bus ,
" org.freedesktop.resolve1 " ,
p ,
property_map ,
2018-03-28 13:37:27 +02:00
BUS_MAP_BOOLEAN_AS_BOOL ,
2017-02-08 17:59:58 +01:00
& error ,
2018-03-19 15:46:29 +01:00
& m ,
2016-06-15 21:43:36 +02:00
& link_info ) ;
2018-08-07 03:13:44 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get link data for %i: %s " , ifindex , bus_error_message ( & error , r ) ) ;
2016-06-15 21:43:36 +02:00
2018-11-11 12:56:29 +01:00
( void ) pager_open ( arg_pager_flags ) ;
2016-06-15 21:43:36 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_DNS )
2020-07-03 14:24:25 +02:00
return status_print_strv_ifindex ( ifindex , name , link_info . dns_ex ? : link_info . dns ) ;
2018-04-11 03:44:51 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_DOMAIN )
return status_print_strv_ifindex ( ifindex , name , link_info . domains ) ;
2018-04-11 03:44:51 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_NTA )
return status_print_strv_ifindex ( ifindex , name , link_info . ntas ) ;
2018-04-11 03:44:51 +02:00
2018-12-04 13:29:41 +01:00
if ( mode = = STATUS_DEFAULT_ROUTE ) {
printf ( " %sLink %i (%s)%s: %s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ,
yes_no ( link_info . default_route ) ) ;
return 0 ;
}
2018-04-11 03:44:51 +02:00
if ( mode = = STATUS_LLMNR ) {
printf ( " %sLink %i (%s)%s: %s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ,
strna ( link_info . llmnr ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
if ( mode = = STATUS_MDNS ) {
printf ( " %sLink %i (%s)%s: %s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ,
strna ( link_info . mdns ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
2018-05-04 17:31:16 +02:00
if ( mode = = STATUS_PRIVATE ) {
printf ( " %sLink %i (%s)%s: %s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ,
2018-06-13 20:26:24 +02:00
strna ( link_info . dns_over_tls ) ) ;
2018-05-04 17:31:16 +02:00
2018-08-07 03:13:44 +02:00
return 0 ;
2018-05-04 17:31:16 +02:00
}
2018-04-11 03:44:51 +02:00
if ( mode = = STATUS_DNSSEC ) {
printf ( " %sLink %i (%s)%s: %s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ,
strna ( link_info . dnssec ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
if ( empty_line & & * empty_line )
2016-06-15 21:43:36 +02:00
fputc ( ' \n ' , stdout ) ;
printf ( " %sLink %i (%s)%s \n " ,
ansi_highlight ( ) , ifindex , name , ansi_normal ( ) ) ;
2020-01-14 10:29:53 +01:00
table = table_new ( " key " , " value " ) ;
if ( ! table )
return log_oom ( ) ;
table_set_header ( table , false ) ;
r = table_add_many ( table ,
TABLE_STRING , " Current Scopes: " ,
TABLE_SET_ALIGN_PERCENT , 100 ) ;
if ( r < 0 )
return table_log_add_error ( r ) ;
2016-06-15 21:43:36 +02:00
if ( link_info . scopes_mask = = 0 )
2020-01-14 10:29:53 +01:00
r = table_add_cell ( table , NULL , TABLE_STRING , " none " ) ;
else {
_cleanup_free_ char * buf = NULL ;
size_t len ;
if ( asprintf ( & buf , " %s%s%s%s%s " ,
link_info . scopes_mask & SD_RESOLVED_DNS ? " DNS " : " " ,
link_info . scopes_mask & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4 " : " " ,
link_info . scopes_mask & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6 " : " " ,
link_info . scopes_mask & SD_RESOLVED_MDNS_IPV4 ? " mDNS/IPv4 " : " " ,
link_info . scopes_mask & SD_RESOLVED_MDNS_IPV6 ? " mDNS/IPv6 " : " " ) < 0 )
return log_oom ( ) ;
2016-06-15 21:43:36 +02:00
2020-01-14 10:29:53 +01:00
len = strlen ( buf ) ;
assert ( len > 0 ) ;
buf [ len - 1 ] = ' \0 ' ;
2016-06-15 21:43:36 +02:00
2020-01-14 10:29:53 +01:00
r = table_add_cell ( table , NULL , TABLE_STRING , buf ) ;
}
if ( r < 0 )
return table_log_add_error ( r ) ;
2020-10-20 10:50:01 +02:00
_cleanup_strv_free_ char * * pstatus = link_protocol_status ( & link_info ) ;
2020-10-11 16:20:27 +02:00
if ( ! pstatus )
return log_oom ( ) ;
2020-01-14 10:29:53 +01:00
r = table_add_many ( table ,
2020-10-20 10:50:01 +02:00
TABLE_STRING , " Protocols: " ,
TABLE_STRV_WRAPPED , pstatus ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return table_log_add_error ( r ) ;
if ( link_info . current_dns ) {
r = table_add_many ( table ,
TABLE_STRING , " Current DNS Server: " ,
2020-07-03 14:24:25 +02:00
TABLE_STRING , link_info . current_dns_ex ? : link_info . current_dns ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return table_log_add_error ( r ) ;
2016-06-15 21:43:36 +02:00
}
2020-07-03 14:24:25 +02:00
r = dump_list ( table , " DNS Servers: " , link_info . dns_ex ? : link_info . dns ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return r ;
r = dump_list ( table , " DNS Domain: " , link_info . domains ) ;
if ( r < 0 )
return r ;
r = table_print ( table , NULL ) ;
if ( r < 0 )
2020-07-08 09:16:52 +02:00
return table_log_print_error ( r ) ;
2020-01-14 10:29:53 +01:00
2018-04-11 03:44:51 +02:00
if ( empty_line )
* empty_line = true ;
2016-06-15 21:43:36 +02:00
2018-08-07 03:13:44 +02:00
return 0 ;
2016-06-15 21:43:36 +02:00
}
2020-07-03 14:24:25 +02:00
static int map_global_dns_servers_internal ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata , bool extended ) {
2016-06-15 21:43:36 +02:00
char * * * l = userdata ;
int r ;
assert ( bus ) ;
assert ( member ) ;
assert ( m ) ;
assert ( l ) ;
2020-07-03 14:24:25 +02:00
r = sd_bus_message_enter_container ( m , ' a ' , extended ? " (iiayqs) " : " (iiay) " ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
for ( ; ; ) {
2019-06-24 07:57:58 +02:00
_cleanup_free_ char * pretty = NULL ;
2016-06-15 21:43:36 +02:00
2020-07-03 14:24:25 +02:00
r = read_dns_server_one ( m , true , extended , & pretty ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
if ( r = = 0 )
break ;
2018-05-03 10:06:06 +02:00
if ( isempty ( pretty ) )
2016-06-15 21:43:36 +02:00
continue ;
2019-06-24 07:57:58 +02:00
r = strv_consume ( l , TAKE_PTR ( pretty ) ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
}
r = sd_bus_message_exit_container ( m ) ;
if ( r < 0 )
return r ;
return 0 ;
}
2020-07-03 14:24:25 +02:00
static int map_global_dns_servers ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
return map_global_dns_servers_internal ( bus , member , m , error , userdata , false ) ;
}
static int map_global_dns_servers_ex ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
return map_global_dns_servers_internal ( bus , member , m , error , userdata , true ) ;
}
2018-05-01 15:17:22 +02:00
static int map_global_current_dns_server ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
assert ( m ) ;
assert ( userdata ) ;
2020-07-03 14:24:25 +02:00
return read_dns_server_one ( m , true , false , userdata ) ;
}
static int map_global_current_dns_server_ex ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
assert ( m ) ;
assert ( userdata ) ;
return read_dns_server_one ( m , true , true , userdata ) ;
2018-05-01 15:17:22 +02:00
}
2016-06-15 21:43:36 +02:00
static int map_global_domains ( sd_bus * bus , const char * member , sd_bus_message * m , sd_bus_error * error , void * userdata ) {
char * * * l = userdata ;
int r ;
assert ( bus ) ;
assert ( member ) ;
assert ( m ) ;
assert ( l ) ;
r = sd_bus_message_enter_container ( m , ' a ' , " (isb) " ) ;
if ( r < 0 )
return r ;
for ( ; ; ) {
2019-06-24 07:57:58 +02:00
_cleanup_free_ char * pretty = NULL ;
2016-06-15 21:43:36 +02:00
2018-05-03 10:10:02 +02:00
r = read_domain_one ( m , true , & pretty ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
if ( r = = 0 )
break ;
2018-05-03 10:10:02 +02:00
if ( isempty ( pretty ) )
2016-06-15 21:43:36 +02:00
continue ;
2019-06-24 07:57:58 +02:00
r = strv_consume ( l , TAKE_PTR ( pretty ) ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
}
r = sd_bus_message_exit_container ( m ) ;
if ( r < 0 )
return r ;
2020-10-11 12:19:46 +02:00
strv_sort ( * l ) ;
2018-04-11 03:44:51 +02:00
return 0 ;
}
2018-08-07 03:13:44 +02:00
static int status_global ( sd_bus * bus , StatusMode mode , bool * empty_line ) {
2016-06-15 21:43:36 +02:00
static const struct bus_properties_map property_map [ ] = {
2020-10-11 13:46:53 +02:00
{ " DNS " , " a(iiay) " , map_global_dns_servers , offsetof ( GlobalInfo , dns ) } ,
{ " DNSEx " , " a(iiayqs) " , map_global_dns_servers_ex , offsetof ( GlobalInfo , dns_ex ) } ,
{ " FallbackDNS " , " a(iiay) " , map_global_dns_servers , offsetof ( GlobalInfo , fallback_dns ) } ,
{ " FallbackDNSEx " , " a(iiayqs) " , map_global_dns_servers_ex , offsetof ( GlobalInfo , fallback_dns_ex ) } ,
{ " CurrentDNSServer " , " (iiay) " , map_global_current_dns_server , offsetof ( GlobalInfo , current_dns ) } ,
{ " CurrentDNSServerEx " , " (iiayqs) " , map_global_current_dns_server_ex , offsetof ( GlobalInfo , current_dns_ex ) } ,
{ " Domains " , " a(isb) " , map_global_domains , offsetof ( GlobalInfo , domains ) } ,
2020-10-11 12:19:46 +02:00
{ " DNSSECNegativeTrustAnchors " , " as " , bus_map_strv_sort , offsetof ( GlobalInfo , ntas ) } ,
2020-10-11 13:46:53 +02:00
{ " LLMNR " , " s " , NULL , offsetof ( GlobalInfo , llmnr ) } ,
{ " MulticastDNS " , " s " , NULL , offsetof ( GlobalInfo , mdns ) } ,
{ " DNSOverTLS " , " s " , NULL , offsetof ( GlobalInfo , dns_over_tls ) } ,
{ " DNSSEC " , " s " , NULL , offsetof ( GlobalInfo , dnssec ) } ,
{ " DNSSECSupported " , " b " , NULL , offsetof ( GlobalInfo , dnssec_supported ) } ,
{ " ResolvConfMode " , " s " , NULL , offsetof ( GlobalInfo , resolv_conf_mode ) } ,
2016-06-15 21:43:36 +02:00
{ }
} ;
2017-02-08 17:59:58 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-03-19 15:46:29 +01:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * m = NULL ;
2020-10-11 13:46:53 +02:00
_cleanup_ ( global_info_clear ) GlobalInfo global_info = { } ;
2020-01-14 10:29:53 +01:00
_cleanup_ ( table_unrefp ) Table * table = NULL ;
2016-06-15 21:43:36 +02:00
int r ;
assert ( bus ) ;
assert ( empty_line ) ;
r = bus_map_all_properties ( bus ,
" org.freedesktop.resolve1 " ,
" /org/freedesktop/resolve1 " ,
property_map ,
2018-03-28 13:37:27 +02:00
BUS_MAP_BOOLEAN_AS_BOOL ,
2017-02-08 17:59:58 +01:00
& error ,
2018-03-19 15:46:29 +01:00
& m ,
2016-06-15 21:43:36 +02:00
& global_info ) ;
2018-08-07 03:13:44 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get global data: %s " , bus_error_message ( & error , r ) ) ;
2016-06-15 21:43:36 +02:00
2018-11-11 12:56:29 +01:00
( void ) pager_open ( arg_pager_flags ) ;
2016-06-15 21:43:36 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_DNS )
2020-07-03 14:24:25 +02:00
return status_print_strv_global ( global_info . dns_ex ? : global_info . dns ) ;
2018-04-11 03:44:51 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_DOMAIN )
return status_print_strv_global ( global_info . domains ) ;
2018-04-11 03:44:51 +02:00
2018-08-07 03:13:44 +02:00
if ( mode = = STATUS_NTA )
return status_print_strv_global ( global_info . ntas ) ;
2018-04-11 03:44:51 +02:00
if ( mode = = STATUS_LLMNR ) {
printf ( " %sGlobal%s: %s \n " , ansi_highlight ( ) , ansi_normal ( ) ,
strna ( global_info . llmnr ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
if ( mode = = STATUS_MDNS ) {
printf ( " %sGlobal%s: %s \n " , ansi_highlight ( ) , ansi_normal ( ) ,
strna ( global_info . mdns ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
2018-05-04 17:31:16 +02:00
if ( mode = = STATUS_PRIVATE ) {
printf ( " %sGlobal%s: %s \n " , ansi_highlight ( ) , ansi_normal ( ) ,
2018-06-13 20:26:24 +02:00
strna ( global_info . dns_over_tls ) ) ;
2018-05-04 17:31:16 +02:00
2018-08-07 03:13:44 +02:00
return 0 ;
2018-05-04 17:31:16 +02:00
}
2018-04-11 03:44:51 +02:00
if ( mode = = STATUS_DNSSEC ) {
printf ( " %sGlobal%s: %s \n " , ansi_highlight ( ) , ansi_normal ( ) ,
strna ( global_info . dnssec ) ) ;
2018-08-07 03:13:44 +02:00
return 0 ;
2018-04-11 03:44:51 +02:00
}
2016-06-15 21:43:36 +02:00
printf ( " %sGlobal%s \n " , ansi_highlight ( ) , ansi_normal ( ) ) ;
2018-03-19 16:40:05 +01:00
2020-01-14 10:29:53 +01:00
table = table_new ( " key " , " value " ) ;
if ( ! table )
return log_oom ( ) ;
2016-06-15 21:43:36 +02:00
2020-01-14 10:29:53 +01:00
table_set_header ( table , false ) ;
2020-10-20 10:50:01 +02:00
_cleanup_strv_free_ char * * pstatus = global_protocol_status ( & global_info ) ;
2020-10-11 16:20:27 +02:00
if ( ! pstatus )
return log_oom ( ) ;
2020-01-14 10:29:53 +01:00
r = table_add_many ( table ,
2020-10-20 10:50:01 +02:00
TABLE_STRING , " Protocols: " ,
2020-01-14 10:29:53 +01:00
TABLE_SET_ALIGN_PERCENT , 100 ,
2020-10-20 10:50:01 +02:00
TABLE_STRV_WRAPPED , pstatus ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return table_log_add_error ( r ) ;
2020-09-29 17:28:31 +02:00
if ( global_info . resolv_conf_mode ) {
r = table_add_many ( table ,
TABLE_STRING , " resolv.conf mode: " ,
TABLE_STRING , global_info . resolv_conf_mode ) ;
if ( r < 0 )
return table_log_add_error ( r ) ;
}
2020-01-14 10:29:53 +01:00
if ( global_info . current_dns ) {
r = table_add_many ( table ,
TABLE_STRING , " Current DNS Server: " ,
2020-07-03 14:24:25 +02:00
TABLE_STRING , global_info . current_dns_ex ? : global_info . current_dns ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return table_log_add_error ( r ) ;
2018-05-11 09:12:17 +02:00
}
2020-07-03 14:24:25 +02:00
r = dump_list ( table , " DNS Servers: " , global_info . dns_ex ? : global_info . dns ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return r ;
2020-07-03 14:24:25 +02:00
r = dump_list ( table , " Fallback DNS Servers: " , global_info . fallback_dns_ex ? : global_info . fallback_dns ) ;
2020-01-14 10:29:53 +01:00
if ( r < 0 )
return r ;
r = dump_list ( table , " DNS Domain: " , global_info . domains ) ;
if ( r < 0 )
return r ;
2016-06-15 21:43:36 +02:00
2020-01-14 10:29:53 +01:00
r = table_print ( table , NULL ) ;
if ( r < 0 )
2020-07-08 09:16:52 +02:00
return table_log_print_error ( r ) ;
2016-06-15 21:43:36 +02:00
* empty_line = true ;
2018-08-07 03:13:44 +02:00
return 0 ;
2016-06-15 21:43:36 +02:00
}
2018-04-11 03:44:51 +02:00
static int status_all ( sd_bus * bus , StatusMode mode ) {
2016-06-15 21:43:36 +02:00
_cleanup_ ( sd_netlink_message_unrefp ) sd_netlink_message * req = NULL , * reply = NULL ;
_cleanup_ ( sd_netlink_unrefp ) sd_netlink * rtnl = NULL ;
2016-06-28 19:55:58 +02:00
bool empty_line = false ;
2016-06-15 21:43:36 +02:00
int r ;
assert ( bus ) ;
2018-04-11 03:44:51 +02:00
r = status_global ( bus , mode , & empty_line ) ;
2016-06-15 21:43:36 +02:00
if ( r < 0 )
return r ;
r = sd_netlink_open ( & rtnl ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to connect to netlink: %m " ) ;
r = sd_rtnl_message_new_link ( rtnl , & req , RTM_GETLINK , 0 ) ;
if ( r < 0 )
return rtnl_log_create_error ( r ) ;
r = sd_netlink_message_request_dump ( req , true ) ;
if ( r < 0 )
return rtnl_log_create_error ( r ) ;
r = sd_netlink_call ( rtnl , req , 0 , & reply ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to enumerate links: %m " ) ;
2020-06-02 17:49:22 +02:00
_cleanup_free_ InterfaceInfo * infos = NULL ;
size_t n_allocated = 0 , n_infos = 0 ;
2020-06-02 17:46:58 +02:00
for ( sd_netlink_message * i = reply ; i ; i = sd_netlink_message_next ( i ) ) {
2016-06-15 21:43:36 +02:00
const char * name ;
2020-06-02 17:49:22 +02:00
int ifindex ;
2016-06-15 21:43:36 +02:00
uint16_t type ;
2020-06-02 17:49:22 +02:00
r = sd_netlink_message_get_type ( i , & type ) ;
if ( r < 0 )
return rtnl_log_parse_error ( r ) ;
2016-06-15 21:43:36 +02:00
if ( type ! = RTM_NEWLINK )
continue ;
2020-06-02 17:49:22 +02:00
r = sd_rtnl_message_link_get_ifindex ( i , & ifindex ) ;
if ( r < 0 )
return rtnl_log_parse_error ( r ) ;
2016-06-15 21:43:36 +02:00
if ( ifindex = = LOOPBACK_IFINDEX )
continue ;
2020-06-02 17:49:22 +02:00
r = sd_netlink_message_read_string ( i , IFLA_IFNAME , & name ) ;
if ( r < 0 )
return rtnl_log_parse_error ( r ) ;
2016-06-15 21:43:36 +02:00
2020-06-02 17:49:22 +02:00
if ( ! GREEDY_REALLOC ( infos , n_allocated , n_infos + 1 ) )
return log_oom ( ) ;
infos [ n_infos + + ] = ( InterfaceInfo ) { ifindex , name } ;
}
typesafe_qsort ( infos , n_infos , interface_info_compare ) ;
r = 0 ;
for ( size_t i = 0 ; i < n_infos ; i + + ) {
int q = status_ifindex ( bus , infos [ i ] . index , infos [ i ] . name , mode , & empty_line ) ;
2016-06-15 21:43:36 +02:00
if ( q < 0 & & r > = 0 )
r = q ;
}
return r ;
}
2018-04-11 03:44:51 +02:00
static int verb_status ( int argc , char * * argv , void * userdata ) {
sd_bus * bus = userdata ;
2020-01-11 11:37:26 +01:00
_cleanup_ ( sd_netlink_unrefp ) sd_netlink * rtnl = NULL ;
2019-12-18 13:54:13 +01:00
int r = 0 ;
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
if ( argc > 1 ) {
char * * ifname ;
bool empty_line = false ;
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
STRV_FOREACH ( ifname , argv + 1 ) {
2019-12-18 13:54:13 +01:00
int ifindex , q ;
2017-12-14 20:13:14 +01:00
2020-01-11 11:37:26 +01:00
ifindex = resolve_interface ( & rtnl , * ifname ) ;
2019-12-18 13:54:13 +01:00
if ( ifindex < 0 ) {
2020-01-11 11:21:01 +01:00
log_warning_errno ( ifindex , " Failed to resolve interface \" %s \" , ignoring: %m " , * ifname ) ;
2018-04-11 03:44:51 +02:00
continue ;
2019-05-29 03:56:55 +02:00
}
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
q = status_ifindex ( bus , ifindex , NULL , STATUS_ALL , & empty_line ) ;
if ( q < 0 )
r = q ;
}
} else
r = status_all ( bus , STATUS_ALL ) ;
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
return r ;
}
2017-12-14 20:13:14 +01:00
2020-07-03 14:05:15 +02:00
static int call_dns ( sd_bus * bus , char * * dns , const BusLocator * locator , sd_bus_error * error , bool extended ) {
2018-04-11 03:44:51 +02:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL ;
char * * p ;
2018-06-26 09:41:22 +02:00
int r ;
2017-12-14 20:13:14 +01:00
2020-07-03 14:05:15 +02:00
r = bus_message_new_method_call ( bus , & req , locator , extended ? " SetLinkDNSEx " : " SetLinkDNS " ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-06-26 09:41:22 +02:00
r = sd_bus_message_append ( req , " i " , arg_ifindex ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2020-07-03 14:05:15 +02:00
r = sd_bus_message_open_container ( req , ' a ' , extended ? " (iayqs) " : " (iay) " ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-07-17 00:16:37 +02:00
/* If only argument is the empty string, then call SetLinkDNS() with an
* empty list , which will clear the list of domains for an interface . */
2019-05-27 03:50:52 +02:00
if ( ! strv_equal ( dns , STRV_MAKE ( " " ) ) )
STRV_FOREACH ( p , dns ) {
2020-07-03 14:05:15 +02:00
_cleanup_free_ char * name = NULL ;
2018-07-17 00:16:37 +02:00
struct in_addr_data data ;
2020-07-03 14:05:15 +02:00
uint16_t port ;
int ifindex ;
2017-12-14 20:13:14 +01:00
2020-07-03 14:05:15 +02:00
r = in_addr_port_ifindex_name_from_string_auto ( * p , & data . family , & data . address , & port , & ifindex , & name ) ;
2018-07-17 00:16:37 +02:00
if ( r < 0 )
return log_error_errno ( r , " Failed to parse DNS server address: %s " , * p ) ;
2017-12-14 20:13:14 +01:00
2020-07-03 14:05:15 +02:00
if ( ifindex ! = 0 & & ifindex ! = arg_ifindex )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) , " Invalid ifindex: %i " , ifindex ) ;
r = sd_bus_message_open_container ( req , ' r ' , extended ? " iayqs " : " iay " ) ;
2018-07-17 00:16:37 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-07-17 00:16:37 +02:00
r = sd_bus_message_append ( req , " i " , data . family ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-07-17 00:16:37 +02:00
r = sd_bus_message_append_array ( req , ' y ' , & data . address , FAMILY_ADDRESS_SIZE ( data . family ) ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2018-04-11 03:44:51 +02:00
2020-07-03 14:05:15 +02:00
if ( extended ) {
r = sd_bus_message_append ( req , " q " , port ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
r = sd_bus_message_append ( req , " s " , name ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
}
2018-07-17 00:16:37 +02:00
r = sd_bus_message_close_container ( req ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
}
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
r = sd_bus_message_close_container ( req ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2020-07-03 14:05:15 +02:00
r = sd_bus_call ( bus , req , 0 , error , NULL ) ;
2020-07-24 14:03:25 +02:00
if ( r < 0 & & extended & & sd_bus_error_has_name ( error , SD_BUS_ERROR_UNKNOWN_METHOD ) ) {
sd_bus_error_free ( error ) ;
2020-07-03 14:05:15 +02:00
return call_dns ( bus , dns , locator , error , false ) ;
2020-07-24 14:03:25 +02:00
}
2020-07-03 14:05:15 +02:00
return r ;
2018-04-11 03:44:51 +02:00
}
2019-05-27 03:50:52 +02:00
static int verb_dns ( int argc , char * * argv , void * userdata ) {
2018-04-11 03:44:51 +02:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2018-04-11 03:44:51 +02:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
2019-05-27 03:50:52 +02:00
return status_all ( bus , STATUS_DNS ) ;
2017-12-14 20:13:14 +01:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2019-05-27 03:50:52 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_DNS , NULL ) ;
2020-07-03 14:05:15 +02:00
r = call_dns ( bus , argv + 2 , bus_resolve_mgr , & error , true ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-07-03 14:05:15 +02:00
r = call_dns ( bus , argv + 2 , bus_network_mgr , & error , true ) ;
2019-05-27 03:50:52 +02:00
}
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 set DNS configuration: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
2020-05-03 08:39:14 +02:00
static int call_domain ( sd_bus * bus , char * * domain , const BusLocator * locator , sd_bus_error * error ) {
2019-05-27 03:50:52 +02:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL ;
char * * p ;
int r ;
2017-12-14 20:13:14 +01:00
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , locator , " SetLinkDomains " ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-06-26 09:41:22 +02:00
r = sd_bus_message_append ( req , " i " , arg_ifindex ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
r = sd_bus_message_open_container ( req , ' a ' , " (sb) " ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2018-07-17 00:16:37 +02:00
/* If only argument is the empty string, then call SetLinkDomains() with an
* empty list , which will clear the list of domains for an interface . */
2019-05-27 03:50:52 +02:00
if ( ! strv_equal ( domain , STRV_MAKE ( " " ) ) )
STRV_FOREACH ( p , domain ) {
2018-07-17 00:16:37 +02:00
const char * n ;
2017-12-14 20:13:14 +01:00
2018-07-17 00:16:37 +02:00
n = * * p = = ' ~ ' ? * p + 1 : * p ;
2017-12-14 20:13:14 +01:00
2018-07-17 00:16:37 +02:00
r = dns_name_is_valid ( n ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to validate specified domain %s: %m " , n ) ;
2020-10-09 14:59:44 +02:00
if ( r = = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Domain not valid: %s " ,
n ) ;
2018-04-11 03:44:51 +02:00
2018-07-17 00:16:37 +02:00
r = sd_bus_message_append ( req , " (sb) " , n , * * p = = ' ~ ' ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
}
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
r = sd_bus_message_close_container ( req ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
2019-05-27 03:50:52 +02:00
return sd_bus_call ( bus , req , 0 , error , NULL ) ;
}
static int verb_domain ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
int r ;
assert ( bus ) ;
if ( argc > = 2 ) {
r = ifname_mangle ( argv [ 1 ] ) ;
if ( r < 0 )
return r ;
}
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_DOMAIN ) ;
if ( argc < 3 )
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_DOMAIN , NULL ) ;
2020-05-03 08:39:14 +02:00
r = call_domain ( bus , argv + 2 , bus_resolve_mgr , & error ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2017-12-14 20:13:14 +01:00
2020-05-03 08:39:14 +02:00
r = call_domain ( bus , argv + 2 , bus_network_mgr , & error ) ;
2019-05-27 03:50:52 +02:00
}
if ( r < 0 ) {
2018-04-11 03:44:51 +02:00
if ( arg_ifindex_permissive & &
sd_bus_error_has_name ( & error , BUS_ERROR_NO_SUCH_LINK ) )
return 0 ;
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
return log_error_errno ( r , " Failed to set domain configuration: %s " , bus_error_message ( & error , r ) ) ;
2017-12-14 20:13:14 +01:00
}
2018-04-11 03:44:51 +02:00
return 0 ;
2017-12-14 20:13:14 +01:00
}
2018-12-04 13:29:41 +01:00
static int verb_default_route ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
int r , b ;
assert ( bus ) ;
if ( argc > = 2 ) {
r = ifname_mangle ( argv [ 1 ] ) ;
if ( r < 0 )
return r ;
}
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_DEFAULT_ROUTE ) ;
if ( argc < 3 )
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_DEFAULT_ROUTE , NULL ) ;
b = parse_boolean ( argv [ 2 ] ) ;
if ( b < 0 )
return log_error_errno ( b , " Failed to parse boolean argument: %s " , argv [ 2 ] ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " SetLinkDefaultRoute " , & error , NULL , " ib " , arg_ifindex , b ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_network_mgr , " SetLinkDefaultRoute " , & error , NULL , " ib " , arg_ifindex , b ) ;
2019-05-27 03:50:52 +02:00
}
2018-12-04 13:29:41 +01:00
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 set default route configuration: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int verb_llmnr ( int argc , char * * argv , void * userdata ) {
2017-12-14 20:13:14 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
2018-04-11 03:44:51 +02:00
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2017-12-14 20:13:14 +01:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_LLMNR ) ;
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2018-06-26 09:41:22 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_LLMNR , NULL ) ;
2018-04-11 03:44:51 +02:00
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " SetLinkLLMNR " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_network_mgr , " SetLinkLLMNR " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
}
2018-02-27 17:48:54 +01:00
if ( r < 0 ) {
if ( arg_ifindex_permissive & &
sd_bus_error_has_name ( & error , BUS_ERROR_NO_SUCH_LINK ) )
return 0 ;
2018-04-11 03:44:51 +02:00
return log_error_errno ( r , " Failed to set LLMNR configuration: %s " , bus_error_message ( & error , r ) ) ;
2018-02-27 17:48:54 +01:00
}
2017-12-14 20:13:14 +01:00
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int verb_mdns ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2015-02-05 03:06:36 +01:00
2018-04-11 03:44:51 +02:00
assert ( bus ) ;
2014-08-01 02:06:30 +02:00
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_MDNS ) ;
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2018-06-26 09:41:22 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_MDNS , NULL ) ;
2018-04-11 03:44:51 +02:00
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " SetLinkMulticastDNS " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method (
2019-05-27 03:50:52 +02:00
bus ,
2020-05-03 08:39:14 +02:00
bus_network_mgr ,
2019-05-27 03:50:52 +02:00
" SetLinkMulticastDNS " ,
& error ,
NULL ,
" is " , arg_ifindex , argv [ 2 ] ) ;
}
2018-04-11 03:44:51 +02:00
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 set MulticastDNS configuration: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
2018-06-13 20:26:24 +02:00
static int verb_dns_over_tls ( int argc , char * * argv , void * userdata ) {
2018-05-04 17:31:16 +02:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2018-05-04 17:31:16 +02:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-05-04 17:31:16 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_PRIVATE ) ;
2018-05-04 17:31:16 +02:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2018-06-26 09:41:22 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_PRIVATE , NULL ) ;
2018-05-04 17:31:16 +02:00
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " SetLinkDNSOverTLS " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method (
2019-05-27 03:50:52 +02:00
bus ,
2020-05-03 08:39:14 +02:00
bus_network_mgr ,
2019-05-27 03:50:52 +02:00
" SetLinkDNSOverTLS " ,
& error ,
NULL ,
" is " , arg_ifindex , argv [ 2 ] ) ;
}
2018-05-04 17:31:16 +02:00
if ( r < 0 ) {
if ( arg_ifindex_permissive & &
sd_bus_error_has_name ( & error , BUS_ERROR_NO_SUCH_LINK ) )
return 0 ;
2018-06-13 20:26:24 +02:00
return log_error_errno ( r , " Failed to set DNSOverTLS configuration: %s " , bus_error_message ( & error , r ) ) ;
2018-05-04 17:31:16 +02:00
}
return 0 ;
}
2018-04-11 03:44:51 +02:00
static int verb_dnssec ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2018-04-11 03:44:51 +02:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_DNSSEC ) ;
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2018-06-26 09:41:22 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_DNSSEC , NULL ) ;
2018-04-11 03:44:51 +02:00
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " SetLinkDNSSEC " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_network_mgr , " SetLinkDNSSEC " , & error , NULL , " is " , arg_ifindex , argv [ 2 ] ) ;
2019-05-27 03:50:52 +02:00
}
2018-04-11 03:44:51 +02:00
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 set DNSSEC configuration: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
2020-05-03 08:39:14 +02:00
static int call_nta ( sd_bus * bus , char * * nta , const BusLocator * locator , sd_bus_error * error ) {
2019-05-27 03:50:52 +02:00
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * req = NULL ;
int r ;
2020-05-03 08:39:14 +02:00
r = bus_message_new_method_call ( bus , & req , locator , " SetLinkDNSSECNegativeTrustAnchors " ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 )
return bus_log_create_error ( r ) ;
r = sd_bus_message_append ( req , " i " , arg_ifindex ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
r = sd_bus_message_append_strv ( req , nta ) ;
if ( r < 0 )
return bus_log_create_error ( r ) ;
return sd_bus_call ( bus , req , 0 , error , NULL ) ;
}
2018-04-11 03:44:51 +02:00
static int verb_nta ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
char * * p ;
int r ;
2018-07-17 00:16:37 +02:00
bool clear ;
2018-04-11 03:44:51 +02:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( arg_ifindex < = 0 )
return status_all ( bus , STATUS_NTA ) ;
2018-04-11 03:44:51 +02:00
2018-12-05 13:58:34 +01:00
if ( argc < 3 )
2018-06-26 09:41:22 +02:00
return status_ifindex ( bus , arg_ifindex , NULL , STATUS_NTA , NULL ) ;
2018-04-11 03:44:51 +02:00
2018-07-17 00:16:37 +02:00
/* If only argument is the empty string, then call SetLinkDNSSECNegativeTrustAnchors()
* with an empty list , which will clear the list of domains for an interface . */
clear = strv_equal ( argv + 2 , STRV_MAKE ( " " ) ) ;
if ( ! clear )
STRV_FOREACH ( p , argv + 2 ) {
r = dns_name_is_valid ( * p ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to validate specified domain %s: %m " , * p ) ;
2020-10-09 14:59:44 +02:00
if ( r = = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Domain not valid: %s " ,
* p ) ;
2018-04-11 03:44:51 +02:00
}
2020-05-03 08:39:14 +02:00
r = call_nta ( bus , clear ? NULL : argv + 2 , bus_resolve_mgr , & error ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2018-04-11 03:44:51 +02:00
2020-05-03 08:39:14 +02:00
r = call_nta ( bus , clear ? NULL : argv + 2 , bus_network_mgr , & error ) ;
2019-05-27 03:50:52 +02:00
}
2018-04-11 03:44:51 +02:00
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 set DNSSEC NTA configuration: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
static int verb_revert_link ( int argc , char * * argv , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
2018-06-26 09:41:22 +02:00
int r ;
2018-04-11 03:44:51 +02:00
assert ( bus ) ;
2018-12-05 13:58:34 +01:00
if ( argc > = 2 ) {
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( argv [ 1 ] ) ;
2018-12-05 13:58:34 +01:00
if ( r < 0 )
return r ;
}
if ( arg_ifindex < = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) , " Interface argument required. " ) ;
2018-04-11 03:44:51 +02:00
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_resolve_mgr , " RevertLink " , & error , NULL , " i " , arg_ifindex ) ;
2019-05-27 03:50:52 +02:00
if ( r < 0 & & sd_bus_error_has_name ( & error , BUS_ERROR_LINK_BUSY ) ) {
sd_bus_error_free ( & error ) ;
2020-05-03 08:39:14 +02:00
r = bus_call_method ( bus , bus_network_mgr , " RevertLinkDNS " , & error , NULL , " i " , arg_ifindex ) ;
2019-05-27 03:50:52 +02:00
}
2018-04-11 03:44:51 +02:00
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 0 ;
}
2020-04-20 11:02:39 +02:00
static int verb_log_level ( int argc , char * argv [ ] , void * userdata ) {
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
sd_bus * bus = userdata ;
int r ;
assert ( bus ) ;
if ( argc = = 1 ) {
_cleanup_free_ char * level = NULL ;
r = sd_bus_get_property_string (
bus ,
" org.freedesktop.resolve1 " ,
2020-04-21 10:27:23 +02:00
" /org/freedesktop/LogControl1 " ,
" org.freedesktop.LogControl1 " ,
2020-04-20 11:02:39 +02:00
" LogLevel " ,
& error ,
& level ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to get log level: %s " , bus_error_message ( & error , r ) ) ;
puts ( level ) ;
} else {
assert ( argc = = 2 ) ;
r = sd_bus_set_property (
bus ,
" org.freedesktop.resolve1 " ,
2020-04-21 10:27:23 +02:00
" /org/freedesktop/LogControl1 " ,
" org.freedesktop.LogControl1 " ,
2020-04-20 11:02:39 +02:00
" LogLevel " ,
& error ,
" s " ,
argv [ 1 ] ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to set log level: %s " , bus_error_message ( & error , r ) ) ;
}
return 0 ;
}
2018-04-11 03:44:51 +02:00
static void help_protocol_types ( void ) {
if ( arg_legend )
puts ( " Known protocol types: " ) ;
puts ( " dns \n llmnr \n llmnr-ipv4 \n llmnr-ipv6 \n mdns \n mdns-ipv4 \n mdns-ipv6 " ) ;
}
static void help_dns_types ( void ) {
if ( arg_legend )
puts ( " Known DNS RR types: " ) ;
2018-05-22 12:10:56 +02:00
DUMP_STRING_TABLE ( dns_type , int , _DNS_TYPE_MAX ) ;
2014-08-01 02:06:30 +02:00
}
static void help_dns_classes ( void ) {
if ( arg_legend )
2015-08-21 16:06:25 +02:00
puts ( " Known DNS RR classes: " ) ;
2018-05-22 12:10:56 +02:00
DUMP_STRING_TABLE ( dns_class , int , _DNS_CLASS_MAX ) ;
2014-08-01 02:06:30 +02:00
}
2018-08-09 10:32:31 +02:00
static int compat_help ( void ) {
_cleanup_free_ char * link = NULL ;
int r ;
r = terminal_urlify_man ( " resolvectl " , " 1 " , & link ) ;
if ( r < 0 )
return log_oom ( ) ;
2016-02-15 19:15:23 +01:00
printf ( " %1$s [OPTIONS...] HOSTNAME|ADDRESS... \n "
" %1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN \n "
" %1$s [OPTIONS...] --openpgp EMAIL@DOMAIN... \n "
" %1$s [OPTIONS...] --statistics \n "
" %1$s [OPTIONS...] --reset-statistics \n "
" \n "
2019-11-15 18:38:44 +01:00
" %2$sResolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%3$s \n \n "
2016-02-15 19:15:23 +01:00
" -h --help Show this help \n "
" --version Show package version \n "
2016-06-15 21:43:36 +02:00
" --no-pager Do not pipe output into a pager \n "
2016-02-15 19:15:23 +01:00
" -4 Resolve IPv4 addresses \n "
" -6 Resolve IPv6 addresses \n "
" -i --interface=INTERFACE Look on interface \n "
" -p --protocol=PROTO|help Look via protocol \n "
" -t --type=TYPE|help Query RR with DNS type \n "
" -c --class=CLASS|help Query RR with DNS class \n "
" --service Resolve service (SRV) \n "
" --service-address=BOOL Resolve address for services (default: yes) \n "
" --service-txt=BOOL Resolve TXT records for services (default: yes) \n "
" --openpgp Query OpenPGP public key \n "
2016-02-18 03:08:57 +01:00
" --tlsa Query TLS public key \n "
2016-02-15 19:15:23 +01:00
" --cname=BOOL Follow CNAME redirects (default: yes) \n "
" --search=BOOL Use search domains for single-label names \n "
" (default: yes) \n "
2016-01-31 06:06:49 +01:00
" --raw[=payload|packet] Dump the answer as binary data \n "
2016-02-15 19:15:23 +01:00
" --legend=BOOL Print headers and additional info (default: yes) \n "
" --statistics Show resolver statistics \n "
" --reset-statistics Reset resolver statistics \n "
2016-06-15 21:43:36 +02:00
" --status Show link and server status \n "
2016-06-10 20:40:30 +02:00
" --flush-caches Flush all local DNS caches \n "
2017-09-29 21:19:54 +02:00
" --reset-server-features \n "
" Forget learnt DNS server feature levels \n "
2017-12-14 20:13:14 +01:00
" --set-dns=SERVER Set per-interface DNS server address \n "
" --set-domain=DOMAIN Set per-interface search domain \n "
" --set-llmnr=MODE Set per-interface LLMNR mode \n "
" --set-mdns=MODE Set per-interface MulticastDNS mode \n "
2018-06-13 20:26:24 +02:00
" --set-dnsovertls=MODE Set per-interface DNS-over-TLS mode \n "
2017-12-14 20:13:14 +01:00
" --set-dnssec=MODE Set per-interface DNSSEC mode \n "
" --set-nta=DOMAIN Set per-interface DNSSEC NTA \n "
" --revert Revert per-interface configuration \n "
2019-11-15 18:38:44 +01:00
" \n See the %4$s for details. \n "
2018-08-09 10:32:31 +02:00
, program_invocation_short_name
2019-11-15 18:38:44 +01:00
, ansi_highlight ( )
, ansi_normal ( )
2018-08-09 10:32:31 +02:00
, link
) ;
return 0 ;
2014-07-16 22:55:23 +02:00
}
2018-08-09 10:32:31 +02:00
static int native_help ( void ) {
_cleanup_free_ char * link = NULL ;
int r ;
r = terminal_urlify_man ( " resolvectl " , " 1 " , & link ) ;
if ( r < 0 )
return log_oom ( ) ;
2019-11-15 18:38:44 +01:00
printf ( " %s [OPTIONS...] COMMAND ... \n "
2018-04-11 03:44:51 +02:00
" \n "
2019-11-15 18:38:44 +01:00
" %sSend control commands to the network name resolution manager, or%s \n "
" %sresolve domain names, IPv4 and IPv6 addresses, DNS records, and services.%s \n "
2019-10-08 17:58:44 +02:00
" \n Commands: \n "
2018-04-11 03:44:51 +02:00
" query HOSTNAME|ADDRESS... Resolve domain names, IPv4 and IPv6 addresses \n "
" service [[NAME] TYPE] DOMAIN Resolve service (SRV) \n "
" openpgp EMAIL@DOMAIN... Query OpenPGP public key \n "
" tlsa DOMAIN[:PORT]... Query TLS public key \n "
" status [LINK...] Show link and server status \n "
" statistics Show resolver statistics \n "
" reset-statistics Reset resolver statistics \n "
" flush-caches Flush all local DNS caches \n "
" reset-server-features Forget learnt DNS server feature levels \n "
" dns [LINK [SERVER...]] Get/set per-interface DNS server address \n "
" domain [LINK [DOMAIN...]] Get/set per-interface search domain \n "
2018-12-04 13:29:41 +01:00
" default-route [LINK [BOOL]] Get/set per-interface default route flag \n "
2018-04-11 03:44:51 +02:00
" llmnr [LINK [MODE]] Get/set per-interface LLMNR mode \n "
" mdns [LINK [MODE]] Get/set per-interface MulticastDNS mode \n "
2018-06-13 20:26:24 +02:00
" dnsovertls [LINK [MODE]] Get/set per-interface DNS-over-TLS mode \n "
2018-04-11 03:44:51 +02:00
" dnssec [LINK [MODE]] Get/set per-interface DNSSEC mode \n "
" nta [LINK [DOMAIN...]] Get/set per-interface DNSSEC NTA \n "
" revert LINK Revert per-interface configuration \n "
2020-09-04 09:58:32 +02:00
" log-level [LEVEL] Get/set logging threshold for systemd-resolved \n "
2019-11-15 18:38:44 +01:00
" \n Options: \n "
2019-10-08 17:58:44 +02:00
" -h --help Show this help \n "
" --version Show package version \n "
" --no-pager Do not pipe output into a pager \n "
" -4 Resolve IPv4 addresses \n "
" -6 Resolve IPv6 addresses \n "
" -i --interface=INTERFACE Look on interface \n "
" -p --protocol=PROTO|help Look via protocol \n "
" -t --type=TYPE|help Query RR with DNS type \n "
" -c --class=CLASS|help Query RR with DNS class \n "
" --service-address=BOOL Resolve address for services (default: yes) \n "
" --service-txt=BOOL Resolve TXT records for services (default: yes) \n "
" --cname=BOOL Follow CNAME redirects (default: yes) \n "
" --search=BOOL Use search domains for single-label names \n "
" (default: yes) \n "
" --raw[=payload|packet] Dump the answer as binary data \n "
" --legend=BOOL Print headers and additional info (default: yes) \n "
2019-10-08 18:19:59 +02:00
" \n See the %s for details. \n "
2018-08-09 10:32:31 +02:00
, program_invocation_short_name
2019-11-15 18:38:44 +01:00
, ansi_highlight ( )
, ansi_normal ( )
, ansi_highlight ( )
2019-10-08 18:19:59 +02:00
, ansi_normal ( )
2018-08-09 10:32:31 +02:00
, link
) ;
return 0 ;
2018-04-11 03:44:51 +02:00
}
static int verb_help ( int argc , char * * argv , void * userdata ) {
2018-08-09 10:32:31 +02:00
return native_help ( ) ;
2018-04-11 03:44:51 +02:00
}
static int compat_parse_argv ( int argc , char * argv [ ] ) {
2014-07-16 22:55:23 +02:00
enum {
ARG_VERSION = 0x100 ,
2014-08-20 00:15:05 +02:00
ARG_LEGEND ,
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
ARG_SERVICE ,
ARG_CNAME ,
ARG_SERVICE_ADDRESS ,
ARG_SERVICE_TXT ,
2016-01-29 00:24:27 +01:00
ARG_OPENPGP ,
2016-02-18 03:08:57 +01:00
ARG_TLSA ,
2016-01-29 00:24:28 +01:00
ARG_RAW ,
2015-11-25 20:47:27 +01:00
ARG_SEARCH ,
2015-12-23 19:06:36 +01:00
ARG_STATISTICS ,
ARG_RESET_STATISTICS ,
2016-06-15 21:43:36 +02:00
ARG_STATUS ,
2016-06-10 20:40:30 +02:00
ARG_FLUSH_CACHES ,
2017-09-29 21:19:54 +02:00
ARG_RESET_SERVER_FEATURES ,
2016-06-15 21:43:36 +02:00
ARG_NO_PAGER ,
2017-12-14 20:13:14 +01:00
ARG_SET_DNS ,
ARG_SET_DOMAIN ,
ARG_SET_LLMNR ,
ARG_SET_MDNS ,
2018-05-04 17:31:16 +02:00
ARG_SET_PRIVATE ,
2017-12-14 20:13:14 +01:00
ARG_SET_DNSSEC ,
ARG_SET_NTA ,
ARG_REVERT_LINK ,
2014-07-16 22:55:23 +02:00
} ;
static const struct option options [ ] = {
2017-09-29 21:19:54 +02:00
{ " help " , no_argument , NULL , ' h ' } ,
{ " version " , no_argument , NULL , ARG_VERSION } ,
{ " type " , required_argument , NULL , ' t ' } ,
{ " class " , required_argument , NULL , ' c ' } ,
{ " legend " , required_argument , NULL , ARG_LEGEND } ,
{ " interface " , required_argument , NULL , ' i ' } ,
{ " protocol " , required_argument , NULL , ' p ' } ,
{ " cname " , required_argument , NULL , ARG_CNAME } ,
{ " service " , no_argument , NULL , ARG_SERVICE } ,
{ " service-address " , required_argument , NULL , ARG_SERVICE_ADDRESS } ,
{ " service-txt " , required_argument , NULL , ARG_SERVICE_TXT } ,
{ " openpgp " , no_argument , NULL , ARG_OPENPGP } ,
{ " tlsa " , optional_argument , NULL , ARG_TLSA } ,
{ " raw " , optional_argument , NULL , ARG_RAW } ,
{ " search " , required_argument , NULL , ARG_SEARCH } ,
{ " statistics " , no_argument , NULL , ARG_STATISTICS , } ,
{ " reset-statistics " , no_argument , NULL , ARG_RESET_STATISTICS } ,
{ " status " , no_argument , NULL , ARG_STATUS } ,
{ " flush-caches " , no_argument , NULL , ARG_FLUSH_CACHES } ,
{ " reset-server-features " , no_argument , NULL , ARG_RESET_SERVER_FEATURES } ,
{ " no-pager " , no_argument , NULL , ARG_NO_PAGER } ,
2017-12-14 20:13:14 +01:00
{ " set-dns " , required_argument , NULL , ARG_SET_DNS } ,
{ " set-domain " , required_argument , NULL , ARG_SET_DOMAIN } ,
{ " set-llmnr " , required_argument , NULL , ARG_SET_LLMNR } ,
{ " set-mdns " , required_argument , NULL , ARG_SET_MDNS } ,
2018-06-13 20:26:24 +02:00
{ " set-dnsovertls " , required_argument , NULL , ARG_SET_PRIVATE } ,
2017-12-14 20:13:14 +01:00
{ " set-dnssec " , required_argument , NULL , ARG_SET_DNSSEC } ,
{ " set-nta " , required_argument , NULL , ARG_SET_NTA } ,
{ " revert " , no_argument , NULL , ARG_REVERT_LINK } ,
2014-07-16 22:55:23 +02:00
{ }
} ;
2014-07-30 19:23:27 +02:00
int c , r ;
2014-07-16 22:55:23 +02:00
assert ( argc > = 0 ) ;
assert ( argv ) ;
2014-08-14 01:00:15 +02:00
while ( ( c = getopt_long ( argc , argv , " h46i:t:c:p: " , options , NULL ) ) > = 0 )
2014-07-16 22:55:23 +02:00
switch ( c ) {
case ' h ' :
2018-08-09 10:32:31 +02:00
return compat_help ( ) ;
2014-07-16 22:55:23 +02:00
case ARG_VERSION :
2015-09-23 03:01:06 +02:00
return version ( ) ;
2014-07-16 22:55:23 +02:00
case ' 4 ' :
arg_family = AF_INET ;
break ;
case ' 6 ' :
arg_family = AF_INET6 ;
break ;
2018-02-27 17:45:04 +01:00
case ' i ' :
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( optarg ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return r ;
2014-07-30 19:23:27 +02:00
break ;
case ' t ' :
2014-08-01 02:06:30 +02:00
if ( streq ( optarg , " help " ) ) {
help_dns_types ( ) ;
return 0 ;
}
2015-12-18 18:53:11 +01:00
r = dns_type_from_string ( optarg ) ;
if ( r < 0 ) {
2014-07-30 19:23:27 +02:00
log_error ( " Failed to parse RR record type %s " , optarg ) ;
2015-12-18 18:53:11 +01:00
return r ;
2014-07-30 19:23:27 +02:00
}
2015-12-18 18:53:11 +01:00
arg_type = ( uint16_t ) r ;
assert ( ( int ) arg_type = = r ) ;
2014-08-01 02:06:30 +02:00
2015-12-23 19:06:36 +01:00
arg_mode = MODE_RESOLVE_RECORD ;
2014-07-30 19:23:27 +02:00
break ;
case ' c ' :
2014-08-01 02:06:30 +02:00
if ( streq ( optarg , " help " ) ) {
help_dns_classes ( ) ;
return 0 ;
}
2015-12-18 18:53:11 +01:00
r = dns_class_from_string ( optarg ) ;
2014-07-30 19:23:27 +02:00
if ( r < 0 ) {
log_error ( " Failed to parse RR record class %s " , optarg ) ;
return r ;
2014-07-16 22:55:23 +02:00
}
2015-12-18 18:53:11 +01:00
arg_class = ( uint16_t ) r ;
assert ( ( int ) arg_class = = r ) ;
2014-08-01 02:06:30 +02:00
break ;
2014-08-20 00:15:05 +02:00
case ARG_LEGEND :
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --legend= argument " ) ;
arg_legend = r ;
2014-07-16 22:55:23 +02:00
break ;
2014-08-14 01:00:15 +02:00
case ' p ' :
2015-02-05 03:06:36 +01:00
if ( streq ( optarg , " help " ) ) {
help_protocol_types ( ) ;
return 0 ;
} else if ( streq ( optarg , " dns " ) )
2014-08-14 01:00:15 +02:00
arg_flags | = SD_RESOLVED_DNS ;
else if ( streq ( optarg , " llmnr " ) )
arg_flags | = SD_RESOLVED_LLMNR ;
else if ( streq ( optarg , " llmnr-ipv4 " ) )
arg_flags | = SD_RESOLVED_LLMNR_IPV4 ;
else if ( streq ( optarg , " llmnr-ipv6 " ) )
arg_flags | = SD_RESOLVED_LLMNR_IPV6 ;
2017-01-19 10:47:51 +01:00
else if ( streq ( optarg , " mdns " ) )
arg_flags | = SD_RESOLVED_MDNS ;
else if ( streq ( optarg , " mdns-ipv4 " ) )
arg_flags | = SD_RESOLVED_MDNS_IPV4 ;
else if ( streq ( optarg , " mdns-ipv6 " ) )
arg_flags | = SD_RESOLVED_MDNS_IPV6 ;
2018-11-20 23:40:44 +01:00
else
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown protocol specifier: %s " , optarg ) ;
2014-08-14 01:00:15 +02:00
break ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
case ARG_SERVICE :
2015-12-23 19:06:36 +01:00
arg_mode = MODE_RESOLVE_SERVICE ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
break ;
2016-01-29 00:24:27 +01:00
case ARG_OPENPGP :
arg_mode = MODE_RESOLVE_OPENPGP ;
break ;
2016-02-18 03:08:57 +01:00
case ARG_TLSA :
arg_mode = MODE_RESOLVE_TLSA ;
2018-05-08 10:52:36 +02:00
if ( ! optarg | | service_family_is_valid ( optarg ) )
arg_service_family = optarg ;
2018-11-20 23:40:44 +01:00
else
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown service family \" %s \" . " , optarg ) ;
2016-02-18 03:08:57 +01:00
break ;
2016-01-29 00:24:28 +01:00
case ARG_RAW :
2018-11-20 23:40:44 +01:00
if ( on_tty ( ) )
return log_error_errno ( SYNTHETIC_ERRNO ( ENOTTY ) ,
" Refusing to write binary data to tty. " ) ;
2016-01-29 00:24:28 +01:00
2016-01-31 06:06:49 +01:00
if ( optarg = = NULL | | streq ( optarg , " payload " ) )
arg_raw = RAW_PAYLOAD ;
else if ( streq ( optarg , " packet " ) )
arg_raw = RAW_PACKET ;
2018-11-20 23:40:44 +01:00
else
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown --raw specifier \" %s \" . " ,
optarg ) ;
2016-01-31 06:06:49 +01:00
2016-01-29 00:24:28 +01:00
arg_legend = false ;
break ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
case ARG_CNAME :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --cname= argument. " ) ;
2016-03-03 18:30:37 +01:00
SET_FLAG ( arg_flags , SD_RESOLVED_NO_CNAME , r = = 0 ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
break ;
case ARG_SERVICE_ADDRESS :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --service-address= argument. " ) ;
2016-03-03 18:30:37 +01:00
SET_FLAG ( arg_flags , SD_RESOLVED_NO_ADDRESS , r = = 0 ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
break ;
case ARG_SERVICE_TXT :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --service-txt= argument. " ) ;
2016-03-03 18:30:37 +01:00
SET_FLAG ( arg_flags , SD_RESOLVED_NO_TXT , r = = 0 ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
break ;
2015-11-25 20:47:27 +01:00
case ARG_SEARCH :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --search argument. " ) ;
2016-03-03 18:30:37 +01:00
SET_FLAG ( arg_flags , SD_RESOLVED_NO_SEARCH , r = = 0 ) ;
2015-11-25 20:47:27 +01:00
break ;
2015-12-23 19:06:36 +01:00
case ARG_STATISTICS :
arg_mode = MODE_STATISTICS ;
break ;
case ARG_RESET_STATISTICS :
arg_mode = MODE_RESET_STATISTICS ;
break ;
2016-06-10 20:40:30 +02:00
case ARG_FLUSH_CACHES :
arg_mode = MODE_FLUSH_CACHES ;
break ;
2017-09-29 21:19:54 +02:00
case ARG_RESET_SERVER_FEATURES :
arg_mode = MODE_RESET_SERVER_FEATURES ;
break ;
2016-06-15 21:43:36 +02:00
case ARG_STATUS :
arg_mode = MODE_STATUS ;
break ;
case ARG_NO_PAGER :
2018-11-11 12:56:29 +01:00
arg_pager_flags | = PAGER_DISABLE ;
2016-06-15 21:43:36 +02:00
break ;
2018-04-11 03:44:51 +02:00
case ARG_SET_DNS :
r = strv_extend ( & arg_set_dns , optarg ) ;
2017-12-14 20:13:14 +01:00
if ( r < 0 )
return log_oom ( ) ;
arg_mode = MODE_SET_LINK ;
break ;
2018-04-11 03:44:51 +02:00
case ARG_SET_DOMAIN :
2017-12-14 20:13:14 +01:00
r = strv_extend ( & arg_set_domain , optarg ) ;
if ( r < 0 )
return log_oom ( ) ;
arg_mode = MODE_SET_LINK ;
break ;
case ARG_SET_LLMNR :
2018-04-11 03:44:51 +02:00
arg_set_llmnr = optarg ;
2017-12-14 20:13:14 +01:00
arg_mode = MODE_SET_LINK ;
break ;
case ARG_SET_MDNS :
2018-04-11 03:44:51 +02:00
arg_set_mdns = optarg ;
2017-12-14 20:13:14 +01:00
arg_mode = MODE_SET_LINK ;
break ;
2018-05-04 17:31:16 +02:00
case ARG_SET_PRIVATE :
2018-06-13 20:26:24 +02:00
arg_set_dns_over_tls = optarg ;
2018-05-04 17:31:16 +02:00
arg_mode = MODE_SET_LINK ;
break ;
2017-12-14 20:13:14 +01:00
case ARG_SET_DNSSEC :
2018-04-11 03:44:51 +02:00
arg_set_dnssec = optarg ;
2017-12-14 20:13:14 +01:00
arg_mode = MODE_SET_LINK ;
break ;
case ARG_SET_NTA :
r = strv_extend ( & arg_set_nta , optarg ) ;
if ( r < 0 )
return log_oom ( ) ;
arg_mode = MODE_SET_LINK ;
break ;
case ARG_REVERT_LINK :
arg_mode = MODE_REVERT_LINK ;
break ;
2014-07-16 22:55:23 +02:00
case ' ? ' :
return - EINVAL ;
default :
assert_not_reached ( " Unhandled option " ) ;
}
2018-11-20 23:40:44 +01:00
if ( arg_type = = 0 & & arg_class ! = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" --class= may only be used in conjunction with --type=. " ) ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
2018-11-20 23:40:44 +01:00
if ( arg_type ! = 0 & & arg_mode = = MODE_RESOLVE_SERVICE )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" --service and --type= may not be combined. " ) ;
2014-07-30 19:23:27 +02:00
if ( arg_type ! = 0 & & arg_class = = 0 )
arg_class = DNS_CLASS_IN ;
2016-01-03 12:58:26 +01:00
if ( arg_class ! = 0 & & arg_type = = 0 )
arg_type = DNS_TYPE_A ;
2017-12-14 20:13:14 +01:00
if ( IN_SET ( arg_mode , MODE_SET_LINK , MODE_REVERT_LINK ) ) {
2018-11-20 23:40:44 +01:00
if ( arg_ifindex < = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" --set-dns=, --set-domain=, --set-llmnr=, --set-mdns=, --set-dnsovertls=, --set-dnssec=, --set-nta= and --revert require --interface=. " ) ;
2017-12-14 20:13:14 +01:00
}
2014-07-16 22:55:23 +02:00
return 1 /* work to do */ ;
}
2018-04-11 03:44:51 +02:00
static int native_parse_argv ( int argc , char * argv [ ] ) {
enum {
ARG_VERSION = 0x100 ,
ARG_LEGEND ,
ARG_CNAME ,
ARG_SERVICE_ADDRESS ,
ARG_SERVICE_TXT ,
ARG_RAW ,
ARG_SEARCH ,
ARG_NO_PAGER ,
} ;
2014-07-16 22:55:23 +02:00
2018-04-11 03:44:51 +02:00
static const struct option options [ ] = {
{ " help " , no_argument , NULL , ' h ' } ,
{ " version " , no_argument , NULL , ARG_VERSION } ,
{ " type " , required_argument , NULL , ' t ' } ,
{ " class " , required_argument , NULL , ' c ' } ,
{ " legend " , required_argument , NULL , ARG_LEGEND } ,
{ " interface " , required_argument , NULL , ' i ' } ,
{ " protocol " , required_argument , NULL , ' p ' } ,
{ " cname " , required_argument , NULL , ARG_CNAME } ,
{ " service-address " , required_argument , NULL , ARG_SERVICE_ADDRESS } ,
{ " service-txt " , required_argument , NULL , ARG_SERVICE_TXT } ,
{ " raw " , optional_argument , NULL , ARG_RAW } ,
{ " search " , required_argument , NULL , ARG_SEARCH } ,
{ " no-pager " , no_argument , NULL , ARG_NO_PAGER } ,
{ }
} ;
2014-07-16 22:55:23 +02:00
2018-04-11 03:44:51 +02:00
int c , r ;
2014-07-30 17:52:21 +02:00
2018-04-11 03:44:51 +02:00
assert ( argc > = 0 ) ;
assert ( argv ) ;
2014-07-16 22:55:23 +02:00
2018-04-11 03:44:51 +02:00
while ( ( c = getopt_long ( argc , argv , " h46i:t:c:p: " , options , NULL ) ) > = 0 )
switch ( c ) {
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
2018-04-11 03:44:51 +02:00
case ' h ' :
2018-08-09 10:32:31 +02:00
return native_help ( ) ;
2018-04-11 03:44:51 +02:00
case ARG_VERSION :
return version ( ) ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ' 4 ' :
arg_family = AF_INET ;
break ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ' 6 ' :
arg_family = AF_INET6 ;
break ;
case ' i ' :
2018-12-05 14:02:06 +01:00
r = ifname_mangle ( optarg ) ;
2018-04-11 03:44:51 +02:00
if ( r < 0 )
return r ;
break ;
case ' t ' :
if ( streq ( optarg , " help " ) ) {
help_dns_types ( ) ;
return 0 ;
}
r = dns_type_from_string ( optarg ) ;
if ( r < 0 ) {
log_error ( " Failed to parse RR record type %s " , optarg ) ;
return r ;
}
arg_type = ( uint16_t ) r ;
assert ( ( int ) arg_type = = r ) ;
break ;
case ' c ' :
if ( streq ( optarg , " help " ) ) {
help_dns_classes ( ) ;
return 0 ;
}
r = dns_class_from_string ( optarg ) ;
if ( r < 0 ) {
log_error ( " Failed to parse RR record class %s " , optarg ) ;
return r ;
}
arg_class = ( uint16_t ) r ;
assert ( ( int ) arg_class = = r ) ;
break ;
case ARG_LEGEND :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --legend= argument " ) ;
arg_legend = r ;
break ;
case ' p ' :
if ( streq ( optarg , " help " ) ) {
help_protocol_types ( ) ;
return 0 ;
} else if ( streq ( optarg , " dns " ) )
arg_flags | = SD_RESOLVED_DNS ;
else if ( streq ( optarg , " llmnr " ) )
arg_flags | = SD_RESOLVED_LLMNR ;
else if ( streq ( optarg , " llmnr-ipv4 " ) )
arg_flags | = SD_RESOLVED_LLMNR_IPV4 ;
else if ( streq ( optarg , " llmnr-ipv6 " ) )
arg_flags | = SD_RESOLVED_LLMNR_IPV6 ;
else if ( streq ( optarg , " mdns " ) )
arg_flags | = SD_RESOLVED_MDNS ;
else if ( streq ( optarg , " mdns-ipv4 " ) )
arg_flags | = SD_RESOLVED_MDNS_IPV4 ;
else if ( streq ( optarg , " mdns-ipv6 " ) )
arg_flags | = SD_RESOLVED_MDNS_IPV6 ;
2018-11-20 23:40:44 +01:00
else
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown protocol specifier: %s " ,
optarg ) ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
break ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ARG_RAW :
2018-11-20 23:40:44 +01:00
if ( on_tty ( ) )
return log_error_errno ( SYNTHETIC_ERRNO ( ENOTTY ) ,
" Refusing to write binary data to tty. " ) ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
if ( optarg = = NULL | | streq ( optarg , " payload " ) )
arg_raw = RAW_PAYLOAD ;
else if ( streq ( optarg , " packet " ) )
arg_raw = RAW_PACKET ;
2018-11-20 23:40:44 +01:00
else
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" Unknown --raw specifier \" %s \" . " ,
optarg ) ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
arg_legend = false ;
break ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ARG_CNAME :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --cname= argument. " ) ;
SET_FLAG ( arg_flags , SD_RESOLVED_NO_CNAME , r = = 0 ) ;
break ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ARG_SERVICE_ADDRESS :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --service-address= argument. " ) ;
SET_FLAG ( arg_flags , SD_RESOLVED_NO_ADDRESS , r = = 0 ) ;
break ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
case ARG_SERVICE_TXT :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --service-txt= argument. " ) ;
SET_FLAG ( arg_flags , SD_RESOLVED_NO_TXT , r = = 0 ) ;
break ;
resolved: add ResolveService() bus call for resolving SRV and DNS-SD services
This also adds client-side support for this to systemd-resolve-host.
Note that the ResolveService() API can deal both with DNS-SD service
(consisting of service name, type and domain), as well as classic SRV
services (consisting just of a type and a domain), all exposed in the
same call.
This patch also reworks CNAME handling in order to reuse it between
hostname, RR and service lookups.
In contrast to Avahi and Bonjour, this new API will actually reolve the
A/AAAA RRs the SRV RRs point to in one go (unless this is explicitly
disabled). This normally comes for free, as these RRs are sent along
the SRV responses anyway, hence let's make use of that. This makes the
API considerably easier to use, as a single ResolveService() invocation
will return all necessary data to pick a server and connect() to it.
Note that this only implements the DNS-SD resolving step, it does not
implement DNS-SD browsing, as that makes sense primarily on mDNS, due to
its continuous nature.
2015-11-23 21:25:40 +01:00
2018-04-11 03:44:51 +02:00
case ARG_SEARCH :
r = parse_boolean ( optarg ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to parse --search argument. " ) ;
SET_FLAG ( arg_flags , SD_RESOLVED_NO_SEARCH , r = = 0 ) ;
break ;
2014-07-30 17:52:21 +02:00
2018-04-11 03:44:51 +02:00
case ARG_NO_PAGER :
2018-11-11 12:56:29 +01:00
arg_pager_flags | = PAGER_DISABLE ;
2018-04-11 03:44:51 +02:00
break ;
case ' ? ' :
return - EINVAL ;
2016-01-29 00:24:27 +01:00
2018-04-11 03:44:51 +02:00
default :
assert_not_reached ( " Unhandled option " ) ;
2016-01-29 00:24:27 +01:00
}
2018-11-20 23:40:44 +01:00
if ( arg_type = = 0 & & arg_class ! = 0 )
return log_error_errno ( SYNTHETIC_ERRNO ( EINVAL ) ,
" --class= may only be used in conjunction with --type=. " ) ;
2016-01-29 00:24:27 +01:00
2018-04-11 03:44:51 +02:00
if ( arg_type ! = 0 & & arg_class = = 0 )
arg_class = DNS_CLASS_IN ;
2016-01-29 00:24:27 +01:00
2018-04-11 03:44:51 +02:00
if ( arg_class ! = 0 & & arg_type = = 0 )
arg_type = DNS_TYPE_A ;
2016-02-18 03:08:57 +01:00
2018-04-11 03:44:51 +02:00
return 1 /* work to do */ ;
}
2016-02-18 03:08:57 +01:00
2018-04-11 03:44:51 +02:00
static int native_main ( int argc , char * argv [ ] , sd_bus * bus ) {
static const Verb verbs [ ] = {
{ " help " , VERB_ANY , VERB_ANY , 0 , verb_help } ,
{ " status " , VERB_ANY , VERB_ANY , VERB_DEFAULT , verb_status } ,
{ " query " , 2 , VERB_ANY , 0 , verb_query } ,
{ " service " , 2 , 4 , 0 , verb_service } ,
{ " openpgp " , 2 , VERB_ANY , 0 , verb_openpgp } ,
{ " tlsa " , 2 , VERB_ANY , 0 , verb_tlsa } ,
{ " statistics " , VERB_ANY , 1 , 0 , show_statistics } ,
{ " reset-statistics " , VERB_ANY , 1 , 0 , reset_statistics } ,
{ " flush-caches " , VERB_ANY , 1 , 0 , flush_caches } ,
{ " reset-server-features " , VERB_ANY , 1 , 0 , reset_server_features } ,
{ " dns " , VERB_ANY , VERB_ANY , 0 , verb_dns } ,
{ " domain " , VERB_ANY , VERB_ANY , 0 , verb_domain } ,
2018-12-04 13:29:41 +01:00
{ " default-route " , VERB_ANY , 3 , 0 , verb_default_route } ,
2018-04-11 03:44:51 +02:00
{ " llmnr " , VERB_ANY , 3 , 0 , verb_llmnr } ,
{ " mdns " , VERB_ANY , 3 , 0 , verb_mdns } ,
2018-12-04 13:30:14 +01:00
{ " dnsovertls " , VERB_ANY , 3 , 0 , verb_dns_over_tls } ,
2018-04-11 03:44:51 +02:00
{ " dnssec " , VERB_ANY , 3 , 0 , verb_dnssec } ,
{ " nta " , VERB_ANY , VERB_ANY , 0 , verb_nta } ,
2018-12-05 13:58:34 +01:00
{ " revert " , VERB_ANY , 2 , 0 , verb_revert_link } ,
2020-04-20 11:02:39 +02:00
{ " log-level " , VERB_ANY , 2 , 0 , verb_log_level } ,
2018-04-11 03:44:51 +02:00
{ }
} ;
2016-02-18 03:08:57 +01:00
2018-04-11 03:44:51 +02:00
return dispatch_verb ( argc , argv , verbs , bus ) ;
}
2016-02-18 03:08:57 +01:00
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
static int translate ( const char * verb , const char * single_arg , size_t num_args , char * * args , sd_bus * bus ) {
2018-04-11 03:44:51 +02:00
char * * fake , * * p ;
2020-06-02 17:46:58 +02:00
size_t num ;
2014-07-16 22:55:23 +02:00
2018-04-11 03:44:51 +02:00
assert ( verb ) ;
assert ( num_args = = 0 | | args ) ;
2015-12-23 19:06:36 +01:00
2018-04-11 03:44:51 +02:00
num = ! ! single_arg + num_args + 1 ;
2014-07-30 17:52:21 +02:00
2018-04-11 03:44:51 +02:00
p = fake = newa0 ( char * , num + 1 ) ;
* p + + = ( char * ) verb ;
if ( single_arg )
* p + + = ( char * ) single_arg ;
2020-06-02 17:46:58 +02:00
for ( size_t i = 0 ; i < num_args ; i + + )
2018-04-11 03:44:51 +02:00
* p + + = args [ i ] ;
2016-06-10 20:40:30 +02:00
2018-04-11 03:44:51 +02:00
optind = 0 ;
tree-wide: be more careful with the type of array sizes
Previously we were a bit sloppy with the index and size types of arrays,
we'd regularly use unsigned. While I don't think this ever resulted in
real issues I think we should be more careful there and follow a
stricter regime: unless there's a strong reason not to use size_t for
array sizes and indexes, size_t it should be. Any allocations we do
ultimately will use size_t anyway, and converting forth and back between
unsigned and size_t will always be a source of problems.
Note that on 32bit machines "unsigned" and "size_t" are equivalent, and
on 64bit machines our arrays shouldn't grow that large anyway, and if
they do we have a problem, however that kind of overly large allocation
we have protections for usually, but for overflows we do not have that
so much, hence let's add it.
So yeah, it's a story of the current code being already "good enough",
but I think some extra type hygiene is better.
This patch tries to be comprehensive, but it probably isn't and I missed
a few cases. But I guess we can cover that later as we notice it. Among
smaller fixes, this changes:
1. strv_length()' return type becomes size_t
2. the unit file changes array size becomes size_t
3. DNS answer and query array sizes become size_t
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=76745
2018-04-27 14:09:31 +02:00
return native_main ( ( int ) num , fake , bus ) ;
2018-04-11 03:44:51 +02:00
}
2016-06-10 20:40:30 +02:00
2018-04-11 03:44:51 +02:00
static int compat_main ( int argc , char * argv [ ] , sd_bus * bus ) {
int r = 0 ;
2016-06-15 21:43:36 +02:00
2018-04-11 03:44:51 +02:00
switch ( arg_mode ) {
case MODE_RESOLVE_HOST :
case MODE_RESOLVE_RECORD :
return translate ( " query " , NULL , argc - optind , argv + optind , bus ) ;
2017-09-29 21:19:54 +02:00
2018-04-11 03:44:51 +02:00
case MODE_RESOLVE_SERVICE :
return translate ( " service " , NULL , argc - optind , argv + optind , bus ) ;
2017-09-29 21:19:54 +02:00
2018-04-11 03:44:51 +02:00
case MODE_RESOLVE_OPENPGP :
return translate ( " openpgp " , NULL , argc - optind , argv + optind , bus ) ;
2016-06-15 21:43:36 +02:00
2018-04-11 03:44:51 +02:00
case MODE_RESOLVE_TLSA :
return translate ( " tlsa " , arg_service_family , argc - optind , argv + optind , bus ) ;
2016-06-15 21:43:36 +02:00
2018-04-11 03:44:51 +02:00
case MODE_STATISTICS :
return translate ( " statistics " , NULL , 0 , NULL , bus ) ;
case MODE_RESET_STATISTICS :
return translate ( " reset-statistics " , NULL , 0 , NULL , bus ) ;
case MODE_FLUSH_CACHES :
return translate ( " flush-caches " , NULL , 0 , NULL , bus ) ;
case MODE_RESET_SERVER_FEATURES :
return translate ( " reset-server-features " , NULL , 0 , NULL , bus ) ;
2016-06-15 21:43:36 +02:00
2018-04-11 03:44:51 +02:00
case MODE_STATUS :
return translate ( " status " , NULL , argc - optind , argv + optind , bus ) ;
2017-12-14 20:13:14 +01:00
case MODE_SET_LINK :
2018-06-26 09:41:22 +02:00
assert ( arg_ifname ) ;
2018-04-11 03:44:51 +02:00
if ( arg_set_dns ) {
r = translate ( " dns " , arg_ifname , strv_length ( arg_set_dns ) , arg_set_dns , bus ) ;
if ( r < 0 )
return r ;
}
if ( arg_set_domain ) {
r = translate ( " domain " , arg_ifname , strv_length ( arg_set_domain ) , arg_set_domain , bus ) ;
if ( r < 0 )
return r ;
2017-12-14 20:13:14 +01:00
}
2018-04-11 03:44:51 +02:00
if ( arg_set_nta ) {
r = translate ( " nta " , arg_ifname , strv_length ( arg_set_nta ) , arg_set_nta , bus ) ;
if ( r < 0 )
return r ;
}
2017-12-14 20:13:14 +01:00
2018-04-11 03:44:51 +02:00
if ( arg_set_llmnr ) {
r = translate ( " llmnr " , arg_ifname , 1 , ( char * * ) & arg_set_llmnr , bus ) ;
if ( r < 0 )
return r ;
}
if ( arg_set_mdns ) {
r = translate ( " mdns " , arg_ifname , 1 , ( char * * ) & arg_set_mdns , bus ) ;
if ( r < 0 )
return r ;
}
2018-06-13 20:26:24 +02:00
if ( arg_set_dns_over_tls ) {
r = translate ( " dnsovertls " , arg_ifname , 1 , ( char * * ) & arg_set_dns_over_tls , bus ) ;
2018-05-04 17:31:16 +02:00
if ( r < 0 )
return r ;
}
2018-04-11 03:44:51 +02:00
if ( arg_set_dnssec ) {
r = translate ( " dnssec " , arg_ifname , 1 , ( char * * ) & arg_set_dnssec , bus ) ;
if ( r < 0 )
return r ;
2017-12-14 20:13:14 +01:00
}
2018-04-11 03:44:51 +02:00
return r ;
case MODE_REVERT_LINK :
2018-06-26 09:41:22 +02:00
assert ( arg_ifname ) ;
2018-04-11 03:44:51 +02:00
return translate ( " revert " , arg_ifname , 0 , NULL , bus ) ;
2018-02-27 17:48:54 +01:00
case _MODE_INVALID :
assert_not_reached ( " invalid mode " ) ;
2014-07-16 22:55:23 +02:00
}
2018-04-11 03:44:51 +02:00
return 0 ;
}
2018-11-22 22:00:02 +01:00
static int run ( int argc , char * * argv ) {
_cleanup_ ( sd_bus_flush_close_unrefp ) sd_bus * bus = NULL ;
2018-04-11 03:44:51 +02:00
int r ;
setlocale ( LC_ALL , " " ) ;
2020-06-17 21:17:54 +02:00
log_setup_cli ( ) ;
2018-04-11 03:44:51 +02:00
if ( streq ( program_invocation_short_name , " resolvconf " ) )
r = resolvconf_parse_argv ( argc , argv ) ;
else if ( streq ( program_invocation_short_name , " systemd-resolve " ) )
r = compat_parse_argv ( argc , argv ) ;
else
r = native_parse_argv ( argc , argv ) ;
if ( r < = 0 )
2018-11-22 22:00:02 +01:00
return r ;
2018-04-11 03:44:51 +02:00
r = sd_bus_open_system ( & bus ) ;
2018-11-22 22:00:02 +01:00
if ( r < 0 )
return log_error_errno ( r , " sd_bus_open_system: %m " ) ;
2018-04-11 03:44:51 +02:00
2018-06-26 03:07:48 +02:00
if ( STR_IN_SET ( program_invocation_short_name , " systemd-resolve " , " resolvconf " ) )
2018-11-22 22:00:02 +01:00
return compat_main ( argc , argv , bus ) ;
2016-06-15 21:43:36 +02:00
2018-11-22 22:00:02 +01:00
return native_main ( argc , argv , bus ) ;
2014-07-16 22:55:23 +02:00
}
2018-11-22 22:00:02 +01:00
DEFINE_MAIN_FUNCTION ( run ) ;