最近,我正在使用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!
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)可以一次写入所有必需的字节,以避免对扫描方法的这么多调用.
| 归档时间: |
|
| 查看次数: |
8337 次 |
| 最近记录: |