75#if LWIP_MDNS_RESPONDER
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"
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"
84#error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h"
87#error "If you want to use MDNS, you have to define LWIP_RAND=(random function) in your lwipopts.h"
102#define MDNS_IP_TTL 255
108static u8_t mdns_netif_client_id;
109static struct udp_pcb *mdns_pcb;
110#if MDNS_RESP_USENETIF_EXTCALLBACK
113static mdns_name_result_cb_t mdns_name_result_cb;
115#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id))
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)
123#define MDNS_RESPONSE_TC_DELAY_MAX 500
124#define MDNS_RESPONSE_TC_DELAY_MIN 400
125#define MDNS_RESPONSE_TC_DELAY_MS (LWIP_RAND() % (MDNS_RESPONSE_TC_DELAY_MAX - \
126 MDNS_RESPONSE_TC_DELAY_MIN) + MDNS_RESPONSE_TC_DELAY_MIN)
129#define MDNS_PROBE_COUNT 3
132#define MDNS_INITIAL_PROBE_DELAY_MS (LWIP_RAND() % MDNS_PROBE_DELAY_MS)
134#define MDNS_INITIAL_PROBE_DELAY_MS MDNS_PROBE_DELAY_MS
137#define MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS 1000
138#define MDNS_PROBE_TIEBREAK_MAX_ANSWERS 5
140#define MDNS_LEXICOGRAPHICAL_EQUAL 0
141#define MDNS_LEXICOGRAPHICAL_EARLIER 1
142#define MDNS_LEXICOGRAPHICAL_LATER 2
147#define MDNS_ANNOUNCE_DELAY_MS 1000
149#define MDNS_ANNOUNCE_COUNT 2
168 u16_t questions_left;
176 u16_t authoritative_left;
180 u16_t additional_left;
182 struct mdns_packet *next_answer;
184 struct mdns_packet *next_tc_question;
188static struct mdns_packet *pending_tc_questions;
194 struct mdns_rr_info
info;
199struct mdns_answer_list {
205 struct mdns_packet *pkt,
206 struct mdns_outmsg *reply);
207static void mdns_define_probe_rrs_to_send(
struct netif *
netif,
208 struct mdns_outmsg *outmsg);
209static void mdns_probe_and_announce(
void*
arg);
210static void mdns_conflict_save_time(
struct netif *
netif);
223 return NETIF_TO_HOST(
netif);
246check_host(
struct netif *
netif,
struct mdns_rr_info *rr,
u8_t *reverse_v6_reply)
250 struct mdns_domain mydomain;
264 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif,
i))) {
265 res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(
netif,
i));
266 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
267 replies |= REPLY_HOST_PTR_V6;
269 if (reverse_v6_reply) {
270 *reverse_v6_reply |= (1 <<
i);
277 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
278 res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(
netif));
279 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
280 replies |= REPLY_HOST_PTR_V4;
286 res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(
netif));
288 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
291 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif))
293 replies |= REPLY_HOST_A;
298 replies |= REPLY_HOST_AAAA;
313check_service(
struct mdns_service *service,
struct mdns_rr_info *rr)
317 struct mdns_domain mydomain;
324 res = mdns_build_dnssd_domain(&mydomain);
325 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
328 replies |= REPLY_SERVICE_TYPE_PTR;
331 res = mdns_build_service_domain(&mydomain, service, 0);
332 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
335 replies |= REPLY_SERVICE_NAME_PTR;
338 res = mdns_build_service_domain(&mydomain, service, 1);
339 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
342 replies |= REPLY_SERVICE_SRV;
345 replies |= REPLY_SERVICE_TXT;
360check_request(
struct mdns_request *
request,
struct mdns_rr_info *rr)
364 struct mdns_domain mydomain;
371 res = mdns_build_request_domain(&mydomain,
request, 0);
372 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) &&
375 replies |= REPLY_SERVICE_TYPE_PTR;
377 res = mdns_build_request_domain(&mydomain,
request, 1);
378 if (
res ==
ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) {
381 replies |= REPLY_SERVICE_SRV;
384 replies |= REPLY_SERVICE_TXT;
400mdns_read_rr_info(
struct mdns_packet *pkt,
struct mdns_rr_info *
info)
402 u16_t field16, copied;
403 pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &
info->domain);
404 if (pkt->parse_offset == MDNS_READNAME_ERROR) {
408 copied =
pbuf_copy_partial(pkt->pbuf, &field16,
sizeof(field16), pkt->parse_offset);
409 if (copied !=
sizeof(field16)) {
412 pkt->parse_offset += copied;
415 copied =
pbuf_copy_partial(pkt->pbuf, &field16,
sizeof(field16), pkt->parse_offset);
416 if (copied !=
sizeof(field16)) {
419 pkt->parse_offset += copied;
434mdns_read_question(
struct mdns_packet *pkt,
struct mdns_question *question)
437 if (pkt->pbuf->tot_len < pkt->parse_offset) {
441 if (pkt->questions_left) {
443 pkt->questions_left--;
445 memset(question, 0,
sizeof(
struct mdns_question));
446 res = mdns_read_rr_info(pkt, &question->info);
452 question->unicast = question->info.klass & 0x8000;
453 question->info.klass &= 0x7FFF;
470mdns_read_answer(
struct mdns_packet *pkt,
struct mdns_answer *answer,
u16_t *num_left)
473 if (pkt->questions_left) {
478 if (pkt->pbuf->tot_len < pkt->parse_offset) {
483 u16_t copied, field16;
488 memset(answer, 0,
sizeof(
struct mdns_answer));
489 res = mdns_read_rr_info(pkt, &answer->info);
495 answer->cache_flush = answer->info.klass & 0x8000;
496 answer->info.klass &= 0x7FFF;
499 if (copied !=
sizeof(ttl)) {
502 pkt->parse_offset += copied;
505 copied =
pbuf_copy_partial(pkt->pbuf, &field16,
sizeof(field16), pkt->parse_offset);
506 if (copied !=
sizeof(field16)) {
509 pkt->parse_offset += copied;
512 answer->rd_offset = pkt->parse_offset;
513 pkt->parse_offset += answer->rd_length;
528 struct mdns_outmsg announce;
530 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
532 memset(&announce, 0,
sizeof(announce));
533 announce.cache_flush = 1;
535 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
536 announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4;
541 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif,
i))) {
542 announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6;
543 announce.host_reverse_v6_replies |= (1 <<
i);
549 struct mdns_service *serv = mdns->services[
i];
551 announce.serv_replies[
i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR |
552 REPLY_SERVICE_SRV | REPLY_SERVICE_TXT;
557 SMEMCPY(&announce.dest_addr, destination,
sizeof(announce.dest_addr));
559 mdns_send_outpacket(&announce,
netif);
575mdns_lexicographical_comparison(
struct mdns_packet *pkt_a,
struct mdns_packet *pkt_b,
576 struct mdns_answer *ans_a,
struct mdns_answer *ans_b,
582 struct mdns_domain domain_a, domain_b;
585 if (ans_a->info.klass != ans_b->info.klass) {
586 if (ans_a->info.klass > ans_b->info.klass) {
587 *
result = MDNS_LEXICOGRAPHICAL_LATER;
591 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
596 if (ans_a->info.type != ans_b->info.type) {
597 if (ans_a->info.type > ans_b->info.type) {
598 *
result = MDNS_LEXICOGRAPHICAL_LATER;
602 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
620 len =
LWIP_MIN(ans_a->rd_length, ans_b->rd_length);
621 for (
i = 0;
i <
len;
i++) {
626 *
result = MDNS_LEXICOGRAPHICAL_LATER;
630 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
636 if (ans_a->rd_length != ans_b->rd_length) {
637 if (ans_a->rd_length > ans_b->rd_length) {
638 *
result = MDNS_LEXICOGRAPHICAL_LATER;
642 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
650 for (
i = 0;
i < 6;
i++) {
655 *
result = MDNS_LEXICOGRAPHICAL_LATER;
659 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
665 res = mdns_readname(pkt_a->pbuf, ans_a->rd_offset + 6, &domain_a);
666 if (
res == MDNS_READNAME_ERROR) {
669 res = mdns_readname(pkt_b->pbuf, ans_b->rd_offset + 6, &domain_b);
670 if (
res == MDNS_READNAME_ERROR) {
674 mdns_domain_debug_print(&domain_a);
677 mdns_domain_debug_print(&domain_b);
681 for (
i = 0;
i <
len;
i++) {
682 if (domain_a.name[
i] != domain_b.name[
i]) {
683 if (domain_a.name[
i] > domain_b.name[
i]) {
684 *
result = MDNS_LEXICOGRAPHICAL_LATER;
688 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
694 if (domain_a.length != domain_b.length) {
695 if (domain_a.length > domain_b.length) {
696 *
result = MDNS_LEXICOGRAPHICAL_LATER;
700 *
result = MDNS_LEXICOGRAPHICAL_EARLIER;
706 *
result = MDNS_LEXICOGRAPHICAL_EQUAL;
716mdns_init_answer_list(
struct mdns_answer_list *a_list)
720 for(
i = 0;
i < MDNS_PROBE_TIEBREAK_MAX_ANSWERS;
i++) {
721 a_list->offset[
i] = 0;
737mdns_push_answer_to_sorted_list(
struct mdns_answer_list *a_list,
738 struct mdns_packet *pkt,
740 struct mdns_answer *new_answer)
743 struct mdns_answer
a;
744 int pos = a_list->size;
747 u16_t num_left = pkt->authoritative;
748 u16_t parse_offset = pkt->parse_offset;
751 if ((a_list->size + 1) >= MDNS_PROBE_TIEBREAK_MAX_ANSWERS) {
755 for (
i = 0;
i < a_list->size;
i++) {
757 pkt->parse_offset = a_list->offset[
i];
758 res = mdns_read_answer(pkt, &
a, &num_left);
764 res = mdns_lexicographical_comparison(pkt, pkt, &
a, new_answer, &
result);
769 if (
result == MDNS_LEXICOGRAPHICAL_LATER) {
772 for (
j = (a_list->size + 1);
j>
i;
j--) {
773 a_list->offset[
j] = a_list->offset[
j-1];
779 a_list->offset[
pos] = new_offset;
782 pkt->parse_offset = parse_offset;
794mdns_is_answer_to_question(
struct mdns_question *
q,
struct mdns_answer *
a)
798 if (mdns_domain_eq(&
q->info.domain, &
a->info.domain)) {
812mdns_convert_out_to_in_pkt(
struct mdns_packet *inpkt,
struct mdns_outpacket *outpkt)
814 inpkt->pbuf = outpkt->pbuf;
817 inpkt->questions = inpkt->questions_left = outpkt->questions;
818 inpkt->answers = inpkt->answers_left = outpkt->answers;
819 inpkt->authoritative = inpkt->authoritative_left = outpkt->authoritative;
820 inpkt->additional = inpkt->additional_left = outpkt->additional;
830mdns_debug_print_answer(
struct mdns_packet *pkt,
struct mdns_answer *
a)
839 pos =
snprintf(
string,
sizeof(
string),
"Type = %2d, class = %1d, rdata = ",
a->info.type,
a->info.klass);
840 for (
i = 0; ((
i <
a->rd_length) && ((
pos + 4*
i) < 195)) ;
i++) {
857mdns_handle_probe_tiebreaking(
struct netif *
netif,
struct mdns_packet *pkt)
859 struct mdns_question pkt_q, my_q, q_dummy;
860 struct mdns_answer pkt_a, my_a;
861 struct mdns_outmsg myprobe_msg;
862 struct mdns_outpacket myprobe_outpkt;
863 struct mdns_packet myprobe_inpkt;
864 struct mdns_answer_list pkt_a_list, my_a_list;
865 u16_t save_parse_offset;
866 u16_t pkt_parse_offset, myprobe_parse_offset, myprobe_questions_left;
875 mdns_define_probe_rrs_to_send(
netif, &myprobe_msg);
876 memset(&myprobe_outpkt, 0,
sizeof(myprobe_outpkt));
877 memset(&myprobe_inpkt, 0,
sizeof(myprobe_inpkt));
878 res = mdns_create_outpacket(
netif, &myprobe_msg, &myprobe_outpkt);
882 mdns_convert_out_to_in_pkt(&myprobe_inpkt, &myprobe_outpkt);
885 while (myprobe_inpkt.questions_left) {
887 res = mdns_read_question(&myprobe_inpkt, &my_q);
893 pkt_parse_offset = pkt->parse_offset;
894 myprobe_parse_offset = myprobe_inpkt.parse_offset;
896 myprobe_questions_left = myprobe_inpkt.questions_left;
900 while (pkt->questions_left) {
902 res = mdns_read_question(pkt, &pkt_q);
914 if (mdns_domain_eq(&pkt_q.info.domain, &my_q.info.domain)) {
923 while (pkt->questions_left) {
924 res = mdns_read_question(pkt, &q_dummy);
930 while (myprobe_inpkt.questions_left) {
931 res = mdns_read_question(&myprobe_inpkt, &q_dummy);
939 mdns_init_answer_list(&my_a_list);
940 while(myprobe_inpkt.authoritative_left) {
941 save_parse_offset = myprobe_inpkt.parse_offset;
942 res = mdns_read_answer(&myprobe_inpkt, &my_a, &myprobe_inpkt.authoritative_left);
947 if (mdns_is_answer_to_question(&my_q, &my_a)) {
949 res = mdns_push_answer_to_sorted_list(&my_a_list, &myprobe_inpkt, save_parse_offset, &my_a);
958 mdns_init_answer_list(&pkt_a_list);
959 while(pkt->authoritative_left) {
960 save_parse_offset = pkt->parse_offset;
961 res = mdns_read_answer(pkt, &pkt_a, &pkt->authoritative_left);
966 if (mdns_is_answer_to_question(&my_q, &pkt_a)) {
968 res = mdns_push_answer_to_sorted_list(&pkt_a_list, pkt, save_parse_offset, &pkt_a);
977 myprobe_inpkt.authoritative_left = myprobe_inpkt.authoritative;
978 pkt->authoritative_left = pkt->authoritative;
986 for (
i = 0;
i <
min;
i++) {
988 myprobe_inpkt.parse_offset = my_a_list.offset[
i];
989 res = mdns_read_answer(&myprobe_inpkt, &my_a, &myprobe_inpkt.authoritative_left);
995 pkt->parse_offset = pkt_a_list.offset[
i];
996 res = mdns_read_answer(pkt, &pkt_a, &pkt->authoritative_left);
1002 mdns_debug_print_answer(pkt, &pkt_a);
1003 mdns_debug_print_answer(&myprobe_inpkt, &my_a);
1005 res = mdns_lexicographical_comparison(&myprobe_inpkt, pkt, &my_a, &pkt_a, &
result);
1010 if (
result == MDNS_LEXICOGRAPHICAL_LATER) {
1014 else if (
result == MDNS_LEXICOGRAPHICAL_EARLIER) {
1015 LWIP_DEBUGF(
MDNS_DEBUG, (
"mDNS: we loose, we are lexicographically earlier. 1s timeout started\n"));
1017 mdns_conflict_save_time(
netif);
1019 mdns_resp_restart_delay(
netif, MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS);
1028 if (my_a_list.size != pkt_a_list.size) {
1029 if (my_a_list.size > pkt_a_list.size) {
1036 mdns_conflict_save_time(
netif);
1038 mdns_resp_restart_delay(
netif, MDNS_PROBE_TIEBREAK_CONFLICT_DELAY_MS);
1051 pkt->parse_offset = pkt_parse_offset;
1052 myprobe_inpkt.parse_offset = myprobe_parse_offset;
1054 pkt->questions_left = pkt->questions;
1055 pkt->authoritative_left = pkt->authoritative;
1056 myprobe_inpkt.questions_left = myprobe_questions_left;
1057 myprobe_inpkt.authoritative_left = myprobe_inpkt.authoritative;
1061 if (myprobe_inpkt.pbuf !=
NULL) {
1075mdns_parse_pkt_questions(
struct netif *
netif,
struct mdns_packet *pkt,
1076 struct mdns_outmsg *reply)
1078 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
1079 struct mdns_service *service;
1083 while (pkt->questions_left) {
1084 struct mdns_question
q;
1086 res = mdns_read_question(pkt, &
q);
1093 mdns_domain_debug_print(&
q.info.domain);
1098 reply->unicast_reply_requested = 1;
1101 reply->host_replies |= check_host(
netif, &
q.info, &reply->host_reverse_v6_replies);
1104 service = mdns->services[
i];
1108 reply->serv_replies[
i] |= check_service(service, &
q.info);
1124mdns_parse_pkt_known_answers(
struct netif *
netif,
struct mdns_packet *pkt,
1125 struct mdns_outmsg *reply)
1127 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
1128 struct mdns_service *service;
1132 while (pkt->answers_left) {
1133 struct mdns_answer ans;
1136 u32_t rr_ttl = MDNS_TTL_120;
1138 res = mdns_read_answer(pkt, &ans, &pkt->answers_left);
1145 mdns_domain_debug_print(&ans.info.domain);
1155 match = reply->host_replies & check_host(
netif, &ans.info, &rev_v6);
1156 if (
match && (ans.ttl > (rr_ttl / 2))) {
1163 struct mdns_domain known_ans, my_ans;
1165 len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
1166 res = mdns_build_host_domain(&my_ans, mdns);
1167 if (
len != MDNS_READNAME_ERROR &&
res ==
ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1169 if (
match & REPLY_HOST_PTR_V4) {
1171 reply->host_replies &= ~REPLY_HOST_PTR_V4;
1175 if (
match & REPLY_HOST_PTR_V6) {
1177 reply->host_reverse_v6_replies &= ~rev_v6;
1178 if (reply->host_reverse_v6_replies == 0) {
1179 reply->host_replies &= ~REPLY_HOST_PTR_V6;
1184 }
else if (
match & REPLY_HOST_A) {
1186 if (ans.rd_length ==
sizeof(ip4_addr_t) &&
1187 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(
netif), ans.rd_length) == 0) {
1189 reply->host_replies &= ~REPLY_HOST_A;
1192 }
else if (
match & REPLY_HOST_AAAA) {
1196 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(
netif, 0), ans.rd_length) == 0) {
1198 reply->host_replies &= ~REPLY_HOST_AAAA;
1205 service = mdns->services[
i];
1209 match = reply->serv_replies[
i] & check_service(service, &ans.info);
1210 if (
match & REPLY_SERVICE_TYPE_PTR) {
1211 rr_ttl = MDNS_TTL_4500;
1213 if (
match && (ans.ttl > (rr_ttl / 2))) {
1220 struct mdns_domain known_ans, my_ans;
1222 len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans);
1223 if (
len != MDNS_READNAME_ERROR) {
1224 if (
match & REPLY_SERVICE_TYPE_PTR) {
1225 res = mdns_build_service_domain(&my_ans, service, 0);
1226 if (
res ==
ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1228 reply->serv_replies[
i] &= ~REPLY_SERVICE_TYPE_PTR;
1231 if (
match & REPLY_SERVICE_NAME_PTR) {
1232 res = mdns_build_service_domain(&my_ans, service, 1);
1233 if (
res ==
ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) {
1235 reply->serv_replies[
i] &= ~REPLY_SERVICE_NAME_PTR;
1239 }
else if (
match & REPLY_SERVICE_SRV) {
1242 struct mdns_domain known_ans, my_ans;
1243 read_pos = ans.rd_offset;
1247 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != SRV_PRIORITY) {
1253 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != SRV_WEIGHT) {
1259 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != service->port) {
1264 len = mdns_readname(pkt->pbuf, read_pos, &known_ans);
1265 mdns_build_host_domain(&my_ans, mdns);
1266 if (
len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) {
1270 reply->serv_replies[
i] &= ~REPLY_SERVICE_SRV;
1272 }
else if (
match & REPLY_SERVICE_TXT) {
1273 mdns_prepare_txtdata(service);
1274 if (service->txtdata.length == ans.rd_length &&
1275 pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
1277 reply->serv_replies[
i] &= ~REPLY_SERVICE_TXT;
1297mdns_parse_pkt_authoritative_answers(
struct netif *
netif,
struct mdns_packet *pkt,
1298 struct mdns_outmsg *reply)
1300 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
1301 struct mdns_service *service;
1305 while (pkt->authoritative_left) {
1306 struct mdns_answer ans;
1310 res = mdns_read_answer(pkt, &ans, &pkt->authoritative_left);
1317 mdns_domain_debug_print(&ans.info.domain);
1327 match = reply->host_replies & check_host(
netif, &ans.info, &rev_v6);
1329 reply->probe_query_recv = 1;
1334 service = mdns->services[
i];
1338 match = reply->serv_replies[
i] & check_service(service, &ans.info);
1341 reply->probe_query_recv = 1;
1357mdns_add_msg_to_delayed(
struct mdns_outmsg *
dest,
struct mdns_outmsg *
src)
1361 dest->host_questions |=
src->host_questions;
1362 dest->host_replies |=
src->host_replies;
1363 dest->host_reverse_v6_replies |=
src->host_reverse_v6_replies;
1365 dest->serv_questions[
i] |=
src->serv_questions[
i];
1366 dest->serv_replies[
i] |=
src->serv_replies[
i];
1370 dest->cache_flush =
src->cache_flush;
1372 dest->legacy_query =
src->legacy_query;
1387mdns_handle_question(
struct mdns_packet *pkt,
struct netif *
netif)
1389 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
1390 struct mdns_outmsg reply;
1392 u8_t shared_answer = 0;
1393 u8_t delay_response = 1;
1394 u8_t send_unicast = 0;
1395 u8_t listen_to_QU_bit = 0;
1399 if ((mdns->state == MDNS_STATE_PROBING) ||
1400 (mdns->state == MDNS_STATE_ANNOUNCE_WAIT)) {
1403 if ((pkt->questions > 0) && (pkt->answers == 0) &&
1404 (pkt->authoritative > 0) && (pkt->additional == 0)) {
1406 mdns_handle_probe_tiebreaking(
netif, pkt);
1410 if ((mdns->state != MDNS_STATE_COMPLETE) &&
1411 (mdns->state != MDNS_STATE_ANNOUNCING)) {
1417 memset(&reply, 0,
sizeof(
struct mdns_outmsg));
1420 res = mdns_parse_pkt_questions(
netif, pkt, &reply);
1425 res = mdns_parse_pkt_known_answers(
netif, pkt, &reply);
1429 if (pkt->next_answer) {
1431 struct mdns_packet *pkta = pkt->next_answer;
1433 res = mdns_parse_pkt_known_answers(
netif, pkta, &reply);
1437 pkta = pkta->next_answer;
1442 res = mdns_parse_pkt_authoritative_answers(
netif, pkt, &reply);
1447 if(pkt->additional) {
1449 (
"MDNS: Query contains additional answers -> they are discarded\n"));
1453 rrs_to_send = reply.host_replies | reply.host_questions;
1455 rrs_to_send |= reply.serv_replies[
i] | reply.serv_questions[
i];
1472 if (pkt->questions == 1) {
1474 reply.legacy_query = 1;
1475 reply.tx_id = pkt->tx_id;
1476 reply.cache_flush = 0;
1484 reply.cache_flush = 1;
1496 shared_answer |= (reply.serv_replies[
i] &
1497 (REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR));
1499 if ( ((pkt->questions == 1) && (!shared_answer) && !reply.probe_query_recv)
1500 || (reply.probe_query_recv && reply.unicast_reply_requested)) {
1504 if (
IP_IS_V6_VAL(pkt->source_addr) && reply.probe_query_recv
1505 && !reply.unicast_reply_requested && !mdns->ipv6.multicast_probe_timeout) {
1510 if (
IP_IS_V4_VAL(pkt->source_addr) && reply.probe_query_recv
1511 && !reply.unicast_reply_requested && !mdns->ipv4.multicast_probe_timeout) {
1527 if ((
IP_IS_V6_VAL(pkt->source_addr) && mdns->ipv6.multicast_timeout_25TTL)) {
1528 listen_to_QU_bit = 1;
1532 if ((
IP_IS_V4_VAL(pkt->source_addr) && mdns->ipv4.multicast_timeout_25TTL)) {
1533 listen_to_QU_bit = 1;
1536 if ( (reply.unicast_reply_requested && listen_to_QU_bit)
1537 || pkt->recv_unicast
1538 || reply.legacy_query
1539 || (reply.probe_query_recv && reply.unicast_reply_requested)) {
1542 LWIP_DEBUGF(
MDNS_DEBUG, (
"MDNS: send response via %s\n", (send_unicast ?
"unicast" :
"multicast")));
1545 if (delay_response) {
1552 if (
IP_IS_V6_VAL(pkt->source_addr) && !mdns->ipv6.unicast_msg_in_use) {
1554 SMEMCPY(&mdns->ipv6.delayed_msg_unicast.dest_addr, &pkt->source_addr,
sizeof(
ip_addr_t));
1555 mdns->ipv6.delayed_msg_unicast.dest_port = pkt->source_port;
1557 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_unicast, &reply);
1559 mdns_set_timeout(
netif, MDNS_RESPONSE_DELAY, mdns_send_unicast_msg_delayed_ipv6,
1560 &mdns->ipv6.unicast_msg_in_use);
1568 if (
IP_IS_V4_VAL(pkt->source_addr) && !mdns->ipv4.unicast_msg_in_use) {
1570 SMEMCPY(&mdns->ipv4.delayed_msg_unicast.dest_addr, &pkt->source_addr,
sizeof(
ip_addr_t));
1571 mdns->ipv4.delayed_msg_unicast.dest_port = pkt->source_port;
1573 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_unicast, &reply);
1575 mdns_set_timeout(
netif, MDNS_RESPONSE_DELAY, mdns_send_unicast_msg_delayed_ipv4,
1576 &mdns->ipv4.unicast_msg_in_use);
1590 if (
IP_IS_V6_VAL(pkt->source_addr) && !mdns->ipv6.multicast_timeout
1591 && !reply.probe_query_recv) {
1594 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_multicast, &reply);
1596 mdns_set_timeout(
netif, MDNS_RESPONSE_DELAY, mdns_send_multicast_msg_delayed_ipv6,
1597 &mdns->ipv6.multicast_msg_waiting);
1599 else if (
IP_IS_V6_VAL(pkt->source_addr) && reply.probe_query_recv) {
1602 mdns_add_msg_to_delayed(&mdns->ipv6.delayed_msg_multicast, &reply);
1604 mdns->ipv6.multicast_msg_waiting = 1;
1616 if (
IP_IS_V4_VAL(pkt->source_addr) && !mdns->ipv4.multicast_timeout
1617 && !reply.probe_query_recv) {
1620 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_multicast, &reply);
1622 mdns_set_timeout(
netif, MDNS_RESPONSE_DELAY, mdns_send_multicast_msg_delayed_ipv4,
1623 &mdns->ipv4.multicast_msg_waiting);
1625 else if (
IP_IS_V4_VAL(pkt->source_addr) && reply.probe_query_recv) {
1628 mdns_add_msg_to_delayed(&mdns->ipv4.delayed_msg_multicast, &reply);
1630 mdns->ipv4.multicast_msg_waiting = 1;
1639 reply.dest_port = pkt->source_port;
1641 res = mdns_send_outpacket(&reply,
netif);
1654 if (mdns->ipv6.multicast_timeout && !reply.probe_query_recv) {
1663 if (mdns->ipv4.multicast_timeout && !reply.probe_query_recv) {
1672 res = mdns_send_outpacket(&reply,
netif);
1680 mdns_start_multicast_timeouts_ipv6(
netif);
1685 mdns_start_multicast_timeouts_ipv4(
netif);
1703mdns_handle_tc_question(
void *
arg)
1705 struct mdns_packet *pkt = (
struct mdns_packet *)
arg;
1708 mdns_handle_question(pkt,
from);
1710 if (pending_tc_questions == pkt) {
1711 pending_tc_questions = pkt->next_tc_question;
1714 struct mdns_packet *prev = pending_tc_questions;
1715 while (prev && prev->next_tc_question != pkt) {
1716 prev = prev->next_tc_question;
1718 LWIP_ASSERT(
"pkt not found in pending_tc_questions list", prev !=
NULL);
1719 prev->next_tc_question = pkt->next_tc_question;
1722 while (pkt->next_answer) {
1723 struct mdns_packet *ans = pkt->next_answer;
1724 pkt->next_answer = ans->next_answer;
1741 struct mdns_host* mdns = NETIF_TO_HOST(
netif);
1747 mdns->num_conflicts++;
1748 mdns->conflict_time[mdns->index] =
sys_now();
1751 for(
i = 0;
i < MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT;
i++) {
1755 if (mdns->num_conflicts >= MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT) {
1757 index2 = (mdns->index + 1) % MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT;
1759 diff = mdns->conflict_time[mdns->index] - mdns->conflict_time[index2];
1761 if (diff < MDNS_PROBE_MAX_CONFLICTS_TIME_WINDOW) {
1763 mdns->rate_limit_activated = 1;
1767 mdns->index = (mdns->index + 1) % MDNS_PROBE_MAX_CONFLICTS_BEFORE_RATE_LIMIT;
1782 mdns_conflict_save_time(
netif);
1785 sys_untimeout(mdns_probe_and_announce,
netif);
1788 if (mdns_name_result_cb !=
NULL) {
1789 mdns_name_result_cb(
netif, MDNS_PROBING_CONFLICT,
slot);
1798static struct mdns_request *
1799mdns_lookup_request(
struct mdns_rr_info *rr)
1804 if ((mdns_requests[
i].result_fn !=
NULL) &&
1805 (check_request(&mdns_requests[
i], rr) != 0)) {
1806 return &mdns_requests[
i];
1822mdns_handle_response(
struct mdns_packet *pkt,
struct netif *
netif)
1824 struct mdns_host* mdns = NETIF_TO_HOST(
netif);
1825 u16_t total_answers_left;
1827 struct mdns_request *req =
NULL;
1838 while (pkt->questions_left) {
1839 struct mdns_question
q;
1841 res = mdns_read_question(pkt, &
q);
1848 req = mdns_lookup_request(&
q.info);
1853 total_answers_left = pkt->answers_left + pkt->authoritative_left + pkt->additional_left;
1854 while (total_answers_left) {
1855 struct mdns_answer ans;
1858 res = mdns_read_answer(pkt, &ans, &total_answers_left);
1865 mdns_domain_debug_print(&ans.info.domain);
1874 if (req && req->only_ptr) {
1876 if (
memcmp (req->service.name, ans.info.domain.name, req->service.length) != 0)
1881 req = mdns_lookup_request(&ans.info);
1883 if (req && req->result_fn) {
1886 int flags = (
first ? MDNS_SEARCH_RESULT_FIRST : 0) |
1887 (!total_answers_left ? MDNS_SEARCH_RESULT_LAST : 0);
1888 if (req->only_ptr) {
1891 flags = MDNS_SEARCH_RESULT_FIRST | MDNS_SEARCH_RESULT_LAST;
1903 struct mdns_domain dom;
1906 u16_t len = mdns_readname(pkt->pbuf, ans.rd_offset + off, &
data.dom);
1907 if (
len == MDNS_READNAME_ERROR) {
1909 data.dom.length = ans.rd_length - off;
1921 req->result_fn(&ans, (
const char *)&
data + off,
len,
flags, req->arg);
1924 req->result_fn(&ans, (
const char *)
p->payload +
offset, ans.rd_length,
flags, req->arg);
1933 if ((mdns->state == MDNS_STATE_PROBING) ||
1934 (mdns->state == MDNS_STATE_ANNOUNCE_WAIT)) {
1935 struct mdns_domain
domain;
1938 res = mdns_build_host_domain(&
domain, mdns);
1941 mdns_probe_conflict(
netif, 0);
1946 struct mdns_service* service = mdns->services[
i];
1950 res = mdns_build_service_domain(&
domain, service, 1);
1953 mdns_probe_conflict(
netif,
i + 1);
1968 else if ((mdns->state == MDNS_STATE_ANNOUNCING) ||
1969 (mdns->state == MDNS_STATE_COMPLETE)) {
1970 struct mdns_domain
domain;
1975 res = mdns_build_host_domain(&
domain, mdns);
1984 if (ans.rd_length ==
sizeof(ip4_addr_t) &&
1985 pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(
netif), ans.rd_length) == 0) {
1995 if (
pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(
netif,
i), ans.rd_length) == 0) {
1996 LWIP_DEBUGF(
MDNS_DEBUG, (
"mDNS: response equals our own iPv6 address record, num = %d -> no conflict\n",
i));
2006 struct mdns_service* service = mdns->services[
i];
2010 res = mdns_build_service_domain(&
domain, service, 1);
2020 struct mdns_domain srv_ans, my_ans;
2021 read_pos = ans.rd_offset;
2025 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != SRV_PRIORITY) {
2031 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != SRV_WEIGHT) {
2037 if (
len !=
sizeof(field16) ||
lwip_ntohs(field16) != service->port) {
2042 len = mdns_readname(pkt->pbuf, read_pos, &srv_ans);
2043 mdns_build_host_domain(&my_ans, mdns);
2044 if (
len == MDNS_READNAME_ERROR || !mdns_domain_eq(&srv_ans, &my_ans)) {
2051 mdns_prepare_txtdata(service);
2052 if (service->txtdata.length == ans.rd_length &&
2053 pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) {
2060 if (conflict != 0) {
2063 mdns_resp_restart(
netif);
2069 pkt->answers_left = 0;
2070 pkt->authoritative_left = 0;
2071 pkt->additional_left = 0;
2082 struct mdns_packet
packet;
2091 if (NETIF_TO_HOST(recv_netif) ==
NULL) {
2143 netif_ip4_addr(recv_netif),
2144 netif_ip4_netmask(recv_netif))){
2152 mdns_handle_response(&
packet, recv_netif);
2161 pkt->next_tc_question = pending_tc_questions;
2162 pending_tc_questions = pkt;
2164 sys_timeout(MDNS_RESPONSE_TC_DELAY_MS, mdns_handle_tc_question, pkt);
2168 else if (!
packet.questions &&
packet.answers && pending_tc_questions) {
2170 struct mdns_packet *
q = pending_tc_questions;
2172 if ((
packet.source_port ==
q->source_port) &&
2175 q =
q->next_tc_question;
2184 pkt->next_answer =
q->next_answer;
2185 q->next_answer = pkt;
2191 mdns_handle_question(&
packet, recv_netif);
2198#if LWIP_NETIF_EXT_STATUS_CALLBACK && MDNS_RESP_USENETIF_EXTCALLBACK
2210 if (
args->status_changed.state != 0) {
2211 mdns_resp_restart(
netif);
2216 if (
args->link_changed.state != 0) {
2217 mdns_resp_restart(
netif);
2223 mdns_resp_restart(
netif);
2229mdns_define_probe_rrs_to_send(
struct netif *
netif,
struct mdns_outmsg *outmsg)
2231 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
2234 memset(outmsg, 0,
sizeof(
struct mdns_outmsg));
2237 outmsg->host_questions = QUESTION_PROBE_HOST_ANY;
2240 struct mdns_service* service = mdns->services[
i];
2244 outmsg->serv_questions[
i] = QUESTION_PROBE_SERVICE_NAME_ANY;
2249 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
2250 outmsg->host_replies = REPLY_HOST_A;
2255 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif,
i))) {
2256 outmsg->host_replies |= REPLY_HOST_AAAA;
2262 struct mdns_service *serv = mdns->services[
i];
2264 outmsg->serv_replies[
i] = REPLY_SERVICE_SRV;
2272 struct mdns_outmsg outmsg;
2274 mdns_define_probe_rrs_to_send(
netif, &outmsg);
2278 SMEMCPY(&outmsg.dest_addr, destination,
sizeof(outmsg.dest_addr));
2279 return mdns_send_outpacket(&outmsg,
netif);
2286mdns_probe_and_announce(
void*
arg)
2289 struct mdns_host* mdns = NETIF_TO_HOST(
netif);
2290 u32_t announce_delay;
2293 switch (mdns->state) {
2294 case MDNS_STATE_OFF:
2295 case MDNS_STATE_PROBE_WAIT:
2296 case MDNS_STATE_PROBING:
2299 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif)) &&
2307 mdns->state = MDNS_STATE_PROBING;
2312 if (mdns->sent_num >= MDNS_PROBE_COUNT) {
2313 mdns->state = MDNS_STATE_ANNOUNCE_WAIT;
2317 if (mdns->sent_num && mdns->rate_limit_activated == 1) {
2319 sys_timeout(MDNS_PROBE_MAX_CONFLICTS_TIMEOUT, mdns_probe_and_announce,
netif);
2325 case MDNS_STATE_ANNOUNCE_WAIT:
2326 case MDNS_STATE_ANNOUNCING:
2327 if (mdns->sent_num == 0) {
2329 mdns->state = MDNS_STATE_ANNOUNCING;
2331 mdns->rate_limit_activated = 0;
2333 if (mdns_name_result_cb !=
NULL) {
2334 mdns_name_result_cb(
netif, MDNS_PROBING_SUCCESSFUL, 0);
2338 mdns_resp_announce(
netif);
2341 if (mdns->sent_num >= MDNS_ANNOUNCE_COUNT) {
2343 mdns->state = MDNS_STATE_COMPLETE;
2347 announce_delay = MDNS_ANNOUNCE_DELAY_MS * (1 << (mdns->sent_num - 1));
2348 sys_timeout(announce_delay, mdns_probe_and_announce,
netif);
2351 case MDNS_STATE_COMPLETE:
2371 struct mdns_host *mdns;
2378 mdns = (
struct mdns_host *)
mem_calloc(1,
sizeof(
struct mdns_host));
2381 netif_set_client_data(
netif, mdns_netif_client_id, mdns);
2388 SMEMCPY(&mdns->ipv4.delayed_msg_multicast.dest_addr, &v4group,
2394 SMEMCPY(&mdns->ipv6.delayed_msg_multicast.dest_addr, &v6group,
2400 res = igmp_joingroup_netif(
netif, ip_2_ip4(&v4group));
2412 mdns_resp_restart(
netif);
2418 netif_set_client_data(
netif, mdns_netif_client_id,
NULL);
2433 struct mdns_host *mdns;
2437 mdns = NETIF_TO_HOST(
netif);
2440 sys_untimeout(mdns_probe_and_announce,
netif);
2443 struct mdns_service *service = mdns->services[
i];
2451 igmp_leavegroup_netif(
netif, ip_2_ip4(&v4group));
2458 netif_set_client_data(
netif, mdns_netif_client_id,
NULL);
2474 struct mdns_host *mdns;
2480 LWIP_ERROR(
"mdns_resp_rename_netif: Hostname too long", (
len <= MDNS_LABEL_MAXLEN),
return ERR_VAL);
2481 mdns = NETIF_TO_HOST(
netif);
2485 mdns->name[
len] =
'\0';
2519mdns_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)
2522 struct mdns_service *srv;
2523 struct mdns_host *mdns;
2527 mdns = NETIF_TO_HOST(
netif);
2531 LWIP_ERROR(
"mdns_resp_add_service: Service too long", (
strlen(service) <= MDNS_LABEL_MAXLEN),
return ERR_VAL);
2532 LWIP_ERROR(
"mdns_resp_add_service: Bad proto (need TCP or UDP)", (
proto == DNSSD_PROTO_TCP ||
proto == DNSSD_PROTO_UDP),
return ERR_VAL);
2535 if (mdns->services[
slot] ==
NULL) {
2541 srv = (
struct mdns_service *)
mem_calloc(1,
sizeof(
struct mdns_service));
2546 srv->txt_fn = txt_fn;
2547 srv->txt_userdata = txt_data;
2551 mdns->services[
slot] = srv;
2553 mdns_resp_restart(
netif);
2568 struct mdns_host *mdns;
2569 struct mdns_service *srv;
2571 mdns = NETIF_TO_HOST(
netif);
2576 srv = mdns->services[
slot];
2593 struct mdns_service *srv;
2594 struct mdns_host *mdns;
2600 mdns = NETIF_TO_HOST(
netif);
2602 LWIP_ERROR(
"mdns_resp_rename_service: Name too long", (
len <= MDNS_LABEL_MAXLEN),
return ERR_VAL);
2606 srv = mdns->services[
slot];
2609 srv->name[
len] =
'\0';
2626mdns_resp_add_service_txtitem(
struct mdns_service *service,
const char *txt,
u8_t txt_len)
2629 LWIP_ASSERT(
"mdns_resp_add_service_txtitem: service != NULL", service);
2632 return mdns_domain_add_label(&service->txtdata, txt, txt_len);
2642mdns_search_stop(
u8_t request_id)
2644 struct mdns_request *req;
2646 req = &mdns_requests[request_id];
2647 if (req && req->result_fn) {
2648 req->result_fn =
NULL;
2667mdns_search_service(
const char *
name,
const char *service,
enum mdns_sd_proto
proto,
2668 struct netif *
netif, search_result_fn_t result_fn,
void *
arg,
2672 struct mdns_request *req;
2677 LWIP_ERROR(
"mdns_search_service: Bad reqid pointer", request_id,
return ERR_VAL);
2678 LWIP_ERROR(
"mdns_search_service: Bad proto (need TCP or UDP)", (
proto == DNSSD_PROTO_TCP ||
proto == DNSSD_PROTO_UDP),
return ERR_VAL);
2680 if (mdns_requests[
slot].result_fn ==
NULL) {
2689 req = &mdns_requests[
slot];
2690 memset(req, 0,
sizeof(
struct mdns_request));
2691 req->result_fn = result_fn;
2695 if (
proto == DNSSD_PROTO_UDP &&
strcmp(service,
"_services._dns-sd") == 0) {
2698 mdns_domain_add_string(&req->service, service);
2706 mdns_send_request(req,
netif, &v6group);
2709 mdns_send_request(req,
netif, &v4group);
2723 struct mdns_host* mdns;
2727 mdns = NETIF_TO_HOST(
netif);
2734 if (mdns->state >= MDNS_STATE_ANNOUNCING) {
2737 mdns_announce(
netif, &v6group);
2738 mdns_start_multicast_timeouts_ipv6(
netif);
2741 if (!ip4_addr_isany_val(*netif_ip4_addr(
netif))) {
2742 mdns_announce(
netif, &v4group);
2743 mdns_start_multicast_timeouts_ipv4(
netif);
2752mdns_resp_register_name_result_cb(mdns_name_result_cb_t
cb)
2754 mdns_name_result_cb =
cb;
2767 struct mdns_host* mdns;
2771 mdns = NETIF_TO_HOST(
netif);
2776 sys_untimeout(mdns_probe_and_announce,
netif);
2779 mdns->state = MDNS_STATE_PROBE_WAIT;
2785 if (mdns->rate_limit_activated == 1) {
2786 sys_timeout(MDNS_PROBE_MAX_CONFLICTS_TIMEOUT, mdns_probe_and_announce,
netif);
2790 sys_timeout(delay, mdns_probe_and_announce,
netif);
2803 mdns_resp_restart_delay(
netif, MDNS_INITIAL_PROBE_DELAY_MS);
2817 memset(mdns_requests, 0,
sizeof(mdns_requests));
2822#if LWIP_MULTICAST_TX_OPTIONS
2823 udp_set_multicast_ttl(mdns_pcb, MDNS_IP_TTL);
2825 mdns_pcb->ttl = MDNS_IP_TTL;
2830 udp_recv(mdns_pcb, mdns_recv,
NULL);
2832 mdns_netif_client_id = netif_alloc_client_data_id();
2834#if MDNS_RESP_USENETIF_EXTCALLBACK
2848 struct mdns_host *mdns = NETIF_TO_HOST(
netif);
2849 struct mdns_service *
s;
2851 s = mdns->services[
slot];
2852 return s ?
s->txt_userdata :
NULL;
int strcmp(const char *String1, const char *String2)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
ACPI_SIZE strlen(const char *String)
#define mem_free(ptr, bsize)
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
static void cleanup(void)
void * mem_calloc(mem_size_t count, mem_size_t size)
#define LWIP_DEBUGF(debug, message)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
#define ip_current_src_addr()
#define ip_current_dest_addr()
#define ip_current_input_netif()
void dealloc(int i, int no_throw)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble GLdouble q
GLboolean GLenum GLenum GLvoid * values
GLenum const GLvoid * addr
GLboolean GLboolean GLboolean GLboolean a
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
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 GLint GLint j
#define LWIP_UNUSED_ARG(x)
#define LWIP_IPV6_NUM_ADDRESSES
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
#define MDNS_MAX_REQUESTS
#define MDNS_PROBE_DELAY_MS
#define MDNS_MAX_SERVICES
#define MDNS_MAX_STORED_PKTS
#define LWIP_MEMPOOL_DECLARE(name, num, size, desc)
#define LWIP_MEMPOOL_ALLOC(name)
#define LWIP_MEMPOOL_INIT(name)
#define LWIP_MEMPOOL_FREE(name, x)
struct netif * netif_get_by_index(u8_t idx)
u16_t pbuf_memcmp(const struct pbuf *p, u16_t offset, const void *s2, u16_t n)
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
u8_t pbuf_free(struct pbuf *p)
struct pbuf * pbuf_skip(struct pbuf *in, u16_t in_offset, u16_t *out_offset)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define IP_IS_V6_VAL(ipaddr)
#define ip_addr_eq(addr1, addr2)
#define ip_addr_zoneless_eq(addr1, addr2)
#define IP_IS_V4_VAL(ipaddr)
#define MEMCPY(DST, SRC, BYTES)
#define memcpy(s1, s2, n)
static HMODULE MODULEINFO DWORD cb
#define LWIP_NSC_IPV6_ADDR_STATE_CHANGED
#define LWIP_NSC_IPV4_GATEWAY_CHANGED
#define LWIP_NSC_IPV4_SETTINGS_CHANGED
#define LWIP_NSC_LINK_CHANGED
#define NETIF_DECLARE_EXT_CALLBACK(name)
#define LWIP_NSC_STATUS_CHANGED
#define netif_add_ext_callback(callback, fn)
#define LWIP_NSC_IPV6_SET
#define LWIP_NSC_IPV4_NETMASK_CHANGED
#define LWIP_NSC_IPV4_ADDRESS_CHANGED
#define DNS_MQUERY_IPV4_GROUP_INIT
#define DNS_HDR_GET_OPCODE(hdr)
#define DNS_FLAG1_RESPONSE
#define DNS_FLAG1_AUTHORATIVE
#define DNS_MQUERY_IPV6_GROUP_INIT
typedefPACK_STRUCT_END struct ip6_addr_packed ip6_addr_p_t