For each protocol (IPv4 and IPv6) we have two interfaces (sockets): one
for unicast and one for multicast. If we noticed CLASS_UNICAST in the
multicast query we were switching to unicast interface for sending
reply.
The problem was not passing destination IP address. It was resulting in
sending packet to multicast IP using unicast interface. As we don't
set IP_MULTICAST_TTL / IPV6_MULTICAST_HOPS for unicast ones TTL was 1
and packets were ignored.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
case STATE_ANNOUNCE:
dns_reply_a(iface, NULL, announce_ttl);
case STATE_ANNOUNCE:
dns_reply_a(iface, NULL, announce_ttl);
- service_announce_services(iface, announce_ttl);
+ service_announce_services(iface, NULL, announce_ttl);
uloop_timeout_set(timeout, announce_ttl * 800);
break;
}
uloop_timeout_set(timeout, announce_ttl * 800);
break;
}
-parse_question(struct interface *iface, char *name, struct dns_question *q)
+parse_question(struct interface *iface, struct sockaddr *from, char *name, struct dns_question *q)
- if ((q->class & CLASS_UNICAST) && iface->multicast)
+ /* TODO: Multicast if more than one quarter of TTL has passed */
+ if ((q->class & CLASS_UNICAST) && iface->multicast) {
+ to = from;
+ } else {
+ to = NULL;
+ }
DBG(1, "Q -> %s %s\n", dns_type_string(q->type), name);
switch (q->type) {
case TYPE_ANY:
if (!strcmp(name, mdns_hostname_local)) {
DBG(1, "Q -> %s %s\n", dns_type_string(q->type), name);
switch (q->type) {
case TYPE_ANY:
if (!strcmp(name, mdns_hostname_local)) {
- service_reply(iface, NULL, announce_ttl);
- dns_reply_a(iface, NULL, announce_ttl);
+ dns_reply_a(iface, to, announce_ttl);
+ service_reply(iface, to, NULL, announce_ttl);
}
break;
case TYPE_PTR:
if (!strcmp(name, sdudp)) {
}
break;
case TYPE_PTR:
if (!strcmp(name, sdudp)) {
- service_announce_services(iface, announce_ttl);
+ service_announce_services(iface, to, announce_ttl);
} else {
/* First dot separates instance name from the rest */
char *dot = strchr(name, '.');
} else {
/* First dot separates instance name from the rest */
char *dot = strchr(name, '.');
/* Make sure it's query for the instance name we use */
if (len && len == strlen(mdns_hostname) &&
!strncmp(name, mdns_hostname, len))
/* Make sure it's query for the instance name we use */
if (len && len == strlen(mdns_hostname) &&
!strncmp(name, mdns_hostname, len))
- service_reply(iface, dot + 1, announce_ttl);
+ service_reply(iface, to, dot + 1, announce_ttl);
if (host)
*host = '\0';
if (!strcmp(mdns_hostname, name))
if (host)
*host = '\0';
if (!strcmp(mdns_hostname, name))
- dns_reply_a(iface, NULL, announce_ttl);
+ dns_reply_a(iface, to, announce_ttl);
}
if (!(h->flags & FLAG_RESPONSE))
}
if (!(h->flags & FLAG_RESPONSE))
- parse_question(iface, name, q);
+ parse_question(iface, s, name, q);
}
if (!(h->flags & FLAG_RESPONSE))
}
if (!(h->flags & FLAG_RESPONSE))
vlist_for_each_element(&interfaces, iface, node)
if (iface->fd.fd > 0 && iface->multicast) {
dns_reply_a(iface, NULL, 0);
vlist_for_each_element(&interfaces, iface, node)
if (iface->fd.fd > 0 && iface->multicast) {
dns_reply_a(iface, NULL, 0);
- service_announce_services(iface, 0);
+ service_announce_services(iface, NULL, 0);
}
vlist_for_each_element(&interfaces, iface, node)
interface_close(iface);
}
vlist_for_each_element(&interfaces, iface, node)
interface_close(iface);
-service_reply_single(struct interface *iface, struct service *s, int ttl, int force)
+service_reply_single(struct interface *iface, struct sockaddr *to, struct service *s, int ttl, int force)
{
const char *host = service_name(s->service);
char *service = strstr(host, "._");
{
const char *host = service_name(s->service);
char *service = strstr(host, "._");
dns_init_answer();
service_add_ptr(service_name(s->service), ttl);
dns_init_answer();
service_add_ptr(service_name(s->service), ttl);
- dns_send_answer(iface, NULL, service);
+ dns_send_answer(iface, to, service);
dns_init_answer();
service_add_srv(s, ttl);
if (s->txt && s->txt_len)
dns_add_answer(TYPE_TXT, (uint8_t *) s->txt, s->txt_len, ttl);
dns_init_answer();
service_add_srv(s, ttl);
if (s->txt && s->txt_len)
dns_add_answer(TYPE_TXT, (uint8_t *) s->txt, s->txt_len, ttl);
- dns_send_answer(iface, NULL, host);
+ dns_send_answer(iface, to, host);
-service_reply(struct interface *iface, const char *match, int ttl)
+service_reply(struct interface *iface, struct sockaddr *to, const char *match, int ttl)
{
struct service *s;
vlist_for_each_element(&services, s, node) {
if (!match || !strcmp(s->service, match))
{
struct service *s;
vlist_for_each_element(&services, s, node) {
if (!match || !strcmp(s->service, match))
- service_reply_single(iface, s, ttl, 0);
+ service_reply_single(iface, to, s, ttl, 0);
-service_announce_services(struct interface *iface, int ttl)
+service_announce_services(struct interface *iface, struct sockaddr *to, int ttl)
if (ttl) {
dns_init_answer();
service_add_ptr(s->service, ttl);
if (ttl) {
dns_init_answer();
service_add_ptr(s->service, ttl);
- dns_send_answer(iface, NULL, sdudp);
+ dns_send_answer(iface, to, sdudp);
- service_reply_single(iface, s, ttl, 0);
+ service_reply_single(iface, to, s, ttl, 0);
if (service_init_announce)
vlist_for_each_element(&interfaces, iface, node) {
s->t = 0;
if (service_init_announce)
vlist_for_each_element(&interfaces, iface, node) {
s->t = 0;
- service_reply_single(iface, s, announce_ttl, 1);
+ service_reply_single(iface, NULL, s, announce_ttl, 1);
s = container_of(node_old, struct service, node);
if (!node_new && service_init_announce)
vlist_for_each_element(&interfaces, iface, node)
s = container_of(node_old, struct service, node);
if (!node_new && service_init_announce)
vlist_for_each_element(&interfaces, iface, node)
- service_reply_single(iface, s, 0, 1);
+ service_reply_single(iface, NULL, s, 0, 1);
extern const char *sdudp;
extern void service_init(int announce);
extern void service_cleanup(void);
extern const char *sdudp;
extern void service_init(int announce);
extern void service_cleanup(void);
-extern void service_reply(struct interface *iface, const char *match, int ttl);
-extern void service_announce_services(struct interface *iface, int ttl);
+extern void service_reply(struct interface *iface, struct sockaddr *to, const char *match, int ttl);
+extern void service_announce_services(struct interface *iface, struct sockaddr *to, int ttl);