إنشاء ، تحليل ومعالجة حزم البيانات. يوفر هذا الصندوق أدوات يمكن استخدامها للعمل بسهولة مع حزم البيانات باستخدام واجهة عالية المستوى. إذا كنت ترغب في طلب أي ميزات أو تحسينات ، فيرجى فتح مشكلة ، بالمثل للإبلاغ عن أي أخطاء بالطبع.
يرجى ملاحظة أن أي نوع من التعليقات التوضيحية في هذه الوثائق ، مثل let data: Vec<u8> = packet.into_vec(); ، تتم إضافتها فقط من أجل الوضوح ، وليست مطلوبة في الكود الخاص بك.
الخطوة 1
استيراد الأجزاء المناسبة من الحزمة ، وقم بإنشاء بنية حزمة جديدة من أجل البدء في ملءها. هناك طريقتان لإنشاء حزمة جديدة ، ستضع الطريقة 1 سعة المخزن المؤقت الداخلي على الطول المناسب للبروتوكولات المحددة ، وستقوم الطريقة 2 فقط بإنشاء حزمة فارغة تمامًا مع سعة المخزن المؤقت الداخلية على 0
extern crate packet_crafter;
use packet_crafter::{
//import sub-modules
headers,
protocol_numbers,
ethertype_numbers,
//import data types
Packet,
Protocol
};
fn main() {
// method 1 (preferred)
let mut new_packet = Packet::new(
vec![
Protocol::ETH,
Protocol::IP,
Protocol::TCP
]
);
// method 2
let mut new_packet = Packet::new_empty();
الخطوة 2
قم بإنشاء الرؤوس وإضافتها إلى الحزمة. هنا سنذهب مع بنية الحزمة في الطريقة 1 من الخطوة 1 ، والتي ethernet> ip> tcp
new_packet.add_header(
headers::EthernetHeader::new(
[6,5,4,3,2,1], // source mac address
[1,2,3,4,5,6], // destination mac address
ethertype_numbers::ETHERTYPE_IPV4
)
);
new_packet.add_header(
headers::IpHeader::new(
[192, 168, 1, 128], // source IP
[192, 168, 1, 38], // destination IP
Protocol::TCP // next protocol
)
);
new_packet.add_header(
headers::TcpHeader::new(
3838, // source port
3838 // destination port
)
);
الخطوة 3
قد لا تكون هذه الخطوة ضرورية دائمًا ، في حالات مثل ICMP Echos حيث لا تحتاج إلى بيانات لأنه تتم قراءة الرؤوس فقط. ومع ذلك ، في كثير من الحالات ، من المحتمل أن ترغب في إضافة بعض بيانات الحمولة النافعة. مرة أخرى ، هناك طريقتان للقيام بذلك ، ستشكل الطريقة 1 الكتابة فوق بيانات الحمولة النافعة (إذا كانت هذه حزمة جديدة ، فلن تكون هناك أي شيء على أي حال ، ولكن إذا كانت حزمة تم تحليلها من البيانات الأولية ، فقد يكون هناك بعض) ، وسيتم إلحاق الطريقة 2 ببيانات الحمولة النافعة الحالية. لاحظ عدم وجود .collect() في الطريقة 2. لا يزال الرمز يعمل معه ، ومع ذلك ، فهو غير مطلوب. سترى لماذا إذا نظرت إلى توقيع الوظيفة في المصدر.
// method 1
new_packet.set_payload("Hello, world!".bytes().collect());
// method 2
new_packet.extend_payload("Hello, world!".bytes());
الخطوة 4
البيانات جاهزة الآن ، لذلك نحتاج فقط إلى خبز الحزمة. هذا هو المكان الذي سيتم فيه ملء حقول الفحص وحقول الطول مثل تلك الموجودة في رأس IP (انظر صفحة المستند هذه لتفسير لماذا قررت حسابها على الرغم من أن نظام التشغيل من المحتمل أن يكتبها)
let data: Vec<u8> = new_packet.into_vec();
}
تذكر دائمًا أنه يمكن نقله &Vec<u8> إلى وظائف تتوقع &[u8] :)
يكون تحليل الحزمة أمرًا بسيطًا للغاية ، طالما أن الحزمة هي واحدة تبدأ من رأس IP أو رأس Ethernet II:
extern crate packet_crafter;
use packet_crafter::Packet;
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let parsed_packet: Result<Packet, packet_crafter::ParseError> = Packet::parse(raw_data);
}
ملاحظة: لم يتم تنفيذ التحليل بعد حزم IPv6
دعنا نقول أننا قمنا فقط بتحليل الحزمة التي تم إنشاؤها في مثال Create Create New Packet ، لذلك فهي عبارة عن حزمة ETH> IP> TCP ، ونريد تحديث منفذ DEORS في حقل TCP بالإضافة إلى IP الوجهة:
// imports elided
fn main() {
let raw_data: &[u8] = your_function_to_read_a_packet_from_socket();
let mut packet = Packet::parse(raw_data).unwrap();
let mut tcp_header = packet.get_tcp_header().unwrap();
tcp_header.set_dst_port(21);
let mut ip_header = packet.get_ip_header().unwrap();
ip_header.set_dst_ip([192, 168, 1, 84]);
packet.update_header(ip_header);
// packet is now good to go, so make it and then send it:
let data = packet.into_vec();
your_function_to_send_packet_down_socket(&data);
}