mirror of
https://github.com/systemd/systemd.git
synced 2025-03-11 20:58:27 +03:00
dnssd: support service subtypes
A service subtype is used for selective enumeration of services.
This commit is contained in:
parent
15d4bedf3d
commit
88123aa21c
@ -118,6 +118,16 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v236"/>
|
<xi:include href="version-info.xml" xpointer="v236"/>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SubType=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>A subtype of the network service as defined in the section 7.1 of <ulink
|
||||||
|
url="https://tools.ietf.org/html/rfc6763">RFC 6763</ulink>, e.g. <literal>_printer</literal>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v256"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Port=</varname></term>
|
<term><varname>Port=</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -299,6 +299,37 @@ int config_parse_dnssd_service_type(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_dnssd_service_subtype(
|
||||||
|
const char *unit,
|
||||||
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
DnssdService *s = ASSERT_PTR(userdata);
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
s->subtype = mfree(s->subtype);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dns_subtype_name_is_valid(rvalue)) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, 0, "Service subtype is invalid. Ignoring.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return free_and_strdup_warn(&s->subtype, rvalue);
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_dnssd_txt(
|
int config_parse_dnssd_txt(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
|
@ -17,6 +17,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dns_servers);
|
|||||||
CONFIG_PARSER_PROTOTYPE(config_parse_search_domains);
|
CONFIG_PARSER_PROTOTYPE(config_parse_search_domains);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_subtype);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra);
|
CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra);
|
||||||
|
@ -1614,6 +1614,12 @@ int dns_scope_add_dnssd_services(DnsScope *scope) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
|
log_warning_errno(r, "Failed to add PTR record to MDNS zone: %m");
|
||||||
|
|
||||||
|
if (service->sub_ptr_rr) {
|
||||||
|
r = dns_zone_put(&scope->zone, scope, service->sub_ptr_rr, false);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to add selective PTR record to MDNS zone: %m");
|
||||||
|
}
|
||||||
|
|
||||||
r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
|
r = dns_zone_put(&scope->zone, scope, service->srv_rr, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
|
log_warning_errno(r, "Failed to add SRV record to MDNS zone: %m");
|
||||||
@ -1646,6 +1652,7 @@ int dns_scope_remove_dnssd_services(DnsScope *scope) {
|
|||||||
|
|
||||||
HASHMAP_FOREACH(service, scope->manager->dnssd_services) {
|
HASHMAP_FOREACH(service, scope->manager->dnssd_services) {
|
||||||
dns_zone_remove_rr(&scope->zone, service->ptr_rr);
|
dns_zone_remove_rr(&scope->zone, service->ptr_rr);
|
||||||
|
dns_zone_remove_rr(&scope->zone, service->sub_ptr_rr);
|
||||||
dns_zone_remove_rr(&scope->zone, service->srv_rr);
|
dns_zone_remove_rr(&scope->zone, service->srv_rr);
|
||||||
LIST_FOREACH(items, txt_data, service->txt_data_items)
|
LIST_FOREACH(items, txt_data, service->txt_data_items)
|
||||||
dns_zone_remove_rr(&scope->zone, txt_data->rr);
|
dns_zone_remove_rr(&scope->zone, txt_data->rr);
|
||||||
|
@ -40,6 +40,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_
|
|||||||
log_warning_errno(r, "Failed to send goodbye messages in IPv4 scope: %m");
|
log_warning_errno(r, "Failed to send goodbye messages in IPv4 scope: %m");
|
||||||
|
|
||||||
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->ptr_rr);
|
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->ptr_rr);
|
||||||
|
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->sub_ptr_rr);
|
||||||
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->srv_rr);
|
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, s->srv_rr);
|
||||||
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
||||||
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, txt_data->rr);
|
dns_zone_remove_rr(&l->mdns_ipv4_scope->zone, txt_data->rr);
|
||||||
@ -51,6 +52,7 @@ int bus_dnssd_method_unregister(sd_bus_message *message, void *userdata, sd_bus_
|
|||||||
log_warning_errno(r, "Failed to send goodbye messages in IPv6 scope: %m");
|
log_warning_errno(r, "Failed to send goodbye messages in IPv6 scope: %m");
|
||||||
|
|
||||||
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->ptr_rr);
|
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->ptr_rr);
|
||||||
|
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->sub_ptr_rr);
|
||||||
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->srv_rr);
|
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, s->srv_rr);
|
||||||
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
||||||
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, txt_data->rr);
|
dns_zone_remove_rr(&l->mdns_ipv6_scope->zone, txt_data->rr);
|
||||||
|
@ -16,10 +16,11 @@ struct ConfigPerfItem;
|
|||||||
%struct-type
|
%struct-type
|
||||||
%includes
|
%includes
|
||||||
%%
|
%%
|
||||||
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.Port, config_parse_ip_port, 0, offsetof(DnssdService, port)
|
Service.SubType, config_parse_dnssd_service_subtype, 0, 0
|
||||||
Service.Priority, config_parse_uint16, 0, offsetof(DnssdService, priority)
|
Service.Port, config_parse_ip_port, 0, offsetof(DnssdService, port)
|
||||||
Service.Weight, config_parse_uint16, 0, offsetof(DnssdService, weight)
|
Service.Priority, config_parse_uint16, 0, offsetof(DnssdService, priority)
|
||||||
Service.TxtText, config_parse_dnssd_txt, DNS_TXT_ITEM_TEXT, 0
|
Service.Weight, config_parse_uint16, 0, offsetof(DnssdService, weight)
|
||||||
Service.TxtData, config_parse_dnssd_txt, DNS_TXT_ITEM_DATA, 0
|
Service.TxtText, config_parse_dnssd_txt, DNS_TXT_ITEM_TEXT, 0
|
||||||
|
Service.TxtData, config_parse_dnssd_txt, DNS_TXT_ITEM_DATA, 0
|
||||||
|
@ -43,6 +43,7 @@ DnssdService *dnssd_service_free(DnssdService *service) {
|
|||||||
hashmap_remove(service->manager->dnssd_services, service->name);
|
hashmap_remove(service->manager->dnssd_services, service->name);
|
||||||
|
|
||||||
dns_resource_record_unref(service->ptr_rr);
|
dns_resource_record_unref(service->ptr_rr);
|
||||||
|
dns_resource_record_unref(service->sub_ptr_rr);
|
||||||
dns_resource_record_unref(service->srv_rr);
|
dns_resource_record_unref(service->srv_rr);
|
||||||
|
|
||||||
dnssd_txtdata_free_all(service->txt_data_items);
|
dnssd_txtdata_free_all(service->txt_data_items);
|
||||||
@ -50,6 +51,7 @@ DnssdService *dnssd_service_free(DnssdService *service) {
|
|||||||
free(service->filename);
|
free(service->filename);
|
||||||
free(service->name);
|
free(service->name);
|
||||||
free(service->type);
|
free(service->type);
|
||||||
|
free(service->subtype);
|
||||||
free(service->name_template);
|
free(service->name_template);
|
||||||
|
|
||||||
return mfree(service);
|
return mfree(service);
|
||||||
@ -208,7 +210,7 @@ int dnssd_load(Manager *manager) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int dnssd_update_rrs(DnssdService *s) {
|
int dnssd_update_rrs(DnssdService *s) {
|
||||||
_cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL;
|
_cleanup_free_ char *n = NULL, *service_name = NULL, *full_name = NULL, *sub_name = NULL, *selective_name = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
@ -216,6 +218,7 @@ int dnssd_update_rrs(DnssdService *s) {
|
|||||||
assert(s->manager);
|
assert(s->manager);
|
||||||
|
|
||||||
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
|
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
|
||||||
|
s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
|
||||||
s->srv_rr = dns_resource_record_unref(s->srv_rr);
|
s->srv_rr = dns_resource_record_unref(s->srv_rr);
|
||||||
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
||||||
txt_data->rr = dns_resource_record_unref(txt_data->rr);
|
txt_data->rr = dns_resource_record_unref(txt_data->rr);
|
||||||
@ -230,6 +233,14 @@ int dnssd_update_rrs(DnssdService *s) {
|
|||||||
r = dns_name_concat(n, service_name, 0, &full_name);
|
r = dns_name_concat(n, service_name, 0, &full_name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
if (s->subtype) {
|
||||||
|
r = dns_name_concat("_sub", service_name, 0, &sub_name);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
r = dns_name_concat(s->subtype, sub_name, 0, &selective_name);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
LIST_FOREACH(items, txt_data, s->txt_data_items) {
|
LIST_FOREACH(items, txt_data, s->txt_data_items) {
|
||||||
txt_data->rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT,
|
txt_data->rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_TXT,
|
||||||
@ -253,6 +264,17 @@ int dnssd_update_rrs(DnssdService *s) {
|
|||||||
if (!s->ptr_rr->ptr.name)
|
if (!s->ptr_rr->ptr.name)
|
||||||
goto oom;
|
goto oom;
|
||||||
|
|
||||||
|
if (selective_name) {
|
||||||
|
s->sub_ptr_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, selective_name);
|
||||||
|
if (!s->sub_ptr_rr)
|
||||||
|
goto oom;
|
||||||
|
|
||||||
|
s->sub_ptr_rr->ttl = MDNS_DEFAULT_TTL;
|
||||||
|
s->sub_ptr_rr->ptr.name = strdup(full_name);
|
||||||
|
if (!s->sub_ptr_rr->ptr.name)
|
||||||
|
goto oom;
|
||||||
|
}
|
||||||
|
|
||||||
s->srv_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SRV,
|
s->srv_rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SRV,
|
||||||
full_name);
|
full_name);
|
||||||
if (!s->srv_rr)
|
if (!s->srv_rr)
|
||||||
@ -272,6 +294,7 @@ oom:
|
|||||||
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
LIST_FOREACH(items, txt_data, s->txt_data_items)
|
||||||
txt_data->rr = dns_resource_record_unref(txt_data->rr);
|
txt_data->rr = dns_resource_record_unref(txt_data->rr);
|
||||||
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
|
s->ptr_rr = dns_resource_record_unref(s->ptr_rr);
|
||||||
|
s->sub_ptr_rr = dns_resource_record_unref(s->sub_ptr_rr);
|
||||||
s->srv_rr = dns_resource_record_unref(s->srv_rr);
|
s->srv_rr = dns_resource_record_unref(s->srv_rr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,13 @@ struct DnssdService {
|
|||||||
char *name;
|
char *name;
|
||||||
char *name_template;
|
char *name_template;
|
||||||
char *type;
|
char *type;
|
||||||
|
char *subtype;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint16_t priority;
|
uint16_t priority;
|
||||||
uint16_t weight;
|
uint16_t weight;
|
||||||
|
|
||||||
DnsResourceRecord *ptr_rr;
|
DnsResourceRecord *ptr_rr;
|
||||||
|
DnsResourceRecord *sub_ptr_rr;
|
||||||
DnsResourceRecord *srv_rr;
|
DnsResourceRecord *srv_rr;
|
||||||
|
|
||||||
/* Section 6.8 of RFC 6763 allows having service
|
/* Section 6.8 of RFC 6763 allows having service
|
||||||
|
@ -980,6 +980,29 @@ bool dns_service_name_is_valid(const char *name) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dns_subtype_name_is_valid(const char *name) {
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
/* This more or less implements RFC 6763, Section 7.2 */
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!utf8_is_valid(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (string_has_cc(name, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
l = strlen(name);
|
||||||
|
if (l <= 0)
|
||||||
|
return false;
|
||||||
|
if (l > DNS_LABEL_MAX)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
|
int dns_service_join(const char *name, const char *type, const char *domain, char **ret) {
|
||||||
char escaped[DNS_LABEL_ESCAPED_MAX];
|
char escaped[DNS_LABEL_ESCAPED_MAX];
|
||||||
_cleanup_free_ char *n = NULL;
|
_cleanup_free_ char *n = NULL;
|
||||||
|
@ -83,6 +83,7 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len, boo
|
|||||||
bool dns_srv_type_is_valid(const char *name);
|
bool dns_srv_type_is_valid(const char *name);
|
||||||
bool dnssd_srv_type_is_valid(const char *name);
|
bool dnssd_srv_type_is_valid(const char *name);
|
||||||
bool dns_service_name_is_valid(const char *name);
|
bool dns_service_name_is_valid(const char *name);
|
||||||
|
bool dns_subtype_name_is_valid(const char *name);
|
||||||
|
|
||||||
int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
|
int dns_service_join(const char *name, const char *type, const char *domain, char **ret);
|
||||||
int dns_service_split(const char *joined, char **ret_name, char **ret_type, char **ret_domain);
|
int dns_service_split(const char *joined, char **ret_name, char **ret_type, char **ret_domain);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user