| /** @file |
| * @brief DNS Service Discovery |
| */ |
| |
| /* |
| * Copyright (c) 2020 Friedt Professional Engineering Services, Inc |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_NET_DNS_SD_H_ |
| #define ZEPHYR_INCLUDE_NET_DNS_SD_H_ |
| |
| #include <stdint.h> |
| #include <sys/byteorder.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * @brief DNS Service Discovery |
| * |
| * @details This API enables services to be advertised via DNS. To |
| * advvertise a service, system or application code should use |
| * @ref DNS_SD_REGISTER_TCP_SERVICE or |
| * @ref DNS_SD_REGISTER_UDP_SERVICE. |
| * |
| * @see <a href="https://tools.ietf.org/html/rfc6763">RFC 6763</a> |
| * |
| * @defgroup dns_sd DNS Service Discovery |
| * @ingroup networking |
| * @{ |
| */ |
| |
| /** RFC 1034 Section 3.1 */ |
| #define DNS_SD_INSTANCE_MIN_SIZE 1 |
| /** RFC 1034 Section 3.1, RFC 6763 Section 7.2 */ |
| #define DNS_SD_INSTANCE_MAX_SIZE 63 |
| /** RFC 6763 Section 7.2 - inclusive of underscore */ |
| #define DNS_SD_SERVICE_MIN_SIZE 2 |
| /** RFC 6763 Section 7.2 - inclusive of underscore */ |
| #define DNS_SD_SERVICE_MAX_SIZE 16 |
| /** RFC 6763 Section 4.1.2 */ |
| #define DNS_SD_SERVICE_PREFIX '_' |
| /** RFC 6763 Section 4.1.2 - either _tcp or _udp (case insensitive) */ |
| #define DNS_SD_PROTO_SIZE 4 |
| /** ICANN Rules for TLD naming */ |
| #define DNS_SD_DOMAIN_MIN_SIZE 2 |
| /** RFC 1034 Section 3.1, RFC 6763 Section 7.2 */ |
| #define DNS_SD_DOMAIN_MAX_SIZE 63 |
| |
| /** |
| * Minimum number of segments in a fully-qualified name |
| * |
| * This reqpresents FQN's of the form below |
| * ``` |
| * <sn>._tcp.<domain>. |
| * ``` |
| * Currently sub-types and service domains are unsupported and only the |
| * "local" domain is supported. Specifically, that excludes the following: |
| * ``` |
| * <sub>._sub.<sn>._tcp.<servicedomain>.<parentdomain>. |
| * ``` |
| * @see <a href="https://datatracker.ietf.org/doc/html/rfc6763">RFC 6763</a>, Section 7.2. |
| */ |
| #define DNS_SD_MIN_LABELS 3 |
| /** |
| * Maximum number of segments in a fully-qualified name |
| * |
| * This reqpresents FQN's of the form below |
| * ``` |
| * <instance>.<sn>._tcp.<domain>. |
| * ``` |
| * |
| * Currently sub-types and service domains are unsupported and only the |
| * "local" domain is supported. Specifically, that excludes the following: |
| * ``` |
| * <sub>._sub.<sn>._tcp.<servicedomain>.<parentdomain>. |
| * ``` |
| * @see <a href="https://datatracker.ietf.org/doc/html/rfc6763">RFC 6763</a>, Section 7.2. |
| */ |
| #define DNS_SD_MAX_LABELS 4 |
| |
| /** |
| * @brief Register a service for DNS Service Discovery |
| * |
| * This macro should be used for advanced use cases. Two simple use cases are |
| * when a custom @p domain or a custom (non-standard) @p proto is required. |
| * |
| * Another use case is when the port number is not preassigned. That could |
| * be for a number of reasons, but the most common use case would be for |
| * ephemeral port usage - i.e. when the service is bound using port number 0. |
| * In that case, Zephyr (like other OS's) will simply choose an unused port. |
| * When using ephemeral ports, it can be helpful to assign @p port to the |
| * @ref sockaddr_in.sin_port field of an IPv4 @ref sockaddr_in, or to the |
| * @ref sockaddr_in6.sin6_port field of an IPv6 @ref sockaddr_in6. |
| * |
| * The service can be referenced using the @p id variable. |
| * |
| * @param id variable name for the DNS-SD service record |
| * @param instance name of the service instance such as "My HTTP Server" |
| * @param service name of the service, such as "_http" |
| * @param proto protocol used by the service - either "_tcp" or "_udp" |
| * @param domain the domain of the service, such as "local" |
| * @param text information for the DNS TXT record |
| * @param port a pointer to the port number that this service will use |
| */ |
| #define DNS_SD_REGISTER_SERVICE(id, instance, service, proto, domain, \ |
| text, port) \ |
| static const STRUCT_SECTION_ITERABLE(dns_sd_rec, id) = { \ |
| instance, \ |
| service, \ |
| proto, \ |
| domain, \ |
| (const char *)text, \ |
| sizeof(text) - 1, \ |
| port \ |
| } |
| |
| /** |
| * @brief Register a TCP service for DNS Service Discovery |
| * |
| * This macro can be used for service advertisement using DNS-SD. |
| * |
| * The service can be referenced using the @p id variable. |
| * |
| * Example (with TXT): |
| * @code{c} |
| * #include <net/dns_sd.h> |
| * static const bar_txt[] = { |
| * "\x06" "path=/" |
| * "\x0f" "this=is the way" |
| * "\x0e" "foo or=foo not" |
| * "\x17" "this=has\0embedded\0nulls" |
| * "\x04" "true" |
| * }; |
| * // Possibly use an ephemeral port |
| * // Possibly only assign bar_port when the service is running |
| * static uint16_t bar_port; |
| * DNS_SD_REGISTER_TCP_SERVICE(bar, CONFIG_NET_HOSTNAME, |
| * "_bar", "local", bar_txt, &bar_port); |
| * @endcode{c} |
| * |
| * TXT records begin with a single length byte (hex-encoded) |
| * and contain key=value pairs. Thus, the length of the key-value pair |
| * must not exceed 255 bytes. Care must be taken to ensure that the |
| * encoded length value is correct. |
| * |
| * For additional rules on TXT encoding, see RFC 6763, Section 6. |
| |
| * @param id variable name for the DNS-SD service record |
| * @param instance name of the service instance such as "My HTTP Server" |
| * @param service name of the service, such as "_http" |
| * @param domain the domain of the service, such as "local" |
| * @param text information for the DNS TXT record |
| * @param port the port number that this service will use |
| * |
| * @see <a href="https://tools.ietf.org/html/rfc6763">RFC 6763</a> |
| */ |
| #define DNS_SD_REGISTER_TCP_SERVICE(id, instance, service, domain, text, \ |
| port) \ |
| static const uint16_t id ## _port = sys_cpu_to_be16(port); \ |
| DNS_SD_REGISTER_SERVICE(id, instance, service, "_tcp", domain, \ |
| text, &id ## _port) |
| |
| /** |
| * @brief Register a UDP service for DNS Service Discovery |
| * |
| * This macro can be used for service advertisement using DNS-SD. |
| * |
| * The service can be referenced using the @p id variable. |
| * |
| * Example (no TXT): |
| * @code{c} |
| * #include <net/dns_sd.h> |
| * #include <sys/byteorder.h> |
| * static const foo_port = sys_cpu_to_be16(4242); |
| * DNS_SD_REGISTER_UDP_SERVICE(foo, CONFIG_NET_HOSTNAME, |
| * "_foo", DNS_SD_EMPTY_TXT, &foo_port); |
| * @endcode{c} |
| * |
| * @param id variable name for the DNS-SD service record |
| * @param instance name of the service instance such as "My TFTP Server" |
| * @param service name of the service, such as "_tftp" |
| * @param domain the domain of the service, such as "local" or "zephyrproject.org" |
| * @param text information for the DNS TXT record |
| * @param port a pointer to the port number that this service will use |
| * |
| * @see <a href="https://tools.ietf.org/html/rfc6763">RFC 6763</a> |
| */ |
| #define DNS_SD_REGISTER_UDP_SERVICE(id, instance, service, domain, text, \ |
| port) \ |
| static const uint16_t id ## _port = sys_cpu_to_be16(port); \ |
| DNS_SD_REGISTER_SERVICE(id, instance, service, "_udp", domain, \ |
| text, &id ## _port) |
| |
| /** Empty DNS-SD TXT specifier */ |
| #define DNS_SD_EMPTY_TXT dns_sd_empty_txt |
| |
| /** @cond INTERNAL_HIDDEN */ |
| |
| /** |
| * @brief DNS Service Discovery record |
| * |
| * This structure used in the implementation of RFC 6763 and should not |
| * need to be accessed directly from application code. |
| * |
| * The @a port pointer must be non-NULL. When the value in @a port |
| * is non-zero, the service is advertized as being on that particular |
| * port. When the value in @a port is zero, then the service is not |
| * advertised. |
| * |
| * Thus, it is possible for multiple services to advertise on a |
| * particular port if they hard-code the port. |
| * |
| * @internal |
| * |
| * @see <a href="https://tools.ietf.org/html/rfc6763">RFC 6763</a> |
| */ |
| struct dns_sd_rec { |
| /** <Instance> - e.g. "My HTTP Server" */ |
| const char *instance; |
| /** Top half of the <Service> such as "_http" */ |
| const char *service; |
| /** Bottom half of the <Service> "_tcp" or "_udp" */ |
| const char *proto; |
| /** <Domain> such as "local" or "zephyrproject.org" */ |
| const char *domain; |
| /** DNS TXT record */ |
| const char *text; |
| /** Size (in bytes) of the DNS TXT record */ |
| size_t text_size; |
| /** A pointer to the port number used by the service */ |
| const uint16_t *port; |
| }; |
| |
| /** |
| * @brief Empty TXT specifier for DNS-SD |
| * |
| * @internal |
| */ |
| extern const char dns_sd_empty_txt[1]; |
| /** |
| * @brief Wildcard Port specifier for DNS-SD |
| * |
| * @internal |
| */ |
| extern const uint16_t dns_sd_port_zero; |
| |
| /** @endcond */ |
| |
| /** |
| * @brief Obtain the size of DNS-SD TXT data |
| * |
| * @param rec the record to in question |
| * @return the size of the text field |
| */ |
| static inline size_t dns_sd_txt_size(const struct dns_sd_rec *rec) |
| { |
| return rec->text_size; |
| } |
| |
| /** |
| * @brief Check if @a rec is a DNS-SD Service Type Enumeration |
| * |
| * DNS-SD Service Type Enumeration is used by network tooling to |
| * acquire a list of all mDNS-advertised services belonging to a |
| * particular host on a particular domain. |
| * |
| * For example, for the domain '.local', the equivalent query |
| * would be '_services._dns-sd._udp.local'. |
| * |
| * Currently, only the '.local' domain is supported. |
| * |
| * @see <a href="https://datatracker.ietf.org/doc/html/rfc6763#section-9">Service Type Enumeration, RFC 6763</a>. |
| * |
| * @param rec the record to in question |
| * @return true if @a rec is a DNS-SD Service Type Enumeration |
| */ |
| bool dns_sd_is_service_type_enumeration(const struct dns_sd_rec *rec); |
| |
| /** |
| * @brief Create a wildcard filter for DNS-SD records |
| * |
| * @param filter a pointer to the filter to use |
| */ |
| void dns_sd_create_wildcard_filter(struct dns_sd_rec *filter); |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| }; |
| #endif |
| |
| #endif /* ZEPHYR_INCLUDE_NET_DNS_SD_H_ */ |