Crear, analizar y manipular paquetes de datos. Esta caja proporciona herramientas que se pueden usar para trabajar fácilmente con paquetes de datos utilizando una interfaz intuitiva de alto nivel. Si desea solicitar cualquier característica o mejoras, simplemente abra un problema, también para informar cualquier error, por supuesto.
Tenga en cuenta que cualquier tipo de anotaciones en esta documentación, como let data: Vec<u8> = packet.into_vec(); , solo se agregan para mayor claridad y no se requieren en su código.
Paso 1
Importe las partes apropiadas del paquete y cree una nueva estructura de paquetes para comenzar a poblarlo. Existen dos métodos para crear un nuevo paquete, el método 1 establecerá la capacidad del búfer interno a la longitud apropiada para los protocolos dados, y el método 2 simplemente creará un paquete totalmente vacío con la capacidad del búfer interno establecido en 0. El método 1 se prefiere para paquetes grandes, ya que será ligeramente más eficiente, ya que no necesitará aumentar constantemente la capacidad de CPC de cada datos de tiempo se agrega que se agrega datos de tiempo se agrega que se agrega datos de tiempo se agrega cada datos de tiempo, se agrega que se agrega datos de tiempo de tiempo.
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();
Paso 2
Cree los encabezados y agréguelos al paquete. Aquí vamos a ir con la estructura del paquete en el Método 1 del Paso 1, que 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
)
);
Paso 3
Es posible que este paso no siempre sea necesario, en casos como Echos ICMP donde no es necesario que haya datos porque solo se leen los encabezados. En muchos casos, sin embargo, es probable que desee agregar algunos datos de carga útil. Una vez más, hay dos formas de hacer esto, el Método 1 sobrescribirá los datos de carga útil exisitantes (si este es un paquete nuevo, no habrá ninguno de todos modos, pero si se trata de un paquete que se ha analizado de los datos sin procesar, puede haber algunos), y el método 2 se agregará a los datos de carga útil existentes. Observe la ausencia del .collect() en el método 2. El código aún funcionaría con él, sin embargo, no es necesario. Verá por qué si observa la firma de la función en la fuente.
// method 1
new_packet.set_payload("Hello, world!".bytes().collect());
// method 2
new_packet.extend_payload("Hello, world!".bytes());
Paso 4
Los datos ahora están listos, por lo que solo necesitamos hornear el paquete. Aquí es donde se poblará los campos de la suma de verificación y los campos de longitud, como el del encabezado IP (consulte esta página de documentos para obtener una explicación de por qué decidí calcularlos a pesar de que el sistema operativo probablemente los sobrescribirá)
let data: Vec<u8> = new_packet.into_vec();
}
Recuerde siempre que &Vec<u8> se puede pasar a funciones esperando &[u8] :)
Analizar un paquete se hace muy simple, siempre y cuando el paquete sea uno que comienza con el encabezado IP o el encabezado 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);
}
Nota: El análisis aún no se ha implementado para los paquetes IPv6
Digamos que acabamos de analizar el paquete que se crea en el nuevo ejemplo de paquete , por lo que es un paquete ETH> IP> TCP, y queremos actualizar el puerto de desinatamiento del campo TCP, así como la IP de destino:
// 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);
}