diff options
Diffstat (limited to 'ctrl/facemgr/src/interfaces/bonjour')
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt | 2 | ||||
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/bonjour.c | 572 | ||||
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/bonjour.h | 12 | ||||
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c | 302 | ||||
-rw-r--r-- | ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h | 950 |
5 files changed, 894 insertions, 944 deletions
diff --git a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt index 8a0ddc888..90ca0e47f 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c index 40b7f5f90..90f18c299 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -25,6 +25,7 @@ #include <hicn/facemgr.h> #include <hicn/util/log.h> #include <hicn/util/map.h> +#include <hicn/util/sstrncpy.h> #include "../../common.h" #include "../../interface.h" @@ -40,368 +41,357 @@ #define DEFAULT_SERVICE_DOMAIN "local" typedef struct { - bonjour_cfg_t cfg; - int sock; - size_t buffer_size; - void* buffer; + bonjour_cfg_t cfg; + int sock; + size_t buffer_size; + void* buffer; - /* The face being resolved, non-NULL values indicate interface is busy... */ - face_t * face; + /* The face being resolved, non-NULL values indicate interface is busy... */ + face_t* face; } bj_data_t; -int bj_initialize(interface_t * interface, void * cfg) -{ - bj_data_t * data = malloc(sizeof(bj_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; +int bj_initialize(interface_t* interface, void* cfg) { + bj_data_t* data = malloc(sizeof(bj_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; - if (cfg) { + if (cfg) { #ifndef __linux__ - if (cfg->netdevice) - WARN("Binding to interface is (currently) only supported on Linux"); + if (cfg->netdevice) + WARN("Binding to interface is (currently) only supported on Linux"); #endif /* ! __linux__ */ - data->cfg = * (bonjour_cfg_t *) cfg; - } else { - memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); - } + data->cfg = *(bonjour_cfg_t*)cfg; + } else { + memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); + } - if (!data->cfg.service_name) - data->cfg.service_name = DEFAULT_SERVICE_NAME; + if (!data->cfg.service_name) data->cfg.service_name = DEFAULT_SERVICE_NAME; - if (!data->cfg.service_protocol) - data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; + if (!data->cfg.service_protocol) + data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; - if (!data->cfg.service_domain) - data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; + if (!data->cfg.service_domain) + data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; - data->sock = mdns_socket_open_ipv4(); - if (data->sock < 0) { - printf("Failed to open socket: %s\n", strerror(errno)); - goto ERR_SOCK; - } + data->sock = mdns_socket_open_ipv4(); + if (data->sock < 0) { + printf("Failed to open socket: %s\n", strerror(errno)); + goto ERR_SOCK; + } - /* Netdevice configuration */ + /* Netdevice configuration */ #ifdef __linux__ #ifndef __ANDROID__ - if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { - int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, - &data->cfg.netdevice.name, strlen(data->cfg.netdevice.name) + 1); - if (rc == -1) { - ERROR("setsockopt"); - goto ERR_SOCK_OPT; - } + if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { + int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, + &data->cfg.netdevice.name, + strnlen_s(data->cfg.netdevice.name, IFNAMSIZ)); + if (rc == -1) { + ERROR("setsockopt"); + goto ERR_SOCK_OPT; } + } #endif #endif /* __linux__ */ - data->buffer_size = DEFAULT_BUFFER_SIZE; - data->buffer = malloc(data->buffer_size); - if (!data->buffer) - goto ERR_BUFFER; + data->buffer_size = DEFAULT_BUFFER_SIZE; + data->buffer = malloc(data->buffer_size); + if (!data->buffer) goto ERR_BUFFER; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - if (interface_register_fd(interface, data->sock, NULL) < 0) { - ERROR("[bj_initialize] Error registering fd"); - goto ERR_FD; - } + if (interface_register_fd(interface, data->sock, NULL) < 0) { + ERROR("[bj_initialize] Error registering fd"); + goto ERR_FD; + } - return 0; + return 0; ERR_FD: - free(data->buffer); + free(data->buffer); ERR_BUFFER: #ifndef __ANDROID__ ERR_SOCK_OPT: #endif - mdns_socket_close(data->sock); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif ERR_SOCK: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } /* * We reuse the callback to be triggered upon external events * TODO: move to a cleaner interface architecture later... */ -int bj_on_event(interface_t * interface, facelet_t * facelet) -{ - bj_data_t * data = (bj_data_t*)interface->data; - - /* - printf("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - printf("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - DEBUG("Sending mDNS query"); - char service_string[SERVICE_STRING_SIZE]; - - int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", - data->cfg.service_name, data->cfg.service_protocol, - data->cfg.service_domain); - if (rc < 0) - ; // error - else if (rc >= SERVICE_STRING_SIZE) - ; //truncated - - if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, - service_string, - strlen(service_string), - data->buffer, data->buffer_size)) { - printf("Failed to send mDNS query: %s\n", strerror(errno)); - return -1; - } - return 0; +int bj_on_event(interface_t* interface, facelet_t* facelet) { + bj_data_t* data = (bj_data_t*)interface->data; + + /* + printf("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); + goto quit; + } + + printf("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, callback, + user_data); + sleep(1); + } + */ + + DEBUG("Sending mDNS query"); + char service_string[SERVICE_STRING_SIZE]; + + int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", + data->cfg.service_name, data->cfg.service_protocol, + data->cfg.service_domain); + if (rc < 0) + ; // error + else if (rc >= SERVICE_STRING_SIZE) + ; // truncated + + if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, service_string, + strnlen_s(service_string, SERVICE_STRING_SIZE), + data->buffer, data->buffer_size)) { + printf("Failed to send mDNS query: %s\n", strerror(errno)); + return -1; + } + return 0; } static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -int -ip_address_set_sockaddr(ip_address_t * ip_address, struct sockaddr * sa) -{ - switch(sa->sa_family) { - case AF_INET: - ip_address->v4.as_inaddr = ((struct sockaddr_in *)sa)->sin_addr; - break; - case AF_INET6: - ip_address->v6.as_in6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; - break; - default: - return -1; - } - - return 0; +int ip_address_set_sockaddr(ip_address_t* ip_address, struct sockaddr* sa) { + switch (sa->sa_family) { + case AF_INET: + ip_address->v4.as_inaddr = ((struct sockaddr_in*)sa)->sin_addr; + break; + case AF_INET6: + ip_address->v6.as_in6addr = ((struct sockaddr_in6*)sa)->sin6_addr; + break; + default: + return -1; + } + + return 0; } -static int -callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, const void* data, size_t size, size_t - offset, size_t length, void* user_data) -{ - interface_t * interface = (interface_t*)user_data; - bj_data_t * bj_data = (bj_data_t *)interface->data; - - struct sockaddr_storage addr; - - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - - switch(type) { - case MDNS_RECORDTYPE_A: - { - ip_address_t ip_address; - mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), (struct sockaddr_in *)&addr); - DEBUG("%.*s : %s A %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + interface_t* interface = (interface_t*)user_data; + bj_data_t* bj_data = (bj_data_t*)interface->data; + + struct sockaddr_storage addr; + + mdns_string_t fromaddrstr = + ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + + switch (type) { + case MDNS_RECORDTYPE_A: { + ip_address_t ip_address; + mdns_record_parse_a(data, size, offset, length, + (struct sockaddr_in*)&addr); + ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv4_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in*)&addr); + DEBUG("%.*s : %s A %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in*)&addr)->sin_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_AAAA: - { - ip_address_t ip_address; - mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, - sizeof(namebuffer), (struct sockaddr_in6*)&addr); - DEBUG("%.*s : %s AAAA %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_AAAA: { + ip_address_t ip_address; + mdns_record_parse_aaaa(data, size, offset, length, + (struct sockaddr_in6*)&addr); + ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv6_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in6*)&addr); + DEBUG("%.*s : %s AAAA %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in6*)&addr)->sin6_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ - { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - - DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - - /* We raise both v4 and v6 - * - * Unless we choose whether we query A and/or AAAA, this might leave - * us with an unused pending facelet, eg. we might not have an IPv6 - * but we raise an IPv6 bonjour event... - */ - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - - facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ + { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + + DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + + /* We raise both v4 and v6 + * + * Unless we choose whether we query A and/or AAAA, this might leave + * us with an unused pending facelet, eg. we might not have an IPv6 + * but we raise an IPv6 bonjour event... + */ + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + + facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_PTR: - { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - break; - } + case MDNS_RECORDTYPE_PTR: { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + break; + } - case MDNS_RECORDTYPE_TXT: - { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - DEBUG("%.*s : %s TXT %.*s = %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - DEBUG("%.*s : %s TXT %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - break; + case MDNS_RECORDTYPE_TXT: { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + DEBUG("%.*s : %s TXT %.*s = %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + DEBUG("%.*s : %s TXT %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key)); } - - default: - /* Silently ignore the received record */ - DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - return 0; + } + break; } - return 0; + default: + /* Silently ignore the received record */ + DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + return 0; + } + return 0; } /* * The fact we use a single fd does not allow us to get user_data associated to * the query. */ -int bj_callback(interface_t * interface, int fd, void * unused) -{ - bj_data_t * data = (bj_data_t*)interface->data; - DEBUG("Got an mDNS reply"); - /* size_t records = */ mdns_query_recv(data->sock, data->buffer, data->buffer_size, callback, interface, 1); +int bj_callback(interface_t* interface, int fd, void* unused) { + bj_data_t* data = (bj_data_t*)interface->data; + DEBUG("Got an mDNS reply"); + /* size_t records = */ mdns_query_recv( + data->sock, data->buffer, data->buffer_size, callback, interface, 1); - return 0; + return 0; } -int bj_finalize(interface_t * interface) -{ - bj_data_t * data = (bj_data_t*)interface->data; +int bj_finalize(interface_t* interface) { + bj_data_t* data = (bj_data_t*)interface->data; - free(data->buffer); - mdns_socket_close(data->sock); + free(data->buffer); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; - + return 0; } const interface_ops_t bonjour_ops = { @@ -410,5 +400,5 @@ const interface_ops_t bonjour_ops = { .on_event = bj_on_event, .callback = bj_callback, .finalize = bj_finalize, - // .on_event = NULL, + // .on_event = NULL, }; diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h index fe053079d..6458423ea 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -25,11 +25,11 @@ * queries... */ -#include <hicn/ctrl/face.h> /* netdevice_t */ +#include <hicn/face.h> /* netdevice_t */ typedef struct { - netdevice_t netdevice; - char * service_name; - char * service_protocol; - char * service_domain; + netdevice_t netdevice; + char* service_name; + char* service_protocol; + char* service_domain; } bonjour_cfg_t; diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c index a8e97e8e0..e2bb4f432 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c @@ -1,6 +1,6 @@ #ifdef _WIN32 -# define _CRT_SECURE_NO_WARNINGS 1 +#define _CRT_SECURE_NO_WARNINGS 1 #endif #include "mdns.h" @@ -9,184 +9,176 @@ #include <errno.h> #ifdef _WIN32 -# define sleep(x) Sleep(x * 1000) +#define sleep(x) Sleep(x * 1000) #else -# include <netdb.h> +#include <netdb.h> #endif static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -static int -callback(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data) { - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - if (type == MDNS_RECORDTYPE_PTR) { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - } - else if (type == MDNS_RECORDTYPE_SRV) { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - } - else if (type == MDNS_RECORDTYPE_A) { - struct sockaddr_in addr; - mdns_record_parse_a(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s A %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_AAAA) { - struct sockaddr_in6 addr; - mdns_record_parse_aaaa(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s AAAA %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_TXT) { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - INFO("%.*s : %s TXT %.*s = %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - INFO("%.*s : %s TXT %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - } - else { - INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - } - return 0; +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + mdns_string_t fromaddrstr = + ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + if (type == MDNS_RECORDTYPE_PTR) { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + } else if (type == MDNS_RECORDTYPE_SRV) { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + } else if (type == MDNS_RECORDTYPE_A) { + struct sockaddr_in addr; + mdns_record_parse_a(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s A %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_AAAA) { + struct sockaddr_in6 addr; + mdns_record_parse_aaaa(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s AAAA %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_TXT) { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + INFO("%.*s : %s TXT %.*s = %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + INFO("%.*s : %s TXT %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(txtbuffer[itxt].key)); + } + } + } else { + INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + } + return 0; } -int -main() { - size_t capacity = 2048; - void* buffer = 0; - void* user_data = 0; - size_t records; +int main() { + size_t capacity = 2048; + void* buffer = 0; + void* user_data = 0; + size_t records; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - int sock = mdns_socket_open_ipv4(); - if (sock < 0) { - INFO("Failed to open socket: %s\n", strerror(errno)); - return -1; - } - INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); - buffer = malloc(capacity); -/* - INFO("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - INFO("Sending mDNS query\n"); - if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, - MDNS_STRING_CONST("_hicn._udp.local."), - buffer, capacity)) { - INFO("Failed to send mDNS query: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading mDNS replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); - sleep(1); - } + int sock = mdns_socket_open_ipv4(); + if (sock < 0) { + INFO("Failed to open socket: %s\n", strerror(errno)); + return -1; + } + INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); + buffer = malloc(capacity); + /* + INFO("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + INFO("Failed to send DNS-DS discovery: %s\n", + strerror(errno)); goto quit; + } + + INFO("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, + callback, user_data); sleep(1); + } + */ + + INFO("Sending mDNS query\n"); + if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, + MDNS_STRING_CONST("_hicn._udp.local."), buffer, + capacity)) { + INFO("Failed to send mDNS query: %s\n", strerror(errno)); + goto quit; + } + + INFO("Reading mDNS replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); + sleep(1); + } quit: - free(buffer); + free(buffer); - mdns_socket_close(sock); - INFO("Closed socket\n"); + mdns_socket_close(sock); + INFO("Closed socket\n"); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; + return 0; } diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h index ff04b5d72..4b8e7a7f4 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h @@ -7,7 +7,8 @@ * * https://github.com/mjansson/mdns * - * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * This library is put in the public domain; you can redistribute it and/or + * modify it without any restrictions. * */ @@ -31,76 +32,73 @@ #define MDNS_INVALID_POS ((size_t)-1) -#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1) +#define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1) #define MDNS_STRING_FORMAT(s) (int)((s).length), s.str enum mdns_record_type { - MDNS_RECORDTYPE_IGNORE = 0, - //Address - MDNS_RECORDTYPE_A = 1, - //Domain Name pointer - MDNS_RECORDTYPE_PTR = 12, - //Arbitrary text string - MDNS_RECORDTYPE_TXT = 16, - //IP6 Address [Thomson] - MDNS_RECORDTYPE_AAAA = 28, - //Server Selection [RFC2782] - MDNS_RECORDTYPE_SRV = 33 + MDNS_RECORDTYPE_IGNORE = 0, + // Address + MDNS_RECORDTYPE_A = 1, + // Domain Name pointer + MDNS_RECORDTYPE_PTR = 12, + // Arbitrary text string + MDNS_RECORDTYPE_TXT = 16, + // IP6 Address [Thomson] + MDNS_RECORDTYPE_AAAA = 28, + // Server Selection [RFC2782] + MDNS_RECORDTYPE_SRV = 33 }; enum mdns_entry_type { - MDNS_ENTRYTYPE_ANSWER = 1, - MDNS_ENTRYTYPE_AUTHORITY = 2, - MDNS_ENTRYTYPE_ADDITIONAL = 3 + MDNS_ENTRYTYPE_ANSWER = 1, + MDNS_ENTRYTYPE_AUTHORITY = 2, + MDNS_ENTRYTYPE_ADDITIONAL = 3 }; -enum mdns_class { - MDNS_CLASS_IN = 1 -}; +enum mdns_class { MDNS_CLASS_IN = 1 }; -typedef enum mdns_record_type mdns_record_type_t; -typedef enum mdns_entry_type mdns_entry_type_t; -typedef enum mdns_class mdns_class_t; +typedef enum mdns_record_type mdns_record_type_t; +typedef enum mdns_entry_type mdns_entry_type_t; +typedef enum mdns_class mdns_class_t; -typedef int (* mdns_record_callback_fn)(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data); +typedef int (*mdns_record_callback_fn)(const struct sockaddr* from, + mdns_entry_type_t entry, uint16_t type, + uint16_t rclass, uint32_t ttl, + const void* data, size_t size, + size_t offset, size_t length, + void* user_data); -typedef struct mdns_string_t mdns_string_t; -typedef struct mdns_string_pair_t mdns_string_pair_t; -typedef struct mdns_record_srv_t mdns_record_srv_t; -typedef struct mdns_record_txt_t mdns_record_txt_t; +typedef struct mdns_string_t mdns_string_t; +typedef struct mdns_string_pair_t mdns_string_pair_t; +typedef struct mdns_record_srv_t mdns_record_srv_t; +typedef struct mdns_record_txt_t mdns_record_txt_t; struct mdns_string_t { - const char* str; - size_t length; + const char* str; + size_t length; }; struct mdns_string_pair_t { - size_t offset; - size_t length; - int ref; + size_t offset; + size_t length; + int ref; }; struct mdns_record_srv_t { - uint16_t priority; - uint16_t weight; - uint16_t port; - mdns_string_t name; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_string_t name; }; struct mdns_record_txt_t { - mdns_string_t key; - mdns_string_t value; + mdns_string_t key; + mdns_string_t value; }; -static int -mdns_socket_open_ipv4(void); +static int mdns_socket_open_ipv4(void); -static int -mdns_socket_setup_ipv4(int sock); +static int mdns_socket_setup_ipv4(int sock); #if 0 static int @@ -112,8 +110,7 @@ static int mdns_socket_setup_ipv6(int sock); #endif -static void -mdns_socket_close(int sock); +static void mdns_socket_close(int sock); #if 0 static int @@ -125,21 +122,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callback_fn callback, void* user_data); #endif -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity); +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity); -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot); +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot); -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity); +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity); -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset); +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset); #if 0 static int @@ -147,78 +141,80 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs); #endif -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length); +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length); -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity); -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity); -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr); +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr); -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr); +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr); -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity); +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity); // Implementations -static int -mdns_socket_open_ipv4(void) { - int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - return -1; - if (mdns_socket_setup_ipv4(sock)) { - mdns_socket_close(sock); - return -1; - } - return sock; +static int mdns_socket_open_ipv4(void) { + int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) return -1; + if (mdns_socket_setup_ipv4(sock)) { + mdns_socket_close(sock); + return -1; + } + return sock; } -static int -mdns_socket_setup_ipv4(int sock) { - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = INADDR_ANY; +static int mdns_socket_setup_ipv4(int sock) { + struct sockaddr_in saddr; + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; #ifdef __APPLE__ - saddr.sin_len = sizeof(saddr); + saddr.sin_len = sizeof(saddr); #endif - if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) - return -1; + if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) return -1; #ifdef _WIN32 - unsigned long param = 1; - ioctlsocket(sock, FIONBIO, ¶m); + unsigned long param = 1; + ioctlsocket(sock, FIONBIO, ¶m); #else - const int flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + const int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); #endif - unsigned char ttl = 1; - unsigned char loopback = 1; - struct ip_mreq req; + unsigned char ttl = 1; + unsigned char loopback = 1; + struct ip_mreq req; - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, + sizeof(ttl)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, + sizeof(loopback)); - memset(&req, 0, sizeof(req)); - req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - req.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) - return -1; + memset(&req, 0, sizeof(req)); + req.imr_multiaddr.s_addr = + htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + req.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) + return -1; - return 0; + return 0; } #if 0 @@ -274,67 +270,58 @@ mdns_socket_setup_ipv6(int sock) { } #endif -static void -mdns_socket_close(int sock) { +static void mdns_socket_close(int sock) { #ifdef _WIN32 - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif } -static int -mdns_is_string_ref(uint8_t val) { - return (0xC0 == (val & 0xC0)); -} +static int mdns_is_string_ref(uint8_t val) { return (0xC0 == (val & 0xC0)); } -static mdns_string_pair_t -mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) { - const uint8_t* buffer = rawdata; - mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; - if (!buffer[offset]) { - pair.offset = offset; - return pair; - } - if (mdns_is_string_ref(buffer[offset])) { - if (size < offset + 2) - return pair; +static mdns_string_pair_t mdns_get_next_substring(const void* rawdata, + size_t size, size_t offset) { + const uint8_t* buffer = rawdata; + mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; + if (!buffer[offset]) { + pair.offset = offset; + return pair; + } + if (mdns_is_string_ref(buffer[offset])) { + if (size < offset + 2) return pair; - offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); - if (offset >= size) - return pair; + offset = + (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); + if (offset >= size) return pair; - pair.ref = 1; - } + pair.ref = 1; + } - size_t length = (size_t)buffer[offset++]; - if (size < offset + length) - return pair; + size_t length = (size_t)buffer[offset++]; + if (size < offset + length) return pair; - pair.offset = offset; - pair.length = length; + pair.offset = offset; + pair.length = length; - return pair; + return pair; } -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset) { - size_t cur = *offset; - mdns_string_pair_t substr; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return 0; - if (substr.ref) { - *offset = cur + 2; - return 1; - } - cur = substr.offset + substr.length; - } - while (substr.length); - - *offset = cur + 1; - return 1; +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset) { + size_t cur = *offset; + mdns_string_pair_t substr; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return 0; + if (substr.ref) { + *offset = cur + 2; + return 1; + } + cur = substr.offset + substr.length; + } while (substr.length); + + *offset = cur + 1; + return 1; } #if 0 @@ -378,142 +365,133 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, } #endif -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity) { - size_t cur = *offset; - size_t end = MDNS_INVALID_POS; - mdns_string_pair_t substr; - mdns_string_t result = {str, 0}; - char* dst = str; - size_t remain = capacity; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return result; - if (substr.ref && (end == MDNS_INVALID_POS)) - end = cur + 2; - if (substr.length) { - size_t to_copy = (substr.length < remain) ? substr.length : remain; - memcpy(dst, (const char*)buffer + substr.offset, to_copy); - dst += to_copy; - remain -= to_copy; - if (remain) { - *dst++ = '.'; - --remain; - } - } - cur = substr.offset + substr.length; - } - while (substr.length); - - if (end == MDNS_INVALID_POS) - end = cur + 1; - *offset = end; - - result.length = capacity - remain; - return result; +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity) { + size_t cur = *offset; + size_t end = MDNS_INVALID_POS; + mdns_string_pair_t substr; + mdns_string_t result = {str, 0}; + char* dst = str; + size_t remain = capacity; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return result; + if (substr.ref && (end == MDNS_INVALID_POS)) end = cur + 2; + if (substr.length) { + size_t to_copy = (substr.length < remain) ? substr.length : remain; + memcpy(dst, (const char*)buffer + substr.offset, to_copy); + dst += to_copy; + remain -= to_copy; + if (remain) { + *dst++ = '.'; + --remain; + } + } + cur = substr.offset + substr.length; + } while (substr.length); + + if (end == MDNS_INVALID_POS) end = cur + 1; + *offset = end; + + result.length = capacity - remain; + return result; } -static size_t -mdns_string_find(const char* str, size_t length, char c, size_t offset) { - const void* found; - if (offset >= length) - return MDNS_INVALID_POS; - found = memchr(str + offset, c, length - offset); - if (found) - return (size_t)((const char*)found - str); - return MDNS_INVALID_POS; +static size_t mdns_string_find(const char* str, size_t length, char c, + size_t offset) { + const void* found; + if (offset >= length) return MDNS_INVALID_POS; + found = memchr(str + offset, c, length - offset); + if (found) return (size_t)((const char*)found - str); + return MDNS_INVALID_POS; } -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length) { - size_t pos = 0; - size_t last_pos = 0; - size_t remain = capacity; - unsigned char* dest = data; - while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) { - size_t sublength = pos - last_pos; - if (sublength < remain) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - last_pos = pos + 1; - } - if (last_pos < length) { - size_t sublength = length - last_pos; - if (sublength < capacity) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - } - if (!remain) - return 0; - *dest++ = 0; - return dest; +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length) { + size_t pos = 0; + size_t last_pos = 0; + size_t remain = capacity; + unsigned char* dest = data; + while ((last_pos < length) && + ((pos = mdns_string_find(name, length, '.', last_pos)) != + MDNS_INVALID_POS)) { + size_t sublength = pos - last_pos; + if (sublength < remain) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + last_pos = pos + 1; + } + if (last_pos < length) { + size_t sublength = length - last_pos; + if (sublength < capacity) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + } + if (!remain) return 0; + *dest++ = 0; + return dest; } -static size_t -mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset, - mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback, - void* user_data) { - size_t parsed = 0; - int do_callback = 1; - for (size_t i = 0; i < records; ++i) { - mdns_string_skip(buffer, size, offset); - const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); - - uint16_t rtype = ntohs(*data++); - uint16_t rclass = ntohs(*data++); - uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2; - uint16_t length = ntohs(*data++); - - *offset += 10; - - if (do_callback) { - ++parsed; - if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length, - user_data)) - do_callback = 0; - } - - *offset += length; - } - return parsed; +static size_t mdns_records_parse(const struct sockaddr* from, + const void* buffer, size_t size, + size_t* offset, mdns_entry_type_t type, + size_t records, + mdns_record_callback_fn callback, + void* user_data) { + size_t parsed = 0; + int do_callback = 1; + for (size_t i = 0; i < records; ++i) { + mdns_string_skip(buffer, size, offset); + const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); + + uint16_t rtype = ntohs(*data++); + uint16_t rclass = ntohs(*data++); + uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); + data += 2; + uint16_t length = ntohs(*data++); + + *offset += 10; + + if (do_callback) { + ++parsed; + if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, + length, user_data)) + do_callback = 0; + } + + *offset += length; + } + return parsed; } static const uint8_t mdns_services_query[] = { - // Transaction ID - 0x00, 0x00, - // Flags - 0x00, 0x00, - // 1 question - 0x00, 0x01, - // No answer, authority or additional RRs - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - // _services._dns-sd._udp.local. - 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', - 0x07, '_', 'd', 'n', 's', '-', 's', 'd', - 0x04, '_', 'u', 'd', 'p', - 0x05, 'l', 'o', 'c', 'a', 'l', - 0x00, - // PTR record - 0x00, MDNS_RECORDTYPE_PTR, - // QU (unicast response) and class IN - 0x80, MDNS_CLASS_IN -}; + // Transaction ID + 0x00, 0x00, + // Flags + 0x00, 0x00, + // 1 question + 0x00, 0x01, + // No answer, authority or additional RRs + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // _services._dns-sd._udp.local. + 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', 0x07, '_', 'd', 'n', 's', + '-', 's', 'd', 0x04, '_', 'u', 'd', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + // PTR record + 0x00, MDNS_RECORDTYPE_PTR, + // QU (unicast response) and class IN + 0x80, MDNS_CLASS_IN}; #if 0 static int @@ -645,233 +623,223 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, static uint16_t mdns_transaction_id = 0; -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity) { - if (capacity < (17 + length)) - return -1; - - uint16_t* data = buffer; - //Transaction ID - *data++ = htons(++mdns_transaction_id); - //Flags - *data++ = 0; - //Questions - *data++ = htons(1); - //No answer, authority or additional RRs - *data++ = 0; - *data++ = 0; - *data++ = 0; - //Name string - data = mdns_string_make(data, capacity - 17, name, length); - if (!data) - return -1; - //Record type - *data++ = htons(type); - //! Unicast response, class IN - *data++ = htons(0x8000U | MDNS_CLASS_IN); - - struct sockaddr_storage addr_storage; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - struct sockaddr* saddr = (struct sockaddr*)&addr_storage; - socklen_t saddrlen = sizeof(struct sockaddr_storage); - if (getsockname(sock, saddr, &saddrlen)) - return -1; - if (saddr->sa_family == AF_INET6) { - memset(&addr6, 0, sizeof(struct sockaddr_in6)); - addr6.sin6_family = AF_INET6; +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity) { + if (capacity < (17 + length)) return -1; + + uint16_t* data = buffer; + // Transaction ID + *data++ = htons(++mdns_transaction_id); + // Flags + *data++ = 0; + // Questions + *data++ = htons(1); + // No answer, authority or additional RRs + *data++ = 0; + *data++ = 0; + *data++ = 0; + // Name string + data = mdns_string_make(data, capacity - 17, name, length); + if (!data) return -1; + // Record type + *data++ = htons(type); + //! Unicast response, class IN + *data++ = htons(0x8000U | MDNS_CLASS_IN); + + struct sockaddr_storage addr_storage; + struct sockaddr_in addr; + struct sockaddr_in6 addr6; + struct sockaddr* saddr = (struct sockaddr*)&addr_storage; + socklen_t saddrlen = sizeof(struct sockaddr_storage); + if (getsockname(sock, saddr, &saddrlen)) return -1; + if (saddr->sa_family == AF_INET6) { + memset(&addr6, 0, sizeof(struct sockaddr_in6)); + addr6.sin6_family = AF_INET6; #ifdef __APPLE__ - addr6.sin6_len = sizeof(struct sockaddr_in6); + addr6.sin6_len = sizeof(struct sockaddr_in6); #endif - addr6.sin6_addr.s6_addr[0] = 0xFF; - addr6.sin6_addr.s6_addr[1] = 0x02; - addr6.sin6_addr.s6_addr[15] = 0xFB; - addr6.sin6_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr6; - saddrlen = sizeof(struct sockaddr_in6); - } - else { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; + addr6.sin6_addr.s6_addr[0] = 0xFF; + addr6.sin6_addr.s6_addr[1] = 0x02; + addr6.sin6_addr.s6_addr[15] = 0xFB; + addr6.sin6_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr6; + saddrlen = sizeof(struct sockaddr_in6); + } else { + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; #ifdef __APPLE__ - addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - addr.sin_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr; - saddrlen = sizeof(struct sockaddr_in); - } - - if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, - saddr, saddrlen) < 0) - return -1; - return 0; + addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + addr.sin_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr; + saddrlen = sizeof(struct sockaddr_in); + } + + if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, saddr, saddrlen) < 0) + return -1; + return 0; } -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot) { - struct sockaddr_in6 addr; - struct sockaddr* saddr = (struct sockaddr*)&addr; - memset(&addr, 0, sizeof(addr)); - saddr->sa_family = AF_INET; +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot) { + struct sockaddr_in6 addr; + struct sockaddr* saddr = (struct sockaddr*)&addr; + memset(&addr, 0, sizeof(addr)); + saddr->sa_family = AF_INET; #ifdef __APPLE__ - saddr->sa_len = sizeof(addr); + saddr->sa_len = sizeof(addr); #endif - socklen_t addrlen = sizeof(addr); - int ret = recvfrom(sock, buffer, capacity, 0, - saddr, &addrlen); - if (ret <= 0) - return 0; - - size_t data_size = (size_t)ret; - uint16_t* data = (uint16_t*)buffer; - - uint16_t transaction_id = ntohs(*data++); - ++data;// uint16_t flags = ntohs(*data++); - uint16_t questions = ntohs(*data++); - uint16_t answer_rrs = ntohs(*data++); - uint16_t authority_rrs = ntohs(*data++); - uint16_t additional_rrs = ntohs(*data++); - - if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400)) - return 0; //Not a reply to our last question - - if (questions > 1) - return 0; - - //Skip questions part - int i; - for (i = 0; i < questions; ++i) { - size_t ofs = (size_t)((char*)data - (char*)buffer); - if (!mdns_string_skip(buffer, data_size, &ofs)) - return 0; - data = (void*)((char*)buffer + ofs); - ++data; - ++data; - } - - size_t records = 0; - size_t offset = (size_t)((char*)data - (char*)buffer); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ANSWER, answer_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, - callback, user_data); - return records; + socklen_t addrlen = sizeof(addr); + int ret = recvfrom(sock, buffer, capacity, 0, saddr, &addrlen); + if (ret <= 0) return 0; + + size_t data_size = (size_t)ret; + uint16_t* data = (uint16_t*)buffer; + + uint16_t transaction_id = ntohs(*data++); + ++data; // uint16_t flags = ntohs(*data++); + uint16_t questions = ntohs(*data++); + uint16_t answer_rrs = ntohs(*data++); + uint16_t authority_rrs = ntohs(*data++); + uint16_t additional_rrs = ntohs(*data++); + + if (one_shot && + transaction_id != mdns_transaction_id) // || (flags != 0x8400)) + return 0; // Not a reply to our last question + + if (questions > 1) return 0; + + // Skip questions part + int i; + for (i = 0; i < questions; ++i) { + size_t ofs = (size_t)((char*)data - (char*)buffer); + if (!mdns_string_skip(buffer, data_size, &ofs)) return 0; + data = (void*)((char*)buffer + ofs); + ++data; + ++data; + } + + size_t records = 0; + size_t offset = (size_t)((char*)data - (char*)buffer); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ANSWER, answer_rrs, callback, + user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, + callback, user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, + callback, user_data); + return records; } -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - //PTR record is just a string - if ((size >= offset + length) && (length >= 2)) - return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - mdns_string_t empty = {0, 0}; - return empty; +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity) { + // PTR record is just a string + if ((size >= offset + length) && (length >= 2)) + return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + mdns_string_t empty = {0, 0}; + return empty; } -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - mdns_record_srv_t srv; - memset(&srv, 0, sizeof(mdns_record_srv_t)); - // Read the priority, weight, port number and the discovery name - // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): - // 2 bytes network-order unsigned priority - // 2 bytes network-order unsigned weight - // 2 bytes network-order unsigned port - // string: discovery (domain) name, minimum 2 bytes when compressed - if ((size >= offset + length) && (length >= 8)) { - const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset); - srv.priority = ntohs(*recorddata++); - srv.weight = ntohs(*recorddata++); - srv.port = ntohs(*recorddata++); - offset += 6; - srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - } - return srv; +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity) { + mdns_record_srv_t srv; + memset(&srv, 0, sizeof(mdns_record_srv_t)); + // Read the priority, weight, port number and the discovery name + // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): + // 2 bytes network-order unsigned priority + // 2 bytes network-order unsigned weight + // 2 bytes network-order unsigned port + // string: discovery (domain) name, minimum 2 bytes when compressed + if ((size >= offset + length) && (length >= 8)) { + const uint16_t* recorddata = + (const uint16_t*)((const char*)buffer + offset); + srv.priority = ntohs(*recorddata++); + srv.weight = ntohs(*recorddata++); + srv.port = ntohs(*recorddata++); + offset += 6; + srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + } + return srv; } -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr) { - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr) { + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; #ifdef __APPLE__ - addr->sin_len = sizeof(struct sockaddr_in); + addr->sin_len = sizeof(struct sockaddr_in); #endif - if ((size >= offset + length) && (length == 4)) - addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 4)) + addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); + return addr; } -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr) { - memset(addr, 0, sizeof(struct sockaddr_in6)); - addr->sin6_family = AF_INET6; +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr) { + memset(addr, 0, sizeof(struct sockaddr_in6)); + addr->sin6_family = AF_INET6; #ifdef __APPLE__ - addr->sin6_len = sizeof(struct sockaddr_in6); + addr->sin6_len = sizeof(struct sockaddr_in6); #endif - if ((size >= offset + length) && (length == 16)) - addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 16)) + addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); + return addr; } -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity) { - size_t parsed = 0; - const char* strdata; - size_t separator, sublength; - size_t end = offset + length; - - if (size < end) - end = size; - - while ((offset < end) && (parsed < capacity)) { - strdata = (const char*)buffer + offset; - sublength = *(const unsigned char*)strdata; - - ++strdata; - offset += sublength + 1; - - separator = 0; - for (size_t c = 0; c < sublength; ++c) { - //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] - if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) - break; - if (strdata[c] == '=') { - separator = c; - break; - } - } - - if (!separator) - continue; - - if (separator < sublength) { - records[parsed].key.str = strdata; - records[parsed].key.length = separator; - records[parsed].value.str = strdata + separator + 1; - records[parsed].value.length = sublength - (separator + 1); - } - else { - records[parsed].key.str = strdata; - records[parsed].key.length = sublength; - } - - ++parsed; - } - - return parsed; +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity) { + size_t parsed = 0; + const char* strdata; + size_t separator, sublength; + size_t end = offset + length; + + if (size < end) end = size; + + while ((offset < end) && (parsed < capacity)) { + strdata = (const char*)buffer + offset; + sublength = *(const unsigned char*)strdata; + + ++strdata; + offset += sublength + 1; + + separator = 0; + for (size_t c = 0; c < sublength; ++c) { + // DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] + if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) break; + if (strdata[c] == '=') { + separator = c; + break; + } + } + + if (!separator) continue; + + if (separator < sublength) { + records[parsed].key.str = strdata; + records[parsed].key.length = separator; + records[parsed].value.str = strdata + separator + 1; + records[parsed].value.length = sublength - (separator + 1); + } else { + records[parsed].key.str = strdata; + records[parsed].key.length = sublength; + } + + ++parsed; + } + + return parsed; } #ifdef _WIN32 |