mdns_responder.c
Go to the documentation of this file.
1 /**
2  * @file mdns_responder.c
3  * @brief mDNS responder (Multicast DNS)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL MDNS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "dns/dns_debug.h"
37 #include "mdns/mdns_responder.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Initialize settings with default values
48  * @param[out] settings Structure that contains mDNS responder settings
49  **/
50 
52 {
53  //Underlying network interface
54  settings->interface = NULL;
55 
56  //Number of announcement packets
58  //TTL resource record
59  settings->ttl = MDNS_DEFAULT_RR_TTL;
60  //FSM state change event
61  settings->stateChangeEvent = NULL;
62 }
63 
64 
65 /**
66  * @brief mDNS responder initialization
67  * @param[in] context Pointer to the mDNS responder context
68  * @param[in] settings mDNS responder specific settings
69  * @return Error code
70  **/
71 
73  const MdnsResponderSettings *settings)
74 {
75  NetInterface *interface;
76 
77  //Debug message
78  TRACE_INFO("Initializing mDNS responder...\r\n");
79 
80  //Ensure the parameters are valid
81  if(context == NULL || settings == NULL)
83 
84  //Invalid network interface?
85  if(settings->interface == NULL)
87 
88  //Point to the underlying network interface
89  interface = settings->interface;
90 
91  //Clear the mDNS responder context
92  osMemset(context, 0, sizeof(MdnsResponderContext));
93 
94  //Attach TCP/IP stack context
95  context->netContext = settings->interface->netContext;
96 
97  //Save user settings
98  context->interface = settings->interface;
99  context->numAnnouncements = settings->numAnnouncements;
100  context->ttl = settings->ttl;
101  context->stateChangeEvent = settings->stateChangeEvent;
102 
103  //mDNS responder is currently suspended
104  context->running = FALSE;
105  //Initialize state machine
106  context->state = MDNS_STATE_INIT;
107 
108  //Get exclusive access
109  netLock(context->netContext);
110  //Attach the mDNS responder context to the network interface
111  interface->mdnsResponderContext = context;
112  //Release exclusive access
113  netUnlock(context->netContext);
114 
115  //Successful initialization
116  return NO_ERROR;
117 }
118 
119 
120 /**
121  * @brief Start mDNS responder
122  * @param[in] context Pointer to the mDNS responder context
123  * @return Error code
124  **/
125 
127 {
128  //Make sure the mDNS responder context is valid
129  if(context == NULL)
131 
132  //Debug message
133  TRACE_INFO("Starting mDNS responder...\r\n");
134 
135  //Get exclusive access
136  netLock(context->netContext);
137 
138  //Start mDNS responder
139  context->running = TRUE;
140  //Initialize state machine
141  context->state = MDNS_STATE_INIT;
142 
143  //Release exclusive access
144  netUnlock(context->netContext);
145 
146  //Successful processing
147  return NO_ERROR;
148 }
149 
150 
151 /**
152  * @brief Stop mDNS responder
153  * @param[in] context Pointer to the mDNS responder context
154  * @return Error code
155  **/
156 
158 {
159  //Make sure the mDNS responder context is valid
160  if(context == NULL)
162 
163  //Debug message
164  TRACE_INFO("Stopping mDNS responder...\r\n");
165 
166  //Get exclusive access
167  netLock(context->netContext);
168 
169  //Suspend mDNS responder
170  context->running = FALSE;
171  //Reinitialize state machine
172  context->state = MDNS_STATE_INIT;
173 
174  //Release exclusive access
175  netUnlock(context->netContext);
176 
177  //Successful processing
178  return NO_ERROR;
179 }
180 
181 
182 /**
183  * @brief Retrieve current state
184  * @param[in] context Pointer to the mDNS responder context
185  * @return Current mDNS responder state
186  **/
187 
189 {
190  MdnsState state;
191 
192  //Get exclusive access
193  netLock(context->netContext);
194  //Get current state
195  state = context->state;
196  //Release exclusive access
197  netUnlock(context->netContext);
198 
199  //Return current state
200  return state;
201 }
202 
203 
204 /**
205  * @brief Set host name
206  * @param[in] context Pointer to the mDNS responder context
207  * @param[in] hostname NULL-terminated string that contains the host name
208  * @return Error code
209  **/
210 
212  const char_t *hostname)
213 {
214  //Check parameters
215  if(context == NULL || hostname == NULL)
217 
218  //Make sure the length of the host name is acceptable
220  return ERROR_INVALID_LENGTH;
221 
222  //Get exclusive access
223  netLock(context->netContext);
224 
225  //Check whether a host name is already assigned
226  if(context->hostname[0] != '\0')
227  {
228  //Check whether the link is up
229  if(context->interface->linkState)
230  {
231  //Send a goodbye packet
232  mdnsResponderSendGoodbye(context);
233  }
234  }
235 
236  //Set host name
237  osStrcpy(context->hostname, hostname);
238 
239  //Restart probing process (host name)
240  mdnsResponderStartProbing(context);
241 
242  //Release exclusive access
243  netUnlock(context->netContext);
244 
245  //Successful processing
246  return NO_ERROR;
247 }
248 
249 
250 /**
251  * @brief Restart probing process
252  * @param[in] context Pointer to the mDNS responder context
253  * @return Error code
254  **/
255 
257 {
258  uint_t i;
259  NetInterface *interface;
260 
261  //Check whether the mDNS responder has been properly instantiated
262  if(context == NULL)
264 
265  //Point to the underlying network interface
266  interface = context->interface;
267 
268  //Reset variables
269  context->ipv4AddrCount = 0;
270  context->ipv6AddrCount = 0;
271 
272 #if (IPV4_SUPPORT == ENABLED)
273  //Loop through the list of IPv4 addresses assigned to the interface
274  for(i = 0; i < IPV4_ADDR_LIST_SIZE; i++)
275  {
276  //Valid IPv4 address?
277  if(interface->ipv4Context.addrList[i].state == IPV4_ADDR_STATE_VALID)
278  {
279  MdnsIpv4AddrEntry *entry;
280 
281  //Point to the current entry
282  entry = &context->ipv4AddrList[i];
283 
284  //Format A resource record
285  entry->record.rtype = HTONS(DNS_RR_TYPE_A);
286  entry->record.rclass = HTONS(DNS_RR_CLASS_IN);
287  entry->record.ttl = htonl(MDNS_DEFAULT_RR_TTL);
288  entry->record.rdlength = HTONS(sizeof(Ipv4Addr));
289 
290  //Copy IPv4 address
291  ipv4CopyAddr(entry->record.rdata, &interface->ipv4Context.addrList[i].addr);
292 
293  //Generate domain name for reverse DNS lookup
294  dnsGenerateIpv4ReverseName(interface->ipv4Context.addrList[i].addr,
295  entry->reverseName);
296 
297  //The entry is valid
298  context->ipv4AddrList[i].valid = TRUE;
299 
300  //Increment the number of valid IPv4 addresses
301  context->ipv4AddrCount++;
302  }
303  else
304  {
305  //Invalidate the entry
306  context->ipv4AddrList[i].valid = FALSE;
307  }
308  }
309 #endif
310 
311 #if (IPV6_SUPPORT == ENABLED)
312  //Loop through the list of IPv6 addresses assigned to the interface
313  for(i = 0; i < IPV6_ADDR_LIST_SIZE; i++)
314  {
315  //Valid IPv6 address?
316  if(interface->ipv6Context.addrList[i].state == IPV6_ADDR_STATE_PREFERRED ||
317  interface->ipv6Context.addrList[i].state == IPV6_ADDR_STATE_DEPRECATED)
318  {
319  MdnsIpv6AddrEntry *entry;
320 
321  //Point to the current entry
322  entry = &context->ipv6AddrList[i];
323 
324  //Format AAAA resource record
325  entry->record.rtype = HTONS(DNS_RR_TYPE_AAAA);
326  entry->record.rclass = HTONS(DNS_RR_CLASS_IN);
327  entry->record.ttl = htonl(MDNS_DEFAULT_RR_TTL);
328  entry->record.rdlength = HTONS(sizeof(Ipv6Addr));
329 
330  //Copy IPv6 address
331  ipv6CopyAddr(entry->record.rdata, &interface->ipv6Context.addrList[i].addr);
332 
333  //Generate domain name for reverse DNS lookup
334  dnsGenerateIpv6ReverseName(&interface->ipv6Context.addrList[i].addr,
335  entry->reverseName);
336 
337  //The entry is valid
338  context->ipv6AddrList[i].valid = TRUE;
339 
340  //Increment the number of valid IPv6 addresses
341  context->ipv6AddrCount++;
342  }
343  else
344  {
345  //Invalidate the entry
346  context->ipv6AddrList[i].valid = FALSE;
347  }
348  }
349 #endif
350 
351  //Force mDNS responder to start probing again
352  context->state = MDNS_STATE_INIT;
353 
354 #if (DNS_SD_RESPONDER_SUPPORT == ENABLED)
355  //Restart probing process (service instance name)
356  dnsSdResponderStartProbing(interface->dnsSdResponderContext);
357 #endif
358 
359  //Successful processing
360  return NO_ERROR;
361 }
362 
363 
364 /**
365  * @brief mDNS responder timer handler
366  *
367  * This routine must be periodically called by the TCP/IP stack to
368  * manage mDNS operation
369  *
370  * @param[in] context Pointer to the mDNS responder context
371  **/
372 
374 {
375  systime_t time;
376  systime_t delay;
377  NetInterface *interface;
379 
380  //Make sure the mDNS responder has been properly instantiated
381  if(context == NULL)
382  return;
383 
384  //Point to the underlying network interface
385  interface = context->interface;
386 
387  //Get current time
388  time = osGetSystemTime();
389 
390  //Check current state
391  if(context->state == MDNS_STATE_INIT)
392  {
393  //Wait for the link to be up before starting mDNS responder
394  if(context->running && interface->linkState)
395  {
396  //Valid host name?
397  if(context->hostname[0] != '\0')
398  {
399  //Check whether a valid IPv4 or IPv6 address has been assigned
400  if(context->ipv4AddrCount > 0 || context->ipv6AddrCount > 0)
401  {
403  }
404  }
405  }
406  }
407  else if(context->state == MDNS_STATE_WAITING)
408  {
409  //Check current time
410  if(timeCompare(time, context->timestamp + MDNS_INIT_DELAY) >= 0)
411  {
412  //Initial random delay
413  delay = netGenerateRandRange(context->netContext, MDNS_RAND_DELAY_MIN,
415 
416  //Start probing
418  }
419  }
420  else if(context->state == MDNS_STATE_PROBING)
421  {
422  //Probing failed?
423  if(context->conflict && context->retransmitCount > 0)
424  {
425  //Programmatically change the host name
427 
428  //Probe again, and repeat as necessary until a unique name is found
431  }
432  //Tie-break lost?
433  else if(context->tieBreakLost && context->retransmitCount > 0)
434  {
435  //The host defers to the winning host by waiting one second, and
436  //then begins probing for this record again
439  }
440  else
441  {
442  //Check current time
443  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
444  {
445  //Probing is on-going?
446  if(context->retransmitCount < MDNS_PROBE_NUM)
447  {
448  //First probe?
449  if(context->retransmitCount == 0)
450  {
451  //Apparently conflicting mDNS responses received before the
452  //first probe packet is sent must be silently ignored
453  context->conflict = FALSE;
454  context->tieBreakLost = FALSE;
455  }
456 
457  //Send probe packet
458  mdnsResponderSendProbe(context);
459 
460  //Save the time at which the packet was sent
461  context->timestamp = time;
462  //Time interval between subsequent probe packets
463  context->timeout = MDNS_PROBE_DELAY;
464  //Increment retransmission counter
465  context->retransmitCount++;
466  }
467  //Probing is complete?
468  else
469  {
470  //The mDNS responder must send unsolicited mDNS responses
471  //containing all of its newly registered resource records
472  if(context->numAnnouncements > 0)
473  {
475  }
476  else
477  {
479  }
480  }
481  }
482  }
483  }
484  else if(context->state == MDNS_STATE_ANNOUNCING)
485  {
486  //Whenever a mDNS responder receives any mDNS response (solicited or
487  //otherwise) containing a conflicting resource record, the conflict
488  //must be resolved
489  if(context->conflict)
490  {
491  //Probe again, and repeat as necessary until a unique name is found
493  }
494  else
495  {
496  //Check current time
497  if(timeCompare(time, context->timestamp + context->timeout) >= 0)
498  {
499  //Send announcement packet
501 
502  //Save the time at which the packet was sent
503  context->timestamp = time;
504  //Increment retransmission counter
505  context->retransmitCount++;
506 
507  //First announcement packet?
508  if(context->retransmitCount == 1)
509  {
510  //The mDNS responder must send at least two unsolicited
511  //responses, one second apart
512  context->timeout = MDNS_ANNOUNCE_DELAY;
513  }
514  else
515  {
516  //To provide increased robustness against packet loss, a mDNS
517  //responder may send up to eight unsolicited responses, provided
518  //that the interval between unsolicited responses increases by
519  //at least a factor of two with every response sent
520  context->timeout *= 2;
521  }
522 
523  //Last announcement packet?
524  if(context->retransmitCount >= context->numAnnouncements)
525  {
526  //A mDNS responder must not send regular periodic announcements
528  }
529  }
530  }
531  }
532  else if(context->state == MDNS_STATE_IDLE)
533  {
534  //Whenever a mDNS responder receives any mDNS response (solicited or
535  //otherwise) containing a conflicting resource record, the conflict
536  //must be resolved
537  if(context->conflict)
538  {
539  //Probe again, and repeat as necessary until a unique name is found
541  }
542  }
543 
544 #if (IPV4_SUPPORT == ENABLED)
545  //Any response message pending to be sent?
546  if(context->ipv4Response.buffer != NULL)
547  {
548  //Check whether the time delay has elapsed
549  if(timeCompare(time, context->ipv4Response.timestamp +
550  context->ipv4Response.timeout) >= 0)
551  {
552 #if (DNS_SD_RESPONDER_SUPPORT == ENABLED)
553  //Generate additional records (DNS-SD)
555  &context->ipv4Response, FALSE);
556 #endif
557  //Generate additional records (mDNS)
559  &context->ipv4Response, FALSE);
560 
561  //Use mDNS IPv4 multicast address
562  destIpAddr.length = sizeof(Ipv4Addr);
564 
565  //Send mDNS response message
566  mdnsSendMessage(interface, &context->ipv4Response, &destIpAddr,
567  MDNS_PORT);
568 
569  //Free previously allocated memory
570  mdnsDeleteMessage(&context->ipv4Response);
571  }
572  }
573 #endif
574 
575 #if (IPV6_SUPPORT == ENABLED)
576  //Any response message pending to be sent?
577  if(context->ipv6Response.buffer != NULL)
578  {
579  //Check whether the time delay has elapsed
580  if(timeCompare(time, context->ipv6Response.timestamp +
581  context->ipv6Response.timeout) >= 0)
582  {
583 #if (DNS_SD_RESPONDER_SUPPORT == ENABLED)
584  //Generate additional records (DNS-SD)
586  &context->ipv6Response, FALSE);
587 #endif
588  //Generate additional records (mDNS)
590  &context->ipv6Response, FALSE);
591 
592  //Use mDNS IPv6 multicast address
593  destIpAddr.length = sizeof(Ipv6Addr);
595 
596  //Send mDNS response message
597  mdnsSendMessage(interface, &context->ipv6Response, &destIpAddr,
598  MDNS_PORT);
599 
600  //Free previously allocated memory
601  mdnsDeleteMessage(&context->ipv6Response);
602  }
603  }
604 #endif
605 }
606 
607 
608 /**
609  * @brief Callback function for link change event
610  * @param[in] context Pointer to the mDNS responder context
611  **/
612 
614 {
615  //Make sure the mDNS responder has been properly instantiated
616  if(context == NULL)
617  return;
618 
619 #if (IPV4_SUPPORT == ENABLED)
620  //Free any response message pending to be sent
621  mdnsDeleteMessage(&context->ipv4Response);
622 #endif
623 
624 #if (IPV6_SUPPORT == ENABLED)
625  //Free any response message pending to be sent
626  mdnsDeleteMessage(&context->ipv6Response);
627 #endif
628 
629  //Whenever a mDNS responder receives an indication of a link
630  //change event, it must perform probing and announcing
632 }
633 
634 
635 /**
636  * @brief Release mDNS responder context
637  * @param[in] context Pointer to the mDNS responder context
638  **/
639 
641 {
642  NetInterface *interface;
643 
644  //Make sure the mDNS responder context is valid
645  if(context != NULL)
646  {
647  //Get exclusive access
648  netLock(context->netContext);
649 
650  //Point to the underlying network interface
651  interface = context->interface;
652  //Detach the mDNS responder context from the network interface
653  interface->mdnsResponderContext = NULL;
654 
655  //Release exclusive access
656  netUnlock(context->netContext);
657 
658  //Clear mDNS responder context
659  osMemset(context, 0, sizeof(MdnsResponderContext));
660  }
661 }
662 
663 #endif
#define MdnsResponderContext
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
const Ipv6Addr MDNS_IPV6_MULTICAST_ADDR
Definition: mdns_common.c:59
DnsIpv4AddrResourceRecord record
A resource record.
#define MDNS_PROBE_NUM
IP network address.
Definition: ip.h:90
void mdnsResponderDeinit(MdnsResponderContext *context)
Release mDNS responder context.
#define TRUE
Definition: os_port.h:50
char_t reverseName[DNS_MAX_IPV6_REVERSE_NAME_LEN+1]
Reverse DNS lookup for IPv6.
Ipv6Addr
Definition: ipv6.h:280
#define MDNS_PROBE_DEFER_DELAY
@ DNS_RR_CLASS_IN
Internet.
Definition: dns_common.h:124
@ MDNS_STATE_IDLE
#define osStrlen(s)
Definition: os_port.h:168
mDNS responder settings
#define timeCompare(t1, t2)
Definition: os_port.h:40
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:322
error_t dnsSdResponderStartProbing(DnsSdResponderContext *context)
Restart probing process.
MdnsState
mDNS responder states
#define MDNS_RAND_DELAY_MIN
error_t mdnsResponderSetHostname(MdnsResponderContext *context, const char_t *hostname)
Set host name.
#define MDNS_PORT
Definition: mdns_common.h:53
error_t mdnsResponderSendGoodbye(MdnsResponderContext *context)
Send goodbye packet.
#define FALSE
Definition: os_port.h:46
#define MDNS_RAND_DELAY_MAX
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
error_t
Error codes.
Definition: error.h:43
void mdnsResponderChangeHostname(MdnsResponderContext *context)
Programmatically change the host name.
uint32_t ttl
TTL resource record.
error_t mdnsResponderInit(MdnsResponderContext *context, const MdnsResponderSettings *settings)
mDNS responder initialization
@ MDNS_STATE_PROBING
#define NetInterface
Definition: net.h:40
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ DNS_RR_TYPE_A
Host address.
Definition: dns_common.h:137
uint32_t netGenerateRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:983
#define MDNS_PROBE_DELAY
error_t mdnsResponderStart(MdnsResponderContext *context)
Start mDNS responder.
#define TRACE_INFO(...)
Definition: debug.h:105
#define IPV4_ADDR_LIST_SIZE
Definition: ipv4.h:80
@ MDNS_STATE_WAITING
MdnsState mdnsResponderGetState(MdnsResponderContext *context)
Retrieve current state.
void mdnsResponderTick(MdnsResponderContext *context)
mDNS responder timer handler
uint_t numAnnouncements
Number of announcement packets.
void dnsGenerateIpv4ReverseName(Ipv4Addr ipv4Addr, char_t *buffer)
Generate domain name for reverse DNS lookup (IPv4)
Definition: dns_common.c:479
@ MDNS_STATE_INIT
NetInterface * interface
Underlying network interface.
uint32_t systime_t
System time.
error_t mdnsResponderSendProbe(MdnsResponderContext *context)
Send probe packet.
#define MDNS_RESPONDER_MAX_HOSTNAME_LEN
void mdnsResponderGetDefaultSettings(MdnsResponderSettings *settings)
Initialize settings with default values.
char char_t
Definition: compiler_port.h:55
void dnsSdResponderGenerateAdditionalRecords(NetInterface *interface, MdnsMessage *response, bool_t legacyUnicast)
Additional record generation.
void mdnsResponderChangeState(MdnsResponderContext *context, MdnsState newState, systime_t delay)
Update FSM state.
#define MDNS_INIT_DELAY
uint32_t time
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:130
void mdnsResponderLinkChangeEvent(MdnsResponderContext *context)
Callback function for link change event.
void mdnsResponderGenerateAdditionalRecords(MdnsResponderContext *context, MdnsMessage *response, bool_t legacyUnicast)
Generate additional records.
Helper functions for DNS-SD responder.
void mdnsDeleteMessage(MdnsMessage *message)
release a mDNS message
Definition: mdns_common.c:434
@ MDNS_STATE_ANNOUNCING
#define HTONS(value)
Definition: cpu_endian.h:410
#define IPV6_ADDR_LIST_SIZE
Definition: ipv6.h:72
MdnsResponderStateChangeCallback stateChangeEvent
FSM state change event.
Helper functions for mDNS responder.
#define MDNS_PROBE_CONFLICT_DELAY
#define MDNS_ANNOUNCE_DELAY
IPv6 address entry.
error_t mdnsResponderStop(MdnsResponderContext *context)
Stop mDNS responder.
char_t hostname[]
Definition: tls.h:1728
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:166
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
char_t reverseName[DNS_MAX_IPV4_REVERSE_NAME_LEN+1]
Reverse DNS lookup for IPv4.
@ IPV4_ADDR_STATE_VALID
An address assigned to an interface whose use is unrestricted.
Definition: ipv4.h:228
IPv4 address entry.
void dnsGenerateIpv6ReverseName(const Ipv6Addr *ipv6Addr, char_t *buffer)
Generate domain name for reverse DNS lookup (IPv6)
Definition: dns_common.c:498
@ IPV6_ADDR_STATE_PREFERRED
An address assigned to an interface whose use is unrestricted.
Definition: ipv6.h:195
#define MDNS_IPV4_MULTICAST_ADDR
Definition: mdns_common.h:65
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
@ IPV6_ADDR_STATE_DEPRECATED
An address assigned to an interface whose use is discouraged.
Definition: ipv6.h:196
#define MDNS_DEFAULT_RR_TTL
Definition: mdns_common.h:47
@ DNS_RR_TYPE_AAAA
IPv6 address.
Definition: dns_common.h:147
Data logging functions for debugging purpose (DNS)
#define osStrcpy(s1, s2)
Definition: os_port.h:210
#define MDNS_ANNOUNCE_NUM
error_t mdnsResponderStartProbing(MdnsResponderContext *context)
Restart probing process.
error_t mdnsResponderSendAnnouncement(MdnsResponderContext *context)
Send announcement packet.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
DnsIpv6AddrResourceRecord record
AAAA resource record.
error_t mdnsSendMessage(NetInterface *interface, const MdnsMessage *message, const IpAddr *destIpAddr, uint_t destPort)
Send mDNS message.
Definition: mdns_common.c:458
mDNS responder (Multicast DNS)
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:80