use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use super::error::PacketError;
use super::ethernet::EtherType;
use crate::object::Object;
#[derive(Debug, Clone)]
pub struct VlanHeader {
priority: ClassOfService, dei: bool, vlan_id: u16, ethertype: EtherType,
}
impl From<&VlanHeader> for Vec<u8> {
fn from(hdr: &VlanHeader) -> Self {
let mut bytes = Vec::new();
let prio_dei: u8 = (hdr.priority.0 << 5) | ((hdr.dei as u8) << 4);
let msb_vlan_id = ((hdr.vlan_id >> 8) & 0x0F) as u8; let lsb_vlan_id = (hdr.vlan_id & 0xFF) as u8; bytes.push(prio_dei | msb_vlan_id);
bytes.push(lsb_vlan_id);
bytes.extend_from_slice(&hdr.ethertype.0.to_be_bytes());
bytes
}
}
#[derive(Debug, Clone)]
pub struct Vlan {
header: RefCell<VlanHeader>,
pub rawdata: RefCell<Rc<Vec<u8>>>, pub offset: usize, pub inner: RefCell<Option<Rc<Object>>>, }
pub const VLAN_HEADER_SIZE: usize = 4;
#[derive(Debug, Clone)]
pub struct ClassOfService(pub u8);
#[allow(unused, non_upper_case_globals, non_snake_case)]
pub mod ClassesOfService {
use super::ClassOfService;
pub const BestEffort: ClassOfService = ClassOfService(0);
pub const Background: ClassOfService = ClassOfService(1);
pub const ExcellentEffort: ClassOfService = ClassOfService(2);
pub const CriticalApplications: ClassOfService = ClassOfService(3);
pub const VideoVoiceApplications: ClassOfService = ClassOfService(4);
pub const InternetworkControl: ClassOfService = ClassOfService(5);
pub const NetworkControl: ClassOfService = ClassOfService(6);
pub const Reserved: ClassOfService = ClassOfService(7);
}
impl fmt::Display for ClassOfService {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<ClassOfService> for u8 {
fn from(item: ClassOfService) -> Self {
item.0
}
}
impl fmt::Display for Vlan {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"<id:{},type:{}>",
self.header.borrow().vlan_id,
self.header.borrow().ethertype,
)?;
if let Some(inner) = self.inner.borrow().clone() {
write!(f, " {}", inner)
} else {
write!(f, " [len: {}]", self.rawdata.borrow().len())
}
}
}
impl From<&Vlan> for Vec<u8> {
fn from(vlan: &Vlan) -> Self {
let header = vlan.header.borrow().clone();
let mut bytes: Vec<u8> = (&header).into();
if let Some(inner) = vlan.inner.borrow().clone() {
let b: Vec<u8> = inner.as_ref().into();
bytes.extend_from_slice(&b);
} else {
let data = vlan.rawdata.borrow().clone();
bytes.extend_from_slice(&data[vlan.offset..]);
}
bytes
}
}
impl Vlan {
pub fn from_bytes(rawdata: Rc<Vec<u8>>, off: usize) -> Result<Self, PacketError> {
if rawdata.len() < off + VLAN_HEADER_SIZE {
return Err(PacketError::InvalidLength(rawdata.len()));
}
let priority = ClassOfService(rawdata[off] >> 5);
let dei = (rawdata[off] >> 4) & 1 == 1;
let vlan_id = (((rawdata[off] as u16) & 0x0F) << 8) | (rawdata[off + 1] as u16);
let ethertype = EtherType(((rawdata[off + 2] as u16) << 8) | (rawdata[off + 3] as u16));
let offset = off + VLAN_HEADER_SIZE;
let header = RefCell::new(VlanHeader {
priority,
dei,
vlan_id,
ethertype,
});
Ok(Self {
header,
rawdata: RefCell::new(rawdata),
offset,
inner: RefCell::new(None),
})
}
pub fn get_ethertype_raw(&self) -> EtherType {
self.header.borrow().ethertype.clone()
}
pub fn get_priority(&self) -> Rc<Object> {
let priority: u8 = self.header.borrow().priority.clone().into();
Rc::new(Object::Integer(priority as i64))
}
pub fn get_dei(&self) -> Rc<Object> {
Rc::new(Object::Bool(self.header.borrow().dei))
}
pub fn get_vlan_id(&self) -> Rc<Object> {
Rc::new(Object::Integer(self.header.borrow().vlan_id as i64))
}
pub fn get_ethertype(&self) -> Rc<Object> {
Rc::new(Object::Integer(self.header.borrow().ethertype.0 as i64))
}
pub fn set_priority(&self, priority: Rc<Object>) -> Result<(), String> {
match priority.as_ref() {
Object::Integer(priority) => {
if *priority < 0 || *priority > 7 {
return Err("Invalid value for VLAN property priority".to_string());
}
self.header.borrow_mut().priority = ClassOfService(*priority as u8);
Ok(())
}
_ => Err("Invalid value for VLAN property priority".to_string()),
}
}
pub fn set_dei(&self, dei: Rc<Object>) -> Result<(), String> {
match dei.as_ref() {
Object::Bool(dei) => {
self.header.borrow_mut().dei = *dei;
Ok(())
}
_ => Err("Invalid value for VLAN property dei".to_string()),
}
}
pub fn set_vlan_id(&self, vlan_id: Rc<Object>) -> Result<(), String> {
match vlan_id.as_ref() {
Object::Integer(vlan_id) => {
if *vlan_id < 0 || *vlan_id > 4095 {
return Err("Invalid value for VLAN property vlan_id".to_string());
}
self.header.borrow_mut().vlan_id = *vlan_id as u16;
Ok(())
}
_ => Err("Invalid value for VLAN property vlan_id".to_string()),
}
}
pub fn set_ethertype(&self, ethertype: Rc<Object>) -> Result<(), String> {
match ethertype.as_ref() {
Object::Integer(ethertype) => {
if *ethertype < 0 || *ethertype > 65535 {
return Err("Invalid value for VLAN property ethertype".to_string());
}
self.header.borrow_mut().ethertype = EtherType(*ethertype as u16);
Ok(())
}
_ => Err("Invalid value for VLAN property ethertype".to_string()),
}
}
}