Skip to content

Commit

Permalink
dnssd: windows: Greatly enhance code
Browse files Browse the repository at this point in the history
The previous code was very complex and was not working properly with
IPv6 addresses.

The new code will use the SRV records to find the hostnames that support
IIO functionality, and then add new entries when a AAAA record provides
a new IPv6 address for a hostname we already know of.

Link-local addresses are now supported, and the interface number will be
appended to the address. Global addresses are supported as well.

Signed-off-by: Paul Cercueil <[email protected]>
  • Loading branch information
pcercuei committed Aug 2, 2023
1 parent 9892815 commit 74623f4
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 118 deletions.
2 changes: 1 addition & 1 deletion dns_sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct dns_sd_discovery_data {
uint16_t found, resolved;
char addr_str[DNS_SD_ADDRESS_STR_MAX];
char *hostname;
uint16_t port;
uint16_t port, iface;
struct dns_sd_discovery_data *next;
};

Expand Down
187 changes: 70 additions & 117 deletions dns_sd_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,23 +212,22 @@ static int query_callback(int sock, const struct sockaddr *from, size_t addrlen,
char entrybuffer[256];
char namebuffer[256];
mdns_record_srv_t srv;
bool found = false;
mdns_string_t entrystr, fromaddrstr, addrstr;
unsigned short port = 0;
mdns_string_t entrystr, fromaddrstr;

if (!dd) {
IIO_ERROR("DNS SD: Missing info structure. Stop browsing.\n");
goto quit;
}

if (rtype != MDNS_RECORDTYPE_SRV && rtype != MDNS_RECORDTYPE_A &&
rtype != MDNS_RECORDTYPE_AAAA)
goto quit;

switch (rtype) {
case MDNS_RECORDTYPE_SRV:
#ifdef HAVE_IPV6
if (rtype == MDNS_RECORDTYPE_AAAA && from->sa_family != AF_INET6)
goto quit;
case MDNS_RECORDTYPE_AAAA:
#endif
break;
default:
goto quit;
}

if (entry != MDNS_ENTRYTYPE_ANSWER)
goto quit;
Expand All @@ -239,129 +238,83 @@ static int query_callback(int sock, const struct sockaddr *from, size_t addrlen,
if (!strstr(entrystr.str, "_iio._tcp.local"))
goto quit;

fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer),
from, addrlen);

iio_mutex_lock(dd->lock);

if (rtype == MDNS_RECORDTYPE_SRV) {
srv = mdns_record_parse_srv(data, size, record_offset, record_length,
namebuffer, sizeof(namebuffer));

fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer),
from, addrlen);

IIO_DEBUG("%.*s : %.*s SRV %.*s priority %d weight %d port %d\n",
MDNS_STRING_FORMAT(fromaddrstr), MDNS_STRING_FORMAT(entrystr),
MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port);

