4

Considering the code below,

I'm trying to bind a UDP socket for multicast.
I've bound it to a specific port, and set IP_ADD_MEMBERSHIP for the address to listen to.

My question: will the socket receive unicast UDP packets bound for that port? If so, how can I prevent it? I wish to only receive multicast.

int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
    perror("socket");
    exit(1);
}

u_int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
    perror("Reusing ADDR failed");
    exit(1);
}

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (source_iface.empty()
                          ? htonl(INADDR_ANY)
                          : inet_addr(source_iface.c_str()));

if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    perror("bind");
    exit(1);
}

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = (source_iface.empty()
                               ? htonl(INADDR_ANY)
                               : inet_addr(source_iface.c_str()));

if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
    perror("setsockopt");
    exit(1);
}
user207421
  • 305,947
  • 44
  • 307
  • 483
Yarel
  • 424
  • 1
  • 6
  • 15
  • Perhaps you want to look at the incoming packet's destination IP address (as described at https://stackoverflow.com/questions/5281409/get-destination-address-of-a-received-udp-packet ) and ignore the packet if that IP address is not a multicast IP address? (OTOH you might want to review *why* you don't want to receive unicast packets -- presumably they are being sent to you for a good reason) – Jeremy Friesner May 30 '18 at 02:40

2 Answers2

3

I believe you'll also need to bind on the particular multicast address on which you want to listen, and not just in the setsockopt call - the latter also being necessary to make sure that the network card and IGMP also do the right thing.

See also What does it mean to bind a multicast (UDP) socket?

Community
  • 1
  • 1
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • In the code, I see a `bind()` call although `INADDR_ANY` is probably wrong in this context... – Alexis Wilke May 30 '18 at 01:19
  • @AlexisWilke Well as INADDR_ANY isn't a multicast address, of course it is wrong in this context, if the solution provided is correct. – user207421 May 30 '18 at 02:13
0

Okay, I got my instance to work so I know what the problem was. The bind() has to occur against the multicast IP address:

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (group.empty()
                          ? htonl(INADDR_ANY)   // <-- this will work here but not below
                          : inet_addr(group.c_str()));

if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    perror("bind");
    exit(1);
}

The difference here is group instead of source_iface. Until I changed that, it would not receive broadcasted packets at all.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156