aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-04-24 23:28:24 +0200
committercbdev <cb@cbcdn.com>2020-04-24 23:28:24 +0200
commit4a575cd3c466abfccf4516f5e9f6eacd534f4dc1 (patch)
tree474b538efcfb6b1ae57e6e7b2191edcbdc2878cf
parentff785c5c5a300d01b404c48335de7f68ad8711a9 (diff)
downloadmidimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.tar.gz
midimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.tar.bz2
midimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.zip
Set MCAST_LOOP/IPV6_V6ONLY only on supported sockets, select outbound multicast interfaces properly
-rw-r--r--backends/libmmbackend.c4
-rw-r--r--backends/rtpmidi.c44
2 files changed, 40 insertions, 8 deletions
diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c
index 186cc66..bad048c 100644
--- a/backends/libmmbackend.c
+++ b/backends/libmmbackend.c
@@ -167,7 +167,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin
}
yes = dualstack ? 0 : 1;
- if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){
+ if(addr_it->ai_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){
LOGPF("Failed to %s dualstack operations on socket: %s", dualstack ? "enable" : "disable", mmbackend_socket_strerror(errno));
}
@@ -178,7 +178,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin
}
yes = 0;
- if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*) &yes, sizeof(yes)) < 0){
+ if(setsockopt(fd, addr_it->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6, addr_it->ai_family == AF_INET ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP, (void*) &yes, sizeof(yes)) < 0){
LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_socket_strerror(errno));
}
}
diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c
index eb08e8d..7c5aa69 100644
--- a/backends/rtpmidi.c
+++ b/backends/rtpmidi.c
@@ -1,5 +1,5 @@
#define BACKEND_NAME "rtpmidi"
-#define DEBUG
+//#define DEBUG
#include <string.h>
#include <errno.h>
@@ -15,6 +15,7 @@
#include <iphlpapi.h>
#else
#include <arpa/inet.h>
+#include <net/if.h>
#include <sys/types.h>
#include <ifaddrs.h>
#endif
@@ -47,6 +48,10 @@ static struct /*_rtpmidi_global*/ {
char* mdns_name;
char* mdns_interface;
+ #ifdef _WIN32
+ unsigned mdns_adapter;
+ unsigned mdns6_adapter;
+ #endif
uint8_t detect;
uint64_t last_service;
@@ -283,6 +288,13 @@ static int rtpmidi_announce_addrs(){
continue;
}
+ //for exact matches, use exactly this interface for multicasts
+ if(!strcmp(iface, cfg.mdns_interface)){
+ LOGPF("Using interface %s for mDNS discovery", iface);
+ cfg.mdns_adapter = iter->IfIndex;
+ cfg.mdns6_adapter = iter->Ipv6IfIndex;
+ }
+
for(unicast_addr = (IP_ADAPTER_UNICAST_ADDRESS_LH*) iter->FirstUnicastAddress; unicast_addr; unicast_addr = unicast_addr->Next){
addr.in = unicast_addr->Address.lpSockaddr;
#else
@@ -1437,7 +1449,7 @@ static int rtpmidi_apple_peermatch(uint8_t* session_raw, struct sockaddr* peer,
for(n = 0; n < cfg.invite[u].invites; n++){
if(!strcmp(cfg.invite[u].name[n], "*")){
done = 1;
- DBGPF("Peer %.*s implicitly invited on instance %s, converting to explicit invitation", session_name[0], session_name + 1, cfg.invite[u].inst->name);
+ DBGPF("Peer %s implicitly invited on instance %s, converting to explicit invitation", session_name, cfg.invite[u].inst->name);
if(rtpmidi_push_invite(cfg.invite[u].inst, session_name)){
return 1;
}
@@ -1524,6 +1536,9 @@ static int rtpmidi_handle_mdns(int fd){
ssize_t bytes = 0;
struct sockaddr_storage peer_addr;
socklen_t peer_len = sizeof(peer_addr);
+ #ifdef DEBUG
+ char peer_name[INET6_ADDRSTRLEN + 1];
+ #endif
for(bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len);
bytes > 0;
@@ -1542,10 +1557,11 @@ static int rtpmidi_handle_mdns(int fd){
//rfc6762 18.3: opcode != 0 -> ignore
//rfc6762 18.11: response code != 0 -> ignore
- DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional",
+ DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional, src %s",
bytes, (fd == cfg.mdns_fd ? '6' : '4'), hdr->id,
DNS_OPCODE(hdr->flags[0]), DNS_RESPONSE(hdr->flags[0]) ? "response" : "query",
- hdr->questions, hdr->answers, hdr->servers, hdr->additional);
+ hdr->questions, hdr->answers, hdr->servers, hdr->additional,
+ mmbackend_sockaddr_ntop((struct sockaddr*) &peer_addr, peer_name, sizeof(peer_name)));
rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr, peer_len);
peer_len = sizeof(peer_addr);
@@ -1605,9 +1621,15 @@ static int rtpmidi_handle(size_t num, managed_fd* fds){
}
static int rtpmidi_start_mdns(){
+ //use ip_mreqn where possible, but that renames the interface member
+ #ifdef _WIN32
struct ip_mreq mcast_req = {
- .imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb)),
- .imr_interface.s_addr = INADDR_ANY
+ .imr_interface.s_addr = INADDR_ANY,
+ #else
+ struct ip_mreqn mcast_req = {
+ .imr_address.s_addr = INADDR_ANY,
+ #endif
+ .imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb))
};
struct ipv6_mreq mcast6_req = {
@@ -1623,6 +1645,16 @@ static int rtpmidi_start_mdns(){
return 0;
}
+ if(cfg.mdns_interface){
+ #ifdef _WIN32
+ mcast6_req.ipv6mr_interface = cfg.mdns6_adapter;
+ mcast_req.imr_interface.s_addr = htobe32(cfg.mdns_adapter);
+ #else
+ mcast6_req.ipv6mr_interface = if_nametoindex(cfg.mdns_interface);
+ mcast_req.imr_ifindex = if_nametoindex(cfg.mdns_interface);
+ #endif
+ }
+
//FIXME might try passing NULL as host here to work around possible windows ipv6 handicaps
cfg.mdns_fd = mmbackend_socket(RTPMIDI_DEFAULT_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);
cfg.mdns4_fd = mmbackend_socket(RTPMIDI_DEFAULT4_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);