diff options
| author | cbdev <cb@cbcdn.com> | 2020-04-24 23:28:24 +0200 | 
|---|---|---|
| committer | cbdev <cb@cbcdn.com> | 2020-04-24 23:28:24 +0200 | 
| commit | 4a575cd3c466abfccf4516f5e9f6eacd534f4dc1 (patch) | |
| tree | 474b538efcfb6b1ae57e6e7b2191edcbdc2878cf /backends | |
| parent | ff785c5c5a300d01b404c48335de7f68ad8711a9 (diff) | |
| download | midimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.tar.gz midimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.tar.bz2 midimonster-4a575cd3c466abfccf4516f5e9f6eacd534f4dc1.zip  | |
Set MCAST_LOOP/IPV6_V6ONLY only on supported sockets, select outbound multicast interfaces properly
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/libmmbackend.c | 4 | ||||
| -rw-r--r-- | backends/rtpmidi.c | 44 | 
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);  | 
