summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Waldvogel2024-12-11 14:34:33 +0000
committerJohn Crispin2024-12-11 14:34:46 +0000
commit68af31143b1fb36922befeb3eb332b3cb4911960 (patch)
tree081e534c123e7f355946933f4c4a34a1f9135dcb
parenta2b4979285a9d0d9c73c7649a5bbee9513f69bd9 (diff)
downloadmdnsd-68af31143b1fb36922befeb3eb332b3cb4911960.tar.gz
fix unicast response port and timeout
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>
-rw-r--r--dns.c9
-rw-r--r--interface.c1
-rw-r--r--service.c4
-rw-r--r--service.h2
4 files changed, 9 insertions, 7 deletions
diff --git a/dns.c b/dns.c
index f6f0be5..e849396 100644
--- 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 = '.';
}
}
diff --git a/interface.c b/interface.c
index ad25b39..944666f 100644
--- a/interface.c
+++ b/interface.c
@@ -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);
diff --git a/service.c b/service.c
index 1f81031..9d3767b 100644
--- 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);
}
}
diff --git a/service.h b/service.h
index ea2a6ed..6cae5bb 100644
--- 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);