ReactOS 0.4.16-dev-1238-gd80fdbe
mdns_out.c
Go to the documentation of this file.
1
6/*
7 * Copyright (c) 2015 Verisure Innovation AB
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30 * OF SUCH DAMAGE.
31 *
32 * This file is part of the lwIP TCP/IP stack.
33 *
34 * Author: Erik Ekman <erik@kryo.se>
35 * Author: Jasper Verschueren <jasper.verschueren@apart-audio.com>
36 *
37 */
38
39#include "lwip/apps/mdns_out.h"
40#include "lwip/apps/mdns_priv.h"
42#include "lwip/prot/dns.h"
43#include "lwip/prot/iana.h"
44#include "lwip/udp.h"
45
46#include <string.h>
47
48#if LWIP_IPV6
49#include "lwip/prot/ip6.h"
50#endif
51
52
53#if LWIP_MDNS_RESPONDER
54
55/* Function prototypes */
56static void mdns_clear_outmsg(struct mdns_outmsg *outmsg);
57
62void
63mdns_prepare_txtdata(struct mdns_service *service)
64{
65 memset(&service->txtdata, 0, sizeof(struct mdns_domain));
66 if (service->txt_fn) {
67 service->txt_fn(service, service->txt_userdata);
68 }
69}
70
83static err_t
84mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain,
85 u16_t type, u16_t klass, u16_t unicast)
86{
87 u16_t question_len;
88 u16_t field16;
89 err_t res;
90
91 if (!outpkt->pbuf) {
92 /* If no pbuf is active, allocate one */
94 if (!outpkt->pbuf) {
95 return ERR_MEM;
96 }
97 outpkt->write_offset = SIZEOF_DNS_HDR;
98 }
99
100 /* Worst case calculation. Domain string might be compressed */
101 question_len = domain->length + sizeof(type) + sizeof(klass);
102 if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) {
103 /* No space */
104 return ERR_MEM;
105 }
106
107 /* Write name */
108 res = mdns_write_domain(outpkt, domain);
109 if (res != ERR_OK) {
110 return res;
111 }
112
113 /* Write type */
114 field16 = lwip_htons(type);
115 res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
116 if (res != ERR_OK) {
117 return res;
118 }
119 outpkt->write_offset += sizeof(field16);
120
121 /* Write class */
122 if (unicast) {
123 klass |= 0x8000;
124 }
125 field16 = lwip_htons(klass);
126 res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset);
127 if (res != ERR_OK) {
128 return res;
129 }
130 outpkt->write_offset += sizeof(field16);
131
132 return ERR_OK;
133}
134
152static err_t
153mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain,
154 u16_t type, u16_t klass, u16_t cache_flush, u32_t ttl,
155 const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain)
156{
157 u16_t answer_len;
158 u16_t field16;
159 u16_t rdlen_offset;
160 u16_t answer_offset;
161 u32_t field32;
162 err_t res;
163
164 if (!reply->pbuf) {
165 /* If no pbuf is active, allocate one */
167 if (!reply->pbuf) {
168 return ERR_MEM;
169 }
170 reply->write_offset = SIZEOF_DNS_HDR;
171 }
172
173 /* Worst case calculation. Domain strings might be compressed */
174 answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/;
175 if (buf) {
176 answer_len += (u16_t)buf_length;
177 }
178 if (answer_domain) {
179 answer_len += answer_domain->length;
180 }
181 if (reply->write_offset + answer_len > reply->pbuf->tot_len) {
182 /* No space */
183 return ERR_MEM;
184 }
185
186 /* Answer starts with same data as question, then more fields */
187 mdns_add_question(reply, domain, type, klass, cache_flush);
188
189 /* Write TTL */
190 field32 = lwip_htonl(ttl);
191 res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset);
192 if (res != ERR_OK) {
193 return res;
194 }
195 reply->write_offset += sizeof(field32);
196
197 /* Store offsets and skip forward to the data */
198 rdlen_offset = reply->write_offset;
199 reply->write_offset += sizeof(field16);
200 answer_offset = reply->write_offset;
201
202 if (buf) {
203 /* Write static data */
204 res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset);
205 if (res != ERR_OK) {
206 return res;
207 }
208 reply->write_offset += (u16_t)buf_length;
209 }
210
211 if (answer_domain) {
212 /* Write name answer (compressed if possible) */
213 res = mdns_write_domain(reply, answer_domain);
214 if (res != ERR_OK) {
215 return res;
216 }
217 }
218
219 /* Write rd_length after when we know the answer size */
220 field16 = lwip_htons(reply->write_offset - answer_offset);
221 res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset);
222
223 return res;
224}
225
227static err_t
228mdns_add_any_host_question(struct mdns_outpacket *outpkt,
229 struct mdns_host *mdns,
230 u16_t request_unicast_reply)
231{
232 struct mdns_domain host;
233 mdns_build_host_domain(&host, mdns);
234 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Adding host question for ANY type\n"));
235 return mdns_add_question(outpkt, &host, DNS_RRTYPE_ANY, DNS_RRCLASS_IN,
236 request_unicast_reply);
237}
238
240static err_t
241mdns_add_any_service_question(struct mdns_outpacket *outpkt,
242 struct mdns_service *service,
243 u16_t request_unicast_reply)
244{
245 struct mdns_domain domain;
246 mdns_build_service_domain(&domain, service, 1);
247 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Adding service instance question for ANY type\n"));
248 return mdns_add_question(outpkt, &domain, DNS_RRTYPE_ANY, DNS_RRCLASS_IN,
249 request_unicast_reply);
250}
251
252#if LWIP_IPV4
254static err_t
255mdns_add_a_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
256 struct netif *netif)
257{
258 err_t res;
259 u32_t ttl = MDNS_TTL_120;
260 struct mdns_domain host;
261 mdns_build_host_domain(&host, netif_mdns_data(netif));
262 /* When answering to a legacy querier, we need to repeat the question and
263 * limit the ttl to the short legacy ttl */
264 if(msg->legacy_query) {
265 /* Repeating the question only needs to be done for the question asked
266 * (max one question), not for the additional records. */
267 if(reply->questions < 1) {
268 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
269 res = mdns_add_question(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, 0);
270 if (res != ERR_OK) {
271 return res;
272 }
273 reply->questions = 1;
274 }
275 /* ttl of legacy answer may not be greater then 10 seconds */
276 ttl = MDNS_TTL_10;
277 }
278 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n"));
279 return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, msg->cache_flush,
280 ttl, (const u8_t *) netif_ip4_addr(netif),
281 sizeof(ip4_addr_t), NULL);
282}
283
285static err_t
286mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
287 struct netif *netif)
288{
289 err_t res;
290 u32_t ttl = MDNS_TTL_120;
291 struct mdns_domain host, revhost;
292 mdns_build_host_domain(&host, netif_mdns_data(netif));
293 mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif));
294 /* When answering to a legacy querier, we need to repeat the question and
295 * limit the ttl to the short legacy ttl */
296 if(msg->legacy_query) {
297 /* Repeating the question only needs to be done for the question asked
298 * (max one question), not for the additional records. */
299 if(reply->questions < 1) {
300 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
301 res = mdns_add_question(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0);
302 if (res != ERR_OK) {
303 return res;
304 }
305 reply->questions = 1;
306 }
307 /* ttl of legacy answer may not be greater then 10 seconds */
308 ttl = MDNS_TTL_10;
309 }
310 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n"));
311 return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN,
312 msg->cache_flush, ttl, NULL, 0, &host);
313}
314#endif
315
316#if LWIP_IPV6
318static err_t
319mdns_add_aaaa_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
320 struct netif *netif, int addrindex)
321{
322 err_t res;
323 u32_t ttl = MDNS_TTL_120;
324 struct mdns_domain host;
325 mdns_build_host_domain(&host, netif_mdns_data(netif));
326 /* When answering to a legacy querier, we need to repeat the question and
327 * limit the ttl to the short legacy ttl */
328 if(msg->legacy_query) {
329 /* Repeating the question only needs to be done for the question asked
330 * (max one question), not for the additional records. */
331 if(reply->questions < 1) {
332 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
333 res = mdns_add_question(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, 0);
334 if (res != ERR_OK) {
335 return res;
336 }
337 reply->questions = 1;
338 }
339 /* ttl of legacy answer may not be greater then 10 seconds */
340 ttl = MDNS_TTL_10;
341 }
342 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n"));
343 return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, msg->cache_flush,
344 ttl, (const u8_t *) netif_ip6_addr(netif, addrindex),
345 sizeof(ip6_addr_p_t), NULL);
346}
347
349static err_t
350mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
351 struct netif *netif, int addrindex)
352{
353 err_t res;
354 u32_t ttl = MDNS_TTL_120;
355 struct mdns_domain host, revhost;
356 mdns_build_host_domain(&host, netif_mdns_data(netif));
357 mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex));
358 /* When answering to a legacy querier, we need to repeat the question and
359 * limit the ttl to the short legacy ttl */
360 if(msg->legacy_query) {
361 /* Repeating the question only needs to be done for the question asked
362 * (max one question), not for the additional records. */
363 if(reply->questions < 1) {
364 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
365 res = mdns_add_question(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0);
366 if (res != ERR_OK) {
367 return res;
368 }
369 reply->questions = 1;
370 }
371 /* ttl of legacy answer may not be greater then 10 seconds */
372 ttl = MDNS_TTL_10;
373 }
374 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n"));
375 return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN,
376 msg->cache_flush, ttl, NULL, 0, &host);
377}
378#endif
379
381static err_t
382mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
383 struct mdns_service *service)
384{
385 err_t res;
386 u32_t ttl = MDNS_TTL_4500;
387 struct mdns_domain service_type, service_dnssd;
388 mdns_build_service_domain(&service_type, service, 0);
389 mdns_build_dnssd_domain(&service_dnssd);
390 /* When answering to a legacy querier, we need to repeat the question and
391 * limit the ttl to the short legacy ttl */
392 if(msg->legacy_query) {
393 /* Repeating the question only needs to be done for the question asked
394 * (max one question), not for the additional records. */
395 if(reply->questions < 1) {
396 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
397 res = mdns_add_question(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0);
398 if (res != ERR_OK) {
399 return res;
400 }
401 reply->questions = 1;
402 }
403 /* ttl of legacy answer may not be greater then 10 seconds */
404 ttl = MDNS_TTL_10;
405 }
406 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n"));
407 return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN,
408 0, ttl, NULL, 0, &service_type);
409}
410
412static err_t
413mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
414 struct mdns_service *service)
415{
416 err_t res;
417 u32_t ttl = MDNS_TTL_120;
418 struct mdns_domain service_type, service_instance;
419 mdns_build_service_domain(&service_type, service, 0);
420 mdns_build_service_domain(&service_instance, service, 1);
421 /* When answering to a legacy querier, we need to repeat the question and
422 * limit the ttl to the short legacy ttl */
423 if(msg->legacy_query) {
424 /* Repeating the question only needs to be done for the question asked
425 * (max one question), not for the additional records. */
426 if(reply->questions < 1) {
427 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
428 res = mdns_add_question(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0);
429 if (res != ERR_OK) {
430 return res;
431 }
432 reply->questions = 1;
433 }
434 /* ttl of legacy answer may not be greater then 10 seconds */
435 ttl = MDNS_TTL_10;
436 }
437 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n"));
438 return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN,
439 0, ttl, NULL, 0, &service_instance);
440}
441
443static err_t
444mdns_add_srv_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
445 struct mdns_host *mdns, struct mdns_service *service)
446{
447 err_t res;
448 u32_t ttl = MDNS_TTL_120;
449 struct mdns_domain service_instance, srvhost;
450 u16_t srvdata[3];
451 mdns_build_service_domain(&service_instance, service, 1);
452 mdns_build_host_domain(&srvhost, mdns);
453 if (msg->legacy_query) {
454 /* RFC 6762 section 18.14:
455 * In legacy unicast responses generated to answer legacy queries,
456 * name compression MUST NOT be performed on SRV records.
457 */
458 srvhost.skip_compression = 1;
459 /* When answering to a legacy querier, we need to repeat the question and
460 * limit the ttl to the short legacy ttl.
461 * Repeating the question only needs to be done for the question asked
462 * (max one question), not for the additional records. */
463 if(reply->questions < 1) {
464 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
465 res = mdns_add_question(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, 0);
466 if (res != ERR_OK) {
467 return res;
468 }
469 reply->questions = 1;
470 }
471 /* ttl of legacy answer may not be greater then 10 seconds */
472 ttl = MDNS_TTL_10;
473 }
474 srvdata[0] = lwip_htons(SRV_PRIORITY);
475 srvdata[1] = lwip_htons(SRV_WEIGHT);
476 srvdata[2] = lwip_htons(service->port);
477 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n"));
478 return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN,
479 msg->cache_flush, ttl,
480 (const u8_t *) &srvdata, sizeof(srvdata), &srvhost);
481}
482
484static err_t
485mdns_add_txt_answer(struct mdns_outpacket *reply, struct mdns_outmsg *msg,
486 struct mdns_service *service)
487{
488 err_t res;
489 u32_t ttl = MDNS_TTL_120;
490 struct mdns_domain service_instance;
491 mdns_build_service_domain(&service_instance, service, 1);
492 mdns_prepare_txtdata(service);
493 /* When answering to a legacy querier, we need to repeat the question and
494 * limit the ttl to the short legacy ttl */
495 if(msg->legacy_query) {
496 /* Repeating the question only needs to be done for the question asked
497 * (max one question), not for the additional records. */
498 if(reply->questions < 1) {
499 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Add question for legacy query\n"));
500 res = mdns_add_question(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, 0);
501 if (res != ERR_OK) {
502 return res;
503 }
504 reply->questions = 1;
505 }
506 /* ttl of legacy answer may not be greater then 10 seconds */
507 ttl = MDNS_TTL_10;
508 }
509 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n"));
510 return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN,
511 msg->cache_flush, ttl, (u8_t *) &service->txtdata.name,
512 service->txtdata.length, NULL);
513}
514
515
516static err_t
517mdns_add_probe_questions_to_outpacket(struct mdns_outpacket *outpkt, struct mdns_outmsg *msg,
518 struct netif *netif)
519{
520 err_t res;
521 int i;
522 struct mdns_host *mdns = netif_mdns_data(netif);
523
524 /* Write host questions (probing or legacy query) */
525 if(msg->host_questions & QUESTION_PROBE_HOST_ANY) {
526 res = mdns_add_any_host_question(outpkt, mdns, 1);
527 if (res != ERR_OK) {
528 return res;
529 }
530 outpkt->questions++;
531 }
532 /* Write service questions (probing or legacy query) */
533 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
534 struct mdns_service* service = mdns->services[i];
535 if (!service) {
536 continue;
537 }
538 if(msg->serv_questions[i] & QUESTION_PROBE_SERVICE_NAME_ANY) {
539 res = mdns_add_any_service_question(outpkt, service, 1);
540 if (res != ERR_OK) {
541 return res;
542 }
543 outpkt->questions++;
544 }
545 }
546 return ERR_OK;
547}
548
549#if LWIP_MDNS_SEARCH
550static err_t
551mdns_add_query_question_to_outpacket(struct mdns_outpacket *outpkt, struct mdns_outmsg *msg)
552{
553 err_t res;
554 /* Write legacy query question */
555 if(msg->query) {
556 struct mdns_request *req = msg->query;
557 struct mdns_domain dom;
558 /* Build question domain */
559 mdns_build_request_domain(&dom, req, req->name[0]);
560 /* Add query question to output packet */
561 res = mdns_add_question(outpkt, &dom, req->qtype, DNS_RRCLASS_IN, 0);
562 if (res != ERR_OK) {
563 return res;
564 }
565 outpkt->questions++;
566 }
567 return ERR_OK;
568}
569#endif
570
577err_t
578mdns_create_outpacket(struct netif *netif, struct mdns_outmsg *msg,
579 struct mdns_outpacket *outpkt)
580{
581 struct mdns_host *mdns = netif_mdns_data(netif);
582 struct mdns_service *service;
583 err_t res;
584 int i;
585 u16_t answers = 0;
586
587#if LWIP_MDNS_SEARCH
588 res = mdns_add_query_question_to_outpacket(outpkt, msg);
589 if (res != ERR_OK) {
590 return res;
591 }
592#endif
593
594 res = mdns_add_probe_questions_to_outpacket(outpkt, msg, netif);
595 if (res != ERR_OK) {
596 return res;
597 }
598
599 /* Write answers to host questions */
600#if LWIP_IPV4
601 if (msg->host_replies & REPLY_HOST_A) {
602 res = mdns_add_a_answer(outpkt, msg, netif);
603 if (res != ERR_OK) {
604 return res;
605 }
606 answers++;
607 }
608 if (msg->host_replies & REPLY_HOST_PTR_V4) {
609 res = mdns_add_hostv4_ptr_answer(outpkt, msg, netif);
610 if (res != ERR_OK) {
611 return res;
612 }
613 answers++;
614 }
615#endif
616#if LWIP_IPV6
617 if (msg->host_replies & REPLY_HOST_AAAA) {
618 int addrindex;
619 for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) {
620 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))) {
621 res = mdns_add_aaaa_answer(outpkt, msg, netif, addrindex);
622 if (res != ERR_OK) {
623 return res;
624 }
625 answers++;
626 }
627 }
628 }
629 if (msg->host_replies & REPLY_HOST_PTR_V6) {
630 u8_t rev_addrs = msg->host_reverse_v6_replies;
631 int addrindex = 0;
632 while (rev_addrs) {
633 if (rev_addrs & 1) {
634 res = mdns_add_hostv6_ptr_answer(outpkt, msg, netif, addrindex);
635 if (res != ERR_OK) {
636 return res;
637 }
638 answers++;
639 }
640 addrindex++;
641 rev_addrs >>= 1;
642 }
643 }
644#endif
645
646 /* Write answers to service questions */
647 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
648 service = mdns->services[i];
649 if (!service) {
650 continue;
651 }
652
653 if (msg->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) {
654 res = mdns_add_servicetype_ptr_answer(outpkt, msg, service);
655 if (res != ERR_OK) {
656 return res;
657 }
658 answers++;
659 }
660
661 if (msg->serv_replies[i] & REPLY_SERVICE_NAME_PTR) {
662 res = mdns_add_servicename_ptr_answer(outpkt, msg, service);
663 if (res != ERR_OK) {
664 return res;
665 }
666 answers++;
667 }
668
669 if (msg->serv_replies[i] & REPLY_SERVICE_SRV) {
670 res = mdns_add_srv_answer(outpkt, msg, mdns, service);
671 if (res != ERR_OK) {
672 return res;
673 }
674 answers++;
675 }
676
677 if (msg->serv_replies[i] & REPLY_SERVICE_TXT) {
678 res = mdns_add_txt_answer(outpkt, msg, service);
679 if (res != ERR_OK) {
680 return res;
681 }
682 answers++;
683 }
684 }
685
686 /* if this is a response, the data above is anwers, else this is a probe and
687 * the answers above goes into auth section */
688 if (msg->flags & DNS_FLAG1_RESPONSE) {
689 outpkt->answers += answers;
690 } else {
691 outpkt->authoritative += answers;
692 }
693
694 /* All answers written, add additional RRs */
695 for (i = 0; i < MDNS_MAX_SERVICES; i++) {
696 service = mdns->services[i];
697 if (!service) {
698 continue;
699 }
700
701 if (msg->serv_replies[i] & REPLY_SERVICE_NAME_PTR) {
702 /* Our service instance requested, include SRV & TXT
703 * if they are already not requested. */
704 if (!(msg->serv_replies[i] & REPLY_SERVICE_SRV)) {
705 res = mdns_add_srv_answer(outpkt, msg, mdns, service);
706 if (res != ERR_OK) {
707 return res;
708 }
709 outpkt->additional++;
710 }
711
712 if (!(msg->serv_replies[i] & REPLY_SERVICE_TXT)) {
713 res = mdns_add_txt_answer(outpkt, msg, service);
714 if (res != ERR_OK) {
715 return res;
716 }
717 outpkt->additional++;
718 }
719 }
720
721 /* If service instance, SRV, record or an IP address is requested,
722 * supply all addresses for the host
723 */
724 if ((msg->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) ||
725 (msg->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) {
726#if LWIP_IPV6
727 if (!(msg->host_replies & REPLY_HOST_AAAA)) {
728 int addrindex;
729 for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) {
730 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, addrindex))) {
731 res = mdns_add_aaaa_answer(outpkt, msg, netif, addrindex);
732 if (res != ERR_OK) {
733 return res;
734 }
735 outpkt->additional++;
736 }
737 }
738 }
739#endif
740#if LWIP_IPV4
741 if (!(msg->host_replies & REPLY_HOST_A) &&
742 !ip4_addr_isany_val(*netif_ip4_addr(netif))) {
743 res = mdns_add_a_answer(outpkt, msg, netif);
744 if (res != ERR_OK) {
745 return res;
746 }
747 outpkt->additional++;
748 }
749#endif
750 }
751 }
752
753 return res;
754}
755
762err_t
763mdns_send_outpacket(struct mdns_outmsg *msg, struct netif *netif)
764{
765 struct mdns_outpacket outpkt;
766 err_t res;
767
768 memset(&outpkt, 0, sizeof(outpkt));
769
770 res = mdns_create_outpacket(netif, msg, &outpkt);
771 if (res != ERR_OK) {
772 goto cleanup;
773 }
774
775 if (outpkt.pbuf) {
776 struct dns_hdr hdr;
777
778 /* Write header */
779 memset(&hdr, 0, sizeof(hdr));
780 hdr.flags1 = msg->flags;
781 hdr.numquestions = lwip_htons(outpkt.questions);
782 hdr.numanswers = lwip_htons(outpkt.answers);
783 hdr.numauthrr = lwip_htons(outpkt.authoritative);
784 hdr.numextrarr = lwip_htons(outpkt.additional);
785 hdr.id = lwip_htons(msg->tx_id);
786 pbuf_take(outpkt.pbuf, &hdr, sizeof(hdr));
787
788 /* Shrink packet */
789 pbuf_realloc(outpkt.pbuf, outpkt.write_offset);
790
791 /* Send created packet */
792 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d\n",
793 outpkt.write_offset));
794
795 res = udp_sendto_if(get_mdns_pcb(), outpkt.pbuf, &msg->dest_addr, msg->dest_port, netif);
796 }
797
798cleanup:
799 if (outpkt.pbuf) {
800 pbuf_free(outpkt.pbuf);
801 outpkt.pbuf = NULL;
802 }
803 return res;
804}
805
806#if LWIP_IPV4
812void
813mdns_multicast_timeout_reset_ipv4(void *arg)
814{
815 struct netif *netif = (struct netif*)arg;
816 struct mdns_host *mdns = netif_mdns_data(netif);
817
818 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout finished - IPv4\n"));
819
820 mdns->ipv4.multicast_timeout = 0;
821}
822
829void
830mdns_multicast_probe_timeout_reset_ipv4(void *arg)
831{
832 struct netif *netif = (struct netif*)arg;
833 struct mdns_host *mdns = netif_mdns_data(netif);
834 err_t res;
835
836 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast probe timeout finished - IPv4\n"));
837
838 mdns->ipv4.multicast_probe_timeout = 0;
839
840 if (mdns->ipv4.multicast_msg_waiting) {
841 res = mdns_send_outpacket(&mdns->ipv4.delayed_msg_multicast, netif);
842 if(res != ERR_OK) {
843 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Waiting probe multicast send failed - IPv4\n"));
844 }
845 else {
846 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Waiting probe multicast send successful - IPv4\n"));
847 mdns_clear_outmsg(&mdns->ipv4.delayed_msg_multicast);
848 mdns->ipv4.multicast_msg_waiting = 0;
849 mdns_start_multicast_timeouts_ipv4(netif);
850 }
851 }
852}
853
860void
861mdns_multicast_timeout_25ttl_reset_ipv4(void *arg)
862{
863 struct netif *netif = (struct netif*)arg;
864 struct mdns_host *mdns = netif_mdns_data(netif);
865
866 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout 1/4 of ttl finished - IPv4\n"));
867
868 mdns->ipv4.multicast_timeout_25TTL = 0;
869}
870
876void
877mdns_send_multicast_msg_delayed_ipv4(void *arg)
878{
879 struct netif *netif = (struct netif*)arg;
880 struct mdns_host *mdns = netif_mdns_data(netif);
881 err_t res;
882
883 res = mdns_send_outpacket(&mdns->ipv4.delayed_msg_multicast, netif);
884 if(res != ERR_OK) {
885 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed multicast send failed - IPv4\n"));
886 }
887 else {
888 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed multicast send successful - IPv4\n"));
889 mdns_clear_outmsg(&mdns->ipv4.delayed_msg_multicast);
890 mdns->ipv4.multicast_msg_waiting = 0;
891 mdns_start_multicast_timeouts_ipv4(netif);
892 }
893}
894
900void
901mdns_send_unicast_msg_delayed_ipv4(void *arg)
902{
903 struct netif *netif = (struct netif*)arg;
904 struct mdns_host *mdns = netif_mdns_data(netif);
905 err_t res;
906
907 res = mdns_send_outpacket(&mdns->ipv4.delayed_msg_unicast, netif);
908 if(res != ERR_OK) {
909 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed unicast send failed - IPv4\n"));
910 }
911 else {
912 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed unicast send successful - IPv4\n"));
913 mdns_clear_outmsg(&mdns->ipv4.delayed_msg_unicast);
914 mdns->ipv4.unicast_msg_in_use = 0;
915 }
916}
917
926void
927mdns_start_multicast_timeouts_ipv4(struct netif *netif)
928{
929 struct mdns_host *mdns = netif_mdns_data(netif);
930
931 mdns_set_timeout(netif, MDNS_MULTICAST_TIMEOUT, mdns_multicast_timeout_reset_ipv4,
932 &mdns->ipv4.multicast_timeout);
933 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout started - IPv4\n"));
934 mdns_set_timeout(netif, MDNS_MULTICAST_PROBE_TIMEOUT, mdns_multicast_probe_timeout_reset_ipv4,
935 &mdns->ipv4.multicast_probe_timeout);
936 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast probe timeout started - IPv4\n"));
937 mdns_set_timeout(netif, MDNS_MULTICAST_TIMEOUT_25TTL, mdns_multicast_timeout_25ttl_reset_ipv4,
938 &mdns->ipv4.multicast_timeout_25TTL);
939 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout 1/4 of ttl started - IPv4\n"));
940}
941#endif
942
943#if LWIP_IPV6
949void
950mdns_multicast_timeout_reset_ipv6(void *arg)
951{
952 struct netif *netif = (struct netif*)arg;
953 struct mdns_host *mdns = netif_mdns_data(netif);
954
955 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout finished - IPv6\n"));
956
957 mdns->ipv6.multicast_timeout = 0;
958}
959
966void
967mdns_multicast_probe_timeout_reset_ipv6(void *arg)
968{
969 struct netif *netif = (struct netif*)arg;
970 struct mdns_host *mdns = netif_mdns_data(netif);
971 err_t res;
972
973 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast probe timeout finished - IPv6\n"));
974
975 mdns->ipv6.multicast_probe_timeout = 0;
976
977 if (mdns->ipv6.multicast_msg_waiting) {
978 res = mdns_send_outpacket(&mdns->ipv6.delayed_msg_multicast, netif);
979 if(res != ERR_OK) {
980 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Waiting probe multicast send failed - IPv6\n"));
981 }
982 else {
983 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Waiting probe multicast send successful - IPv6\n"));
984 mdns_clear_outmsg(&mdns->ipv6.delayed_msg_multicast);
985 mdns->ipv6.multicast_msg_waiting = 0;
986 mdns_start_multicast_timeouts_ipv6(netif);
987 }
988 }
989}
990
997void
998mdns_multicast_timeout_25ttl_reset_ipv6(void *arg)
999{
1000 struct netif *netif = (struct netif*)arg;
1001 struct mdns_host *mdns = netif_mdns_data(netif);
1002
1003 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout 1/4 of ttl finished - IPv6\n"));
1004
1005 mdns->ipv6.multicast_timeout_25TTL = 0;
1006}
1007
1013void
1014mdns_send_multicast_msg_delayed_ipv6(void *arg)
1015{
1016 struct netif *netif = (struct netif*)arg;
1017 struct mdns_host *mdns = netif_mdns_data(netif);
1018 err_t res;
1019
1020 res = mdns_send_outpacket(&mdns->ipv6.delayed_msg_multicast, netif);
1021 if(res != ERR_OK) {
1022 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed multicast send failed - IPv6\n"));
1023 }
1024 else {
1025 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed multicast send successful - IPv6\n"));
1026 mdns_clear_outmsg(&mdns->ipv6.delayed_msg_multicast);
1027 mdns->ipv6.multicast_msg_waiting = 0;
1028 mdns_start_multicast_timeouts_ipv6(netif);
1029 }
1030}
1031
1037void
1038mdns_send_unicast_msg_delayed_ipv6(void *arg)
1039{
1040 struct netif *netif = (struct netif*)arg;
1041 struct mdns_host *mdns = netif_mdns_data(netif);
1042 err_t res;
1043
1044 res = mdns_send_outpacket(&mdns->ipv6.delayed_msg_unicast, netif);
1045 if(res != ERR_OK) {
1046 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed unicast send failed - IPv6\n"));
1047 }
1048 else {
1049 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Delayed unicast send successful - IPv6\n"));
1050 mdns_clear_outmsg(&mdns->ipv6.delayed_msg_unicast);
1051 mdns->ipv6.unicast_msg_in_use = 0;
1052 }
1053}
1054
1063void
1064mdns_start_multicast_timeouts_ipv6(struct netif *netif)
1065{
1066 struct mdns_host *mdns = netif_mdns_data(netif);
1067
1068 mdns_set_timeout(netif, MDNS_MULTICAST_TIMEOUT, mdns_multicast_timeout_reset_ipv6,
1069 &mdns->ipv6.multicast_timeout);
1070 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout started - IPv6\n"));
1071 mdns_set_timeout(netif, MDNS_MULTICAST_PROBE_TIMEOUT, mdns_multicast_probe_timeout_reset_ipv6,
1072 &mdns->ipv6.multicast_probe_timeout);
1073 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast probe timeout started - IPv6\n"));
1074 mdns_set_timeout(netif, MDNS_MULTICAST_TIMEOUT_25TTL, mdns_multicast_timeout_25ttl_reset_ipv6,
1075 &mdns->ipv6.multicast_timeout_25TTL);
1076 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: multicast timeout 1/4 of ttl started - IPv6\n"));
1077}
1078#endif
1079
1087static void
1088mdns_clear_outmsg(struct mdns_outmsg *outmsg)
1089{
1090 int i;
1091
1092 outmsg->tx_id = 0;
1093 outmsg->flags = 0;
1094 outmsg->cache_flush = 0;
1095 outmsg->unicast_reply_requested = 0;
1096 outmsg->legacy_query = 0;
1097 outmsg->probe_query_recv = 0;
1098 outmsg->host_questions = 0;
1099 outmsg->host_replies = 0;
1100 outmsg->host_reverse_v6_replies = 0;
1101
1102 for(i = 0; i < MDNS_MAX_SERVICES; i++) {
1103 outmsg->serv_questions[i] = 0;
1104 outmsg->serv_replies[i] = 0;
1105 }
1106}
1107
1118void
1119mdns_set_timeout(struct netif *netif, u32_t msecs, sys_timeout_handler handler,
1120 u8_t *busy_flag)
1121{
1122 if(*busy_flag) {
1123 /* restart timer */
1124 sys_untimeout(handler, netif);
1125 sys_timeout(msecs, handler, netif);
1126 }
1127 else {
1128 /* start timer */
1129 sys_timeout(msecs, handler, netif);
1130 }
1131 /* Now we have a timer running */
1132 *busy_flag = 1;
1133}
1134
1135#ifdef LWIP_MDNS_SEARCH
1142err_t
1143mdns_send_request(struct mdns_request *req, struct netif *netif, const ip_addr_t *destination)
1144{
1145 struct mdns_outmsg outmsg;
1146 err_t res;
1147
1148 memset(&outmsg, 0, sizeof(outmsg));
1149 outmsg.query = req;
1150 outmsg.dest_port = LWIP_IANA_PORT_MDNS;
1151 SMEMCPY(&outmsg.dest_addr, destination, sizeof(outmsg.dest_addr));
1152 res = mdns_send_outpacket(&outmsg, netif);
1153 if(res != ERR_OK) {
1154 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Multicast query request send failed\n"));
1155 }
1156 else {
1157 LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Multicast query request send successful\n"));
1158 }
1159 return res;
1160}
1161#endif
1162
1163#endif /* LWIP_MDNS_RESPONDER */
#define msg(x)
Definition: auth_time.c:54
#define lwip_htons(x)
Definition: def.h:86
#define lwip_htonl(x)
Definition: def.h:88
#define NULL
Definition: types.h:112
static void cleanup(void)
Definition: main.c:1335
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define ERR_MEM
Definition: fontsub.h:52
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint res
Definition: glext.h:9613
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t u32_t
Definition: arch.h:129
uint8_t u8_t
Definition: arch.h:125
uint16_t u16_t
Definition: arch.h:127
@ LWIP_IANA_PORT_MDNS
Definition: iana.h:88
s8_t err_t
Definition: err.h:96
@ ERR_OK
Definition: err.h:55
#define LWIP_IPV6_NUM_ADDRESSES
Definition: opt.h:2487
#define SMEMCPY(dst, src, len)
Definition: opt.h:145
#define MDNS_OUTPUT_PACKET_SIZE
Definition: mdns_opts.h:88
#define MDNS_DEBUG
Definition: mdns_opts.h:114
#define MDNS_MAX_SERVICES
Definition: mdns_opts.h:60
void pbuf_realloc(struct pbuf *p, u16_t new_len)
Definition: pbuf.c:402
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:224
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:727
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
Definition: pbuf.c:1227
err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1271
@ PBUF_RAM
Definition: pbuf.h:152
@ PBUF_TRANSPORT
Definition: pbuf.h:93
ip6_addr_t ip_addr_t
Definition: ip_addr.h:344
char hdr[14]
Definition: iptest.cpp:33
#define DNS_RRCLASS_IN
Definition: dns.h:76
#define SIZEOF_DNS_HDR
Definition: dns.h:116
#define DNS_RRTYPE_SRV
Definition: dns.h:72
#define DNS_RRTYPE_TXT
Definition: dns.h:70
#define DNS_RRTYPE_A
Definition: dns.h:55
#define DNS_FLAG1_RESPONSE
Definition: dns.h:84
#define DNS_RRTYPE_PTR
Definition: dns.h:66
#define DNS_RRTYPE_AAAA
Definition: dns.h:71
#define DNS_RRTYPE_ANY
Definition: dns.h:73
typedefPACK_STRUCT_END struct ip6_addr_packed ip6_addr_p_t
Definition: ip6.h:62
#define memset(x, y, z)
Definition: compat.h:39
char * name
Definition: compiler.c:66
Definition: dns.h:103
Definition: cookie.c:42
Definition: txthost.c:37
Definition: netif.h:269