Compare commits
11 Commits
cf72f7f116
...
a15e7eb9e0
Author | SHA1 | Date |
---|---|---|
Vishal Chillara | a15e7eb9e0 | |
Winterhuman | 5bed97dd57 | |
Luca Boccassi | c4d7a13c06 | |
Abderrahim Kitouni | 0ae6f4843e | |
Frantisek Sumsal | c922c19d0e | |
Vishal Chillara Srinivas | 49c4cc2b8f | |
Vishal Chillara Srinivas | 28efd46614 | |
Vishal Chillara Srinivas | dfcc54ac15 | |
Yu Watanabe | 1ea1a79aa1 | |
Luca Boccassi | 7a9d0abe4d | |
Yu Watanabe | 6046cc3660 |
|
@ -684,6 +684,15 @@ fi</programlisting>
|
||||||
<citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
<citerefentry><refentrytitle>file-hierarchy</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
All example codes in this page are licensed under <literal>MIT No Attribution</literal>
|
||||||
|
(SPDX-License-Identifier: MIT-0).
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
<para><simplelist type="inline">
|
<para><simplelist type="inline">
|
||||||
|
|
|
@ -302,7 +302,7 @@
|
||||||
and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of
|
and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of
|
||||||
the per-unit setting of the same name, see
|
the per-unit setting of the same name, see
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
details: currently, the <literal>full</literal> or <literal>struct</literal> values are not
|
details: currently, the <literal>full</literal> or <literal>strict</literal> values are not
|
||||||
supported.</para>
|
supported.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "format-util.h"
|
#include "format-util.h"
|
||||||
#include "hexdecoct.h"
|
#include "hexdecoct.h"
|
||||||
|
#include "iovec-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
@ -31,8 +32,7 @@ int decrypt_pkcs11_key(
|
||||||
const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */
|
const char *key_file, /* We either expect key_file and associated parameters to be set (for file keys) … */
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data, /* … or key_data and key_data_size (for literal keys) */
|
const struct iovec *key_data, /* … or literal keys via key_data */
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
AskPasswordFlags askpw_flags,
|
AskPasswordFlags askpw_flags,
|
||||||
void **ret_decrypted_key,
|
void **ret_decrypted_key,
|
||||||
|
@ -47,15 +47,15 @@ int decrypt_pkcs11_key(
|
||||||
|
|
||||||
assert(friendly_name);
|
assert(friendly_name);
|
||||||
assert(pkcs11_uri);
|
assert(pkcs11_uri);
|
||||||
assert(key_file || key_data);
|
assert(key_file || iovec_is_set(key_data));
|
||||||
assert(ret_decrypted_key);
|
assert(ret_decrypted_key);
|
||||||
assert(ret_decrypted_key_size);
|
assert(ret_decrypted_key_size);
|
||||||
|
|
||||||
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
|
/* The functions called here log about all errors, except for EAGAIN which means "token not found right now" */
|
||||||
|
|
||||||
if (key_data) {
|
if (iovec_is_set(key_data)) {
|
||||||
data.encrypted_key = (void*) key_data;
|
data.encrypted_key = (void*) key_data->iov_base;
|
||||||
data.encrypted_key_size = key_data_size;
|
data.encrypted_key_size = key_data->iov_len;
|
||||||
|
|
||||||
data.free_encrypted_key = false;
|
data.free_encrypted_key = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,8 +16,7 @@ int decrypt_pkcs11_key(
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
AskPasswordFlags askpw_flags,
|
AskPasswordFlags askpw_flags,
|
||||||
void **ret_decrypted_key,
|
void **ret_decrypted_key,
|
||||||
|
@ -39,8 +38,7 @@ static inline int decrypt_pkcs11_key(
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
AskPasswordFlags askpw_flags,
|
AskPasswordFlags askpw_flags,
|
||||||
void **ret_decrypted_key,
|
void **ret_decrypted_key,
|
||||||
|
|
|
@ -1471,8 +1471,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||||
struct crypt_device *cd,
|
struct crypt_device *cd,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
bool pass_volume_key) {
|
bool pass_volume_key) {
|
||||||
|
@ -1489,7 +1488,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(arg_fido2_device || arg_fido2_device_auto);
|
assert(arg_fido2_device || arg_fido2_device_auto);
|
||||||
|
|
||||||
if (arg_fido2_cid && !key_file && !key_data)
|
if (arg_fido2_cid && !key_file && !iovec_is_set(key_data))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
|
"FIDO2 mode with manual parameters selected, but no keyfile specified, refusing.");
|
||||||
|
|
||||||
|
@ -1513,7 +1512,7 @@ static int attach_luks_or_plain_or_bitlk_by_fido2(
|
||||||
arg_fido2_rp_id,
|
arg_fido2_rp_id,
|
||||||
arg_fido2_cid, arg_fido2_cid_size,
|
arg_fido2_cid, arg_fido2_cid_size,
|
||||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||||
key_data, key_data_size,
|
key_data,
|
||||||
until,
|
until,
|
||||||
arg_fido2_manual_flags,
|
arg_fido2_manual_flags,
|
||||||
"cryptsetup.fido2-pin",
|
"cryptsetup.fido2-pin",
|
||||||
|
@ -1623,8 +1622,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||||
struct crypt_device *cd,
|
struct crypt_device *cd,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
bool pass_volume_key) {
|
bool pass_volume_key) {
|
||||||
|
@ -1635,6 +1633,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||||
_cleanup_free_ void *discovered_key = NULL;
|
_cleanup_free_ void *discovered_key = NULL;
|
||||||
|
struct iovec discovered_key_data = {};
|
||||||
int keyslot = arg_key_slot, r;
|
int keyslot = arg_key_slot, r;
|
||||||
const char *uri = NULL;
|
const char *uri = NULL;
|
||||||
bool use_libcryptsetup_plugin = use_token_plugins();
|
bool use_libcryptsetup_plugin = use_token_plugins();
|
||||||
|
@ -1653,13 +1652,13 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
uri = discovered_uri;
|
uri = discovered_uri;
|
||||||
key_data = discovered_key;
|
discovered_key_data = IOVEC_MAKE(discovered_key, discovered_key_size);
|
||||||
key_data_size = discovered_key_size;
|
key_data = &discovered_key_data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uri = arg_pkcs11_uri;
|
uri = arg_pkcs11_uri;
|
||||||
|
|
||||||
if (!key_file && !key_data)
|
if (!key_file && !iovec_is_set(key_data))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "PKCS#11 mode selected but no key file specified, refusing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1682,7 +1681,7 @@ static int attach_luks_or_plain_or_bitlk_by_pkcs11(
|
||||||
friendly,
|
friendly,
|
||||||
uri,
|
uri,
|
||||||
key_file, arg_keyfile_size, arg_keyfile_offset,
|
key_file, arg_keyfile_size, arg_keyfile_offset,
|
||||||
key_data, key_data_size,
|
key_data,
|
||||||
until,
|
until,
|
||||||
arg_ask_password_flags,
|
arg_ask_password_flags,
|
||||||
&decrypted_key, &decrypted_key_size);
|
&decrypted_key, &decrypted_key_size);
|
||||||
|
@ -2231,9 +2230,9 @@ static int attach_luks_or_plain_or_bitlk(
|
||||||
if (token_type == TOKEN_TPM2)
|
if (token_type == TOKEN_TPM2)
|
||||||
return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key);
|
return attach_luks_or_plain_or_bitlk_by_tpm2(cd, name, key_file, key_data, until, flags, pass_volume_key);
|
||||||
if (token_type == TOKEN_FIDO2)
|
if (token_type == TOKEN_FIDO2)
|
||||||
return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key);
|
return attach_luks_or_plain_or_bitlk_by_fido2(cd, name, key_file, key_data, until, flags, pass_volume_key);
|
||||||
if (token_type == TOKEN_PKCS11)
|
if (token_type == TOKEN_PKCS11)
|
||||||
return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data->iov_base, key_data->iov_len, until, flags, pass_volume_key);
|
return attach_luks_or_plain_or_bitlk_by_pkcs11(cd, name, key_file, key_data, until, flags, pass_volume_key);
|
||||||
if (key_data)
|
if (key_data)
|
||||||
return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key);
|
return attach_luks_or_plain_or_bitlk_by_key_data(cd, name, key_data, flags, pass_volume_key);
|
||||||
if (key_file)
|
if (key_file)
|
||||||
|
|
|
@ -1858,7 +1858,7 @@ static int bus_method_reset_server_features(sd_bus_message *message, void *userd
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) {
|
static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) {
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
|
|
||||||
|
@ -1870,11 +1870,11 @@ static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) {
|
||||||
|
|
||||||
static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||||
_cleanup_(dnssd_service_freep) DnssdService *service = NULL;
|
_cleanup_(dnssd_service_freep) DnssdRegisteredService *service = NULL;
|
||||||
_cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
|
_cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
|
||||||
const char *id, *name_template, *type;
|
const char *id, *name_template, *type;
|
||||||
_cleanup_free_ char *path = NULL;
|
_cleanup_free_ char *path = NULL;
|
||||||
DnssdService *s = NULL;
|
DnssdRegisteredService *s = NULL;
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
uid_t euid;
|
uid_t euid;
|
||||||
int r;
|
int r;
|
||||||
|
@ -1884,7 +1884,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
|
||||||
if (m->mdns_support != RESOLVE_SUPPORT_YES)
|
if (m->mdns_support != RESOLVE_SUPPORT_YES)
|
||||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
|
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
|
||||||
|
|
||||||
service = new0(DnssdService, 1);
|
service = new0(DnssdRegisteredService, 1);
|
||||||
if (!service)
|
if (!service)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -2046,7 +2046,7 @@ static int bus_method_register_service(sd_bus_message *message, void *userdata,
|
||||||
|
|
||||||
static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
|
static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
|
||||||
_cleanup_free_ char *name = NULL;
|
_cleanup_free_ char *name = NULL;
|
||||||
DnssdService *s = NULL;
|
DnssdRegisteredService *s = NULL;
|
||||||
const char *path;
|
const char *path;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|
|
@ -1,76 +1,81 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "resolved-dns-browse-services.h"
|
||||||
#include "af-list.h"
|
#include "af-list.h"
|
||||||
#include "event-util.h"
|
#include "event-util.h"
|
||||||
#include "json-util.h"
|
#include "json-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
#include "resolved-dns-browse-services.h"
|
|
||||||
#include "resolved-dns-cache.h"
|
#include "resolved-dns-cache.h"
|
||||||
#include "resolved-varlink.h"
|
#include "resolved-varlink.h"
|
||||||
|
#include "string-table.h"
|
||||||
|
|
||||||
|
typedef enum BrowseServiceUpdateFlag {
|
||||||
|
BROWSE_SERVICE_UPDATE_ADDED,
|
||||||
|
BROWSE_SERVICE_UPDATE_REMOVED,
|
||||||
|
_BROWSE_SERVICE_UPDATE_MAX,
|
||||||
|
_BROWSE_SERVICE_UPDATE_INVALID = -EINVAL,
|
||||||
|
} BrowseServiceUpdateFlag;
|
||||||
|
|
||||||
|
static const char * const browse_service_update_flag_table[_BROWSE_SERVICE_UPDATE_MAX] = {
|
||||||
|
[BROWSE_SERVICE_UPDATE_ADDED] = "added",
|
||||||
|
[BROWSE_SERVICE_UPDATE_REMOVED] = "removed",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(browse_service_update_flag, BrowseServiceUpdateFlag);
|
||||||
|
|
||||||
/* RFC 6762 section 5.2 - The querier should plan to issue a query at 80% of
|
/* RFC 6762 section 5.2 - The querier should plan to issue a query at 80% of
|
||||||
* the record lifetime, and then if no answer is received, at 85%, 90%, and 95%. */
|
* the record lifetime, and then if no answer is received, at 85%, 90%, and 95%.
|
||||||
static usec_t mdns_maintenance_next_time(usec_t until, uint32_t ttl, int ttl_state) {
|
*/
|
||||||
|
static usec_t mdns_maintenance_next_time(usec_t until, uint32_t ttl, DnsRecordTTLState ttl_state) {
|
||||||
|
assert(ttl_state >= DNS_RECORD_TTL_STATE_80_PERCENT);
|
||||||
|
assert(ttl_state <= _DNS_RECORD_TTL_STATE_MAX);
|
||||||
|
|
||||||
return usec_sub_unsigned(until, (20 - ttl_state * 5) * ttl * USEC_PER_SEC / 100);
|
return usec_sub_unsigned(until, (20 - ttl_state * 5) * ttl * USEC_PER_SEC / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RFC 6762 section 5.2 - A random variation of 2% of the record TTL should
|
/* RFC 6762 section 5.2 - A random variation of 2% of the record TTL should
|
||||||
* be added to maintenance queries. */
|
* be added to maintenance queries. */
|
||||||
static usec_t mdns_maintenance_jitter(uint32_t ttl) {
|
static usec_t mdns_maintenance_jitter(uint32_t ttl) {
|
||||||
return random_u64_range(100) * 2 * ttl * USEC_PER_SEC / 10000;
|
return random_u64_range(2 * ttl * USEC_PER_SEC / 100);
|
||||||
}
|
|
||||||
|
|
||||||
#define MDNS_80_PERCENT 80
|
|
||||||
#define MDNS_5_PERCENT 5
|
|
||||||
|
|
||||||
static void mdns_find_service_from_query(DnsService **service, DnsServiceBrowser *sb, DnsQuery *q) {
|
|
||||||
assert(sb);
|
|
||||||
|
|
||||||
/* Find the service that owns the query. */
|
|
||||||
LIST_FOREACH(dns_services, s, sb->dns_services) {
|
|
||||||
if (s->query == q) {
|
|
||||||
*service = s;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*service = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mdns_maintenance_query_complete(DnsQuery *q) {
|
static void mdns_maintenance_query_complete(DnsQuery *q) {
|
||||||
_cleanup_(dns_service_browser_unrefp) DnsServiceBrowser *sb = NULL;
|
_cleanup_(dns_service_browser_unrefp) DnsServiceBrowser *sb = NULL;
|
||||||
_cleanup_(dns_query_freep) DnsQuery *query = q;
|
_cleanup_(dns_query_freep) DnsQuery *query = q;
|
||||||
DnsService *service = NULL;
|
DnssdDiscoveredService *service = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(query);
|
assert(query);
|
||||||
assert(query->manager);
|
assert(query->manager);
|
||||||
|
|
||||||
sb = dns_service_browser_ref(hashmap_get(query->manager->dns_service_browsers, query->varlink_request));
|
if (query->state != DNS_TRANSACTION_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
service = dns_service_ref(query->dnsservice_request);
|
||||||
|
|
||||||
|
if (!service)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sb = dns_service_browser_ref(service->service_browser);
|
||||||
|
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (query->state != DNS_TRANSACTION_SUCCESS) {
|
r = dns_answer_match_key(query->answer, sb->key, NULL);
|
||||||
r = 0;
|
if (r <= 0) {
|
||||||
goto finish;
|
log_error_errno(r, "mDNS answer does not match service browser key: %m");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dns_answer_match_key(query->answer, sb->key, NULL);
|
r = mdns_browser_revisit_cache(sb, query->answer_family);
|
||||||
if (r <= 0)
|
if (r < 0) {
|
||||||
goto finish;
|
log_error_errno(r, "Failed to mDNS revisit cache for family %d: %m", query->answer_family);
|
||||||
|
return;
|
||||||
r = mdns_browser_lookup_cache(sb, query->answer_family);
|
}
|
||||||
|
|
||||||
finish:
|
|
||||||
if (r < 0)
|
|
||||||
log_error_errno(r, "mDNS maintenance query complete failed: %m");
|
|
||||||
|
|
||||||
mdns_find_service_from_query(&service, sb, query);
|
|
||||||
if (service)
|
|
||||||
service->query = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdns_maintenance_query(sd_event_source *s, uint64_t usec, void *userdata) {
|
static int mdns_maintenance_query(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||||
DnsService *service = NULL;
|
DnssdDiscoveredService *service = NULL;
|
||||||
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
|
_cleanup_(dns_query_freep) DnsQuery *q = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -78,132 +83,155 @@ static int mdns_maintenance_query(sd_event_source *s, uint64_t usec, void *userd
|
||||||
|
|
||||||
service = userdata;
|
service = userdata;
|
||||||
|
|
||||||
if (service->rr_ttl_state++ == MDNS_TTL_100_PERCENT)
|
/* Check if the TTL state has reached the maximum value, then revisit
|
||||||
return mdns_browser_lookup_cache(service->sb, service->family);
|
* cache */
|
||||||
|
if (service->rr_ttl_state++ == _DNS_RECORD_TTL_STATE_MAX)
|
||||||
|
return mdns_browser_revisit_cache(service->service_browser, service->family);
|
||||||
|
|
||||||
r = dns_query_new(service->sb->m, &q, service->sb->question_utf8, service->sb->question_idna, NULL, service->sb->ifindex, service->sb->flags);
|
/* Create a new DNS query */
|
||||||
|
r = dns_query_new(
|
||||||
|
service->service_browser->manager,
|
||||||
|
&q,
|
||||||
|
service->service_browser->question_utf8,
|
||||||
|
service->service_browser->question_idna,
|
||||||
|
/* question_bypass= */ NULL,
|
||||||
|
service->service_browser->ifindex,
|
||||||
|
service->service_browser->flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to create mDNS query for maintenance: %m");
|
||||||
|
|
||||||
q->complete = mdns_maintenance_query_complete;
|
q->complete = mdns_maintenance_query_complete;
|
||||||
q->varlink_request = sd_varlink_ref(service->sb->link);
|
q->varlink_request = sd_varlink_ref(service->service_browser->link);
|
||||||
service->query = TAKE_PTR(q);
|
q->dnsservice_request = dns_service_ref(service);
|
||||||
|
|
||||||
|
/* Schedule the next maintenance query based on the TTL */
|
||||||
usec_t next_time = mdns_maintenance_next_time(service->until, service->rr->ttl, service->rr_ttl_state);
|
usec_t next_time = mdns_maintenance_next_time(service->until, service->rr->ttl, service->rr_ttl_state);
|
||||||
|
|
||||||
/* Schedule next maintenance query for service */
|
|
||||||
r = event_reset_time(
|
r = event_reset_time(
|
||||||
service->sb->m->event, &service->schedule_event,
|
service->service_browser->manager->event,
|
||||||
CLOCK_BOOTTIME, next_time, 0, mdns_maintenance_query,
|
&service->schedule_event,
|
||||||
service, 0, "mdns-next-query-schedule", true);
|
CLOCK_BOOTTIME,
|
||||||
|
next_time,
|
||||||
|
/* accuracy= */ 0,
|
||||||
|
mdns_maintenance_query,
|
||||||
|
service,
|
||||||
|
/* priority= */ 0,
|
||||||
|
"mdns-next-query-schedule",
|
||||||
|
/* force_reset= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to schedule next mDNS maintenance query: %m");
|
||||||
|
|
||||||
r = dns_query_go(service->query);
|
/* Perform the query */
|
||||||
|
r = dns_query_go(q);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to send mDNS maintenance query: %m");
|
||||||
|
|
||||||
|
TAKE_PTR(q);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
dns_query_free(service->query);
|
|
||||||
return log_error_errno(r, "Failed mdns maintenance query: %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_family) {
|
int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_family) {
|
||||||
_cleanup_(dns_service_unrefp) DnsService *s = NULL;
|
_cleanup_(dns_service_unrefp) DnssdDiscoveredService *s = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(sb);
|
assert(sb);
|
||||||
assert(rr);
|
assert(rr);
|
||||||
|
|
||||||
s = new(DnsService, 1);
|
s = new (DnssdDiscoveredService, 1);
|
||||||
if (!s)
|
if (!s) {
|
||||||
return log_oom();
|
log_oom();
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
usec_t usec = now(CLOCK_BOOTTIME);
|
usec_t usec = now(CLOCK_BOOTTIME);
|
||||||
|
|
||||||
*s = (DnsService) {
|
*s = (DnssdDiscoveredService) {
|
||||||
.n_ref = 1,
|
.n_ref = 1,
|
||||||
.sb = dns_service_browser_ref(sb),
|
.service_browser = sb,
|
||||||
.rr = dns_resource_record_copy(rr),
|
.rr = dns_resource_record_copy(rr),
|
||||||
.family = owner_family,
|
.family = owner_family,
|
||||||
.until = rr->until,
|
.until = rr->until,
|
||||||
.query = NULL,
|
.query = NULL,
|
||||||
.rr_ttl_state = MDNS_TTL_80_PERCENT,
|
.rr_ttl_state = DNS_RECORD_TTL_STATE_80_PERCENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_PREPEND(dns_services, sb->dns_services, s);
|
LIST_PREPEND(dns_services, sb->dns_services, s);
|
||||||
|
|
||||||
/* Schedule the first cache maintenance query at 80% of the record's TTL.
|
/* Schedule the first cache maintenance query at 80% of the record's
|
||||||
* Subsequent queries issued at 5% increments until 100% of the TTL. RFC 6762 section 5.2.
|
* TTL. Subsequent queries issued at 5% increments until 100% of the
|
||||||
* If service is being added after 80% of the TTL has already elapsed,
|
* TTL. RFC 6762 section 5.2. If service is being added after 80% of the
|
||||||
* schedule the next query at the next 5% increment. */
|
* TTL has already elapsed, schedule the next query at the next 5%
|
||||||
|
* increment. */
|
||||||
usec_t next_time = 0;
|
usec_t next_time = 0;
|
||||||
while (s->rr_ttl_state <= MDNS_TTL_100_PERCENT) {
|
while (s->rr_ttl_state >= DNS_RECORD_TTL_STATE_80_PERCENT &&
|
||||||
|
s->rr_ttl_state <= _DNS_RECORD_TTL_STATE_MAX) {
|
||||||
next_time = mdns_maintenance_next_time(rr->until, rr->ttl, s->rr_ttl_state);
|
next_time = mdns_maintenance_next_time(rr->until, rr->ttl, s->rr_ttl_state);
|
||||||
if (next_time >= usec)
|
if (next_time >= usec)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
s->rr_ttl_state++;
|
s->rr_ttl_state++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_time < usec) {
|
if (next_time < usec) {
|
||||||
/* If next_time is still in the past, the service is being added after it has already expired.
|
/* If next_time is still in the past, the service is being added
|
||||||
* Just schedule a 100% maintenance query */
|
* after it has already expired. Just schedule a 100%
|
||||||
|
* maintenance query */
|
||||||
next_time = usec + USEC_PER_SEC;
|
next_time = usec + USEC_PER_SEC;
|
||||||
s->rr_ttl_state = MDNS_TTL_100_PERCENT;
|
s->rr_ttl_state = _DNS_RECORD_TTL_STATE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
usec_t jitter = mdns_maintenance_jitter(rr->ttl);
|
usec_t jitter = mdns_maintenance_jitter(rr->ttl);
|
||||||
|
|
||||||
r = sd_event_add_time(
|
r = sd_event_add_time(
|
||||||
sb->m->event,
|
sb->manager->event,
|
||||||
&s->schedule_event,
|
&s->schedule_event,
|
||||||
CLOCK_BOOTTIME,
|
CLOCK_BOOTTIME,
|
||||||
usec_add(next_time, jitter),
|
usec_add(next_time, jitter),
|
||||||
0,
|
/* accuracy= */ 0,
|
||||||
mdns_maintenance_query,
|
mdns_maintenance_query,
|
||||||
s);
|
s);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
return r;
|
return log_error_errno(
|
||||||
|
r,
|
||||||
|
"Failed to schedule mDNS maintenance query "
|
||||||
|
"for DNS service: %m");
|
||||||
|
}
|
||||||
TAKE_PTR(s);
|
TAKE_PTR(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dns_remove_service(DnsServiceBrowser *sb, DnsService *service) {
|
void dns_remove_service(DnsServiceBrowser *sb, DnssdDiscoveredService *service) {
|
||||||
assert(sb);
|
assert(sb);
|
||||||
assert(service);
|
assert(service);
|
||||||
|
|
||||||
LIST_REMOVE(dns_services, sb->dns_services, service);
|
LIST_REMOVE(dns_services, sb->dns_services, service);
|
||||||
dns_service_free(service);
|
dns_service_unref(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
DnsService *dns_service_free(DnsService *service) {
|
DnssdDiscoveredService *dns_service_free(DnssdDiscoveredService *service) {
|
||||||
if (!service)
|
if (!service)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
sd_event_source_disable_unref(service->schedule_event);
|
sd_event_source_disable_unref(service->schedule_event);
|
||||||
|
|
||||||
if (service->query && DNS_TRANSACTION_IS_LIVE(service->query->state))
|
if (service->query && DNS_TRANSACTION_IS_LIVE(service->query->state))
|
||||||
dns_query_complete(service->query, DNS_TRANSACTION_ABORTED);
|
dns_query_complete(service->query, DNS_TRANSACTION_ABORTED);
|
||||||
|
|
||||||
dns_service_browser_unref(service->sb);
|
|
||||||
|
|
||||||
dns_resource_record_unref(service->rr);
|
dns_resource_record_unref(service->rr);
|
||||||
|
|
||||||
return mfree(service);
|
return mfree(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsService, dns_service, dns_service_free);
|
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnssdDiscoveredService, dns_service, dns_service_free);
|
||||||
|
|
||||||
int mdns_service_update(DnsService *service, DnsResourceRecord *rr, usec_t t) {
|
int mdns_service_update(DnssdDiscoveredService *service, DnsResourceRecord *rr, usec_t t) {
|
||||||
service->until = rr->until;
|
service->until = rr->until;
|
||||||
service->rr->ttl = rr->ttl;
|
service->rr->ttl = rr->ttl;
|
||||||
|
|
||||||
/* Update the 80% TTL maintenance event based on new record received from the network.
|
/* Update the 80% TTL maintenance event based on new record received
|
||||||
* RFC 6762 section 5.2 */
|
* from the network. RFC 6762 section 5.2 */
|
||||||
usec_t next_time = mdns_maintenance_next_time(service->until, service->rr->ttl, MDNS_TTL_80_PERCENT);
|
usec_t next_time = mdns_maintenance_next_time(
|
||||||
|
service->until, service->rr->ttl, DNS_RECORD_TTL_STATE_80_PERCENT);
|
||||||
usec_t jitter = mdns_maintenance_jitter(service->rr->ttl);
|
usec_t jitter = mdns_maintenance_jitter(service->rr->ttl);
|
||||||
|
|
||||||
if (service->schedule_event)
|
if (service->schedule_event)
|
||||||
|
@ -212,7 +240,7 @@ int mdns_service_update(DnsService *service, DnsResourceRecord *rr, usec_t t) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dns_service_contains(DnsService *services, DnsResourceRecord *rr, int owner_family) {
|
bool dns_service_contains(DnssdDiscoveredService *services, DnsResourceRecord *rr, int owner_family) {
|
||||||
usec_t t = now(CLOCK_BOOTTIME);
|
usec_t t = now(CLOCK_BOOTTIME);
|
||||||
|
|
||||||
LIST_FOREACH(dns_services, service, services)
|
LIST_FOREACH(dns_services, service, services)
|
||||||
|
@ -232,7 +260,7 @@ bool dns_service_contains(DnsService *services, DnsResourceRecord *rr, int owner
|
||||||
void dns_browse_services_purge(Manager *m, int family) {
|
void dns_browse_services_purge(Manager *m, int family) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
/* Called after caches are flused.
|
/* Called after caches are flushed.
|
||||||
* Clear local service records and notify varlink client. */
|
* Clear local service records and notify varlink client. */
|
||||||
if (!(m && m->dns_service_browsers))
|
if (!(m && m->dns_service_browsers))
|
||||||
return;
|
return;
|
||||||
|
@ -240,28 +268,31 @@ void dns_browse_services_purge(Manager *m, int family) {
|
||||||
DnsServiceBrowser *sb;
|
DnsServiceBrowser *sb;
|
||||||
HASHMAP_FOREACH(sb, m->dns_service_browsers) {
|
HASHMAP_FOREACH(sb, m->dns_service_browsers) {
|
||||||
r = sd_event_source_set_enabled(sb->schedule_event, SD_EVENT_OFF);
|
r = sd_event_source_set_enabled(sb->schedule_event, SD_EVENT_OFF);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
goto finish;
|
log_error_errno(r, "Failed to disable event source for service browser: %m");
|
||||||
|
|
||||||
if (family == AF_UNSPEC) {
|
|
||||||
r = mdns_browser_lookup_cache(sb, AF_INET);
|
|
||||||
if (r < 0)
|
|
||||||
goto finish;
|
|
||||||
r = mdns_browser_lookup_cache(sb, AF_INET6);
|
|
||||||
if (r < 0)
|
|
||||||
goto finish;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = mdns_browser_lookup_cache(sb, family);
|
if (family == AF_UNSPEC) {
|
||||||
if (r < 0)
|
r = mdns_browser_revisit_cache(sb, AF_INET);
|
||||||
goto finish;
|
if (r < 0) {
|
||||||
}
|
log_error_errno(r, "Failed to revisit cache for IPv4: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r = mdns_browser_revisit_cache(sb, AF_INET6);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to revisit cache for IPv6: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
finish:
|
r = mdns_browser_revisit_cache(sb, family);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
log_error_errno(r, "mdns browse services purge failed: %m");
|
log_error_errno(r, "Failed to revisit cache for family %d: %m", family);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int owner_family) {
|
int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int owner_family) {
|
||||||
|
@ -280,44 +311,61 @@ int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int ow
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dns_service_split(i->ptr.name, &name, &type, &domain);
|
r = dns_service_split(i->ptr.name, &name, &type, &domain);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to split DNS service name: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
type = mfree(type);
|
type = mfree(type);
|
||||||
domain = mfree(domain);
|
domain = mfree(domain);
|
||||||
r = dns_service_split(dns_resource_key_name(i->key), &name, &type, &domain);
|
r = dns_service_split(dns_resource_key_name(i->key), &name, &type, &domain);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to split DNS service name (fallback): %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dns_add_new_service(sb, i, owner_family);
|
r = dns_add_new_service(sb, i, owner_family);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to add new DNS service: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
log_debug("Add into the list %s, %s, %s, %s, %d",
|
log_debug("Add into the list %s, %s, %s, %s, %d",
|
||||||
strna(name),
|
strna(name),
|
||||||
strna(type),
|
strna(type),
|
||||||
strna(domain),
|
strna(domain),
|
||||||
strna(af_to_ipv4_ipv6(owner_family)),
|
strna(af_to_ipv4_ipv6(owner_family)),
|
||||||
sb->ifindex);
|
sb->ifindex);
|
||||||
|
|
||||||
r = sd_json_buildo(&entry,
|
r = sd_json_buildo(
|
||||||
SD_JSON_BUILD_PAIR("add_flag", SD_JSON_BUILD_BOOLEAN(true)),
|
&entry,
|
||||||
SD_JSON_BUILD_PAIR("family", SD_JSON_BUILD_INTEGER(owner_family)),
|
SD_JSON_BUILD_PAIR(
|
||||||
SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(name?: "")),
|
"updateFlag",
|
||||||
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type?: "")),
|
SD_JSON_BUILD_STRING(browse_service_update_flag_to_string(
|
||||||
SD_JSON_BUILD_PAIR("domain", SD_JSON_BUILD_STRING(domain?: "")),
|
BROWSE_SERVICE_UPDATE_ADDED))),
|
||||||
SD_JSON_BUILD_PAIR("interface", SD_JSON_BUILD_INTEGER(sb->ifindex)));
|
SD_JSON_BUILD_PAIR("family", SD_JSON_BUILD_INTEGER(owner_family)),
|
||||||
if (r < 0)
|
SD_JSON_BUILD_PAIR_CONDITION(
|
||||||
|
!isempty(name), "name", SD_JSON_BUILD_STRING(name)),
|
||||||
|
SD_JSON_BUILD_PAIR_CONDITION(
|
||||||
|
!isempty(type), "type", SD_JSON_BUILD_STRING(type)),
|
||||||
|
SD_JSON_BUILD_PAIR_CONDITION(
|
||||||
|
!isempty(domain), "domain", SD_JSON_BUILD_STRING(domain)),
|
||||||
|
SD_JSON_BUILD_PAIR("ifindex", SD_JSON_BUILD_INTEGER(sb->ifindex)));
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to build JSON for new service: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_json_variant_append_array(&array, entry);
|
r = sd_json_variant_append_array(&array, entry);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to append JSON entry to array: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for services removed */
|
/* Check for services removed */
|
||||||
|
@ -332,52 +380,70 @@ int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int ow
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = dns_service_split(service->rr->ptr.name, &name, &type, &domain);
|
r = dns_service_split(service->rr->ptr.name, &name, &type, &domain);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to split DNS service name from list: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
type = mfree(type);
|
type = mfree(type);
|
||||||
domain = mfree(domain);
|
domain = mfree(domain);
|
||||||
r = dns_service_split(dns_resource_key_name(service->rr->key), &name, &type, &domain);
|
r = dns_service_split(dns_resource_key_name(service->rr->key), &name, &type, &domain);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r,
|
||||||
|
"Failed to split DNS service name (fallback) from list: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_remove_service(sb, service);
|
dns_remove_service(sb, service);
|
||||||
|
|
||||||
log_debug("Remove from the list %s, %s, %s, %s, %d",
|
log_debug("Remove from the list %s, %s, %s, %s, %d",
|
||||||
strna(name),
|
strna(name),
|
||||||
strna(type),
|
strna(type),
|
||||||
strna(domain),
|
strna(domain),
|
||||||
strna(af_to_ipv4_ipv6(owner_family)),
|
strna(af_to_ipv4_ipv6(owner_family)),
|
||||||
sb->ifindex);
|
sb->ifindex);
|
||||||
|
|
||||||
r = sd_json_buildo(&entry,
|
r = sd_json_buildo(
|
||||||
SD_JSON_BUILD_PAIR("add_flag", SD_JSON_BUILD_BOOLEAN(false)),
|
&entry,
|
||||||
SD_JSON_BUILD_PAIR("family", SD_JSON_BUILD_INTEGER(owner_family)),
|
SD_JSON_BUILD_PAIR(
|
||||||
SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(name?: "")),
|
"updateFlag",
|
||||||
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type?: "")),
|
SD_JSON_BUILD_STRING(browse_service_update_flag_to_string(
|
||||||
SD_JSON_BUILD_PAIR("domain", SD_JSON_BUILD_STRING(domain?: "")),
|
BROWSE_SERVICE_UPDATE_REMOVED))),
|
||||||
SD_JSON_BUILD_PAIR("interface", SD_JSON_BUILD_INTEGER(sb->ifindex)));
|
SD_JSON_BUILD_PAIR("family", SD_JSON_BUILD_INTEGER(owner_family)),
|
||||||
if (r < 0)
|
SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(name ?: "")),
|
||||||
|
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(type ?: "")),
|
||||||
|
SD_JSON_BUILD_PAIR("domain", SD_JSON_BUILD_STRING(domain ?: "")),
|
||||||
|
SD_JSON_BUILD_PAIR("ifindex", SD_JSON_BUILD_INTEGER(sb->ifindex)));
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to build JSON for removed service: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_json_variant_append_array(&array, entry);
|
r = sd_json_variant_append_array(&array, entry);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to append JSON entry to array: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sd_json_variant_is_blank_array(array)) {
|
if (!sd_json_variant_is_blank_array(array)) {
|
||||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *vm = NULL;
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *vm = NULL;
|
||||||
|
|
||||||
r = sd_json_buildo(&vm,
|
r = sd_json_buildo(&vm, SD_JSON_BUILD_PAIR("browserServiceData", SD_JSON_BUILD_VARIANT(array)));
|
||||||
SD_JSON_BUILD_PAIR("browser_service_data", SD_JSON_BUILD_VARIANT(array)));
|
if (r < 0) {
|
||||||
if (r < 0)
|
log_error_errno(r,
|
||||||
|
"Failed to build JSON object for "
|
||||||
|
"browser service data: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_varlink_notify(sb->link, vm);
|
r = sd_varlink_notify(sb->link, vm);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to notify via varlink: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -387,33 +453,29 @@ finish:
|
||||||
return sd_varlink_error_errno(sb->link, r);
|
return sd_varlink_error_errno(sb->link, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdns_browser_lookup_cache(DnsServiceBrowser *sb, int owner_family) {
|
int mdns_browser_revisit_cache(DnsServiceBrowser *sb, int owner_family) {
|
||||||
_cleanup_(dns_answer_unrefp) DnsAnswer *lookup_ret_answer = NULL;
|
_cleanup_(dns_answer_unrefp) DnsAnswer *lookup_ret_answer = NULL;
|
||||||
DnsScope *scope;
|
DnsScope *scope;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(sb);
|
assert(sb);
|
||||||
assert(sb->m);
|
assert(sb->manager);
|
||||||
|
|
||||||
scope = manager_find_scope_from_protocol(sb->m, sb->ifindex, DNS_PROTOCOL_MDNS, owner_family);
|
scope = manager_find_scope_from_protocol(sb->manager, sb->ifindex, DNS_PROTOCOL_MDNS, owner_family);
|
||||||
if (!scope)
|
if (!scope)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dns_cache_prune(&scope->cache);
|
dns_cache_prune(&scope->cache);
|
||||||
|
|
||||||
r = dns_cache_lookup(
|
r = dns_cache_lookup(&scope->cache, sb->key, sb->flags, NULL, &lookup_ret_answer, NULL, NULL, NULL);
|
||||||
&scope->cache,
|
|
||||||
sb->key,
|
|
||||||
sb->flags,
|
|
||||||
NULL,
|
|
||||||
&lookup_ret_answer,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Failed to look up DNS cache for service browser key: %m");
|
||||||
|
|
||||||
return mdns_manage_services_answer(sb, lookup_ret_answer, owner_family);
|
r = mdns_manage_services_answer(sb, lookup_ret_answer, owner_family);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to manage mDNS services after cache lookup: %m");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdns_notify_browsers_goodbye(DnsScope *scope) {
|
int mdns_notify_browsers_goodbye(DnsScope *scope) {
|
||||||
|
@ -424,15 +486,16 @@ int mdns_notify_browsers_goodbye(DnsScope *scope) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
HASHMAP_FOREACH(sb, scope->manager->dns_service_browsers) {
|
HASHMAP_FOREACH(sb, scope->manager->dns_service_browsers) {
|
||||||
r = mdns_browser_lookup_cache(sb, scope->family);
|
r = mdns_browser_revisit_cache(sb, scope->family);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(
|
||||||
|
r,
|
||||||
|
"Failed to revisit cache for service "
|
||||||
|
"browser with family %d: %m",
|
||||||
|
scope->family);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mdns_notify_browsers_unsolicited_updates(Manager *m, DnsAnswer *answer, int owner_family) {
|
int mdns_notify_browsers_unsolicited_updates(Manager *m, DnsAnswer *answer, int owner_family) {
|
||||||
|
@ -448,21 +511,23 @@ int mdns_notify_browsers_unsolicited_updates(Manager *m, DnsAnswer *answer, int
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
HASHMAP_FOREACH(sb, m->dns_service_browsers) {
|
HASHMAP_FOREACH(sb, m->dns_service_browsers) {
|
||||||
|
|
||||||
r = dns_answer_match_key(answer, sb->key, NULL);
|
r = dns_answer_match_key(answer, sb->key, NULL);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
goto finish;
|
return log_error_errno(
|
||||||
else if (r == 0)
|
r,
|
||||||
|
"Failed to match answer key with "
|
||||||
|
"service browser's key: %m");
|
||||||
|
}
|
||||||
|
if (r == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = mdns_browser_lookup_cache(sb, owner_family);
|
r = mdns_browser_revisit_cache(sb, owner_family);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to revisit cache for service browser: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
return log_error_errno(r, "Failed to notify mDNS service subscribers, %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mdns_browse_service_query_complete(DnsQuery *q) {
|
static void mdns_browse_service_query_complete(DnsQuery *q) {
|
||||||
|
@ -476,32 +541,37 @@ static void mdns_browse_service_query_complete(DnsQuery *q) {
|
||||||
if (query->state != DNS_TRANSACTION_SUCCESS)
|
if (query->state != DNS_TRANSACTION_SUCCESS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sb = dns_service_browser_ref(hashmap_get(query->manager->dns_service_browsers, query->varlink_request));
|
sb = dns_service_browser_ref(query->service_browser_request);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = dns_answer_match_key(query->answer, sb->key, NULL);
|
r = dns_answer_match_key(query->answer, sb->key, NULL);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
goto finish;
|
log_error_errno(r,
|
||||||
else if (r == 0)
|
"Failed to match answer key with service "
|
||||||
|
"browser's key: %m");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = mdns_browser_lookup_cache(sb, query->answer_family);
|
|
||||||
if (r < 0)
|
|
||||||
goto finish;
|
|
||||||
|
|
||||||
/* When the query is answered from cache, we only get answers for one answer_family
|
|
||||||
* i.e. either ipv4 or ipv6.
|
|
||||||
* We need to perform another cache lookup for the other answer_family */
|
|
||||||
if (query->answer_query_flags == SD_RESOLVED_FROM_CACHE) {
|
|
||||||
r = mdns_browser_lookup_cache(sb, query->answer_family == AF_INET? AF_INET6 : AF_INET);
|
|
||||||
if (r < 0)
|
|
||||||
goto finish;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
if (r == 0)
|
||||||
finish:
|
return;
|
||||||
log_error_errno(r, "mDNS browse query complete failed, %m");
|
|
||||||
|
r = mdns_browser_revisit_cache(sb, query->answer_family);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to revisit cache for service browser: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When the query is answered from cache, we only get answers for one
|
||||||
|
* answer_family i.e. either ipv4 or ipv6. We need to perform another
|
||||||
|
* cache lookup for the other answer_family */
|
||||||
|
if (query->answer_query_flags == SD_RESOLVED_FROM_CACHE) {
|
||||||
|
r = mdns_browser_revisit_cache(sb, query->answer_family == AF_INET ? AF_INET6 : AF_INET);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error_errno(r, "Failed to revisit cache for service browser: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mdns_next_query_schedule(sd_event_source *s, uint64_t usec, void *userdata) {
|
static int mdns_next_query_schedule(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||||
|
@ -512,49 +582,65 @@ static int mdns_next_query_schedule(sd_event_source *s, uint64_t usec, void *use
|
||||||
assert(userdata);
|
assert(userdata);
|
||||||
|
|
||||||
sb = dns_service_browser_ref(userdata);
|
sb = dns_service_browser_ref(userdata);
|
||||||
|
if (!sb)
|
||||||
|
return log_error_errno(0, "Failed to reference service browser: %m");
|
||||||
|
|
||||||
r = dns_query_new(sb->m, &q, sb->question_utf8, sb->question_idna, NULL, sb->ifindex, sb->flags);
|
/* Enable the answer from the cache for the very first query */
|
||||||
|
if (sb->delay == 0) {
|
||||||
|
SET_FLAG(sb->flags, SD_RESOLVED_NO_CACHE, false);
|
||||||
|
sb->delay++;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = dns_query_new(sb->manager, &q, sb->question_utf8, sb->question_idna, NULL, sb->ifindex, sb->flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to create new DNS query: %m");
|
||||||
|
|
||||||
q->complete = mdns_browse_service_query_complete;
|
q->complete = mdns_browse_service_query_complete;
|
||||||
|
q->service_browser_request = dns_service_browser_ref(sb);
|
||||||
q->varlink_request = sd_varlink_ref(sb->link);
|
q->varlink_request = sd_varlink_ref(sb->link);
|
||||||
|
|
||||||
|
if (!q->varlink_request) {
|
||||||
|
log_error_errno(0, "Failed to reference varlink request: %m");
|
||||||
|
dns_query_free(q);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
sd_varlink_set_userdata(sb->link, q);
|
sd_varlink_set_userdata(sb->link, q);
|
||||||
|
|
||||||
r = dns_query_go(q);
|
r = dns_query_go(q);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to send DNS query: %m");
|
||||||
|
|
||||||
/* RFC6762 5.2
|
/* RFC6762 5.2
|
||||||
* The intervals between successive queries MUST increase by at least a factor of two.
|
* The intervals between successive queries MUST increase by at least a
|
||||||
* When the interval between queries reaches or exceeds 60 minutes,perform
|
* factor of two. When the interval between queries reaches or exceeds
|
||||||
* subsequent queries at a steady-state rate of one query per hour */
|
* 60 minutes,perform subsequent queries at a steady-state rate of one
|
||||||
if (sb->delay == 0) {
|
* query per hour */
|
||||||
sb->delay++;
|
|
||||||
/* First query is sent wihtout SD_RESOLVED_NO_CACHE to fetch answers already in cache.
|
sb->delay = sb->delay < 2048 ? sb->delay * 2 : 3600;
|
||||||
* Set SD_RESOLVED_NO_CACHE to make all subsequent queries go to the network. */
|
|
||||||
sb->flags |= SD_RESOLVED_NO_CACHE;
|
SET_FLAG(sb->flags, SD_RESOLVED_NO_CACHE, true);
|
||||||
}
|
|
||||||
else
|
|
||||||
sb->delay = sb->delay < 2048 ? sb->delay * 2 : 3600;
|
|
||||||
|
|
||||||
r = event_reset_time_relative(
|
r = event_reset_time_relative(
|
||||||
sb->m->event, &sb->schedule_event,
|
sb->manager->event,
|
||||||
CLOCK_BOOTTIME, (sb->delay * USEC_PER_SEC),
|
&sb->schedule_event,
|
||||||
0, mdns_next_query_schedule,
|
CLOCK_BOOTTIME,
|
||||||
sb, 0, "mdns-next-query-schedule", true);
|
(sb->delay * USEC_PER_SEC),
|
||||||
|
/* accuracy= */ 0,
|
||||||
|
mdns_next_query_schedule,
|
||||||
|
sb,
|
||||||
|
/* priority= */ 0,
|
||||||
|
"mdns-next-query-schedule",
|
||||||
|
/* force_reset= */ true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto finish;
|
return log_error_errno(r, "Failed to reset event time for next query schedule: %m");
|
||||||
|
|
||||||
TAKE_PTR(q);
|
TAKE_PTR(q);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
finish:
|
|
||||||
return log_error_errno(r, "Failed to schedule mDNS query, %m");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dns_service_browser_reset(Manager *m) {
|
void dns_browse_services_restart(Manager *m) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!(m && m->dns_service_browsers))
|
if (!(m && m->dns_service_browsers))
|
||||||
|
@ -566,25 +652,27 @@ void dns_service_browser_reset(Manager *m) {
|
||||||
sb->delay = 0;
|
sb->delay = 0;
|
||||||
|
|
||||||
r = event_reset_time_relative(
|
r = event_reset_time_relative(
|
||||||
sb->m->event, &sb->schedule_event,
|
sb->manager->event,
|
||||||
CLOCK_BOOTTIME, (sb->delay * USEC_PER_SEC),
|
&sb->schedule_event,
|
||||||
0, mdns_next_query_schedule,
|
CLOCK_BOOTTIME,
|
||||||
sb, 0, "mdns-next-query-schedule", true);
|
(sb->delay * USEC_PER_SEC),
|
||||||
if (r < 0)
|
/* accuracy= */ 0,
|
||||||
log_error_errno(r, "Failed to reset mdns service subscriber, %m");
|
mdns_next_query_schedule,
|
||||||
}
|
sb,
|
||||||
|
/* priority= */ 0,
|
||||||
|
"mdns-next-query-schedule",
|
||||||
|
/* force_reset= */ true);
|
||||||
|
|
||||||
return;
|
if (r < 0) {
|
||||||
|
log_error_errno(r,
|
||||||
|
"Failed to reset mDNS service subscriber event "
|
||||||
|
"for service browser: %m");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_subscribe_browse_service(
|
int dns_subscribe_browse_service(
|
||||||
Manager *m,
|
Manager *m, sd_varlink *link, const char *domain, const char *type, int ifindex, uint64_t flags) {
|
||||||
sd_varlink *link,
|
|
||||||
const char *domain,
|
|
||||||
const char *name,
|
|
||||||
const char *type,
|
|
||||||
int ifindex,
|
|
||||||
uint64_t flags) {
|
|
||||||
|
|
||||||
_cleanup_(dns_service_browser_unrefp) DnsServiceBrowser *sb = NULL;
|
_cleanup_(dns_service_browser_unrefp) DnsServiceBrowser *sb = NULL;
|
||||||
_cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
|
_cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
|
||||||
|
@ -593,40 +681,40 @@ int dns_subscribe_browse_service(
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(link);
|
assert(link);
|
||||||
|
|
||||||
if (ifindex <= 0)
|
if (ifindex < 0)
|
||||||
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("ifindex"));
|
return sd_varlink_error_invalid_parameter_name(link, "ifindex");
|
||||||
|
|
||||||
if (isempty(name))
|
|
||||||
name = NULL;
|
|
||||||
else if (!dns_service_name_is_valid(name))
|
|
||||||
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("name"));
|
|
||||||
|
|
||||||
if (isempty(type))
|
if (isempty(type))
|
||||||
type = NULL;
|
type = NULL;
|
||||||
else if (!dnssd_srv_type_is_valid(type))
|
else if (!dnssd_srv_type_is_valid(type))
|
||||||
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("type"));
|
return sd_varlink_error_invalid_parameter_name(link, "type");
|
||||||
|
|
||||||
|
if (isempty(domain))
|
||||||
|
domain = "local";
|
||||||
|
|
||||||
r = dns_name_is_valid(domain);
|
r = dns_name_is_valid(domain);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("domain"));
|
return sd_varlink_error_invalid_parameter_name(link, "domain");
|
||||||
|
|
||||||
r = dns_question_new_service_type(&question_utf8, name, type, domain, false, DNS_TYPE_PTR);
|
r = dns_question_new_service_type(
|
||||||
|
&question_utf8, /* name= */ NULL, type, domain, /* convert_idna= */ false, DNS_TYPE_PTR);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Failed to create DNS question for UTF8 version: %m");
|
||||||
|
|
||||||
r = dns_question_new_service_type(&question_idna, name, type, domain, true, DNS_TYPE_PTR);
|
r = dns_question_new_service_type(
|
||||||
|
&question_idna, /* name= */ NULL, type, domain, /* convert_idna= */ true, DNS_TYPE_PTR);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Failed to create DNS question for IDNA version: %m");
|
||||||
|
|
||||||
sb = new(DnsServiceBrowser, 1);
|
sb = new (DnsServiceBrowser, 1);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
*sb = (DnsServiceBrowser) {
|
*sb = (DnsServiceBrowser) {
|
||||||
.n_ref = 1,
|
.n_ref = 1,
|
||||||
.m = m,
|
.manager = m,
|
||||||
.link = sd_varlink_ref(link),
|
.link = sd_varlink_ref(link),
|
||||||
.question_utf8 = dns_question_ref(question_utf8),
|
.question_utf8 = dns_question_ref(question_utf8),
|
||||||
.question_idna = dns_question_ref(question_idna),
|
.question_idna = dns_question_ref(question_idna),
|
||||||
|
@ -638,11 +726,12 @@ int dns_subscribe_browse_service(
|
||||||
/* Only mDNS continuous querying is currently supported. See RFC 6762 */
|
/* Only mDNS continuous querying is currently supported. See RFC 6762 */
|
||||||
switch (flags & SD_RESOLVED_PROTOCOLS_ALL) {
|
switch (flags & SD_RESOLVED_PROTOCOLS_ALL) {
|
||||||
case SD_RESOLVED_MDNS:
|
case SD_RESOLVED_MDNS:
|
||||||
r = sd_event_add_time(m->event,
|
r = sd_event_add_time_relative(
|
||||||
|
m->event,
|
||||||
&sb->schedule_event,
|
&sb->schedule_event,
|
||||||
CLOCK_BOOTTIME,
|
CLOCK_BOOTTIME,
|
||||||
usec_add(now(CLOCK_BOOTTIME), (sb->delay * USEC_PER_SEC)),
|
(sb->delay * USEC_PER_SEC),
|
||||||
0,
|
/* accuracy= */ 0,
|
||||||
mdns_next_query_schedule,
|
mdns_next_query_schedule,
|
||||||
sb);
|
sb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -654,7 +743,7 @@ int dns_subscribe_browse_service(
|
||||||
|
|
||||||
r = hashmap_ensure_put(&m->dns_service_browsers, NULL, link, sb);
|
r = hashmap_ensure_put(&m->dns_service_browsers, NULL, link, sb);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_error_errno(r, "Failed to add service browser to the hashmap: %m");
|
||||||
|
|
||||||
TAKE_PTR(sb);
|
TAKE_PTR(sb);
|
||||||
|
|
||||||
|
@ -667,8 +756,8 @@ DnsServiceBrowser *dns_service_browser_free(DnsServiceBrowser *sb) {
|
||||||
if (!sb)
|
if (!sb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
LIST_FOREACH(dns_services, service, sb->dns_services)
|
while (sb->dns_services)
|
||||||
dns_remove_service(sb, service);
|
dns_remove_service(sb, sb->dns_services);
|
||||||
|
|
||||||
sd_event_source_disable_unref(sb->schedule_event);
|
sd_event_source_disable_unref(sb->schedule_event);
|
||||||
|
|
||||||
|
|
|
@ -3,38 +3,39 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef struct DnsServiceBrowser DnsServiceBrowser;
|
typedef struct DnsServiceBrowser DnsServiceBrowser;
|
||||||
|
typedef struct DnssdDiscoveredService DnssdDiscoveredService;
|
||||||
|
|
||||||
|
#include "sd-varlink.h"
|
||||||
#include "resolved-dns-query.h"
|
#include "resolved-dns-query.h"
|
||||||
#include "resolved-manager.h"
|
#include "resolved-manager.h"
|
||||||
#include "sd-varlink.h"
|
|
||||||
|
|
||||||
typedef struct DnsService DnsService;
|
|
||||||
|
|
||||||
typedef enum DnsRecordTTLState DnsRecordTTLState;
|
typedef enum DnsRecordTTLState DnsRecordTTLState;
|
||||||
|
|
||||||
enum DnsRecordTTLState {
|
enum DnsRecordTTLState {
|
||||||
MDNS_TTL_80_PERCENT,
|
DNS_RECORD_TTL_STATE_80_PERCENT,
|
||||||
MDNS_TTL_85_PERCENT,
|
DNS_RECORD_TTL_STATE_85_PERCENT,
|
||||||
MDNS_TTL_90_PERCENT,
|
DNS_RECORD_TTL_STATE_90_PERCENT,
|
||||||
MDNS_TTL_95_PERCENT,
|
DNS_RECORD_TTL_STATE_95_PERCENT,
|
||||||
MDNS_TTL_100_PERCENT
|
_DNS_RECORD_TTL_STATE_MAX,
|
||||||
|
_DNS_RECORD_TTL_STATE_MAX_INVALID = -EINVAL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DnsService {
|
struct DnssdDiscoveredService {
|
||||||
unsigned n_ref;
|
unsigned n_ref;
|
||||||
DnsServiceBrowser *sb;
|
DnsServiceBrowser *service_browser;
|
||||||
sd_event_source *schedule_event;
|
sd_event_source *schedule_event;
|
||||||
DnsResourceRecord *rr;
|
DnsResourceRecord *rr;
|
||||||
int family;
|
int family;
|
||||||
usec_t until;
|
usec_t until;
|
||||||
DnsRecordTTLState rr_ttl_state;
|
DnsRecordTTLState rr_ttl_state;
|
||||||
DnsQuery *query;
|
DnsQuery *query;
|
||||||
LIST_FIELDS(DnsService, dns_services);
|
LIST_FIELDS(DnssdDiscoveredService, dns_services);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DnsServiceBrowser {
|
struct DnsServiceBrowser {
|
||||||
unsigned n_ref;
|
unsigned n_ref;
|
||||||
Manager *m;
|
Manager *manager;
|
||||||
sd_varlink *link;
|
sd_varlink *link;
|
||||||
DnsQuestion *question_idna;
|
DnsQuestion *question_idna;
|
||||||
DnsQuestion *question_utf8;
|
DnsQuestion *question_utf8;
|
||||||
|
@ -44,35 +45,35 @@ struct DnsServiceBrowser {
|
||||||
DnsResourceKey *key;
|
DnsResourceKey *key;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
uint64_t token;
|
uint64_t token;
|
||||||
LIST_HEAD(DnsService, dns_services);
|
LIST_HEAD(DnssdDiscoveredService, dns_services);
|
||||||
};
|
};
|
||||||
|
|
||||||
DnsServiceBrowser *dns_service_browser_free(DnsServiceBrowser *sb);
|
DnsServiceBrowser *dns_service_browser_free(DnsServiceBrowser *sb);
|
||||||
void dns_remove_service(DnsServiceBrowser *sb, DnsService *service);
|
void dns_remove_service(DnsServiceBrowser *sb, DnssdDiscoveredService *service);
|
||||||
DnsService *dns_service_free(DnsService *service);
|
DnssdDiscoveredService *dns_service_free(DnssdDiscoveredService *service);
|
||||||
|
|
||||||
DnsServiceBrowser* dns_service_browser_ref(DnsServiceBrowser *sb);
|
DnsServiceBrowser *dns_service_browser_ref(DnsServiceBrowser *sb);
|
||||||
DnsServiceBrowser* dns_service_browser_unref(DnsServiceBrowser *sb);
|
DnsServiceBrowser *dns_service_browser_unref(DnsServiceBrowser *sb);
|
||||||
|
|
||||||
DnsService* dns_service_ref(DnsService *service);
|
DnssdDiscoveredService *dns_service_ref(DnssdDiscoveredService *service);
|
||||||
DnsService* dns_service_unref(DnsService *service);
|
DnssdDiscoveredService *dns_service_unref(DnssdDiscoveredService *service);
|
||||||
|
|
||||||
void dns_browse_services_purge(Manager *m, int family);
|
void dns_browse_services_purge(Manager *m, int family);
|
||||||
void dns_service_browser_reset(Manager *m);
|
void dns_browse_services_restart(Manager *m);
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServiceBrowser*, dns_service_browser_unref);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServiceBrowser *, dns_service_browser_unref);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsService*, dns_service_unref);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdDiscoveredService *, dns_service_unref);
|
||||||
|
|
||||||
bool dns_service_contains(DnsService *services, DnsResourceRecord *rr, int owner_family);
|
bool dns_service_contains(DnssdDiscoveredService *services, DnsResourceRecord *rr, int owner_family);
|
||||||
int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int owner_family);
|
int mdns_manage_services_answer(DnsServiceBrowser *sb, DnsAnswer *answer, int owner_family);
|
||||||
int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_family);
|
int dns_add_new_service(DnsServiceBrowser *sb, DnsResourceRecord *rr, int owner_family);
|
||||||
int mdns_service_update(DnsService *service, DnsResourceRecord *rr, usec_t t);
|
int mdns_service_update(DnssdDiscoveredService *service, DnsResourceRecord *rr, usec_t t);
|
||||||
int mdns_browser_lookup_cache(DnsServiceBrowser *sb, int owner_family);
|
int mdns_browser_revisit_cache(DnsServiceBrowser *sb, int owner_family);
|
||||||
int dns_subscribe_browse_service(Manager *m,
|
int dns_subscribe_browse_service(
|
||||||
|
Manager *m,
|
||||||
sd_varlink *link,
|
sd_varlink *link,
|
||||||
const char *domain,
|
const char *domain,
|
||||||
const char * name,
|
const char *type,
|
||||||
const char * type,
|
|
||||||
int ifindex,
|
int ifindex,
|
||||||
uint64_t flags);
|
uint64_t flags);
|
||||||
int mdns_notify_browsers_unsolicited_updates(Manager *m, DnsAnswer *answer, int owner_family);
|
int mdns_notify_browsers_unsolicited_updates(Manager *m, DnsAnswer *answer, int owner_family);
|
||||||
|
|
|
@ -456,6 +456,12 @@ DnsQuery *dns_query_free(DnsQuery *q) {
|
||||||
|
|
||||||
free(q->request_address_string);
|
free(q->request_address_string);
|
||||||
|
|
||||||
|
if (q->dnsservice_request)
|
||||||
|
dns_service_unref(q->dnsservice_request);
|
||||||
|
|
||||||
|
if (q->service_browser_request)
|
||||||
|
dns_service_browser_unref(q->service_browser_request);
|
||||||
|
|
||||||
if (q->manager) {
|
if (q->manager) {
|
||||||
LIST_REMOVE(queries, q->manager->dns_queries, q);
|
LIST_REMOVE(queries, q->manager->dns_queries, q);
|
||||||
q->manager->n_dns_queries--;
|
q->manager->n_dns_queries--;
|
||||||
|
|
|
@ -11,6 +11,7 @@ typedef struct DnsQuery DnsQuery;
|
||||||
typedef struct DnsStubListenerExtra DnsStubListenerExtra;
|
typedef struct DnsStubListenerExtra DnsStubListenerExtra;
|
||||||
|
|
||||||
#include "resolved-dns-answer.h"
|
#include "resolved-dns-answer.h"
|
||||||
|
#include "resolved-dns-browse-services.h"
|
||||||
#include "resolved-dns-question.h"
|
#include "resolved-dns-question.h"
|
||||||
#include "resolved-dns-search-domain.h"
|
#include "resolved-dns-search-domain.h"
|
||||||
#include "resolved-dns-transaction.h"
|
#include "resolved-dns-transaction.h"
|
||||||
|
@ -111,6 +112,10 @@ struct DnsQuery {
|
||||||
DnsAnswer *reply_additional;
|
DnsAnswer *reply_additional;
|
||||||
DnsStubListenerExtra *stub_listener_extra;
|
DnsStubListenerExtra *stub_listener_extra;
|
||||||
|
|
||||||
|
/* Browser Service and Dnssd Discovered Service Information */
|
||||||
|
DnssdDiscoveredService *dnsservice_request;
|
||||||
|
DnsServiceBrowser *service_browser_request;
|
||||||
|
|
||||||
/* Completion callback */
|
/* Completion callback */
|
||||||
void (*complete)(DnsQuery* q);
|
void (*complete)(DnsQuery* q);
|
||||||
|
|
||||||
|
|
|
@ -1606,7 +1606,7 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_scope_add_dnssd_services(DnsScope *scope) {
|
int dns_scope_add_dnssd_services(DnsScope *scope) {
|
||||||
DnssdService *service;
|
DnssdRegisteredService *service;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
@ -1645,7 +1645,7 @@ int dns_scope_add_dnssd_services(DnsScope *scope) {
|
||||||
|
|
||||||
int dns_scope_remove_dnssd_services(DnsScope *scope) {
|
int dns_scope_remove_dnssd_services(DnsScope *scope) {
|
||||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||||
DnssdService *service;
|
DnssdRegisteredService *service;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(scope);
|
assert(scope);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
|
|
||||||
int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
Manager *m;
|
Manager *m;
|
||||||
Link *l;
|
Link *l;
|
||||||
int r;
|
int r;
|
||||||
|
@ -69,7 +69,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_
|
||||||
static int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
|
static int dnssd_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
|
||||||
_cleanup_free_ char *name = NULL;
|
_cleanup_free_ char *name = NULL;
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
DnssdService *service;
|
DnssdRegisteredService *service;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(bus);
|
assert(bus);
|
||||||
|
@ -92,7 +92,7 @@ static int dnssd_object_find(sd_bus *bus, const char *path, const char *interfac
|
||||||
static int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
|
static int dnssd_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
Manager *m = ASSERT_PTR(userdata);
|
Manager *m = ASSERT_PTR(userdata);
|
||||||
DnssdService *service;
|
DnssdRegisteredService *service;
|
||||||
unsigned c = 0;
|
unsigned c = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ struct ConfigPerfItem;
|
||||||
Service.Name, config_parse_dnssd_service_name, 0, 0
|
Service.Name, config_parse_dnssd_service_name, 0, 0
|
||||||
Service.Type, config_parse_dnssd_service_type, 0, 0
|
Service.Type, config_parse_dnssd_service_type, 0, 0
|
||||||
Service.SubType, config_parse_dnssd_service_subtype, 0, 0
|
Service.SubType, config_parse_dnssd_service_subtype, 0, 0
|
||||||
Service.Port, config_parse_ip_port, 0, offsetof(DnssdService, port)
|
Service.Port, config_parse_ip_port, 0, offsetof(DnssdRegisteredService, port)
|
||||||
Service.Priority, config_parse_uint16, 0, offsetof(DnssdService, priority)
|
Service.Priority, config_parse_uint16, 0, offsetof(DnssdRegisteredService, priority)
|
||||||
Service.Weight, config_parse_uint16, 0, offsetof(DnssdService, weight)
|
Service.Weight, config_parse_uint16, 0, offsetof(DnssdRegisteredService, weight)
|
||||||
Service.TxtText, config_parse_dnssd_txt, DNS_TXT_ITEM_TEXT, 0
|
Service.TxtText, config_parse_dnssd_txt, DNS_TXT_ITEM_TEXT, 0
|
||||||
Service.TxtData, config_parse_dnssd_txt, DNS_TXT_ITEM_DATA, 0
|
Service.TxtData, config_parse_dnssd_txt, DNS_TXT_ITEM_DATA, 0
|
||||||
|
|
|
@ -37,7 +37,7 @@ DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data) {
|
||||||
return dnssd_txtdata_free_all(next);
|
return dnssd_txtdata_free_all(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
DnssdService *dnssd_service_free(DnssdService *service) {
|
DnssdRegisteredService *dnssd_service_free(DnssdRegisteredService *service) {
|
||||||
if (!service)
|
if (!service)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ DnssdService *dnssd_service_free(DnssdService *service) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dnssd_service_clear_on_reload(Hashmap *services) {
|
void dnssd_service_clear_on_reload(Hashmap *services) {
|
||||||
DnssdService *service;
|
DnssdRegisteredService *service;
|
||||||
|
|
||||||
HASHMAP_FOREACH(service, services)
|
HASHMAP_FOREACH(service, services)
|
||||||
if (service->config_source == RESOLVE_CONFIG_SOURCE_FILE) {
|
if (service->config_source == RESOLVE_CONFIG_SOURCE_FILE) {
|
||||||
|
@ -91,7 +91,7 @@ static int dnssd_id_from_path(const char *path, char **ret_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dnssd_service_load(Manager *manager, const char *path) {
|
static int dnssd_service_load(Manager *manager, const char *path) {
|
||||||
_cleanup_(dnssd_service_freep) DnssdService *service = NULL;
|
_cleanup_(dnssd_service_freep) DnssdRegisteredService *service = NULL;
|
||||||
_cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
|
_cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
|
||||||
_cleanup_free_ char *dropin_dirname = NULL;
|
_cleanup_free_ char *dropin_dirname = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
@ -99,7 +99,7 @@ static int dnssd_service_load(Manager *manager, const char *path) {
|
||||||
assert(manager);
|
assert(manager);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
service = new0(DnssdService, 1);
|
service = new0(DnssdRegisteredService, 1);
|
||||||
if (!service)
|
if (!service)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ static int specifier_dnssd_hostname(char specifier, const void *data, const char
|
||||||
return strdup_to(ret, m->llmnr_hostname);
|
return strdup_to(ret, m->llmnr_hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dnssd_render_instance_name(Manager *m, DnssdService *s, char **ret) {
|
int dnssd_render_instance_name(Manager *m, DnssdRegisteredService *s, char **ret) {
|
||||||
static const Specifier specifier_table[] = {
|
static const Specifier specifier_table[] = {
|
||||||
{ 'a', specifier_architecture, NULL },
|
{ 'a', specifier_architecture, NULL },
|
||||||
{ 'b', specifier_boot_id, NULL },
|
{ 'b', specifier_boot_id, NULL },
|
||||||
|
@ -229,7 +229,7 @@ int dnssd_load(Manager *manager) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dnssd_update_rrs(DnssdService *s) {
|
int dnssd_update_rrs(DnssdRegisteredService *s) {
|
||||||
_cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL, *sub_name = NULL, *selective_name = NULL;
|
_cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL, *sub_name = NULL, *selective_name = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ int dnssd_txt_item_new_from_data(const char *key, const void *data, const size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
int dnssd_signal_conflict(Manager *manager, const char *name) {
|
int dnssd_signal_conflict(Manager *manager, const char *name) {
|
||||||
DnssdService *s;
|
DnssdRegisteredService *s;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (sd_bus_is_ready(manager->bus) <= 0)
|
if (sd_bus_is_ready(manager->bus) <= 0)
|
||||||
|
@ -428,7 +428,7 @@ int config_parse_dnssd_service_name(
|
||||||
{ 'W', specifier_os_variant_id, NULL },
|
{ 'W', specifier_os_variant_id, NULL },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
_cleanup_free_ char *name = NULL;
|
_cleanup_free_ char *name = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ int config_parse_dnssd_service_type(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
|
@ -506,7 +506,7 @@ int config_parse_dnssd_service_subtype(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
assert(lvalue);
|
assert(lvalue);
|
||||||
|
@ -538,7 +538,7 @@ int config_parse_dnssd_txt(
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
_cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
|
_cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
|
||||||
DnssdService *s = ASSERT_PTR(userdata);
|
DnssdRegisteredService *s = ASSERT_PTR(userdata);
|
||||||
DnsTxtItem *last = NULL;
|
DnsTxtItem *last = NULL;
|
||||||
|
|
||||||
assert(filename);
|
assert(filename);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "resolved-conf.h"
|
#include "resolved-conf.h"
|
||||||
|
|
||||||
typedef struct DnssdService DnssdService;
|
typedef struct DnssdRegisteredService DnssdRegisteredService;
|
||||||
typedef struct DnssdTxtData DnssdTxtData;
|
typedef struct DnssdTxtData DnssdTxtData;
|
||||||
|
|
||||||
typedef struct Manager Manager;
|
typedef struct Manager Manager;
|
||||||
|
@ -25,7 +25,7 @@ struct DnssdTxtData {
|
||||||
LIST_FIELDS(DnssdTxtData, items);
|
LIST_FIELDS(DnssdTxtData, items);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DnssdService {
|
struct DnssdRegisteredService {
|
||||||
char *path;
|
char *path;
|
||||||
char *id;
|
char *id;
|
||||||
char *name_template;
|
char *name_template;
|
||||||
|
@ -52,19 +52,19 @@ struct DnssdService {
|
||||||
uid_t originator;
|
uid_t originator;
|
||||||
};
|
};
|
||||||
|
|
||||||
DnssdService *dnssd_service_free(DnssdService *service);
|
DnssdRegisteredService *dnssd_service_free(DnssdRegisteredService *service);
|
||||||
DnssdTxtData *dnssd_txtdata_free(DnssdTxtData *txt_data);
|
DnssdTxtData *dnssd_txtdata_free(DnssdTxtData *txt_data);
|
||||||
DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data);
|
DnssdTxtData *dnssd_txtdata_free_all(DnssdTxtData *txt_data);
|
||||||
void dnssd_service_clear_on_reload(Hashmap *services);
|
void dnssd_service_clear_on_reload(Hashmap *services);
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdService*, dnssd_service_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdRegisteredService*, dnssd_service_free);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdTxtData*, dnssd_txtdata_free);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(DnssdTxtData*, dnssd_txtdata_free);
|
||||||
|
|
||||||
int dnssd_render_instance_name(Manager *m, DnssdService *s, char **ret);
|
int dnssd_render_instance_name(Manager *m, DnssdRegisteredService *s, char **ret);
|
||||||
int dnssd_load(Manager *manager);
|
int dnssd_load(Manager *manager);
|
||||||
int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item);
|
int dnssd_txt_item_new_from_string(const char *key, const char *value, DnsTxtItem **ret_item);
|
||||||
int dnssd_txt_item_new_from_data(const char *key, const void *value, const size_t size, DnsTxtItem **ret_item);
|
int dnssd_txt_item_new_from_data(const char *key, const void *value, const size_t size, DnsTxtItem **ret_item);
|
||||||
int dnssd_update_rrs(DnssdService *s);
|
int dnssd_update_rrs(DnssdRegisteredService *s);
|
||||||
int dnssd_signal_conflict(Manager *manager, const char *name);
|
int dnssd_signal_conflict(Manager *manager, const char *name);
|
||||||
|
|
||||||
const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
const struct ConfigPerfItem* resolved_dnssd_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||||
|
|
|
@ -167,7 +167,7 @@ void link_allocate_scopes(Link *l) {
|
||||||
r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
|
r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv4 scope, ignoring: %m");
|
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv4 scope, ignoring: %m");
|
||||||
dns_service_browser_reset(l->manager);
|
dns_browse_services_restart(l->manager);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
|
l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
|
||||||
|
@ -178,7 +178,7 @@ void link_allocate_scopes(Link *l) {
|
||||||
r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
|
r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv6 scope, ignoring: %m");
|
log_link_warning_errno(l, r, "Failed to allocate mDNS IPv6 scope, ignoring: %m");
|
||||||
dns_service_browser_reset(l->manager);
|
dns_browse_services_restart(l->manager);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
|
l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
|
||||||
|
|
|
@ -768,7 +768,7 @@ int manager_start(Manager *m) {
|
||||||
|
|
||||||
Manager *manager_free(Manager *m) {
|
Manager *manager_free(Manager *m) {
|
||||||
Link *l;
|
Link *l;
|
||||||
DnssdService *s;
|
DnssdRegisteredService *s;
|
||||||
DnsServiceBrowser *sb;
|
DnsServiceBrowser *sb;
|
||||||
|
|
||||||
if (!m)
|
if (!m)
|
||||||
|
@ -1350,7 +1350,7 @@ int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_a
|
||||||
|
|
||||||
void manager_refresh_rrs(Manager *m) {
|
void manager_refresh_rrs(Manager *m) {
|
||||||
Link *l;
|
Link *l;
|
||||||
DnssdService *s;
|
DnssdRegisteredService *s;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
@ -1711,7 +1711,7 @@ void manager_flush_caches(Manager *m, int log_level) {
|
||||||
dns_cache_flush(&scope->cache);
|
dns_cache_flush(&scope->cache);
|
||||||
|
|
||||||
dns_browse_services_purge(m, AF_UNSPEC); /* Clear records of DNS service browse subscriber, since caches are flushed */
|
dns_browse_services_purge(m, AF_UNSPEC); /* Clear records of DNS service browse subscriber, since caches are flushed */
|
||||||
dns_service_browser_reset(m);
|
dns_browse_services_restart(m);
|
||||||
|
|
||||||
log_full(log_level, "Flushed all caches.");
|
log_full(log_level, "Flushed all caches.");
|
||||||
}
|
}
|
||||||
|
@ -1776,7 +1776,7 @@ void manager_cleanup_saved_user(Manager *m) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool manager_next_dnssd_names(Manager *m) {
|
bool manager_next_dnssd_names(Manager *m) {
|
||||||
DnssdService *s;
|
DnssdRegisteredService *s;
|
||||||
bool tried = false;
|
bool tried = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
|
|
@ -361,19 +361,19 @@ static int mdns_goodbye_callback(sd_event_source *s, uint64_t usec, void *userda
|
||||||
|
|
||||||
r = mdns_notify_browsers_goodbye(scope);
|
r = mdns_notify_browsers_goodbye(scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_error_errno(r, "mDNS: Failed to notify service subscribers of goodbyes, %m");
|
log_warning_errno(r, "mDNS: Failed to notify service subscribers of goodbyes, ignoring: %m");
|
||||||
|
|
||||||
if (dns_cache_expiry_in_one_second(&scope->cache, usec)) {
|
if (dns_cache_expiry_in_one_second(&scope->cache, usec)) {
|
||||||
r = sd_event_add_time_relative(
|
r = sd_event_add_time_relative(
|
||||||
scope->manager->event,
|
scope->manager->event,
|
||||||
&scope->mdns_goodbye_event_source,
|
&scope->mdns_goodbye_event_source,
|
||||||
CLOCK_BOOTTIME,
|
CLOCK_BOOTTIME,
|
||||||
USEC_PER_SEC,
|
USEC_PER_SEC,
|
||||||
0,
|
/* accuracy= */ 0,
|
||||||
mdns_goodbye_callback,
|
mdns_goodbye_callback,
|
||||||
scope);
|
scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "mDNS: Failed to re-schedule goodbye callback: %m");
|
return log_warning_errno(r, "mDNS: Failed to re-schedule goodbye callback, ignoring: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -451,7 +451,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
||||||
&scope->mdns_goodbye_event_source,
|
&scope->mdns_goodbye_event_source,
|
||||||
CLOCK_BOOTTIME,
|
CLOCK_BOOTTIME,
|
||||||
USEC_PER_SEC,
|
USEC_PER_SEC,
|
||||||
0,
|
/* accuracy= */ 0,
|
||||||
mdns_goodbye_callback,
|
mdns_goodbye_callback,
|
||||||
scope);
|
scope);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -461,19 +461,19 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_cache_put(
|
dns_cache_put(
|
||||||
&scope->cache,
|
&scope->cache,
|
||||||
scope->manager->enable_cache,
|
scope->manager->enable_cache,
|
||||||
DNS_PROTOCOL_MDNS,
|
DNS_PROTOCOL_MDNS,
|
||||||
NULL,
|
/* key= */ NULL,
|
||||||
DNS_PACKET_RCODE(p),
|
DNS_PACKET_RCODE(p),
|
||||||
p->answer,
|
p->answer,
|
||||||
NULL,
|
/* full_packet= */ NULL,
|
||||||
false,
|
/* query_flags= */ false,
|
||||||
_DNSSEC_RESULT_INVALID,
|
_DNSSEC_RESULT_INVALID,
|
||||||
UINT32_MAX,
|
/* nsec_ttl= */ UINT32_MAX,
|
||||||
p->family,
|
p->family,
|
||||||
&p->sender,
|
&p->sender,
|
||||||
scope->manager->stale_retention_usec);
|
scope->manager->stale_retention_usec);
|
||||||
|
|
||||||
for (bool match = true; match;) {
|
for (bool match = true; match;) {
|
||||||
match = false;
|
match = false;
|
||||||
|
@ -500,7 +500,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check incoming packet key matches with active clients if yes update the same */
|
/* Check if incoming packet key matches with active browse clients. If yes, update the same */
|
||||||
if (unsolicited_packet)
|
if (unsolicited_packet)
|
||||||
mdns_notify_browsers_unsolicited_updates(m, p->answer, p->family);
|
mdns_notify_browsers_unsolicited_updates(m, p->answer, p->family);
|
||||||
|
|
||||||
|
|
|
@ -31,26 +31,18 @@ typedef struct LookupParametersResolveService {
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
} LookupParametersResolveService;
|
} LookupParametersResolveService;
|
||||||
|
|
||||||
typedef struct LookupParametersMdnsBrowse {
|
typedef struct LookupParametersBrowse {
|
||||||
char *domainName;
|
const char *domain;
|
||||||
char *name;
|
const char *type;
|
||||||
char *type;
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
} LookupParametersMdnsBrowse;
|
} LookupParametersBrowse;
|
||||||
|
|
||||||
static void lookup_parameters_destroy(LookupParameters *p) {
|
static void lookup_parameters_destroy(LookupParameters *p) {
|
||||||
assert(p);
|
assert(p);
|
||||||
free(p->name);
|
free(p->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lookup_parameters_mdns_destroy(LookupParametersMdnsBrowse *p) {
|
|
||||||
assert(p);
|
|
||||||
free(p->domainName);
|
|
||||||
free(p->name);
|
|
||||||
free(p->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int reply_query_state(DnsQuery *q) {
|
static int reply_query_state(DnsQuery *q) {
|
||||||
|
|
||||||
assert(q);
|
assert(q);
|
||||||
|
@ -134,7 +126,7 @@ static void vl_on_disconnect(sd_varlink_server *s, sd_varlink *link, void *userd
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DnsServiceBrowser *sb = hashmap_remove(m->dns_service_browsers, link);
|
DnsServiceBrowser *sb = hashmap_remove(m->dns_service_browsers, link);
|
||||||
dns_service_browser_free(sb);
|
dns_service_browser_unref(sb);
|
||||||
|
|
||||||
q = sd_varlink_get_userdata(link);
|
q = sd_varlink_get_userdata(link);
|
||||||
if (!q)
|
if (!q)
|
||||||
|
@ -1233,17 +1225,16 @@ static int verify_polkit(sd_varlink *link, sd_json_variant *parameters, const ch
|
||||||
&m->polkit_registry);
|
&m->polkit_registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vl_method_start_browse(sd_varlink* link, sd_json_variant* parameters, sd_varlink_method_flags_t flags, void* userdata) {
|
static int vl_method_browse_services(sd_varlink* link, sd_json_variant* parameters, sd_varlink_method_flags_t flags, void* userdata) {
|
||||||
static const sd_json_dispatch_field dispatch_table[] = {
|
static const sd_json_dispatch_field dispatch_table[] = {
|
||||||
{ "domainName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LookupParametersMdnsBrowse, domainName), SD_JSON_MANDATORY },
|
{ "domain", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParametersBrowse, domain), 0 },
|
||||||
{ "name", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LookupParametersMdnsBrowse, name), 0 },
|
{ "type", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(LookupParametersBrowse, type), 0 },
|
||||||
{ "type", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(LookupParametersMdnsBrowse, type), 0 },
|
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParametersBrowse, ifindex), 0 },
|
||||||
{ "ifindex", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_int, offsetof(LookupParametersMdnsBrowse, ifindex), SD_JSON_MANDATORY },
|
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParametersBrowse, flags), 0 },
|
||||||
{ "flags", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint64, offsetof(LookupParametersMdnsBrowse, flags), SD_JSON_MANDATORY },
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
_cleanup_(lookup_parameters_mdns_destroy) LookupParametersMdnsBrowse p = {};
|
LookupParametersBrowse p = {};
|
||||||
Manager *m;
|
Manager *m;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
@ -1258,12 +1249,12 @@ static int vl_method_start_browse(sd_varlink* link, sd_json_variant* parameters,
|
||||||
|
|
||||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "vl_method_start_browse json_dispatch fail: %m");
|
return log_error_errno(r, "Failed vl_method_browse_services json dispatch: %m");
|
||||||
|
|
||||||
if (!validate_and_mangle_flags(NULL, &p.flags, 0))
|
if (!validate_and_mangle_flags(NULL, &p.flags, 0))
|
||||||
return sd_varlink_error_invalid_parameter(link, JSON_VARIANT_STRING_CONST("flags"));
|
return sd_varlink_error_invalid_parameter_name(link, "flags");
|
||||||
|
|
||||||
r = dns_subscribe_browse_service(m, link, p.domainName, p.name, p.type, p.ifindex, p.flags);
|
r = dns_subscribe_browse_service(m, link, p.domain, p.type, p.ifindex, p.flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return sd_varlink_error_errno(link, r);
|
return sd_varlink_error_errno(link, r);
|
||||||
|
|
||||||
|
@ -1484,7 +1475,7 @@ static int varlink_main_server_init(Manager *m) {
|
||||||
"io.systemd.Resolve.ResolveAddress", vl_method_resolve_address,
|
"io.systemd.Resolve.ResolveAddress", vl_method_resolve_address,
|
||||||
"io.systemd.Resolve.ResolveService", vl_method_resolve_service,
|
"io.systemd.Resolve.ResolveService", vl_method_resolve_service,
|
||||||
"io.systemd.Resolve.ResolveRecord", vl_method_resolve_record,
|
"io.systemd.Resolve.ResolveRecord", vl_method_resolve_record,
|
||||||
"io.systemd.Resolve.StartBrowse", vl_method_start_browse);
|
"io.systemd.Resolve.BrowseServices", vl_method_browse_services);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to register varlink methods: %m");
|
return log_error_errno(r, "Failed to register varlink methods: %m");
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,7 @@ int acquire_fido2_key(
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
Fido2EnrollFlags required,
|
Fido2EnrollFlags required,
|
||||||
const char *askpw_credential,
|
const char *askpw_credential,
|
||||||
|
@ -45,10 +44,10 @@ int acquire_fido2_key(
|
||||||
"Local verification is required to unlock this volume, but the 'headless' parameter was set.");
|
"Local verification is required to unlock this volume, but the 'headless' parameter was set.");
|
||||||
|
|
||||||
assert(cid);
|
assert(cid);
|
||||||
assert(key_file || key_data);
|
assert(key_file || iovec_is_set(key_data));
|
||||||
|
|
||||||
if (key_data)
|
if (iovec_is_set(key_data))
|
||||||
salt = IOVEC_MAKE(key_data, key_data_size);
|
salt = *key_data;
|
||||||
else {
|
else {
|
||||||
if (key_file_size > 0)
|
if (key_file_size > 0)
|
||||||
log_debug("Ignoring 'keyfile-size=' option for a FIDO2 salt file.");
|
log_debug("Ignoring 'keyfile-size=' option for a FIDO2 salt file.");
|
||||||
|
@ -252,7 +251,7 @@ int acquire_fido2_key_auto(
|
||||||
/* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */
|
/* key_file= */ NULL, /* salt is read from LUKS header instead of key_file */
|
||||||
/* key_file_size= */ 0,
|
/* key_file_size= */ 0,
|
||||||
/* key_file_offset= */ 0,
|
/* key_file_offset= */ 0,
|
||||||
salt, salt_size,
|
&IOVEC_MAKE(salt, salt_size),
|
||||||
until,
|
until,
|
||||||
required,
|
required,
|
||||||
"cryptsetup.fido2-pin",
|
"cryptsetup.fido2-pin",
|
||||||
|
|
|
@ -20,8 +20,7 @@ int acquire_fido2_key(
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
Fido2EnrollFlags required,
|
Fido2EnrollFlags required,
|
||||||
const char *askpw_credential,
|
const char *askpw_credential,
|
||||||
|
@ -52,8 +51,7 @@ static inline int acquire_fido2_key(
|
||||||
const char *key_file,
|
const char *key_file,
|
||||||
size_t key_file_size,
|
size_t key_file_size,
|
||||||
uint64_t key_file_offset,
|
uint64_t key_file_offset,
|
||||||
const void *key_data,
|
const struct iovec *key_data,
|
||||||
size_t key_data_size,
|
|
||||||
usec_t until,
|
usec_t until,
|
||||||
Fido2EnrollFlags required,
|
Fido2EnrollFlags required,
|
||||||
const char *askpw_credential,
|
const char *askpw_credential,
|
||||||
|
|
|
@ -102,14 +102,26 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
SD_VARLINK_DEFINE_FIELD(ifindex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(ifindex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, 0));
|
SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, 0));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||||
|
BrowseServiceUpdateFlag,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Indicates that the service was added."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(added),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Indicates that the service was removed."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(removed));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
static SD_VARLINK_DEFINE_STRUCT_TYPE(
|
||||||
ServiceData,
|
ServiceData,
|
||||||
SD_VARLINK_DEFINE_FIELD(add_flag, SD_VARLINK_BOOL, 0),
|
SD_VARLINK_DEFINE_FIELD_BY_TYPE(updateFlag, BrowseServiceUpdateFlag, 0),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The address family of the service, one of AF_INET or AF_INET6."),
|
||||||
SD_VARLINK_DEFINE_FIELD(family, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_FIELD(family, SD_VARLINK_INT, 0),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The name of the service, e.g., 'My Service'. May be null if not specified."),
|
||||||
SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_FIELD(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The type of service, e.g., '_http._tcp'."),
|
||||||
SD_VARLINK_DEFINE_FIELD(type, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(type, SD_VARLINK_STRING, 0),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The domain in which the service resides, e.g., 'local'."),
|
||||||
SD_VARLINK_DEFINE_FIELD(domain, SD_VARLINK_STRING, 0),
|
SD_VARLINK_DEFINE_FIELD(domain, SD_VARLINK_STRING, 0),
|
||||||
SD_VARLINK_DEFINE_FIELD(interface, SD_VARLINK_INT, 0));
|
SD_VARLINK_FIELD_COMMENT("The Linux interface index for the network interface associated with this service."),
|
||||||
|
SD_VARLINK_DEFINE_FIELD(ifindex, SD_VARLINK_INT, 0));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_METHOD(
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
ResolveAddress,
|
ResolveAddress,
|
||||||
|
@ -168,14 +180,19 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||||
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(rrs, ResolvedRecord, SD_VARLINK_ARRAY),
|
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(rrs, ResolvedRecord, SD_VARLINK_ARRAY),
|
||||||
SD_VARLINK_DEFINE_OUTPUT(flags, SD_VARLINK_INT, 0));
|
SD_VARLINK_DEFINE_OUTPUT(flags, SD_VARLINK_INT, 0));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_METHOD(
|
static SD_VARLINK_DEFINE_METHOD_FULL(
|
||||||
StartBrowse,
|
BrowseServices,
|
||||||
SD_VARLINK_DEFINE_INPUT(domainName, SD_VARLINK_STRING, 0),
|
SD_VARLINK_SUPPORTS_MORE,
|
||||||
SD_VARLINK_DEFINE_INPUT(name, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_FIELD_COMMENT("The domain to browse for services. If null, the default browsing domain local is used."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(domain, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The service type to browse for (e.g., '_http._tcp')."),
|
||||||
SD_VARLINK_DEFINE_INPUT(type, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
SD_VARLINK_DEFINE_INPUT(type, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_INPUT(ifindex, SD_VARLINK_INT, 0),
|
SD_VARLINK_FIELD_COMMENT("The Linux interface index for the network interface to search on."),
|
||||||
SD_VARLINK_DEFINE_INPUT(flags, SD_VARLINK_INT, 0),
|
SD_VARLINK_DEFINE_INPUT(ifindex, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(browser_service_data, ServiceData, SD_VARLINK_ARRAY));
|
SD_VARLINK_FIELD_COMMENT("Various browsing flags to modify the operation."),
|
||||||
|
SD_VARLINK_DEFINE_INPUT(flags, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("An array of service data containing information about discovered services."),
|
||||||
|
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(browserServiceData, ServiceData, SD_VARLINK_ARRAY));
|
||||||
|
|
||||||
static SD_VARLINK_DEFINE_ERROR(NoNameServers);
|
static SD_VARLINK_DEFINE_ERROR(NoNameServers);
|
||||||
static SD_VARLINK_DEFINE_ERROR(NoSuchResourceRecord);
|
static SD_VARLINK_DEFINE_ERROR(NoSuchResourceRecord);
|
||||||
|
@ -216,8 +233,8 @@ SD_VARLINK_DEFINE_INTERFACE(
|
||||||
&vl_method_ResolveService,
|
&vl_method_ResolveService,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("Resolves a domain name to one or more DNS resource records."),
|
SD_VARLINK_SYMBOL_COMMENT("Resolves a domain name to one or more DNS resource records."),
|
||||||
&vl_method_ResolveRecord,
|
&vl_method_ResolveRecord,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("Starts browsing for mDNS services of specified type."),
|
SD_VARLINK_SYMBOL_COMMENT("Starts browsing for DNS-SD services of specified type."),
|
||||||
&vl_method_StartBrowse,
|
&vl_method_BrowseServices,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("Encapsulates a resolved address."),
|
SD_VARLINK_SYMBOL_COMMENT("Encapsulates a resolved address."),
|
||||||
&vl_type_ResolvedAddress,
|
&vl_type_ResolvedAddress,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("Encapsulates a resolved host name."),
|
SD_VARLINK_SYMBOL_COMMENT("Encapsulates a resolved host name."),
|
||||||
|
@ -232,6 +249,9 @@ SD_VARLINK_DEFINE_INTERFACE(
|
||||||
&vl_type_ResourceRecord,
|
&vl_type_ResourceRecord,
|
||||||
SD_VARLINK_SYMBOL_COMMENT("Encapsulates information about a resolved DNS resource record "),
|
SD_VARLINK_SYMBOL_COMMENT("Encapsulates information about a resolved DNS resource record "),
|
||||||
&vl_type_ResolvedRecord,
|
&vl_type_ResolvedRecord,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Describes the update flag for browsing services, indicating whether a service was added or removed during browsing."),
|
||||||
|
&vl_type_BrowseServiceUpdateFlag,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Encapsulates the service data obtained from browsing."),
|
||||||
&vl_type_ServiceData,
|
&vl_type_ServiceData,
|
||||||
&vl_error_NoNameServers,
|
&vl_error_NoNameServers,
|
||||||
&vl_error_NoSuchResourceRecord,
|
&vl_error_NoSuchResourceRecord,
|
||||||
|
|
|
@ -1414,7 +1414,7 @@ static int verb_enable(int argc, char **argv, void *userdata) {
|
||||||
"SetFeatureEnabled",
|
"SetFeatureEnabled",
|
||||||
&error,
|
&error,
|
||||||
/* reply= */ NULL,
|
/* reply= */ NULL,
|
||||||
"sbt",
|
"sit",
|
||||||
*feature,
|
*feature,
|
||||||
(int) enable,
|
(int) enable,
|
||||||
UINT64_C(0));
|
UINT64_C(0));
|
||||||
|
|
|
@ -80,7 +80,6 @@ show_journal = True # When true, show journal on stopping networkd.
|
||||||
|
|
||||||
active_units = []
|
active_units = []
|
||||||
protected_links = {
|
protected_links = {
|
||||||
'br0',
|
|
||||||
'erspan0',
|
'erspan0',
|
||||||
'gre0',
|
'gre0',
|
||||||
'gretap0',
|
'gretap0',
|
||||||
|
|
|
@ -114,10 +114,10 @@ run_and_check_services() {
|
||||||
error_file="$(mktemp)"
|
error_file="$(mktemp)"
|
||||||
tmp_file="$(mktemp)"
|
tmp_file="$(mktemp)"
|
||||||
service_type="_testService$service_id._udp"
|
service_type="_testService$service_id._udp"
|
||||||
parameters="{ \"domainName\": \"$service_type.local\", \"name\": \"\", \"type\": \"\", \"ifindex\": ${BRIDGE_INDEX:?}, \"flags\": 16785432 }"
|
parameters="{ \"domain\": \"$service_type.local\", \"type\": \"\", \"ifindex\": ${BRIDGE_INDEX:?}, \"flags\": 16785432 }"
|
||||||
|
|
||||||
systemd-run --unit="$unit_name" --service-type=exec -p StandardOutput="file:$out_file" -p StandardError="file:$error_file" \
|
systemd-run --unit="$unit_name" --service-type=exec -p StandardOutput="file:$out_file" -p StandardError="file:$error_file" \
|
||||||
varlinkctl call --more /run/systemd/resolve/io.systemd.Resolve io.systemd.Resolve.StartBrowse "$parameters"
|
varlinkctl call --more /run/systemd/resolve/io.systemd.Resolve io.systemd.Resolve.BrowseServices "$parameters"
|
||||||
|
|
||||||
# shellcheck disable=SC2064
|
# shellcheck disable=SC2064
|
||||||
# Note: unregister the trap once it's fired, otherwise it'll get propagated to functions that call this
|
# Note: unregister the trap once it's fired, otherwise it'll get propagated to functions that call this
|
||||||
|
@ -131,7 +131,7 @@ run_and_check_services() {
|
||||||
# {
|
# {
|
||||||
# "browser_service_data": [
|
# "browser_service_data": [
|
||||||
# {
|
# {
|
||||||
# "add_flag": true,
|
# "updateFlag": true,
|
||||||
# "family": 10,
|
# "family": 10,
|
||||||
# "name": "Test Service 13 on test-mdns-1",
|
# "name": "Test Service 13 on test-mdns-1",
|
||||||
# "type": "_testService0._udp",
|
# "type": "_testService0._udp",
|
||||||
|
@ -144,7 +144,7 @@ run_and_check_services() {
|
||||||
if [[ -s "$out_file" ]]; then
|
if [[ -s "$out_file" ]]; then
|
||||||
# Extract the service name from each valid record...
|
# Extract the service name from each valid record...
|
||||||
# jq --slurp --raw-output \
|
# jq --slurp --raw-output \
|
||||||
# ".[].browser_service_data[] | select(.add_flag == true and .type == \"$service_type\" and .family == 10).name" "$out_file" | sort | tee "$tmp_file"
|
# ".[].browser_service_data[] | select(.updateFlag == true and .type == \"$service_type\" and .family == 10).name" "$out_file" | sort | tee "$tmp_file"
|
||||||
grep -o '"name":"[^"]*"' "$out_file" | sed 's/"name":"//;s/"//g' | sort | tee "$tmp_file"
|
grep -o '"name":"[^"]*"' "$out_file" | sed 's/"name":"//;s/"//g' | sort | tee "$tmp_file"
|
||||||
# ...and compare them with what we expect
|
# ...and compare them with what we expect
|
||||||
if "$check_func" "$service_id" "$tmp_file"; then
|
if "$check_func" "$service_id" "$tmp_file"; then
|
||||||
|
|
Loading…
Reference in New Issue