/* find a match based on name/port/ipv[46] & update it, otherwise add it */
while (dd->next) {
if (dd->hostname &&
!strncmp(dd->hostname, srv.name.str, srv.name.length - 1) &&
(!dd->port || dd->port == srv.port) &&
dd->found == (from->sa_family != AF_INET)) {
dd->port = srv.port;
IIO_DEBUG("DNS SD: updated SRV %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);
found = true;
}
dd = dd->next;
}
if (!found) {
/* new hostname and port */
if (srv.name.length > 1) {
dd->hostname = iio_strndup(srv.name.str,
srv.name.length - 1);
if (!dd->hostname)
goto mem_fail;
}

iio_strlcpy(dd->addr_str, fromaddrstr.str, fromaddrstr.length + 1);
dd->port = srv.port;
dd->found = (from->sa_family != AF_INET);
IIO_DEBUG("DNS SD: added SRV %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);

/* A list entry was filled, prepare new item on the list */
dd->next = new_discovery_data(dd);
if (!dd->next)
goto mem_fail;
}
} else if (rtype == MDNS_RECORDTYPE_A) {
struct sockaddr_in addr;

mdns_record_parse_a(data, size, record_offset, record_length, &addr);
addrstr = ip_address_to_string(namebuffer, sizeof(namebuffer),
(struct sockaddr *) &addr, sizeof(addr));
IIO_DEBUG("%.*s : %.*s A %.*s\n", MDNS_STRING_FORMAT(fromaddrstr),
MDNS_STRING_FORMAT(entrystr), MDNS_STRING_FORMAT(addrstr));

/* find a match based on name/ipv4 or 6 & update it, otherwise add it */
while (dd->next) {
if (dd->hostname &&
!strncmp(dd->hostname, entrystr.str, entrystr.length - 1) &&
!dd->found) {
iio_strlcpy(dd->addr_str, addrstr.str, addrstr.length + 1);
IIO_DEBUG("DNS SD: updated A %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);
found = true;
}
dd = dd->next;
}
if (!found) {
dd->hostname = iio_strndup(entrystr.str, entrystr.length - 1);
if (!dd->hostname)
goto mem_fail;
iio_strlcpy(dd->addr_str, addrstr.str, addrstr.length + 1);
dd->found = 0;
IIO_DEBUG("DNS SD: Added A %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);
/* A list entry was filled, prepare new item on the list */
dd->next = new_discovery_data(dd);
if (!dd->next)
goto mem_fail;
}
}
#ifdef HAVE_IPV6
else if (rtype == MDNS_RECORDTYPE_AAAA) {
else {
struct sockaddr_in6 addr;

mdns_record_parse_aaaa(data, size, record_offset, record_length, &addr);
addr.sin6_scope_id = ((struct sockaddr_in6 *)from)->sin6_scope_id;
addrstr = ip_address_to_string(namebuffer, sizeof(namebuffer),
(struct sockaddr *) &addr, sizeof(addr));
IIO_DEBUG("%.*s : %.*s AAAA %.*s\n", MDNS_STRING_FORMAT(fromaddrstr),
MDNS_STRING_FORMAT(entrystr), MDNS_STRING_FORMAT(addrstr));

/* find a match based on name/port/ipv[46] & update it, otherwise add it */
while (dd->next) {
if (dd->hostname &&
!strncmp(dd->hostname, entrystr.str, entrystr.length - 1) &&
dd->found) {
iio_strlcpy(dd->addr_str, addrstr.str, addrstr.length + 1);
IIO_DEBUG("DNS SD: updated AAAA %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);
found = true;
}
else if (dd->hostname &&
!strncmp(dd->hostname, entrystr.str, entrystr.length - 1)) {
port = dd->port;
}
dd = dd->next;

/* Find a match based on hostname */
for (; dd->next; dd = dd->next) {
if (dd->hostname
&& dd->found
&& !strncmp(dd->hostname, entrystr.str, entrystr.length - 1))
break;
}
if (!found) {
dd->hostname = iio_strndup(entrystr.str, entrystr.length - 1);
if (!dd->hostname)
goto mem_fail;
iio_strlcpy(dd->addr_str, addrstr.str, addrstr.length + 1);
dd->found = 1;
if (port)
dd->port = port;
IIO_DEBUG("DNS SD: added AAAA %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);
/* A list entry was filled, prepare new item on the list */
dd->next = new_discovery_data(dd);
if (!dd->next)
goto mem_fail;

if (!dd->next) {
IIO_DEBUG("No SRV found for hostname %.*s\n",
MDNS_STRING_FORMAT(entrystr));
iio_mutex_unlock(dd->lock);
goto quit;
}

srv.name.str = dd->hostname;
srv.name.length = strlen(dd->hostname) + 1;
srv.port = dd->port;

if (IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr))
addr.sin6_scope_id = dd->iface;
else
addr.sin6_scope_id = 0;

fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer),
(struct sockaddr *)&addr, sizeof(addr));

IIO_DEBUG("Found IPv6 address %.*s for hostname %s\n",
MDNS_STRING_FORMAT(fromaddrstr), dd->hostname);
}
#endif /* HAVE_IPV6 */
#endif

while (dd->next)
dd = dd->next;

/* new hostname and port */
if (srv.name.length > 1) {
dd->hostname = iio_strndup(srv.name.str,
srv.name.length - 1);
if (!dd->hostname)
goto mem_fail;
}

iio_strlcpy(dd->addr_str, fromaddrstr.str, fromaddrstr.length + 1);
dd->port = srv.port;
dd->found = (from->sa_family != AF_INET);
#ifdef HAVE_IPV6
if (dd->found)
dd->iface = (uint16_t)((struct sockaddr_in6 *)from)->sin6_scope_id;
#endif
IIO_DEBUG("DNS SD: added SRV %s (%s port: %hu)\n",
dd->hostname, dd->addr_str, dd->port);

/* A list entry was filled, prepare new item on the list */
dd->next = new_discovery_data(dd);
if (!dd->next)
goto mem_fail;

lasttime = iio_read_counter_us();
iio_mutex_unlock(dd->lock);
quit:
Expand Down

0 comments on commit 74623f4

Please sign in to comment.