This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
The following commit(s) were added to refs/heads/master by this push:
new c51180d78 examples/mdnsd: Create an event-based starter for mDNS daemon
c51180d78 is described below
commit c51180d780bc86c6a69263abf2c408093cb077fa
Author: Tiago Medicci <[email protected]>
AuthorDate: Thu Jun 11 09:34:54 2026 -0300
examples/mdnsd: Create an event-based starter for mDNS daemon
Start the mDNS daemon based on the event of getting a new IP
address for any of the system's network interfaces. This allows
DHCP client to trigger the mDNS daemon after getting a new IP
address, for instance.
Signed-off-by: Tiago Medicci <[email protected]>
---
examples/mdnsd/Makefile | 4 +-
examples/mdnsd/mdnsd_event.c | 244 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 246 insertions(+), 2 deletions(-)
diff --git a/examples/mdnsd/Makefile b/examples/mdnsd/Makefile
index 316e6d817..5dc84bd13 100644
--- a/examples/mdnsd/Makefile
+++ b/examples/mdnsd/Makefile
@@ -26,11 +26,11 @@ include $(APPDIR)/Make.defs
CSRCS = mdnsd_daemon.c
-MAINSRC = mdnsd_start.c mdnsd_stop.c
+MAINSRC = mdnsd_start.c mdnsd_stop.c mdnsd_event.c
# MDNSD built-in application info
-PROGNAME = mdnsd_start mdnsd_stop
+PROGNAME = mdnsd_start mdnsd_stop mdnsd_event
PRIORITY = SCHED_PRIORITY_DEFAULT
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
MODULE = $(CONFIG_EXAMPLES_MDNSD)
diff --git a/examples/mdnsd/mdnsd_event.c b/examples/mdnsd/mdnsd_event.c
new file mode 100644
index 000000000..432042372
--- /dev/null
+++ b/examples/mdnsd/mdnsd_event.c
@@ -0,0 +1,244 @@
+/****************************************************************************
+ * apps/examples/mdnsd/mdnsd_event.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netpacket/if_addr.h>
+#include <netpacket/netlink.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "netutils/mdnsd.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MDNSD_EVENT_BUFSIZE 512
+#define MDNSD_EVENT_SETTLE_MS 500
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mdnsd_event_has_ipv4addr
+ *
+ * Description:
+ * Check whether any network interface already has a non-zero IPv4
+ * address. Uses SIOCGIFCONF to enumerate interfaces.
+ *
+ * Returned Value:
+ * true if at least one interface has a non-zero IPv4 address,
+ * false otherwise.
+ *
+ ****************************************************************************/
+
+static bool mdnsd_event_has_ipv4addr(void)
+{
+ struct ifconf ifc;
+ char buf[sizeof(struct ifreq) * 4];
+ int sd;
+ int i;
+
+ sd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sd < 0)
+ {
+ return false;
+ }
+
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(sd, SIOCGIFCONF, &ifc) < 0)
+ {
+ close(sd);
+ return false;
+ }
+
+ close(sd);
+
+ for (i = 0; i < ifc.ifc_len; i += sizeof(struct ifreq))
+ {
+ FAR struct ifreq *ifr = (FAR struct ifreq *)&buf[i];
+ FAR struct sockaddr_in *sin;
+
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ {
+ continue;
+ }
+
+ sin = (FAR struct sockaddr_in *)&ifr->ifr_addr;
+ if (sin->sin_addr.s_addr != INADDR_ANY &&
+ sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/****************************************************************************
+ * Name: mdnsd_event_is_newaddr
+ *
+ * Description:
+ * Checks whether the given Netlink message header represents a new
+ * IPv4 or IPv6 address event (RTM_NEWADDR).
+ *
+ * Input Parameters:
+ * hdr - Pointer to the Netlink message header to inspect.
+ *
+ * Returned Value:
+ * true if the message is a new IPv4 or IPv6 address notification,
+ * false otherwise.
+ *
+ ****************************************************************************/
+
+static bool mdnsd_event_is_newaddr(FAR struct nlmsghdr *hdr)
+{
+ FAR struct ifaddrmsg *addr;
+
+ if (hdr->nlmsg_type != RTM_NEWADDR)
+ {
+ return false;
+ }
+
+ if (hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
+ {
+ return false;
+ }
+
+ addr = (FAR struct ifaddrmsg *)NLMSG_DATA(hdr);
+ return addr->ifa_family == AF_INET || addr->ifa_family == AF_INET6;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: main
+ *
+ * Description:
+ * Entry point for the mdnsd_event application. Listens for Netlink
+ * address events and starts the mDNS daemon when an IP address is
+ * assigned to a network interface.
+ *
+ * Input Parameters:
+ * argc - Number of command-line arguments.
+ * argv - Array of command-line argument strings.
+ *
+ * Returned Value:
+ * EXIT_SUCCESS on success, EXIT_FAILURE on error.
+ *
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+#ifdef CONFIG_NETLINK_ROUTE
+ struct sockaddr_nl addr;
+ uint8_t buffer[MDNSD_EVENT_BUFSIZE];
+ int sd;
+ int ret;
+
+ /* If an interface already has an IP (DHCP finished before we started),
+ * skip the netlink wait and start mDNS right away.
+ */
+
+ if (mdnsd_event_has_ipv4addr())
+ {
+ printf("mdnsd_event: address already set, starting mDNS\n");
+ usleep(MDNSD_EVENT_SETTLE_MS * 1000);
+ ret = mdnsd_start(CONFIG_EXAMPLES_MDNS_SERVICE,
+ CONFIG_EXAMPLES_MDNS_SERVICE_PORT);
+ return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+
+ sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (sd < 0)
+ {
+ fprintf(stderr, "mdnsd_event: socket failed: %d\n", errno);
+ return EXIT_FAILURE;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.nl_family = AF_NETLINK;
+ addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;
+
+ ret = bind(sd, (FAR struct sockaddr *)&addr, sizeof(addr));
+ if (ret < 0)
+ {
+ fprintf(stderr, "mdnsd_event: bind failed: %d\n", errno);
+ close(sd);
+ return EXIT_FAILURE;
+ }
+
+ printf("mdnsd_event: waiting for network address event\n");
+
+ for (; ; )
+ {
+ FAR struct nlmsghdr *hdr;
+ ssize_t nread;
+ int remaining;
+
+ nread = recv(sd, buffer, sizeof(buffer), 0);
+ if (nread < 0)
+ {
+ fprintf(stderr, "mdnsd_event: recv failed: %d\n", errno);
+ close(sd);
+ return EXIT_FAILURE;
+ }
+
+ remaining = nread;
+ for (hdr = (FAR struct nlmsghdr *)buffer;
+ NLMSG_OK(hdr, remaining);
+ hdr = NLMSG_NEXT(hdr, remaining))
+ {
+ if (mdnsd_event_is_newaddr(hdr))
+ {
+ printf("mdnsd_event: address set, starting mDNS\n");
+ usleep(MDNSD_EVENT_SETTLE_MS * 1000);
+ ret = mdnsd_start(CONFIG_EXAMPLES_MDNS_SERVICE,
+ CONFIG_EXAMPLES_MDNS_SERVICE_PORT);
+ close(sd);
+ return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+ }
+ }
+#else
+ fprintf(stderr, "mdnsd_event: CONFIG_NETLINK_ROUTE is required\n");
+ return EXIT_FAILURE;
+#endif
+}