问题描述
我想读取由 tcpdump 生成的 pcap 文件,其中包含经过 IPV4 fragmentation 的大型 UDP 数据包。原始数据包大小约为 22000 字节。
在 C++ 中,我会使用带有 IPV4Reassembler 的 libtins。有没有办法在 Rust 中做类似的事情?
目前在 Rust 中,这是我到目前为止所写的内容:非常不完整的第一次尝试(使用 crate use pnet::packet::{
ethernet::{EtherTypes,EthernetPacket},ip::IpNextHeaderProtocols,ipv4::Ipv4Packet,udp::UdpPacket,Packet,};
struct Ipv4Reassembler {
cap: pcap::Capture<pcap::Offline>,}
impl Iterator for Ipv4Reassembler {
type Item = Vec<u8>;
fn next(&mut self) -> Option<Self::Item> {
let mut payload = Vec::<u8>::new();
while let Some(packet) = self.cap.next().ok() {
// todo: handle packets other than Ethernet packets
let ethernet = EthernetPacket::new(packet.data).unwrap();
match ethernet.get_ethertype() {
EtherTypes::Ipv4 => {
let ipv4_packet = Ipv4Packet::new(ethernet.payload()).unwrap();
// dbg!(&ipv4_packet);
// todo: discard incomplete packets
// todo: construct header for reassembled packet
// todo: check id,etc
let off: usize = 8 * ipv4_packet.get_fragment_offset() as usize;
let end = off + ipv4_packet.payload().len();
if payload.len() < end {
payload.resize(end,0);
}
payload[off..end].clone_from_slice(ipv4_packet.payload());
if ipv4_packet.get_flags() & 1 == 0 {
return Some(payload);
}
}
_ => {}
}
}
None
}
}
fn main() {
let pcap_path = "os-992114000702.pcap";
let reass = Ipv4Reassembler {
cap: pcap::Capture::from_file(&pcap_path).unwrap(),};
for payload in reass {
let udp_packet = UdpPacket::new(&payload).unwrap();
dbg!(&udp_packet);
dbg!(&udp_packet.payload().len());
}
}
):
#include <tins/ip_reassembler.h>
#include <tins/packet.h>
#include <tins/rawpdu.h>
#include <tins/sniffer.h>
#include <tins/tins.h>
#include <tins/udp.h>
#include <iostream>
#include <string>
void read_packets(const std::string &pcap_filename) {
Tins::IPv4Reassembler reassembler;
Tins::FileSniffer sniffer(pcap_filename);
while (Tins::Packet packet = sniffer.next_packet()) {
auto &pdu = *packet.pdu();
const Tins::Timestamp ×tamp = packet.timestamp();
if (reassembler.process(pdu) != Tins::IPv4Reassembler::FRAGMENTED) {
const Tins::UDP *udp = pdu.find_pdu<Tins::UDP>();
if (!udp) {
continue;
}
const Tins::RawPDU *raw = pdu.find_pdu<Tins::RawPDU>();
if (!raw) {
continue;
}
const Tins::RawPDU::payload_type &payload = raw->payload();
std::cout << "Packet: " << payload.size() << std::endl;
// do something with the reassembled packet here
}
}
}
int main() {
const std::string pcap_path = "os-992114000702.pcap";
read_packets(pcap_path);
}
在 C++ 中,这是我将使用的代码(使用 libtins):
g++ -O3 -o pcap pcap.cpp -ltins
private fun fetchData() {
val url =
"https://newsapi.org/v2/top-headlines?country=in&category=science&apiKey=1f4a12d2698e432ea9cf18126dcc7acd"
val jsonObjectRequest = object : JsonObjectRequest(
Request.Method.GET,url,null,{
Log.e("TAG","fetchData: $it")
val newsJsonArray = it.getJSONArray("articles")
val newsArray = ArrayList<News>()
for (i in 0 until newsJsonArray.length()) {
val newsJsonObject = newsJsonArray.getJSONObject(i)
val news = News(
newsJsonObject.getString("title"),newsJsonObject.getString("author"),newsJsonObject.getString("url"),newsJsonObject.getString("urlToImage")
)
newsArray.add(news)
}
mAdapter.updateNews(newsArray)
},{
Log.d("Error occur","Try again..." + it.networkResponse.statusCode)
}
) {
override fun getHeaders(): MutableMap<String,String> {
val headers = HashMap<String,String>()
headers["User-Agent"] = "Mozilla/5.0"
return headers
}
}
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest)
}
似乎一种解决方案是实现 RFC815,但我不确定如何在 Rust 中实现。我发现:
- this old pull request to smolltcp 但它似乎已被放弃。
- Fuschia reassembly.rs 但我不知道如何在 Fuschia 之外使用它。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)