Jnetpcap,准备UDP/TCP/IP/ICMP数据包

mas*_*oud 6 java jnetpcap

最近,我正在使用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);

    }
}
Run Code Online (Sandbox Code Playgroud)

错误:

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)
Run Code Online (Sandbox Code Playgroud)

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

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

Jua*_*ado 8

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

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

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

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

JMemoryPacket packet = new JMemoryPacket(packetSize);
packet.order(ByteOrder.BIG_ENDIAN); 
Run Code Online (Sandbox Code Playgroud)

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

packet.setUShort(12, 0x0800);
packet.scan(JProtocol.ETHERNET_ID); 
Run Code Online (Sandbox Code Playgroud)

之后scan,可以检索以太网实例并使用setter:

Ethernet ethernet = packet.getHeader( new Ethernet() );  
ethernet.destination(...);
...
Run Code Online (Sandbox Code Playgroud)

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(...);  
...
Run Code Online (Sandbox Code Playgroud)

TCP头需要大小(0x50):

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

Tcp tcp = packet.getHeader( new Tcp() );  
tcp.seq(...); 
...
Run Code Online (Sandbox Code Playgroud)

因此,有效负载:

Payload payload = packet.getHeader( new Payload() );
payload.set...(...);
...
Run Code Online (Sandbox Code Playgroud)

最后:

pcap.sendPacket( ByteBuffer.wrap( packet.getByteArray(0, packet.size() )  );
Run Code Online (Sandbox Code Playgroud)

5)可以一次写入所有必需的字节,以避免对扫描方法的这么多调用.

  • 完善!`packetSize`怎么样?如何预测合适的尺寸? (2认同)