diff options
| author | Tobias Waldvogel | 2024-12-11 14:34:33 +0000 |
|---|---|---|
| committer | John Crispin | 2024-12-11 14:34:46 +0000 |
| commit | 68af31143b1fb36922befeb3eb332b3cb4911960 (patch) | |
| tree | 081e534c123e7f355946933f4c4a34a1f9135dcb | |
| parent | a2b4979285a9d0d9c73c7649a5bbee9513f69bd9 (diff) | |
| download | mdnsd-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.c | 9 | ||||
| -rw-r--r-- | interface.c | 1 | ||||
| -rw-r--r-- | service.c | 4 | ||||
| -rw-r--r-- | service.h | 2 |
4 files changed, 9 insertions, 7 deletions
@@ -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); @@ -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); } } @@ -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); |