0

Related: Error "No such device" in call setsockopt

while stracing one of a unit test process (I am not the author of the unit test), I am encountering

socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP) = 8
setsockopt(8, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(8, SOL_IPV6, IPV6_ADD_MEMBERSHIP, "\377\2\0\0\0\0\0\0\0\0\0\0\0\0\0\373\2\0\0\0", 20) = -1 ENODEV (No such device)
close(8)                                = 0

On the related question, it is susepcting that MULTICAST is not enabled on the machine

However, I believe it is enabled in my environment as I see MULTICAST

eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:15 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1518 (1.4 KiB)  TX bytes:0 (0.0 b)

eth1      Link encap:Ethernet  HWaddr 02:42:0A:3C:73:A9  
          inet addr:10.60.115.169  Bcast:10.60.115.255  Mask:255.255.254.0
          inet6 addr: fd20:8b1e:b255:8136:42:aff:fe3c:73a9/64 Scope:Global
          inet6 addr: 2002:3984:3989::2/80 Scope:Global
          inet6 addr: fe80::42:aff:fe3c:73a9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
          RX packets:2797166513 errors:0 dropped:5 overruns:0 frame:0
          TX packets:1847378326 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:5442226175566 (4.9 TiB)  TX bytes:4392851979876 (3.9 TiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:861782 errors:0 dropped:0 overruns:0 frame:0
          TX packets:861782 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1 
          RX bytes:363667068 (346.8 MiB)  TX bytes:363667068 (346.8 MiB)

and

$ netstat -g
IPv6/IPv4 Group Memberships
Interface       RefCnt Group
--------------- ------ ---------------------
lo              1      all-systems.mcast.net
eth0            1      all-systems.mcast.net
eth1            1      all-systems.mcast.net
lo              1      ff02::1
lo              1      ff01::1
eth0            1      ff02::1
eth0            1      ff01::1
eth1            1      ff02::202
eth1            2      ff02::1:ff3c:73a9
eth1            1      ff02::1:ff00:2
eth1            1      ff02::1
eth1            1      ff01::1

Any idea why I am getting "No such device" in call setsockopt?

am i missing some options on /etc/sysctl.conf? I am running on RHEL7.4

I believe the code i am seeing it from

static int
create_ipv6_listener_socket(ifi_info* ifi)
{
    struct ipv6_mreq imr6;
    int err = 0;
    static const int kOn = 1;
    int skt = -1;

    std::string addr_str = sock_addr_to_string(ifi->ifi_ipv6_addr);
    TLOG_INFO(plogger, "Creating listener socket on addr %s", addr_str.c_str());

    skt = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    if (skt < 0) {
        TLOG_ERROR(plogger,
                   "Failed to create listener socket on addr %s: %d",
                   addr_str.c_str(),
                   errno);
        return -1;
    }

    err = setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
    if (err < 0) {
        TLOG_ERROR(plogger,
                   "For listener socket on %s, failed to set SO_REUSEADDR: %d",
                   addr_str.c_str(),
                   errno);
        close(skt);
        return -1;
    }

    imr6.ipv6mr_interface = ifi->ifi_index;
    err = inet_pton(AF_INET6, "FF02::FB", &imr6.ipv6mr_multiaddr);
    if (err < 1) { 
        TLOG_ERROR(plogger,
                   "For listener socket on %s, failed to assign dns-sd "
                   "multicast address: %d",
                   addr_str.c_str(),
                   errno);
        close(skt);
        return -1;
    }    

    err = setsockopt(skt, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
    if (err < 0) { 
        TLOG_ERROR(
            plogger,
            "For listener socket on %s, failed to join multicast group: %d",
            addr_str.c_str(),
            errno);
        close(skt);
        return -1;
    }  


static int
create_listener_socket(ifi_info* ifi)
{
    if (ifi->ifi_family == AF_INET) {
        return create_ipv4_listener_socket(ifi);
    } else if (ifi->ifi_family == AF_INET6) {
        return create_ipv6_listener_socket(ifi);
    } else {
        assert(false);
    }

    return -1;
}

static void
create_sockets()
{
    int skt = -1;
    std::vector<struct ifi_info*> interfaces;

    ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
    assert(ifi);
    strcpy(ifi->ifi_name, "fake_ipv6_ifi_info");
    ifi->ifi_family = AF_INET6;
    ifi->ifi_index = 2;
    interfaces.push_back(ifi);

    for (uint32_t ii = 0; ii < interfaces.size(); ++ii) {
        struct ifi_info* ifi = interfaces[ii];

        while ((skt = create_listener_socket(ifi)) == -1) {
            TLOG_ERROR(plogger,
                   "Failed to create a listener socket for interface %s; "
                   "will try again in 5 seconds",
                   ifi->ifi_name);
            sleep(5);
        }
        listener_sockets.push_back(skt);

I am getting error "For listener socket on INADDR_ANY, failed to join multicast group: 19"

ealeon
  • 12,074
  • 24
  • 92
  • 173
  • The final argument for IPV6_ADD_MEMBERSHIP is not a pointer to null-terminated string, but if this isn't your code and you can't fix it the question is off topic. – user207421 Jul 24 '18 at 22:29
  • 1
    @EJP `IPV6_ADD_MEMBERSHIP` doesn't take a string as input, it takes a pointer to an `ipv6_mreq` struct. The log is simply displaying the raw bytes of that struct in string format. – Remy Lebeau Jul 24 '18 at 22:32
  • @ealeon The second parameter of `setsockopt()` should be `IPPROTO_IPV6`. But more importantly, you are trying to join a multicast group of `FF02::FB` ([Multicast DNS](https://tools.ietf.org/html/rfc6762)) on interface index 2. Which of your interfaces is actually at index 2? Is it `lo` (local loopback), by chance? Have you tried using index 0 or 1 to access `eth0`/`eth1`? – Remy Lebeau Jul 24 '18 at 22:33
  • @RemyLebeau thank you for the reply. How did you figure out that it is "trying to join the multicast group IP of FF02::FB (Multicast DNS) on interface index 2" – ealeon Jul 24 '18 at 22:36
  • @RemyLebeau That's what I said. I don't know why you're repeating it back too me. If that isn't code the question is off topic. – user207421 Jul 24 '18 at 22:47
  • @EJP i think i found the code – ealeon Jul 24 '18 at 22:57
  • @ealeon "*How did you figure out ...*" - by reading the `IPV6_ADD_MEMBERSHIP` documentation, and looking at the bytes you showed from your strace log (which are logged in octal format). `IPV6_ADD_MEMBERSHIP` takes an `ipv6_mreq` struct as input, which is 20 bytes, containing 2 fields: a 16-byte `in6_addr` for the group IPv6 address, and a 4-byte interface index. Thus, `\377\2\0\0\0\0\0\0\0\0\0\0\0\0\0\373` is bytes `FF 02 00 00 00 00 00 00 00 00 00 00 00 00 00 FB` in hex, aka `FF02::FB` in IPv6 short notation, and `\2\0\0\0` is bytes `02 00 00 00` in hex, aka decimal 2 in integer form. – Remy Lebeau Jul 25 '18 at 01:47
  • @RemyLebeauah thank you. I am not still following 100%. FF is the 16-byte in6_addr and 02 is the 4-byte interface index? so bascially try using FF01::FB or FF00:FB instead of FF02:FB? – ealeon Jul 26 '18 at 15:54
  • @RemyLebeau i've tried FF00::FB and FF01:FB but no luck – ealeon Jul 26 '18 at 16:23
  • @RemyLebeau Also I think i narrowed down the code and concistently seeiing that error message "failed to join multicast group 19" – ealeon Jul 26 '18 at 16:27
  • @ealeon you are ignoring the other aspect of my earlier comment. You are focusing only on the `ipv6mr_multiaddr` to join, but what about the `ipv6mr_interface` that is joining from? Which of your interfaces does `ifi` represent? You can't join from `lo`, for instance. Did you check to make sure `ifi` points to `eth0` or `eth1`? And does that interface have a network route to the multicast broadcaster you are trying to join? – Remy Lebeau Jul 26 '18 at 17:29
  • @RemyLebeau thank you for your patience. i am really trying to understand. How do i check that ifi points to either eth0 or eth1, I assume it is based on the index. I've played around the index to 0,1,2 and 3. I assume that means I've tried with all of the interfaces. and as you can see from "netstat -g" doesnt that show that lo, eth0, and eth1 does have multicast broadcaster enabled noted by MULTICAST? – ealeon Jul 26 '18 at 17:29
  • @ealeon your logging leaves much to be desired. You should be logging the interface name and index that `ifi` says. Also, you can't join from `INADDR_ANY`, either, like your earlier error message says. You have to `bind()` your socket to a specific interface so it can receive packets, before you then join the group using that interface. You are not calling `bind()` at all. – Remy Lebeau Jul 26 '18 at 17:31
  • @RemyLebeau just to give more context. this code works without an issue in the production machine. i am trying to run it in my personal test machine which is failling. hence, i am assuming the code is fine. there must be some configurations with multicast and interfaces that my test machine is missing but i have no idea – ealeon Jul 26 '18 at 17:35
  • @RemyLebeau i found more code and it looks like it is defining the interface name? – ealeon Jul 26 '18 at 17:42

0 Answers0