Skip to content

Commit 4a575cd

Browse files
committed
Set MCAST_LOOP/IPV6_V6ONLY only on supported sockets, select outbound multicast interfaces properly
1 parent ff785c5 commit 4a575cd

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

backends/libmmbackend.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin
167167
}
168168

169169
yes = dualstack ? 0 : 1;
170-
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){
170+
if(addr_it->ai_family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){
171171
LOGPF("Failed to %s dualstack operations on socket: %s", dualstack ? "enable" : "disable", mmbackend_socket_strerror(errno));
172172
}
173173

@@ -178,7 +178,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin
178178
}
179179

180180
yes = 0;
181-
if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*) &yes, sizeof(yes)) < 0){
181+
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){
182182
LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_socket_strerror(errno));
183183
}
184184
}

backends/rtpmidi.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#define BACKEND_NAME "rtpmidi"
2-
#define DEBUG
2+
//#define DEBUG
33

44
#include <string.h>
55
#include <errno.h>
@@ -15,6 +15,7 @@
1515
#include <iphlpapi.h>
1616
#else
1717
#include <arpa/inet.h>
18+
#include <net/if.h>
1819
#include <sys/types.h>
1920
#include <ifaddrs.h>
2021
#endif
@@ -47,6 +48,10 @@ static struct /*_rtpmidi_global*/ {
4748

4849
char* mdns_name;
4950
char* mdns_interface;
51+
#ifdef _WIN32
52+
unsigned mdns_adapter;
53+
unsigned mdns6_adapter;
54+
#endif
5055

5156
uint8_t detect;
5257
uint64_t last_service;
@@ -283,6 +288,13 @@ static int rtpmidi_announce_addrs(){
283288
continue;
284289
}
285290

291+
//for exact matches, use exactly this interface for multicasts
292+
if(!strcmp(iface, cfg.mdns_interface)){
293+
LOGPF("Using interface %s for mDNS discovery", iface);
294+
cfg.mdns_adapter = iter->IfIndex;
295+
cfg.mdns6_adapter = iter->Ipv6IfIndex;
296+
}
297+
286298
for(unicast_addr = (IP_ADAPTER_UNICAST_ADDRESS_LH*) iter->FirstUnicastAddress; unicast_addr; unicast_addr = unicast_addr->Next){
287299
addr.in = unicast_addr->Address.lpSockaddr;
288300
#else
@@ -1437,7 +1449,7 @@ static int rtpmidi_apple_peermatch(uint8_t* session_raw, struct sockaddr* peer,
14371449
for(n = 0; n < cfg.invite[u].invites; n++){
14381450
if(!strcmp(cfg.invite[u].name[n], "*")){
14391451
done = 1;
1440-
DBGPF("Peer %.*s implicitly invited on instance %s, converting to explicit invitation", session_name[0], session_name + 1, cfg.invite[u].inst->name);
1452+
DBGPF("Peer %s implicitly invited on instance %s, converting to explicit invitation", session_name, cfg.invite[u].inst->name);
14411453
if(rtpmidi_push_invite(cfg.invite[u].inst, session_name)){
14421454
return 1;
14431455
}
@@ -1524,6 +1536,9 @@ static int rtpmidi_handle_mdns(int fd){
15241536
ssize_t bytes = 0;
15251537
struct sockaddr_storage peer_addr;
15261538
socklen_t peer_len = sizeof(peer_addr);
1539+
#ifdef DEBUG
1540+
char peer_name[INET6_ADDRSTRLEN + 1];
1541+
#endif
15271542

15281543
for(bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len);
15291544
bytes > 0;
@@ -1542,10 +1557,11 @@ static int rtpmidi_handle_mdns(int fd){
15421557
//rfc6762 18.3: opcode != 0 -> ignore
15431558
//rfc6762 18.11: response code != 0 -> ignore
15441559

1545-
DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional",
1560+
DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional, src %s",
15461561
bytes, (fd == cfg.mdns_fd ? '6' : '4'), hdr->id,
15471562
DNS_OPCODE(hdr->flags[0]), DNS_RESPONSE(hdr->flags[0]) ? "response" : "query",
1548-
hdr->questions, hdr->answers, hdr->servers, hdr->additional);
1563+
hdr->questions, hdr->answers, hdr->servers, hdr->additional,
1564+
mmbackend_sockaddr_ntop((struct sockaddr*) &peer_addr, peer_name, sizeof(peer_name)));
15491565
rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr, peer_len);
15501566

15511567
peer_len = sizeof(peer_addr);
@@ -1605,9 +1621,15 @@ static int rtpmidi_handle(size_t num, managed_fd* fds){
16051621
}
16061622

16071623
static int rtpmidi_start_mdns(){
1624+
//use ip_mreqn where possible, but that renames the interface member
1625+
#ifdef _WIN32
16081626
struct ip_mreq mcast_req = {
1609-
.imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb)),
1610-
.imr_interface.s_addr = INADDR_ANY
1627+
.imr_interface.s_addr = INADDR_ANY,
1628+
#else
1629+
struct ip_mreqn mcast_req = {
1630+
.imr_address.s_addr = INADDR_ANY,
1631+
#endif
1632+
.imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb))
16111633
};
16121634

16131635
struct ipv6_mreq mcast6_req = {
@@ -1623,6 +1645,16 @@ static int rtpmidi_start_mdns(){
16231645
return 0;
16241646
}
16251647

1648+
if(cfg.mdns_interface){
1649+
#ifdef _WIN32
1650+
mcast6_req.ipv6mr_interface = cfg.mdns6_adapter;
1651+
mcast_req.imr_interface.s_addr = htobe32(cfg.mdns_adapter);
1652+
#else
1653+
mcast6_req.ipv6mr_interface = if_nametoindex(cfg.mdns_interface);
1654+
mcast_req.imr_ifindex = if_nametoindex(cfg.mdns_interface);
1655+
#endif
1656+
}
1657+
16261658
//FIXME might try passing NULL as host here to work around possible windows ipv6 handicaps
16271659
cfg.mdns_fd = mmbackend_socket(RTPMIDI_DEFAULT_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);
16281660
cfg.mdns4_fd = mmbackend_socket(RTPMIDI_DEFAULT4_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);

0 commit comments

Comments
 (0)