* WindowsPinger now works

* LibraryLoader class introduced: now used by RawSocket and WindowsPinger
* JNI libraries are now always loaded from the classpath (or the jar file): lib dirs added to the classpath in eclipse project

git-svn-id: https://ipscan.svn.sourceforge.net/svnroot/ipscan/trunk@176 375186e5-ef17-0410-b0b6-91563547dcda
This commit is contained in:
angryziber 2007-07-24 21:33:44 +00:00
parent 21bfc726c6
commit 6832ae589d
15 changed files with 242 additions and 157 deletions

View File

@ -5,17 +5,14 @@
<classpathentry kind="src" path="ext/rocksaw/src/java"/>
<classpathentry kind="src" path="ext/vserv-tcpip/src/java"/>
<classpathentry kind="src" path="resources"/>
<classpathentry kind="src" path="ext/rocksaw/lib"/>
<classpathentry kind="src" path="ext/winping/lib"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="ext/rocksaw/lib/tmp.jar">
<attributes>
<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="ipscan/ext/rocksaw/lib"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="ext/picocontainer/picocontainer-1.0.jar"/>
<classpathentry kind="lib" path="ext/swt/swt-linux.jar" sourcepath="ext/swt/src-linux"/>
<classpathentry kind="lib" path="ext/swt/swt-mac.jar" sourcepath="ext/swt/src-mac"/>
<classpathentry kind="lib" path="ext/swt/swt-win32.jar" sourcepath="ext/swt/src-win32"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="ext/swt/swt-mac.jar" sourcepath="ext/swt/src-mac"/>
<classpathentry kind="lib" path="ext/easymock/easymock.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1,3 +1,4 @@
#Thu Jan 04 10:25:32 EET 2007
#Tue Jul 24 22:19:33 EEST 2007
eclipse.preferences.version=1
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
line.separator=\n

View File

@ -125,7 +125,8 @@
<mkdir dir="${bin}.@{platform}"/>
<unzip src="${ext}/picocontainer/picocontainer-1.0.jar" dest="${bin}"/>
<unzip src="${swt}/swt-@{platform}.jar" dest="${bin}.@{platform}"/>
<copy file="${ext}/rocksaw/lib/@{librocksaw}" todir="${bin}.@{platform}"/>
<copy file="${ext}/rocksaw/lib/@{librocksaw}" todir="${bin}.@{platform}"/>
<copy file="${ext}/winping/lib/winping.dll" todir="${bin}.win32"/>
<delete includeemptydirs="true" failonerror="false">
<fileset dir="${bin}/META-INF"/>
<fileset dir="${bin}/images" includes="**/*.svg"/>
@ -198,7 +199,7 @@
</target>
<target name="package-win32">
<package-for platform="win32" librocksaw="rocksaw.dll"/>
<package-for platform="win32" librocksaw="rocksaw.dll"/>
</target>
<target name="package-mac">

Binary file not shown.

View File

