From dd90f0a2283e6feb36d553b32f96efae0999a916 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 12 Apr 2020 12:11:32 +0200 Subject: Move sockaddr_ntop implementation to libmmbackend --- backends/libmmbackend.c | 50 +++++++++++++++++++++++++++++++++++++++++++------ backends/libmmbackend.h | 4 +++- backends/rtpmidi.c | 47 +++++++++++++++++++--------------------------- backends/rtpmidi.md | 3 +++ 4 files changed, 69 insertions(+), 35 deletions(-) diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index 1624f56..2bbc226 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -17,7 +17,7 @@ int mmbackend_strdup(char** dest, char* src){ return 0; } -char* mmbackend_sockstrerror(int err_no){ +char* mmbackend_socket_strerror(int err_no){ #ifdef _WIN32 static char error[2048] = ""; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), @@ -28,6 +28,44 @@ char* mmbackend_sockstrerror(int err_no){ #endif } +const char* mmbackend_sockaddr_ntop(struct sockaddr* peer, char* buffer, size_t length){ + union { + struct sockaddr* in; + struct sockaddr_in* in4; + struct sockaddr_in6* in6; + } addr; + addr.in = peer; + #ifdef _WIN32 + uint8_t* data = NULL; + #endif + + switch(addr.in->sa_family){ + //inet_ntop has become available in the winapi with vista, but eh. + #ifdef _WIN32 + case AF_INET6: + data = addr.in6->sin6_addr.s6_addr; + snprintf(buffer, length, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], + data[8], data[9], data[10], data[11], + data[12], data[13], data[14], data[15]); + return buffer; + case AF_INET: + data = (uint8_t*) &(addr.in4->sin_addr.s_addr); + snprintf(buffer, length, "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); + return buffer; + #else + case AF_INET6: + return inet_ntop(addr.in->sa_family, &(addr.in6->sin6_addr), buffer, length); + case AF_INET: + return inet_ntop(addr.in->sa_family, &(addr.in4->sin_addr), buffer, length); + #endif + default: + snprintf(buffer, length, "Socket family not implemented"); + return buffer; + } +} + void mmbackend_parse_hostspec(char* spec, char** host, char** port, char** options){ size_t u = 0; @@ -118,18 +156,18 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin //set required socket options yes = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0){ - LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_socket_strerror(errno)); } if(mcast){ yes = 1; if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){ - LOGPF("Failed to enable SO_BROADCAST on socket: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to enable SO_BROADCAST on socket: %s", mmbackend_socket_strerror(errno)); } yes = 0; if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){ - LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_socket_strerror(errno)); } } @@ -167,7 +205,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin #else int flags = fcntl(fd, F_GETFL, 0); if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0){ - LOGPF("Failed to set socket nonblocking: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to set socket nonblocking: %s", mmbackend_socket_strerror(errno)); close(fd); return -1; } @@ -185,7 +223,7 @@ int mmbackend_send(int fd, uint8_t* data, size_t length){ sent = send(fd, data + total, 1, 0); #endif if(sent < 0){ - LOGPF("Failed to send: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to send: %s", mmbackend_socket_strerror(errno)); return 1; } total += sent; diff --git a/backends/libmmbackend.h b/backends/libmmbackend.h index 969de6f..557c243 100644 --- a/backends/libmmbackend.h +++ b/backends/libmmbackend.h @@ -5,6 +5,7 @@ #include //#define close closesocket #else +#include #include #include #endif @@ -21,7 +22,8 @@ /** Convenience functions **/ int mmbackend_strdup(char** dest, char* src); -char* mmbackend_sockstrerror(int err_no); +char* mmbackend_socket_strerror(int err_no); +const char* mmbackend_sockaddr_ntop(struct sockaddr* peer, char* buffer, size_t length); /** Networking functions **/ diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 581b16c..5d588bc 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -247,25 +247,9 @@ static int rtpmidi_wide_pfxcmp(wchar_t* haystack, char* needle){ } return 0; } - -//this has become available with vista for some reason... -static char* inet_ntop(int family, uint8_t* data, char* buffer, size_t length){ - switch(family){ - case AF_INET: - snprintf(buffer, length, "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); - break; - case AF_INET6: - snprintf(buffer, length, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7], - data[8], data[9], data[10], data[11], - data[12], data[13], data[14], data[15]); - break; - } - return buffer; -} #endif +//TODO this should be trimmed down a bit static int rtpmidi_announce_addrs(){ char repr[INET6_ADDRSTRLEN + 1]; union { @@ -314,7 +298,7 @@ static int rtpmidi_announce_addrs(){ memcpy(&cfg.address[cfg.addresses].addr, (addr.in->sa_family == AF_INET) ? (void*) &addr.in4->sin_addr.s_addr : (void*) &addr.in6->sin6_addr.s6_addr, (addr.in->sa_family == AF_INET) ? 4 : 16); - LOGPF("mDNS announce address %" PRIsize_t ": %s (from %S)", cfg.addresses, inet_ntop(addr.in->sa_family, cfg.address[cfg.addresses].addr, repr, sizeof(repr)), iter->FriendlyName); + LOGPF("mDNS announce address %" PRIsize_t ": %s (from %S)", cfg.addresses, mmbackend_sockaddr_ntop(addr.in, repr, sizeof(repr)), iter->FriendlyName); cfg.addresses++; } } @@ -324,7 +308,7 @@ static int rtpmidi_announce_addrs(){ struct ifaddrs* ifa = NULL, *iter = NULL; if(getifaddrs(&ifa)){ - LOGPF("Failed to get adapter address information: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to get adapter address information: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -348,7 +332,7 @@ static int rtpmidi_announce_addrs(){ memcpy(&cfg.address[cfg.addresses].addr, (addr.in->sa_family == AF_INET) ? (void*) &addr.in4->sin_addr.s_addr : (void*) &addr.in6->sin6_addr.s6_addr, (addr.in->sa_family == AF_INET) ? 4 : 16); - LOGPF("mDNS announce address %" PRIsize_t ": %s (from %s)", cfg.addresses, inet_ntop(addr.in->sa_family, cfg.address[cfg.addresses].addr, repr, sizeof(repr)), iter->ifa_name); + LOGPF("mDNS announce address %" PRIsize_t ": %s (from %s)", cfg.addresses, mmbackend_sockaddr_ntop(addr.in, repr, sizeof(repr)), iter->ifa_name); cfg.addresses++; } } @@ -410,7 +394,7 @@ static int rtpmidi_bind_instance(instance* inst, rtpmidi_instance_data* data, ch } if(getsockname(data->fd, (struct sockaddr*) &sock_addr, &sock_len)){ - LOGPF("Failed to fetch data port information: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to fetch data port information: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -1396,11 +1380,12 @@ static int rtpmidi_service(){ } //TODO bounds check all accesses -static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hdr, dns_name* name, dns_name* host){ +static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hdr, dns_name* name, dns_name* host, struct sockaddr* source){ dns_rr* rr = NULL; dns_rr_srv* srv = NULL; size_t u = 0, offset = sizeof(dns_header); uint8_t* session_name = NULL; + char peer_name[1024]; for(u = 0; u < hdr->questions; u++){ if(dns_decode_name(buffer, length, offset, name)){ @@ -1444,7 +1429,7 @@ static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hd } //we just use the packet's source as peer, because who would announce mdns for another host (also implementing an additional registry for this would bloat this backend further) - LOGPF("Detected possible peer %.*s on %s Port %d", session_name[0], session_name + 1, host->name, be16toh(srv->port)); + LOGPF("Detected possible peer %.*s on %s (%s) Port %d", session_name[0], session_name + 1, host->name, mmbackend_sockaddr_ntop(source, peer_name, sizeof(peer_name)), be16toh(srv->port)); offset -= sizeof(dns_rr_srv); } @@ -1462,8 +1447,12 @@ static int rtpmidi_handle_mdns(){ .alloc = 0 }, host = name; ssize_t bytes = 0; + struct sockaddr_storage peer_addr; + socklen_t peer_len = sizeof(peer_addr); - for(bytes = recv(cfg.mdns_fd, buffer, sizeof(buffer), 0); bytes > 0; bytes = recv(cfg.mdns_fd, buffer, sizeof(buffer), 0)){ + for(bytes = recvfrom(cfg.mdns_fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len); + bytes > 0; + bytes = recvfrom(cfg.mdns_fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len)){ if(bytes < sizeof(dns_header)){ continue; } @@ -1479,7 +1468,9 @@ static int rtpmidi_handle_mdns(){ //rfc6762 18.11: response code != 0 -> ignore DBGPF("%" PRIsize_t " bytes, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional", bytes, hdr->id, DNS_OPCODE(hdr->flags[0]), DNS_RESPONSE(hdr->flags[0]) ? "response" : "query", hdr->questions, hdr->answers, hdr->servers, hdr->additional); - rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host); + rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr); + + peer_len = sizeof(peer_addr); } free(name.name); @@ -1493,7 +1484,7 @@ static int rtpmidi_handle_mdns(){ return 0; } - LOGPF("Error reading from mDNS descriptor: %s", mmbackend_sockstrerror(errno)); + LOGPF("Error reading from mDNS descriptor: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -1567,12 +1558,12 @@ static int rtpmidi_start_mdns(){ //join ipv4 multicast group if(setsockopt(cfg.mdns_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){ - LOGPF("Failed to join IPv4 multicast group for mDNS, discovery may be impaired: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to join IPv4 multicast group for mDNS, discovery may be impaired: %s", mmbackend_socket_strerror(errno)); } //join ipv6 multicast group if(setsockopt(cfg.mdns_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (uint8_t*) &mcast6_req, sizeof(mcast6_req))){ - LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_socket_strerror(errno)); } //register mdns fd to core diff --git a/backends/rtpmidi.md b/backends/rtpmidi.md index d15c9b5..33fbe59 100644 --- a/backends/rtpmidi.md +++ b/backends/rtpmidi.md @@ -89,3 +89,6 @@ specifications in multiple cases. Due to the complexity involved in supporting t arising from this will be considered a bug only in cases where they hinder normal operation of the backend. mDNS discovery may announce flawed records when run on a host with multiple active interfaces. + +While this backend should be reasonably stable, there may be problematic edge cases simply due to the +enormous size and scope of the protocols and implementations required to make this work. -- cgit v1.2.3