1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
use nom::{rest,be_u16}; use {ParseOps,ConvError}; use packet_writer::{PacketWriter,WriteFields}; named!(bytes_to_ethernet<&[u8], EthHdr>, do_parse!( src: take!(6) >> dest: take!(6) >> eth_type: be_u16 >> (EthHdr { mac_src: src, mac_dest: dest, eth_type: EthType::from(eth_type) }) )); named!(strip_ethernet<&[u8]>, do_parse!( take!(14) >> inner_bytes: rest >> (inner_bytes) )); c_enum!(EthType, u16, { IPv4 => 0x0800 }); #[derive(Debug,PartialEq)] pub struct EthHdr<'a> { mac_src: &'a [u8], mac_dest: &'a [u8], eth_type: EthType, } impl<'a> ParseOps<'a> for EthHdr<'a> { fn to_bytes(self) -> Result<Vec<u8>, ConvError> { let mut pw = PacketWriter::new(); pw.write_bytes(self.mac_src)?; pw.write_bytes(self.mac_dest)?; <PacketWriter as WriteFields<Vec<u8>>>::write_u16::<u16>( &mut pw, self.eth_type as u16 )?; Ok(pw.get_result()) } fn from_bytes(buf: &'a [u8]) -> Result<Self, ConvError> { match bytes_to_ethernet(buf) { Ok((_, ip)) => Ok(ip), Err(e) => { Err(ConvError( format!("Failed to parse - here is the remaining output: {:?}", e) )) }, } } fn strip_header(buf: &[u8]) -> Result<&[u8], ConvError> { match strip_ethernet(buf) { Ok((_, eth)) => Ok(eth), Err(e) => { Err(ConvError( format!("Failed to parse - here is the remaining output: {:?}", e) )) }, } } } #[cfg(test)] mod test { use super::*; #[test] fn test_write_header() { assert_eq!(EthHdr { mac_src: &[1, 2, 3, 4, 5, 6], mac_dest: &[7, 8, 9, 10, 11, 12], eth_type: EthType::IPv4, }.to_bytes().unwrap(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0x08, 0x00]) } #[test] fn test_parse_header() { let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0x08, 0x00, 15, 16, 17]; assert_eq!(EthHdr { mac_src: &[1, 2, 3, 4, 5, 6], mac_dest: &[7, 8, 9, 10, 11, 12], eth_type: EthType::IPv4 }, EthHdr::from_bytes(s).unwrap()) } #[test] fn test_strip_header() { let s = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; assert_eq!(EthHdr::strip_header(s).unwrap(), &[15, 16, 17]) } }