1 /**
2 * @file
3 * MDNS responder implementation
4 *
5 * @defgroup mdns MDNS
6 * @ingroup apps
7 *
8 * RFC 6762 - Multicast DNS<br>
9 * RFC 6763 - DNS-Based Service Discovery
10 *
11 * You need to increase MEMP_NUM_SYS_TIMEOUT by one if you use MDNS!
12 *
13 * @verbinclude mdns.txt
14 *
15 * Things left to implement:
16 * -------------------------
17 *
18 * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off...
19 * - Sending negative responses NSEC
20 * - Fragmenting replies if required
21 * - Handling multi-packet known answers (TC bit)
22 * - Individual known answer detection for all local IPv6 addresses
23 * - Dynamic size of outgoing packet
24 */
25
26 /*
27 * Copyright (c) 2015 Verisure Innovation AB
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without modification,
31 * are permitted provided that the following conditions are met:
32 *
33 * 1. Redistributions of source code must retain the above copyright notice,
34 * this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright notice,
36 * this list of conditions and the following disclaimer in the documentation
37 * and/or other materials provided with the distribution.
38 * 3. The name of the author may not be used to endorse or promote products
39 * derived from this software without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
44 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
46 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
49 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
50 * OF SUCH DAMAGE.
51 *
52 * This file is part of the lwIP TCP/IP stack.
53 *
54 * Author: Erik Ekman <[email protected]>
55 * Author: Jasper Verschueren <[email protected]>
56 *
57 */
58
59 #include "lwip/apps/mdns.h"
60 #include "lwip/apps/mdns_priv.h"
61 #include "lwip/apps/mdns_domain.h"
62 #include "lwip/apps/mdns_out.h"
63 #include "lwip/netif.h"
64 #include "lwip/udp.h"
65 #include "lwip/ip_addr.h"
66 #include "lwip/mem.h"
67 #include "lwip/prot/dns.h"
68 #include "lwip/prot/iana.h"
69 #include "lwip/timeouts.h"
70 #include "lwip/sys.h"
71
72 #include <string.h> /* memset */
73 #include <stdio.h> /* snprintf */
74
75 #if LWIP_MDNS_RESPONDER
76
77 #if (LWIP_IPV4 && !LWIP_IGMP)
78 #error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h"
79 #endif
80 #if (LWIP_IPV6 && !LWIP_IPV6_MLD)
81 #error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h"
82 #endif
83 #if (!LWIP_UDP)
84 #error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h"
85 #endif
86 #ifndef LWIP_RAND
87 #error "If you want to use MDNS, you have to define LWIP_RAND=(random function) in your lwipopts.h"
88 #endif
89
90 #if LWIP_IPV4
91 #include "lwip/igmp.h"
92 /* IPv4 multicast group 224.0.0.251 */
93 static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT;
94 #endif
95
96 #if LWIP_IPV6
97 #include "lwip/mld6.h"
98 /* IPv6 multicast group FF02::FB */
99 static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT;
100 #endif
101
102 #define MDNS_IP_TTL 255
103
104 #if LWIP_MDNS_SEARCH
105 static struct mdns_request mdns_requests[MDNS_MAX_REQUESTS];
106 #endif
107
108 static u8_t mdns_netif_client_id;
109 static struct udp_pcb *mdns_pcb;
110 #if MDNS_RESP_USENETIF_EXTCALLBACK
NETIF_DECLARE_EXT_CALLBACK(netif_callback)111 NETIF_DECLARE_EXT_CALLBACK(netif_callback)
112 #endif
113 static mdns_name_result_cb_t mdns_name_result_cb;
114
115 #define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id))
116
117 /** Delayed response defines */
118 #define MDNS_RESPONSE_DELAY_MAX 120
119 #define MDNS_RESPONSE_DELAY_MIN 20
120 #define MDNS_RESPONSE_DELAY (LWIP_RAND() %(MDNS_RESPONSE_DELAY_MAX - \
121 MDNS_RESPONSE_DELAY_MIN) + MDNS_RESPONSE_DELAY_MIN)
122
123 /** Probing & announcing defines */
124 #define MDNS_PROBE_DELAY_MS 250
125 #define MDNS_PROBE_COUNT 3
126 #ifdef LWIP_RAND
127 /* first probe timeout SHOULD be random 0-250 ms*/
128 #define MDNS_INITIAL_PROBE_DELAY_MS (LWIP_RAND() % MDNS_PROBE_DELAY_MS)
129 #else
130 #define MDNS_INITIAL_PROBE_DELAY_MS MDNS_PROBE_DELAY_MS
131 #endif
132
133 #define MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS 1000
134 #define MDNS_PROBE_TIEBREAK_MAX_ANSWERS 5
135
136 #define MDNS_LEXICOGRAPHICAL_EQUAL 0
137 #define MDNS_LEXICOGRAPHICAL_EARLIER 1
138 #define MDNS_LEXICOGRAPHICAL_LATER 2
139
140 /* Delay between successive announcements (RFC6762 section 8.3)
141 * -> increase by a factor 2 with every response sent.
142 */
143 #define MDNS_ANNOUNCE_DELAY_MS 1000
144 /* Minimum 2 announces, may send up to 8 (RFC6762 section 8.3) */
145 #define MDNS_ANNOUNCE_COUNT 2
146
147 /** Information about received packet */
148 struct mdns_packet {
149 /** Sender IP/port */
150 ip_addr_t source_addr;
151 u16_t source_port;
152 /** If packet was received unicast */
153 u16_t recv_unicast;
154 /** Packet data */
155 struct pbuf *pbuf;
156 /** Current parsing offset in packet */
157 u16_t parse_offset;
158 /** Identifier. Used in legacy queries */
159 u16_t tx_id;
160 /** Number of questions in packet,
161 * read from packet header */
162 u16_t questions;
163 /** Number of unparsed questions */
164 u16_t questions_left;
165 /** Number of answers in packet */
166 u16_t answers;
167 /** Number of unparsed answers */
168 u16_t answers_left;
169 /** Number of authoritative answers in packet */
170 u16_t authoritative;
171 /** Number of unparsed authoritative answers */
172 u16_t authoritative_left;
173 /** Number of additional answers in packet */
174 u16_t additional;
175 /** Number of unparsed additional answers */
176 u16_t additional_left;
177 };
178
179 struct mdns_question {
180 struct mdns_rr_info info;
181 /** unicast reply requested */
182 u16_t unicast;
183 };
184
185 struct mdns_answer_list {
186 u16_t offset[MDNS_PROBE_TIEBREAK_MAX_ANSWERS];
187 u16_t size;
188 };
189
190 static err_t mdns_parse_pkt_questions(struct netif *netif,
191 struct mdns_packet *pkt,
192 struct mdns_outmsg *reply);
193 static void mdns_define_probe_rrs_to_send(struct netif *netif,
194 struct mdns_outmsg *outmsg);
195 static void mdns_probe_and_announce(void* arg);
196
197 /**
198 * Construction to make mdns struct accessible from mdns_out.c
199 * TODO:
200 * can we add the mdns struct to the netif like we do for dhcp, autoip,...?
201 * Then this is not needed any more.
202 *
203 * @param netif The network interface
204 * @return mdns struct
205 */
206 struct mdns_host*
netif_mdns_data(struct netif * netif)207 netif_mdns_data(struct netif *netif) {
208 return NETIF_TO_HOST(netif);
209 }
210
211 /**
212 * Construction to access the mdns udp pcb.
213 *
214 * @return udp_pcb struct of mdns
215 */
216 struct udp_pcb*
get_mdns_pcb(void)217 get_mdns_pcb(void)
218 {
219 return mdns_pcb;
220 }
221
222 /**
223 * Check which replies we should send for a host/netif based on question
224 * @param netif The network interface that received the question
225 * @param rr Domain/type/class from a question
226 * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for
227 * if reply bit has REPLY_HOST_PTR_V6 set
228 * @return Bitmask of which replies to send
229 */
230 static int
check_host(struct netif * netif,struct mdns_rr_info * rr,u8_t * reverse_v6_reply)231 check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply)
232 {
233 err_t res;
234 int replies = 0;
235 struct mdns_domain mydomain;
236
237 LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */
238
239 if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) {
240 /* Invalid class */
241 return replies;
242 }
243
244 /* Handle PTR for our addresses */
245 if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) {
246 #if LWIP_IPV6
247 int i;
248 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
249 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
250 res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i));
251 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
252 replies |= REPLY_HOST_PTR_V6;
253 /* Mark which addresses where requested */
254 if (reverse_v6_reply) {
255 *reverse_v6_reply |= (1 << i);
256 }
257 }
258 }
259 }
260 #endif
261 #if LWIP_IPV4
262 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
263 res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif));
264 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
265 replies |= REPLY_HOST_PTR_V4;
266 }
267 }
268 #endif
269 }
270
271 res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif));
272 /* Handle requests for our hostname */
273 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
274 /* TODO return NSEC if unsupported protocol requested */
275 #if LWIP_IPV4
276 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))
277 && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) {
278 replies |= REPLY_HOST_A;
279 }
280 #endif
281 #if LWIP_IPV6
282 if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) {
283 replies |= REPLY_HOST_AAAA;
284 }
285 #endif
286 }
287
288 return replies;
289 }
290
291 /**
292 * Check which replies we should send for a service based on question
293 * @param service A registered MDNS service
294 * @param rr Domain/type/class from a question
295 * @return Bitmask of which replies to send
296 */
297 static int
check_service(struct mdns_service * service,struct mdns_rr_info * rr)298 check_service(struct mdns_service *service, struct mdns_rr_info *rr)
299 {
300 err_t res;
301 int replies = 0;
302 struct mdns_domain mydomain;
303
304 if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) {
305 /* Invalid class */
306 return 0;
307 }
308
309 res = mdns_build_dnssd_domain(&mydomain);
310 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
311 (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) {
312 /* Request for all service types */
313 replies |= REPLY_SERVICE_TYPE_PTR;
314 }
315
316 res = mdns_build_service_domain(&mydomain, service, 0);
317 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
318 (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) {
319 /* Request for the instance of my service */
320 replies |= REPLY_SERVICE_NAME_PTR;
321 }
322
323 res = mdns_build_service_domain(&mydomain, service, 1);
324 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
325 /* Request for info about my service */
326 if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) {
327 replies |= REPLY_SERVICE_SRV;
328 }
329 if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) {
330 replies |= REPLY_SERVICE_TXT;
331 }
332 }
333
334 return replies;
335 }
336
337 #if LWIP_MDNS_SEARCH
338 /**
339 * Check if question belong to a specified request
340 * @param request A ongoing MDNS request
341 * @param rr Domain/type/class from an answer
342 * @return Bitmask of which matching replies
343 */
344 static int
check_request(struct mdns_request * request,struct mdns_rr_info * rr)345 check_request(struct mdns_request *request, struct mdns_rr_info *rr)
346 {
347 err_t res;
348 int replies = 0;
349 struct mdns_domain mydomain;
350
351 if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) {
352 /* Invalid class */
353 return 0;
354 }
355
356 res = mdns_build_request_domain(&mydomain, request, 0);
357 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
358 (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) {
359 /* Request for the instance of my service */
360 replies |= REPLY_SERVICE_TYPE_PTR;
361 }
362 res = mdns_build_request_domain(&mydomain, request, 1);
363 if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
364 /* Request for info about my service */
365 if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) {
366 replies |= REPLY_SERVICE_SRV;
367 }
368 if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) {
369 replies |= REPLY_SERVICE_TXT;
370 }
371 }
372 return replies;
373 }
374 #endif
375
376 /**
377 * Helper function for mdns_read_question/mdns_read_answer
378 * Reads a domain, type and class from the packet
379 * @param pkt The MDNS packet to read from. The parse_offset field will be
380 * incremented to point to the next unparsed byte.
381 * @param info The struct to fill with domain, type and class
382 * @return ERR_OK on success, an err_t otherwise
383 */
384 static err_t
mdns_read_rr_info(struct mdns_packet * pkt,struct mdns_rr_info * info)385 mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info)
386 {
387 u16_t field16, copied;
388 pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain);
389 if (pkt->parse_offset == MDNS_READNAME_ERROR) {
390 return ERR_VAL;
391 }
392
393 copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
394 if (copied != sizeof(field16)) {
395 return ERR_VAL;
396 }
397 pkt->parse_offset += copied;
398 info->type = lwip_ntohs(field16);
399
400 copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
401 if (copied != sizeof(field16)) {
402 return ERR_VAL;
403 }
404 pkt->parse_offset += copied;
405 info->klass = lwip_ntohs(field16);
406
407 return ERR_OK;
408 }
409
410 /**
411 * Read a question from the packet.
412 * All questions have to be read before the answers.
413 * @param pkt The MDNS packet to read from. The questions_left field will be decremented
414 * and the parse_offset will be updated.
415 * @param question The struct to fill with question data
416 * @return ERR_OK on success, an err_t otherwise
417 */
418 static err_t
mdns_read_question(struct mdns_packet * pkt,struct mdns_question * question)419 mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question)
420 {
421 /* Safety check */
422 if (pkt->pbuf->tot_len < pkt->parse_offset) {
423 return ERR_VAL;
424 }
425
426 if (pkt->questions_left) {
427 err_t res;
428 pkt->questions_left--;
429
430 memset(question, 0, sizeof(struct mdns_question));
431 res = mdns_read_rr_info(pkt, &question->info);
432 if (res != ERR_OK) {
433 return res;
434 }
435
436 /* Extract unicast flag from class field */
437 question->unicast = question->info.klass & 0x8000;
438 question->info.klass &= 0x7FFF;
439
440 return ERR_OK;
441 }
442 return ERR_VAL;
443 }
444
445 /**
446 * Read an answer from the packet
447 * The variable length reply is not copied, its pbuf offset and length is stored instead.
448 * @param pkt The MDNS packet to read. The num_left field will be decremented and
449 * the parse_offset will be updated.
450 * @param answer The struct to fill with answer data
451 * @param num_left number of answers left -> answers, authoritative or additional
452 * @return ERR_OK on success, an err_t otherwise
453 */
454 static err_t
mdns_read_answer(struct mdns_packet * pkt,struct mdns_answer * answer,u16_t * num_left)455 mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer, u16_t *num_left)
456 {
457 /* Read questions first */
458 if (pkt->questions_left) {
459 return ERR_VAL;
460 }
461
462 /* Safety check */
463 if (pkt->pbuf->tot_len < pkt->parse_offset) {
464 return ERR_VAL;
465 }
466
467 if (*num_left) {
468 u16_t copied, field16;
469 u32_t ttl;
470 err_t res;
471 (*num_left)--;
472
473 memset(answer, 0, sizeof(struct mdns_answer));
474 res = mdns_read_rr_info(pkt, &answer->info);
475 if (res != ERR_OK) {
476 return res;
477 }
478
479 /* Extract cache_flush flag from class field */
480 answer->cache_flush = answer->info.klass & 0x8000;
481 answer->info.klass &= 0x7FFF;
482
483 copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset);
484 if (copied != sizeof(ttl)) {
485 return ERR_VAL;
486 }
487 pkt->parse_offset += copied;
488 answer->ttl = lwip_ntohl(ttl);
489
490 copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset);
491 if (copied != sizeof(field16)) {
492 return ERR_VAL;
493 }
494 pkt->parse_offset += copied;
495 answer->rd_length = lwip_ntohs(field16);
496
497 answer->rd_offset = pkt->parse_offset;
498 pkt->parse_offset += answer->rd_length;
499
500 return ERR_OK;
501 }
502 return ERR_VAL;
503 }
504
505 /**
506 * Send unsolicited answer containing all our known data
507 * @param netif The network interface to send on
508 * @param destination The target address to send to (usually multicast address)
509 */
510 static void
mdns_announce(struct netif * netif,const ip_addr_t * destination)511 mdns_announce(struct netif *netif, const ip_addr_t *destination)
512 {
513 struct mdns_outmsg announce;
514 int i;
515 struct mdns_host *mdns = NETIF_TO_HOST(netif);
516
517 memset(&announce, 0, sizeof(announce));
518 announce.cache_flush = 1;
519 #if LWIP_IPV4
520 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
521 announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4;
522 }
523 #endif
524 #if LWIP_IPV6
525 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
526 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
527 announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6;
528 announce.host_reverse_v6_replies |= (1 << i);
529 }
530 }
531 #endif
532
533 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
534 struct mdns_service *serv = mdns->services[i];
535 if (serv) {
536 announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR |
537 REPLY_SERVICE_SRV | REPLY_SERVICE_TXT;
538 }
539 }
540
541 announce.dest_port = LWIP_IANA_PORT_MDNS;
542 SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr));
543 announce.flags = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
544 mdns_send_outpacket(&announce, netif);
545 }
546
547 /**
548 * Perform lexicographical comparison to define the lexicographical order of the
549 * records.
550 *
551 * @param pkt_a first packet (needed for rr data)
552 * @param pkt_b second packet (needed for rr data)
553 * @param ans_a first rr
554 * @param ans_b second rr
555 * @param result pointer to save result in -> MDNS_LEXICOGRAPHICAL_EQUAL,
556 * MDNS_LEXICOGRAPHICAL_LATER or MDNS_LEXICOGRAPHICAL_EARLIER.
557 * @return err_t ERR_OK if result is good, ERR_VAL if domain decompression failed.
558 */
559 static err_t
mdns_lexicographical_comparison(struct mdns_packet * pkt_a,struct mdns_packet * pkt_b,struct mdns_answer * ans_a,struct mdns_answer * ans_b,u8_t * result)560 mdns_lexicographical_comparison(struct mdns_packet *pkt_a, struct mdns_packet *pkt_b,
561 struct mdns_answer *ans_a, struct mdns_answer *ans_b,
562 u8_t *result)
563 {
564 int len, i;
565 u8_t a_rd, b_rd;
566 u16_t res;
567 struct mdns_domain domain_a, domain_b;
568
569 /* Compare classes */
570 if (ans_a->info.klass != ans_b->info.klass) {
571 if (ans_a->info.klass > ans_b->info.klass) {
572 *result = MDNS_LEXICOGRAPHICAL_LATER;
573 return ERR_OK;
574 }
575 else {
576 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
577 return ERR_OK;
578 }
579 }
580 /* Compare types */
581 if (ans_a->info.type != ans_b->info.type) {
582 if (ans_a->info.type > ans_b->info.type) {
583 *result = MDNS_LEXICOGRAPHICAL_LATER;
584 return ERR_OK;
585 }
586 else {
587 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
588 return ERR_OK;
589 }
590 }
591
592 /* Compare rr data section
593 * Name compression:
594 * We have 4 different RR types in our authoritative section (if IPv4 and IPv6 is enabled): A,
595 * AAAA, SRV and TXT. Only one of the 4 can be subject to name compression in the rdata, the SRV
596 * record. As stated in the RFC6762 section 8.2: the names must be uncompressed before comparison.
597 * We only need to take the SRV record into account. It's the only one that in a comparison with
598 * compressed data could lead to rdata comparison. Others will already stop after the type
599 * comparison. So if we get passed the class and type comparison we need to check if the
600 * comparison contains an SRV record. If so, we need a different comparison method.
601 */
602
603 /* The answers do not contain an SRV record */
604 if (ans_a->info.type != DNS_RRTYPE_SRV && ans_b->info.type != DNS_RRTYPE_SRV) {
605 len = LWIP_MIN(ans_a->rd_length, ans_b->rd_length);
606 for (i = 0; i < len; i++) {
607 a_rd = pbuf_get_at(pkt_a->pbuf, (u16_t)(ans_a->rd_offset + i));
608 b_rd = pbuf_get_at(pkt_b->pbuf, (u16_t)(ans_b->rd_offset + i));
609 if (a_rd != b_rd) {
610 if (a_rd > b_rd) {
611 *result = MDNS_LEXICOGRAPHICAL_LATER;
612 return ERR_OK;
613 }
614 else {
615 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
616 return ERR_OK;
617 }
618 }
619 }
620 /* If the overlapping data is the same, compare the length */
621 if (ans_a->rd_length != ans_b->rd_length) {
622 if (ans_a->rd_length > ans_b->rd_length) {
623 *result = MDNS_LEXICOGRAPHICAL_LATER;
624 return ERR_OK;
625 }
626 else {
627 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
628 return ERR_OK;
629 }
630 }
631 }
632 /* Because the types are guaranteed equal here, we know they are both SRV RRs */
633 else {
634 /* We will first compare the priority, weight and port */
635 for (i = 0; i < 6; i++) {
636 a_rd = pbuf_get_at(pkt_a->pbuf, (u16_t)(ans_a->rd_offset + i));
637 b_rd = pbuf_get_at(pkt_b->pbuf, (u16_t)(ans_b->rd_offset + i));
638 if (a_rd != b_rd) {
639 if (a_rd > b_rd) {
640 *result = MDNS_LEXICOGRAPHICAL_LATER;
641 return ERR_OK;
642 }
643 else {
644 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
645 return ERR_OK;
646 }
647 }
648 }
649 /* Decompress names if compressed and save in domain_a or domain_b */
650 res = mdns_readname(pkt_a->pbuf, ans_a->rd_offset + 6, &domain_a);
651 if (res == MDNS_READNAME_ERROR) {
652 return ERR_VAL;
653 }
654 res = mdns_readname(pkt_b->pbuf, ans_b->rd_offset + 6, &domain_b);
655 if (res == MDNS_READNAME_ERROR) {
656 return ERR_VAL;
657 }
658 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: domain a: len = %d, name = ", domain_a.name[0]));
659 mdns_domain_debug_print(&domain_a);
660 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: domain b: len = %d, name = ", domain_b.name[0]));
661 mdns_domain_debug_print(&domain_b);
662 /* Compare names pairwise */
663 len = LWIP_MIN(domain_a.length, domain_b.length);
664 for (i = 0; i < len; i++) {
665 if (domain_a.name[i] != domain_b.name[i]) {
666 if (domain_a.name[i] > domain_b.name[i]) {
667 *result = MDNS_LEXICOGRAPHICAL_LATER;
668 return ERR_OK;
669 }
670 else {
671 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
672 return ERR_OK;
673 }
674 }
675 }
676 /* If the overlapping data is the same, compare the length */
677 if (domain_a.length != domain_b.length) {
678 if (domain_a.length > domain_b.length) {
679 *result = MDNS_LEXICOGRAPHICAL_LATER;
680 return ERR_OK;
681 }
682 else {
683 *result = MDNS_LEXICOGRAPHICAL_EARLIER;
684 return ERR_OK;
685 }
686 }
687 }
688 /* They are exactly the same */
689 *result = MDNS_LEXICOGRAPHICAL_EQUAL;
690 return ERR_OK;
691 }
692
693 /**
694 * Clear authoritative answer list
695 *
696 * @param a_list answer list to clear
697 */
698 static void
mdns_init_answer_list(struct mdns_answer_list * a_list)699 mdns_init_answer_list(struct mdns_answer_list *a_list)
700 {
701 int i;
702 a_list->size = 0;
703 for(i = 0; i < MDNS_PROBE_TIEBREAK_MAX_ANSWERS; i++) {
704 a_list->offset[i] = 0;
705 }
706 }
707
708 /**
709 * Pushes the offset of the answer on a lexicographically later sorted list.
710 * We use a simple insertion sort because most of the time we are only sorting
711 * two items. The answers are sorted from the smallest to the largest.
712 *
713 * @param a_list Answer list to which to add the answer
714 * @param pkt Packet where answer originated
715 * @param new_offset Offset of the new answer in the packet
716 * @param new_answer The new answer
717 * @return err_t ERR_MEM if list is full
718 */
719 static err_t
mdns_push_answer_to_sorted_list(struct mdns_answer_list * a_list,struct mdns_packet * pkt,u16_t new_offset,struct mdns_answer * new_answer)720 mdns_push_answer_to_sorted_list(struct mdns_answer_list *a_list,
721 struct mdns_packet *pkt,
722 u16_t new_offset,
723 struct mdns_answer *new_answer)
724 {
725 int i;
726 struct mdns_answer a;
727 int pos = a_list->size;
728 err_t res = ERR_OK;
729 u8_t result;
730 u16_t num_left = pkt->authoritative;
731 u16_t parse_offset = pkt->parse_offset;
732
733 /* Check size */
734 if ((a_list->size + 1) >= MDNS_PROBE_TIEBREAK_MAX_ANSWERS) {
735 return ERR_MEM;
736 }
737 /* Search location and open a location */
738 for (i = 0; i < a_list->size; i++) {
739 /* Read answers already in the list from pkt */
740 pkt->parse_offset = a_list->offset[i];
741 res = mdns_read_answer(pkt, &a, &num_left);
742 if (res != ERR_OK) {
743 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping probe packet\n"));
744 return res;
745 }
746 /* Compare them with the new answer to find it's place */
747 res = mdns_lexicographical_comparison(pkt, pkt, &a, new_answer, &result);
748 if (res != ERR_OK) {
749 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to compare answers, skipping probe packet\n"));
750 return res;
751 }
752 if (result == MDNS_LEXICOGRAPHICAL_LATER) {
753 int j;
754 pos = i;
755 for (j = (a_list->size + 1); j>i; j--) {
756 a_list->offset[j] = a_list->offset[j-1];
757 }
758 break;
759 }
760 }
761 /* Insert new value */
762 a_list->offset[pos] = new_offset;
763 a_list->size++;
764 /* Reset parse offset for further evaluation */
765 pkt->parse_offset = parse_offset;
766 return res;
767 }
768
769 /**
770 * Check if the given answer answers the give question
771 *
772 * @param q query to find answer for
773 * @param a answer to given query
774 * @return 1 it a answers q, 0 if not
775 */
776 static u8_t
mdns_is_answer_to_question(struct mdns_question * q,struct mdns_answer * a)777 mdns_is_answer_to_question(struct mdns_question *q, struct mdns_answer *a)
778 {
779 if (q->info.type == DNS_RRTYPE_ANY || q->info.type == a->info.type) {
780 /* The types match or question type is any */
781 if (mdns_domain_eq(&q->info.domain, &a->info.domain)) {
782 return 1;
783 }
784 }
785 return 0;
786 }
787
788 /**
789 * Converts the output packet to the input packet format for probe tiebreaking
790 *
791 * @param inpkt destination packet for conversion
792 * @param outpkt source packet for conversion
793 */
794 static void
mdns_convert_out_to_in_pkt(struct mdns_packet * inpkt,struct mdns_outpacket * outpkt)795 mdns_convert_out_to_in_pkt(struct mdns_packet *inpkt, struct mdns_outpacket *outpkt)
796 {
797 inpkt->pbuf = outpkt->pbuf;
798 inpkt->parse_offset = SIZEOF_DNS_HDR;
799
800 inpkt->questions = inpkt->questions_left = outpkt->questions;
801 inpkt->answers = inpkt->answers_left = outpkt->answers;
802 inpkt->authoritative = inpkt->authoritative_left = outpkt->authoritative;
803 inpkt->additional = inpkt->additional_left = outpkt->additional;
804 }
805
806 /**
807 * Debug print to print the answer part that is lexicographically compared
808 *
809 * @param pkt Packet where answer originated
810 * @param a The answer to print
811 */
812 static void
mdns_debug_print_answer(struct mdns_packet * pkt,struct mdns_answer * a)813 mdns_debug_print_answer(struct mdns_packet *pkt, struct mdns_answer *a)
814 {
815 #ifdef LWIP_DEBUG
816 /* Arbitrarily chose 200 -> don't want to see more then that. It's only
817 * for debug so not that important. */
818 char string[200];
819 int i;
820 int pos;
821
822 pos = snprintf(string, sizeof(string), "Type = %2d, class = %1d, rdata = ", a->info.type, a->info.klass);
823 for (i = 0; ((i < a->rd_length) && ((pos + 4*i) < 195)) ; i++) {
824 snprintf(&string[pos + 4*i], 5, "%3d ", (u8_t)pbuf_get_at(pkt->pbuf, (u16_t)(a->rd_offset + i)));
825 }
826 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: %s\n", string));
827 #else
828 LWIP_UNUSED_ARG(pkt);
829 LWIP_UNUSED_ARG(a);
830 #endif
831 }
832
833 /**
834 * Perform probe tiebreaking according to RFC6762 section 8.2
835 *
836 * @param netif network interface of incoming packet
837 * @param pkt incoming packet
838 */
839 static void
mdns_handle_probe_tiebreaking(struct netif * netif,struct mdns_packet * pkt)840 mdns_handle_probe_tiebreaking(struct netif *netif, struct mdns_packet *pkt)
841 {
842 struct mdns_host *mdns = NETIF_TO_HOST(netif);
843 struct mdns_question pkt_q, my_q, q_dummy;
844 struct mdns_answer pkt_a, my_a;
845 struct mdns_outmsg myprobe_msg;
846 struct mdns_outpacket myprobe_outpkt;
847 struct mdns_packet myprobe_inpkt;
848 struct mdns_answer_list pkt_a_list, my_a_list;
849 u16_t save_parse_offset;
850 u16_t pkt_parse_offset, myprobe_parse_offset, myprobe_questions_left;
851 err_t res;
852 u8_t match, result;
853 int min, i;
854
855 /* Generate probe packet to perform comparison.
856 * This is a lot of calculation at this stage without any pre calculation
857 * needed. It should be evaluated if this is the best approach.
858 */
859 mdns_define_probe_rrs_to_send(netif, &myprobe_msg);
860 memset(&myprobe_outpkt, 0, sizeof(myprobe_outpkt));
861 memset(&myprobe_inpkt, 0, sizeof(myprobe_inpkt));
862 res = mdns_create_outpacket(netif, &myprobe_msg, &myprobe_outpkt);
863 if (res != ERR_OK) {
864 goto cleanup;
865 }
866 mdns_convert_out_to_in_pkt(&myprobe_inpkt, &myprobe_outpkt);
867
868 /* Loop over all our probes to search for matches */
869 while (myprobe_inpkt.questions_left) {
870 /* Read one of our probe questions to check if pkt contains same question */
871 res = mdns_read_question(&myprobe_inpkt, &my_q);
872 if (res != ERR_OK) {
873 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping probe packet\n"));
874 goto cleanup;
875 }
876 /* Remember parse offsets so we can restart the search for the next question */
877 pkt_parse_offset = pkt->parse_offset;
878 myprobe_parse_offset = myprobe_inpkt.parse_offset;
879 /* Remember questions left of our probe packet */
880 myprobe_questions_left = myprobe_inpkt.questions_left;
881 /* Reset match flag */
882 match = 0;
883 /* Search for a matching probe in the incomming packet */
884 while (pkt->questions_left) {
885 /* Read probe questions one by one */
886 res = mdns_read_question(pkt, &pkt_q);
887 if (res != ERR_OK) {
888 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping probe packet\n"));
889 goto cleanup;
890 }
891 /* Stop evaluating if the class is not supported */
892 if (pkt_q.info.klass != DNS_RRCLASS_IN && pkt_q.info.klass != DNS_RRCLASS_ANY) {
893 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: question class not supported, skipping probe packet\n"));
894 goto cleanup;
895 }
896 /* We probe for type any, so we do not have to compare types */
897 /* Compare if we are probing for the same domain */
898 if (mdns_domain_eq(&pkt_q.info.domain, &my_q.info.domain)) {
899 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: We are probing for the same rr\n"));
900 match = 1;
901 break;
902 }
903 }
904 /* When matched start evaluating the authoritative section */
905 if (match) {
906 /* Ignore all following questions to be able to get to the authoritative answers */
907 while (pkt->questions_left) {
908 res = mdns_read_question(pkt, &q_dummy);
909 if (res != ERR_OK) {
910 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping probe packet\n"));
911 goto cleanup;
912 }
913 }
914 while (myprobe_inpkt.questions_left) {
915 res = mdns_read_question(&myprobe_inpkt, &q_dummy);
916 if (res != ERR_OK) {
917 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping probe packet\n"));
918 goto cleanup;
919 }
920 }
921
922 /* Extract and sort our authoritative answers that answer our question */
923 mdns_init_answer_list(&my_a_list);
924 while(myprobe_inpkt.authoritative_left) {
925 save_parse_offset = myprobe_inpkt.parse_offset;
926 res = mdns_read_answer(&myprobe_inpkt, &my_a, &myprobe_inpkt.authoritative_left);
927 if (res != ERR_OK) {
928 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping probe packet\n"));
929 goto cleanup;
930 }
931 if (mdns_is_answer_to_question(&my_q, &my_a)) {
932 /* Add to list */
933 res = mdns_push_answer_to_sorted_list(&my_a_list, &myprobe_inpkt, save_parse_offset, &my_a);
934 if (res != ERR_OK) {
935 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to add answer, skipping probe packet\n"));
936 goto cleanup;
937 }
938 }
939 }
940 /* Extract and sort the packets authoritative answers that answer the
941 question */
942 mdns_init_answer_list(&pkt_a_list);
943 while(pkt->authoritative_left) {
944 save_parse_offset = pkt->parse_offset;
945 res = mdns_read_answer(pkt, &pkt_a, &pkt->authoritative_left);
946 if (res != ERR_OK) {
947 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping probe packet\n"));
948 goto cleanup;
949 }
950 if (mdns_is_answer_to_question(&my_q, &pkt_a)) {
951 /* Add to list */
952 res = mdns_push_answer_to_sorted_list(&pkt_a_list, pkt, save_parse_offset, &pkt_a);
953 if (res != ERR_OK) {
954 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to add answer, skipping probe packet\n"));
955 goto cleanup;
956 }
957 }
958 }
959
960 /* Reinitiate authoritative left */
961 myprobe_inpkt.authoritative_left = myprobe_inpkt.authoritative;
962 pkt->authoritative_left = pkt->authoritative;
963
964 /* Compare pairwise.
965 * - lexicographically later? -> we win, ignore the packet.
966 * - lexicographically earlier? -> we loose, wait one second and retry.
967 * - lexicographically equal? -> no conflict, check other probes.
968 */
969 min = LWIP_MIN(my_a_list.size, pkt_a_list.size);
970 for (i = 0; i < min; i++) {
971 /* Get answer of our own list */
972 myprobe_inpkt.parse_offset = my_a_list.offset[i];
973 res = mdns_read_answer(&myprobe_inpkt, &my_a, &myprobe_inpkt.authoritative_left);
974 if (res != ERR_OK) {
975 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping probe packet\n"));
976 goto cleanup;
977 }
978 /* Get answer of the packets list */
979 pkt->parse_offset = pkt_a_list.offset[i];
980 res = mdns_read_answer(pkt, &pkt_a, &pkt->authoritative_left);
981 if (res != ERR_OK) {
982 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping probe packet\n"));
983 goto cleanup;
984 }
985 /* Print both answers for debugging */
986 mdns_debug_print_answer(pkt, &pkt_a);
987 mdns_debug_print_answer(&myprobe_inpkt, &my_a);
988 /* Define the winner */
989 res = mdns_lexicographical_comparison(&myprobe_inpkt, pkt, &my_a, &pkt_a, &result);
990 if (res != ERR_OK) {
991 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to compare answers, skipping probe packet\n"));
992 goto cleanup;
993 }
994 if (result == MDNS_LEXICOGRAPHICAL_LATER) {
995 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: we win, we are lexicographically later\n"));
996 goto cleanup;
997 }
998 else if (result == MDNS_LEXICOGRAPHICAL_EARLIER) {
999 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: we loose, we are lexicographically earlier. 1s timeout started\n"));
1000 sys_untimeout(mdns_probe_and_announce, netif);
1001 mdns->state = MDNS_STATE_PROBE_WAIT;
1002 mdns->sent_num = 0;
1003 sys_timeout(MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS, mdns_probe_and_announce, netif);
1004 goto cleanup;
1005 }
1006 else {
1007 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: lexicographically equal, so no conclusion\n"));
1008 }
1009 }
1010 /* All compared RR were equal, otherwise we would not be here
1011 * -> check if one of both have more answers to the question */
1012 if (my_a_list.size != pkt_a_list.size) {
1013 if (my_a_list.size > pkt_a_list.size) {
1014 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: we win, we have more records answering the probe\n"));
1015 goto cleanup;
1016 }
1017 else {
1018 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: we loose, we have less records. 1s timeout started\n"));
1019 sys_untimeout(mdns_probe_and_announce, netif);
1020 mdns->state = MDNS_STATE_PROBE_WAIT;
1021 mdns->sent_num = 0;
1022 sys_timeout(MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS, mdns_probe_and_announce, netif);
1023 goto cleanup;
1024 }
1025 }
1026 else {
1027 /* There is no conflict on this probe, both devices have the same data
1028 * in the authoritative section. We should still check the other probes
1029 * for conflicts. */
1030 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: no conflict, all records answering the probe are equal\n"));
1031 }
1032 }
1033 /* Evaluate other probes if any. */
1034 /* Reinitiate parse offsets */
1035 pkt->parse_offset = pkt_parse_offset;
1036 myprobe_inpkt.parse_offset = myprobe_parse_offset;
1037 /* Reinitiate questions_left and authoritative_left */
1038 pkt->questions_left = pkt->questions;
1039 pkt->authoritative_left = pkt->authoritative;
1040 myprobe_inpkt.questions_left = myprobe_questions_left;
1041 myprobe_inpkt.authoritative_left = myprobe_inpkt.authoritative;
1042 }
1043
1044 cleanup:
1045 if (myprobe_inpkt.pbuf != NULL) {
1046 pbuf_free(myprobe_inpkt.pbuf);
1047 }
1048 }
1049
1050 /**
1051 * Check the incomming packet and parse all questions
1052 *
1053 * @param netif network interface of incoming packet
1054 * @param pkt incoming packet
1055 * @param reply outgoing message
1056 * @return err_t
1057 */
1058 static err_t
mdns_parse_pkt_questions(struct netif * netif,struct mdns_packet * pkt,struct mdns_outmsg * reply)1059 mdns_parse_pkt_questions(struct netif *netif, struct mdns_packet *pkt,
1060 struct mdns_outmsg *reply)
1061 {
1062 struct mdns_host *mdns = NETIF_TO_HOST(netif);
1063 struct mdns_service *service;
1064 int i;
1065 err_t res;
1066
1067 while (pkt->questions_left) {
1068 struct mdns_question q;
1069
1070 res = mdns_read_question(pkt, &q);
1071 if (res != ERR_OK) {
1072 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n"));
1073 return res;
1074 }
1075
1076 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain "));
1077 mdns_domain_debug_print(&q.info.domain);
1078 LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass));
1079
1080 if (q.unicast) {
1081 /* Reply unicast if it is requested in the question */
1082 reply->unicast_reply_requested = 1;
1083 }
1084
1085 reply->host_replies |= check_host(netif, &q.info, &reply->host_reverse_v6_replies);
1086
1087 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1088 service = mdns->services[i];
1089 if (!service) {
1090 continue;
1091 }
1092 reply->serv_replies[i] |= check_service(service, &q.info);
1093 }
1094 }
1095
1096 return ERR_OK;
1097 }
1098
1099 /**
1100 * Check the incomming packet and parse all (known) answers
1101 *
1102 * @param netif network interface of incoming packet
1103 * @param pkt incoming packet
1104 * @param reply outgoing message
1105 * @return err_t
1106 */
1107 static err_t
mdns_parse_pkt_known_answers(struct netif * netif,struct mdns_packet * pkt,struct mdns_outmsg * reply)1108 mdns_parse_pkt_known_answers(struct netif *netif, struct mdns_packet *pkt,
1109 struct mdns_outmsg *reply)
1110 {
1111 struct mdns_host *mdns = NETIF_TO_HOST(netif);
1112 struct mdns_service *service;
1113 int i;
1114 err_t res;
1115
1116 while (pkt->answers_left) {
1117 struct mdns_answer ans;
1118 u8_t rev_v6;
1119 int match;
1120 u32_t rr_ttl = MDNS_TTL_120;
1121
1122 res = mdns_read_answer(pkt, &ans, &pkt->answers_left);
1123 if (res != ERR_OK) {
1124 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n"));
1125 return res;
1126 }
1127
1128 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain "));
1129 mdns_domain_debug_print(&ans.info.domain);
1130 LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
1131
1132
1133 if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) {
1134 /* Skip known answers for ANY type & class */
1135 continue;
1136 }
1137
1138 rev_v6 = 0;
1139 match = reply->host_replies & check_host(netif, &ans.info, &rev_v6);
1140 if (match && (ans.ttl > (rr_ttl / 2))) {
1141 /* The RR in the known answer matches an RR we are planning to send,
1142 * and the TTL is less than half gone.
1143 * If the payload matches we should not send that answer.
1144 */
1145 if (ans.info.type == DNS_RRTYPE_PTR) {
1146 /* Read domain and compare */
1147 struct mdns_domain known_ans, my_ans;
1148 u16_t len;
1149 len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
1150 res = mdns_build_host_domain(&my_ans, mdns);
1151 if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1152 #if LWIP_IPV4
1153 if (match & REPLY_HOST_PTR_V4) {
1154 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n"));
1155 reply->host_replies &= ~REPLY_HOST_PTR_V4;
1156 }
1157 #endif
1158 #if LWIP_IPV6
1159 if (match & REPLY_HOST_PTR_V6) {
1160 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n"));
1161 reply->host_reverse_v6_replies &= ~rev_v6;
1162 if (reply->host_reverse_v6_replies == 0) {
1163 reply->host_replies &= ~REPLY_HOST_PTR_V6;
1164 }
1165 }
1166 #endif
1167 }
1168 } else if (match & REPLY_HOST_A) {
1169 #if LWIP_IPV4
1170 if (ans.rd_length == sizeof(ip4_addr_t) &&
1171 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(netif), ans.rd_length) == 0) {
1172 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n"));
1173 reply->host_replies &= ~REPLY_HOST_A;
1174 }
1175 #endif
1176 } else if (match & REPLY_HOST_AAAA) {
1177 #if LWIP_IPV6
1178 if (ans.rd_length == sizeof(ip6_addr_p_t) &&
1179 /* TODO this clears all AAAA responses if first addr is set as known */
1180 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(netif, 0), ans.rd_length) == 0) {
1181 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n"));
1182 reply->host_replies &= ~REPLY_HOST_AAAA;
1183 }
1184 #endif
1185 }
1186 }
1187
1188 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1189 service = mdns->services[i];
1190 if (!service) {
1191 continue;
1192 }
1193 match = reply->serv_replies[i] & check_service(service, &ans.info);
1194 if (match & REPLY_SERVICE_TYPE_PTR) {
1195 rr_ttl = MDNS_TTL_4500;
1196 }
1197 if (match && (ans.ttl > (rr_ttl / 2))) {
1198 /* The RR in the known answer matches an RR we are planning to send,
1199 * and the TTL is less than half gone.
1200 * If the payload matches we should not send that answer.
1201 */
1202 if (ans.info.type == DNS_RRTYPE_PTR) {
1203 /* Read domain and compare */
1204 struct mdns_domain known_ans, my_ans;
1205 u16_t len;
1206 len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
1207 if (len != MDNS_READNAME_ERROR) {
1208 if (match & REPLY_SERVICE_TYPE_PTR) {
1209 res = mdns_build_service_domain(&my_ans, service, 0);
1210 if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1211 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n"));
1212 reply->serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR;
1213 }
1214 }
1215 if (match & REPLY_SERVICE_NAME_PTR) {
1216 res = mdns_build_service_domain(&my_ans, service, 1);
1217 if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1218 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n"));
1219 reply->serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR;
1220 }
1221 }
1222 }
1223 } else if (match & REPLY_SERVICE_SRV) {
1224 /* Read and compare to my SRV record */
1225 u16_t field16, len, read_pos;
1226 struct mdns_domain known_ans, my_ans;
1227 read_pos = ans.rd_offset;
1228 do {
1229 /* Check priority field */
1230 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1231 if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) {
1232 break;
1233 }
1234 read_pos += len;
1235 /* Check weight field */
1236 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1237 if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) {
1238 break;
1239 }
1240 read_pos += len;
1241 /* Check port field */
1242 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1243 if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) {
1244 break;
1245 }
1246 read_pos += len;
1247 /* Check host field */
1248 len = mdns_readname(pkt->pbuf, read_pos, &known_ans);
1249 mdns_build_host_domain(&my_ans, mdns);
1250 if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) {
1251 break;
1252 }
1253 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n"));
1254 reply->serv_replies[i] &= ~REPLY_SERVICE_SRV;
1255 } while (0);
1256 } else if (match & REPLY_SERVICE_TXT) {
1257 mdns_prepare_txtdata(service);
1258 if (service->txtdata.length == ans.rd_length &&
1259 pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
1260 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n"));
1261 reply->serv_replies[i] &= ~REPLY_SERVICE_TXT;
1262 }
1263 }
1264 }
1265 }
1266 }
1267
1268 return ERR_OK;
1269 }
1270
1271 /**
1272 * Check the incomming packet and parse all authoritative answers to see if the
1273 * query is a probe query.
1274 *
1275 * @param netif network interface of incoming packet
1276 * @param pkt incoming packet
1277 * @param reply outgoing message
1278 * @return err_t
1279 */
1280 static err_t
mdns_parse_pkt_authoritative_answers(struct netif * netif,struct mdns_packet * pkt,struct mdns_outmsg * reply)1281 mdns_parse_pkt_authoritative_answers(struct netif *netif, struct mdns_packet *pkt,
1282 struct mdns_outmsg *reply)
1283 {
1284 struct mdns_host *mdns = NETIF_TO_HOST(netif);
1285 struct mdns_service *service;
1286 int i;
1287 err_t res;
1288
1289 while (pkt->authoritative_left) {
1290 struct mdns_answer ans;
1291 u8_t rev_v6;
1292 int match;
1293
1294 res = mdns_read_answer(pkt, &ans, &pkt->authoritative_left);
1295 if (res != ERR_OK) {
1296 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n"));
1297 return res;
1298 }
1299
1300 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Authoritative answer for domain "));
1301 mdns_domain_debug_print(&ans.info.domain);
1302 LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
1303
1304
1305 if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) {
1306 /* Skip known answers for ANY type & class */
1307 continue;
1308 }
1309
1310 rev_v6 = 0;
1311 match = reply->host_replies & check_host(netif, &ans.info, &rev_v6);
1312 if (match) {
1313 reply->probe_query_recv = 1;
1314 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe for own host info received\n"));
1315 }
1316
1317 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1318 service = mdns->services[i];
1319 if (!service) {
1320 continue;
1321 }
1322 match = reply->serv_replies[i] & check_service(service, &ans.info);
1323
1324 if (match) {
1325 reply->probe_query_recv = 1;
1326 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe for own service info received\n"));
1327 }
1328 }
1329 }
1330
1331 return ERR_OK;
1332 }
1333
1334 /**
1335 * Add / copy message to delaying message buffer.
1336 *
1337 * @param dest destination msg struct
1338 * @param src source msg struct
1339 */
1340 static void
mdns_add_msg_to_delayed(struct mdns_outmsg * dest,struct mdns_outmsg * src)1341 mdns_add_msg_to_delayed(struct mdns_outmsg *dest, struct mdns_outmsg *src)
1342 {
1343 int i;
1344
1345 dest->host_questions |= src->host_questions;
1346 dest->host_replies |= src->host_replies;
1347 dest->host_reverse_v6_replies |= src->host_reverse_v6_replies;
1348 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1349 dest->serv_questions[i] |= src->serv_questions[i];
1350 dest->serv_replies[i] |= src->serv_replies[i];
1351 }
1352
1353 dest->flags = src->flags;
1354 dest->cache_flush = src->cache_flush;
1355 dest->tx_id = src->tx_id;
1356 dest->legacy_query = src->legacy_query;
1357 }
1358
1359 /**
1360 * Handle question MDNS packet
1361 * - Perform probe tiebreaking when in probing state
1362 * - Parse all questions and set bits what answers to send
1363 * - Clear pending answers if known answers are supplied
1364 * - Define which type of answer is requested
1365 * - Send out packet or put it on hold until after random time
1366 *
1367 * @param pkt incoming packet
1368 * @param netif network interface of incoming packet
1369 */
1370 static void
mdns_handle_question(struct mdns_packet * pkt,struct netif * netif)1371 mdns_handle_question(struct mdns_packet *pkt, struct netif *netif)
1372 {
1373 struct mdns_host *mdns = NETIF_TO_HOST(netif);
1374 struct mdns_outmsg reply;
1375 u8_t rrs_to_send;
1376 u8_t shared_answer = 0;
1377 u8_t delay_response = 1;
1378 u8_t send_unicast = 0;
1379 u8_t listen_to_QU_bit = 0;
1380 int i;
1381 err_t res;
1382
1383 if ((mdns->state == MDNS_STATE_PROBING) ||
1384 (mdns->state == MDNS_STATE_ANNOUNCE_WAIT)) {
1385 /* Probe Tiebreaking */
1386 /* Check if packet is a probe message */
1387 if ((pkt->questions > 0) && (pkt->answers == 0) &&
1388 (pkt->authoritative > 0) && (pkt->additional == 0)) {
1389 /* This should be a probe message -> call probe handler */
1390 mdns_handle_probe_tiebreaking(netif, pkt);
1391 }
1392 }
1393
1394 if ((mdns->state != MDNS_STATE_COMPLETE) &&
1395 (mdns->state != MDNS_STATE_ANNOUNCING)) {
1396 /* Don't answer questions until we've verified our domains via probing */
1397 /* @todo we should check incoming questions during probing for tiebreaking */
1398 return;
1399 }
1400
1401 memset(&reply, 0, sizeof(struct mdns_outmsg));
1402
1403 /* Parse question */
1404 res = mdns_parse_pkt_questions(netif, pkt, &reply);
1405 if (res != ERR_OK) {
1406 return;
1407 }
1408 /* Parse answers -> count as known answers because it's a question */
1409 res = mdns_parse_pkt_known_answers(netif, pkt, &reply);
1410 if (res != ERR_OK) {
1411 return;
1412 }
1413 /* Parse authoritative answers -> probing */
1414 /* If it's a probe query, we need to directly answer via unicast. */
1415 res = mdns_parse_pkt_authoritative_answers(netif, pkt, &reply);
1416 if (res != ERR_OK) {
1417 return;
1418 }
1419 /* Ignore additional answers -> do not have any need for them at the moment */
1420 if(pkt->additional) {
1421 LWIP_DEBUGF(MDNS_DEBUG,
1422 ("MDNS: Query contains additional answers -> they are discarded\n"));
1423 }
1424
1425 /* Any replies on question? */
1426 rrs_to_send = reply.host_replies | reply.host_questions;
1427 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1428 rrs_to_send |= reply.serv_replies[i] | reply.serv_questions[i];
1429 }
1430
1431 if (!rrs_to_send) {
1432 /* This case is most common */
1433 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Nothing to answer\n"));
1434 return;
1435 }
1436
1437 reply.flags = DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE;
1438
1439 /* Detect if it's a legacy querier asking the question
1440 * How to detect legacy DNS query? (RFC6762 section 6.7)
1441 * - source port != 5353
1442 * - a legacy query can only contain 1 question
1443 */
1444 if (pkt->source_port != LWIP_IANA_PORT_MDNS) {
1445 if (pkt->questions == 1) {
1446 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: request from legacy querier\n"));
1447 reply.legacy_query = 1;
1448 reply.tx_id = pkt->tx_id;
1449 reply.cache_flush = 0;
1450 }
1451 else {
1452 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: ignore query if (src UDP port != 5353) && (!= legacy query)\n"));
1453 return;
1454 }
1455 }
1456 else {
1457 reply.cache_flush = 1;
1458 }
1459
1460 /* Delaying response. (RFC6762 section 6)
1461 * Always delay the response, unicast or multicast, except when:
1462 * - Answering to a single question with a unique answer (not a probe).
1463 * - Answering to a probe query via unicast.
1464 * - Answering to a probe query via multicast if not multicasted within 250ms.
1465 *
1466 * unique answer? -> not if it includes service type or name ptr's
1467 */
1468 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1469 shared_answer |= (reply.serv_replies[i] &
1470 (REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR));
1471 }
1472 if ( ((pkt->questions == 1) && (!shared_answer) && !reply.probe_query_recv)
1473 || (reply.probe_query_recv && reply.unicast_reply_requested)) {
1474 delay_response = 0;
1475 }
1476 #if LWIP_IPV6
1477 if (IP_IS_V6_VAL(pkt->source_addr) && reply.probe_query_recv
1478 && !reply.unicast_reply_requested && !mdns->ipv6.multicast_probe_timeout) {
1479 delay_response = 0;
1480 }
1481 #endif
1482 #if LWIP_IPV4
1483 if (IP_IS_V4_VAL(pkt->source_addr) && reply.probe_query_recv
1484 && !reply.unicast_reply_requested && !mdns->ipv4.multicast_probe_timeout) {
1485 delay_response = 0;
1486 }
1487 #endif
1488 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: response %s delayed\n", (delay_response ? "randomly" : "not")));
1489
1490 /* Unicast / multicast response:
1491 * Answering to (m)DNS querier via unicast response.
1492 * When:
1493 * a) Unicast reply requested && recently multicasted 1/4ttl (RFC6762 section 5.4)
1494 * b) Direct unicast query to port 5353 (RFC6762 section 5.5)
1495 * c) Reply to Legacy DNS querier (RFC6762 section 6.7)
1496 * d) A probe message is received requesting unicast (RFC6762 section 6)
1497 */
1498
1499 #if LWIP_IPV6
1500 if ((IP_IS_V6_VAL(pkt->source_addr) && mdns->ipv6.multicast_timeout_25TTL)) {
1501 listen_to_QU_bit = 1;
1502 }
1503 #endif
1504 #if LWIP_IPV4
1505 if ((IP_IS_V4_VAL(pkt->source_addr) && mdns->ipv4.multicast_timeout_25TTL)) {
1506 listen_to_QU_bit = 1;
1507 }
1508 #endif
1509 if ( (reply.unicast_reply_requested && listen_to_QU_bit)
1510 || pkt->recv_unicast
1511 || reply.legacy_query
1512 || (reply.probe_query_recv && reply.unicast_reply_requested)) {
1513 send_unicast = 1;
1514 }
1515 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: send response via %s\n", (send_unicast ? "unicast" : "multicast")));
1516
1517 /* Send out or put on waiting list */
1518 if (delay_response) {
1519 if (send_unicast) {
1520 #if LWIP_IPV6
1521 /* Add answers to IPv6 waiting list if:
1522 * - it's a IPv6 incoming packet
1523 * - no message is in it yet
1524 */
1525 if (IP_IS_V6_VAL(pkt->source_addr) && !mdns->ipv6.unicast_msg_in_use) {
1526 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to unicast IPv6 waiting list\n"));
1527 SMEMCPY(&mdns->ipv6.delayed_msg_unicast.dest_addr, &pkt->source_addr, sizeof(ip_addr_t));
1528 mdns->ipv6.delayed_msg_unicast.dest_port = pkt->source_port;
1529
1530 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_unicast, &reply);
1531
1532 mdns_set_timeout(netif, MDNS_RESPONSE_DELAY, mdns_send_unicast_msg_delayed_ipv6,
1533 &mdns->ipv6.unicast_msg_in_use);
1534 }
1535 #endif
1536 #if LWIP_IPV4
1537 /* Add answers to IPv4 waiting list if:
1538 * - it's a IPv4 incoming packet
1539 * - no message is in it yet
1540 */
1541 if (IP_IS_V4_VAL(pkt->source_addr) && !mdns->ipv4.unicast_msg_in_use) {
1542 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to unicast IPv4 waiting list\n"));
1543 SMEMCPY(&mdns->ipv4.delayed_msg_unicast.dest_addr, &pkt->source_addr, sizeof(ip_addr_t));
1544 mdns->ipv4.delayed_msg_unicast.dest_port = pkt->source_port;
1545
1546 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_unicast, &reply);
1547
1548 mdns_set_timeout(netif, MDNS_RESPONSE_DELAY, mdns_send_unicast_msg_delayed_ipv4,
1549 &mdns->ipv4.unicast_msg_in_use);
1550 }
1551 #endif
1552 }
1553 else {
1554 #if LWIP_IPV6
1555 /* Add answers to IPv6 waiting list if:
1556 * - it's a IPv6 incoming packet
1557 * - the 1 second timeout is passed (RFC6762 section 6)
1558 * - and it's not a probe packet
1559 * Or if:
1560 * - it's a IPv6 incoming packet
1561 * - and it's a probe packet
1562 */
1563 if (IP_IS_V6_VAL(pkt->source_addr) && !mdns->ipv6.multicast_timeout
1564 && !reply.probe_query_recv) {
1565 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to multicast IPv6 waiting list\n"));
1566
1567 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_multicast, &reply);
1568
1569 mdns_set_timeout(netif, MDNS_RESPONSE_DELAY, mdns_send_multicast_msg_delayed_ipv6,
1570 &mdns->ipv6.multicast_msg_waiting);
1571 }
1572 else if (IP_IS_V6_VAL(pkt->source_addr) && reply.probe_query_recv) {
1573 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to probe multicast IPv6 waiting list\n"));
1574
1575 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_multicast, &reply);
1576
1577 mdns->ipv6.multicast_msg_waiting = 1;
1578 }
1579 #endif
1580 #if LWIP_IPV4
1581 /* Add answers to IPv4 waiting list if:
1582 * - it's a IPv4 incoming packet
1583 * - the 1 second timeout is passed (RFC6762 section 6)
1584 * - and it's not a probe packet
1585 * Or if:
1586 * - it's a IPv4 incoming packet
1587 * - and it's a probe packet
1588 */
1589 if (IP_IS_V4_VAL(pkt->source_addr) && !mdns->ipv4.multicast_timeout
1590 && !reply.probe_query_recv) {
1591 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to multicast IPv4 waiting list\n"));
1592
1593 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_multicast, &reply);
1594
1595 mdns_set_timeout(netif, MDNS_RESPONSE_DELAY, mdns_send_multicast_msg_delayed_ipv4,
1596 &mdns->ipv4.multicast_msg_waiting);
1597 }
1598 else if (IP_IS_V4_VAL(pkt->source_addr) && reply.probe_query_recv) {
1599 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: add answers to probe multicast IPv4 waiting list\n"));
1600
1601 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_multicast, &reply);
1602
1603 mdns->ipv4.multicast_msg_waiting = 1;
1604 }
1605 #endif
1606 }
1607 }
1608 else {
1609 if (send_unicast) {
1610 /* Copy source IP/port to use when responding unicast */
1611 SMEMCPY(&reply.dest_addr, &pkt->source_addr, sizeof(ip_addr_t));
1612 reply.dest_port = pkt->source_port;
1613 /* send answer directly via unicast */
1614 res = mdns_send_outpacket(&reply, netif);
1615 if (res != ERR_OK) {
1616 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Unicast answer could not be send\n"));
1617 }
1618 else {
1619 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Unicast answer send successfully\n"));
1620 }
1621 return;
1622 }
1623 else {
1624 /* Set IP/port to use when responding multicast */
1625 #if LWIP_IPV6
1626 if (IP_IS_V6_VAL(pkt->source_addr)) {
1627 if (mdns->ipv6.multicast_timeout && !reply.probe_query_recv) {
1628 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: we just multicasted, ignore question\n"));
1629 return;
1630 }
1631 SMEMCPY(&reply.dest_addr, &v6group, sizeof(ip_addr_t));
1632 }
1633 #endif
1634 #if LWIP_IPV4
1635 if (IP_IS_V4_VAL(pkt->source_addr)) {
1636 if (mdns->ipv4.multicast_timeout && !reply.probe_query_recv) {
1637 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: we just multicasted, ignore question\n"));
1638 return;
1639 }
1640 SMEMCPY(&reply.dest_addr, &v4group, sizeof(ip_addr_t));
1641 }
1642 #endif
1643 reply.dest_port = LWIP_IANA_PORT_MDNS;
1644 /* send answer directly via multicast */
1645 res = mdns_send_outpacket(&reply, netif);
1646 if (res != ERR_OK) {
1647 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Multicast answer could not be send\n"));
1648 }
1649 else {
1650 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Multicast answer send successfully\n"));
1651 #if LWIP_IPV6
1652 if (IP_IS_V6_VAL(pkt->source_addr)) {
1653 mdns_start_multicast_timeouts_ipv6(netif);
1654 }
1655 #endif
1656 #if LWIP_IPV4
1657 if (IP_IS_V4_VAL(pkt->source_addr)) {
1658 mdns_start_multicast_timeouts_ipv4(netif);
1659 }
1660 #endif
1661 }
1662 return;
1663 }
1664 }
1665 }
1666
1667 /**
1668 * Handle a probe conflict:
1669 * - Check if we exceeded the maximum of 15 conflicts in 10seconds.
1670 * - Let the user know there is a conflict.
1671 *
1672 * @param netif network interface on which the conflict occured.
1673 */
1674 static void
mdns_probe_conflict(struct netif * netif)1675 mdns_probe_conflict(struct netif *netif)
1676 {
1677 struct mdns_host* mdns = NETIF_TO_HOST(netif);
1678 int i;
1679 u32_t diff;
1680 u8_t index2;
1681
1682 /* Disable currently running probe / announce timer */
1683 sys_untimeout(mdns_probe_and_announce, netif);
1684
1685 /* Increase the number of conflicts occured */
1686 mdns->num_conflicts++;
1687 mdns->conflict_time[mdns->index] = sys_now();
1688 /* Print timestamp list */
1689 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: conflict timestamp list, insert index = %d\n", mdns->index));
1690 for(i = 0; i < MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT; i++) {
1691 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: time no. %d = %d\n", i, mdns->conflict_time[i]));
1692 }
1693 /* Check if we had enough conflicts, minimum 15 */
1694 if (mdns->num_conflicts >= MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT) {
1695 /* Get the index to the oldest timestamp */
1696 index2 = (mdns->index + 1) % MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT;
1697 /* Compare the oldest vs newest time stamp */
1698 diff = mdns->conflict_time[mdns->index] - mdns->conflict_time[index2];
1699 /* If they are less then 10 seconds apart, initiate rate limit */
1700 if (diff < MDNS_PROBE_MAX_CONFLICTS_TIME_WINDOW) {
1701 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: probe rate limit enabled\n"));
1702 mdns->rate_limit_activated = 1;
1703 }
1704 }
1705 /* Increase index */
1706 mdns->index = (mdns->index + 1) % MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT;
1707
1708 /* Inform the host on the conflict, if a callback is set */
1709 if (mdns_name_result_cb != NULL) {
1710 mdns_name_result_cb(netif, MDNS_PROBING_CONFLICT);
1711 }
1712 }
1713
1714
1715 /**
1716 * Loockup matching request for response MDNS packet
1717 */
1718 #if LWIP_MDNS_SEARCH
1719 static struct mdns_request *
mdns_lookup_request(struct mdns_rr_info * rr)1720 mdns_lookup_request(struct mdns_rr_info *rr)
1721 {
1722 int i;
1723 /* search originating request */
1724 for (i = 0; i < MDNS_MAX_REQUESTS; i++) {
1725 if ((mdns_requests[i].result_fn != NULL) &&
1726 (check_request(&mdns_requests[i], rr) != 0)) {
1727 return &mdns_requests[i];
1728 }
1729 }
1730 return NULL;
1731 }
1732 #endif
1733
1734 /**
1735 * Handle response MDNS packet:
1736 * - Handle responses on probe query
1737 * - Perform conflict resolution on every packet (RFC6762 section 9)
1738 *
1739 * @param pkt incoming packet
1740 * @param netif network interface on which packet was received
1741 */
1742 static void
mdns_handle_response(struct mdns_packet * pkt,struct netif * netif)1743 mdns_handle_response(struct mdns_packet *pkt, struct netif *netif)
1744 {
1745 struct mdns_host* mdns = NETIF_TO_HOST(netif);
1746 u16_t total_answers_left;
1747 #if LWIP_MDNS_SEARCH
1748 struct mdns_request *req = NULL;
1749 s8_t first = 1;
1750 #endif
1751
1752 /* Ignore responses with a source port different from 5353
1753 * (LWIP_IANA_PORT_MDNS) -> RFC6762 section 6 */
1754 if (pkt->source_port != LWIP_IANA_PORT_MDNS) {
1755 return;
1756 }
1757
1758 /* Ignore all questions */
1759 while (pkt->questions_left) {
1760 struct mdns_question q;
1761 err_t res;
1762 res = mdns_read_question(pkt, &q);
1763 if (res != ERR_OK) {
1764 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n"));
1765 return;
1766 }
1767 #if LWIP_MDNS_SEARCH
1768 else {
1769 req = mdns_lookup_request(&q.info);
1770 }
1771 #endif
1772 }
1773 /* We need to check all resource record sections: answers, authoritative and additional */
1774 total_answers_left = pkt->answers_left + pkt->authoritative_left + pkt->additional_left;
1775 while (total_answers_left) {
1776 struct mdns_answer ans;
1777 err_t res;
1778
1779 res = mdns_read_answer(pkt, &ans, &total_answers_left);
1780 if (res != ERR_OK) {
1781 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n"));
1782 return;
1783 }
1784
1785 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain "));
1786 mdns_domain_debug_print(&ans.info.domain);
1787 LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass));
1788
1789 if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass != DNS_RRCLASS_IN) {
1790 /* Skip answers for ANY type or if class != IN */
1791 continue;
1792 }
1793
1794 #if LWIP_MDNS_SEARCH
1795 if (req && req->only_ptr) {
1796 /* Need to recheck that this answer match request that match previous answer */
1797 if (memcmp (req->service.name, ans.info.domain.name, req->service.length) != 0)
1798 req = NULL;
1799 }
1800 if (!req) {
1801 /* Try hard to search matching request */
1802 req = mdns_lookup_request(&ans.info);
1803 }
1804 if (req && req->result_fn) {
1805 u16_t offset;
1806 struct pbuf *p;
1807 int flags = (first ? MDNS_SEARCH_RESULT_FIRST : 0) |
1808 (!total_answers_left ? MDNS_SEARCH_RESULT_LAST : 0);
1809 if (req->only_ptr) {
1810 if (ans.info.type != DNS_RRTYPE_PTR)
1811 continue; /* Ignore non matching answer type */
1812 flags = MDNS_SEARCH_RESULT_FIRST | MDNS_SEARCH_RESULT_LAST;
1813 }
1814 p = pbuf_skip(pkt->pbuf, ans.rd_offset, &offset);
1815 if (ans.info.type == DNS_RRTYPE_PTR || ans.info.type == DNS_RRTYPE_SRV) {
1816 /* Those RR types have compressed domain name. Must uncompress here,
1817 since cannot be done without pbuf. */
1818 struct {
1819 u16_t values[3]; /* SRV: Prio, Weight, Port */
1820 struct mdns_domain dom; /* PTR & SRV: Domain (uncompressed) */
1821 } data;
1822 u16_t off = (ans.info.type == DNS_RRTYPE_SRV ? 6 : 0);
1823 u16_t len = mdns_readname(pkt->pbuf, ans.rd_offset + off, &data.dom);
1824 if (len == MDNS_READNAME_ERROR) {
1825 /* Ensure result_fn is called anyway, just copy failed domain as is */
1826 data.dom.length = ans.rd_length - off;
1827 memcpy(&data.dom, (const char *)p->payload + offset + off, data.dom.length);
1828 }
1829 /* Adjust len/off according RR type */
1830 if (ans.info.type == DNS_RRTYPE_SRV) {
1831 memcpy(&data, (const char *)p->payload + offset, 6);
1832 len = data.dom.length + 6;
1833 off = 0;
1834 } else {
1835 len = data.dom.length;
1836 off = 6;
1837 }
1838 req->result_fn(&ans, (const char *)&data + off, len, flags, req->arg);
1839 } else {
1840 /* Direct call result_fn with varpart pointing in pbuf payload */
1841 req->result_fn(&ans, (const char *)p->payload + offset, ans.rd_length, flags, req->arg);
1842 }
1843 first = 0;
1844 }
1845 #endif
1846
1847 /* "Conflicting Multicast DNS responses received *before* the first probe
1848 * packet is sent MUST be silently ignored" so drop answer if we haven't
1849 * started probing yet. */
1850 if ((mdns->state == MDNS_STATE_PROBING) ||
1851 (mdns->state == MDNS_STATE_ANNOUNCE_WAIT)) {
1852 struct mdns_domain domain;
1853 u8_t i;
1854 u8_t conflict = 0;
1855
1856 res = mdns_build_host_domain(&domain, mdns);
1857 if (res == ERR_OK && mdns_domain_eq(&ans.info.domain, &domain)) {
1858 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe response matches host domain!"));
1859 conflict = 1;
1860 }
1861
1862 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1863 struct mdns_service* service = mdns->services[i];
1864 if (!service) {
1865 continue;
1866 }
1867 res = mdns_build_service_domain(&domain, service, 1);
1868 if ((res == ERR_OK) && mdns_domain_eq(&ans.info.domain, &domain)) {
1869 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe response matches service domain!"));
1870 conflict = 1;
1871 }
1872 }
1873
1874 if (conflict != 0) {
1875 mdns_probe_conflict(netif);
1876 break;
1877 }
1878 }
1879 /* Perform conflict resolution (RFC6762 section 9):
1880 * We assume a conflict if the hostname or service name matches the answers
1881 * domain. Only if the rdata matches exactly we reset our assumption to no
1882 * conflict. As stated in the RFC:
1883 * What may be considered inconsistent is context sensitive, except that
1884 * resource records with identical rdata are never considered inconsistent,
1885 * even if they originate from different hosts.
1886 */
1887 else if ((mdns->state == MDNS_STATE_ANNOUNCING) ||
1888 (mdns->state == MDNS_STATE_COMPLETE)) {
1889 struct mdns_domain domain;
1890 u8_t i;
1891 u8_t conflict = 0;
1892
1893 /* Evaluate unique hostname records -> A and AAAA */
1894 res = mdns_build_host_domain(&domain, mdns);
1895 if (res == ERR_OK && mdns_domain_eq(&ans.info.domain, &domain)) {
1896 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response matches host domain, assuming conflict\n"));
1897 /* This means a conflict has taken place, except when the packet contains
1898 * exactly the same rdata. */
1899 conflict = 1;
1900 /* Evaluate rdata -> to see if it's a copy of our own data */
1901 if (ans.info.type == DNS_RRTYPE_A) {
1902 #if LWIP_IPV4
1903 if (ans.rd_length == sizeof(ip4_addr_t) &&
1904 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(netif), ans.rd_length) == 0) {
1905 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own IPv4 address record -> no conflict\n"));
1906 conflict = 0;
1907 }
1908 #endif
1909 }
1910 else if (ans.info.type == DNS_RRTYPE_AAAA) {
1911 #if LWIP_IPV6
1912 if (ans.rd_length == sizeof(ip6_addr_p_t)) {
1913 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
1914 if (pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(netif, i), ans.rd_length) == 0) {
1915 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own iPv6 address record, num = %d -> no conflict\n",i));
1916 conflict = 0;
1917 }
1918 }
1919 }
1920 #endif
1921 }
1922 }
1923 /* Evaluate unique service name records -> SRV and TXT */
1924 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
1925 struct mdns_service* service = mdns->services[i];
1926 if (!service) {
1927 continue;
1928 }
1929 res = mdns_build_service_domain(&domain, service, 1);
1930 if ((res == ERR_OK) && mdns_domain_eq(&ans.info.domain, &domain)) {
1931 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response matches service domain, assuming conflict\n"));
1932 /* This means a conflict has taken place, except when the packet contains
1933 * exactly the same rdata. */
1934 conflict = 1;
1935 /* Evaluate rdata -> to see if it's a copy of our own data */
1936 if (ans.info.type == DNS_RRTYPE_SRV) {
1937 /* Read and compare to with our SRV record */
1938 u16_t field16, len, read_pos;
1939 struct mdns_domain srv_ans, my_ans;
1940 read_pos = ans.rd_offset;
1941 do {
1942 /* Check priority field */
1943 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1944 if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) {
1945 break;
1946 }
1947 read_pos += len;
1948 /* Check weight field */
1949 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1950 if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) {
1951 break;
1952 }
1953 read_pos += len;
1954 /* Check port field */
1955 len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos);
1956 if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) {
1957 break;
1958 }
1959 read_pos += len;
1960 /* Check host field */
1961 len = mdns_readname(pkt->pbuf, read_pos, &srv_ans);
1962 mdns_build_host_domain(&my_ans, mdns);
1963 if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&srv_ans, &my_ans)) {
1964 break;
1965 }
1966 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own SRV record -> no conflict\n"));
1967 conflict = 0;
1968 } while (0);
1969 } else if (ans.info.type == DNS_RRTYPE_TXT) {
1970 mdns_prepare_txtdata(service);
1971 if (service->txtdata.length == ans.rd_length &&
1972 pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
1973 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: response equals our own TXT record -> no conflict\n"));
1974 conflict = 0;
1975 }
1976 }
1977 }
1978 }
1979 if (conflict != 0) {
1980 /* Reset host to probing to reconfirm uniqueness */
1981 LWIP_DEBUGF(MDNS_DEBUG, ("mDNS: Conflict resolution -> reset to probing state\n"));
1982 mdns->state = MDNS_STATE_PROBE_WAIT;
1983 mdns->sent_num = 0;
1984 sys_timeout(MDNS_INITIAL_PROBE_DELAY_MS, mdns_probe_and_announce, netif);
1985 break;
1986 }
1987 }
1988 }
1989 /* Clear all xxx_left variables because we parsed all answers */
1990 pkt->answers_left = 0;
1991 pkt->authoritative_left = 0;
1992 pkt->additional_left = 0;
1993 }
1994
1995 /**
1996 * Receive input function for MDNS packets.
1997 * Handles both IPv4 and IPv6 UDP pcbs.
1998 */
1999 static void
mdns_recv(void * arg,struct udp_pcb * pcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)2000 mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
2001 {
2002 struct dns_hdr hdr;
2003 struct mdns_packet packet;
2004 struct netif *recv_netif = ip_current_input_netif();
2005 u16_t offset = 0;
2006
2007 LWIP_UNUSED_ARG(arg);
2008 LWIP_UNUSED_ARG(pcb);
2009
2010 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr) ? 6 : 4, p->tot_len));
2011
2012 if (NETIF_TO_HOST(recv_netif) == NULL) {
2013 /* From netif not configured for MDNS */
2014 goto dealloc;
2015 }
2016
2017 if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) {
2018 /* Too small */
2019 goto dealloc;
2020 }
2021 offset += SIZEOF_DNS_HDR;
2022
2023 if (DNS_HDR_GET_OPCODE(&hdr)) {
2024 /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */
2025 goto dealloc;
2026 }
2027
2028 memset(&packet, 0, sizeof(packet));
2029 SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr));
2030 packet.source_port = port;
2031 packet.pbuf = p;
2032 packet.parse_offset = offset;
2033 packet.tx_id = lwip_ntohs(hdr.id);
2034 packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions);
2035 packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers);
2036 packet.authoritative = packet.authoritative_left = lwip_ntohs(hdr.numauthrr);
2037 packet.additional = packet.additional_left = lwip_ntohs(hdr.numextrarr);
2038
2039 /* Source address check (RFC6762 section 11) -> for responses.
2040 * Source address check (RFC6762 section 5.5) -> for queries.
2041 * When the dest addr == multicast addr we know the packet originated on that
2042 * link. If not, we need to check the source address. We only accept queries
2043 * that originated on the link. Others are discarded.
2044 */
2045 #if LWIP_IPV6
2046 if (IP_IS_V6(ip_current_dest_addr())) {
2047 /* instead of having one 'v6group' per netif, just compare zoneless here */
2048 if (!ip_addr_cmp_zoneless(ip_current_dest_addr(), &v6group)) {
2049 packet.recv_unicast = 1;
2050
2051 if (ip6_addr_ismulticast_global(ip_2_ip6(ip_current_src_addr()))
2052 || ip6_addr_isglobal(ip_2_ip6(ip_current_src_addr()))) {
2053 goto dealloc;
2054 }
2055 }
2056 }
2057 #endif
2058 #if LWIP_IPV4
2059 if (!IP_IS_V6(ip_current_dest_addr())) {
2060 if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) {
2061 packet.recv_unicast = 1;
2062
2063 if (!ip4_addr_netcmp(ip_2_ip4(ip_current_src_addr()),
2064 netif_ip4_addr(recv_netif),
2065 netif_ip4_netmask(recv_netif))){
2066 goto dealloc;
2067 }
2068 }
2069 }
2070 #endif
2071
2072 if (hdr.flags1 & DNS_FLAG1_RESPONSE) {
2073 mdns_handle_response(&packet, recv_netif);
2074 } else {
2075 mdns_handle_question(&packet, recv_netif);
2076 }
2077
2078 dealloc:
2079 pbuf_free(p);
2080 }
2081
2082 #if LWIP_NETIF_EXT_STATUS_CALLBACK && MDNS_RESP_USENETIF_EXTCALLBACK
2083 static void
mdns_netif_ext_status_callback(struct netif * netif,netif_nsc_reason_t reason,const netif_ext_callback_args_t * args)2084 mdns_netif_ext_status_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args)
2085 {
2086 LWIP_UNUSED_ARG(args);
2087
2088 /* MDNS enabled on netif? */
2089 if (NETIF_TO_HOST(netif) == NULL) {
2090 return;
2091 }
2092
2093 if (reason & LWIP_NSC_STATUS_CHANGED) {
2094 if (args->status_changed.state != 0) {
2095 mdns_resp_restart(netif);
2096 }
2097 /* TODO: send goodbye message */
2098 }
2099 if (reason & LWIP_NSC_LINK_CHANGED) {
2100 if (args->link_changed.state != 0) {
2101 mdns_resp_restart(netif);
2102 }
2103 }
2104 if (reason & (LWIP_NSC_IPV4_ADDRESS_CHANGED | LWIP_NSC_IPV4_GATEWAY_CHANGED |
2105 LWIP_NSC_IPV4_NETMASK_CHANGED | LWIP_NSC_IPV4_SETTINGS_CHANGED |
2106 LWIP_NSC_IPV6_SET | LWIP_NSC_IPV6_ADDR_STATE_CHANGED)) {
2107 mdns_resp_announce(netif);
2108 }
2109 }
2110 #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK && MDNS_RESP_USENETIF_EXTCALLBACK */
2111
2112 static void
mdns_define_probe_rrs_to_send(struct netif * netif,struct mdns_outmsg * outmsg)2113 mdns_define_probe_rrs_to_send(struct netif *netif, struct mdns_outmsg *outmsg)
2114 {
2115 struct mdns_host *mdns = NETIF_TO_HOST(netif);
2116 int i;
2117
2118 memset(outmsg, 0, sizeof(struct mdns_outmsg));
2119
2120 /* Add unicast questions with rtype ANY for all our desired records */
2121 outmsg->host_questions = QUESTION_PROBE_HOST_ANY;
2122
2123 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
2124 struct mdns_service* service = mdns->services[i];
2125 if (!service) {
2126 continue;
2127 }
2128 outmsg->serv_questions[i] = QUESTION_PROBE_SERVICE_NAME_ANY;
2129 }
2130
2131 /* Add answers to the questions above into the authority section for tiebreaking */
2132 #if LWIP_IPV4
2133 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
2134 outmsg->host_replies = REPLY_HOST_A;
2135 }
2136 #endif
2137 #if LWIP_IPV6
2138 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
2139 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
2140 outmsg->host_replies |= REPLY_HOST_AAAA;
2141 }
2142 }
2143 #endif
2144
2145 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
2146 struct mdns_service *serv = mdns->services[i];
2147 if (serv) {
2148 outmsg->serv_replies[i] = REPLY_SERVICE_SRV | REPLY_SERVICE_TXT;
2149 }
2150 }
2151 }
2152
2153 static err_t
mdns_send_probe(struct netif * netif,const ip_addr_t * destination)2154 mdns_send_probe(struct netif* netif, const ip_addr_t *destination)
2155 {
2156 struct mdns_outmsg outmsg;
2157
2158 mdns_define_probe_rrs_to_send(netif, &outmsg);
2159
2160 outmsg.tx_id = 0;
2161 outmsg.dest_port = LWIP_IANA_PORT_MDNS;
2162 SMEMCPY(&outmsg.dest_addr, destination, sizeof(outmsg.dest_addr));
2163 return mdns_send_outpacket(&outmsg, netif);
2164 }
2165
2166 /**
2167 * Timer callback for probing and announcing on the network.
2168 */
2169 static void
mdns_probe_and_announce(void * arg)2170 mdns_probe_and_announce(void* arg)
2171 {
2172 struct netif *netif = (struct netif *)arg;
2173 struct mdns_host* mdns = NETIF_TO_HOST(netif);
2174 u32_t announce_delay;
2175
2176
2177 switch (mdns->state) {
2178 case MDNS_STATE_OFF:
2179 case MDNS_STATE_PROBE_WAIT:
2180 case MDNS_STATE_PROBING:
2181 #if LWIP_IPV4
2182 /*if ipv4 wait with probing until address is set*/
2183 if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) &&
2184 mdns_send_probe(netif, &v4group) == ERR_OK)
2185 #endif
2186 {
2187 #if LWIP_IPV6
2188 if (mdns_send_probe(netif, &v6group) == ERR_OK)
2189 #endif
2190 {
2191 mdns->state = MDNS_STATE_PROBING;
2192 mdns->sent_num++;
2193 }
2194 }
2195
2196 if (mdns->sent_num >= MDNS_PROBE_COUNT) {
2197 mdns->state = MDNS_STATE_ANNOUNCE_WAIT;
2198 mdns->sent_num = 0;
2199 }
2200
2201 sys_timeout(MDNS_PROBE_DELAY_MS, mdns_probe_and_announce, netif);
2202
2203 break;
2204 case MDNS_STATE_ANNOUNCE_WAIT:
2205 case MDNS_STATE_ANNOUNCING:
2206 if (mdns->sent_num == 0) {
2207 /* probing was succesful, announce all records */
2208 mdns->state = MDNS_STATE_ANNOUNCING;
2209 /* Reset rate limit max probe conflict timeout flag */
2210 mdns->rate_limit_activated = 0;
2211 /* Let the client know probing was successful */
2212 if (mdns_name_result_cb != NULL) {
2213 mdns_name_result_cb(netif, MDNS_PROBING_SUCCESSFUL);
2214 }
2215 }
2216
2217 mdns_resp_announce(netif);
2218 mdns->sent_num++;
2219
2220 if (mdns->sent_num >= MDNS_ANNOUNCE_COUNT) {
2221 /* Announcing and probing complete */
2222 mdns->state = MDNS_STATE_COMPLETE;
2223 mdns->sent_num = 0;
2224 }
2225 else {
2226 announce_delay = MDNS_ANNOUNCE_DELAY_MS * (1 << (mdns->sent_num - 1));
2227 sys_timeout(announce_delay, mdns_probe_and_announce, netif);
2228 }
2229 break;
2230 case MDNS_STATE_COMPLETE:
2231 default:
2232 /* Do nothing */
2233 break;
2234 }
2235 }
2236
2237 /**
2238 * @ingroup mdns
2239 * Activate MDNS responder for a network interface.
2240 * @param netif The network interface to activate.
2241 * @param hostname Name to use. Queries for <hostname>.local will be answered
2242 * with the IP addresses of the netif. The hostname will be copied, the
2243 * given pointer can be on the stack.
2244 * @return ERR_OK if netif was added, an err_t otherwise
2245 */
2246 err_t
mdns_resp_add_netif(struct netif * netif,const char * hostname)2247 mdns_resp_add_netif(struct netif *netif, const char *hostname)
2248 {
2249 err_t res;
2250 struct mdns_host *mdns;
2251
2252 LWIP_ASSERT_CORE_LOCKED();
2253 LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL);
2254 LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2255
2256 LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL);
2257 mdns = (struct mdns_host *) mem_calloc(1, sizeof(struct mdns_host));
2258 LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM);
2259
2260 netif_set_client_data(netif, mdns_netif_client_id, mdns);
2261
2262 MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname)));
2263
2264 /* Init delayed message structs with address and port */
2265 #if LWIP_IPV4
2266 mdns->ipv4.delayed_msg_multicast.dest_port = LWIP_IANA_PORT_MDNS;
2267 SMEMCPY(&mdns->ipv4.delayed_msg_multicast.dest_addr, &v4group,
2268 sizeof(ip_addr_t));
2269 #endif
2270
2271 #if LWIP_IPV6
2272 mdns->ipv6.delayed_msg_multicast.dest_port = LWIP_IANA_PORT_MDNS;
2273 SMEMCPY(&mdns->ipv6.delayed_msg_multicast.dest_addr, &v6group,
2274 sizeof(ip_addr_t));
2275 #endif
2276
2277 /* Join multicast groups */
2278 #if LWIP_IPV4
2279 res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group));
2280 if (res != ERR_OK) {
2281 goto cleanup;
2282 }
2283 #endif
2284 #if LWIP_IPV6
2285 res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group));
2286 if (res != ERR_OK) {
2287 goto cleanup;
2288 }
2289 #endif
2290
2291 mdns_resp_restart(netif);
2292
2293 return ERR_OK;
2294
2295 cleanup:
2296 mem_free(mdns);
2297 netif_set_client_data(netif, mdns_netif_client_id, NULL);
2298 return res;
2299 }
2300
2301 /**
2302 * @ingroup mdns
2303 * Stop responding to MDNS queries on this interface, leave multicast groups,
2304 * and free the helper structure and any of its services.
2305 * @param netif The network interface to remove.
2306 * @return ERR_OK if netif was removed, an err_t otherwise
2307 */
2308 err_t
mdns_resp_remove_netif(struct netif * netif)2309 mdns_resp_remove_netif(struct netif *netif)
2310 {
2311 int i;
2312 struct mdns_host *mdns;
2313
2314 LWIP_ASSERT_CORE_LOCKED();
2315 LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif);
2316 mdns = NETIF_TO_HOST(netif);
2317 LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL);
2318
2319 sys_untimeout(mdns_probe_and_announce, netif);
2320
2321 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
2322 struct mdns_service *service = mdns->services[i];
2323 if (service) {
2324 mem_free(service);
2325 }
2326 }
2327
2328 /* Leave multicast groups */
2329 #if LWIP_IPV4
2330 igmp_leavegroup_netif(netif, ip_2_ip4(&v4group));
2331 #endif
2332 #if LWIP_IPV6
2333 mld6_leavegroup_netif(netif, ip_2_ip6(&v6group));
2334 #endif
2335
2336 mem_free(mdns);
2337 netif_set_client_data(netif, mdns_netif_client_id, NULL);
2338 return ERR_OK;
2339 }
2340
2341 /**
2342 * @ingroup mdns
2343 * Update MDNS hostname for a network interface.
2344 * @param netif The network interface to activate.
2345 * @param hostname Name to use. Queries for <hostname>.local will be answered
2346 * with the IP addresses of the netif. The hostname will be copied, the
2347 * given pointer can be on the stack.
2348 * @return ERR_OK if name could be set on netif, an err_t otherwise
2349 */
2350 err_t
mdns_resp_rename_netif(struct netif * netif,const char * hostname)2351 mdns_resp_rename_netif(struct netif *netif, const char *hostname)
2352 {
2353 struct mdns_host *mdns;
2354 size_t len;
2355
2356 LWIP_ASSERT_CORE_LOCKED();
2357 len = strlen(hostname);
2358 LWIP_ERROR("mdns_resp_rename_netif: netif != NULL", (netif != NULL), return ERR_VAL);
2359 LWIP_ERROR("mdns_resp_rename_netif: Hostname too long", (len <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2360 mdns = NETIF_TO_HOST(netif);
2361 LWIP_ERROR("mdns_resp_rename_netif: Not an mdns netif", (mdns != NULL), return ERR_VAL);
2362
2363 MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, len));
2364 mdns->name[len] = '\0'; /* null termination in case new name is shorter than previous */
2365
2366 mdns_resp_restart(netif);
2367
2368 return ERR_OK;
2369 }
2370
2371 /**
2372 * @ingroup mdns
2373 * Add a service to the selected network interface.
2374 * @param netif The network interface to publish this service on
2375 * @param name The name of the service
2376 * @param service The service type, like "_http"
2377 * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP
2378 * for others ("_udp")
2379 * @param port The port the service listens to
2380 * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to
2381 * allow dynamic replies.
2382 * @param txt_data Userdata pointer for txt_fn
2383 * @return service_id if the service was added to the netif, an err_t otherwise
2384 */
2385 s8_t
mdns_resp_add_service(struct netif * netif,const char * name,const char * service,enum mdns_sd_proto proto,u16_t port,service_get_txt_fn_t txt_fn,void * txt_data)2386 mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, service_get_txt_fn_t txt_fn, void *txt_data)
2387 {
2388 u8_t slot;
2389 struct mdns_service *srv;
2390 struct mdns_host *mdns;
2391
2392 LWIP_ASSERT_CORE_LOCKED();
2393 LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif);
2394 mdns = NETIF_TO_HOST(netif);
2395 LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL);
2396
2397 LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2398 LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2399 LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL);
2400
2401 for (slot = 0; slot < MDNS_MAX_SERVICES; slot++) {
2402 if (mdns->services[slot] == NULL) {
2403 break;
2404 }
2405 }
2406 LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot < MDNS_MAX_SERVICES), return ERR_MEM);
2407
2408 srv = (struct mdns_service *)mem_calloc(1, sizeof(struct mdns_service));
2409 LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM);
2410
2411 MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name)));
2412 MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service)));
2413 srv->txt_fn = txt_fn;
2414 srv->txt_userdata = txt_data;
2415 srv->proto = (u16_t)proto;
2416 srv->port = port;
2417
2418 mdns->services[slot] = srv;
2419
2420 mdns_resp_restart(netif);
2421
2422 return slot;
2423 }
2424
2425 /**
2426 * @ingroup mdns
2427 * Delete a service on the selected network interface.
2428 * @param netif The network interface on which service should be removed
2429 * @param slot The service slot number returned by mdns_resp_add_service
2430 * @return ERR_OK if the service was removed from the netif, an err_t otherwise
2431 */
2432 err_t
mdns_resp_del_service(struct netif * netif,u8_t slot)2433 mdns_resp_del_service(struct netif *netif, u8_t slot)
2434 {
2435 struct mdns_host *mdns;
2436 struct mdns_service *srv;
2437 LWIP_ASSERT("mdns_resp_del_service: netif != NULL", netif);
2438 mdns = NETIF_TO_HOST(netif);
2439 LWIP_ERROR("mdns_resp_del_service: Not an mdns netif", (mdns != NULL), return ERR_VAL);
2440 LWIP_ERROR("mdns_resp_del_service: Invalid Service ID", slot < MDNS_MAX_SERVICES, return ERR_VAL);
2441 LWIP_ERROR("mdns_resp_del_service: Invalid Service ID", (mdns->services[slot] != NULL), return ERR_VAL);
2442
2443 srv = mdns->services[slot];
2444 mdns->services[slot] = NULL;
2445 mem_free(srv);
2446 return ERR_OK;
2447 }
2448
2449 /**
2450 * @ingroup mdns
2451 * Update name for an MDNS service.
2452 * @param netif The network interface to activate.
2453 * @param slot The service slot number returned by mdns_resp_add_service
2454 * @param name The new name for the service
2455 * @return ERR_OK if name could be set on service, an err_t otherwise
2456 */
2457 err_t
mdns_resp_rename_service(struct netif * netif,u8_t slot,const char * name)2458 mdns_resp_rename_service(struct netif *netif, u8_t slot, const char *name)
2459 {
2460 struct mdns_service *srv;
2461 struct mdns_host *mdns;
2462 size_t len;
2463
2464 LWIP_ASSERT_CORE_LOCKED();
2465 len = strlen(name);
2466 LWIP_ASSERT("mdns_resp_rename_service: netif != NULL", netif);
2467 mdns = NETIF_TO_HOST(netif);
2468 LWIP_ERROR("mdns_resp_rename_service: Not an mdns netif", (mdns != NULL), return ERR_VAL);
2469 LWIP_ERROR("mdns_resp_rename_service: Name too long", (len <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2470 LWIP_ERROR("mdns_resp_rename_service: Invalid Service ID", slot < MDNS_MAX_SERVICES, return ERR_VAL);
2471 LWIP_ERROR("mdns_resp_rename_service: Invalid Service ID", (mdns->services[slot] != NULL), return ERR_VAL);
2472
2473 srv = mdns->services[slot];
2474
2475 MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, len));
2476 srv->name[len] = '\0'; /* null termination in case new name is shorter than previous */
2477
2478 mdns_resp_restart(netif);
2479
2480 return ERR_OK;
2481 }
2482
2483 /**
2484 * @ingroup mdns
2485 * Call this function from inside the service_get_txt_fn_t callback to add text data.
2486 * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte.
2487 * @param service The service provided to the get_txt callback
2488 * @param txt String to add to the TXT field.
2489 * @param txt_len Length of string
2490 * @return ERR_OK if the string was added to the reply, an err_t otherwise
2491 */
2492 err_t
mdns_resp_add_service_txtitem(struct mdns_service * service,const char * txt,u8_t txt_len)2493 mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len)
2494 {
2495 LWIP_ASSERT_CORE_LOCKED();
2496 LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service);
2497
2498 /* Use a mdns_domain struct to store txt chunks since it is the same encoding */
2499 return mdns_domain_add_label(&service->txtdata, txt, txt_len);
2500 }
2501
2502 #if LWIP_MDNS_SEARCH
2503 /**
2504 * @ingroup mdns
2505 * Stop a search request.
2506 * @param request_id The search request to stop
2507 */
2508 void
mdns_search_stop(u8_t request_id)2509 mdns_search_stop(u8_t request_id)
2510 {
2511 struct mdns_request *req;
2512 LWIP_ASSERT("mdns_search_stop: bad request_id", request_id < MDNS_MAX_REQUESTS);
2513 req = &mdns_requests[request_id];
2514 if (req && req->result_fn) {
2515 req->result_fn = NULL;
2516 }
2517 }
2518
2519 /**
2520 * @ingroup mdns
2521 * Search a specific service on the network.
2522 * @param name The name of the service
2523 * @param service The service type, like "_http"
2524 * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP
2525 * for others ("_udp")
2526 * @param netif The network interface where to send search request
2527 * @param result_fn Callback to send answer received. Will be called for each answer of a
2528 * response frame matching request sent.
2529 * @param arg Userdata pointer for result_fn
2530 * @param request_id Returned request identifier to allow stop it.
2531 * @return ERR_OK if the search request was created and sent, an err_t otherwise
2532 */
2533 err_t
mdns_search_service(const char * name,const char * service,enum mdns_sd_proto proto,struct netif * netif,search_result_fn_t result_fn,void * arg,u8_t * request_id)2534 mdns_search_service(const char *name, const char *service, enum mdns_sd_proto proto,
2535 struct netif *netif, search_result_fn_t result_fn, void *arg,
2536 u8_t *request_id)
2537 {
2538 u8_t slot;
2539 struct mdns_request *req;
2540 if (name) {
2541 LWIP_ERROR("mdns_search_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL);
2542 }
2543 LWIP_ERROR("mdns_search_service: Service too long", (strlen(service) < MDNS_DOMAIN_MAXLEN), return ERR_VAL);
2544 LWIP_ERROR("mdns_search_service: Bad reqid pointer", request_id, return ERR_VAL);
2545 LWIP_ERROR("mdns_search_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL);
2546 for (slot = 0; slot < MDNS_MAX_REQUESTS; slot++) {
2547 if (mdns_requests[slot].result_fn == NULL) {
2548 break;
2549 }
2550 }
2551 if (slot >= MDNS_MAX_REQUESTS) {
2552 /* Don't assert if no more space in mdns_request table. Just return an error. */
2553 return ERR_MEM;
2554 }
2555
2556 req = &mdns_requests[slot];
2557 memset(req, 0, sizeof(struct mdns_request));
2558 req->result_fn = result_fn;
2559 req->arg = arg;
2560 req->proto = (u16_t)proto;
2561 req->qtype = DNS_RRTYPE_PTR;
2562 if (proto == DNSSD_PROTO_UDP && strcmp(service, "_services._dns-sd") == 0) {
2563 req->only_ptr = 1; /* don't check other answers */
2564 }
2565 mdns_domain_add_string(&req->service, service);
2566 if (name) {
2567 MEMCPY(&req->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name)));
2568 }
2569 /* save request id (slot) in pointer provided by caller */
2570 *request_id = slot;
2571 /* now prepare a MDNS request and send it (on specified interface) */
2572 #if LWIP_IPV6
2573 mdns_send_request(req, netif, &v6group);
2574 #endif
2575 #if LWIP_IPV4
2576 mdns_send_request(req, netif, &v4group);
2577 #endif
2578 return ERR_OK;
2579 }
2580 #endif
2581
2582 /**
2583 * @ingroup mdns
2584 * Send unsolicited answer containing all our known data
2585 * @param netif The network interface to send on
2586 */
2587 void
mdns_resp_announce(struct netif * netif)2588 mdns_resp_announce(struct netif *netif)
2589 {
2590 struct mdns_host* mdns;
2591 LWIP_ASSERT_CORE_LOCKED();
2592 LWIP_ERROR("mdns_resp_announce: netif != NULL", (netif != NULL), return);
2593
2594 mdns = NETIF_TO_HOST(netif);
2595 if (mdns == NULL) {
2596 return;
2597 }
2598
2599 /* Do not announce if the mdns responder is off, waiting to probe, probing or
2600 * waiting to announce. */
2601 if (!( (mdns->state == MDNS_STATE_OFF)
2602 || (mdns->state == MDNS_STATE_PROBE_WAIT)
2603 || (mdns->state == MDNS_STATE_PROBING)
2604 || (mdns->state == MDNS_STATE_ANNOUNCE_WAIT))) {
2605 /* Announce on IPv6 and IPv4 */
2606 #if LWIP_IPV6
2607 mdns_announce(netif, &v6group);
2608 mdns_start_multicast_timeouts_ipv6(netif);
2609 #endif
2610 #if LWIP_IPV4
2611 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) {
2612 mdns_announce(netif, &v4group);
2613 mdns_start_multicast_timeouts_ipv4(netif);
2614 }
2615 #endif
2616 } /* else: ip address changed while probing was ongoing? @todo reset counter to restart? */
2617 }
2618
2619 /** Register a callback function that is called if probing is completed successfully
2620 * or with a conflict. */
2621 void
mdns_resp_register_name_result_cb(mdns_name_result_cb_t cb)2622 mdns_resp_register_name_result_cb(mdns_name_result_cb_t cb)
2623 {
2624 mdns_name_result_cb = cb;
2625 }
2626
2627 /**
2628 * @ingroup mdns
2629 * Restart mdns responder. Call this when cable is connected after being disconnected or
2630 * administrative interface is set up after being down
2631 * @param netif The network interface to send on
2632 */
2633 void
mdns_resp_restart(struct netif * netif)2634 mdns_resp_restart(struct netif *netif)
2635 {
2636 struct mdns_host* mdns;
2637 LWIP_ASSERT_CORE_LOCKED();
2638 LWIP_ERROR("mdns_resp_restart: netif != NULL", (netif != NULL), return);
2639
2640 mdns = NETIF_TO_HOST(netif);
2641 if (mdns == NULL) {
2642 return;
2643 }
2644 /* Make sure timer is not running */
2645 sys_untimeout(mdns_probe_and_announce, netif);
2646
2647 mdns->sent_num = 0;
2648 mdns->state = MDNS_STATE_PROBE_WAIT;
2649
2650 /* RFC6762 section 8.1: If fifteen conflicts occur within any ten-second period,
2651 * then the host MUST wait at least five seconds before each successive
2652 * additional probe attempt.
2653 */
2654 if (mdns->rate_limit_activated == 1) {
2655 sys_timeout(MDNS_PROBE_MAX_CONFLICTS_TIMEOUT, mdns_probe_and_announce, netif);
2656 }
2657 else {
2658 sys_timeout(MDNS_INITIAL_PROBE_DELAY_MS, mdns_probe_and_announce, netif);
2659 }
2660 }
2661
2662 /**
2663 * @ingroup mdns
2664 * Initiate MDNS responder. Will open UDP sockets on port 5353
2665 */
2666 void
mdns_resp_init(void)2667 mdns_resp_init(void)
2668 {
2669 err_t res;
2670
2671 /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
2672
2673 #if LWIP_MDNS_SEARCH
2674 memset(mdns_requests, 0, sizeof(mdns_requests));
2675 #endif
2676 mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
2677 LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL);
2678 #if LWIP_MULTICAST_TX_OPTIONS
2679 udp_set_multicast_ttl(mdns_pcb, MDNS_IP_TTL);
2680 #else
2681 mdns_pcb->ttl = MDNS_IP_TTL;
2682 #endif
2683 res = udp_bind(mdns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_MDNS);
2684 LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */
2685 LWIP_ASSERT("Failed to bind pcb", res == ERR_OK);
2686 udp_recv(mdns_pcb, mdns_recv, NULL);
2687
2688 mdns_netif_client_id = netif_alloc_client_data_id();
2689
2690 #if MDNS_RESP_USENETIF_EXTCALLBACK
2691 /* register for netif events when started on first netif */
2692 netif_add_ext_callback(&netif_callback, mdns_netif_ext_status_callback);
2693 #endif
2694 }
2695
2696 #endif /* LWIP_MDNS_RESPONDER */
2697