Skip to main content

packet/ip/
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 crate::error::*;
16use crate::packet::{Packet as P, PacketMut as PM, AsPacket, AsPacketMut};
17use crate::size;
18use crate::ip::{v4, v6};
19
20/// Generic IP packet.
21#[derive(Debug)]
22pub enum Packet<B: AsRef<[u8]>> {
23	/// IPv4 packet.
24	V4(v4::Packet<B>),
25
26	/// IPv6 packet.
27	V6(v6::Packet<B>),
28}
29
30impl<B: AsRef<[u8]>> Packet<B> {
31	/// Create an IP packet without checking the buffer.
32	///
33	/// # Note
34	///
35	/// This still checks the version field to pick an IPv4 or IPv6 packet.
36	pub fn unchecked(buffer: B) -> Packet<B> {
37		match buffer.as_ref()[0] >> 4 {
38			4 =>
39				Packet::V4(v4::Packet::unchecked(buffer)),
40
41			6 =>
42				Packet::V6(v6::Packet::unchecked(buffer)),
43
44			_ =>
45				panic!("not an IPv4 or IPv6 packet")
46		}
47	}
48
49	/// Parse an IP packet without checking the payload.
50	pub fn no_payload(buffer: B) -> Result<Packet<B>> {
51		match buffer.as_ref()[0] >> 4 {
52			4 =>
53				v4::Packet::no_payload(buffer).map(Packet::V4),
54
55			6 =>
56				v6::Packet::no_payload(buffer).map(Packet::V6),
57
58			_ =>
59				Err(Error::InvalidPacket)
60		}
61	}
62
63	/// Parse an IP packet, checking the buffer contents are correct.
64	pub fn new(buffer: B) -> Result<Packet<B>> {
65		match buffer.as_ref()[0] >> 4 {
66			4 =>
67				v4::Packet::new(buffer).map(Packet::V4),
68
69			6 =>
70				v6::Packet::new(buffer).map(Packet::V6),
71
72			_ =>
73				Err(Error::InvalidPacket)
74		}
75	}
76}
77
78impl<B: AsRef<[u8]>> From<v4::Packet<B>> for Packet<B> {
79	fn from(value: v4::Packet<B>) -> Packet<B> {
80		Packet::V4(value)
81	}
82}
83
84impl<B: AsRef<[u8]>> From<v6::Packet<B>> for Packet<B> {
85	fn from(value: v6::Packet<B>) -> Packet<B> {
86		Packet::V6(value)
87	}
88}
89
90impl<'a, B: AsRef<[u8]> + Clone> From<&'a v4::Packet<B>> for Packet<B> {
91	fn from(value: &'a v4::Packet<B>) -> Packet<B> {
92		Packet::V4(value.clone())
93	}
94}
95
96impl<'a, B: AsRef<[u8]> + Clone> From<&'a v6::Packet<B>> for Packet<B> {
97	fn from(value: &'a v6::Packet<B>) -> Packet<B> {
98		Packet::V6(value.clone())
99	}
100}
101
102impl<B: AsRef<[u8]>> Packet<B> {
103	/// Convert the packet to its owned version.
104	///
105	/// # Notes
106	///
107	/// It would be nice if `ToOwned` could be implemented, but `Packet` already
108	/// implements `Clone` and the impl would conflict.
109	pub fn to_owned(&self) -> Packet<Vec<u8>> {
110		match *self {
111			Packet::V4(ref packet) =>
112				Packet::V4(packet.to_owned()),
113
114			Packet::V6(ref packet) =>
115				Packet::V6(packet.to_owned()),
116		}
117	}
118}
119
120impl<B: AsRef<[u8]>> AsRef<[u8]> for Packet<B> {
121	fn as_ref(&self) -> &[u8] {
122		match *self {
123			Packet::V4(ref packet) =>
124				packet.as_ref(),
125
126			Packet::V6(ref packet) =>
127				packet.as_ref(),
128		}
129	}
130}
131
132impl<B: AsRef<[u8]> + AsMut<[u8]>> AsMut<[u8]> for Packet<B> {
133	fn as_mut(&mut self) -> &mut [u8] {
134		match *self {
135			Packet::V4(ref mut packet) =>
136				packet.as_mut(),
137
138			Packet::V6(ref mut packet) =>
139				packet.as_mut(),
140		}
141	}
142}
143
144impl<'a, B: AsRef<[u8]>> AsPacket<'a, Packet<&'a [u8]>> for B {
145	fn as_packet(&self) -> Result<Packet<&[u8]>> {
146		Packet::new(self.as_ref())
147	}
148}
149
150impl<'a, B: AsRef<[u8]> + AsMut<[u8]>> AsPacketMut<'a, Packet<&'a mut [u8]>> for B {
151	fn as_packet_mut(&mut self) -> Result<Packet<&mut [u8]>> {
152		Packet::new(self.as_mut())
153	}
154}
155
156impl<B: AsRef<[u8]>> P for Packet<B> {
157	fn split(&self) -> (&[u8], &[u8]) {
158		match *self {
159			Packet::V4(ref packet) =>
160				packet.split(),
161
162			Packet::V6(ref packet) =>
163				packet.split(),
164		}
165	}
166}
167
168impl<B: AsRef<[u8]> + AsMut<[u8]>> PM for Packet<B> {
169	fn split_mut(&mut self) -> (&mut [u8], &mut [u8]) {
170		match *self {
171			Packet::V4(ref mut packet) =>
172				packet.split_mut(),
173
174			Packet::V6(ref mut packet) =>
175				packet.split_mut(),
176		}
177	}
178}
179
180impl<B: AsRef<[u8]>> size::header::Size for Packet<B> {
181	fn size(&self) -> usize {
182		match *self {
183			Packet::V4(ref packet) =>
184				size::header::Size::size(packet),
185
186			Packet::V6(ref packet) =>
187				size::header::Size::size(packet),
188		}
189	}
190}
191
192impl<B: AsRef<[u8]>> size::payload::Size for Packet<B> {
193	fn size(&self) -> usize {
194		match *self {
195			Packet::V4(ref packet) =>
196				size::payload::Size::size(packet),
197
198			Packet::V6(ref packet) =>
199				size::payload::Size::size(packet),
200		}
201	}
202}