Jas*_*n C 5 java windows windows-7 jpcap
我正在尝试执行以下操作:
然而,以下几点给我带来了麻烦:
PacketCapture.lookupDevices()
,它返回到接口的 Windows NPF 驱动程序设备路径列表(例如\Device\NPF_{39966C4C-3728-4368-AE92-1D36ACAF6634}
)和相当平淡的显示字符串(例如Microsoft
),并且没有其他信息。所以我不能用它来构造UI界面列表。NetworkInterface.getNetworkInterfaces()
提供系统上的接口列表,其中包含 UI 所需的所有信息,但NetworkInterface
不提供 NDF 驱动程序设备路径,仅提供显示名称和设备名称,例如“net5”、“lo”等。PacketCapture#open()
只接受设备路径。既已启动又未环回的设备列表NetworkInterface
确实与 jpcap 返回的设备列表相对应,尽管它们的顺序不同。
因此,我找不到任何NetworkInterface
可以传递给 的内容PacketCapture#open()
,并且我不知道如何从 . 返回的设备路径中获取适合 UI 的信息PacketCapture#lookupDevices()
。PacketCapture
不接受NetworkInterface#getName()
。因此,我被困住了。
我还没有在 Linux 上尝试过这个。我怀疑这个问题是 Windows 特有的,它NetworkInterface#getName()
与PacketCapture#open()
.
我如何获取 jpcap 打开设备所需的信息NetworkInterface
(或相反 - 获取NetworkInterface
给定的设备路径),或者是否有另一种方法可以让我获得一个好的显示名称和 IP 地址每个设备都直接来自 jpcap?
Windows 注册表:我一直在进行一些挖掘,至少在注册表中找到了有关 NPF 设备的信息。给定 jpcap 设备路径,并使用此处的技术之一NetworkInterface
或本机库,可以从注册表获取一个好的适配器名称(相当于返回的名称)和当前 IP 地址,如下所示:
{39966C4C-3728-4368-AE92-1D36ACAF6634}
从上面的示例中)。保留大括号并调用它。HKLM\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces\<guid>
包含设备的当前 IP 地址以及一些其他配置信息。HKLM\SYSTEM\CurrentControlSet\services\<guid>\Parameters\Tcpip
包含类似信息。HKLM\SYSTEM\CurrentControlSet\Control\Class\
。如果发现一个子项包含一个NetCfgInstanceId
值为<guid>的键,那么其余的键将包含驱动程序信息 - 漂亮的显示名称、供应商信息等。我不知道 IPv6 如何影响上述内容(有一些注册表区域具有单独的 Tcpip6 信息块)。我也不知道这些键在 Windows 7 之外是否相同,但我怀疑它们是相同的。如果没有提供更好的答案,我会将以上内容转换为答案,并附有示例代码。我仍在寻找一种更直接的(理想情况下独立于平台且无需注册表)的方式。
这是一个替代解决方案,尽管仅提供已启动接口的信息,但它应该独立于平台。注册表解决方案是我的第一次尝试,效果很好,但我相信只要不需要有关下行接口的信息,这是一个更好的解决方案。
PacketCapture
可以在给定设备字符串的情况下提供网络地址和子网掩码(但它是实例方法,而不是静态方法)。对于 中的每个设备字符串PacketCapture.lookupDevices()
:PacketCapture
(捕获不需要打开)。NetworkInterface.getNetworkInterfaces()
,并找到其地址与 jpcap 为设备返回的网络地址和掩码指定的同一网络上的接口。NetworkInterface
(可能)对应于设备字符串。先决条件:
问题:
代码如下。根据 SO 的CC 归属共享许可证,可以免费使用。它是独立的,所以我没有把它放在 github 上。
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import net.sourceforge.jpcap.capture.CaptureDeviceLookupException;
import net.sourceforge.jpcap.capture.PacketCapture;
public class JpcapInterfaceInfo {
/**
* Get a list of interface information for all devices returned by jpcap.
* @param capture An instance of PacketCapture to use for getting network address and mask info. If null,
* a new instance will be created.
* @return List of information.
* @throws CaptureDeviceLookupException
*/
public static List<InterfaceInfo> listInterfaces (PacketCapture capture) throws CaptureDeviceLookupException {
if (capture == null)
capture = new PacketCapture();
List<InterfaceInfo> infos = new ArrayList<InterfaceInfo>();
for (String device : PacketCapture.lookupDevices())
infos.add(getInterfaceInfo(capture, device));
return infos;
}
/**
* Get a list of interface information for all devices returned by jpcap.
* @return List of information.
* @throws CaptureDeviceLookupException
*/
public static List<InterfaceInfo> listInterfaces () throws CaptureDeviceLookupException {
return listInterfaces(null);
}
/**
* Utility to check if an interface address matches a jpcap network address and mask.
* @param address An InetAddress to check.
* @param jpcapAddr Network address.
* @param jpcapMask Network mask.
* @return True if address is an IPv4 address on the network given by jpcapAddr/jpcapMask,
* false otherwise.
*/
private static boolean networkMatches (InetAddress address, int jpcapAddr, int jpcapMask) {
if (!(address instanceof Inet4Address))
return false;
byte[] address4 = address.getAddress();
if (address4.length != 4)
return false;
int addr = ByteBuffer.wrap(address4).order(ByteOrder.LITTLE_ENDIAN).getInt();
return ((addr & jpcapMask) == jpcapAddr);
}
/**
* Get an InterfaceInfo that corresponds to the given jpcap device string. The interface must be
* up in order to query info about it; if it is not then the NetworkInterface in the returned
* InterfaceInfo will be null.
* @param capture A PacketCapture instance used to get network address and mask info.
* @param jpcapDeviceString String from PacketCapture.lookupDevices().
* @return InterfaceInfo.
*/
public static InterfaceInfo getInterfaceInfo (PacketCapture capture, String jpcapDeviceString) {
InterfaceInfo info = null;
String deviceName = jpcapDeviceString.replaceAll("\n.*", "").trim();
try {
int netAddress = capture.getNetwork(deviceName);
int netMask = capture.getNetmask(deviceName);
// go through all addresses of all interfaces and try to find a match.
Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements() && info == null) {
NetworkInterface iface = e.nextElement();
Enumeration<InetAddress> ae = iface.getInetAddresses();
while (ae.hasMoreElements() && info == null) {
if (networkMatches(ae.nextElement(), netAddress, netMask))
info = new InterfaceInfo(iface, deviceName);
}
}
} catch (Exception x) {
System.err.println("While querying info for " + deviceName + ":");
x.printStackTrace(System.err);
}
if (info == null)
info = new InterfaceInfo(null, deviceName);
return info;
}
/**
* Information about a network interface for jpcap, which is basically just a NetworkInterface
* with details, and the jpcap device name for use with PacketCapture.
*/
public static class InterfaceInfo {
private final NetworkInterface iface;
private final String deviceName;
InterfaceInfo (NetworkInterface iface, String deviceName) {
this.iface = iface;
this.deviceName = deviceName;
}
/**
* Get NetworkInterface for this interface.
* @return May return null if no matching NetworkInterface was found.
*/
public final NetworkInterface getIface () {
return iface;
}
/**
* Get jpcap device name for this interface. This can be passed to PacketCapture.open().
* @return Device name for interface.
*/
public final String getDeviceName () {
return deviceName;
}
@Override public final String toString () {
return deviceName + " : " + iface;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个例子:
import java.util.List;
import net.sourceforge.jpcap.capture.PacketCapture;
public class JpcapInterfaceInfoTest {
public static void main (String[] args) throws Exception {
// Info can be queried from jpcap device list.
List<JpcapInterfaceInfo.InterfaceInfo> infos = JpcapInterfaceInfo.listInterfaces();
// Info can be displayed.
for (JpcapInterfaceInfo.InterfaceInfo info : infos)
System.out.println(info);
// Device names from InterfaceInfo can be passed directly to jpcap:
JpcapInterfaceInfo.InterfaceInfo selected = infos.get(0);
PacketCapture capture = new PacketCapture();
capture.open(selected.getDeviceName(), true);
}
}
Run Code Online (Sandbox Code Playgroud)
在我的机器上(与注册表解决方案相同的设置),输出:
\设备\NPF_{691D289D-7EE5-4BD8-B5C1-3C4729A852D5}:空 \Device\NPF_{39966C4C-3728-4368-AE92-1D36ACAF6634} :名称:net5(1x1 11b/g/n 无线 LAN PCI Express 半迷你卡适配器)
我没有使输出像其他解决方案一样漂亮。请注意,“虚拟 wifi 微型端口适配器”(第一个)为空NetworkInterface
,因为它未启动,因此无法找到匹配项(不存在 IP 地址和网络地址)。
归档时间: |
|
查看次数: |
3442 次 |
最近记录: |