diff --git a/ipscan.iml b/ipscan.iml index 8c1039db..392cbdfb 100644 --- a/ipscan.iml +++ b/ipscan.iml @@ -1,8 +1,8 @@ - - + + @@ -27,6 +27,19 @@ + + + + + + + + + + + + + diff --git a/src/net/azib/ipscan/core/net/WinIpHlp.java b/src/net/azib/ipscan/core/net/WinIpHlp.java new file mode 100644 index 00000000..82fdae36 --- /dev/null +++ b/src/net/azib/ipscan/core/net/WinIpHlp.java @@ -0,0 +1,20 @@ +package net.azib.ipscan.core.net; + +import net.azib.ipscan.core.net.WinIpHlpDll.Ip6SockAddrByRef; +import net.azib.ipscan.core.net.WinIpHlpDll.IpAddrByVal; + +import java.net.InetAddress; + +public class WinIpHlp { + public static IpAddrByVal toIpAddr(InetAddress address) { + IpAddrByVal addr = new IpAddrByVal(); + addr.bytes = address.getAddress(); + return addr; + } + + public static Ip6SockAddrByRef toIp6Addr(InetAddress address) { + Ip6SockAddrByRef addr = new Ip6SockAddrByRef(); + addr.bytes = address.getAddress(); + return addr; + } +} diff --git a/src/net/azib/ipscan/core/net/WinIpHlpDll.java b/src/net/azib/ipscan/core/net/WinIpHlpDll.java index 076239f2..a09b24f8 100644 --- a/src/net/azib/ipscan/core/net/WinIpHlpDll.java +++ b/src/net/azib/ipscan/core/net/WinIpHlpDll.java @@ -44,6 +44,11 @@ public interface WinIpHlpDll extends Library { */ Pointer IcmpCreateFile(); + /** + * Wrapper for Microsoft's Icmp6CreateFile + */ + Pointer Icmp6CreateFile(); + /** * Wrapper for Microsoft's IcmpCloseHandle */ @@ -63,6 +68,24 @@ public interface WinIpHlpDll extends Library { int timeout ); + /** + * Wrapper for Microsoft's Icmp6SendEcho2 + */ + int Icmp6SendEcho2( + Pointer hIcmp, + Pointer event, + Pointer apcRoutine, + Pointer apcContext, + Ip6SockAddrByRef sourceAddress, + Ip6SockAddrByRef destinationAddress, + Pointer requestData, + short requestSize, + IpOptionInformationByRef requestOptions, + Pointer replyBuffer, + int replySize, + int timeout + ); + /** * Wrapper for Microsoft's SendARP */ @@ -80,6 +103,17 @@ public interface WinIpHlpDll extends Library { class IpAddrByVal extends IpAddr implements Structure.ByValue { } + class Ip6SockAddr extends AutoOrderedStructure { + public short family = 10; + public short port; + public int flowInfo; + public byte[] bytes = new byte[16]; + public int scopeId; + } + + class Ip6SockAddrByRef extends Ip6SockAddr implements Structure.ByReference { + } + class IpOptionInformation extends AutoOrderedStructure { public byte ttl; public byte tos; @@ -113,4 +147,21 @@ public interface WinIpHlpDll extends Library { read(); } } + + class Icmp6EchoReply extends AutoOrderedStructure { + public short port; + public byte[] flowInfo = new byte[4]; + public byte[] addressBytes = new byte[16]; + public int scopeId; + public int status; + public int roundTripTime; + + public Icmp6EchoReply() { + } + + public Icmp6EchoReply(Pointer p) { + useMemory(p); + read(); + } + } } diff --git a/src/net/azib/ipscan/core/net/WindowsPinger.java b/src/net/azib/ipscan/core/net/WindowsPinger.java index f6d47d89..2e283ffa 100644 --- a/src/net/azib/ipscan/core/net/WindowsPinger.java +++ b/src/net/azib/ipscan/core/net/WindowsPinger.java @@ -8,7 +8,9 @@ package net.azib.ipscan.core.net; import com.sun.jna.Memory; import com.sun.jna.Pointer; import net.azib.ipscan.core.ScanningSubject; +import net.azib.ipscan.core.net.WinIpHlpDll.Icmp6EchoReply; import net.azib.ipscan.core.net.WinIpHlpDll.IcmpEchoReply; +import net.azib.ipscan.core.net.WinIpHlpDll.Ip6SockAddrByRef; import net.azib.ipscan.core.net.WinIpHlpDll.IpAddrByVal; import java.io.IOException; @@ -16,6 +18,8 @@ import java.net.InetAddress; import java.util.Arrays; import static java.lang.Thread.currentThread; +import static net.azib.ipscan.core.net.WinIpHlp.toIp6Addr; +import static net.azib.ipscan.core.net.WinIpHlp.toIpAddr; import static net.azib.ipscan.core.net.WinIpHlpDll.dll; /** @@ -29,18 +33,23 @@ import static net.azib.ipscan.core.net.WinIpHlpDll.dll; */ public class WindowsPinger implements Pinger { private int timeout; + private Ip6SockAddrByRef anyIp6SourceAddr = new Ip6SockAddrByRef(); public WindowsPinger(int timeout) { this.timeout = timeout; } public PingResult ping(ScanningSubject subject, int count) throws IOException { + if (subject.isIPv6()) + return ping6(subject, count); + else + return ping4(subject, count); + } + + private PingResult ping4(ScanningSubject subject, int count) throws IOException { Pointer handle = dll.IcmpCreateFile(); if (handle == null) throw new IOException("Unable to create Windows native ICMP handle"); - IpAddrByVal ipaddr = new IpAddrByVal(); - ipaddr.bytes = subject.getAddress().getAddress(); - int sendDataSize = 56; int replyDataSize = sendDataSize + (new IcmpEchoReply().size()) + 10; Pointer sendData = new Memory(sendDataSize); @@ -50,6 +59,7 @@ public class WindowsPinger implements Pinger { PingResult result = new PingResult(subject.getAddress(), count); try { for (int i = 1; i <= count && !currentThread().isInterrupted(); i++) { + IpAddrByVal ipaddr = toIpAddr(subject.getAddress()); int numReplies = dll.IcmpSendEcho(handle, ipaddr, sendData, (short) sendDataSize, null, replyData, replyDataSize, timeout); IcmpEchoReply echoReply = new IcmpEchoReply(replyData); if (numReplies > 0 && echoReply.status == 0 && Arrays.equals(echoReply.address.bytes, ipaddr.bytes)) { @@ -61,6 +71,36 @@ public class WindowsPinger implements Pinger { finally { dll.IcmpCloseHandle(handle); } + return result; + } + + private PingResult ping6(ScanningSubject subject, int count) throws IOException { + Pointer handle = dll.Icmp6CreateFile(); + if (handle == null) throw new IOException("Unable to create Windows native ICMP6 handle"); + + int sendDataSize = 56; + int replyDataSize = sendDataSize + (new Icmp6EchoReply().size()) + 10; + Pointer sendData = new Memory(sendDataSize); + sendData.clear(sendDataSize); + Pointer replyData = new Memory(replyDataSize); + + PingResult result = new PingResult(subject.getAddress(), count); + try { + Ip6SockAddrByRef ipaddr = toIp6Addr(subject.getAddress()); + for (int i = 1; i <= count && !currentThread().isInterrupted(); i++) { + int numReplies = dll.Icmp6SendEcho2(handle, null, null, null, anyIp6SourceAddr, toIp6Addr(subject.getAddress()), sendData, (short) sendDataSize, null, replyData, replyDataSize, timeout); + Icmp6EchoReply echoReply = new Icmp6EchoReply(replyData); + if (numReplies > 0 && echoReply.status == 0 && Arrays.equals(echoReply.addressBytes, ipaddr.bytes)) { + result.addReply(echoReply.roundTripTime); + //result.setTTL(echoReply.options.ttl & 0xFF); + } + System.err.println("Icmp6SendEcho2 response: " + numReplies + " " + echoReply.status + " " + InetAddress.getByAddress(echoReply.addressBytes) + " " + Arrays.toString(echoReply.addressBytes) + " vs " + InetAddress.getByAddress(ipaddr.bytes)); + System.err.println(echoReply.getFieldOrder()); + } + } + finally { + dll.IcmpCloseHandle(handle); + } return result; } @@ -70,7 +110,7 @@ public class WindowsPinger implements Pinger { } public static void main(String[] args) throws IOException { - PingResult ping = new WindowsPinger(5000).ping(new ScanningSubject(InetAddress.getLocalHost()), 3); + PingResult ping = new WindowsPinger(5000).ping(new ScanningSubject(InetAddress.getByName("::1")), 1); System.out.println(ping.getAverageTime() + "ms"); System.out.println("TTL " + ping.getTTL()); } diff --git a/src/net/azib/ipscan/fetchers/WinMACFetcher.java b/src/net/azib/ipscan/fetchers/WinMACFetcher.java index d60db788..f359f320 100644 --- a/src/net/azib/ipscan/fetchers/WinMACFetcher.java +++ b/src/net/azib/ipscan/fetchers/WinMACFetcher.java @@ -2,25 +2,22 @@ package net.azib.ipscan.fetchers; import com.sun.jna.Memory; import com.sun.jna.Pointer; -import net.azib.ipscan.core.net.WinIpHlpDll.IpAddrByVal; import javax.inject.Inject; import java.net.InetAddress; +import static net.azib.ipscan.core.net.WinIpHlp.toIpAddr; import static net.azib.ipscan.core.net.WinIpHlpDll.dll; public class WinMACFetcher extends MACFetcher { @Inject public WinMACFetcher() {} @Override public String resolveMAC(InetAddress address) { - IpAddrByVal destIP = new IpAddrByVal(); - destIP.bytes = address.getAddress(); - Pointer pmac = new Memory(8); Pointer plen = new Memory(4); plen.setInt(0, 8); - int result = dll.SendARP(destIP, 0, pmac, plen); + int result = dll.SendARP(toIpAddr(address), 0, pmac, plen); if (result != 0) return null;