Discussion:
Simple multicast question
(too old to reply)
Frank Kardel
2009-11-22 21:17:23 UTC
Permalink
Hi!

If I were to
1) create an IPv4, DGRAM (UDP) socket
2) bind that to 224.0.1.1
3) do a IP_ADD_MEMBERSHIP for address 224.0.1.1 and imr_interface =
INADDR_ANY on that socket
4) start recvmsg-ing on it

Would I be able to read the packets that I see via tcpdump going to
224.0.1.1 ?

The thing is I see the packets via tcpdump, IGMP seems to work
correctly, but nothing arrives in the
program. Am I missing something or do we have a multicast reception
problem in NetBSD
(even for older versions of -current)?
Short investigation gave that mcast packets can be dropped for the
mcast-address not being
in the receiving interface's mcast-address-list (ip_input.c) or when the
dst-addr/port is not found (udp_usrreq.c).

The interface is wm0 and ifconfig shows the multicast counter going up
as does the CANTFORWARD IP-statistics counter.

Frank

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Ivo Vachkov
2009-11-22 23:11:23 UTC
Permalink
I use something like this usually ...

int XXX_freebsd_joinmcast(in_addr_t mcast_addr, unsigned short int port) {
int mcast_s = -1, yes = 1;
struct sockaddr_in mcast_group;
struct ip_mreq mreq;

memset(&mcast_group, 0, sizeof(mcast_group));
mcast_group.sin_family = AF_INET;
mcast_group.sin_port = htons(port);
mcast_group.sin_addr.s_addr = mcast_addr;

if ((mcast_s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("recv socket");
return -1;
}

if (setsockopt(mcast_s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
perror("reuseaddr setsockopt");
return -1;
}

if (bind(mcast_s, (struct sockaddr*)&mcast_group, sizeof(mcast_group)) < 0){
perror("bind");
return -1;
}

memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr = mcast_group.sin_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

if (setsockopt(mcast_s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq)) < 0) {
perror("add_membership setsockopt");
return -1;
}

return mcast_s;
}

Hope you will be able to modify it according to your needs.

/ipv
Post by Frank Kardel
Hi!
If I were to
 1) create an IPv4, DGRAM (UDP) socket
 2) bind that to 224.0.1.1
 3) do a IP_ADD_MEMBERSHIP for address 224.0.1.1 and imr_interface =
INADDR_ANY on that socket
 4) start recvmsg-ing on it
Would I be able to read the packets that I see via tcpdump going to
224.0.1.1 ?
The thing is I see the packets via tcpdump, IGMP seems to work correctly,
but nothing arrives in the
program. Am I missing something or do we have a multicast reception problem
in NetBSD
(even for older versions of -current)?
Short investigation gave that mcast packets can be dropped for the
mcast-address not being
in the receiving interface's mcast-address-list (ip_input.c) or when the
dst-addr/port is not found (udp_usrreq.c).
The interface is wm0 and ifconfig shows the multicast counter going up as
does the CANTFORWARD IP-statistics counter.
Frank
--
"UNIX is basically a simple operating system, but you have to be a
genius to understand the simplicity." Dennis Ritchie

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Frank Kardel
2009-11-23 04:57:07 UTC
Permalink
Post by Ivo Vachkov
I use something like this usually ...
Thanks, close to what I use (except for REUSEADDR). But adding REUSEADDR
and thus disabling the delivery optimization didn't help either. That
needs more investigation
on my part.

My fragment now is (setting the bind address to INADDR_ANY on multicast
addresses).

fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

if (fd == -1)
{
errx(EXIT_FAILURE, "socket(2) failed");
}

printf("Binding to %s\n", argv[1]);
if (IN_CLASSD(ntohl(((struct sockaddr_in
*)ai->ai_addr)->sin_addr.s_addr)))
{
printf("MCAST ADD MEMBERSHIP: ");

memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr = ((struct sockaddr_in
*)ai->ai_addr)->sin_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr =
htonl(INADDR_ANY);
if (setsockopt(fd,
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
(char *)&mreq,
sizeof(mreq)))
{
printf("FAIL %s (%d)\n", strerror(errno), errno);
}
else
{
printf("SUCCESS\n");
}
}

if (bind(fd, ai->ai_addr, ai->ai_addrlen) == -1) ....


With that I see broadcast packets that are also flying around, but not
multicast packets yet.

Thanks,
Frank

--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Greg Troxel
2009-11-23 16:40:45 UTC
Permalink
Post by Frank Kardel
If I were to
1) create an IPv4, DGRAM (UDP) socket
2) bind that to 224.0.1.1
This seems bizarre to me. bind sets the source address, which is a
separate issue.
Post by Frank Kardel
3) do a IP_ADD_MEMBERSHIP for address 224.0.1.1 and imr_interface =
INADDR_ANY on that socket
that should join on the interface of the default route.
Post by Frank Kardel
4) start recvmsg-ing on it
The thing is I see the packets via tcpdump, IGMP seems to work
correctly, but nothing arrives in the
program. Am I missing something or do we have a multicast reception
Are you seeing IGMP membership reports from your box on the interface
you are seeing mcast on?
Post by Frank Kardel
problem in NetBSD
(even for older versions of -current)?
Short investigation gave that mcast packets can be dropped for the
mcast-address not being
in the receiving interface's mcast-address-list (ip_input.c) or when
the dst-addr/port is not found (udp_usrreq.c).
The interface is wm0 and ifconfig shows the multicast counter going up
as does the CANTFORWARD IP-statistics counter.
'netstat -ai' should be useful. but on a netbsd-5 box it isn't showing
OSPF groups joined even though ospf (quagga) is running fine.
David Arnold
2009-11-23 16:45:01 UTC
Permalink
Post by Greg Troxel
Post by Frank Kardel
2) bind that to 224.0.1.1
This seems bizarre to me. bind sets the source address, which is a
separate issue.
It is usually recommended to bind a socket intended to receive a single multicast group to that group's address in order to have the kernel discard unicast datagrams received addressed to the same port number.




d


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Mihai Chelaru
2009-11-23 17:55:30 UTC
Permalink
Post by David Arnold
It is usually recommended to bind a socket intended to receive a single
multicast group to that group's address in order to have the kernel
discard unicast datagrams received addressed to the same port number.
It is usually expected that bind(2) will bind an inet socket to a specific
address instead of filtering datagrams. I wrote a message [1] on this
mailist about 2 years ago about how multicast datagrams are matched in our
code and why it does look erroneous to me. I still believe that patch should
be checked in.

[1] - http://archive.netbsd.se/?ml=netbsd-tech-net&a=2007-12&m=5989732


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Robert Elz
2009-11-23 18:15:25 UTC
Permalink
Date: Mon, 23 Nov 2009 11:40:45 -0500
From: Greg Troxel <***@ir.bbn.com>
Message-ID: <***@fnord.ir.bbn.com>

| This seems bizarre to me. bind sets the source address, which is a
| separate issue.

It also sets a filter on incoming packets - only those addressed to the
bound address will be received (this is just obvious for TCP, which is
always bound once connected, but for UDP, it is less blatant, but the
same effect exists).

Note it isn't just multicast this applies to, but everything.

Since multicast addresses can't be source addresses, the source addr
setting part of bind is irrelevant there, and you're left with just the
incoming packet filter.

| 'netstat -ai' should be useful. but on a netbsd-5 box it isn't showing
| OSPF groups joined even though ospf (quagga) is running fine.

Try ifmcstat

kre


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...