Menu

Outgoing interface

Thomas
2016-09-19
2016-09-19
  • Thomas

    Thomas - 2016-09-19

    Hello,
    I have a multi-homed Linux machine, i.e. a machine that has more than one interface connected to a network (a wifi and a mobile broadband NIC in this particular case). What I want to do is to constantly ping a certain remote host via each of these adapters simultaneously to see which one's got the lowest RTT.

    With 'ping' I could simply specify the '-I <adapter>' argument to specify the network interface to emit the echo request and using java TCP-sockets I can do a bind() before a connect() to choose the desired outbound interface. However I'd like to have a similar thing using icmp4j. How can I get there?

    Thanks in advance!
    Best
    Thomas

     

    Last edit: Thomas 2016-09-19
  • laurent buhler

    laurent buhler - 2016-09-19

    Thomas,
    Icmp4j doesn't have this option!
    There is a lot of work to do in order to have it under every implementation!
    Which implementation you are using or planning to use ? (JNI/JNA/Java)

    L.

     

    Last edit: laurent buhler 2016-09-19
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-27

    I join to the Thomas question - i need to execute(in windows) command like "ping -S someSourceIP someHostP" programmatically, and after superficially learning the sample of how to using, i didn't find mentioned feature. Is it so hard to realize? it's very often used and necessary thing in everyday needs. I'm planning to use java.

     
  • Sal Ingrilli

    Sal Ingrilli - 2017-03-27

    ICMP4J has a WindowsProcessNativeBridge that spawsn ping.exe.
    I can make the changes to pass in the source address and include it in ping.exe.
    1. Will this work for you?
    2. What platforms can you to test on? XP Pro 32-bit, XP Pro 64-bit, Win7, Win8, WinX, ...?

     
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-27

    Thanks for you reply, Sal Ingrilli. Maybe i I spoke too abstractly. Let i explain you what i need. I have method in my code:

    public static boolean ping(String sourceIp, String hostIp) throws InterruptedException {
    
        // request
        final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest();
    
        request.setHost(hostIp );
        request.setTimeout(1000);
        // delegate
        final IcmpPingResponse response = IcmpPingUtil.executePingRequest(request);
        // log
        final String formattedResponse = IcmpPingUtil.formatResponse(response);
    
        if (formattedResponse.contains("TTL")) {
            System.out.println("Host ip :"+ hostIp + " available from source ip: " + sourceIp + "\n" + formattedResponse);
            Thread.sleep(1000);
            return true;
        } else {
            System.out.println("Host ip :" + hostIp + " IS NOT RESPONDED from source ip: " + sourceIp + "\n" + formattedResponse);
            Thread.sleep(1000);
            return false;
        }
    }
    

    but i can't assign the sourceIP, what you can reccomend ?
    I use Windows 8.1 x64

     

    Last edit: Dmitry Ilyushko 2017-03-27
  • Sal Ingrilli

    Sal Ingrilli - 2017-03-27

    I may be able to add something like this:
    request.setSource(sourceIp);

    Please run this command from a command prompt, and give me the full output:
    ping -n 1 -l 32 -w 1 -S <YOUR_SOURCE_IP> www.google.com

     
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-27

    C:\Users\ADM>ping -n 1 -l 32 -w 1 -S 192.168.0.77 192.168.0.238

    Pinging 192.168.0.238 from 192.168.0.77 with 32 bytes of data:
    Reply from 192.168.0.238: bytes=32 time=4ms TTL=64

    Ping statistics for 192.168.0.238:
    Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
    Minimum = 4ms, Maximum = 4ms, Average = 4ms

    In case, when i'm trying to ping my interesting host address 192.168.0.238
    everything works fine, but when i'm trying to ping www.google.com there some problems
    C:\Users\ADM>ping -n 1 -l 32 -w 1 -S 192.168.0.77 www.google.com

    Pinging www.google.com [74.125.232.209] from 192.168.0.77 with 32 bytes of data:

    PING: transmit failed.
    Ping statistics for 74.125.232.209:
    Packets: Sent = 1, Received = 0, Lost = 1 (100% loss),

     
    • laurent buhler

      laurent buhler - 2017-03-27

      Hey Dimitri,
      Can you get a more precise error message when you do
      ping -n 1 -l 32 -w 1 -S 192.168.0.77 www.google.com

      I am suprised it worked for ping -n 1 -l 32 -w 1 -S 192.168.0.77 192.168.0.238
      On OSX, the -S option is pretty strict; following is the description of the option from the man pages

      Use the following IP address as the source address in outgoing packets. On hosts with more than one IP address, this option can be used to force
      the source address to be something other than the IP address of the interface the probe packet is sent on. If the IP address is not one of this
      machine's interface addresses, an error is returned and nothing is sent.

      and you get error like:

      bind: Can't assign requested address
      
       
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-27

    It's good idea to add the method mentioned above like: request.setSource(sourceIp); - it will help me for my purposes and other developers. I think that adding that feature will very increase the good of your library.

     

    Last edit: Dmitry Ilyushko 2017-03-27
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-27
     
  • Sal Ingrilli

    Sal Ingrilli - 2017-03-28

    Dmitry, please try this beta build of 1021:
    http://secure.fileprotocol.com/dl?guid=932ECC05-9203-E594-00AD-0F9E23D7B0AE

    Make sure that you initialize icmp4j with this:

    Icmp4jUtil.initialize ();
    final NativeBridge nativeBridge = new WindowsProcessNativeBridge ();
    nativeBridge.initialize ();
    Icmp4jUtil.setNativeBridge (nativeBridge);
    

    This tells icmp4j to use the Windows ping.exe to issue the ping, and you will be able to set the source via:
    request.setSource (source);

    Please test on Windows 8.1 x64, and any other OS you can get your hands on...

     
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-28

    Okay, i have dowloaded your attachement and extracted archive. I have linked files icmp4j-all.jar, jna-3.5.1.jar, platform-3.5.1.jar from "\1021rc1\icmp4j-project\trunk\icmp4j\output\tool" and "\1021rc1\icmp4j-project\trunk\icmp4j\output\lib"(for the icmp4j.jar file) directories. to the my Netbeans project and rebuilt the code and try to lauch my code with your recomendations below:

    public static boolean ping(String sourceIp, String hostIp) throws InterruptedException {
            Icmp4jUtil.initialize ();
            final NativeBridge nativeBridge = new WindowsProcessNativeBridge ();
            nativeBridge.initialize ();
            Icmp4jUtil.setNativeBridge (nativeBridge);
            // request
            final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest();
            request.setSource(sourceIp);
    
            request.setHost(hostIp );
            request.setTimeout(1000);
            // delegate
            final IcmpPingResponse response = IcmpPingUtil.executePingRequest(request);
            // log
            final String formattedResponse = IcmpPingUtil.formatResponse(response);
    
            if (formattedResponse.contains("TTL")) {
                System.out.println("Host ip :"+ hostIp + " available from source ip: " + sourceIp + "\n" + formattedResponse);
                Thread.sleep(1000);
                return true;
            } else {
                System.out.println("Host ip :" + hostIp + " IS NOT RESPONDED from source ip: " + sourceIp + "\n" + formattedResponse);
                Thread.sleep(1000);
                return false;
            }
        }
    

    The output is:

    ~~~
    <2017-03-28 12:59:20> <INFO> <JnaUtil> <loadLibrary2 ()="">
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < strategy: native via java.library.path>
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < libraryName: icmp>
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < libraryClass: org.icmp4j.platform.windows.jna.IcmpLibrary>
    <2017-03-28 12:59:20> <INFO> <JnaUtil> <loadLibrary2 ()="">
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < strategy: native via java.library.path>
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < libraryName: ws2_32>
    <2017-03-28 12:59:20> <INFO> <JnaUtil> < libraryClass: org.icmp4j.platform.windows.jna.Winsock2Library>
    <2017-03-28 12:59:20> <DEBUG> <WindowsProcessUtil> <findWindowsRootDirectory ():="" looking="" up="" env="" var="" SystemRoot:="" C:\\windows="">
    command: "C:\windows\system32\ping.exe" -n 1 -l 32 -w 1000 -S 192.168.1.3 www.google.com
    Host ip :www.google.com IS NOT RESPONDED from source ip: 192.168.1.3
    Error:
    ~~~


    if i try to do the same thing in win console and i have got the positive result(See the picture)
    I use the Netbeans 8 IDE, Windows 8.1 x64

     

    Last edit: Dmitry Ilyushko 2017-03-28
    • laurent buhler

      laurent buhler - 2017-03-28

      Rather than looking for some strings in the result, you should use the response flags

      if (!response.getSuccessFlag() {
          // check if it timed out
          if (response.getTimeoutFlag()) {
              System.out.println("time out!");
          }
          else {
              System.out.println(response.getErrorMessage());
      }
      

      From your screen shot, looks you have a 4 to 9 ms round trip, so you should set time out accordingly, for example 10 ms

      request.setTimeout(10000);
      
       
      • Dmitry Ilyushko

        Dmitry Ilyushko - 2017-03-29

        laurent buhler,
        you right, parsing the output - is bad solution, I'll take your advice, thanks

         
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-28

    I tried to run my another custom ping method and everything fine:

    // Use this method to ping hosts on Windows or other platforms, withrespond timeout of 3 secs

    public static boolean ping2(String sourceIp, String hostIp) throws IOException, InterruptedException {
        while (!Thread.currentThread().isInterrupted()) {
            boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
            //ProcessBuilder processBuilder = new ProcessBuilder("ping", "-S", sourceIp, hostIp, "-w 1000"); 
            ProcessBuilder processBuilder = new ProcessBuilder("ping", isWindows ? "-S" : "-I", sourceIp, hostIp);
            final Process proc = processBuilder.start();
            long str = System.currentTimeMillis();
    
            proc.waitFor();
    
            InputStream is = proc.getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "CP866");
            BufferedReader br = new BufferedReader(isr);
            String line;
    
            while ((line = br.readLine()) != null) {
    
                if (line.contains("TTL")) {
                    System.out.println("Host " + hostIp + " available from ip " + sourceIp);
                    long end = System.currentTimeMillis();
                    System.out.println("process elapsed time = " + (float) (end - str) + " ms");
                    System.out.println("------------------------------------------------------------");
                    return true;
                }
    
            }
        }
        return false;
    }
    

    Output:

    Host www.google.com available from ip 192.168.1.3
    process elapsed time = 3063.0 ms
    

    It's taken from the error output:

    command: "C:\windows\system32\ping.exe" -n 1 -l 32 -w 1000 -S 192.168.1.3 www.google.com
    Host ip :www.google.com IS NOT RESPONDED from source ip: 192.168.1.3

    And there's a question - how i can get access to the notorious "command" from the code
    I don't want to set some parameters for the native ping, for example i don't want to set parameter "-w 1" or "-w 1000" How can i change the sended packet from my code?

     

    Last edit: Dmitry Ilyushko 2017-03-28
  • Sal Ingrilli

    Sal Ingrilli - 2017-03-28

    Dmitry,
    Here are some more changes:
    http://secure.fileprotocol.com/dl?guid=0F5C2869-F5EF-4714-16DD-A63AAF4DFCCF

    Please test it with something similar to this:

    final NativeBridge nativeBridge = new WindowsProcessNativeBridge ();
    nativeBridge.initialize ();
    Icmp4jUtil.setNativeBridge (nativeBridge);
    Icmp4jUtil.initialize ();
    
    // request
    final IcmpPingRequest request = IcmpPingUtil.createIcmpPingRequest ();
    request.setCharsetName ("CP866");
    request.setHost ("www.google.com");
    request.setSource ("192.168.1.3");
    request.setTimeout (30000);
    
    // ping
    final IcmpPingResponse response = IcmpPingUtil.executePingRequest (request);
    final String formattedResponse = IcmpPingUtil.formatResponse (response);
    System.out.println (formattedResponse);
    
    // print the command and its output
    final String command = response.getCommand ();
    System.out.println ("command: " + command);
    
    final String output = response.getOutput ();
    System.out.println ("<output>");
    System.out.println (output);
    System.out.println ("</output>");
    

    I tested with the ping output that you gave earlier, and the parsing works.
    So if this does not work for you, give me the full output of this test.
    BTW, I think your test failed because you set a timeout of 1000 msecs, and that may not be enough in your case.

     
  • Dmitry Ilyushko

    Dmitry Ilyushko - 2017-03-29

    Sal,
    I have tested your new update, and it works in my case, even if doing
    request.setTimeout (1000);
    not:
    request.setTimeout (30000);
    Thank you very much!

     

    Last edit: Dmitry Ilyushko 2017-03-29

Log in to post a comment.