3

My work is developing software for network capable cameras for retail enviroments. One of the peices of software my team is developing is a webserver that retrieves various reports generated in HTML by the camera itself (which has its own embedded webserver) and stored on the camera. Our software will then GET these reports from the camera and store it on a central webserver.

While we are fine plugging in the IPs of the cameras into our software, I am developing a simple Java class that will query the network and locate all cameras on the network.

The problem though is that while it runs just fine on my PC, and my coworker's PC, when we attempt to run it on the actual webserver PC that will host our software... it runs, but says every IP in the subnet is offline / unreachable EXCEPT for the gateway IP.

For example, if I run it from my PC or my coworkers PC when plugged into the closed LAN, I get the following active IPs found along with a flag telling me if its a camera or not. (gateway is 192.168.0.1, subnet mask is 255.255.255.0, which means full range of 256 devices to be looked for)

IP:/192.168.0.1  Active:true Camera:false
IP:/192.168.0.100  Active:true Camera:true    <- this is camera 1
IP:/192.168.0.101  Active:true Camera:true    <- this is camera 2
IP:/192.168.0.103  Active:true Camera:false   <- my PC
IP:/192.168.0.104  Active:true Camera:false   <- this is our webserver

But for some reason, when running the same program from the webserver PC, using the same JRE, I only get the following found

IP:/192.168.0.1  Active:true Camera:false

Now my code, instead of enumerating through each IP in order on the main Thread, instead creates a seperate Thread for each IP to be checked and runs them concurrently (else it would take little over 21 minutes to enumerate through the entire IP range at a timeout of 5000ms / IP). The main Thread then re-runs these IP scan threads every 15 seconds over and over.

I have checked that all the threads are running to completion on all the PCs, no exceptions are being thrown. Even verified that none of the threads are getting stuck. Each Thread takes about 5001 to 5050ms from start to complete, and those Threads that have an active IP finish sooner (>5000ms), so I know that its correctly waiting the full 5000ms in the ipAddr.isReachable(5000) method.

Me and my coworker are stumped at this point while it seems to reach those active IPs fine when run on our PCs, yet getting no response from the webserver PC???

We have ruled out firewall issues, admin access issues, etc.. The only difference is that our webserver is Embedded Win XP, and our PCs are Windows 7.

This has us stumped. Any ideas why?

Below is the code that is running each IP Thread:

