1use std::fmt;
16use std::io::Cursor;
17use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
18use hwaddr::HwAddr;
19
20use crate::error::*;
21use crate::packet::{Packet as P, PacketMut as PM, AsPacket, AsPacketMut};
22use crate::ether::Protocol;
23
24pub struct Packet<B> {
26 pub(crate) buffer: B,
27}
28
29sized!(Packet,
30 header {
31 min: 14,
32 max: 14,
33 size: 14,
34 }
35
36 payload {
37 min: 0,
38 max: 1486,
39 size: p => p.buffer.as_ref().len() - 14,
40 });
41
42impl<B: AsRef<[u8]>> fmt::Debug for Packet<B> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.debug_struct("ether::Packet")
45 .field("destination", &self.source())
46 .field("source", &self.destination())
47 .field("protocol", &self.protocol())
48 .field("payload", &self.payload())
49 .finish()
50 }
51}
52
53impl<B: AsRef<[u8]>> Packet<B> {
54 pub fn unchecked(buffer: B) -> Packet<B> {
56 Packet { buffer }
57 }
58
59 pub fn new(buffer: B) -> Result<Packet<B>> {
61 use crate::size::header::Min;
62
63 let packet = Packet::unchecked(buffer);
64
65 if packet.buffer.as_ref().len() < Self::min() {
66 Err(Error::SmallBuffer)?
67 }
68
69 Ok(packet)
70 }
71}
72
73impl<B: AsRef<[u8]>> Packet<B> {
74 pub fn to_owned(&self) -> Packet<Vec<u8>> {
81 Packet::unchecked(self.buffer.as_ref().to_vec())
82 }
83}
84
85impl<B: AsRef<[u8]>> AsRef<[u8]> for Packet<B> {
86 fn as_ref(&self) -> &[u8] {
87 use crate::size::Size;
88
89 &self.buffer.as_ref()[.. self.size()]
90 }
91}
92
93impl<B: AsRef<[u8]> + AsMut<[u8]>> AsMut<[u8]> for Packet<B> {
94 fn as_mut(&mut self) -> &mut [u8] {
95 use crate::size::Size;
96
97 let size = self.size();
98 &mut self.buffer.as_mut()[.. size]
99 }
100}
101
102impl<'a, B: AsRef<[u8]>> AsPacket<'a, Packet<&'a [u8]>> for B {
103 fn as_packet(&self) -> Result<Packet<&[u8]>> {
104 Packet::new(self.as_ref())
105 }
106}
107
108impl<'a, B: AsRef<[u8]> + AsMut<[u8]>> AsPacketMut<'a, Packet<&'a mut [u8]>> for B {
109 fn as_packet_mut(&mut self) -> Result<Packet<&mut [u8]>> {
110 Packet::new(self.as_mut())
111 }
112}
113
114impl<B: AsRef<[u8]>> P for Packet<B> {
115 fn split(&self) -> (&[u8], &[u8]) {
116 self.buffer.as_ref().split_at(14)
117 }
118}
119
120impl<B: AsRef<[u8]> + AsMut<[u8]>> PM for Packet<B> {
121 fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) {
122 self.buffer.as_mut().split_at_mut(14)
123 }
124}
125
126impl<B: AsRef<[u8]>> Packet<B> {
127 pub fn destination(&self) -> HwAddr {
129 self.buffer.as_ref()[0 .. 6].into()
130 }
131
132 pub fn source(&self) -> HwAddr {
134 self.buffer.as_ref()[6 .. 12].into()
135 }
136
137 pub fn protocol(&self) -> Protocol {
139 (&self.buffer.as_ref()[12 ..]).read_u16::<BigEndian>().unwrap().into()
140 }
141}
142
143impl<B: AsRef<[u8]> + AsMut<[u8]>> Packet<B> {
144 pub fn set_destination(&mut self, value: HwAddr) -> Result<&mut Self> {
146 self.buffer.as_mut()[0 .. 6].copy_from_slice(&value.octets());
147
148 Ok(self)
149 }
150
151 pub fn set_source(&mut self, value: HwAddr) -> Result<&mut Self> {
153 self.buffer.as_mut()[6 .. 12].copy_from_slice(&value.octets());
154
155 Ok(self)
156 }
157
158 pub fn set_protocol(&mut self, value: Protocol) -> Result<&mut Self> {
160 Cursor::new(&mut self.buffer.as_mut()[12 ..])
161 .write_u16::<BigEndian>(value.into())?;
162
163 Ok(self)
164 }
165}
166
167#[cfg(test)]
168mod test {
169 use crate::packet::Packet;
170 use crate::ether;
171 use crate::ip;
172 use crate::udp;
173
174 #[test]
175 fn values() {
176 let raw = [0x00u8, 0x23, 0x69, 0x63, 0x59, 0xbe, 0xe4, 0xb3, 0x18, 0x26, 0x63, 0xa3, 0x08, 0x00, 0x45, 0x00, 0x00, 0x42, 0x47, 0x07, 0x40, 0x00, 0x40, 0x11, 0x6e, 0xcc, 0xc0, 0xa8, 0x01, 0x89, 0xc0, 0xa8, 0x01, 0xfe, 0xba, 0x2f, 0x00, 0x35, 0x00, 0x2e, 0x1d, 0xf8, 0xbc, 0x81, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x61, 0x70, 0x69, 0x0c, 0x73, 0x74, 0x65, 0x61, 0x6d, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x65, 0x64, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x1c, 0x00, 0x01];
177
178 let ether = ether::Packet::new(&raw[..]).unwrap();
179 let ip = ip::v4::Packet::new(ether.payload()).unwrap();
180 let udp = udp::Packet::new(ip.payload()).unwrap();
181
182 assert!(ip.is_valid());
183 assert!(udp.is_valid(&ip::Packet::from(&ip)));
184
185 assert_eq!(ether.destination(), "00:23:69:63:59:be".parse().unwrap());
186 assert_eq!(ether.source(), "e4:b3:18:26:63:a3".parse().unwrap());
187 assert_eq!(ether.protocol(), ether::Protocol::Ipv4);
188 }
189}