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

时间:2011-11-15 18:19:15

标签: 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);

    }
}

错误:

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!

2 个答案:

答案 0 :(得分:8)

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

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

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

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

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

Ethernet frame在位置12需要协议类型(0x0800):

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

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

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

IP4 header需要版本(0x04)和位置14的大小(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 header需要大小(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)可以一次写入所有必需的字节,以避免对扫描方法进行如此多的调用。

答案 1 :(得分:1)

您是否遇到how to write subheders on jNetPcap的问题?是的,JNetPcap以字节为单位进行发送,但内容可以通过我给出的帮助填充子标题。如果您希望在数据包内发送一些数据,则许多Java类型具有toBytes()函数或类似功能。

修改
该特定Icmp类的API为here。同样可以对给定链接上的其他类进行操作。只需打开Goog​​le并为其他标题类型提供“Icmp类引用jnetpcap”。

<强> EDIT2:
更简单的创建ICMP数据包的方法是通过ICMPPacket class,它有一个简单的ICMP数据包构造函数,其中标头是在单个Constructor调用中创建的。根据课程参考,它做了以下内容:

  

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