Commit 9132cd13 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

finish: arp

parent 8faec2e2
......@@ -3,22 +3,25 @@ use std::io::{BufRead, Cursor};
use byteorder::{BigEndian, ReadBytesExt};
use super::packet::IP;
use super::{
packet::{ARP, IP},
tools::bits::mac_to_bytes,
};
struct EthernetFrame {
mac_des: u64,
mac_src: u64,
vlan: Option<u16>,
vlan_pcp: u8,
valn_dei: bool,
vlan_vid: u16,
vlan_dei: bool,
vlan_vid: Option<u16>,
ip_header: Network,
}
impl EthernetFrame {
fn parse(payload: &Vec<u8>) {
fn parse(payload: &Vec<u8>) -> EthernetFrame {
let mut bytes = Cursor::new(payload.to_vec());
let mut mac_des = vec![0u8; 6];
let mut mac_src = vec![0u8; 6];
let mut mac_des = [0u8; 6];
let mut mac_src = [0u8; 6];
for i in 0..6 {
mac_des[i] = bytes.read_u8().unwrap();
}
......@@ -27,7 +30,7 @@ impl EthernetFrame {
}
// check 802.1q tag tpid
let typ = bytes.read_u16::<BigEndian>().unwrap();
let (pcp, dei, vid, typ) = match typ {
let (vlan_pcp, vlan_dei, vlan_vid, typ) = match typ {
tp if tp == EtherType::VLAN as u16 => {
let tci = bytes.read_u16::<BigEndian>().unwrap();
let pcp = tci >> 13;
......@@ -46,15 +49,29 @@ impl EthernetFrame {
Network::Unparsable(typ, bytes.fill_buf().unwrap().to_vec())
}
}
// tp if tp == (EtherType::ARP as u16) => {
// }
tp if tp == (EtherType::ARP as u16) => {
let arp = ARP::parse(&mut bytes);
if arp.is_some() {
Network::ARP(arp.unwrap())
} else {
Network::Unparsable(typ, bytes.fill_buf().unwrap().to_vec())
}
}
_ => Network::Unparsable(typ, bytes.fill_buf().unwrap().to_vec()),
};
EthernetFrame {
mac_des: mac_to_bytes(mac_des),
mac_src: mac_to_bytes(mac_src),
vlan_pcp,
vlan_dei,
vlan_vid,
ip_header,
}
}
}
pub enum Network {
IP(IP),
ARP(ARP),
Unparsable(u16, Vec<u8>),
}
use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt};
pub enum ArpOperation {
Query = 0x0001,
Reply = 0x0002,
Unparse,
}
pub struct ARP {
pub hardware_type: u16,
pub protocol_type: u16,
pub hardware_length: u8,
pub protocol_length: u8,
pub operation: ArpOperation,
pub sender_mac: [u8; 6],
pub sender_address: u32,
pub target_mac: [u8; 6],
pub target_address: u32,
}
impl ARP {
pub fn size_of() -> usize {
28
}
pub fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<ARP> {
if bytes.get_ref().len() < ARP::size_of() {
return None;
}
let hardware_type = bytes.read_u16::<BigEndian>().unwrap();
let protocol_type = bytes.read_u16::<BigEndian>().unwrap();
let hardware_length = bytes.read_u8().unwrap();
let protocol_length = bytes.read_u8().unwrap();
let operation = match bytes.read_u16::<BigEndian>().unwrap() {
0x0001 => ArpOperation::Query,
0x0002 => ArpOperation::Reply,
_ => ArpOperation::Unparse,
};
if let ArpOperation::Unparse = operation {
return None;
}
let mut sender_mac = [0u8; 6];
for i in 0..6 {
sender_mac[i] = bytes.read_u8().unwrap();
}
let sender_address = bytes.read_u32::<BigEndian>().unwrap();
let mut target_mac = [0u8; 6];
for i in 0..6 {
target_mac[i] = bytes.read_u8().unwrap();
}
let target_address = bytes.read_u32::<BigEndian>().unwrap();
Some(ARP {
hardware_type,
protocol_type,
hardware_length,
protocol_length,
operation,
sender_mac,
sender_address,
target_mac,
target_address,
})
}
}
......@@ -7,4 +7,7 @@ pub use tcp::TCP;
pub mod udp;
pub mod ipv4;
pub use ipv4::{IP, EtherData, IpProtocol};
\ No newline at end of file
pub use ipv4::{EtherData, IpProtocol, IP};
pub mod arp;
pub use arp::{ArpOperation, ARP};
pub fn bit_bool(position: u16, byte: u16) -> bool {
(byte >> position) & 1 == 1
}
pub fn mac_to_bytes(byte: [u8; 6]) -> u64 {
let mut addr = [0u8; 8];
for i in 2..8 {
addr[i] = byte[i - 2];
}
u64::from_be_bytes(addr)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment