1 /* 2 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef DNS_SD_H_ 8 #define DNS_SD_H_ 9 10 #include <stdbool.h> 11 #include <stdint.h> 12 #include <string.h> 13 14 #include <net/dns_sd.h> 15 #include <net/net_ip.h> 16 17 #include "dns_pack.h" 18 19 /* TODO: Move these into Kconfig */ 20 #define DNS_SD_PTR_TTL 4500 21 #define DNS_SD_TXT_TTL 4500 22 #define DNS_SD_SRV_TTL 120 23 #define DNS_SD_A_TTL 120 24 #define DNS_SD_AAAA_TTL 120 25 26 #define DNS_SD_PTR_MASK (NS_CMPRSFLGS << 8) 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #define DNS_SD_FOREACH(it) \ 33 STRUCT_SECTION_FOREACH(dns_sd_rec, it) 34 35 /** 36 * @brief Extract labels from a DNS-SD PTR query 37 * 38 * ``` 39 * <sn>._tcp.<domain>. 40 * <instance>.<sn>._tcp.<domain>. 41 * ``` 42 * 43 * Currently sub-types and service domains are unsupported and only the 44 * "local" domain is supported. Specifically, that excludes the following: 45 * ``` 46 * <sub>._sub.<sn>._tcp.<servicedomain>.<parentdomain>. 47 * ``` 48 * 49 * @param query a pointer to the start of the query 50 * @param query_size the number of bytes contained in the query 51 * @param[out] record the DNS-SD record to initialize and populate 52 * @param label array of pointers to suitably sized buffers 53 * @param size array of sizes for each buffer in @p label 54 * @param[inout] n number of elements in @p label and @p size 55 * 56 * @return on success, number of bytes read from @p query 57 * @return on failure, a negative errno value 58 * 59 * @see <a href="https://datatracker.ietf.org/doc/html/rfc6763">RFC 6763</a>, Section 7.2. 60 */ 61 int dns_sd_query_extract(const uint8_t *query, size_t query_size, struct dns_sd_rec *record, 62 char **label, size_t *size, size_t *n); 63 64 /** 65 * @brief Extract the Service, Protocol, and Domain from a DNS-SD PTR query 66 * 67 * This function zero-initializes @p record and populates the appropriate 68 * fields so that @p record may be subsequently passed to @ref dns_sd_rec_match. 69 * 70 * If a query with a supported format is found, the function returns the 71 * length of the initial, variable-length portion of the query. 72 * 73 * For example, if the query begins with "._foo._tcp.local.", where 74 * the '.' character represents a length of the subsequent string value, 75 * then this function will return 17. 76 * 77 * @param query a pointer to the start of the query 78 * @param query_size the number of bytes contained in the query 79 * @param[out] record the DNS-SD record to initialize and populate 80 * @param service buffer to store the null-terminated service 81 * @param service_size the size of @p service 82 * @param proto buffer to store the null-terminated proto 83 * @param proto_size the size of @p proto 84 * @param domain buffer to store the null-terminated domain 85 * @param domain_size the size of @p domain 86 * @return on success, a positive number representing length of the query 87 * @return on failure, a negative errno value 88 */ 89 __deprecated 90 int dns_sd_extract_service_proto_domain(const uint8_t *query, 91 size_t query_size, struct dns_sd_rec *record, char *service, 92 size_t service_size, char *proto, size_t proto_size, 93 char *domain, size_t domain_size); 94 95 /** 96 * @brief See if the DNS SD @p filter matches the @p record 97 * 98 * The fields in @p filter should be populated with filter elements to 99 * identify a possible match. If pointer fields are set to NULL, they 100 * act as a wildcard in the matching process. I.e. they will match 101 * anything. Similarly, the @ref dns_sd_rec.port field may be set to 0 102 * to be used as a wildcard. 103 * 104 * The @ref dns_sd_rec.text and @ref dns_ds_rec.text_size fields 105 * are not included in the matching process. 106 * 107 * For example, the filter below can be used to match any 108 * "_http._tcp" records. 109 * 110 * @code{c} 111 * const struct dns_sd_rec *it; 112 * struct dns_sd_rec filter = { 113 * // match any instance 114 * .instance = NULL, 115 * // match records with service "_http" 116 * .service = "_http", 117 * // match records with protocol "_tcp" 118 * .proto = "_tcp", 119 * // match any domain 120 * .domain = NULL, 121 * // match any port 122 * .port = 0, 123 * }; 124 * 125 * DNS_SD_FOREACH(it) { 126 * if (dns_sd_rec_match(it, filter)) { 127 * // found a match! 128 * } 129 * } 130 * @endcode{c} 131 * 132 * @param record The reference DNS-SD record 133 * @param filter The DNS-SD record filter 134 * 135 * @return true if the @p record matches the @p filter 136 * @return false if @p record is not a match for @p filter 137 * @return false if either @p record or @p filter are invalid 138 */ 139 bool dns_sd_rec_match(const struct dns_sd_rec *record, 140 const struct dns_sd_rec *filter); 141 142 /** 143 * @brief Handle a DNS PTR Query with DNS Service Discovery 144 * 145 * This function should be called once for each DNS-SD record that 146 * matches a particular DNS PTR query. 147 * 148 * If there is no IPv4 address to advertise, then @p addr4 should be 149 * NULL. 150 * 151 * If there is no IPv6 address to advertise, then @p addr6 should be 152 * NULL. 153 * 154 * @param inst the DNS-SD record to advertise 155 * @param addr4 pointer to the IPv4 address 156 * @param addr6 pointer to the IPv6 address 157 * @param buf output buffer 158 * @param buf_size size of the output buffer 159 * 160 * @return on success, number of bytes written to @p buf 161 * @return on failure, a negative errno value 162 */ 163 int dns_sd_handle_ptr_query(const struct dns_sd_rec *inst, 164 const struct in_addr *addr4, const struct in6_addr *addr6, 165 uint8_t *buf, uint16_t buf_size); 166 167 /** 168 * @brief Handle a Service Type Enumeration with DNS Service Discovery 169 * 170 * This function should be called once for each type of advertised service. 171 * 172 * @param service the DNS-SD service to advertise 173 * @param addr4 pointer to the IPv4 address 174 * @param addr6 pointer to the IPv6 address 175 * @param buf output buffer 176 * @param buf_size size of the output buffer 177 * 178 * @return on success, number of bytes written to @p buf 179 * @return on failure, a negative errno value 180 */ 181 int dns_sd_handle_service_type_enum(const struct dns_sd_rec *service, 182 const struct in_addr *addr4, const struct in6_addr *addr6, 183 uint8_t *buf, uint16_t buf_size); 184 185 #ifdef __cplusplus 186 }; 187 #endif 188 189 #endif /* DNS_SD_H_ */ 190