public void CheckIP() {
new Thread() {
    @Override
    public void run() {
        try {
            isActive = ipAddr.isReachable(5000);
            if (isActive) {
                if (!isCamera) {
                    isCamera = new IpHttpManager().GetResponse(ipAddr.toString());
                }
            } else {
                isCamera = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}.start();

}

EDIT: Here is the code that builds each IP to check after determining the range based on gateway and subnet...

for(int i=subMin; i<=subMax; i++) {
byte[] ip = new byte[] {(byte)oct[0],(byte)oct[1],(byte)oct[2],(byte)i};
try {
    scanners[subCount] = new IpScan(InetAddress.getByAddress(ip));
    subCount++;
} catch (UnknownHostException e) {
    e.printStackTrace();
}}
Jgregoire108
  • 109
  • 1
  • 9
  • can you ping your machine from the webserver? – BevynQ Sep 26 '13 at 22:30
  • Have you done any network tracing with Wireshark? This is the best starting point. Install it on the server and determine if the packets are going out the correct interface, and if there is any response. I presume the traffic is going through a switch to the cameras. Attach a laptop with Wireshark to the tap/mirror port and see where the packets are going. – Jim Garrison Sep 26 '13 at 22:51
  • @BevynQ Yes, I can ping it. At Jim: Will check that out. I had thought the same thing as well, that the packets being sent from the webserver are different. – Jgregoire108 Sep 26 '13 at 23:01
  • Alternatively you can try http://www.icmp4j.org/ – kervin Jul 13 '15 at 13:37

2 Answers2

4

Thanks everyone, but I never did figure out or pinpoint why this oddity was happening. Everything I checked for was not the cause, so this question can be closed.

In any case, I ended up working around it completely. Instead of using InetAddress, I just went native and built my own ICMP ping class instead, via JNA, invoking Windows libraries IPHLPAPI.DLL and WSOCK32.DLL. Here is what I used...

public interface InetAddr extends StdCallLibrary {
    InetAddr INSTANCE = (InetAddr) 
            Native.loadLibrary("wsock32.dll", InetAddr.class);

    ULONG inet_addr(String cp);                     //in_addr creator. Creates the in_addr C struct used below
}

public interface IcmpEcho extends StdCallLibrary {
    IcmpEcho INSTANCE = (IcmpEcho)
            Native.loadLibrary("iphlpapi.dll", IcmpEcho.class);

    int IcmpSendEcho(
            HANDLE IcmpHandle,                      //Handle to the ICMP
            ULONG DestinationAddress,               //Destination address, in the form of an in_addr C Struct defaulted to ULONG
            Pointer RequestData,                    //Pointer to the buffer where my Message to be sent is
            short RequestSize,                      //size of the above buffer. sizeof(Message)
            byte[] RequestOptions,                  //OPTIONAL!! Can set this to NULL
            Pointer ReplyBuffer,                    //Pointer to the buffer where the replied echo is written to
            int ReplySize,                          //size of the above buffer. Normally its set to the sizeof(ICMP_ECHO_REPLY), but arbitrarily set it to 256 bytes
            int Timeout);                           //time, as int, for timeout

    HANDLE IcmpCreateFile();                        //win32 ICMP Handle creator

    boolean IcmpCloseHandle(HANDLE IcmpHandle);     //win32 ICMP Handle destroyer
}

And then using those to create the following method...

public void SendReply(String ipAddress) {
    final IcmpEcho icmpecho = IcmpEcho.INSTANCE;
    final InetAddr inetAddr = InetAddr.INSTANCE;
    HANDLE icmpHandle = icmpecho.IcmpCreateFile();
    byte[] message = new String("thisIsMyMessage!".toCharArray()).getBytes();
    Memory messageData = new Memory(32);                    //In C/C++ this would be: void *messageData = (void*) malloc(message.length);
    messageData.write(0, message, 0, message.length);       //but ignored the length and set it to 32 bytes instead for now
    Pointer requestData = messageData;
    Pointer replyBuffer = new Memory(256);
    replyBuffer.clear(256);

    // HERE IS THE NATIVE CALL!!
    reply = icmpecho.IcmpSendEcho(icmpHandle, 
            inetAddr.inet_addr(ipAddress), 
            requestData, 
            (short) 32, 
            null, 
            replyBuffer, 
            256, 
            timeout);
    // NATIVE CALL DONE, CHECK REPLY!!

    icmpecho.IcmpCloseHandle(icmpHandle);
}

public boolean IsReachable () {
    return (reply > 0);
}
Jgregoire108
  • 109
  • 1
  • 9
  • I know this is a super old post, but where is ULONG coming from? And what is reply? – Jdban101 Mar 24 '16 at 23:38
  • reply looks to be an int returned from IcmpSendEcho: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366050%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 for ULONG, I just turned it into a long and it seemed to work – Jdban101 Mar 30 '16 at 18:47
  • @Jdban101 Wow, this post of mine is old! I cant recall why I just used a java int instead of MS's ULONG, but in either case, it should be fine. the reply in actuality is just a DWORD which on my machine is a 32-bit unsigned integer, which matches the 32-bit size of java's int, which is more than enough space for a simple count of replies anyway – Jgregoire108 Apr 08 '16 at 17:30
0

My guess is that your iteration logic to determine the different ip address is based upon different configuration hence your pc's fetches all addresses but your webserver doesn't.

Try adding debug in the logic where you build up the list of ip adresses to check.

GerritCap
  • 1,570
  • 9
  • 8
  • I appreciate the response, but actually, I dont fetch the IP addresses, I only fetch the gateway and subnet mask, and then manually build each IP address to check from there. If I am unable to fetch the gateway, it defaults to 0.0.0.0 and terminates. Since I am able to get the gateway, it continues running. Odd part is that when it does run the scanning threads, I get a response from the gateway on the webserver, but none of the other addresses, while on the PCs, I get responses from the gateway and all active IPs – Jgregoire108 Sep 26 '13 at 23:15
  • But I did debug that part where it builds the IPs, as well as debug where each Thread starts and ends. Will add a code snip of where I build the IPs above – Jgregoire108 Sep 26 '13 at 23:17