From: Guus Sliepen Date: Sun, 12 Jul 2020 20:45:37 +0000 (+0200) Subject: When receiving an mDNS request, send a unicast response back. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=8b44f34be360263e5f30fdd1559da66e1faa3b25;p=meshlink When receiving an mDNS request, send a unicast response back. --- diff --git a/src/discovery.c b/src/discovery.c index 428e4407..82d1edb5 100644 --- a/src/discovery.c +++ b/src/discovery.c @@ -167,7 +167,8 @@ static void send_mdns_packet(meshlink_handle_t *mesh, const discovery_address_t char *fingerprint = meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self); const char *keys[] = {MESHLINK_MDNS_NAME_KEY, MESHLINK_MDNS_FINGERPRINT_KEY}; const char *values[] = {mesh->name, fingerprint}; - size_t size = prepare_packet(data, sizeof data, fingerprint, mesh->appname, "tcp", atoi(mesh->myport), 2, keys, values); + size_t size = prepare_packet(data, sizeof data, fingerprint, mesh->appname, "tcp", atoi(mesh->myport), 2, keys, values, false); + free(fingerprint); switch(addr->address.sa.sa_family) { case AF_INET: @@ -233,13 +234,23 @@ static void mdns_io_handler(event_loop_t *loop, void *data, int flags) { uint16_t port = 0; const char *keys[2] = {MESHLINK_MDNS_NAME_KEY, MESHLINK_MDNS_FINGERPRINT_KEY}; char *values[2] = {NULL, NULL}; + bool response; - if(parse_packet(buf, len, &name, mesh->appname, "tcp", &port, 2, keys, values)) { + if(parse_packet(buf, len, &name, mesh->appname, "tcp", &port, 2, keys, values, &response)) { node_t *n = (node_t *)meshlink_get_node(mesh, values[0]); if(n) { logger(mesh, MESHLINK_INFO, "Node %s is part of the mesh network.\n", n->name); + if(!response && n != mesh->self) { + // Send a unicast response back + char *fingerprint = meshlink_get_fingerprint(mesh, (meshlink_node_t *)mesh->self); + const char *response_values[] = {mesh->name, fingerprint}; + size_t size = prepare_packet(buf, sizeof(buf), fingerprint, mesh->appname, "tcp", atoi(mesh->myport), 2, keys, response_values, true); + sendto(io->fd, buf, size, MSG_DONTWAIT | MSG_NOSIGNAL, &sa.sa, sl); + free(fingerprint); + } + switch(sa.sa.sa_family) { case AF_INET: sa.in.sin_port = port; @@ -504,6 +515,7 @@ static void netlink_parse(meshlink_handle_t *mesh, const void *data, size_t len) static void netlink_io_handler(event_loop_t *loop, void *data, int flags) { (void)flags; + (void)data; static time_t prev_update; meshlink_handle_t *mesh = loop->data; @@ -547,6 +559,7 @@ static void netlink_io_handler(event_loop_t *loop, void *data, int flags) { #elif defined(RTM_NEWADDR) static void pfroute_io_handler(event_loop_t *loop, void *data, int flags) { (void)flags; + (void)data; static time_t prev_update; meshlink_handle_t *mesh = loop->data; @@ -663,6 +676,8 @@ void discovery_stop(meshlink_handle_t *mesh) { free(mesh->discovery.ifaces); free(mesh->discovery.addresses); + mesh->discovery.ifaces = NULL; + mesh->discovery.addresses = NULL; mesh->discovery.iface_count = 0; mesh->discovery.address_count = 0; diff --git a/src/mdns.c b/src/mdns.c index b243b3ae..79de309f 100644 --- a/src/mdns.c +++ b/src/mdns.c @@ -247,14 +247,14 @@ static void buf_check_len_end(cbuf_t *buf, const uint8_t *ptr) { } } -size_t prepare_packet(void *vdata, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values) { +size_t prepare_packet(void *vdata, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values, bool response) { // Create the request/response packet right now uint8_t *data = vdata; buf_t buf = {data, size}; // Header buf_add_uint16(&buf, 0); // TX ID - buf_add_uint16(&buf, 0); // flags + buf_add_uint16(&buf, response ? ntohs(1 << 15) : 0); // flags buf_add_uint16(&buf, 1); // 1 question buf_add_uint16(&buf, 1); // 1 answer RR buf_add_uint16(&buf, 0); // 0 authority RRs @@ -314,22 +314,24 @@ size_t prepare_packet(void *vdata, size_t size, const char *name, const char *pr } } -bool parse_packet(const void *vdata, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values) { +bool parse_packet(const void *vdata, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values, bool *response) { const uint8_t *data = vdata; cbuf_t buf = {data, size}; // Header buf_check_uint16(&buf, 0); // TX ID - buf_check_uint16(&buf, 0); // flags + uint16_t flags = buf_get_uint16(&buf); // flags buf_check_uint16(&buf, 1); // 1 question buf_check_uint16(&buf, 1); // 1 answer RR buf_check_uint16(&buf, 0); // 0 authority RRs buf_check_uint16(&buf, 2); // 1 checkitional RR - if(buf.len == -1) { + if(buf.len == -1 || flags & ~ntohs(1 << 15)) { return false; } + *response = flags & ntohs(1 << 15); + // Question section: _protocol._transport.local PTR IN buf_check_ulabel(&buf, protocol); buf_check_ulabel(&buf, transport); diff --git a/src/mdns.h b/src/mdns.h index a5384599..1bd8451d 100644 --- a/src/mdns.h +++ b/src/mdns.h @@ -6,6 +6,6 @@ #include #include -size_t prepare_packet(void *buf, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values); -bool parse_packet(const void *buf, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values); +size_t prepare_packet(void *buf, size_t size, const char *name, const char *protocol, const char *transport, uint16_t port, int nkeys, const char **keys, const char **values, bool response); +bool parse_packet(const void *buf, size_t size, char **name, const char *protocol, const char *transport, uint16_t *port, int nkeys, const char **keys, char **values, bool *response);