fix unicast response port and timeout
authorTobias Waldvogel <tobias.waldvogel@gmail.com>
Wed, 11 Dec 2024 14:34:33 +0000 (15:34 +0100)
committerJohn Crispin <john@phrozen.org>
Wed, 11 Dec 2024 14:34:46 +0000 (15:34 +0100)
Responses to One-Shot Multicast DNS Queries (as in RFC 6762 5.1)
with CLASS_UNICAST set should be sent back to the port of the
client and not to 5353. In addition timeouts should be ignored.

Signed-off-by: Tobias Waldvogel <tobias.waldvogel@gmail.com>
dns.c
interface.c
service.c
service.h

diff --git a/dns.c b/dns.c
index f6f0be5cc1181eda18a29ddd586749cf096fa3d2..e849396e1276e25a051b36815c9bd73272f5e1a7 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -357,12 +357,13 @@ static int parse_answer(struct interface *iface, struct sockaddr *from,
 static void
 parse_question(struct interface *iface, struct sockaddr *from, char *name, struct dns_question *q)
 {
+       int is_unicast = (q->class & CLASS_UNICAST) != 0;
        struct sockaddr *to = NULL;
        struct hostname *h;
        char *host;
 
        /* TODO: Multicast if more than one quarter of TTL has passed */
-       if (q->class & CLASS_UNICAST) {
+       if (is_unicast) {
                to = from;
                if (interface_multicast(iface))
                        iface = interface_get(iface->name, iface->type | SOCKTYPE_BIT_UNICAST);
@@ -375,7 +376,7 @@ parse_question(struct interface *iface, struct sockaddr *from, char *name, struc
                if (!strcmp(name, mdns_hostname_local)) {
                        dns_reply_a(iface, to, announce_ttl, NULL);
                        dns_reply_a_additional(iface, to, announce_ttl);
-                       service_reply(iface, to, NULL, NULL, announce_ttl);
+                       service_reply(iface, to, NULL, NULL, announce_ttl, is_unicast);
                }
                break;
 
@@ -386,14 +387,14 @@ parse_question(struct interface *iface, struct sockaddr *from, char *name, struc
                        service_announce_services(iface, to, announce_ttl);
                } else {
                        if (name[0] == '_') {
-                               service_reply(iface, to, NULL, name, announce_ttl);
+                               service_reply(iface, to, NULL, name, announce_ttl, is_unicast);
                        } else {
                                /* First dot separates instance name from the rest */
                                char *dot = strchr(name, '.');
 
                                if (dot) {
                                        *dot = '\0';
-                                       service_reply(iface, to, name, dot + 1, announce_ttl);
+                                       service_reply(iface, to, name, dot + 1, announce_ttl, is_unicast);
                                        *dot = '.';
                                }
                        }
index ad25b39b984ad7d9b9e392da3db5a3f39bbcec89..944666f1b0a058c6cd924751f9b477a0bf17de2a 100644 (file)
@@ -84,6 +84,7 @@ interface_send_packet4(struct interface *iface, struct sockaddr_in *to, struct i
                        fprintf(stderr, "Ignoring IPv4 address for multicast interface\n");
        } else {
                a.sin_addr.s_addr = to->sin_addr.s_addr;
+               a.sin_port = to->sin_port;
        }
 
        return sendmsg(fd, &m, 0);
index 1f81031f8d5ee3b8e96b7abd0d9e36fd13578e60..9d3767b3f6b8d630326ea83a17269f8f813a0be5 100644 (file)
--- a/service.c
+++ b/service.c
@@ -144,7 +144,7 @@ service_reply_single(struct interface *iface, struct sockaddr *to, struct servic
 }
 
 void
-service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl)
+service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force)
 {
        struct service *s;
 
@@ -153,7 +153,7 @@ service_reply(struct interface *iface, struct sockaddr *to, const char *instance
                        continue;
                if (service_domain && strcmp(s->service, service_domain))
                        continue;
-               service_reply_single(iface, to, s, ttl, 0);
+               service_reply_single(iface, to, s, ttl, force);
        }
 }
 
index ea2a6ed287f96be63f20cb0f1f1dcbbc7b506a3b..6cae5bb2eeb242b29e5fef5d3fc5427e087d7771 100644 (file)
--- a/service.h
+++ b/service.h
@@ -41,7 +41,7 @@ extern struct vlist_tree announced_services;
 
 extern void service_init(int announce);
 extern void service_cleanup(void);
-extern void service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl);
+extern void service_reply(struct interface *iface, struct sockaddr *to, const char *instance, const char *service_domain, int ttl, int force);
 extern void service_announce_services(struct interface *iface, struct sockaddr *to, int ttl);
 extern void service_update(struct vlist_tree *tree, struct vlist_node *node_new, struct vlist_node *node_old);