@ -19,14 +19,13 @@
package org.savarese.rocksaw.net;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import net.azib.ipscan.core.LibraryLoader;
/**
* <p>The RawSocket class provides a strictly utilitarian API for
* performing I/O with raw sockets. The API is currently crude, but
@ -79,8 +78,8 @@ public class RawSocket {
native static void __RockSawShutdown();
static {
// modified to reuse SWT's loading of jni libs from jar file
loadLibrary("rocksaw");
// modified to load jni libs from jar file
LibraryLoader.loadLibrary("rocksaw");
if(__RockSawStartup() != 0)
throw new UnsatisfiedLinkError(__getErrorMessage());
@ -151,41 +150,7 @@ public class RawSocket {
setUseSelectTimeout(false);
}
private static void loadLibrary(String library) {
String filename = System.mapLibraryName(library);
String fullFilename = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + filename;
try {
System.load(fullFilename);
}
catch (UnsatisfiedLinkError e) {
try {
// try to extract
InputStream is = RawSocket.class.getClassLoader().getResourceAsStream(filename);
byte[] buffer = new byte[4096];
OutputStream os = new FileOutputStream(fullFilename);
int read;
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
is.close();
if (!net.azib.ipscan.config.Platform.WINDOWS) {
// TODO: change this to new File(fullFilename).setExecutable(true) in case of Java 1.6
try {
Runtime.getRuntime ().exec (new String []{"chmod", "755", fullFilename}).waitFor();
} catch (Throwable t) {}
}
System.load(fullFilename);
}
catch (IOException ioe) {
throw new RuntimeException("Unable to extract native library: " + library, ioe);
}
}
}
/**
/**
* Tests if the socket has been opened.
*
* @return True if the socket is open.

View File

@ -1,93 +0,0 @@
/*
* Copyright 2007 Anton Keks
*/
#include <windows.h>
#include "WindowsPinger.h"
FARPROC IcmpCreateFile;
typedef BOOL (FAR WINAPI *TIcmpCloseHandle)(HANDLE IcmpHandle);
TIcmpCloseHandle IcmpCloseHandle;
typedef DWORD (FAR WINAPI *TIcmpSendEcho)(
HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
u_long DestAddress, /* destination IP address (in network order) */
LPVOID RequestData, /* pointer to buffer to send */
WORD RequestSize, /* length of data in buffer */
LPIPINFO RequestOptns, /* see Note 2 */
LPVOID ReplyBuffer, /* see Note 1 */
DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
DWORD Timeout /* time in milliseconds to wait for reply */
);
TIcmpSendEcho IcmpSendEcho;
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpCreateFile
*/
JNIEXPORT jint JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCreateFile
(JNIEnv *env, jclass cls)
{
HMODULE hICMP = LoadLibrary("icmp.dll");
if (!hICMP) {
// newer versions of Windows should include this one instead
hICMP = LoadLibrary("iphlpapi.dll");
}
if (!hICMP) {
return -1;
}
IcmpCreateFile = (FARPROC)GetProcAddress(hICMP, "IcmpCreateFile");
IcmpCloseHandle = (TIcmpCloseHandle)GetProcAddress(hICMP, "IcmpCloseHandle");
IcmpSendEcho = (TIcmpSendEcho)GetProcAddress(hICMP, "IcmpSendEcho");
return IcmpCreateFile();
}
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpCloseHandle
*/
JNIEXPORT jint JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCloseHandle
(JNIEnv *env, jclass cls, jint handle)
{
return IcmpCloseHandle(handle);
}
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpSendEcho
*/
JNIEXPORT jint JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpSendEcho
(JNIEnv *env, jclass cls, jint handle,
jbyteArray address, jbyteArray pingData, jbyteArray replyData, jint timeout)
{
DWORD replyCount;
IPINFO IPInfo;
jbyte *addrBuf, *pingDataBuf, replyDataBuf;
jclass replyClass;
jfieldID fid;
IPInfo.Ttl = 128;
IPInfo.Tos = 0;
IPInfo.Flags = 0;
IPInfo.OptionsSize = 0;
IPInfo.OptionsData = NULL;
addrBuf = env->GetByteArrayElements(env, address, NULL);
pingDataBuf = env->GetByteArrayElements(env, pingData, NULL);
replyDataBuf = env->GetByteArrayElements(env, replyData, NULL);
replyCount = IcmpSendEcho(handle, (DWORD)*addrBuf, pingDataBuf, env->GetArrayLength(pingData) * sizeof(jbyte),
&IPInfo, replyDataBuf, env->GetArrayLength(replyData), timeout);
env->ReleaseByteArrayElements(env, address, addrBuf, JNI_ABORT);
env->ReleaseByteArrayElements(env, pingData, pingDataBuf, JNI_ABORT);
env->ReleaseByteArrayElements(env, replyData, replyDataBuf, NULL);
return replyCount;
}

BIN
ext/winping/lib/winping.dll Normal file

Binary file not shown.

View File

@ -1,8 +1,13 @@
#
# This file is a part of Angry IP Scanner source code,
# see http://www.azib.net/ for more information.
# Licensed under GPLv2.
#
# Windows JNI pinger using Microsoft's ICMP.DLL
# Author: Anton Keks
#
# Copyright 2007 Anton Keks
#
DEST = ..\lib
JAVA_INCDIR = $(JDK_HOME)\include
JAVA_INCDIR_PLAF = $(JAVA_INCDIR)\win32
@ -22,10 +27,10 @@ CLEAN_EXTENSIONS = *.obj *.$(LIBEXTENSION) *.lib *.exp
all: $(LIBWINPING)
.c.obj:
$(CC) -nologo $(CFLAGS) $(CPPFLAGS) -c $< -o $@
$(CC) -nologo $(CFLAGS) $(CPPFLAGS) -c $< -o $(DEST)\$@
$(LIBWINPING): $(OBJ)
$(CC) -nologo -MD -LD -o $@ $**
$(CC) -nologo -MD -LD -o $(DEST)\$@ $**
clean:
del $(CLEAN_EXTENSIONS)

103
ext/winping/src/WindowsPinger.c Executable file
View File

