packet/ether/
packet.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use 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
24/// Ethernet frame parser.
25pub 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	/// Create an Ethernet frame without checking the buffer.
55	pub fn unchecked(buffer: B) -> Packet<B> {
56		Packet { buffer }
57	}
58
59	/// Parse an Ethernet frame, checking the buffer contents are correct.
60	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	/// Convert the packet to its owned version.
75	///
76	/// # Notes
77	///
78	/// It would be nice if `ToOwned` could be implemented, but `Packet` already
79	/// implements `Clone` and the impl would conflict.
80	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	/// MAC address for the destination.
128	pub fn destination(&self) -> HwAddr {
129		self.buffer.as_ref()[0 .. 6].into()
130	}
131
132	/// MAC address for the source.
133	pub fn source(&self) -> HwAddr {
134		self.buffer.as_ref()[6 .. 12].into()
135	}
136
137	/// Protocol of the inner packet.
138	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	/// Destination MAC address.
145	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	/// Source MAC address.
152	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	/// Inner protocol.
159	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}