Can't send multicast packets in Linux

Jason
2010-01-01
2013-10-25
  • Jason
    Jason
    2010-01-01

    I've found my way here from another software package that use JmDNS and I find that this program does not work for me in Linux. I've downloaded version 3.0, and when I run it I receive an exception:

    :~/code/jmdns-3.0 5> java -jar lib/jmdns.jar -browse 
    TYPE: _http._tcp.local. 
    TYPE: _ftp._tcp.local. 
    TYPE: _tftp._tcp.local. 
    TYPE: _ssh._tcp.local. 
    TYPE: _smb._tcp.local. 
    TYPE: _printer._tcp.local. 
    TYPE: _airport._tcp.local. 
    TYPE: _afpovertcp._tcp.local. 
    TYPE: _ichat._tcp.local. 
    TYPE: _eppc._tcp.local. 
    TYPE: _presence._tcp.local. 
    TYPE: _rfb._tcp.local. 
    TYPE: _daap._tcp.local. 
    TYPE: _touchcs._tcp.local. 
    Dec 31, 2009 7:11:34 PM javax.jmdns.impl.tasks.Prober run 
    WARNING: run() exception 
    java.io.IOException: Network is unreachable 
            at java.net.PlainDatagramSocketImpl.send(Native Method) 
            at java.net.DatagramSocket.send(DatagramSocket.java:612) 
            at javax.jmdns.impl.JmDNSImpl.send(JmDNSImpl.java:1158) 
            at javax.jmdns.impl.tasks.Prober.run(Prober.java:171) 
            at java.util.TimerThread.mainLoop(Timer.java:512) 
            at java.util.TimerThread.run(Timer.java:462) 
    Dec 31, 2009 7:11:34 PM javax.jmdns.impl.JmDNSImpl recover 
    WARNING: recover() Start services exception  
    java.lang.IllegalThreadStateException 
            at java.lang.Thread.start(Thread.java:595) 
            at javax.jmdns.impl.JmDNSImpl.start(JmDNSImpl.java:290) 
            at javax.jmdns.impl.JmDNSImpl.recover(JmDNSImpl.java:1228) 
            at javax.jmdns.impl.tasks.Prober.run(Prober.java:184) 
            at java.util.TimerThread.mainLoop(Timer.java:512) 
            at java.util.TimerThread.run(Timer.java:462) 
    Dec 31, 2009 7:11:34 PM javax.jmdns.impl.JmDNSImpl recover 
    WARNING: recover() We are back!

    I've tracked down JmDNSImpl.java:1158 to this line of code: ms.send(packet);

    I'm not sure why it can't send the multicast packet. I have double checked, and my interface does support multicast:

    :~# ifconfig eth0 
    eth0      Link encap:Ethernet  HWaddr 00:ad:be:ef:be:eb 
              inet addr:192.168.0.5  Bcast:192.168.0.255  Mask:255.255.255.0 
              inet6 addr: fe80::dcad:beff:feef:beeb/64 Scope:Link 
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1 
              RX packets:569893 errors:0 dropped:0 overruns:0 frame:0 
              TX packets:79695 errors:0 dropped:0 overruns:0 carrier:0 
              collisions:0 txqueuelen:1000 
              RX bytes:172111849 (164.1 MiB)  TX bytes:10089548 (9.6 MiB) 
              Memory:ee000000-ee020000

    Further, I have attempted to ping the multicast address 224.0.0.1, and my wireless router (a Linksys WRT54GL) responds:

    :~# ping 224.0.0.1 
    PING 224.0.0.1 (224.0.0.1) 56(84) bytes of data. 
    64 bytes from 192.168.0.16: icmp_seq=1 ttl=64 time=0.763 ms 
    64 bytes from 192.168.0.16: icmp_seq=2 ttl=64 time=0.642 ms 
    64 bytes from 192.168.0.16: icmp_seq=3 ttl=64 time=0.670 ms 

    I am stuck at this moment. I've looked up the MulticastSocket documentation, and the DatagramSocket docs, and they do mention that the send() function can throw an IOException, but I don't get sufficient information as to why exactly this is being thrown.

    Thanks for any help you can give.

     
  • Jason
    Jason
    2010-01-02

    I have written a small Java program that shows this problem:

        import java.io.*;
        import java.net.*;

        class multicast
        {
          public static void main(String args) throws IOException
          {
            //Create socket.
            int port=5353;
            MulticastSocket socket=new MulticastSocket(port);
            //Create address structure.
            InetAddress group=InetAddress.getByName("224.0.0.251");
            String msg="Hello";
            //Join group.
            socket.joinGroup(group);
            //Send datagram.
            DatagramPacket packet = new DatagramPacket(msg.getBytes(), msg.length(), group, port);
            System.out.println("Exception on the next line.");
            socket.send(packet);
          }
        }

    This generates an exception every time:

        :~/code/multicast 44> javac multicast.java && java multicast
        Exception on the next line.
        Exception in thread "main" java.io.IOException: Network is unreachable
                at java.net.PlainDatagramSocketImpl.send(Native Method)
                at java.net.DatagramSocket.send(DatagramSocket.java:612)
                at multicast.main(multicast.java:19)

    Also, to prove that this isn't just a configuration issue with my computer, or a hardware problem, I also wrote a C++ program that does work:

        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netdb.h>
        #include <arpa/inet.h>
        #include <iostream>

        int main(int argv, char* argc)
        {
          //Create Socket.
          protoent* protocol=getprotobyname("udp");
          int sock=socket(PF_INET, SOCK_DGRAM, protocol->p_proto);
          if(sock==-1) { std::cout << "Error creating socket\n"; exit(1); }
          //Create address structure.
          sockaddr_in mdns_addr;
          mdns_addr.sin_family=AF_INET;
          mdns_addr.sin_port=htons(5353);
          mdns_addr.sin_addr.s_addr=inet_addr("224.0.0.251");
          char message="Hello";
          //Join group.
          struct ip_mreq mreq;
          mreq.imr_multiaddr.s_addr=inet_addr("224.0.0.251");
          mreq.imr_interface.s_addr=INADDR_ANY;
          setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
          //Send datagram.
          int return_val=sendto(sock, message, sizeof(message), 0, (sockaddr*)&mdns_addr, sizeof(mdns_addr));
          if(return_val==-1) { std::cout << "Error sending message\n"; exit(1); }
        }

    When I run the C++ program it does not generate an error, and a WireShark capture shows that the interface does indeed send out a multicast datagram.

    I have also tried both programs without joining the multicast group, and the Java program still throws an IOException, and the C++ program still works.

    If I haven't said it, I am running Sun's Java 1.6:

        :~/code/multicast 47> javac -version
        javac 1.6.0_12
        :~/code/multicast 48> java -version
        java version "1.6.0_12"
        Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
        Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)

    If anyone can help me with this problem, I would appreciate it.

     
  • Jason
    Jason
    2010-01-02

    I have discovered the root cause of this problem. I had IPv6 configured on this computer. Since other devices that I communicate with do not support IPv6, I turned it off. This stopped the IOExceptions in JmDNS.

     
  • Rick Blair
    Rick Blair
    2010-01-02

    Glad you are up and running.

      This makes sense.

    Java 1.6 will prefer IPV6 over IPV4.  There is a setting that will
    reverse it.

    I will see what I can dig up.

     
  • Bruno
    Bruno
    2013-10-25

    This problems seems to be specific to trying to use an IPv6 multicast address on the loopback interface. This patch should fix this problem, without having to disable IPv6 altogether:

    --- a/src/main/java/javax/jmdns/impl/JmDNSImpl.java
    +++ b/src/main/java/javax/jmdns/impl/JmDNSImpl.java
    @@ -1537,7 +1537,7 @@ public class JmDNSImpl extends JmDNS implements DNSStatefulObject, DNSTaskStarte
                     }
                 }
                 final MulticastSocket ms = _socket;
    -            if (ms != null && !ms.isClosed()) {
    +            if (ms != null && !ms.isClosed() && !(_group instanceof Inet6Address && ms.getInterface().isLoopbackAddress())) {
                     ms.send(packet);
                 }
             }