@ -0,0 +1,103 @@
/*
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*
* Windows JNI pinger using Microsoft's ICMP.DLL
* Author: Anton Keks
*/
#include <windows.h>
#include "WindowsPinger.h"
FARPROC IcmpCreateFile = NULL;
typedef BOOL (FAR WINAPI *TIcmpCloseHandle)(HANDLE IcmpHandle);
TIcmpCloseHandle IcmpCloseHandle = NULL;
typedef DWORD (FAR WINAPI *TIcmpSendEcho)(
HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
u_long DestAddress, /* destination IP address (in network order) */
LPVOID RequestData, /* pointer to buffer to send */
WORD RequestSize, /* length of data in buffer */
LPVOID RequestOptns, /* see Note 2 */
LPVOID ReplyBuffer, /* see Note 1 */
DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
DWORD Timeout /* time in milliseconds to wait for reply */
);
TIcmpSendEcho IcmpSendEcho = NULL;
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpCreateFile
*/
JNIEXPORT jint JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCreateFile
(JNIEnv *env, jclass cls)
{
// Initialize dlls on first use
if (IcmpCreateFile == NULL) {
HMODULE hICMP = LoadLibrary("icmp.dll");
if (!hICMP) {
// newer versions of Windows should include this one instead
hICMP = LoadLibrary("iphlpapi.dll");
}
if (!hICMP) {
return -1;
}
IcmpCreateFile = (FARPROC) GetProcAddress(hICMP, "IcmpCreateFile");
IcmpCloseHandle = (TIcmpCloseHandle) GetProcAddress(hICMP, "IcmpCloseHandle");
IcmpSendEcho = (TIcmpSendEcho) GetProcAddress(hICMP, "IcmpSendEcho");
}
return IcmpCreateFile();
}
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpCloseHandle
*/
JNIEXPORT void JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCloseHandle
(JNIEnv *env, jclass cls, jint handle)
{
return IcmpCloseHandle((HANDLE)handle);
}
/*
* Class: net_azib_ipscan_core_net_WindowsPinger
* Method: nativeIcmpSendEcho
*/
JNIEXPORT jint JNICALL
Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpSendEcho
(JNIEnv *env, jclass cls, jint handle, jbyteArray address, jbyteArray pingData, jbyteArray replyData, jint timeout)
{
DWORD replyCount;
jbyte *addrBuf, *pingDataBuf, *replyDataBuf;
jint pingDataLen, replyDataLen;
jclass replyClass;
jfieldID fid;
u_long ip;
addrBuf = (*env)->GetByteArrayElements(env, address, NULL);
pingDataBuf = (*env)->GetByteArrayElements(env, pingData, NULL);
replyDataBuf = (*env)->GetByteArrayElements(env, replyData, NULL);
pingDataLen = (*env)->GetArrayLength(env, pingData);
replyDataLen = (*env)->GetArrayLength(env, replyData);
ip = *((u_long*)addrBuf);
replyCount = IcmpSendEcho((HANDLE)handle, ip, pingDataBuf, pingDataLen,
NULL, replyDataBuf, replyDataLen, timeout);
(*env)->ReleaseByteArrayElements(env, address, addrBuf, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, pingData, pingDataBuf, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, replyData, replyDataBuf, 0);
return replyCount;
}

View File

@ -1,3 +1,12 @@
/*
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*
* Windows JNI pinger using Microsoft's ICMP.DLL
* Author: Anton Keks
*/
#include <jni.h>
/* Header for class net_azib_ipscan_core_net_WindowsPinger */

View File

@ -134,6 +134,7 @@ list.alive.img=images/list/alive.png
list.addinfo.img=images/list/addinfo.png
pinger.icmp=ICMP Echo
pinger.icmp2=ICMP Echo (Alternative)
pinger.windows=Windows ICMP.DLL
pinger.udp=UDP packet
pinger.tcp=TCP port probe
opener.web=Web Browser

View File

@ -0,0 +1,64 @@
/**
* This file is a part of Angry IP Scanner source code,
* see http://www.azib.net/ for more information.
* Licensed under GPLv2.
*/
package net.azib.ipscan.core;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Utility class for loading of JNI libraries from jar files.
*
* @author Anton Keks
*/
public class LibraryLoader {
/**
* Loads native library from the jar file (storing it in the temp dir)
* @param library JNI library name
*/
public static void loadLibrary(String library) {
String filename = System.mapLibraryName(library);
String fullFilename = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + filename;
try {
// try to load from the temp dir (in case it is already there)
System.load(fullFilename);
}
catch (UnsatisfiedLinkError err2) {
try {
// try to extract from the jar
InputStream is = LibraryLoader.class.getClassLoader().getResourceAsStream(filename);
if (is == null) {
throw new IOException(filename + " not found in the jar file (classpath)");
}
byte[] buffer = new byte[4096];
OutputStream os = new FileOutputStream(fullFilename);
int read;
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
is.close();
if (!net.azib.ipscan.config.Platform.WINDOWS) {
// TODO: change this to new File(fullFilename).setExecutable(true) in case of
// Java 1.6
try {
Runtime.getRuntime().exec(new String[] { "chmod", "755", fullFilename }).waitFor();
}
catch (Throwable t) {
}
}
System.load(fullFilename);
}
catch (IOException ioe) {
throw new RuntimeException("Unable to extract native library: " + library, ioe);
}
}
}
}

