* IP_ADD_MEMBERSHIP with imr_ifindex!=0 for multiple processes with different interfaces
@ 2018-04-23 13:22 Klebsch, Mario
2018-04-23 13:29 ` Eric Dumazet
0 siblings, 1 reply; 2+ messages in thread
From: Klebsch, Mario @ 2018-04-23 13:22 UTC (permalink / raw)
To: netdev@vger.kernel.org
Hi,
I have a problem with multicast reception in the linux kernel and I hope, this is the right place to ask for help or to report a bug.
I need to receive multicasts on a single interface. I have written a small program, which executes IP_ADD_MEMBERSHIP with imr.imr_ifindex set to the interface index. The program works well, as long as only a single instance of this program is running. If I start a second instance on a different network interface, both programs receive multicast frames from both interfaces.
When called without argument, the test program list the network interfaces. When called with an interface name as argument, if starts receiving multicasts on that interface.
I am running vanilla Linux kernel 4.12.0.
# uname -a
Linux c627 4.12.0 #1 SMP Mon Apr 23 14:08:24 CEST 2018 i686 Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz GenuineIntel GNU/Linux
#
P.S. The program runs fine on MacOSX.
73, Mario
----8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<----
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#define MCAST_PORT 6154
#define MCAST_ADDR "239.255.1.1"
void ListInterfaces(struct ifaddrs *Interfaces)
{
for (struct ifaddrs *a=Interfaces; a; a=a->ifa_next)
{
if (!(a->ifa_flags & IFF_UP))
continue;
if (!a->ifa_addr || a->ifa_addr->sa_family != AF_INET)
continue;
struct sockaddr_in *Addr = (struct sockaddr_in *)a->ifa_addr;
printf("%s: %s\n", a->ifa_name, inet_ntoa(Addr->sin_addr));
}
}
int main(int argc, char *argv[])
{
struct ifaddrs *Interfaces;
if (getifaddrs(&Interfaces) < 0)
{
perror("getifaddrs");
return -1;
}
struct sockaddr_in *MyIfAddr=NULL;
int MyIfIndex=0;
if (argc > 1 && (MyIfIndex = if_nametoindex(argv[1])) )
for (struct ifaddrs *a=Interfaces; a; a=a->ifa_next)
{
if (!(a->ifa_flags & IFF_UP))
continue;
if (!a->ifa_addr || a->ifa_addr->sa_family != AF_INET)
continue;
if (strcmp(argv[1], a->ifa_name)!= 0)
continue;
MyIfAddr = (struct sockaddr_in *)a->ifa_addr;
break;
}
if (!MyIfAddr || !MyIfIndex)
{
ListInterfaces(Interfaces);
return 0;
}
int s=socket(PF_INET, SOCK_DGRAM, 0);
if (s<0)
{
perror("socket");
return -1;
}
int off=0;
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &off, sizeof(off)) < 0)
perror("setsockopt(SO_REUSEADDR)");
int on=1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
perror("setsockopt(SO_REUSEADDR)");
struct sockaddr_in Addr;
Addr.sin_family = AF_INET;
Addr.sin_port = htons(MCAST_PORT);
inet_aton(MCAST_ADDR, &Addr.sin_addr);
if (bind(s, (struct sockaddr*)&Addr, sizeof(Addr)) < 0)
perror("bind");
struct ip_mreqn imr;
inet_aton(MCAST_ADDR, &imr.imr_multiaddr);
imr.imr_address = MyIfAddr->sin_addr;
imr.imr_ifindex = MyIfIndex;
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)) < 0)
perror("setsockopt(IP_ADD_MEMBERSHIP)");
for (;;)
{
struct sockaddr_in AddrBuffer;
int AddrLen = sizeof(AddrBuffer);
char Buffer[2048];
size_t BufferLen = recvfrom(s, &Buffer, sizeof(Buffer), 0, (struct sockaddr*)&AddrBuffer, & AddrLen);
if (BufferLen <= 0)
{
if (BufferLen < 0)
perror("recvfrom");
break;
}
printf("%s: Received %d bytes from %s\n", argv[1], BufferLen, inet_ntoa(AddrBuffer.sin_addr));
}
}
----8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<----
--
Mario Klebsch Actia I+ME GmbH
Mario.klebsch@ime-actia.de Dresdenstrasse 17/18
Fon: +49 531 38 701 716 38124 Braunschweig
Fax: +49 531 38 701 88 Germany
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: IP_ADD_MEMBERSHIP with imr_ifindex!=0 for multiple processes with different interfaces
2018-04-23 13:22 IP_ADD_MEMBERSHIP with imr_ifindex!=0 for multiple processes with different interfaces Klebsch, Mario
@ 2018-04-23 13:29 ` Eric Dumazet
0 siblings, 0 replies; 2+ messages in thread
From: Eric Dumazet @ 2018-04-23 13:29 UTC (permalink / raw)
To: Klebsch, Mario, netdev@vger.kernel.org
On 04/23/2018 06:22 AM, Klebsch, Mario wrote:
> Hi,
>
> I have a problem with multicast reception in the linux kernel and I hope, this is the right place to ask for help or to report a bug.
>
> I need to receive multicasts on a single interface. I have written a small program, which executes IP_ADD_MEMBERSHIP with imr.imr_ifindex set to the interface index. The program works well, as long as only a single instance of this program is running. If I start a second instance on a different network interface, both programs receive multicast frames from both interfaces.
>
> When called without argument, the test program list the network interfaces. When called with an interface name as argument, if starts receiving multicasts on that interface.
>
> I am running vanilla Linux kernel 4.12.0.
>
> # uname -a
> Linux c627 4.12.0 #1 SMP Mon Apr 23 14:08:24 CEST 2018 i686 Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz GenuineIntel GNU/Linux
> #
>
> P.S. The program runs fine on MacOSX.
>
It looks like your program needs to use SO_BINDTODEVICE if it really wants this device filtering ?
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2018-04-23 13:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-04-23 13:22 IP_ADD_MEMBERSHIP with imr_ifindex!=0 for multiple processes with different interfaces Klebsch, Mario
2018-04-23 13:29 ` Eric Dumazet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).