How to receive multicast join reports (IGMP v3)

723 Views Asked by At

I want to see which Multicast-Join-Reports fly through the network in which my host computer resides in. For that I've written a little TypeScript program, that joins the multicast group '224.0.0.22', which is defined in RFC3376 under 4.2.14 as the IP Destination for Multicast-Join-Reports. But I receive no requests even when I should, because I'am watching traffic via Wireshark and there Multicast-Join-Reports are send and received.

Edit 1: Attached is the receiving part:

const interfaces = os.networkInterfaces();

const IGMP_V3_REPORT_MULTICAST_ADDRESS = '224.0.0.22';
const socket = dgram.createSocket('udp4');

const ipv4Interface = interfaces['eth0'].find((i) => i.family === 'IPv4');

if (ipv4Interface) {
    socket.on('error', (e: Error) => {
        console.log(`${ifaceName}: socket error: ${e}`);
        sockResults[index] = false;
    });

    socket.on('listening', () => {
        const address = socket.address();
        console.log(`${ifaceName}: listening on ${address.address}:${address.port}`);

        console.log(`${ifaceName}: joining multicast group with address: ${IGMP_V3_REPORT_MULTICAST_ADDRESS} for local address: ${ipv4Interface.address}`);
        socket.addMembership(IGMP_V3_REPORT_MULTICAST_ADDRESS, ipv4Interface.address);
    })

    socket.on('message', (msg, rinfo) => {
        console.log(`${ifaceName}: got ${msg}`);
    });

    socket.bind(0);

    setTimeout(() => {
        console.log(`${ifaceName}: dropping multicast membership for ${IGMP_V3_REPORT_MULTICAST_ADDRESS}`);
        socket.dropMembership(IGMP_V3_REPORT_MULTICAST_ADDRESS,  ipv4Interface.address);

        console.log(`${ifaceName}: closing socket`);
        socket.close();

        resolve();
    }, 120 * 1000);
}
1

There are 1 best solutions below

3
On

Let's ignore IGMP, multicast-join, switches, and all that stuff for a moment, as you're already physically receiving the desired packets.

If you want to receive packets that are destined to 239.255.255.250, you're gonna have to use that address (and for UPnP the relevant port) in socket.bind().

These are all Python implementations, but hopefully converting to TypeScript won't be difficult: https://github.com/leslie-wang/py-multicast-example/blob/master/mcast.py and this.

Specifically, you need to:

socket.bind((MCAST_GRP, MCAST_PORT))

which in your case should be ('239.255.255.250', 1900), which are the default for UPnP.

Whereas, you are binding to "any available port" with socket.bind(0).

And I believe the parameters given to socket.addMembership(), should be the mcast group you want to receive messages from. The kernel, specifically the code that handles IP, needs to know to "forward" these packets upwards towards UDP.


By the way... there's also the option of sniffing instead of listening, in your use-case, but it may require higher privileges.