View File

@ -25,7 +25,7 @@ import org.savarese.vserv.tcpip.OctetConverter;
*/
public class ICMPPinger implements Pinger {
static final Logger LOG = Logger.getLogger(ICMPPinger.class.getName());
private static final Logger LOG = Logger.getLogger(ICMPPinger.class.getName());
private int timeout;

View File

@ -14,12 +14,13 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import net.azib.ipscan.config.GlobalConfig;
import net.azib.ipscan.config.Platform;
import net.azib.ipscan.fetchers.FetcherException;
/**
* PingerRegistryImpl
*
* @author Anton Keks Keks
* @author Anton Keks
*/
public class PingerRegistryImpl implements PingerRegistry {
@ -34,6 +35,10 @@ public class PingerRegistryImpl implements PingerRegistry {
this.globalConfig = globalConfig;
pingers = new LinkedHashMap<String, Class<? extends Pinger>>();
if (Platform.WINDOWS) {
// this will be the preferred choice for Windows users
pingers.put("pinger.windows", WindowsPinger.class);
}
pingers.put("pinger.icmp", ICMPSharedPinger.class);
pingers.put("pinger.icmp2", ICMPPinger.class);
pingers.put("pinger.udp", UDPPinger.class);

View File

@ -8,10 +8,13 @@ package net.azib.ipscan.core.net;
import java.io.IOException;
import java.net.InetAddress;
import net.azib.ipscan.core.LibraryLoader;
/**
* Windows-only pinger that uses Microsoft's ICMP.DLL for its job.
* <p/>
* This pinger exists to provide adequate pinging to Windows users,
* because Microsoft has removed raw socket support from consumer
* because Microsoft has removed Raw Socket support from consumer
* versions of Windows since XP SP2.
*
* @author Anton Keks
@ -19,12 +22,13 @@ import java.net.InetAddress;
public class WindowsPinger implements Pinger {
private int timeout;
private boolean libraryLoaded;
public WindowsPinger(int timeout) {
this.timeout = timeout;
}
public void close() throws IOException {
if (!libraryLoaded) {
LibraryLoader.loadLibrary("winping");
}
}
public PingResult ping(InetAddress address, int count) throws IOException {
@ -34,15 +38,22 @@ public class WindowsPinger implements Pinger {
byte[] replyData = new byte[56 + 100];
int handle = nativeIcmpCreateFile();
if (handle < 0) {
throw new IOException("Unable to create Windows native ICMP handle");
}
try {
// send a bunch of packets
for (int i = 1; i <= count; i++) {
if (nativeIcmpSendEcho(handle, address.getAddress(), pingData, replyData, timeout) > 0) {
/*if (replyData.status == 11000) {
result.addReply(replyData.roundTripTime);
result.setTTL(replyData.ttl);
}*/
int status = replyData[4] + (replyData[5]<<8) + (replyData[6]<<16) + (replyData[7]<<24);
if (status == 0) {
int roundTripTime = replyData[8] + (replyData[9]<<8) + (replyData[10]<<16) + (replyData[11]<<24);
int timeToLive = replyData[20] & 0xFF;
result.addReply(roundTripTime);
result.setTTL(timeToLive);
}
}
}
}
@ -53,9 +64,25 @@ public class WindowsPinger implements Pinger {
return result;
}
/**
* Wrapper for Microsoft's
* {@linkplain http://msdn2.microsoft.com/en-US/library/aa366045.aspx IcmpCreateFile}
*/
private native static int nativeIcmpCreateFile();
/**
* Wrapper for Microsoft's
* {@linkplain http://msdn2.microsoft.com/EN-US/library/aa366050.aspx IcmpSendEcho}
*/
private native static int nativeIcmpSendEcho(int handle, byte[] address, byte[] pingData, byte[] replyData, int timeout);
/**
* Wrapper for Microsoft's IcmpCreateFile:
* {@linkplain http://msdn2.microsoft.com/en-us/library/Aa366043.aspx IcmpCloseHandle}
*/
private native static void nativeIcmpCloseHandle(int handle);
public void close() throws IOException {
// not needed in this pinger
}
}