]> git.meshlink.io Git - meshlink/commitdiff
When receiving an mDNS request, send a unicast response back.
authorGuus Sliepen <guus@meshlink.io>
Sun, 12 Jul 2020 20:45:37 +0000 (22:45 +0200)
committerGuus Sliepen <guus@meshlink.io>
Tue, 26 Jan 2021 20:43:45 +0000 (21:43 +0100)
src/discovery.c
src/mdns.c
src/mdns.h

index 428e44074fcc4103d76ad74f9fad75bf8ec726c4..82d1edb5fa5c7f32398590cf5127bf82ec89e908 100644 (file)
@@ -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;
 
index b243b3ae0430c671333211baa24f5ee1fac1145b..79de309f8805f12442671fa469ea50b33ede58b3 100644 (file)
@@ -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);
index a538459963e485f2f6515cc9123d634768f9d519..1bd8451da0c1dc5940a1bb40ffca0fe2d1f51a8c 100644 (file)
@@ -6,6 +6,6 @@
 #include <stdint.h>
 #include <unistd.h>
 
-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);