6

最近,我使用 Jnetpcap 通过网络发送/接收原始数据包。

Jnetpcap 提供通过Pcap.sendPacket(). 此方法获取要发送的原始缓冲区或字节。

另一方面,有些org.jnetpcap.protocol.*类封装了协议头,我们可以使用它们来解码捕获的数据包。

当我使用下面的代码制作Ip4数据包时,它会导致 NullPointerException:

import org.jnetpcap.protocol.network.Ip4;

public class Test {

    public static void main(String[] args) {

        Ip4 ip4 = new Ip4();

        ip4.ttl(10);

    }
}

错误:

Exception in thread "main" java.lang.NullPointerException
    at org.jnetpcap.nio.JBuffer.check(Unknown Source)
    at org.jnetpcap.nio.JBuffer.setUByte(Unknown Source)
    at org.jnetpcap.protocol.network.Ip4.ttl(Unknown Source)
    at jaeger.Test.main(Test.java:17)

如何构建该数据包然后发送它Pcap.sendPacket()

注意:我真的对逐字节准备数据包不感兴趣...... C/C++ libpcap 和 Jpcap 有工作功能,但我想使用 Jnetpcap!

4

2 回答 2

9

1)代码抛出异常,因为包装类仅使用先前分配的缓冲区工作,因为库的主要目的是分析捕获数据包的缓冲区。因此,有必要在使用它们之前分配一个缓冲区。

2)必须构建提供所有必要字节的数据包。但是可以编写代码,以便真正需要几个字节(见上文)。

3) sendPacket期望一个完整的数据包,一个完整的以太网帧。因此,必须将以太网、IP、TCP 标头和有效负载写入缓冲区。

4)允许您使用包装类的主要思想是分配一个缓冲区,然后让库扫描它以发现标头,但必须提供最少的信息(字节)。

JMemoryPacket packet = new JMemoryPacket(packetSize);
packet.order(ByteOrder.BIG_ENDIAN); 

以太网帧在位置 12 需要一个协议类型 (0x0800):

packet.setUShort(12, 0x0800);
packet.scan(JProtocol.ETHERNET_ID); 

之后scan,可以检索以太网实例并使用设置器

Ethernet ethernet = packet.getHeader( new Ethernet() );  
ethernet.destination(...);
...

IP4 标头在位置 14 需要版本 (0x04) 和大小 (0x05):

packet.setUByte(14, 0x40 | 0x05);
packet.scan(JProtocol.ETHERNET_ID);  

Ip4 ip4 = packet.getHeader( new Ip4() );
ip4.type(0x06); //TCP
ip4.length( packetSize - ethernet.size() );
ip4.ttl(...);  
...

TCP 标头需要大小 (0x50):

packet.setUByte(46, 0x50);
packet.scan(JProtocol.ETHERNET_ID);  

Tcp tcp = packet.getHeader( new Tcp() );  
tcp.seq(...); 
...

所以,有效载荷:

Payload payload = packet.getHeader( new Payload() );
payload.set...(...);
...

最后:

pcap.sendPacket( ByteBuffer.wrap( packet.getByteArray(0, packet.size() )  );

5)可以一次写入所有必要的字节,以避免对扫描方法的如此多的调用。

于 2012-02-27T22:58:00.617 回答
1

您是否面临如何在 jNetPcap 上编写 subheders的问题?是的,JNetPcap 以字节为单位进行发送,但在我提供的帮助下,内容可以用子标题填充。如果您想在数据包内发送一些数据,许多 Java 类型都有一个toBytes()功能或类似的功能。

编辑:
特定 Icmp 类的 API 在这里。对给定链接上的其他类也可以这样做。只需打开 Google 并提供“Icmp 类参考 jnetpcap”或其他标头类型。

edit2:
创建 ICMP 数据包的更简单方法是通过ICMPPacket 类,该类具有用于 ICMP 数据包的简单构造函数,其中在单个构造函数调用中创建标头。根据类参考,它做了以下内容:

扩展 IP 数据包,添加 ICMP 标头和 ICMP 数据有效负载。

于 2011-11-19T16:49:36.610 回答