Search code examples
cudpnetstatmulticastsocketss

How to enable ss(another utility to investigate sockets) to see the joined multicast group IP address on a Linux host?


I have access to an internal tool which can be used to join a multicast IP:PORT and capture packets as a pcap file but the tool doesn't come with implementation.

When I run the tool, both netstat and ss can be used to see the joined multicast IP address.

For example:

$ netstat -gn|grep 224.0.115.66
sfc2            1      224.0.115.66

$ ss -uan|grep 224.0.115.66
UNCONN 0      0       224.0.115.66:6000      0.0.0.0:*

I have written a simple c code that can be used to join a multicast group. The issue I have is that when I run my application, only netstat can find the joined multicast group but ss.

$ netstat -gn|grep 224.0.115.66
sfc2            1      224.0.115.66

$ ss -uan|grep 224.0.115.66

Question> I assume there must be some extra configurations I have to do in order to enable ss to see the joined multicast group IP address. Can someone tell me whether there is any special handling I have to incorporate into the code so that ss can detect the joined multicast group IP:PORT similar as what netstat can do?

Thank you

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>

int main() {
    struct sockaddr_in multicast_addr;
    struct ip_mreq mreq;
    int sockfd;

    // Create a UDP socket
    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        exit(1);
    }

    // Set up the multicast address structure
    memset(&multicast_addr, 0, sizeof(multicast_addr));
    multicast_addr.sin_family = AF_INET;
    multicast_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    multicast_addr.sin_port = htons(6000);

    // Bind the socket to the multicast address
    if (bind(sockfd, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)) < 0) {
        perror("bind");
        exit(1);
    }

    // Join the multicast group
    memset(&mreq, 0, sizeof(mreq));
    mreq.imr_multiaddr.s_addr = inet_addr("224.0.115.66");
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt");
        exit(1);
    }

    printf("Joined multicast group successfully\n");

    // You can now receive data from the multicast group using this socket
    // do sth thing here so that the application doesn't immediately exit!!!
    
    // Close the socket when done
    close(sockfd);

    return 0;
}

Solution

  • The problem is that netstat -ng and ss -uan don't do the same thing.

    Running netstat -ng gives you the list of joined multicast groups. In contrast, ss -uan gives you the list of all open UDP sockets. The latter is the same as netstat -uan.

    The internal tool you reference is probably binding the socket directly to the multicast address which is why the multicast address shows up in the ss -uan list. This by itself however doesn't mean it's joined the multicast group. The output of netstat -ng is what tells you that. Your program is binding to 0.0.0.0 which is why the multicast address doesn't show up there.

    It turns out that ss doesn't have an option to show the joined multicast groups. An alternative tool that does show that would be ip maddress.

    So it's not that your program is doing something wrong, you're just using the wrong tool.