[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <9208AF0D0E6F444F80E90796B4E51CA07C163C10@EXCHANGE01.muppets.local>
Date: Mon, 23 Apr 2018 13:22:07 +0000
From: "Klebsch, Mario" <Mario.Klebsch@...-actia.de>
To: "netdev@...r.kernel.org" <netdev@...r.kernel.org>
Subject: IP_ADD_MEMBERSHIP with imr_ifindex!=0 for multiple processes with
different interfaces
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@...-actia.de Dresdenstrasse 17/18
Fon: +49 531 38 701 716 38124 Braunschweig
Fax: +49 531 38 701 88 Germany
Powered by blists - more mailing lists