receiving multicast on a server with multiple interfaces (linux) - linux

To receive a multicast on my not default NIC (dvb) I do the following:
open a socket (AF_INET, SOCK_DGRAM)
join the multicast address with IP_ADD_MEMBERSHIP on the dvb interface
bind the multicast address (note that a common error is to bind "0.0.0.0" and then receive on that socket even multicast you are not interested in) and the port
at this point the only way to receive the needed multicast packets is to add in the routing table a rule to reach the network where the sender is (another network) trough the dvb, as if the dvb needs to reply to the multicast sender; let say a sort of source sender multicast mode. Anyone knows what is going on? The problem is annoying to me because in principle I don't know the ip of sender.

You appear to be being stung by rp_filter reverse-path filtering. This drops packets if they arrive on an interface that doesn't have a route for the source address.
You can disable it on a per-interface basis with the sysctl /proc/sys/net/ipv4/conf/<if>/rp_filter.

bind the multicast address
That is definitely wrong. You must bind to an actual IP address of a real adapter, or 0.0.0.0.
note that a common error is to bind
"0.0.0.0"
That's not an error. THat is correct procedure unless you only want to listen to one IP address.
and then receive on that
socket even multicast you are not
interested in
I don't know what this means.
in principle I don't know the ip of sender
The IP address of the sender of any UDP datagram is available via the sockets API.

Related

Will linux discard multicast packets that are not in the same subnet?

