BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
fnet_mdns.c
00001 /************************************************************************** 00002 * 00003 * Copyright (c) 2017, Arm Limited and affiliates. 00004 * Copyright 2016 by Andrey Butok. FNET Community. 00005 * 00006 *************************************************************************** 00007 * 00008 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00009 * not use this file except in compliance with the License. 00010 * You may obtain a copy of the License at 00011 * 00012 * http://www.apache.org/licenses/LICENSE-2.0 00013 * 00014 * Unless required by applicable law or agreed to in writing, software 00015 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00016 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00017 * See the License for the specific language governing permissions and 00018 * limitations under the License. 00019 * 00020 **********************************************************************/ 00021 /*! 00022 * @brief mDNS (Bonjour) Server/Responder implementation (RFC6762). 00023 * 00024 ***************************************************************************/ 00025 #include "fnet.h" 00026 #include <stdio.h> 00027 00028 #if FNET_CFG_MDNS 00029 00030 #include "fnet_mdns.h" 00031 #include "services/dns/fnet_dns_prv.h" //TBD use common DNS definitions and use common code for DNS, mDNS and LLMNR. 00032 #include "fnet_netif_prv.h" 00033 00034 #if FNET_CFG_DEBUG_MDNS && FNET_CFG_DEBUG 00035 #define FNET_DEBUG_MDNS FNET_DEBUG 00036 #else 00037 #define FNET_DEBUG_MDNS(...) do{}while(0) 00038 #endif 00039 00040 /* mDNS requires multicast support.*/ 00041 #if FNET_CFG_MULTICAST == 0 00042 #error FNET_CFG_MULTICAST must be enabled for MDNS 00043 #endif 00044 00045 /************************************************************************ 00046 * Definitions 00047 *************************************************************************/ 00048 /* MDNS settings */ 00049 #define FNET_MDNS_DOMAIN_NAME "local" /* mDNS top level domain (TLD) name: local */ 00050 #define FNET_MDNS_PORT FNET_CFG_MDNS_PORT /* mDNS port */ 00051 00052 #define FNET_MDNS_WAIT 250 /* Wait 250ms to check domain name. */ 00053 #define FNET_MDNS_PROBE_WAIT (5*1000) /* Wait 5 seconds before trying again. */ 00054 #define FNET_MDNS_PROBE_DEFER_WAIT (1*1000) /* Defers to the winning host by waiting one second. */ 00055 #define FNET_MDNS_SHARED_RESPONSE_DELAY (200) /* Delay for shared response. Random amount of time selected with uniform random distribution in the range 20-120 ms. */ 00056 00057 #define FNET_MDNS_ANNOUNCE_COUNT (2) /* The Multicast DNS responder MUST send at least two unsolicited responses. */ 00058 #define FNET_MDNS_ANNOUNCE_INTERVAL (1000) /* one second apart. */ 00059 00060 #define FNET_MDNS_HEADER_CLASS_IN 0x01 /* Internet */ 00061 #define FNET_MDNS_HEADER_CACHE_FLUSH 0x8000 /* Cache flush */ 00062 00063 #define FNET_MDNS_DOMAIN_NAME_COMPRESSION 0xC0 /* Domain Name Compression flag */ 00064 00065 /* MDNS Header Flags.*/ 00066 #define FNET_MDNS_HEADER_FLAGS_QR 0x8000 00067 #define FNET_MDNS_HEADER_FLAGS_OPCODE 0x7800 00068 #define FNET_MDNS_HEADER_FLAGS_TC 0x0200 /* Trancation Flag */ 00069 #define FNET_MDNS_HEADER_FLAGS_C 0x0400 00070 00071 #define FNET_MDNS_PACKET_SIZE 512 /* mDNS maximum packet size*/ 00072 00073 /* [RFC6762] All Multicast DNS responses (including responses sent via unicast) 00074 * SHOULD be sent with IP TTL set to 255. This is recommended to 00075 * provide backwards-compatibility with older Multicast DNS queriers 00076 * (implementing a draft version of this document, posted in February 00077 * 2004) that check the IP TTL on reception to determine whether the 00078 * packet originated on the local link. These older queriers discard 00079 * all packets with TTLs other than 255.*/ 00080 #define FNET_MDNS_IP_TTL (255u) 00081 00082 #define FNET_MDNS_NAME_MAX 64 /**< Maximum length for MDNS name. */ 00083 #define FNET_MDNS_HOST_NAME_LEN_MAX (FNET_MDNS_NAME_MAX+sizeof(" 4294967295")) /**< Maximum length of the host name. */ 00084 #define FNET_MDNS_RR_NAME_LEN_MAX (FNET_MDNS_HOST_NAME_LEN_MAX+sizeof("._saccessdata-f2d._tcp."FNET_MDNS_DOMAIN_NAME)) /**< Maximum length of the RR name. */ 00085 /* Maximum RR record size of probe RR - SRV RR*/ 00086 #define FNET_MDNS_RR_PROBE_LEN_MAX (FNET_MDNS_RR_NAME_LEN_MAX + sizeof(fnet_mdns_rr_header_t) + sizeof(fnet_mdns_rr_data_srv_t) + FNET_MDNS_RR_NAME_LEN_MAX ) /**< Maximum length of the SRV RR. */ 00087 00088 /* Error strings.*/ 00089 #define FNET_MDNS_ERR_PARAMS "MDNS: Wrong input parameters." 00090 #define FNET_MDNS_ERR_SOCKET_CREATION "MDNS: Socket creation error." 00091 #define FNET_MDNS_ERR_SOCKET_BIND "MDNS: Socket Error during bind." 00092 #define FNET_MDNS_ERR_SERVICE "MDNS: Service registration is failed." 00093 #define FNET_MDNS_ERR_IS_INITIALIZED "MDNS: Is already initialized." 00094 #define FNET_MDNS_ERR_JOIN_MULTICAST "MDNS: Joining to multicast group is failed." 00095 00096 /******************************************************************************* 00097 * Types definitions 00098 *******************************************************************************/ 00099 /* RR record types */ 00100 typedef enum 00101 { 00102 FNET_MDNS_RR_PTR = 0x000C, /* PTR record */ 00103 FNET_MDNS_RR_NSEC = 0x002F, /* NSEC record */ 00104 FNET_MDNS_RR_TXT = 0x0010, /* TXT record */ 00105 FNET_MDNS_RR_ANY = 0x00FF, /* ANY record */ 00106 FNET_MDNS_RR_SRV = 0x0021, /* SRV record */ 00107 FNET_MDNS_RR_OPT = 0x0029, /* OPT record */ 00108 FNET_MDNS_RR_A = 0x0001, /* IPv4 record */ 00109 FNET_MDNS_RR_AAAA = 0x001C, /* IPv6 record */ 00110 }fnet_mdns_rr_type_t; 00111 00112 /* Query RR record types (bitmap). */ 00113 typedef enum 00114 { 00115 FNET_MDNS_QUERY_NONE = 0, /* No record */ 00116 FNET_MDNS_QUERY_PTR = 1<<0, /* PTR record */ 00117 FNET_MDNS_QUERY_TXT = 1<<1, /* TXT record */ 00118 FNET_MDNS_QUERY_SRV = 1<<2, /* SRV record */ 00119 FNET_MDNS_QUERY_A = 1<<3, /* IPv4 record */ 00120 FNET_MDNS_QUERY_AAAA = 1<<4, /* IPv6 record */ 00121 FNET_MDNS_QUERY_ANY = (FNET_MDNS_QUERY_PTR | FNET_MDNS_QUERY_TXT | FNET_MDNS_QUERY_SRV | FNET_MDNS_QUERY_A | FNET_MDNS_QUERY_AAAA) /* ANY record */ 00122 } fnet_mdns_query_type_t; 00123 00124 /* mDNS-server states. */ 00125 typedef enum 00126 { 00127 FNET_MDNS_STATE_DISABLED = 0, /**< @brief mDNS server is not initialized or released. */ 00128 FNET_MDNS_STATE_PROBING_WAIT, /**< @brief mDNS server is waiting five seconds after any failed probe attempt before trying again. */ 00129 /*RFC6762: Whenever a Multicast DNS responder starts up, wakes up from sleep, 00130 receives an indication of a network interface "Link Change" event, or 00131 has any other reason to believe that its network connectivity may 00132 have changed in some relevant way, it MUST perform the two startup 00133 steps below: Probing (Section 8.1) and Announcing (Section 8.3).*/ 00134 FNET_MDNS_STATE_PROBING, /**< @brief mDNS server is sending probe queries. */ 00135 FNET_MDNS_STATE_ANNOUNCING, /**< @brief mDNS server is sending aannouncements. */ 00136 FNET_MDNS_STATE_WAITING_REQUEST /**< @brief mDNS server is waiting for a request from a mDNS client. */ 00137 } fnet_mdns_state_t; 00138 00139 typedef struct fnet_mdns_service_if_s 00140 { 00141 const char *service_type; /* Service Type. Null-terminated string. Example _http._tcp*/ 00142 fnet_uint16_t service_port; /* Service Port number (in network byte order). */ 00143 const fnet_uint8_t *(*service_get_txt)(void); /* Call-back function, which returns pointer to the service TXT record (null-terminated). 00144 * If the service does not provide any TXT record, this parameter must be set to NULL. */ 00145 fnet_uint16_t offset_service_name; /* Pointer to service name. Offset from the start of the DNS message. Used for Domain Name Compression. */ 00146 fnet_uint16_t offset_service_type; /* Pointer to service type. Offset from the start of the DNS message. Used for Domain Name Compression. */ 00147 fnet_mdns_query_type_t response_type; /* Response type used in mDNS response.*/ 00148 } fnet_mdns_service_if_t; 00149 00150 /* MDNS interface structure */ 00151 typedef struct fnet_mdns_if 00152 { 00153 fnet_mdns_state_t state; /* Current state */ 00154 fnet_poll_desc_t service_descriptor; /* Service descriptor. */ 00155 fnet_netif_desc_t netif; /* Network interface descriptor. */ 00156 fnet_uint32_t rr_ttl; /* Resource record TTL */ 00157 fnet_uint32_t rr_ttl_ip; /* Resource record TTL for IP header, hop-count limit for a packet */ 00158 fnet_address_family_t addr_family; /* Address family (IPv6 or IPv4 or both) the server will listen and send */ 00159 fnet_size_t name_length; /* Length of the service name without index postfix */ 00160 char host_name[FNET_MDNS_HOST_NAME_LEN_MAX+1]; /* Parsed "name" containing only legal symbols, optionally appended with host_name_count */ 00161 fnet_uint32_t host_name_count; /* Count of try device name */ 00162 char service_name[FNET_MDNS_HOST_NAME_LEN_MAX+1]; /* Service name, optionally appended with host_name_count */ 00163 fnet_uint32_t probe_count; /* Number of sent probe queries without name conflict.*/ 00164 fnet_uint32_t announce_count; /* Count of sent annoncemnts */ 00165 fnet_socket_t socket_listen; /* Listening socket.*/ 00166 fnet_uint32_t host_name_conflict_timestamp; /* Last Conflict timestamp. */ 00167 fnet_uint32_t probe_wait_interval; /* Lenghth of time before next probe attempt. */ 00168 fnet_uint32_t send_timestamp; /* Last Send timestamp.*/ 00169 fnet_uint8_t buffer[FNET_MDNS_PACKET_SIZE]; /* TX/RX Data buffer. */ 00170 fnet_uint16_t offset_host_name; /* Pointer to host name. Offset from the start of the DNS message. Used for Domain Name Compression. */ 00171 fnet_bool_t is_truncated; /* RFC6762:In query messages, if the TC bit is set, it means that additional Known-Answer records may be following shortly. A responder SHOULD 00172 * record this fact, and wait for those additional Known-Answer records, before deciding whether to respond.*/ 00173 fnet_bool_t is_legacy_unicast; /* If the source UDP port in a received Multicast DNS query is not port 5353*/ 00174 fnet_bool_t is_shared; /* Response contains only shared records. 00175 * RFC 6762: In any case where there may be multiple responses, such as queries 00176 * where the answer is a member of a shared resource record set, each 00177 * responder SHOULD delay its response by a random amount of time 00178 * selected with uniform random distribution in the range 20-120 ms. */ 00179 fnet_uint32_t is_shared_timestamp; /* Timestamp of shared response query.*/ 00180 struct sockaddr remote_address; /* Remote address.*/ 00181 fnet_address_family_t response_address_family; /* Address family used in mDNS response.*/ 00182 fnet_mdns_query_type_t response_type; /* Response type used in mDNS response.*/ 00183 fnet_mdns_service_if_t service_if_list[FNET_CFG_MDNS_SERVICE_MAX]; /* Service Discovery List */ 00184 } fnet_mdns_if_t; 00185 00186 /* MDNS packet header - count of all records */ 00187 FNET_COMP_PACKED_BEGIN 00188 typedef struct fnet_mdns_header_s 00189 { 00190 fnet_uint16_t ip FNET_COMP_PACKED; 00191 fnet_uint16_t flags FNET_COMP_PACKED; /* flags */ 00192 fnet_uint16_t qdcount FNET_COMP_PACKED; /* count of questions */ 00193 fnet_uint16_t ancount FNET_COMP_PACKED; /* count of answers */ 00194 fnet_uint16_t nscount FNET_COMP_PACKED; /* Authority Record Count. Number of RR in the Authority section. (mDNS - name server). */ 00195 fnet_uint16_t arcount FNET_COMP_PACKED; /* count of additional */ 00196 } fnet_mdns_header_t; 00197 FNET_COMP_PACKED_END 00198 00199 /* MDNS record header */ 00200 FNET_COMP_PACKED_BEGIN 00201 typedef struct fnet_mdns_rr_header_s 00202 { 00203 fnet_uint16_t type FNET_COMP_PACKED; /* RR type */ 00204 fnet_uint16_t rr_class FNET_COMP_PACKED; /* RR class */ 00205 fnet_uint32_t ttl FNET_COMP_PACKED; /* time to live (in seconds) */ 00206 fnet_uint16_t data_length FNET_COMP_PACKED; /* length of data */ 00207 } fnet_mdns_rr_header_t; 00208 FNET_COMP_PACKED_END 00209 00210 /* MDNS query Question Entry header */ 00211 FNET_COMP_PACKED_BEGIN 00212 typedef struct fnet_mdns_qe_header_s 00213 { 00214 fnet_uint16_t type FNET_COMP_PACKED; /* Question type */ 00215 fnet_uint16_t rr_class FNET_COMP_PACKED; /* Question class */ 00216 } fnet_mdns_qe_header_t; 00217 FNET_COMP_PACKED_END 00218 00219 /* MDNS data RR SRV */ 00220 FNET_COMP_PACKED_BEGIN 00221 typedef struct fnet_mdns_rr_data_srv_s 00222 { 00223 fnet_uint16_t priority FNET_COMP_PACKED; 00224 fnet_uint16_t weight FNET_COMP_PACKED; 00225 fnet_uint16_t port FNET_COMP_PACKED; 00226 } fnet_mdns_rr_data_srv_t; 00227 FNET_COMP_PACKED_END 00228 00229 static void fnet_mdns_poll( void *fnet_mdns_if_p ); 00230 static fnet_uint8_t * fnet_mdns_add_domain_name(fnet_uint8_t *buf, fnet_uint32_t buf_size, const char * domain_name); 00231 static void fnet_mdns_send_response(fnet_mdns_if_t *mdns_if, fnet_uint32_t ttl, fnet_uint32_t ttl_ip); 00232 static fnet_uint8_t * fnet_mdns_add_rr_header(fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_rr_type_t type, fnet_bool_t flush, fnet_uint32_t ttl, fnet_uint16_t data_length); 00233 static void fnet_mdns_send(fnet_mdns_if_t *mdns_if, fnet_address_family_t address_family, fnet_uint8_t * buffer, fnet_uint32_t send_size); 00234 static void fnet_mdns_update_name(fnet_mdns_if_t *mdns_if, const fnet_char_t *name); 00235 static void fnet_mdns_update_name_counter(fnet_mdns_if_t *mdns_if); 00236 static void fnet_mdns_change_state(fnet_mdns_if_t *mdns_if, fnet_mdns_state_t state); 00237 static void fnet_mdns_recv(fnet_mdns_if_t *mdns_if); 00238 static void fnet_mdns_send_probe(fnet_mdns_if_t *mdns_if); 00239 static void fnet_mdns_process_simultaneous_probe(fnet_mdns_if_t *mdns_if, const fnet_uint8_t *ns_ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size); 00240 fnet_uint8_t * fnet_mdns_add_rr_txt(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression); 00241 static fnet_uint8_t *fnet_mdns_add_rr_ptr(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t compression); 00242 static fnet_uint8_t * fnet_mdns_add_rr_srv(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression); 00243 #if FNET_CFG_IP4 00244 static fnet_uint8_t * fnet_mdns_add_rr_a(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression); 00245 #endif 00246 static fnet_uint8_t * fnet_mdns_add_rr_aaaa(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression); 00247 static fnet_uint8_t * fnet_mdns_add_qe_any(fnet_uint8_t *buf, fnet_uint32_t buf_size); 00248 static fnet_uint8_t * fnet_mdns_add_host_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_bool_t compression); 00249 static fnet_uint8_t * fnet_mdns_add_service_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_bool_t compression); 00250 static fnet_uint8_t * fnet_mdns_add_service_type_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_bool_t compression); 00251 static fnet_uint8_t * fnet_mdns_add_domain_name_compression(fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint16_t name_offset); 00252 static const fnet_uint8_t *fnet_mdns_get_rr_name(char *rr_name, fnet_uint32_t rr_name_size, const fnet_uint8_t *rr, const fnet_uint8_t *packet); 00253 static fnet_bool_t fnet_mdns_cmp_rr_name(const char * rr_name, const char *name_1, const char *name_2); 00254 static fnet_bool_t fnet_mdns_is_rr_win(fnet_uint8_t *our_rr, const fnet_uint8_t *ns_ptr, fnet_uint16_t ns_count, fnet_uint8_t *packet); 00255 static const fnet_uint8_t *fnet_mdns_get_ns(fnet_uint8_t *packet, fnet_uint32_t packet_size); 00256 static const fnet_uint8_t *fnet_mdns_get_an(const fnet_uint8_t *packet, fnet_uint32_t packet_size); 00257 static fnet_int32_t fnet_mdns_cmp_rr(fnet_uint8_t *our_rr, const fnet_uint8_t **rr, const fnet_uint8_t *packet); 00258 static fnet_mdns_query_type_t fnet_mdns_get_query_type(fnet_uint16_t type); 00259 static void fnet_mdns_process_duplicate_answer(fnet_mdns_if_t *mdns_if, const fnet_uint8_t *an_ptr, const fnet_uint8_t *packet, fnet_uint32_t packet_size); 00260 static fnet_bool_t fnet_mdns_is_our_host_name(fnet_mdns_if_t *mdns_if, char *host_name); 00261 static fnet_mdns_service_if_t *fnet_mdns_get_service_by_name(fnet_mdns_if_t *mdns_if, char *service_name); 00262 static fnet_mdns_service_if_t *fnet_mdns_get_service_by_type(fnet_mdns_if_t *mdns_if, char *service_name); 00263 static void fnet_mdns_send_announcement(fnet_mdns_if_t *mdns_if, fnet_uint32_t ttl, fnet_uint32_t ttl_ip); 00264 static fnet_bool_t fnet_mdns_cmp_name(const char **rr_name_p, const char *name); 00265 static const fnet_uint8_t *fnet_mdns_process_query(fnet_mdns_if_t *mdns_if, fnet_address_family_t address_family, const fnet_uint8_t *ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size); 00266 static const fnet_uint8_t *fnet_mdns_process_response(fnet_mdns_if_t *mdns_if, const fnet_uint8_t * ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size); 00267 static fnet_int32_t fnet_mdns_cmp_rr(fnet_uint8_t *our_rr, const fnet_uint8_t **rr, const fnet_uint8_t *packet); 00268 static fnet_uint32_t fnet_mdns_key_value_record_len(const fnet_uint8_t *record); 00269 00270 /* RFC 6762: The destination UDP port in all Multicast DNS responses MUST be 5353, 00271 and the destination address MUST be the mDNS IPv4 link-local 00272 multicast address 224.0.0.251 or its IPv6 equivalent FF02::FB, except 00273 when generating a reply to a query that explicitly requested a 00274 unicast response*/ 00275 #define FNET_MDNS_IP4_MULTICAST_ADDR FNET_IP4_ADDR_INIT(224u, 0u, 0u, 251u) 00276 static const fnet_ip6_addr_t fnet_mdns_ip6_multicast_addr = FNET_IP6_ADDR_INIT(0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFB); 00277 00278 /* The MDNS interface list*/ 00279 static fnet_mdns_if_t mdns_if_list[FNET_CFG_MDNS_MAX]; 00280 00281 00282 /************************************************************************ 00283 * DESCRIPTION: Initializes mDNS server/responder. 00284 ************************************************************************/ 00285 fnet_mdns_desc_t fnet_mdns_init( struct fnet_mdns_params *params ) 00286 { 00287 struct fnet_mdns_if *mdns_if = FNET_NULL; 00288 fnet_index_t i; 00289 struct sockaddr local_addr; 00290 fnet_uint32_t option; 00291 fnet_size_t name_length; 00292 fnet_scope_id_t scope_id; 00293 00294 /* Check input paramters. */ 00295 if((params == 0) || (params->netif_desc == 0) || (params->name == 0) 00296 || ((name_length = fnet_strlen(params->name)) == 0u) || (name_length >= FNET_MDNS_NAME_MAX)) 00297 { 00298 FNET_DEBUG_MDNS(FNET_MDNS_ERR_PARAMS); 00299 goto ERROR_1; 00300 } 00301 00302 scope_id = fnet_netif_get_scope_id(params->netif_desc); 00303 if(scope_id == 0) 00304 { 00305 FNET_DEBUG_MDNS(FNET_MDNS_ERR_PARAMS); 00306 goto ERROR_1; 00307 } 00308 00309 /* Try to find free mDNS server descriptor. */ 00310 for(i = 0u; i < FNET_CFG_MDNS_MAX; i++) 00311 { 00312 if(mdns_if_list[i].state == FNET_MDNS_STATE_DISABLED) 00313 { 00314 mdns_if = &mdns_if_list[i]; 00315 } 00316 } 00317 00318 if(mdns_if == FNET_NULL) 00319 { 00320 /* No free mDNS descriptor. */ 00321 FNET_DEBUG_MDNS(FNET_MDNS_ERR_IS_INITIALIZED); 00322 goto ERROR_1; 00323 } 00324 00325 /* Reset interface structure. */ 00326 fnet_memset_zero(mdns_if, sizeof(struct fnet_mdns_if)); 00327 00328 /* Set parameters.*/ 00329 mdns_if->netif = params->netif_desc; 00330 if(params->rr_ttl == 0u) 00331 { 00332 mdns_if->rr_ttl = FNET_CFG_MDNS_RR_TTL; 00333 } 00334 else 00335 { 00336 mdns_if->rr_ttl = params->rr_ttl; 00337 } 00338 00339 /* TTL for AAAA record */ 00340 if(params->rr_ttl_ip == 0u) 00341 { 00342 mdns_if->rr_ttl_ip = FNET_MDNS_IP_TTL; 00343 } 00344 else 00345 { 00346 mdns_if->rr_ttl_ip = params->rr_ttl_ip; 00347 } 00348 00349 option = mdns_if->rr_ttl_ip; 00350 00351 /* Generate host_name.*/ 00352 fnet_mdns_update_name(mdns_if, params->name); 00353 00354 /* Init local socket address.*/ 00355 fnet_memset_zero(&local_addr, sizeof(local_addr)); 00356 if(local_addr.sa_family == AF_UNSPEC) 00357 { 00358 local_addr.sa_family = AF_SUPPORTED; 00359 } 00360 else 00361 { 00362 local_addr.sa_family = params->addr_family; 00363 } 00364 local_addr.sa_port = FNET_MDNS_PORT; 00365 local_addr.sa_scope_id = scope_id; 00366 00367 mdns_if->addr_family = local_addr.sa_family; 00368 00369 /* Create listen socket */ 00370 mdns_if->socket_listen = fnet_socket(local_addr.sa_family, SOCK_DGRAM, 0u); 00371 if(mdns_if->socket_listen == FNET_NULL) 00372 { 00373 FNET_DEBUG_MDNS(FNET_MDNS_ERR_SOCKET_CREATION); 00374 goto ERROR_1; 00375 } 00376 00377 /* Bind socket. */ 00378 if(fnet_socket_bind(mdns_if->socket_listen, &local_addr, sizeof(local_addr)) == FNET_ERR) 00379 { 00380 FNET_DEBUG_MDNS(FNET_MDNS_ERR_SOCKET_BIND); 00381 goto ERROR_2; 00382 } 00383 00384 /* Join Multicast Group.*/ 00385 #if FNET_CFG_IP4 00386 if((local_addr.sa_family & AF_INET) != 0u) 00387 { 00388 struct ip_mreq mreq; /* Multicast group information.*/ 00389 00390 mreq.imr_multiaddr.s_addr = FNET_MDNS_IP4_MULTICAST_ADDR; 00391 mreq.imr_interface = scope_id; 00392 00393 /* Join multicast group. */ 00394 if(fnet_socket_setopt(mdns_if->socket_listen, IPPROTO_IP, IP_ADD_MEMBERSHIP, (fnet_char_t *)&mreq, sizeof(mreq)) == FNET_ERR) 00395 { 00396 FNET_DEBUG_MDNS(FNET_MDNS_ERR_JOIN_MULTICAST); 00397 goto ERROR_2; 00398 } 00399 /* Set IPv4 TTL. */ 00400 fnet_socket_setopt(mdns_if->socket_listen, IPPROTO_IP, IP_MULTICAST_TTL, (fnet_char_t *) &option, sizeof(option)); 00401 } 00402 #endif 00403 #if FNET_CFG_IP6 00404 if((local_addr.sa_family & AF_INET6) != 0u) 00405 { 00406 struct ipv6_mreq mreq6; /* Multicast group information.*/ 00407 00408 FNET_IP6_ADDR_COPY(&fnet_mdns_ip6_multicast_addr, &mreq6.ipv6imr_multiaddr.s6_addr); 00409 mreq6.ipv6imr_interface = scope_id; 00410 00411 /* Join multicast group. */ 00412 if(fnet_socket_setopt(mdns_if->socket_listen, IPPROTO_IPV6, IPV6_JOIN_GROUP, (fnet_char_t *)&mreq6, sizeof(mreq6)) == FNET_ERR) 00413 { 00414 FNET_DEBUG_MDNS(FNET_MDNS_ERR_JOIN_MULTICAST); 00415 goto ERROR_2; 00416 } 00417 00418 /* Set IPv6 Hop Limit. */ 00419 fnet_socket_setopt(mdns_if->socket_listen, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (fnet_char_t *) &option, sizeof(option)); 00420 } 00421 #endif 00422 00423 /* Register service. */ 00424 mdns_if->service_descriptor = fnet_poll_service_register(fnet_mdns_poll, (void *) mdns_if); 00425 if(mdns_if->service_descriptor == 0) 00426 { 00427 FNET_DEBUG_MDNS(FNET_MDNS_ERR_SERVICE); 00428 goto ERROR_2; 00429 } 00430 00431 /* Start probing.*/ 00432 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_PROBING); 00433 00434 return (fnet_mdns_desc_t)mdns_if; 00435 00436 ERROR_2: 00437 fnet_socket_close(mdns_if->socket_listen); 00438 ERROR_1: 00439 return 0; 00440 } 00441 00442 /************************************************************************ 00443 * DESCRIPTION: Registers application-specific service in the mDNS server. 00444 ************************************************************************/ 00445 fnet_mdns_service_desc_t fnet_mdns_service_register(fnet_mdns_desc_t mdns_desc, const fnet_mdns_service_t *service) 00446 { 00447 fnet_mdns_service_desc_t result = 0; 00448 fnet_mdns_if_t *mdns_if = (fnet_mdns_if_t *)mdns_desc; 00449 fnet_index_t i; 00450 00451 if(mdns_if) 00452 { 00453 /* Initialize Service List */ 00454 if(service && service->service_type) 00455 { 00456 00457 if (fnet_strlen(service->service_type) >= FNET_MDNS_NAME_MAX) { 00458 return 0; 00459 } 00460 00461 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 00462 { 00463 /* Find empty service entry.*/ 00464 if(mdns_if->service_if_list[i].service_type == NULL) 00465 { 00466 mdns_if->service_if_list[i].service_type = service->service_type; 00467 mdns_if->service_if_list[i].service_port = service->service_port; 00468 mdns_if->service_if_list[i].service_get_txt = service->service_get_txt; 00469 00470 result = (fnet_mdns_service_desc_t)(&mdns_if->service_if_list[i]); 00471 break; 00472 } 00473 } 00474 } 00475 00476 /* Probing new service */ 00477 if(result && ((mdns_if->state == FNET_MDNS_STATE_WAITING_REQUEST) || (mdns_if->state ==FNET_MDNS_STATE_ANNOUNCING)) ) 00478 { 00479 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_PROBING); /* Start probing.*/ 00480 } 00481 } 00482 00483 return result; 00484 } 00485 00486 /************************************************************************ 00487 * DESCRIPTION: Unregisters application service from the mDNS server. 00488 ************************************************************************/ 00489 void fnet_mdns_service_unregister(fnet_mdns_service_desc_t service_desc) 00490 { 00491 fnet_mdns_service_if_t *service_if = (fnet_mdns_service_if_t *)service_desc; 00492 00493 /* Free service entry.*/ 00494 if(service_if) 00495 { 00496 service_if->service_type = NULL; 00497 } 00498 } 00499 00500 /************************************************************************ 00501 * DESCRIPTION: Sends unsolicited mDNS announcement. 00502 ************************************************************************/ 00503 void fnet_mdns_announce(fnet_mdns_desc_t mdns_desc) 00504 { 00505 fnet_mdns_if_t *mdns_if = (fnet_mdns_if_t *)mdns_desc; 00506 00507 if(mdns_if) 00508 { 00509 /* RFC6762: At any time, if the rdata of any of a host's Multicast DNS records 00510 changes, the host MUST repeat the Announcing step described above to 00511 update neighboring caches. For example, if any of a host's IP 00512 addresses change, it MUST re-announce those address records. The 00513 host does not need to repeat the Probing step because it has already 00514 established unique ownership of that name.*/ 00515 if((mdns_if->state == FNET_MDNS_STATE_WAITING_REQUEST) 00516 || (mdns_if->state == FNET_MDNS_STATE_ANNOUNCING)) 00517 { 00518 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_ANNOUNCING); 00519 } 00520 } 00521 } 00522 00523 /************************************************************************ 00524 * DESCRIPTION: Releases the mDNS server/responder. 00525 ************************************************************************/ 00526 void fnet_mdns_release(fnet_mdns_desc_t mdns_desc) 00527 { 00528 struct fnet_mdns_if *mdns_if = (struct fnet_mdns_if *)mdns_desc; 00529 00530 if(mdns_if && (mdns_if->state != FNET_MDNS_STATE_DISABLED)) 00531 { 00532 /* Send "goodbye" */ 00533 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_DISABLED ); 00534 00535 fnet_socket_close(mdns_if->socket_listen); 00536 00537 fnet_poll_service_unregister(mdns_if->service_descriptor); /* Delete service.*/ 00538 } 00539 } 00540 00541 /************************************************************************ 00542 * DESCRIPTION: This function returns FNET_TRUE if the mDNS server 00543 * is enabled/initialised. 00544 ************************************************************************/ 00545 fnet_bool_t fnet_mdns_is_enabled(fnet_mdns_desc_t desc) 00546 { 00547 struct fnet_mdns_if *mdns_if = (struct fnet_mdns_if *) desc; 00548 fnet_bool_t result; 00549 00550 if(mdns_if) 00551 { 00552 result = (mdns_if->state == FNET_MDNS_STATE_DISABLED) ? FNET_FALSE : FNET_TRUE; 00553 } 00554 else 00555 { 00556 result = FNET_FALSE; 00557 } 00558 00559 return result; 00560 } 00561 00562 /************************************************************************ 00563 * DESCRIPTION: Generate host and service name. 00564 ************************************************************************/ 00565 static void fnet_mdns_update_name(fnet_mdns_if_t *mdns_if, const fnet_char_t *name) 00566 { 00567 FNET_ASSERT(mdns_if != NULL); 00568 FNET_ASSERT(name != NULL); 00569 00570 fnet_char_t *c; 00571 fnet_size_t length = fnet_strlen(name); 00572 00573 if(length <= FNET_MDNS_NAME_MAX) 00574 { 00575 /* Reset device name counter */ 00576 mdns_if->host_name_count = 0; 00577 00578 /* Save name length.*/ 00579 mdns_if->name_length = fnet_strlen(name); 00580 00581 /* Copy name. */ 00582 fnet_strcpy(mdns_if->host_name, name); 00583 fnet_strcpy(mdns_if->service_name, name); 00584 00585 /* Allow only legal characters in address record names.*/ 00586 for(c = mdns_if->host_name; *c != '\0'; c++) 00587 { 00588 /*7-bit ASCII embedded in an 8 bit byte whose high order bit is always 0.*/ 00589 if((size_t)*c <= 127) 00590 { 00591 /*RFC6762: For names that are restricted to US-ASCII [RFC0020] letters, digits and and hyphens*/ 00592 if( !(((*c<='Z') && (*c>='A'))|| 00593 ((*c<='z') && (*c>='a'))|| 00594 ((*c<='9') && (*c>='0'))|| 00595 (*c=='-') || 00596 (*c=='_') ) ) 00597 { 00598 /* Replace illegal label symbols by '-'*/ 00599 *c = '-'; 00600 } 00601 } 00602 /* else UTF-8 */ 00603 } 00604 } 00605 00606 FNET_DEBUG_MDNS("MDNS: Host-name set to (%s).", mdns_if->host_name); 00607 } 00608 /************************************************************************ 00609 * DESCRIPTION: Update counter of host and service name. 00610 ************************************************************************/ 00611 static void fnet_mdns_update_name_counter(fnet_mdns_if_t *mdns_if) 00612 { 00613 FNET_ASSERT(mdns_if != NULL); 00614 00615 /* Update name counter. */ 00616 mdns_if->host_name_count++; 00617 00618 /* Change name to device (count) */ 00619 if(mdns_if->host_name_count>0) 00620 { 00621 snprintf(&mdns_if->host_name[mdns_if->name_length], (sizeof(mdns_if->host_name) - mdns_if->name_length), "-%d", (int)mdns_if->host_name_count); 00622 snprintf(&mdns_if->service_name[mdns_if->name_length], (sizeof(mdns_if->service_name) - mdns_if->name_length), " %d", (int)mdns_if->host_name_count); 00623 } 00624 else 00625 { 00626 mdns_if->host_name[mdns_if->name_length] = '\0'; 00627 mdns_if->service_name[mdns_if->name_length] = '\0'; 00628 } 00629 00630 FNET_DEBUG_MDNS("MDNS: Host-name set to (%s).", mdns_if->host_name); 00631 } 00632 00633 00634 /************************************************************************ 00635 * DESCRIPTION: mDNS server poll (state machine). 00636 ************************************************************************/ 00637 static void fnet_mdns_poll( void *fnet_mdns_if_p ) 00638 { 00639 struct fnet_mdns_if *mdns_if = (struct fnet_mdns_if *)fnet_mdns_if_p; 00640 00641 if(mdns_if) 00642 { 00643 fnet_mdns_recv(mdns_if); /* Receive mDNS packets. */ 00644 00645 switch(mdns_if->state) 00646 { 00647 case FNET_MDNS_STATE_PROBING_WAIT: 00648 if( (fnet_timer_get_ms() - mdns_if->host_name_conflict_timestamp) > mdns_if->probe_wait_interval ) 00649 { 00650 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_PROBING); /* Start probing.*/ 00651 } 00652 break; 00653 case FNET_MDNS_STATE_PROBING: 00654 /* RFC: 250 ms after the first query, the host should send a second; then, 00655 250 ms after that, a third. */ 00656 if( (fnet_timer_get_ms() - mdns_if->send_timestamp) > FNET_MDNS_WAIT ) 00657 { 00658 /* Any response from this name => try three times */ 00659 if(mdns_if->probe_count < 3) 00660 { 00661 fnet_mdns_send_probe(mdns_if); /* Send next probe.*/ 00662 } 00663 else 00664 { 00665 /* RFC6762: If, by 250 ms after the third probe, no 00666 conflicting Multicast DNS responses have been received, the host may 00667 move to the next step, announcing. */ 00668 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_ANNOUNCING); 00669 } 00670 } 00671 break; 00672 case FNET_MDNS_STATE_ANNOUNCING: 00673 if( (fnet_timer_get_ms() - mdns_if->send_timestamp) > FNET_MDNS_ANNOUNCE_INTERVAL ) 00674 { 00675 /* RFC6762: The Multicast DNS responder MUST send at least two unsolicited 00676 responses, one second apart.*/ 00677 if(mdns_if->announce_count < FNET_MDNS_ANNOUNCE_COUNT) 00678 { 00679 mdns_if->announce_count++; 00680 fnet_mdns_send_announcement(mdns_if, mdns_if->rr_ttl, mdns_if->rr_ttl_ip); 00681 } 00682 else 00683 { 00684 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_WAITING_REQUEST); 00685 } 00686 } 00687 break; 00688 case FNET_MDNS_STATE_WAITING_REQUEST: 00689 if( (mdns_if->is_shared == FNET_TRUE) && 00690 ((fnet_timer_get_ms() - mdns_if->is_shared_timestamp) > FNET_MDNS_SHARED_RESPONSE_DELAY) ) 00691 { 00692 mdns_if->is_shared = FNET_FALSE; /* REST FLAG.*/ 00693 } 00694 00695 if(mdns_if->is_truncated == FNET_FALSE) 00696 { 00697 /* RFC6762: In any case where there may be multiple responses, such as queries 00698 * where the answer is a member of a shared resource record set, each 00699 * responder SHOULD delay its response by a random amount of time 00700 * selected with uniform random distribution in the range 20-120 ms. 00701 * The reason for requiring that the delay be at least 20 ms is to 00702 * accommodate the situation where two or more query packets are sent 00703 * back-to-back, because in that case we want a responder with answers 00704 * to more than one of those queries to have the opportunity to 00705 * aggregate all of its answers into a single response message.*/ 00706 if(mdns_if->is_shared == FNET_FALSE) 00707 { 00708 /* Send response */ 00709 fnet_mdns_send_response(mdns_if, mdns_if->rr_ttl, mdns_if->rr_ttl_ip); 00710 } 00711 } 00712 break; 00713 default: 00714 break; 00715 } 00716 } 00717 } 00718 00719 /************************************************************************ 00720 * DESCRIPTION: Change state of the mDNS server. 00721 ************************************************************************/ 00722 static void fnet_mdns_change_state(fnet_mdns_if_t *mdns_if, fnet_mdns_state_t state ) 00723 { 00724 FNET_ASSERT(mdns_if != NULL); 00725 00726 mdns_if->state = state; 00727 switch (state) 00728 { 00729 case FNET_MDNS_STATE_DISABLED: 00730 /* RFC6762: In the case where a host knows that certain resource record data is 00731 * about to become invalid (for example, when the host is undergoing a 00732 * clean shutdown), the host SHOULD send an unsolicited Multicast DNS */ 00733 /* "goodbye" announcement with RR TTL zero */ 00734 fnet_mdns_send_announcement(mdns_if, 0, 0); 00735 break; 00736 case FNET_MDNS_STATE_PROBING_WAIT: 00737 break; 00738 case FNET_MDNS_STATE_PROBING: 00739 mdns_if->probe_count = 0; /* Reset probe counter.*/ 00740 fnet_mdns_send_probe(mdns_if); /* First probing.*/ 00741 break; 00742 case FNET_MDNS_STATE_ANNOUNCING: 00743 /* RFC6762: The second startup step is that the Multicast DNS responder MUST send 00744 * an unsolicited Multicast DNS response containing, in the Answer 00745 * Section, all of its newly registered resource records (both shared 00746 * records, and unique records that have completed the probing step). */ 00747 mdns_if->announce_count = 1; 00748 fnet_mdns_send_announcement(mdns_if, mdns_if->rr_ttl, mdns_if->rr_ttl_ip); 00749 break; 00750 case FNET_MDNS_STATE_WAITING_REQUEST: 00751 break; 00752 default: 00753 break; 00754 } 00755 } 00756 00757 /************************************************************************ 00758 * DESCRIPTION: Compare R names. 00759 ************************************************************************/ 00760 static fnet_bool_t fnet_mdns_cmp_rr_name(const char *rr_name, const char *name_1, const char *name_2) 00761 { 00762 FNET_ASSERT(rr_name != NULL); 00763 FNET_ASSERT(name_1 != NULL); 00764 FNET_ASSERT(name_2 != NULL); 00765 00766 fnet_bool_t result; 00767 00768 result = fnet_mdns_cmp_name(&rr_name, name_1); 00769 if( result == FNET_TRUE) 00770 { 00771 result = fnet_mdns_cmp_name(&rr_name, name_2); 00772 if( result == FNET_TRUE) 00773 { 00774 result = fnet_mdns_cmp_name(&rr_name, FNET_MDNS_DOMAIN_NAME); 00775 } 00776 } 00777 00778 return result; 00779 } 00780 00781 /************************************************************************ 00782 * DESCRIPTION: Compare R name with sub-name. 00783 ************************************************************************/ 00784 static fnet_bool_t fnet_mdns_cmp_name(const char **rr_name_p, const char *name) 00785 { 00786 FNET_ASSERT(rr_name_p != NULL); 00787 FNET_ASSERT(name != NULL); 00788 00789 fnet_index_t i=0; 00790 const fnet_char_t *rr_name = *rr_name_p; 00791 fnet_uint32_t name_length = fnet_strlen(name); 00792 fnet_uint32_t rr_name_length = fnet_strlen(rr_name); 00793 00794 if(name_length) 00795 { 00796 if(name_length > rr_name_length) 00797 { 00798 return FNET_FALSE; 00799 } 00800 00801 rr_name++; /* Skip length byte */ 00802 00803 for(i=0; i<name_length; i++) 00804 { 00805 if(name[i] == '.') 00806 { 00807 continue; 00808 } 00809 00810 if(fnet_tolower(rr_name[i]) != fnet_tolower(name[i])) 00811 { 00812 return FNET_FALSE; 00813 } 00814 } 00815 00816 *rr_name_p = &rr_name[i]; 00817 } 00818 00819 return FNET_TRUE; 00820 } 00821 00822 /************************************************************************ 00823 * DESCRIPTION: Put RR name to rr_name. Retutns pointer to the next pointer; 0 if error. 00824 If rr_name or rr_name_size are 0, just skip name. 00825 ************************************************************************/ 00826 static const fnet_uint8_t *fnet_mdns_get_rr_name(char *rr_name, fnet_uint32_t rr_name_size, const fnet_uint8_t *rr, const fnet_uint8_t *packet) 00827 { 00828 FNET_ASSERT(rr != NULL); 00829 FNET_ASSERT(packet != NULL); 00830 00831 const fnet_uint8_t *ptr = rr; 00832 fnet_uint8_t length = *rr; 00833 fnet_uint16_t offset = 0; 00834 const fnet_uint8_t *result = ptr; 00835 00836 while(length != 0) 00837 { 00838 /* Check if compression is used */ 00839 while((*ptr & FNET_MDNS_DOMAIN_NAME_COMPRESSION) == FNET_MDNS_DOMAIN_NAME_COMPRESSION) 00840 { 00841 if(offset == 0) /* Is it first compression?*/ 00842 { 00843 result += 2; /* 2 bytes (compression+length) */ 00844 } 00845 00846 offset = (fnet_uint16_t)((*ptr) & ~FNET_MDNS_DOMAIN_NAME_COMPRESSION)<<8; 00847 offset = offset + *(ptr + 1); 00848 if(offset < FNET_MDNS_PACKET_SIZE) /* Check maximum offset */ 00849 { 00850 ptr = packet+offset; 00851 } 00852 else 00853 { 00854 /* Wrong offset */ 00855 goto ERROR; 00856 } 00857 } 00858 00859 if((*ptr & FNET_MDNS_DOMAIN_NAME_COMPRESSION) != 0) /* Top two bits may be used only by the compression flag.*/ 00860 { 00861 goto ERROR; 00862 } 00863 00864 length = *ptr; 00865 00866 if( rr_name && rr_name_size ) /* Copy to rr_name buffer.*/ 00867 { 00868 if((size_t)(length+1) <= rr_name_size) /* Check maximum rr_name_size */ 00869 { 00870 fnet_memcpy(rr_name, ptr, length+1); 00871 00872 rr_name += (length+1); 00873 rr_name_size -= (length+1); 00874 } 00875 else 00876 { 00877 goto ERROR; 00878 } 00879 } 00880 00881 ptr += (length+1); 00882 if(ptr > result) 00883 { 00884 result = ptr; 00885 } 00886 } 00887 00888 return result; 00889 ERROR: 00890 return NULL; 00891 } 00892 00893 /************************************************************************ 00894 * DESCRIPTION: Get query type. 00895 ************************************************************************/ 00896 static fnet_mdns_query_type_t fnet_mdns_get_query_type(fnet_uint16_t type) 00897 { 00898 fnet_mdns_query_type_t query_rr_type; 00899 00900 switch(type) 00901 { 00902 case FNET_HTONS(FNET_MDNS_RR_PTR): 00903 query_rr_type = FNET_MDNS_QUERY_PTR; 00904 break; 00905 case FNET_HTONS(FNET_MDNS_RR_TXT): 00906 query_rr_type = FNET_MDNS_QUERY_TXT; 00907 break; 00908 case FNET_HTONS(FNET_MDNS_RR_SRV): 00909 query_rr_type = FNET_MDNS_QUERY_SRV; 00910 break; 00911 case FNET_HTONS(FNET_MDNS_RR_A): 00912 query_rr_type = FNET_MDNS_QUERY_A; 00913 break; 00914 case FNET_HTONS(FNET_MDNS_RR_AAAA): 00915 query_rr_type = FNET_MDNS_QUERY_AAAA; 00916 break; 00917 case FNET_HTONS(FNET_MDNS_RR_ANY): 00918 query_rr_type = FNET_MDNS_QUERY_ANY; 00919 break; 00920 default: 00921 query_rr_type = FNET_MDNS_QUERY_NONE; 00922 break; 00923 } 00924 00925 return query_rr_type; 00926 } 00927 00928 /* Print query name */ 00929 /************************************************************************ 00930 * DESCRIPTION: Print MDNS query name. 00931 ************************************************************************/ 00932 #if FNET_CFG_DEBUG_MDNS && FNET_CFG_DEBUG 00933 static void fnet_mdns_print_qe_name(const fnet_char_t *prefix, const fnet_char_t *qe_name) 00934 { 00935 fnet_size_t qe_name_legth = fnet_strlen(qe_name); 00936 fnet_uint8_t name_length_index = 0; 00937 fnet_index_t i; 00938 00939 fnet_print("%s", prefix); /* Print prefix*/ 00940 00941 for(i=0; i<qe_name_legth; i++) 00942 { 00943 if(i == name_length_index) 00944 { 00945 fnet_print("."); /* Instead of name length */ 00946 name_length_index += qe_name[i]+1; /* Next name length byte */ 00947 } 00948 else 00949 { 00950 fnet_print("%c", qe_name[i]); 00951 } 00952 } 00953 00954 //fnet_prinln(""); 00955 } 00956 #endif 00957 00958 /************************************************************************ 00959 * DESCRIPTION: Received MDNS query (request) and process it. 00960 ************************************************************************/ 00961 static const fnet_uint8_t * fnet_mdns_process_query(fnet_mdns_if_t *mdns_if, fnet_address_family_t address_family, const fnet_uint8_t *ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size) 00962 { 00963 FNET_ASSERT(mdns_if != NULL); 00964 FNET_ASSERT(ptr != NULL); 00965 FNET_ASSERT(packet != NULL); 00966 00967 fnet_char_t qe_name[FNET_MDNS_RR_NAME_LEN_MAX] = {0}; 00968 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t *)packet; 00969 fnet_mdns_qe_header_t *qe_header; 00970 fnet_mdns_service_if_t *service = NULL; 00971 00972 if( packet_size > (sizeof(fnet_mdns_header_t) + sizeof(fnet_mdns_qe_header_t)) ) 00973 { 00974 /* Get Requested name */ 00975 ptr = fnet_mdns_get_rr_name(qe_name, sizeof(qe_name), ptr, packet); 00976 00977 if(ptr) 00978 { 00979 qe_header = (fnet_mdns_qe_header_t*)ptr; 00980 00981 switch(mdns_if->state) 00982 { 00983 case FNET_MDNS_STATE_ANNOUNCING: 00984 case FNET_MDNS_STATE_WAITING_REQUEST: 00985 /* Compare received hostname with my_device.local, my_device._hap._tcp.local or _hap._tcp.local */ 00986 if( fnet_mdns_is_our_host_name(mdns_if, qe_name) 00987 || (service = fnet_mdns_get_service_by_name(mdns_if, qe_name)) /* service instance name */ 00988 || (service = fnet_mdns_get_service_by_type(mdns_if, qe_name)) ) /* service type in a domain */ 00989 { 00990 #if FNET_CFG_DEBUG_MDNS && FNET_CFG_DEBUG 00991 fnet_mdns_print_qe_name("MDNS: RX Query for:", qe_name); 00992 #endif 00993 00994 /* Check query record */ //TBD move it UP 00995 if( (qe_header->rr_class &(~FNET_HTONS(FNET_MDNS_HEADER_CACHE_FLUSH)))== FNET_HTONS(FNET_MDNS_HEADER_CLASS_IN)) /* Support only IN = Internet protocol. Ignore flush flag.*/ 00996 { 00997 fnet_mdns_query_type_t query_type = fnet_mdns_get_query_type(qe_header->type); 00998 if(fnet_mdns_get_service_by_type(mdns_if, qe_name)) /* Service Type has only PTR record.*/ 00999 { 01000 query_type &= FNET_MDNS_QUERY_PTR; 01001 if(query_type) /* Shared response.*/ 01002 { 01003 if(mdns_if->is_shared == FNET_FALSE) 01004 { 01005 mdns_if->is_shared = FNET_TRUE; 01006 mdns_if->is_shared_timestamp = fnet_timer_get_ms(); 01007 } 01008 else if((fnet_timer_get_ms() - mdns_if->is_shared_timestamp) > FNET_MDNS_SHARED_RESPONSE_DELAY) 01009 { 01010 mdns_if->is_shared = FNET_FALSE; 01011 } 01012 } 01013 } 01014 /* Send later */ 01015 mdns_if->response_type |= query_type; 01016 if(service) 01017 { 01018 service->response_type |= query_type; 01019 } 01020 mdns_if->response_address_family |= address_family; 01021 } 01022 } 01023 break; 01024 case FNET_MDNS_STATE_PROBING: 01025 /* Compare received hostname with my_device.local or my_device._hap._tcp.local*/ 01026 if(fnet_mdns_is_our_host_name(mdns_if, qe_name) 01027 || fnet_mdns_get_service_by_name(mdns_if, qe_name)) 01028 { 01029 #if FNET_CFG_DEBUG_MDNS && FNET_CFG_DEBUG 01030 fnet_mdns_print_qe_name("MDNS: RX Probe for:", qe_name); 01031 #endif 01032 01033 /* Simultaneous Probe Tiebreaking */ 01034 /* RFC6762: When a host that is probing for a record sees another host issue a 01035 * query for the same record, it consults the Authority Section of that 01036 * query. If it finds any resource record(s) there which answers the 01037 * query, then it compares the data of that (those) resource record(s) 01038 * with its own tentative data. */ 01039 if(mdns_header->nscount > 0) 01040 { 01041 const fnet_uint8_t *authority_ptr; 01042 01043 authority_ptr = fnet_mdns_get_ns(packet, packet_size); /* Authority section */ 01044 fnet_mdns_process_simultaneous_probe(mdns_if, authority_ptr, packet, packet_size); 01045 } 01046 } 01047 break; 01048 default: 01049 /* Ignore.*/ 01050 break; 01051 } 01052 01053 ptr += sizeof(fnet_mdns_qe_header_t); 01054 } 01055 } 01056 01057 return ptr; 01058 } 01059 01060 /************************************************************************ 01061 * DESCRIPTION: Avoid duplicate answer. 01062 ************************************************************************/ 01063 static void fnet_mdns_process_duplicate_answer(fnet_mdns_if_t *mdns_if, const fnet_uint8_t *an_ptr, const fnet_uint8_t *packet, fnet_uint32_t packet_size) 01064 { 01065 FNET_ASSERT(mdns_if != NULL); 01066 FNET_ASSERT(an_ptr != NULL); 01067 FNET_ASSERT(packet != NULL); 01068 01069 fnet_uint8_t our_rr[FNET_MDNS_RR_PROBE_LEN_MAX]; 01070 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t *)packet; 01071 fnet_uint16_t an_count = FNET_HTONS(mdns_header->ancount); 01072 const fnet_uint8_t *ptr = an_ptr; 01073 fnet_mdns_rr_header_t *rr_header; 01074 fnet_uint32_t i; 01075 fnet_mdns_query_type_t rr_type; 01076 fnet_bool_t skip; 01077 fnet_mdns_service_if_t *service; 01078 char rr_name[FNET_MDNS_RR_NAME_LEN_MAX]; 01079 01080 /* Check all RRs in known answer records.*/ 01081 for(i=0; ptr && (i<an_count) && (ptr < (packet + packet_size)); i++ ) 01082 { 01083 service = NULL; 01084 01085 rr_header = (fnet_mdns_rr_header_t *)fnet_mdns_get_rr_name(rr_name, sizeof(rr_name), ptr, packet); 01086 if(rr_header == NULL) 01087 { 01088 goto ERROR; 01089 } 01090 01091 rr_type = fnet_mdns_get_query_type(rr_header->type); 01092 01093 skip = FNET_FALSE; 01094 01095 /* Generate our record.*/ 01096 switch(rr_type) 01097 { 01098 case FNET_MDNS_QUERY_PTR: 01099 service = fnet_mdns_get_service_by_type(mdns_if, rr_name); 01100 if(service) 01101 { 01102 if(fnet_mdns_add_rr_ptr(mdns_if, our_rr, sizeof(our_rr), service, mdns_if->rr_ttl, FNET_FALSE) == NULL) 01103 { 01104 goto ERROR; 01105 } 01106 } 01107 else 01108 { 01109 skip = FNET_TRUE; 01110 } 01111 break; 01112 case FNET_MDNS_QUERY_TXT: 01113 service = fnet_mdns_get_service_by_name(mdns_if, rr_name); 01114 if(service) 01115 { 01116 if(fnet_mdns_add_rr_txt(mdns_if, our_rr, sizeof(our_rr), service, mdns_if->rr_ttl, FNET_FALSE, FNET_FALSE) == NULL) 01117 { 01118 goto ERROR; 01119 } 01120 } 01121 else 01122 { 01123 skip = FNET_TRUE; 01124 } 01125 break; 01126 case FNET_MDNS_QUERY_SRV: 01127 service = fnet_mdns_get_service_by_name(mdns_if, rr_name); 01128 if(service) 01129 { 01130 if(fnet_mdns_add_rr_srv(mdns_if, our_rr, sizeof(our_rr), service, mdns_if->rr_ttl, FNET_FALSE, FNET_FALSE) == NULL) 01131 { 01132 goto ERROR; 01133 } 01134 } 01135 else 01136 { 01137 skip = FNET_TRUE; 01138 } 01139 break; 01140 case FNET_MDNS_QUERY_AAAA: 01141 if(fnet_mdns_add_rr_aaaa(mdns_if, our_rr, sizeof(our_rr), mdns_if->rr_ttl_ip, FNET_FALSE, FNET_FALSE) == NULL) 01142 { 01143 goto ERROR; 01144 } 01145 break; 01146 case FNET_MDNS_QUERY_A: 01147 #if FNET_CFG_IP4 01148 if(fnet_mdns_add_rr_a(mdns_if, our_rr, sizeof(our_rr), mdns_if->rr_ttl, FNET_FALSE, FNET_FALSE) == NULL) 01149 { 01150 goto ERROR; 01151 } 01152 #endif 01153 break; 01154 default: 01155 skip = FNET_TRUE; 01156 break; 01157 } 01158 01159 if(skip == FNET_TRUE) 01160 { /* Skip RR record.*/ 01161 ptr += sizeof(fnet_mdns_rr_header_t) + FNET_HTONS(rr_header->data_length); 01162 } 01163 else 01164 { 01165 /* Check if the same RR in answer section.*/ 01166 if(fnet_mdns_cmp_rr(our_rr, &ptr, packet) == 0) 01167 { 01168 /* Remove duplicate answer */ 01169 if(service) 01170 { 01171 service->response_type = (fnet_mdns_query_type_t)(service->response_type & (~rr_type)); 01172 } 01173 else 01174 { 01175 mdns_if->response_type = (fnet_mdns_query_type_t)(mdns_if->response_type & (~rr_type)); 01176 } 01177 FNET_DEBUG_MDNS("MDNS: RX Duplicate Answer for: %s ; rr_type =0x%X", our_rr, rr_type); 01178 } 01179 } 01180 } 01181 ERROR: 01182 return; 01183 } 01184 01185 /************************************************************************ 01186 * DESCRIPTION: Simultaneous Probe Tiebreaking. 01187 ************************************************************************/ 01188 static void fnet_mdns_process_simultaneous_probe(fnet_mdns_if_t *mdns_if, const fnet_uint8_t *ns_ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size) 01189 { 01190 FNET_ASSERT(mdns_if != NULL); 01191 FNET_ASSERT(ns_ptr != NULL); 01192 FNET_ASSERT(packet != NULL); 01193 01194 fnet_uint8_t our_rr[FNET_MDNS_RR_PROBE_LEN_MAX] = {0}; 01195 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t *)packet; 01196 fnet_uint16_t ns_count = FNET_HTONS(mdns_header->nscount); 01197 fnet_bool_t is_win = FNET_FALSE; 01198 01199 FNET_DEBUG_MDNS("MDNS: RX Simultaneous probe"); 01200 01201 (void)packet_size; 01202 #if FNET_CFG_IP4 01203 /* Prepare and Compare Our RR A record */ 01204 if(fnet_mdns_add_rr_a(mdns_if, our_rr, sizeof(our_rr), mdns_if->rr_ttl, FNET_FALSE, FNET_FALSE) == NULL) 01205 { 01206 goto ERROR; 01207 } 01208 #endif 01209 01210 if(fnet_mdns_is_rr_win(our_rr, ns_ptr, ns_count, packet) == FNET_TRUE) 01211 { 01212 /* Prepare and Compare Our RR AAAA record */ 01213 if(fnet_mdns_add_rr_aaaa(mdns_if, our_rr, sizeof(our_rr), mdns_if->rr_ttl_ip, FNET_FALSE, FNET_FALSE) == NULL) 01214 { 01215 goto ERROR; 01216 } 01217 if(fnet_mdns_is_rr_win(our_rr, ns_ptr, ns_count, packet) == FNET_TRUE) 01218 { 01219 fnet_uint32_t i; 01220 01221 is_win = FNET_TRUE; 01222 01223 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 01224 { 01225 if(mdns_if->service_if_list[i].service_type != NULL) 01226 { 01227 /* Prepare and Compare Our RR SRV records */ 01228 if(fnet_mdns_add_rr_srv(mdns_if, our_rr, sizeof(our_rr), &mdns_if->service_if_list[i], mdns_if->rr_ttl, FNET_FALSE, FNET_FALSE) == NULL) 01229 { 01230 goto ERROR; 01231 } 01232 if(fnet_mdns_is_rr_win(our_rr, ns_ptr, ns_count, packet) == FNET_TRUE) 01233 { 01234 is_win = FNET_TRUE; 01235 } 01236 else 01237 { 01238 is_win = FNET_FALSE; 01239 break; 01240 } 01241 } 01242 } 01243 } 01244 } 01245 01246 if(is_win == FNET_FALSE) 01247 { 01248 /* RFC6762: If the host finds that its 01249 own data is lexicographically earlier, then it defers to the winning 01250 host by waiting one second, and then begins probing for this record again.*/ 01251 mdns_if->probe_wait_interval = FNET_MDNS_PROBE_DEFER_WAIT; 01252 /* Save conflict timestamp.*/ 01253 mdns_if->host_name_conflict_timestamp = fnet_timer_get_ms(); //TBD move to state change. 01254 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_PROBING_WAIT); /* Reset probing.*/ 01255 } 01256 ERROR: 01257 return; 01258 } 01259 01260 /************************************************************************ 01261 * DESCRIPTION: Get pointer to Answer Record. 01262 ************************************************************************/ 01263 static const fnet_uint8_t *fnet_mdns_get_an(const fnet_uint8_t *packet, fnet_uint32_t packet_size) 01264 { 01265 FNET_ASSERT(packet != NULL); 01266 01267 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t *)packet; 01268 fnet_uint16_t qd_count; /* Question Count */ 01269 fnet_uint16_t an_count; /* Answer Record Count */ 01270 const fnet_uint8_t *result = NULL; 01271 fnet_index_t i; 01272 const fnet_uint8_t *ptr; 01273 01274 if(packet_size > sizeof(fnet_mdns_header_t)) 01275 { 01276 qd_count = FNET_HTONS(mdns_header->qdcount); /* Question Count */ 01277 an_count = FNET_HTONS(mdns_header->ancount); /* Answer Record Count */ 01278 01279 /* Skip mDNS header.*/ 01280 ptr = packet + sizeof(fnet_mdns_header_t); 01281 01282 /* Skip Questions.*/ 01283 for(i=0; (i < qd_count) && (ptr < (packet + packet_size)); i++) 01284 { 01285 /* Get Requested name */ 01286 ptr = fnet_mdns_get_rr_name(NULL, 0, ptr, packet); 01287 01288 if(ptr) 01289 { 01290 ptr += sizeof(fnet_mdns_qe_header_t); 01291 } 01292 else 01293 { 01294 goto ERROR; 01295 } 01296 } 01297 01298 if(an_count > 0) 01299 { 01300 result = ptr; /*Pointer to Answer Record*/ 01301 } 01302 } 01303 01304 ERROR: 01305 return result; 01306 } 01307 01308 /************************************************************************ 01309 * DESCRIPTION: Get pointer to Name Server (Authority Record). 01310 ************************************************************************/ 01311 static const fnet_uint8_t *fnet_mdns_get_ns(fnet_uint8_t *packet, fnet_uint32_t packet_size) 01312 { 01313 FNET_ASSERT(packet != NULL); 01314 01315 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t *)packet; 01316 fnet_uint16_t qd_count; /* Question Count */ 01317 fnet_uint16_t an_count; /* Answer Record Count */ 01318 fnet_uint16_t ns_count; /* Authority Record Count */ 01319 const fnet_uint8_t *result = NULL; 01320 fnet_index_t i; 01321 const fnet_uint8_t *ptr; 01322 01323 if(packet_size > sizeof(fnet_mdns_header_t)) 01324 { 01325 qd_count = FNET_HTONS(mdns_header->qdcount); /* Question Count */ 01326 an_count = FNET_HTONS(mdns_header->ancount); /* Answer Record Count */ 01327 ns_count = FNET_HTONS(mdns_header->nscount); /* Authority Record Count */ 01328 01329 /* Skip mDNS header.*/ 01330 ptr = packet + sizeof(fnet_mdns_header_t); 01331 01332 /* Skip Questions.*/ 01333 for(i=0; (i < qd_count) && (ptr < (packet + packet_size)); i++) 01334 { 01335 /* Get Requested name */ 01336 ptr = fnet_mdns_get_rr_name(NULL, 0, ptr, packet); 01337 01338 if(ptr) 01339 { 01340 ptr += sizeof(fnet_mdns_qe_header_t); 01341 } 01342 else 01343 { 01344 goto ERROR; 01345 } 01346 } 01347 01348 /* Skip Answers.*/ 01349 for(i=0; (i < an_count) && (ptr < (packet + packet_size)); i++) 01350 { 01351 fnet_mdns_rr_header_t *rr_header; 01352 01353 /* Get RR name */ 01354 ptr = fnet_mdns_get_rr_name(NULL, 0, ptr, packet); 01355 01356 if(ptr) 01357 { 01358 rr_header = (fnet_mdns_rr_header_t *)ptr; 01359 ptr += sizeof(fnet_mdns_rr_header_t) + FNET_HTONS(rr_header->data_length); 01360 } 01361 else 01362 { 01363 goto ERROR; 01364 } 01365 } 01366 01367 if(ns_count > 0) 01368 { 01369 result = ptr; /*Pointer to Authority Record*/ 01370 } 01371 } 01372 01373 ERROR: 01374 return result; 01375 } 01376 01377 /************************************************************************ 01378 * DESCRIPTION: Compare RRs. 01379 ************************************************************************/ 01380 static fnet_int32_t fnet_mdns_cmp_rr(fnet_uint8_t *our_rr, const fnet_uint8_t **rr, const fnet_uint8_t *packet) 01381 { 01382 FNET_ASSERT(our_rr != NULL); 01383 FNET_ASSERT(rr != NULL); 01384 FNET_ASSERT(packet != NULL); 01385 01386 fnet_uint16_t rr_type; /* RR type */ 01387 fnet_uint16_t rr_class; /* RR class */ 01388 const fnet_uint8_t *rr_data; 01389 fnet_uint16_t rr_data_length; 01390 fnet_mdns_rr_header_t *rr_header; 01391 const fnet_uint8_t *ptr = *rr; 01392 fnet_char_t rr_name[FNET_MDNS_RR_NAME_LEN_MAX]; 01393 fnet_uint16_t our_rr_type; /* RR type */ 01394 fnet_uint16_t our_rr_class; /* RR class */ 01395 const fnet_uint8_t *our_rr_data; 01396 fnet_uint16_t our_rr_data_length; 01397 fnet_mdns_rr_header_t *our_rr_header; 01398 fnet_int32_t result; 01399 01400 our_rr_header = (fnet_mdns_rr_header_t *)(our_rr + fnet_strlen((char *)our_rr)+1); 01401 our_rr_class = FNET_HTONS(our_rr_header->rr_class); 01402 our_rr_type = FNET_HTONS(our_rr_header->type); 01403 our_rr_data = ((fnet_uint8_t *)our_rr_header) + sizeof(fnet_mdns_rr_header_t); 01404 our_rr_data_length = FNET_HTONS(our_rr_header->data_length); 01405 01406 /* RFC6762: When a host that is probing for a record sees another host issue a 01407 query for the same record, it consults the Authority Section of that 01408 query. If it finds any resource record(s) there which answers the 01409 query, then it compares the data of that (those) resource record(s) 01410 with its own tentative data. We consider first the simple case of a 01411 host probing for a single record, receiving a simultaneous probe from 01412 another host also probing for a single record. The two records are 01413 compared and the lexicographically later data wins.*/ 01414 01415 /* Get RR name */ 01416 ptr = fnet_mdns_get_rr_name(rr_name, sizeof(rr_name), ptr, packet); 01417 if(ptr) 01418 { 01419 rr_header = (fnet_mdns_rr_header_t *)ptr; 01420 ptr += sizeof(fnet_mdns_rr_header_t); 01421 01422 rr_data_length = FNET_HTONS(rr_header->data_length); 01423 01424 /* Compare RR names.*/ 01425 if(fnet_strcmp((char*)our_rr, (char*)rr_name) == 0) 01426 { 01427 rr_data = ptr; 01428 rr_class = FNET_HTONS(rr_header->rr_class) & (~FNET_HTONS(FNET_MDNS_HEADER_CACHE_FLUSH)); 01429 rr_type = FNET_HTONS(rr_header->type); 01430 01431 /* RFC6762: The determination of "lexicographically later" is performed by first 01432 comparing the record class (excluding the cache-flush bit described 01433 in Section 10.2), then the record type, then raw comparison of the 01434 binary content of the rdata without regard for meaning or structure. 01435 If the record classes differ, then the numerically greater class is 01436 considered "lexicographically later".*/ 01437 if(rr_class < our_rr_class) 01438 { 01439 result = 1; /* Win. */ 01440 } 01441 else if(rr_class > our_rr_class) 01442 { 01443 result = -1; /* Loss. */ 01444 } 01445 else 01446 { 01447 /* RFC6762: Otherwise, if the record types 01448 differ, then the numerically greater type is considered 01449 "lexicographically later".*/ 01450 if(rr_type < our_rr_type) 01451 { 01452 result = 1; /* Win. */ 01453 } 01454 else if(rr_type > our_rr_type) 01455 { 01456 result = -1; /* Loss. */ 01457 } 01458 /* RFC6762: If the rrtype and rrclass both match, 01459 then the rdata is compared.*/ 01460 else if(rr_data_length) 01461 { 01462 int cmp_res; 01463 fnet_uint16_t cmp_length; 01464 01465 cmp_length = (rr_data_length > our_rr_data_length)? our_rr_data_length : rr_data_length; /* Get min length value */ 01466 01467 cmp_res = fnet_memcmp(rr_data, our_rr_data, cmp_length); 01468 01469 if(cmp_res < 0) 01470 { 01471 result = 1; /* Win. */ 01472 } 01473 else if (cmp_res > 0) 01474 { 01475 result = -1; /* Loss. */ 01476 } 01477 else /* cmp_res == 0 */ 01478 { 01479 /* RFC:If both lists run out of records at the same time without any difference 01480 being found, then this indicates that two devices are advertising 01481 identical sets of records, as is sometimes done for fault tolerance, 01482 and there is, in fact, no conflict.*/ 01483 if(rr_data_length < our_rr_data_length) 01484 { 01485 result = 1; /* Win. */ 01486 } 01487 else if(rr_data_length > our_rr_data_length) 01488 { 01489 result = -1; /* Loss. */ 01490 } 01491 else 01492 { 01493 /* Check TTL. Used for Duplicate Suppression */ 01494 if(FNET_HTONL(rr_header->ttl) > (FNET_HTONL(our_rr_header->ttl)>>1)) 01495 { 01496 result = 0; /* Absoulutely same records */ 01497 } 01498 else 01499 { 01500 result = 1; 01501 } 01502 } 01503 } 01504 } 01505 else 01506 { 01507 result = 1; /* Win. */ 01508 } 01509 } 01510 } 01511 else 01512 { 01513 result = 1; /* Win. */ 01514 } 01515 01516 ptr += rr_data_length; 01517 } 01518 else 01519 { 01520 /* Malformed packet.*/ 01521 result = 1; /* Win. */ 01522 } 01523 01524 *rr = ptr; 01525 01526 return result; 01527 } 01528 01529 /************************************************************************ 01530 * DESCRIPTION: Is our RR winner. 01531 ************************************************************************/ 01532 static fnet_bool_t fnet_mdns_is_rr_win(fnet_uint8_t *our_rr, const fnet_uint8_t *ns_ptr, fnet_uint16_t ns_count, fnet_uint8_t *packet) 01533 { 01534 FNET_ASSERT(our_rr != NULL); 01535 FNET_ASSERT(ns_ptr != NULL); 01536 01537 fnet_index_t i; 01538 const fnet_uint8_t *ptr = ns_ptr; 01539 fnet_bool_t result; 01540 01541 /* RFC6762: When a host that is probing for a record sees another host issue a 01542 query for the same record, it consults the Authority Section of that 01543 query. If it finds any resource record(s) there which answers the 01544 query, then it compares the data of that (those) resource record(s) 01545 with its own tentative data. We consider first the simple case of a 01546 host probing for a single record, receiving a simultaneous probe from 01547 another host also probing for a single record. The two records are 01548 compared and the lexicographically later data wins.*/ 01549 01550 /* Check all RRs. Find lowest class */ 01551 for(i=0; i<ns_count; i++ ) 01552 { 01553 if(fnet_mdns_cmp_rr(our_rr, &ptr, packet) >= 0) 01554 { 01555 break; /* Win */ 01556 } 01557 } 01558 01559 if(i == ns_count) 01560 { 01561 result = FNET_FALSE; 01562 } 01563 else 01564 { 01565 result = FNET_TRUE; 01566 } 01567 01568 return result; 01569 } 01570 01571 /************************************************************************ 01572 * DESCRIPTION: Process MDNS response 01573 ************************************************************************/ 01574 static const fnet_uint8_t *fnet_mdns_process_response(fnet_mdns_if_t *mdns_if, const fnet_uint8_t * ptr, fnet_uint8_t *packet, fnet_uint32_t packet_size) 01575 { 01576 FNET_ASSERT(mdns_if != NULL); 01577 FNET_ASSERT(ptr != NULL); 01578 FNET_ASSERT(packet != NULL); 01579 01580 fnet_char_t rr_name[FNET_MDNS_RR_NAME_LEN_MAX]; 01581 01582 /* Header follows the hostname and the terminating zero */ 01583 fnet_mdns_rr_header_t *rr_header; 01584 01585 if( packet_size > (sizeof(fnet_mdns_header_t) + sizeof(fnet_mdns_rr_header_t)) ) /* TND make it universal*/ 01586 { 01587 /* Get RR name */ 01588 ptr = fnet_mdns_get_rr_name(rr_name, sizeof(rr_name), ptr, packet); 01589 01590 if(ptr) 01591 { 01592 rr_header = (fnet_mdns_rr_header_t *)ptr; 01593 ptr += sizeof(fnet_mdns_rr_header_t) + FNET_HTONS(rr_header->data_length); 01594 01595 /* Compare received hostname with my_device.local */ 01596 if( (fnet_mdns_is_our_host_name(mdns_if, rr_name) 01597 || fnet_mdns_get_service_by_name(mdns_if, rr_name)) 01598 && ( rr_header->rr_class == FNET_HTONS((FNET_MDNS_HEADER_CLASS_IN | FNET_MDNS_HEADER_CACHE_FLUSH)) ) 01599 #if 0 /* Cause of Test warnings.*/ 01600 && ((rr_header->type == FNET_HTONS(FNET_MDNS_RR_SRV)) || 01601 (rr_header->type == FNET_HTONS(FNET_MDNS_RR_A)) || 01602 (rr_header->type == FNET_HTONS(FNET_MDNS_RR_AAAA))) 01603 #endif 01604 ) /* service instance name */ 01605 { 01606 FNET_DEBUG_MDNS("MDNS: RX response for - %s", rr_name); 01607 01608 /* RFC: In the case of a host 01609 probing using query type "ANY" as recommended above, any answer 01610 containing a record with that name, of any type, MUST be considered a 01611 conflicting response and handled accordingly.*/ 01612 01613 /* Save conflict timestamp.*/ 01614 mdns_if->host_name_conflict_timestamp = fnet_timer_get_ms(); 01615 01616 /* If in Probing state, change name and try again */ 01617 if((mdns_if->state == FNET_MDNS_STATE_PROBING)) 01618 { 01619 fnet_mdns_update_name_counter(mdns_if); /* Regenerate name.*/ 01620 } 01621 01622 /* RFC: If fifteen conflicts occur within any ten-second period, then the 01623 host MUST wait at least five seconds before each successive 01624 additional probe attempt. This is to help ensure that, in the event 01625 of software bugs or other unanticipated problems, errant hosts do not 01626 flood the network with a continuous stream of multicast traffic. For 01627 very simple devices, a valid way to comply with this requirement is 01628 to always wait five seconds after any failed probe attempt before 01629 trying again.*/ 01630 /* We use the simple device aproach.*/ 01631 mdns_if->probe_wait_interval = FNET_MDNS_PROBE_WAIT; 01632 fnet_mdns_change_state(mdns_if, FNET_MDNS_STATE_PROBING_WAIT); /* Reset probing.*/ 01633 } 01634 } 01635 } 01636 else 01637 { 01638 ptr = NULL; 01639 } 01640 01641 return ptr; 01642 } 01643 01644 /************************************************************************ 01645 * DESCRIPTION: MDNS receive. 01646 ************************************************************************/ 01647 static void fnet_mdns_recv(fnet_mdns_if_t *mdns_if) 01648 { 01649 FNET_ASSERT(mdns_if != NULL); 01650 01651 fnet_int32_t received; 01652 fnet_mdns_header_t *mdns_header; 01653 fnet_uint32_t cnt=0; 01654 const fnet_uint8_t *ptr; 01655 fnet_index_t i; 01656 fnet_size_t addr_len; 01657 01658 /* Receive UDP data */ 01659 addr_len = sizeof(mdns_if->remote_address); 01660 received = fnet_socket_recvfrom( mdns_if->socket_listen, mdns_if->buffer, sizeof(mdns_if->buffer), 0u, &mdns_if->remote_address, &addr_len ); 01661 if(received > 0) 01662 { 01663 switch(mdns_if->state) 01664 { 01665 case FNET_MDNS_STATE_PROBING: 01666 case FNET_MDNS_STATE_ANNOUNCING: 01667 case FNET_MDNS_STATE_WAITING_REQUEST: 01668 /* Received MDNS header */ 01669 if((size_t)received > sizeof(fnet_mdns_header_t)) 01670 { 01671 mdns_header = (fnet_mdns_header_t*)&mdns_if->buffer[0]; 01672 01673 char *hostname = (char*)&mdns_if->buffer[sizeof(fnet_mdns_header_t)]; 01674 01675 /* Query */ 01676 if( ((mdns_header->flags & FNET_HTONS(FNET_MDNS_HEADER_FLAGS_QR)) == 0) /* Query.*/ 01677 && ((mdns_header->flags & FNET_HTONS(FNET_MDNS_HEADER_FLAGS_OPCODE)) == 0) ) /* Standard Query */ 01678 { 01679 if(mdns_if->remote_address.sa_port != FNET_MDNS_PORT) 01680 { 01681 mdns_if->is_legacy_unicast = FNET_TRUE; 01682 } 01683 else 01684 { 01685 mdns_if->is_legacy_unicast = FNET_FALSE; 01686 } 01687 01688 if( (mdns_header->flags & FNET_HTONS(FNET_MDNS_HEADER_FLAGS_TC)) == 0) /* Trancation.*/ 01689 { 01690 mdns_if->is_truncated = FNET_FALSE; 01691 } 01692 else 01693 { 01694 mdns_if->is_truncated = FNET_TRUE; 01695 } 01696 01697 ptr = (fnet_uint8_t*)hostname; 01698 for(i=0; i<FNET_HTONS(mdns_header->qdcount); i++) 01699 { 01700 ptr = fnet_mdns_process_query(mdns_if, mdns_if->remote_address.sa_family, ptr, mdns_if->buffer, received); 01701 if(ptr == NULL) 01702 { 01703 return; 01704 } 01705 } 01706 01707 /* Duplicate Suppression.*/ 01708 if(mdns_if->response_type != FNET_MDNS_QUERY_NONE) 01709 { 01710 const fnet_uint8_t *an_ptr; 01711 01712 an_ptr = fnet_mdns_get_an(mdns_if->buffer, received); 01713 01714 /* Eliminate duplicated answers */ 01715 if(an_ptr) 01716 { 01717 fnet_mdns_process_duplicate_answer(mdns_if, an_ptr, mdns_if->buffer, received); 01718 } 01719 } 01720 } 01721 /* Response */ 01722 else if( ( ((mdns_header->flags & FNET_HTONS(FNET_MDNS_HEADER_FLAGS_QR)) != 0) && /* Response.*/ 01723 (mdns_header->qdcount == 0)) && 01724 ( (mdns_header->nscount > 0) 01725 || (mdns_header->arcount > 0) 01726 || (mdns_header->ancount > 0)) 01727 ) 01728 { 01729 cnt = FNET_HTONS(mdns_header->nscount) + FNET_HTONS(mdns_header->arcount) + FNET_HTONS(mdns_header->ancount) + FNET_HTONS(mdns_header->qdcount); 01730 01731 ptr = (fnet_uint8_t*)hostname; 01732 for(i=0; (i < cnt) && (ptr < (mdns_if->buffer + received)); i++) 01733 { 01734 ptr = fnet_mdns_process_response(mdns_if, ptr, mdns_if->buffer, received); 01735 if(ptr == NULL) 01736 { 01737 break; 01738 } 01739 } 01740 } 01741 } 01742 break; 01743 case FNET_MDNS_STATE_PROBING_WAIT: 01744 default: 01745 /* Ignore packet. */ 01746 break; 01747 } 01748 } 01749 01750 } 01751 01752 /************************************************************************ 01753 * DESCRIPTION: Prepare domain name - replace dots by length of string 01754 ************************************************************************/ 01755 static fnet_uint8_t *fnet_mdns_add_domain_name(fnet_uint8_t *buf, fnet_uint32_t buf_size, const char * domain_name) 01756 { 01757 FNET_ASSERT(buf != NULL); 01758 FNET_ASSERT(domain_name != NULL); 01759 01760 fnet_uint32_t domain_len = fnet_strlen(domain_name) + 1; 01761 fnet_uint32_t len = 0; 01762 fnet_index_t i; 01763 fnet_index_t p = 0; 01764 fnet_uint8_t *result = NULL; 01765 01766 if(domain_len <= buf_size) /* Check buffer size limit */ 01767 { 01768 for(i=0; i<domain_len; i++) 01769 { 01770 buf[i+1] = domain_name[i]; 01771 len++; 01772 01773 if(domain_name[i] == '.') 01774 { 01775 buf[p] = len-1; 01776 p = i+1; 01777 len = 0; 01778 } 01779 } 01780 01781 /* the last part */ 01782 buf[p] = len ? len-1 : 0; 01783 result = buf + domain_len; 01784 } 01785 01786 return result; 01787 } 01788 01789 /************************************************************************ 01790 * DESCRIPTION: Send probe query. 01791 RFC: All probe queries SHOULD be done 01792 using the desired resource record name and class (usually class 1, 01793 "Internet"), and query type "ANY" (255), to elicit answers for all 01794 types of records with that name. This allows a single question to be 01795 used in place of several questions, which is more efficient on the 01796 network. It also allows a host to verify exclusive ownership of a 01797 name for all rrtypes, which is desirable in most cases. 01798 ************************************************************************/ 01799 static void fnet_mdns_send_probe(fnet_mdns_if_t *mdns_if) 01800 { 01801 FNET_ASSERT(mdns_if != NULL); 01802 01803 fnet_uint8_t *ptr; 01804 fnet_uint32_t send_size = 0; 01805 fnet_uint16_t nscount = 0; 01806 fnet_uint16_t qdcount = 0; 01807 fnet_index_t i; 01808 fnet_mdns_header_t *mdns_header; 01809 fnet_uint8_t *buf_end = &mdns_if->buffer[FNET_MDNS_PACKET_SIZE-1]; 01810 01811 fnet_memset(mdns_if->buffer, 0, sizeof(mdns_if->buffer)); 01812 01813 mdns_header = (fnet_mdns_header_t*)&mdns_if->buffer[0]; 01814 01815 ptr = (fnet_uint8_t*)mdns_header + sizeof(fnet_mdns_header_t); 01816 01817 /* RFC: All probe queries SHOULD be done 01818 using the desired resource record name and class (usually class 1, 01819 "Internet"), and query type "ANY" (255), to elicit answers for all 01820 types of records with that name. */ 01821 01822 /* Question section: */ 01823 /*RFC6762: When a host is probing for a group of related records with the same 01824 name (e.g., the SRV and TXT record describing a DNS-SD service), only 01825 a single question need be placed in the Question Section, since query 01826 type "ANY" (255) is used, which will elicit answers for all records 01827 with that name.*/ 01828 01829 /* Prepary ANY records with service name */ 01830 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 01831 { 01832 if(mdns_if->service_if_list[i].service_type) 01833 { 01834 ptr = fnet_mdns_add_service_name(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], FNET_TRUE); 01835 if(ptr == NULL) 01836 { 01837 goto ERROR; 01838 } 01839 ptr = fnet_mdns_add_qe_any(ptr, (buf_end - ptr)); 01840 if(ptr == NULL) 01841 { 01842 goto ERROR; 01843 } 01844 qdcount++; 01845 } 01846 } 01847 01848 /* Prepary ANY record with device/host name */ 01849 ptr = fnet_mdns_add_host_name(mdns_if, ptr, (buf_end - ptr), FNET_TRUE); 01850 if(ptr == NULL) 01851 { 01852 goto ERROR; 01853 } 01854 ptr = fnet_mdns_add_qe_any(ptr, (buf_end - ptr)); 01855 if(ptr == NULL) 01856 { 01857 goto ERROR; 01858 } 01859 qdcount++; 01860 01861 /* Count */ 01862 mdns_header->qdcount = FNET_HTONS(qdcount); 01863 01864 /* Authority section: */ 01865 /* RFC6762: A probe query can be distinguished from a normal query by the fact that a probe 01866 query contains a proposed record in the Authority Section that 01867 answers the question in the Question Section (for more details, see 01868 Section 8.2, "Simultaneous Probe Tiebreaking"). */ 01869 01870 /* RFC: For tiebreaking to work correctly in all 01871 cases, the Authority Section must contain *all* the records and 01872 proposed rdata being probed for uniqueness.*/ 01873 01874 /* The cache-flush bit MUST NOT be set in any resource records in the 01875 Known-Answer list of any query message.*/ 01876 01877 /* Prepare RR SRV records */ 01878 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 01879 { 01880 if(mdns_if->service_if_list[i].service_type) 01881 { 01882 ptr = fnet_mdns_add_rr_srv(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], mdns_if->rr_ttl, FNET_FALSE, FNET_TRUE); 01883 if(ptr == NULL) 01884 { 01885 goto ERROR; 01886 } 01887 nscount++; 01888 } 01889 } 01890 01891 #if FNET_CFG_IP4 01892 /* Prepare RR A record */ 01893 ptr = fnet_mdns_add_rr_a(mdns_if, ptr, (buf_end - ptr), mdns_if->rr_ttl, FNET_FALSE, FNET_TRUE); 01894 if(ptr == NULL) 01895 { 01896 goto ERROR; 01897 } 01898 nscount++; 01899 #endif 01900 01901 /* Prepare RR AAAA record */ 01902 ptr = fnet_mdns_add_rr_aaaa(mdns_if, ptr, (buf_end - ptr), mdns_if->rr_ttl_ip, FNET_FALSE, FNET_TRUE); 01903 if(ptr == NULL) 01904 { 01905 goto ERROR; 01906 } 01907 nscount++; 01908 01909 mdns_header->nscount = FNET_HTONS(nscount); 01910 01911 /* Message size.*/ 01912 send_size = ptr - mdns_if->buffer; 01913 01914 FNET_DEBUG_MDNS("MDNS: Probing..."); 01915 01916 /* Send mdns packet */ 01917 fnet_mdns_send(mdns_if, mdns_if->addr_family, mdns_if->buffer, send_size); 01918 01919 ERROR: 01920 mdns_if->probe_count++; 01921 return; 01922 } 01923 01924 /************************************************************************ 01925 * DESCRIPTION: Actual Send. 01926 ************************************************************************/ 01927 static void fnet_mdns_send(fnet_mdns_if_t *mdns_if, fnet_address_family_t address_family, fnet_uint8_t *buffer, fnet_uint32_t send_size) 01928 { 01929 FNET_ASSERT(mdns_if != NULL); 01930 FNET_ASSERT(buffer != NULL); 01931 01932 fnet_index_t i; 01933 struct sockaddr *address; 01934 struct sockaddr multicast_addr; 01935 01936 /* Reset Domain Name Compression pointers.*/ 01937 mdns_if->offset_host_name = 0; 01938 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 01939 { 01940 mdns_if->service_if_list[i].offset_service_name = 0; 01941 mdns_if->service_if_list[i].offset_service_type = 0; 01942 } 01943 01944 mdns_if->send_timestamp = fnet_timer_get_ms(); /* Save last sending time stamp.*/ 01945 01946 #if FNET_CFG_IP4 01947 if(address_family & AF_INET) 01948 { 01949 if(mdns_if->is_legacy_unicast == FNET_TRUE) 01950 { 01951 address = &mdns_if->remote_address; 01952 } 01953 else 01954 { 01955 fnet_memset_zero(&multicast_addr, sizeof(multicast_addr)); 01956 multicast_addr.sa_family = AF_INET; 01957 multicast_addr.sa_port = FNET_MDNS_PORT; 01958 multicast_addr.sa_scope_id = fnet_netif_get_scope_id(mdns_if->netif); 01959 ((struct sockaddr_in*)(&multicast_addr))->sin_addr.s_addr = FNET_MDNS_IP4_MULTICAST_ADDR; 01960 01961 address = &multicast_addr; 01962 } 01963 01964 /* Send to IPv4 address */ 01965 fnet_socket_sendto ( mdns_if->socket_listen, buffer, send_size, 0u, address, sizeof(*address) ); 01966 } 01967 #endif 01968 #if FNET_CFG_IP6 01969 if(address_family & AF_INET6) 01970 { 01971 if(mdns_if->is_legacy_unicast == FNET_TRUE) 01972 { 01973 address = &mdns_if->remote_address; 01974 } 01975 else 01976 { 01977 fnet_memset_zero(&multicast_addr, sizeof(multicast_addr)); 01978 multicast_addr.sa_family = AF_INET6; 01979 multicast_addr.sa_port = FNET_MDNS_PORT; 01980 multicast_addr.sa_scope_id = fnet_netif_get_scope_id(mdns_if->netif); 01981 FNET_IP6_ADDR_COPY(&fnet_mdns_ip6_multicast_addr, &((struct sockaddr_in6 *)(&multicast_addr))->sin6_addr.s6_addr); 01982 01983 address = &multicast_addr; 01984 } 01985 01986 /* Send to IPv6 address */ 01987 fnet_socket_sendto ( mdns_if->socket_listen, buffer, send_size, 0u, address, sizeof(*address) ); 01988 } 01989 #endif 01990 01991 /* Reset flag.*/ 01992 mdns_if->is_legacy_unicast = FNET_FALSE; 01993 } 01994 01995 /************************************************************************ 01996 * DESCRIPTION: Prepare all mdns records to send. 01997 ************************************************************************/ 01998 static void fnet_mdns_send_response(fnet_mdns_if_t *mdns_if, fnet_uint32_t ttl, fnet_uint32_t ttl_ip) 01999 { 02000 FNET_ASSERT(mdns_if != NULL); 02001 02002 fnet_uint8_t *ptr; 02003 fnet_uint32_t send_size = 0; 02004 fnet_mdns_header_t *mdns_header = (fnet_mdns_header_t*)&mdns_if->buffer[0]; 02005 fnet_uint16_t answer_count = 0; 02006 fnet_uint16_t additional_count = 0; 02007 fnet_bool_t has_srv = FNET_FALSE; 02008 fnet_bool_t has_ptr = FNET_FALSE; 02009 fnet_index_t i; 02010 fnet_bool_t flush; 02011 fnet_uint8_t *buf_end = &mdns_if->buffer[FNET_MDNS_PACKET_SIZE-1]; 02012 02013 fnet_memset(mdns_if->buffer, 0, sizeof(mdns_if->buffer)); 02014 02015 ptr = (fnet_uint8_t*)mdns_header + sizeof(fnet_mdns_header_t); 02016 send_size += sizeof(fnet_mdns_header_t); 02017 02018 mdns_header->flags |= FNET_HTONS(FNET_MDNS_HEADER_FLAGS_QR | FNET_MDNS_HEADER_FLAGS_C); 02019 02020 if(mdns_if->is_legacy_unicast == FNET_TRUE) 02021 { 02022 /* RFC6762: The cache-flush bit MUST NOT be set in legacy unicast responses.*/ 02023 flush = FNET_FALSE; 02024 } 02025 else 02026 { 02027 flush = FNET_TRUE; 02028 } 02029 02030 /* Answer records */ 02031 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02032 { 02033 if(mdns_if->service_if_list[i].service_type) 02034 { 02035 /* Prepare TXT record */ 02036 if(mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_TXT) 02037 { 02038 if((&mdns_if->service_if_list[i])->service_get_txt) /* Check if service has TXT */ 02039 { 02040 ptr = fnet_mdns_add_rr_txt(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], ttl, flush, FNET_TRUE); 02041 if(ptr == NULL) 02042 { 02043 goto ERROR; 02044 } 02045 answer_count++; 02046 } 02047 } 02048 02049 /* Prepare RR PTR record */ 02050 if(mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_PTR) 02051 { 02052 ptr = fnet_mdns_add_rr_ptr(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], ttl, FNET_TRUE); 02053 if(ptr == NULL) 02054 { 02055 goto ERROR; 02056 } 02057 answer_count++; 02058 has_ptr = FNET_TRUE; 02059 } 02060 02061 /* Prepare RR SRV record */ 02062 if(mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_SRV) 02063 { 02064 ptr = fnet_mdns_add_rr_srv(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], ttl, flush, FNET_TRUE); 02065 if(ptr == NULL) 02066 { 02067 goto ERROR; 02068 } 02069 answer_count++; 02070 has_srv = FNET_TRUE; 02071 } 02072 } 02073 } 02074 02075 #if FNET_CFG_IP4 02076 // Do not send A record in IPV6 only stack 02077 /* Prepare RR A record */ 02078 if(mdns_if->response_type & FNET_MDNS_QUERY_A) 02079 { 02080 ptr = fnet_mdns_add_rr_a(mdns_if, ptr, (buf_end - ptr), ttl, flush, FNET_TRUE); 02081 if(ptr == NULL) 02082 { 02083 goto ERROR; 02084 } 02085 answer_count++; 02086 } 02087 #endif 02088 02089 /* Prepare RR AAAA record */ 02090 if(mdns_if->response_type & FNET_MDNS_QUERY_AAAA) 02091 { 02092 ptr = fnet_mdns_add_rr_aaaa(mdns_if, ptr, (buf_end - ptr), ttl_ip, flush, FNET_TRUE); 02093 if(ptr == NULL) 02094 { 02095 goto ERROR; 02096 } 02097 answer_count++; 02098 } 02099 02100 /* Additional records */ 02101 02102 /* RFC6763: When including a DNS-SD Service Instance Enumeration or Selective 02103 Instance Enumeration (subtype) PTR record in a response packet, the 02104 server/responder SHOULD include the following additional records: 02105 o The SRV record(s) named in the PTR rdata. 02106 o The TXT record(s) named in the PTR rdata. 02107 o All address records (type "A" and "AAAA") named in the SRV rdata.*/ 02108 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02109 { 02110 if(mdns_if->service_if_list[i].service_type) 02111 { 02112 if(mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_PTR) 02113 { 02114 if((mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_SRV) == 0) 02115 { 02116 ptr = fnet_mdns_add_rr_srv(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], ttl, flush, FNET_TRUE); 02117 if(ptr == NULL) 02118 { 02119 goto ERROR; 02120 } 02121 additional_count++; 02122 } 02123 02124 if((mdns_if->service_if_list[i].response_type & FNET_MDNS_QUERY_TXT) == 0) 02125 { 02126 if((&mdns_if->service_if_list[i])->service_get_txt) /* Check if service has TXT */ 02127 { 02128 ptr = fnet_mdns_add_rr_txt(mdns_if, ptr, (buf_end - ptr), &mdns_if->service_if_list[i], ttl, flush, FNET_TRUE); 02129 if(ptr == NULL) 02130 { 02131 goto ERROR; 02132 } 02133 additional_count++; 02134 } 02135 } 02136 } 02137 } 02138 } 02139 02140 /* RFC6763: When including an SRV record in a response packet, the 02141 server/responder SHOULD include the following additional records: 02142 o All address records (type "A" and "AAAA") named in the SRV rdata.*/ 02143 if((has_ptr == FNET_TRUE) || (has_srv == FNET_TRUE)) 02144 { 02145 #if FNET_CFG_IP4 02146 if((mdns_if->response_type & FNET_MDNS_QUERY_A) == 0) 02147 { 02148 /* Prepare RR A record */ 02149 ptr = fnet_mdns_add_rr_a(mdns_if, ptr, (buf_end - ptr), ttl, flush, FNET_TRUE); 02150 if(ptr == NULL) 02151 { 02152 goto ERROR; 02153 } 02154 additional_count++; 02155 } 02156 #endif 02157 if((mdns_if->response_type & FNET_MDNS_QUERY_AAAA) == 0) 02158 { 02159 /* Prepare RR AAAA record */ 02160 ptr = fnet_mdns_add_rr_aaaa(mdns_if, ptr, (buf_end - ptr), ttl_ip, flush, FNET_TRUE); 02161 if(ptr == NULL) 02162 { 02163 goto ERROR; 02164 } 02165 additional_count++; 02166 } 02167 } 02168 02169 /* RFC6762: Multicast DNS responses MUST NOT contain any questions in the 02170 * Question Section. */ 02171 if(answer_count) /* Check if any answer for sending*/ 02172 { 02173 /* Answers */ 02174 mdns_header->ancount = FNET_HTONS(answer_count); 02175 /* Additional */ 02176 mdns_header->arcount = FNET_HTONS(additional_count); 02177 02178 send_size = ptr - (fnet_uint8_t*)mdns_header; 02179 02180 /* Send all mdns records */ 02181 fnet_mdns_send(mdns_if, mdns_if->response_address_family, mdns_if->buffer, send_size); 02182 } 02183 02184 ERROR: 02185 /* Reset response parameters.*/ 02186 mdns_if->response_type = FNET_MDNS_QUERY_NONE; 02187 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02188 { 02189 mdns_if->service_if_list[i].response_type = FNET_MDNS_QUERY_NONE; 02190 } 02191 mdns_if->response_address_family = AF_UNSPEC; 02192 mdns_if->is_shared = FNET_FALSE; 02193 mdns_if->is_legacy_unicast = FNET_FALSE; 02194 } 02195 02196 /************************************************************************ 02197 * DESCRIPTION: Send announcement. 02198 ************************************************************************/ 02199 static void fnet_mdns_send_announcement(fnet_mdns_if_t *mdns_if, fnet_uint32_t ttl, fnet_uint32_t ttl_ip) 02200 { 02201 FNET_ASSERT(mdns_if != NULL); 02202 02203 fnet_index_t i; 02204 02205 /* Set response_type to ANY */ 02206 mdns_if->response_type = FNET_MDNS_QUERY_ANY; 02207 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02208 { 02209 mdns_if->service_if_list[i].response_type = FNET_MDNS_QUERY_ANY; 02210 } 02211 mdns_if->response_address_family = mdns_if->addr_family; 02212 02213 fnet_mdns_send_response(mdns_if, ttl, ttl_ip); 02214 } 02215 02216 /************************************************************************ 02217 * DESCRIPTION: Add record header. 02218 ************************************************************************/ 02219 static fnet_uint8_t * fnet_mdns_add_rr_header(fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_rr_type_t type, fnet_bool_t flush, fnet_uint32_t ttl, fnet_uint16_t data_length) 02220 { 02221 FNET_ASSERT(buf != NULL); 02222 02223 fnet_uint8_t *ptr = buf; 02224 fnet_mdns_rr_header_t *mdns_rr_header = (fnet_mdns_rr_header_t*)buf; 02225 fnet_uint16_t rr_class = FNET_MDNS_HEADER_CLASS_IN; /* RFC: generally only DNS class 1 ("Internet") is used */ 02226 fnet_uint8_t *result = NULL; 02227 02228 if(sizeof(fnet_mdns_rr_header_t) <= buf_size) 02229 { 02230 if(flush != FNET_FALSE) 02231 { 02232 rr_class |= FNET_MDNS_HEADER_CACHE_FLUSH; 02233 } 02234 02235 mdns_rr_header->type = FNET_HTONS( (fnet_uint16_t) type ); 02236 mdns_rr_header->rr_class = FNET_HTONS( (fnet_uint16_t) rr_class ); 02237 mdns_rr_header->ttl = FNET_HTONL( (fnet_uint32_t) ttl ); 02238 mdns_rr_header->data_length = FNET_HTONS( (fnet_uint16_t) data_length ); 02239 02240 result = ptr + sizeof(fnet_mdns_rr_header_t); 02241 } 02242 return result; 02243 } 02244 02245 /************************************************************************ 02246 * DESCRIPTION: Add TXT record to buffer. 02247 ************************************************************************/ 02248 fnet_uint8_t *fnet_mdns_add_rr_txt(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression) 02249 { 02250 FNET_ASSERT(mdns_if != NULL); 02251 FNET_ASSERT(buf != NULL); 02252 02253 fnet_uint8_t *rr_header_ptr; 02254 fnet_uint8_t *txt_ptr; 02255 fnet_uint32_t rr_txt_length = 0; 02256 const fnet_uint8_t *txt_user_buffer; 02257 fnet_uint8_t *ptr = buf; 02258 fnet_uint8_t *result = NULL; 02259 02260 /* RR Name */ 02261 /* Add service name */ 02262 ptr = fnet_mdns_add_service_name(mdns_if, ptr, (buf+buf_size) - ptr, service_if, compression); 02263 if(ptr == NULL) 02264 { 02265 goto ERROR; 02266 } 02267 02268 if((size_t)((buf+buf_size) - ptr) > sizeof(fnet_mdns_rr_header_t)) 02269 { 02270 rr_header_ptr = ptr; 02271 txt_ptr = ptr + sizeof(fnet_mdns_rr_header_t); 02272 02273 /* TXT */ 02274 if(service_if->service_get_txt) 02275 { 02276 txt_user_buffer = service_if->service_get_txt(); 02277 02278 if(txt_user_buffer) 02279 { 02280 rr_txt_length = fnet_mdns_key_value_record_len(txt_user_buffer); 02281 if( (size_t)((buf+buf_size) - txt_ptr) < (rr_txt_length+1) ) 02282 { 02283 goto ERROR; 02284 } 02285 fnet_memcpy(txt_ptr, txt_user_buffer, rr_txt_length); 02286 } 02287 } 02288 02289 /* RR TXT header */ 02290 ptr = fnet_mdns_add_rr_header(rr_header_ptr, sizeof(fnet_mdns_rr_header_t), FNET_MDNS_RR_TXT, flush, ttl, rr_txt_length); 02291 02292 ptr += rr_txt_length; 02293 02294 result = ptr; 02295 } 02296 02297 ERROR: 02298 return result; 02299 } 02300 02301 /************************************************************************ 02302 * DESCRIPTION: Add PTR record to buffer. 02303 ************************************************************************/ 02304 static fnet_uint8_t *fnet_mdns_add_rr_ptr(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t compression) 02305 { 02306 FNET_ASSERT(mdns_if != NULL); 02307 FNET_ASSERT(buf != NULL); 02308 02309 fnet_uint8_t *rr_header_ptr; 02310 fnet_uint8_t *ptr = buf; 02311 fnet_uint8_t *result = NULL; 02312 02313 /* Add service type */ 02314 ptr = fnet_mdns_add_service_type_name(mdns_if, ptr, (buf+buf_size) - ptr, service_if, compression); 02315 if(ptr == NULL) 02316 { 02317 goto ERROR; 02318 } 02319 02320 if((size_t)((buf+buf_size) - ptr) > sizeof(fnet_mdns_rr_header_t)) 02321 { 02322 /* Add RR header later, when calculate data size */ 02323 rr_header_ptr = ptr; 02324 ptr = ptr + sizeof(fnet_mdns_rr_header_t); 02325 02326 /* Add PTR data */ 02327 ptr = fnet_mdns_add_service_name(mdns_if, ptr, (buf+buf_size) - ptr, service_if, compression); 02328 if(ptr == NULL) 02329 { 02330 goto ERROR; 02331 } 02332 02333 /* Add RR PTR header */ 02334 fnet_mdns_add_rr_header(rr_header_ptr, sizeof(fnet_mdns_rr_header_t), FNET_MDNS_RR_PTR, FNET_FALSE, ttl, ptr - rr_header_ptr - sizeof(fnet_mdns_rr_header_t)); 02335 02336 result = ptr; 02337 } 02338 ERROR: 02339 return result; 02340 } 02341 02342 /************************************************************************ 02343 * DESCRIPTION: Add SRV record to buffer. 02344 ************************************************************************/ 02345 static fnet_uint8_t *fnet_mdns_add_rr_srv(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression) 02346 { 02347 FNET_ASSERT(mdns_if != NULL); 02348 FNET_ASSERT(buf != NULL); 02349 02350 fnet_mdns_rr_data_srv_t data; 02351 fnet_uint8_t *rr_header_ptr; 02352 fnet_uint8_t *ptr = buf; 02353 fnet_uint8_t *result = NULL; 02354 02355 /* Add service name */ 02356 ptr = fnet_mdns_add_service_name(mdns_if, ptr, (buf+buf_size) - ptr, service_if, compression); 02357 if(ptr == NULL) 02358 { 02359 goto ERROR; 02360 } 02361 02362 if((size_t)((buf+buf_size) - ptr) > (sizeof(fnet_mdns_rr_header_t) + sizeof(fnet_mdns_rr_data_srv_t))) 02363 { 02364 /* Add RR header later, when calculate data size */ 02365 rr_header_ptr = ptr; 02366 ptr = ptr + sizeof(fnet_mdns_rr_header_t); 02367 02368 /* Add SRV data */ 02369 fnet_memset(&data, 0, sizeof(data)); 02370 data.port = service_if->service_port; 02371 fnet_memcpy(ptr, (fnet_uint8_t*)&data, sizeof(fnet_mdns_rr_data_srv_t)); 02372 ptr += sizeof(data); 02373 02374 ptr = fnet_mdns_add_host_name(mdns_if, ptr, (buf+buf_size) - ptr, compression); 02375 if(ptr == NULL) 02376 { 02377 goto ERROR; 02378 } 02379 02380 /* Add RR SRV header */ 02381 fnet_mdns_add_rr_header(rr_header_ptr, sizeof(fnet_mdns_rr_header_t), FNET_MDNS_RR_SRV, flush, ttl, ptr - rr_header_ptr - sizeof(fnet_mdns_rr_header_t)); 02382 02383 result = ptr; 02384 } 02385 02386 ERROR: 02387 return result; 02388 } 02389 02390 /************************************************************************ 02391 * DESCRIPTION: Add A record to buffer. 02392 ************************************************************************/ 02393 #if FNET_CFG_IP4 02394 static fnet_uint8_t * fnet_mdns_add_rr_a(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression) 02395 { 02396 FNET_ASSERT(mdns_if != NULL); 02397 FNET_ASSERT(buf != NULL); 02398 02399 fnet_ip4_addr_t my_addr; 02400 fnet_uint8_t *ptr = buf; 02401 fnet_uint8_t *result = NULL; 02402 02403 my_addr = fnet_netif_get_ip4_addr(mdns_if->netif); 02404 02405 ptr = fnet_mdns_add_host_name(mdns_if, ptr, (buf+buf_size) - ptr, compression); 02406 if(ptr == NULL) 02407 { 02408 goto ERROR; 02409 } 02410 02411 /* Prepare RR A record */ 02412 ptr = fnet_mdns_add_rr_header(ptr, (buf+buf_size) - ptr, FNET_MDNS_RR_A, flush, ttl, sizeof(my_addr)); 02413 if(ptr == NULL) 02414 { 02415 goto ERROR; 02416 } 02417 02418 if(((buf+buf_size) - ptr) > sizeof(my_addr)) 02419 { 02420 fnet_memcpy(ptr, &my_addr, sizeof(my_addr)); 02421 ptr += sizeof(my_addr); 02422 02423 result = ptr; 02424 } 02425 02426 ERROR: 02427 return result; 02428 } 02429 #endif /* FNET_CFG_IP4 */ 02430 02431 /************************************************************************ 02432 * DESCRIPTION: Add AAAA record to buffer. 02433 ************************************************************************/ 02434 static fnet_uint8_t * fnet_mdns_add_rr_aaaa(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint32_t ttl, fnet_bool_t flush, fnet_bool_t compression) 02435 { 02436 FNET_ASSERT(mdns_if != NULL); 02437 FNET_ASSERT(buf != NULL); 02438 02439 fnet_uint8_t *ptr = buf; 02440 fnet_uint8_t *result = NULL; 02441 fnet_netif_ip6_addr_info_t addr_info = {.state = FNET_NETIF_IP6_ADDR_STATE_NOT_USED}; 02442 02443 fnet_netif_get_ip6_addr (mdns_if->netif, 0u, &addr_info); /* Just get 1st address.*/ 02444 02445 ptr = fnet_mdns_add_host_name(mdns_if, ptr, (buf+buf_size) - ptr, compression); 02446 if(ptr == NULL) 02447 { 02448 goto ERROR; 02449 } 02450 02451 /* Prepare RR AAAA record */ 02452 ptr = fnet_mdns_add_rr_header(ptr, (buf+buf_size) - ptr, FNET_MDNS_RR_AAAA, flush, ttl, sizeof(addr_info.address)); 02453 if(ptr == NULL) 02454 { 02455 goto ERROR; 02456 } 02457 02458 if((size_t)((buf+buf_size) - ptr) > sizeof(addr_info.address)) 02459 { 02460 fnet_memcpy(ptr, &addr_info.address, sizeof(addr_info.address)); 02461 ptr += sizeof(addr_info.address); 02462 02463 result = ptr; 02464 } 02465 02466 ERROR: 02467 return result; 02468 } 02469 02470 /************************************************************************ 02471 * DESCRIPTION: Add ANY Question Entry to buffer. 02472 ************************************************************************/ 02473 static fnet_uint8_t * fnet_mdns_add_qe_any(fnet_uint8_t *buf, fnet_uint32_t buf_size) 02474 { 02475 FNET_ASSERT(buf != NULL); 02476 02477 fnet_mdns_qe_header_t *qe_header; 02478 fnet_uint8_t *ptr = buf; 02479 fnet_uint8_t *result = NULL; 02480 02481 if(buf_size > sizeof(fnet_mdns_qe_header_t)) 02482 { 02483 /* Prepare Question type and class*/ 02484 qe_header = (fnet_mdns_qe_header_t *)ptr; 02485 qe_header->rr_class = FNET_HTONS( (fnet_uint16_t) FNET_MDNS_HEADER_CLASS_IN ); 02486 qe_header->type = FNET_HTONS( (fnet_uint16_t) FNET_MDNS_RR_ANY ); 02487 ptr += sizeof(fnet_mdns_qe_header_t); 02488 result = ptr; 02489 } 02490 02491 return result; 02492 } 02493 02494 /************************************************************************ 02495 * DESCRIPTION: Add domain name compression. 02496 ************************************************************************/ 02497 static fnet_uint8_t * fnet_mdns_add_domain_name_compression(fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_uint16_t name_offset) 02498 { 02499 FNET_ASSERT(buf != NULL); 02500 02501 fnet_uint8_t *ptr = buf; 02502 fnet_uint8_t *result = NULL; 02503 02504 if(buf_size > 2) 02505 { 02506 *ptr = FNET_MDNS_DOMAIN_NAME_COMPRESSION|((name_offset&0x3F00)>>8); 02507 ptr++; 02508 *ptr = name_offset&0xFF; 02509 ptr++; 02510 02511 result = ptr; 02512 } 02513 02514 return result; 02515 } 02516 02517 /************************************************************************ 02518 * DESCRIPTION: Add host name string. 02519 ************************************************************************/ 02520 static fnet_uint8_t * fnet_mdns_add_host_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_bool_t compression) 02521 { 02522 FNET_ASSERT(mdns_if != NULL); 02523 FNET_ASSERT(buf != NULL); 02524 02525 fnet_uint8_t *ptr = buf; 02526 fnet_uint8_t *result = NULL; 02527 02528 if(mdns_if->offset_host_name && compression) 02529 { 02530 /* Use Domain Name Compression */ 02531 ptr = fnet_mdns_add_domain_name_compression(ptr, (buf+buf_size) - ptr, mdns_if->offset_host_name); 02532 if(ptr == NULL) 02533 { 02534 goto ERROR; 02535 } 02536 } 02537 else 02538 { 02539 if(compression) 02540 { 02541 /* Offset, used by Domain Name Compression.*/ 02542 fnet_uint16_t offset = ptr - mdns_if->buffer; 02543 02544 if(offset <= 0x3FFF) /* Check offset maximum value.*/ 02545 { 02546 mdns_if->offset_host_name = offset; 02547 } 02548 } 02549 02550 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, mdns_if->host_name); 02551 if(ptr == NULL) 02552 { 02553 goto ERROR; 02554 } 02555 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, FNET_MDNS_DOMAIN_NAME); 02556 if(ptr == NULL) 02557 { 02558 goto ERROR; 02559 } 02560 if(((buf+buf_size) - ptr) < 2) 02561 { 02562 goto ERROR; 02563 } 02564 *ptr++ = 0; 02565 } 02566 02567 result = ptr; 02568 02569 ERROR: 02570 return result; 02571 } 02572 02573 /************************************************************************ 02574 * DESCRIPTION: Add service name string. 02575 ************************************************************************/ 02576 static fnet_uint8_t * fnet_mdns_add_service_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_bool_t compression) 02577 { 02578 FNET_ASSERT(mdns_if != NULL); 02579 FNET_ASSERT(buf != NULL); 02580 02581 fnet_uint16_t offset; 02582 fnet_uint8_t *ptr = buf; 02583 fnet_uint8_t *result = NULL; 02584 02585 if(service_if->offset_service_name && compression) 02586 { 02587 /* Use Domain Name Compression */ 02588 ptr = fnet_mdns_add_domain_name_compression(ptr, (buf+buf_size) - ptr, service_if->offset_service_name); 02589 if(ptr == NULL) 02590 { 02591 goto ERROR; 02592 } 02593 } 02594 else 02595 { 02596 if(compression) 02597 { 02598 /* Offset, used by Domain Name Compression.*/ 02599 offset = ptr - mdns_if->buffer; 02600 if(offset <= 0x3FFF) /* Check offset maximum value.*/ 02601 { 02602 service_if->offset_service_name = offset; 02603 } 02604 } 02605 02606 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, mdns_if->service_name); 02607 if(ptr == NULL) 02608 { 02609 goto ERROR; 02610 } 02611 02612 if(compression && (service_if->offset_service_type == 0)) 02613 { 02614 /* Offset, used by Domain Name Compression.*/ 02615 offset = ptr - mdns_if->buffer; 02616 if(offset <= 0x3FFF) /* Check offset maximum value.*/ 02617 { 02618 service_if->offset_service_type = offset; 02619 } 02620 } 02621 02622 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, service_if->service_type); 02623 if(ptr == NULL) 02624 { 02625 goto ERROR; 02626 } 02627 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, FNET_MDNS_DOMAIN_NAME); 02628 if(ptr == NULL) 02629 { 02630 goto ERROR; 02631 } 02632 if(((buf+buf_size) - ptr) < 2) 02633 { 02634 goto ERROR; 02635 } 02636 *ptr++ = 0; 02637 } 02638 02639 result = ptr; 02640 02641 ERROR: 02642 return result; 02643 } 02644 02645 /************************************************************************ 02646 * DESCRIPTION: Add service type string. 02647 ************************************************************************/ 02648 static fnet_uint8_t * fnet_mdns_add_service_type_name(fnet_mdns_if_t *mdns_if, fnet_uint8_t *buf, fnet_uint32_t buf_size, fnet_mdns_service_if_t *service_if, fnet_bool_t compression) 02649 { 02650 FNET_ASSERT(mdns_if != NULL); 02651 FNET_ASSERT(buf != NULL); 02652 02653 fnet_uint8_t *ptr = buf; 02654 fnet_uint16_t offset; 02655 fnet_uint8_t *result = NULL; 02656 02657 if(service_if->offset_service_type && compression) 02658 { 02659 /* Use Domain Name Compression */ 02660 ptr = fnet_mdns_add_domain_name_compression(ptr, (buf+buf_size) - ptr, service_if->offset_service_type); 02661 if(ptr == NULL) 02662 { 02663 goto ERROR; 02664 } 02665 } 02666 else 02667 { 02668 if(compression) 02669 { 02670 /* Offset, used by Domain Name Compression.*/ 02671 offset = ptr - mdns_if->buffer; 02672 if(offset <= 0x3FFF) /* Check offset maximum value.*/ 02673 { 02674 service_if->offset_service_type = offset; 02675 } 02676 } 02677 02678 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, service_if->service_type); 02679 if(ptr == NULL) 02680 { 02681 goto ERROR; 02682 } 02683 ptr = fnet_mdns_add_domain_name(ptr, (buf+buf_size) - ptr, FNET_MDNS_DOMAIN_NAME); 02684 if(ptr == NULL) 02685 { 02686 goto ERROR; 02687 } 02688 if(((buf+buf_size) - ptr) < 2) 02689 { 02690 goto ERROR; 02691 } 02692 *ptr++ = 0; 02693 } 02694 02695 result = ptr; 02696 02697 ERROR: 02698 return result; 02699 } 02700 02701 /************************************************************************ 02702 * DESCRIPTION: Determines if host_name is our fully qualified domain 02703 * name FQDN (hostname.domain). 02704 ************************************************************************/ 02705 static fnet_bool_t fnet_mdns_is_our_host_name(fnet_mdns_if_t *mdns_if, char *host_name) 02706 { 02707 FNET_ASSERT(mdns_if != NULL); 02708 02709 return fnet_mdns_cmp_rr_name(host_name, "", mdns_if->host_name); 02710 } 02711 02712 /************************************************************************ 02713 * DESCRIPTION: Gets service interfcase by name (servicename.type.domain). 02714 ************************************************************************/ 02715 static fnet_mdns_service_if_t *fnet_mdns_get_service_by_name(fnet_mdns_if_t *mdns_if, char *service_name) 02716 { 02717 FNET_ASSERT(mdns_if != NULL); 02718 02719 fnet_index_t i; 02720 fnet_mdns_service_if_t *result = NULL; 02721 02722 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02723 { 02724 if(mdns_if->service_if_list[i].service_type != NULL) 02725 { 02726 if(fnet_mdns_cmp_rr_name(service_name, mdns_if->service_name, mdns_if->service_if_list[i].service_type) == FNET_TRUE) 02727 { 02728 result = &mdns_if->service_if_list[i]; 02729 break; /* Found.*/ 02730 } 02731 } 02732 } 02733 02734 return result; 02735 } 02736 02737 /************************************************************************ 02738 * DESCRIPTION: Gets service interfcase by type (type.domain). 02739 ************************************************************************/ 02740 static fnet_mdns_service_if_t *fnet_mdns_get_service_by_type(fnet_mdns_if_t *mdns_if, char *service_name) 02741 { 02742 FNET_ASSERT(mdns_if != NULL); 02743 02744 fnet_index_t i; 02745 fnet_mdns_service_if_t *result = NULL; 02746 02747 for(i = 0; i<FNET_CFG_MDNS_SERVICE_MAX; i++) 02748 { 02749 if(mdns_if->service_if_list[i].service_type != NULL) 02750 { 02751 if(fnet_mdns_cmp_rr_name(service_name, "", mdns_if->service_if_list[i].service_type) == FNET_TRUE) 02752 { 02753 result = &mdns_if->service_if_list[i]; 02754 break; /* Found.*/ 02755 } 02756 } 02757 } 02758 02759 return result; 02760 } 02761 02762 /************************************************************************ 02763 * DESCRIPTION: Calculate length of key-value record that may have binary data. 02764 ************************************************************************/ 02765 static fnet_uint32_t fnet_mdns_key_value_record_len(const fnet_uint8_t *record) 02766 { 02767 const fnet_uint8_t *ptr; 02768 02769 if (!record) { 02770 return 0; 02771 } 02772 02773 ptr = record; 02774 do { 02775 ptr += (*ptr + 1); 02776 } while (*ptr != 0); 02777 02778 return ptr - record; 02779 } 02780 02781 #endif /* FNET_CFG_MDNS*/
Generated on Tue Jul 12 2022 12:21:53 by
