diff --git a/auip/Cargo.toml b/auip/Cargo.toml index 757df4f..568b4e0 100644 --- a/auip/Cargo.toml +++ b/auip/Cargo.toml @@ -10,3 +10,8 @@ edition = "2018" # byteorder = {version = "1", default-features = false} log = "0.4" auip-pkt = {path = "../pkt"} + +[features] +default = ["alloc"] +alloc = [] + diff --git a/auip/src/device/addrs_storage.rs b/auip/src/device/addrs_storage.rs deleted file mode 100644 index b350aad..0000000 --- a/auip/src/device/addrs_storage.rs +++ /dev/null @@ -1,15 +0,0 @@ -use auip_pkt::{ip, mac}; - -use crate::Result; - -pub trait AddrsStorage { - fn set_mac_addr(&mut self, addr: mac::Address); - - fn mac_addr(&self) -> &mac::Address; - - fn add_ip_addr(&mut self, addr: ip::Cidr) -> Result<()>; - - fn del_ip_addr(&mut self, addr: ip::Cidr); - - fn ip_addrs(&self) -> &[ip::Cidr]; -} diff --git a/auip/src/device/device.rs b/auip/src/device/device.rs deleted file mode 100644 index e5b27e2..0000000 --- a/auip/src/device/device.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::{Medium, Result}; - -pub trait Device { - fn send(&mut self, buffer: &[u8]) -> Result<()>; - - fn recv(&mut self) -> Result<&[u8]>; - - fn medium(&self) -> Medium; -} diff --git a/auip/src/device/mod.rs b/auip/src/device/mod.rs index 5ee74fd..d47b37c 100644 --- a/auip/src/device/mod.rs +++ b/auip/src/device/mod.rs @@ -1,8 +1,5 @@ mod medium; pub use medium::*; -mod device; -pub use device::*; - -mod addrs_storage; -pub use addrs_storage::*; +mod prelude; +pub use prelude::*; diff --git a/auip/src/device/prelude.rs b/auip/src/device/prelude.rs new file mode 100644 index 0000000..71d4688 --- /dev/null +++ b/auip/src/device/prelude.rs @@ -0,0 +1,31 @@ +use auip_pkt::{layer2, layer3}; + +use crate::{Medium, Result}; + +pub trait Device { + fn send(&mut self, buffer: &[u8]) -> Result<()>; + + fn recv(&mut self) -> Result>; + + fn medium(&self) -> Medium; +} + +pub trait AddrsStorage { + fn set_mac_addr(&mut self, addr: layer2::Address); + + fn mac_addr(&self) -> &layer2::Address; + + fn add_ip_addr(&mut self, addr: layer3::Cidr) -> Result<()>; + + fn del_ip_addr(&mut self, addr: layer3::Cidr); + + fn ip_addrs(&self) -> &[layer3::Cidr]; +} + +pub trait Layer3PacketStorage { + type Layer3PacketBytes; + + fn get(&self, idx: usize) -> Option<&layer3::Packet>; + + fn get_mut(&mut self, idx: usize) -> Option<&mut layer3::Packet>; +} diff --git a/auip/src/interface/mod.rs b/auip/src/interface/mod.rs index 4dbfd4e..2352783 100644 --- a/auip/src/interface/mod.rs +++ b/auip/src/interface/mod.rs @@ -1,50 +1,86 @@ use auip_pkt::{ - ip, - mac::{ethernet, VlanId}, + layer2::{self, ethernet, VlanId}, + layer3, }; -use crate::{AddrsStorage, Device, Medium, Result}; +use crate::{AddrsStorage, Device, Layer3PacketStorage, Medium, Result}; -pub struct Interface { +pub struct Interface { device: D, + addrs_storage: AS, + layer3_packet_storage: L3PS, medium: Medium, - addrs_storage: A, - vlanid: VlanId, + + vlanid0: Option, + vlanid1: Option, } -impl Interface { - pub fn new(device: D, addrs_storage: A, vlanid: VlanId) -> Self { +impl Interface +where + D: Device, + AS: AddrsStorage, + L3PS: Layer3PacketStorage, +{ + pub fn new(device: D, addrs_storage: AS, layer3_packet_storage: L3PS) -> Self { let medium = device.medium(); Self { device, medium, addrs_storage, - vlanid, + layer3_packet_storage, + vlanid0: None, + vlanid1: None, } } pub(crate) fn poll_ethernet(&mut self) -> Result<()> { - let rx_bytes = self.device.recv()?; - let rx_pkt = ethernet::Packet::new_checked(rx_bytes)?; + if let Some(rx_bytes) = self.device.recv()? { + let rx_pkt = ethernet::Packet::new_checked(rx_bytes)?; - // TODO: Hook + // TODO: Hook - let dest_addr = rx_pkt.dest_addr(); + let dest_addr = rx_pkt.dest_addr(); - if &dest_addr == self.addrs_storage.mac_addr() { - // Got vlan id and math - // Process ip packet - } + if &dest_addr == self.addrs_storage.mac_addr() { + let protocol = rx_pkt.protocol(); + + match protocol { + layer2::Protocol::Layer3Protocol(l3) => poll_layer3(l3, rx_pkt.payload())?, + layer2::Protocol::IEEE8021Q(vlanid, l3) => { + if Some(vlanid) == self.vlanid0 { + poll_layer3(l3, rx_pkt.payload())?; + } + } + layer2::Protocol::QinQ(vlanid, vlanid1, l3) => { + if Some(vlanid) == self.vlanid0 && Some(vlanid1) == self.vlanid1 { + poll_layer3(l3, rx_pkt.payload())?; + } + } + + // TODO: process IEEE802.3 packet. + layer2::Protocol::Length(_) => {} + + // Skip + layer2::Protocol::Unknown(_) => {} + } + } - // Select mac address and send packet + // Select mac address and send packet + } Ok(()) } pub(crate) fn poll_ip(&mut self) -> Result<()> { - let rx_bytes = self.device.recv()?; - // let rx_pkt = ip::Packet::new_checked(rx_bytes)?; + if let Some(rx_bytes) = self.device.recv()? { + let ip_pkt = layer3::IpPacket::parse(rx_bytes)?; + + match ip_pkt { + layer3::IpPacket::IPv4(pkt) => poll_ipv4(pkt)?, + layer3::IpPacket::Ipv6 => {} + } + } Ok(()) } @@ -58,3 +94,28 @@ impl Interface { Ok(()) } } + +pub(crate) fn poll_layer3(protocol: layer2::Layer3Protocol, bytes: &[u8]) -> Result<()> { + match protocol { + layer2::Layer3Protocol::IPv4 => { + let pkt = layer3::ipv4::Packet::new_checked(bytes)?; + + poll_ipv4(pkt)?; + } + layer2::Layer3Protocol::IPv6 => {} + layer2::Layer3Protocol::ARP => {} + layer2::Layer3Protocol::Unknown(_) => {} + } + + Ok(()) +} + +pub(crate) fn poll_arp(bytes: &[u8]) -> Result<()> { + let pkt = layer3::arp::Packet::new_checked(bytes)?; + + Ok(()) +} + +pub(crate) fn poll_ipv4(pkt: layer3::ipv4::Packet<&[u8]>) -> Result<()> { + Ok(()) +} diff --git a/pkt/src/ip/ipv6/mod.rs b/auip/src/storage/dynamic_addrs.rs similarity index 100% rename from pkt/src/ip/ipv6/mod.rs rename to auip/src/storage/dynamic_addrs.rs diff --git a/auip/src/storage/fixed_addrs.rs b/auip/src/storage/fixed_addrs.rs index 22fdd9a..50fe0b3 100644 --- a/auip/src/storage/fixed_addrs.rs +++ b/auip/src/storage/fixed_addrs.rs @@ -1,10 +1,10 @@ -use auip_pkt::{ip, mac}; +use auip_pkt::{layer2, layer3}; use crate::{AddrsStorage, Error, Result}; pub struct FixedAddrsStorage { - pub mac_addr: mac::Address, - pub ip_addrs: [ip::Cidr; IP_ADDR_NUM], + pub mac_addr: layer2::Address, + pub ip_addrs: [layer3::Cidr; IP_ADDR_NUM], } impl Default for FixedAddrsStorage { @@ -19,19 +19,19 @@ impl Default for FixedAddrsStorage { } impl AddrsStorage for FixedAddrsStorage { - fn mac_addr(&self) -> &mac::Address { + fn mac_addr(&self) -> &layer2::Address { &self.mac_addr } - fn set_mac_addr(&mut self, addr: mac::Address) { + fn set_mac_addr(&mut self, addr: layer2::Address) { self.mac_addr = addr; } - fn add_ip_addr(&mut self, addr: ip::Cidr) -> Result<()> { + fn add_ip_addr(&mut self, addr: layer3::Cidr) -> Result<()> { let mut setted = false; for it in &mut self.ip_addrs { - if it.address() == &ip::Address::Unspecified { + if it.address() == &layer3::Address::Unspecified { *it = addr; setted = true; } @@ -44,7 +44,7 @@ impl AddrsStorage for FixedAddrsStorage { } } - fn del_ip_addr(&mut self, addr: ip::Cidr) { + fn del_ip_addr(&mut self, addr: layer3::Cidr) { for it in &mut self.ip_addrs { if it == &addr { *it = Default::default() @@ -52,7 +52,7 @@ impl AddrsStorage for FixedAddrsStorage { } } - fn ip_addrs(&self) -> &[ip::Cidr] { + fn ip_addrs(&self) -> &[layer3::Cidr] { &self.ip_addrs } } diff --git a/auip/src/storage/fixed_l3ps.rs b/auip/src/storage/fixed_l3ps.rs new file mode 100644 index 0000000..815ed11 --- /dev/null +++ b/auip/src/storage/fixed_l3ps.rs @@ -0,0 +1,29 @@ +use auip_pkt::layer3; + +use crate::{FixedBytes, Layer3PacketStorage}; + +pub struct FixedLayer3PacketStorage { + pub packets: [layer3::Packet>; LEN], +} + +impl Layer3PacketStorage + for FixedLayer3PacketStorage +{ + type Layer3PacketBytes = FixedBytes; + + fn get(&self, idx: usize) -> Option<&layer3::Packet> { + if self.packets.len() < idx { + Some(&self.packets[idx]) + } else { + None + } + } + + fn get_mut(&mut self, idx: usize) -> Option<&mut layer3::Packet> { + if self.packets.len() < idx { + Some(&mut self.packets[idx]) + } else { + None + } + } +} diff --git a/auip/src/storage/mod.rs b/auip/src/storage/mod.rs index 5d2698d..b58d2e3 100644 --- a/auip/src/storage/mod.rs +++ b/auip/src/storage/mod.rs @@ -1,2 +1,10 @@ mod fixed_addrs; pub use fixed_addrs::*; + +#[cfg(feature = "alloc")] +mod dynamic_addrs; +#[cfg(feature = "alloc")] +pub use dynamic_addrs::*; + +mod fixed_l3ps; +pub use fixed_l3ps::*; diff --git a/auip/src/utils.rs b/auip/src/utils.rs index 8b13789..06abbb8 100644 --- a/auip/src/utils.rs +++ b/auip/src/utils.rs @@ -1 +1,13 @@ +pub struct FixedBytes(pub [u8; LEN]); +impl AsRef<[u8]> for FixedBytes { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl AsMut<[u8]> for FixedBytes { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} diff --git a/pkt/src/error.rs b/pkt/src/error.rs index d1abacd..5301d5e 100644 --- a/pkt/src/error.rs +++ b/pkt/src/error.rs @@ -1,14 +1,13 @@ /// Error's for packet. #[derive(Clone, Debug)] pub enum Error { - Illegal, - Malformed, - Unrecognized, WrongLengthForEthernetAddress, WrongLengthForIpv4Address, WrongLengthForArpPacket, WrongLengthForIpv4Packet, WrongLengthForEthernetPacket, + UnknownIpVersionNumber, + IllegalNetmask, } /// Result for packet. diff --git a/pkt/src/ip/ipv4/mod.rs b/pkt/src/ip/ipv4/mod.rs deleted file mode 100644 index 81969ee..0000000 --- a/pkt/src/ip/ipv4/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! ipv4. - -mod address; -pub use address::Address; - -mod cidr; -pub use cidr::Cidr; - -mod packet; -pub use packet::Packet; diff --git a/pkt/src/ip/mod.rs b/pkt/src/ip/mod.rs deleted file mode 100644 index e1a9ee9..0000000 --- a/pkt/src/ip/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Ip layer's packet. - -pub mod arp; -pub mod ipv4; -// pub mod ipv6; - -mod address; -pub use address::Address; - -mod protocol; -pub use protocol::Protocol; - -mod cidr; -pub use cidr::Cidr; - -mod packet; -pub use packet::Packet; diff --git a/pkt/src/ip/packet.rs b/pkt/src/ip/packet.rs deleted file mode 100644 index d56028c..0000000 --- a/pkt/src/ip/packet.rs +++ /dev/null @@ -1,15 +0,0 @@ -use super::arp; -use super::ipv4; - -#[derive(Debug, Clone)] -pub enum Packet { - IPv4(ipv4::Packet), - ARP(arp::Packet), -} - -impl> Packet { - pub fn parse_ip(t: T) { - - } -} - diff --git a/pkt/src/mac/address.rs b/pkt/src/layer2/address.rs similarity index 100% rename from pkt/src/mac/address.rs rename to pkt/src/layer2/address.rs diff --git a/pkt/src/mac/ethernet.rs b/pkt/src/layer2/ethernet.rs similarity index 80% rename from pkt/src/mac/ethernet.rs rename to pkt/src/layer2/ethernet.rs index 75831fb..7eeb397 100644 --- a/pkt/src/mac/ethernet.rs +++ b/pkt/src/layer2/ethernet.rs @@ -2,7 +2,7 @@ use crate::{prelude::IntoInner, Error, Result}; -use super::{consts, Address, Protocol, VlanId}; +use super::{consts, Address, Layer3Protocol, Protocol, VlanId}; use byteorder::{ByteOrder, NetworkEndian}; use core::fmt::{self, Display}; @@ -112,25 +112,24 @@ impl> Packet { if ty == consts::IEEE802_1Q { let vlanid1 = VlanId::from_bytes_unchecked(&data[field::qinq::PRI_CFI_VID]); - Protocol::QinQ(vlanid, vlanid1) + + let layer3_raw = NetworkEndian::read_u16(&data[field::qinq::ETHERTYPE]); + + Protocol::QinQ(vlanid, vlanid1, Layer3Protocol::from(layer3_raw)) } else { - Protocol::IEEE8021Q(vlanid) + Protocol::IEEE8021Q(vlanid, Layer3Protocol::from(ty)) } } else { Protocol::from(ty) } } - /* pub fn upper_protocol(&self) -> Protocol { */ - /* */ - /* } */ - pub fn header_len(&self) -> usize { let protocol = self.protocol(); match protocol { - Protocol::IEEE8021Q(_) => field::ieee8021q::PAYLOAD.start, - Protocol::QinQ(_, _) => field::qinq::PAYLOAD.start, + Protocol::IEEE8021Q(_, _) => field::ieee8021q::PAYLOAD.start, + Protocol::QinQ(_, _, _) => field::qinq::PAYLOAD.start, _ => field::ethernetii::PAYLOAD.start, } } @@ -158,9 +157,11 @@ impl> Packet { let protocol = self.protocol(); + // TODO: Use direct logic + match protocol { - Protocol::IEEE8021Q(_) => &inner[field::ieee8021q::PAYLOAD], - Protocol::QinQ(_, _) => &inner[field::qinq::PAYLOAD], + Protocol::IEEE8021Q(_, _) => &inner[field::ieee8021q::PAYLOAD], + Protocol::QinQ(_, _, _) => &inner[field::qinq::PAYLOAD], _ => &inner[field::ethernetii::PAYLOAD], } } @@ -172,13 +173,18 @@ impl + AsMut<[u8]>> Packet { let data = self.buffer.as_mut(); match &protocol { - Protocol::IEEE8021Q(vlanid) => { - NetworkEndian::write_u16(&mut data[field::ieee8021q::PRI_CFI_VID], vlanid.0) + Protocol::IEEE8021Q(vlanid, l3) => { + NetworkEndian::write_u16(&mut data[field::ieee8021q::PRI_CFI_VID], vlanid.0); + NetworkEndian::write_u16(&mut data[field::ieee8021q::ETHERTYPE], l3.into()); } - Protocol::QinQ(vlanid, vlanid1) => { + Protocol::QinQ(vlanid, vlanid1, l3) => { NetworkEndian::write_u16(&mut data[field::ieee8021q::PRI_CFI_VID], vlanid.0); - NetworkEndian::write_u16(&mut data[field::qinq::ETHERTYPE], (&protocol).into()); + NetworkEndian::write_u16( + &mut data[field::ieee8021q::ETHERTYPE], + (&protocol).into(), + ); NetworkEndian::write_u16(&mut data[field::qinq::PRI_CFI_VID], vlanid1.0); + NetworkEndian::write_u16(&mut data[field::qinq::ETHERTYPE], l3.into()); } _ => {} } @@ -205,8 +211,8 @@ impl + AsMut<[u8]>> Packet { let inner = self.buffer.as_mut(); match protocol { - Protocol::IEEE8021Q(_) => &mut inner[field::ieee8021q::PAYLOAD], - Protocol::QinQ(_, _) => &mut inner[field::qinq::PAYLOAD], + Protocol::IEEE8021Q(_, _) => &mut inner[field::ieee8021q::PAYLOAD], + Protocol::QinQ(_, _, _) => &mut inner[field::qinq::PAYLOAD], _ => &mut inner[field::ethernetii::PAYLOAD], } } diff --git a/pkt/src/mac/mod.rs b/pkt/src/layer2/mod.rs similarity index 100% rename from pkt/src/mac/mod.rs rename to pkt/src/layer2/mod.rs diff --git a/pkt/src/layer2/protocol.rs b/pkt/src/layer2/protocol.rs new file mode 100644 index 0000000..7a08eb5 --- /dev/null +++ b/pkt/src/layer2/protocol.rs @@ -0,0 +1,112 @@ +use super::VlanId; + +pub mod consts { + pub const IPV4: u16 = 0x0800; + pub const IPV6: u16 = 0x86DD; + pub const ARP: u16 = 0x0806; + pub const IEEE802_1Q: u16 = 0x8100; + pub const Q_IN_Q: u16 = IEEE802_1Q; + pub const IEEE802_3: u16 = 0x05DC; +} + +/// Ethernet payload type for layer3 +#[derive(Debug, Clone)] +pub enum Layer3Protocol { + IPv4, + + IPv6, + + ARP, + + Unknown(u16), +} + +impl From for Layer3Protocol { + fn from(ty: u16) -> Self { + match ty { + consts::ARP => Self::ARP, + consts::IPV4 => Self::IPv4, + consts::IPV6 => Self::IPv6, + _ => Self::Unknown(ty), + } + } +} + +impl From for u16 { + fn from(e: Layer3Protocol) -> u16 { + match e { + Layer3Protocol::ARP => consts::ARP, + Layer3Protocol::IPv4 => consts::IPV4, + Layer3Protocol::IPv6 => consts::IPV6, + Layer3Protocol::Unknown(v) => v, + } + } +} + +impl From<&Layer3Protocol> for u16 { + fn from(e: &Layer3Protocol) -> u16 { + match e { + Layer3Protocol::ARP => consts::ARP, + Layer3Protocol::IPv4 => consts::IPV4, + Layer3Protocol::IPv6 => consts::IPV6, + Layer3Protocol::Unknown(v) => *v, + } + } +} + +/// Ethernet payload type. +#[derive(Debug, Clone)] +pub enum Protocol { + Layer3Protocol(Layer3Protocol), + + IEEE8021Q(VlanId, Layer3Protocol), + + QinQ(VlanId, VlanId, Layer3Protocol), + + /// IEEE802.3 + Length(u16), + + Unknown(u16), +} + +impl From for Protocol { + fn from(ty: u16) -> Self { + let layer3 = Layer3Protocol::from(ty); + + if let Layer3Protocol::Unknown(ty) = &layer3 { + let ty = *ty; + + if ty < consts::IEEE802_3 { + Self::Length(ty) + } else { + Self::Unknown(ty) + } + } else { + Self::Layer3Protocol(layer3) + } + } +} + +impl From for u16 { + fn from(e: Protocol) -> u16 { + match e { + Protocol::Layer3Protocol(p) => p.into(), + Protocol::IEEE8021Q(_, _) => consts::IEEE802_1Q, + Protocol::QinQ(_, _, _) => consts::Q_IN_Q, + Protocol::Length(v) => v, + Protocol::Unknown(v) => v, + } + } +} + +impl From<&Protocol> for u16 { + fn from(e: &Protocol) -> u16 { + match e { + Protocol::Layer3Protocol(p) => p.into(), + Protocol::IEEE8021Q(_, _) => consts::IEEE802_1Q, + Protocol::QinQ(_, _, _) => consts::Q_IN_Q, + Protocol::Length(v) => *v, + Protocol::Unknown(v) => *v, + } + } +} diff --git a/pkt/src/ip/address.rs b/pkt/src/layer3/address.rs similarity index 100% rename from pkt/src/ip/address.rs rename to pkt/src/layer3/address.rs diff --git a/pkt/src/ip/arp/mod.rs b/pkt/src/layer3/arp/mod.rs similarity index 100% rename from pkt/src/ip/arp/mod.rs rename to pkt/src/layer3/arp/mod.rs diff --git a/pkt/src/ip/arp/packet.rs b/pkt/src/layer3/arp/packet.rs similarity index 97% rename from pkt/src/ip/arp/packet.rs rename to pkt/src/layer3/arp/packet.rs index 31aadee..3aedc75 100644 --- a/pkt/src/ip/arp/packet.rs +++ b/pkt/src/layer3/arp/packet.rs @@ -1,5 +1,5 @@ use super::{consts, HardwareAddress, Operation, ProtocolAddress}; -use crate::{error::*, ip::ipv4::Address, mac}; +use crate::{error::*, layer2, layer3::ipv4::Address}; use byteorder::{ByteOrder, NetworkEndian}; use core::fmt::{self, Display}; @@ -82,7 +82,7 @@ impl> Packet { if raw == consts::HARDWARE_ETHERNET { if self.hardware_len() == consts::HARDWARE_ETHERNET_LENGTH { let raw_addr = self.source_hardware_addr(); - let addr = mac::Address::from(raw_addr); + let addr = layer2::Address::from(raw_addr); Ok(HardwareAddress::Ethernet(addr)) } else { Err(Error::WrongLengthForEthernetAddress) @@ -100,7 +100,7 @@ impl> Packet { if raw == consts::HARDWARE_ETHERNET { if self.hardware_len() == consts::HARDWARE_ETHERNET_LENGTH { let raw_addr = self.target_hardware_addr(); - let addr = mac::Address::from(raw_addr); + let addr = layer2::Address::from(raw_addr); Ok(HardwareAddress::Ethernet(addr)) } else { Err(Error::WrongLengthForEthernetAddress) @@ -154,7 +154,7 @@ impl> Packet { impl + AsMut<[u8]>> Packet { /// Set source hardware address - pub fn set_source_map( + pub fn set_source_address( &mut self, hd_addr: HardwareAddress, pc_addr: ProtocolAddress, @@ -175,7 +175,7 @@ impl + AsMut<[u8]>> Packet { } /// Set target hardware address - pub fn set_target_map( + pub fn set_target_address( &mut self, hd_addr: HardwareAddress, pc_addr: ProtocolAddress, diff --git a/pkt/src/ip/arp/types.rs b/pkt/src/layer3/arp/types.rs similarity index 96% rename from pkt/src/ip/arp/types.rs rename to pkt/src/layer3/arp/types.rs index 4b39152..6c78312 100644 --- a/pkt/src/ip/arp/types.rs +++ b/pkt/src/layer3/arp/types.rs @@ -1,4 +1,4 @@ -use crate::{ip::ipv4::Address, mac}; +use crate::{layer2, layer3::ipv4::Address}; pub mod consts { pub const HARDWARE_ETHERNET: u16 = 1; @@ -15,7 +15,7 @@ pub mod consts { #[derive(Debug, PartialEq, Eq, Clone)] pub enum HardwareAddress { - Ethernet(mac::Address), + Ethernet(layer2::Address), Unknown(u16), } diff --git a/pkt/src/ip/cidr.rs b/pkt/src/layer3/cidr.rs similarity index 100% rename from pkt/src/ip/cidr.rs rename to pkt/src/layer3/cidr.rs diff --git a/pkt/src/ip/ipv4/address.rs b/pkt/src/layer3/ipv4/address.rs similarity index 100% rename from pkt/src/ip/ipv4/address.rs rename to pkt/src/layer3/ipv4/address.rs diff --git a/pkt/src/ip/ipv4/cidr.rs b/pkt/src/layer3/ipv4/cidr.rs similarity index 98% rename from pkt/src/ip/ipv4/cidr.rs rename to pkt/src/layer3/ipv4/cidr.rs index 27780c0..11772e8 100644 --- a/pkt/src/ip/ipv4/cidr.rs +++ b/pkt/src/layer3/ipv4/cidr.rs @@ -32,7 +32,7 @@ impl Cidr { prefix_len: netmask.count_ones() as u8, }) } else { - Err(Error::Illegal) + Err(Error::IllegalNetmask) } } diff --git a/pkt/src/layer3/ipv4/mod.rs b/pkt/src/layer3/ipv4/mod.rs new file mode 100644 index 0000000..cf9b9be --- /dev/null +++ b/pkt/src/layer3/ipv4/mod.rs @@ -0,0 +1,10 @@ +//! ipv4. + +mod address; +pub use address::*; + +mod cidr; +pub use cidr::*; + +mod packet; +pub use packet::*; diff --git a/pkt/src/ip/ipv4/packet.rs b/pkt/src/layer3/ipv4/packet.rs similarity index 98% rename from pkt/src/ip/ipv4/packet.rs rename to pkt/src/layer3/ipv4/packet.rs index a166a2b..3acb1bc 100644 --- a/pkt/src/ip/ipv4/packet.rs +++ b/pkt/src/layer3/ipv4/packet.rs @@ -1,6 +1,6 @@ use core::fmt::{self, Display, Formatter}; -use crate::{ip::Protocol, prelude::IntoInner, utils::checksum, Error, Result}; +use crate::{layer3::Protocol, prelude::IntoInner, utils::checksum, Error, Result}; use super::Address; use byteorder::{ByteOrder, NetworkEndian}; @@ -22,7 +22,7 @@ impl> Display for Packet { } } -mod field { +pub(crate) mod field { use crate::utils::field::Field; pub const VER_IHL: usize = 0; diff --git a/pkt/src/layer3/ipv6/mod.rs b/pkt/src/layer3/ipv6/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pkt/src/layer3/ipv6/mod.rs @@ -0,0 +1 @@ + diff --git a/pkt/src/layer3/mod.rs b/pkt/src/layer3/mod.rs new file mode 100644 index 0000000..fc9e7e1 --- /dev/null +++ b/pkt/src/layer3/mod.rs @@ -0,0 +1,17 @@ +// //! Ip layer's packet. + +pub mod arp; +pub mod ipv4; +// pub mod ipv6; + +mod address; +pub use address::*; + +mod protocol; +pub use protocol::*; + +mod cidr; +pub use cidr::*; + +mod packet; +pub use packet::*; diff --git a/pkt/src/layer3/packet.rs b/pkt/src/layer3/packet.rs new file mode 100644 index 0000000..f455848 --- /dev/null +++ b/pkt/src/layer3/packet.rs @@ -0,0 +1,27 @@ +use crate::{Error, Result}; + +use super::{arp, ipv4}; + +#[derive(Debug, Clone)] +pub enum IpPacket { + IPv4(ipv4::Packet), + Ipv6, +} + +impl> IpPacket { + pub fn parse(t: T) -> Result { + let data = t.as_ref(); + if data[ipv4::field::VER_IHL] >> 4 == 4 { + let pkt = ipv4::Packet::new_checked(t)?; + Ok(IpPacket::IPv4(pkt)) + } else { + Err(Error::UnknownIpVersionNumber) + } + } +} + +pub enum Packet { + Arp(arp::Packet), + IPv4(ipv4::Packet), + Ipv6, +} diff --git a/pkt/src/ip/protocol.rs b/pkt/src/layer3/protocol.rs similarity index 100% rename from pkt/src/ip/protocol.rs rename to pkt/src/layer3/protocol.rs diff --git a/pkt/src/lib.rs b/pkt/src/lib.rs index c097b17..49cb014 100644 --- a/pkt/src/lib.rs +++ b/pkt/src/lib.rs @@ -4,7 +4,10 @@ mod error; pub use error::*; -pub mod ip; -pub mod mac; -pub mod prelude; +pub mod layer2; +pub mod layer3; + +mod prelude; +pub use prelude::*; + pub mod utils; diff --git a/pkt/src/mac/protocol.rs b/pkt/src/mac/protocol.rs deleted file mode 100644 index d38fa60..0000000 --- a/pkt/src/mac/protocol.rs +++ /dev/null @@ -1,72 +0,0 @@ -use super::VlanId; - -pub mod consts { - pub const IPV4: u16 = 0x0800; - pub const IPV6: u16 = 0x86DD; - pub const ARP: u16 = 0x0806; - pub const IEEE802_1Q: u16 = 0x8100; - pub const Q_IN_Q: u16 = IEEE802_1Q; - pub const IEEE802_3: u16 = 0x05DC; -} - -/// Ethernet payload type. -#[derive(Debug, Clone)] -pub enum Protocol { - IPv4, - - IPv6, - - ARP, - - IEEE8021Q(VlanId), - - QinQ(VlanId, VlanId), - - /// IEEE802.3 - Length(u16), - - Unknown(u16), -} - -impl From for Protocol { - fn from(ty: u16) -> Self { - if ty < consts::IEEE802_3 { - Self::Length(ty) - } else { - match ty { - consts::ARP => Self::ARP, - consts::IPV4 => Self::IPv4, - consts::IPV6 => Self::IPv6, - _ => Self::Unknown(ty), - } - } - } -} - -impl From for u16 { - fn from(e: Protocol) -> u16 { - match e { - Protocol::ARP => consts::ARP, - Protocol::IPv4 => consts::IPV4, - Protocol::IPv6 => consts::IPV6, - Protocol::IEEE8021Q(_) => consts::IEEE802_1Q, - Protocol::QinQ(_, _) => consts::Q_IN_Q, - Protocol::Length(v) => v, - Protocol::Unknown(v) => v, - } - } -} - -impl From<&Protocol> for u16 { - fn from(e: &Protocol) -> u16 { - match e { - Protocol::ARP => consts::ARP, - Protocol::IPv4 => consts::IPV4, - Protocol::IPv6 => consts::IPV6, - Protocol::IEEE8021Q(_) => consts::IEEE802_1Q, - Protocol::QinQ(_, _) => consts::Q_IN_Q, - Protocol::Length(v) => *v, - Protocol::Unknown(v) => *v, - } - } -}