I want to build an overlay network through VXLAN multicast to achieve communication between virtual machines, but I found that multicast packets can only be transmitted on the same subnet. In order to allow virtual machines on hosts that are not on the same subnet to communicate, I am thinking whether "capture and forward packets" would work. That is, grab a UDP packet with a destination address of 239.1.1.1 and a port of 4789 on hostA on network1, and send it to hostB on network2, and let hostB send the multicast packet. Then I found that the hosts on network2 all can catch this packet with wireshark, but no host corresponds to it. I wonder if Linux has a mechanism to discard fake multicast packets? If this is the case, how should this mechanism be prevented?
Unhandled, multicast is essentially broadcast. For IPv4 multicast that broadcast effect can be mitigated with IGMP. On switched networks with semi-intelligent switches there may be IGMP snooping functionality to further aid in this. Provided this exists, an end-device must subscribe to a multicast group by sending an IGMP join for the given group to "unfilter" that traffic towards itself. Routing multicast between subnets can be done with PIM or DVRMP implementations, or even static multicast routing daemons.
Only exception to this filtering is the 224.0.0.x range, which is reserved for link-local communication, usually IETF protocols. Traffic to these groups must never be filtered in any way.
Hence, to prevent filtering, either the end devices join the group (recommended!), or you send traffic to a group in the reserved range, e.g. on 224.0.0.1 the all-hosts group. (It's ugly and you may trigger ugly bugs on devices in the LAN, but it works.)

If there are no subscribers, does udp multicast put anything on the wire?

Suppose an application is writing to a udp multicast, and all subscribers quit (or perhaps no processes ever register to read the multicast). Does anything go out on the wire?
The source host always sends the datagram. It is up to the router to decide whether there are group members on the other side, and if so to forward the datagram, otherwise drop it.
The packet will always be sent out. IGMP messages, which contain information about hosts joining/leaving multicast groups, are typically only processed by routers so they know where to route multicast traffic. So hosts generally don't have that information.
Even then, routers may not forward IGMP messages but may have static multicast routes set up to forward certain traffic anyway. In that situation, multicast traffic could pass through routers to an intended destination even in the absence of IGMP.
Regarding which interface(s) the source host sends on, that's application defined behavior. The sending socket sets the IP_MULTICAST_IF or IPV6_MULTICAST_IF socket option to dictate which interface multicast traffic is sent out on. If this option is not set, the system chooses a default interface to send multicast packets out on.

Multicast packets are not sent if I use an address different from 224.0.0.1

I am using this code to experiment with multicast.
I have wireshark running on another PC in the LAN and I am trying to see the packets sent over the network.
If packets are sent to the IP address 224.0.0.1 they are correctly received, if I send them to the address 239.255.255.250 they are not.
I have this entry in my routing table
224.0.0.0/4 dev eth0.100 src 192.0.0.1
I know 192.0.0.1 looks weird, but it is the correct interface address
Do you know why packets are not being sent?
The PC that you are attempting to capture the multicast traffic most likely has multicast filtering enabled and has not enabled reception of the 239.255.255.250 group.
Any host device that communicates multicast joins the 224.0.0.1 (All Hosts group) so packets sent to that group pass the filter, but not packets sent to 239.255.255.250.
Multicast filtering is usually implemented in the network interface and received frames that don't pass the filter will be dropped in hardware instead of being passed up to the Kernel driver. If the frames are not passed to the Kernel, then Wireshark can not capture them.
You can verify the active multicast groups per interface with netstat. I'm assuming you're on a Linux system since you tagged the question with "Linux"
netstat -g
Multicast groups are joined when a socket enables the IP_ADD_MEMBERSHIP socket option. In order to join the group on your capturing device, you'll need a program that creates a socket and joins the multicast group using the IP_ADD_MEMBERSHIP socket option
To add to Joel Cunningham's answer in the case of switched LAN:
There's nothing listening for multicast on 239.255.255.250, thus no IGMP joins are sent out. thus the switch does not propagate these multicast frames to the port where you have the wireshark(1)-running PC.
Again, 226.0.0.1 is well known and is always joined to by all hosts.

listing multicast sockets

I am trying to list all opened multicast sockets on a linux system? netstat -g lists the groups joined though. Is there any other utility that I can use for this sake?
Thanks a lot for the help.
In addition to netstat -g you can use this to see all sockets which are bound to a multicast address:
netstat -anu|sort -nk4
This is a list of all UDP sockets (whether multicast or not). Look for all addresses in the range 224.0.0.0 to 239.255.255.255. These are sockets bound to multicast addresses, regardless whether they joined the multicast group or not. These will only receive traffic for this multicast group.
But:
In practice UDP sockets which are used to receive multicast traffic are usually bound to address 0.0.0.0. These can receive UDP packets for all unicast and multicast addresses, and the server usually does some additional filtering based on the source-IP-address.
So in that list above you may want to look also at UDP sockets bound to 0.0.0.0, for example 0.0.0.0:5353 which is most likely the mDNS (avahi, zeroconf) server.
I don't think there is a tool that can give you that information.
The reason is that a multicast socket is not bound to an address, it only participates in a multicast group (IP_ADD_MEMBERSHIP). A socket can join multiple different groups on the same interface, or same group on different interfaces, so it would make little sense to maintain these cross refences. The only information exposed by the kernel is in /proc/net, and in this case /proc/net/igmp (<- netstat -g).

Do I need a PORT when joining a multicast group or just the IP?

I would like to learn that once and for all. What is the procedure to connect a multicast socket? I know you have to bind to a local interface (do you need IP and port for that?) then I know you have to join a group (do you need IP:PORT for the address you want to join and the network interface again!!!??) and then finally you can leave the group.
Can someone with experience clarify what is the whole of those many addresses? I will list below:
BindAddress (IP:PORT)
NetworkAddress (IP:PORT)
MulticastAddress (IP:PORT)
Where and what is the multicast group here?
A multicast group is a special IP address. You join it via setsockopt() using the socket option IP_ADDMEMBERSHIP, or e.g. in Java via MulticastSocket.joinGroup(). No port number here. If you want to join via a specific local address, use the overload that specifies a local address, or call setNetworkInterface() first.
Binding to a local address is a separate operation, which primarily determines which local addresses the socket can send and receive data on: one, or all of them: either one local address, which determines which of your available subnets you are listening to and can send via, or a port, or both. Normally it is best to use INADDR_ANY as the bind-address, unless your application magically knows about the network topology.
This is muddied by the fact that you can bind to a multicast address in Linux, but this appears to be a misunderstanding that will now always be with us.
You send to a multicast group by sending to the multicast address.
Yes, you must define both the address and the port for sending/receiving multicast messages. These are UDP packets, so they require both address and port for the networking stack to be able to properly deliver the messages to participating processes. So to listen for a particular set of multicast messages, your application needs to bind to a particular multicast ip address and port combination (and obviously for a set or all interfaces on the machine). The group is defined by the address/port combination.
Good quick explanation
Some sample source code in C and other languages

Resources