Crie, analise e manipule pacotes de dados. Esta caixa fornece ferramentas que podem ser usadas para trabalhar facilmente com pacotes de dados usando uma interface intuitiva de alto nível. Se você deseja solicitar algum recurso ou melhorias, basta abrir um problema, da mesma forma para relatar qualquer bug, é claro.
Observe que qualquer anotações de tipo nesta documentação, como let data: Vec<u8> = packet.into_vec(); , são adicionados apenas para maior clareza e não são necessários em seu código.
Etapa 1
Importe as partes apropriadas do pacote e crie uma nova estrutura de pacotes para começar a preencher. Existem dois métodos de criação de um novo pacote, o método 1 definirá a capacidade do buffer interno com o comprimento apropriado para os protocolos especificados, e o Método 2 criará apenas um pacote totalmente vazio com a capacidade de buffer interna definida como 0. O método 1 é preferido para pacotes grandes, pois será adicionado um pouco mais eficiente, pois não haverá necessidade de aumentar constantemente o cpacity do tampão a cada tempo
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();
Etapa 2
Crie os cabeçalhos e adicione -os no pacote. Aqui vamos ir com a estrutura de pacotes no método 1 da etapa 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
)
);
Etapa 3
Essa etapa nem sempre pode ser necessária, em casos como o ICMP Echos, onde não precisa haver dados porque apenas os cabeçalhos são lidos. Em muitos casos, no entanto, você provavelmente desejará adicionar alguns dados de carga útil. Novamente, existem duas maneiras de fazer isso, o Método 1 substituirá os dados expositivos da carga útil (se este for um novo pacote, não haverá nenhum de qualquer maneira, mas se for um pacote que foi analisado a partir de dados brutos, pode haver alguns), e o método 2 anexará os dados de carga útil existente. Observe a ausência do .collect() no método 2. O código ainda funcionaria com ele, no entanto, não é necessário. Você verá por que se você olhar para a assinatura da função na fonte.
// method 1
new_packet.set_payload("Hello, world!".bytes().collect());
// method 2
new_packet.extend_payload("Hello, world!".bytes());
Etapa 4
Os dados agora estão prontos, então precisamos apenas assar o pacote. É aqui que os campos de soma de verificação e campos de comprimento, como o do cabeçalho IP, serão preenchidos (consulte esta página do documento para uma explicação de por que eu decidi calculá -los, mesmo que o sistema operacional provavelmente os substitua)
let data: Vec<u8> = new_packet.into_vec();
}
Lembre -se sempre de que &Vec<u8> podem ser transmitidos em funções esperando &[u8] :)
Analisar um pacote é muito simples, desde que o pacote seja iniciado com o cabeçalho IP ou o cabeçalho 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: A análise ainda não foi implementada para pacotes IPv6
Digamos que acabamos de analisar o pacote criado no exemplo de criação de novos pacotes , por isso é um pacote eth> ip> tcp e queremos atualizar a porta de desinalização do campo TCP, bem como o 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);
}