1#![deny(missing_docs)]
11
12pub mod ipv4;
13pub mod ipv6;
14pub mod link;
15pub mod records;
16
17use packet::{
18 BufferView, BufferViewMut, FragmentedBytesMut, PacketBuilder, PacketConstraints,
19 ParsablePacket, ParseMetadata, SerializeTarget,
20};
21use thiserror::Error;
22use zerocopy::byteorder::network_endian::{U16, U32};
23use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned};
24
25#[derive(Error, Debug, PartialEq)]
27pub enum ParseError {
28 #[error("Too few bytes for header.")]
30 InsufficientHeaderBytes,
31 #[error("Too few bytes for body (per header).")]
33 InsufficientBodyBytes,
34 #[error("Too many bytes for body (per header).")]
36 ExcessBodyBytes,
37}
38
39#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
40#[repr(C)]
41struct PppHeader {
42 protocol: U16,
43}
44
45impl PppHeader {
46 pub fn protocol(&self) -> u16 {
47 self.protocol.get()
48 }
49}
50
51pub struct PppPacket<B> {
53 header: Ref<B, PppHeader>,
54 body: B,
55}
56
57impl<B: SplitByteSlice> PppPacket<B> {
58 pub fn protocol(&self) -> u16 {
60 self.header.protocol()
61 }
62}
63
64impl<B: SplitByteSlice> ParsablePacket<B, ()> for PppPacket<B> {
65 type Error = ParseError;
66
67 fn parse_metadata(&self) -> ParseMetadata {
68 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
69 }
70
71 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
72 let header =
73 buffer.take_obj_front::<PppHeader>().ok_or(ParseError::InsufficientHeaderBytes)?;
74 Ok(Self { header, body: buffer.into_rest() })
75 }
76}
77
78pub struct PppPacketBuilder {
80 protocol: u16,
81}
82
83impl PppPacketBuilder {
84 pub fn new(protocol: u16) -> Self {
86 Self { protocol }
87 }
88}
89
90impl PacketBuilder for PppPacketBuilder {
91 fn constraints(&self) -> PacketConstraints {
92 PacketConstraints::new(std::mem::size_of::<PppHeader>(), 0, 0, usize::max_value())
93 }
94
95 fn serialize(&self, target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {
96 let mut header = (&mut target.header).take_obj_front_zero::<PppHeader>().unwrap();
97 header.protocol = U16::new(self.protocol);
98 }
99}
100
101#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
102#[repr(C)]
103struct ControlProtocolHeader {
104 code: u8,
105 identifier: u8,
106 length: U16,
107}
108
109impl ControlProtocolHeader {
110 pub fn code(&self) -> u8 {
111 self.code
112 }
113
114 pub fn identifier(&self) -> u8 {
115 self.identifier
116 }
117
118 pub fn length(&self) -> u16 {
119 self.length.get()
120 }
121}
122
123pub struct ControlProtocolPacket<B> {
125 header: Ref<B, ControlProtocolHeader>,
126 body: B,
127}
128
129impl<B: SplitByteSlice> ControlProtocolPacket<B> {
130 pub fn code(&self) -> u8 {
132 self.header.code()
133 }
134
135 pub fn identifier(&self) -> u8 {
137 self.header.identifier()
138 }
139}
140
141impl<B: SplitByteSlice> ParsablePacket<B, ()> for ControlProtocolPacket<B> {
142 type Error = ParseError;
143
144 fn parse_metadata(&self) -> ParseMetadata {
145 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
146 }
147
148 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
149 let header = buffer
150 .take_obj_front::<ControlProtocolHeader>()
151 .ok_or(ParseError::InsufficientHeaderBytes)?;
152
153 let body_length = (header.length() as usize)
154 .checked_sub(Ref::bytes(&header).len())
155 .ok_or(ParseError::InsufficientBodyBytes)?;
156
157 let padding = buffer.len().checked_sub(body_length).ok_or(ParseError::ExcessBodyBytes)?;
158
159 buffer.take_back(padding).unwrap();
163
164 Ok(Self { header, body: buffer.into_rest() })
165 }
166}
167
168pub struct ControlProtocolPacketBuilder {
170 code: u8,
171 identifier: u8,
172}
173
174impl ControlProtocolPacketBuilder {
175 pub fn new(code: u8, identifier: u8) -> Self {
177 Self { code, identifier }
178 }
179}
180
181impl PacketBuilder for ControlProtocolPacketBuilder {
182 fn constraints(&self) -> PacketConstraints {
183 PacketConstraints::new(
184 std::mem::size_of::<ControlProtocolHeader>(),
185 0,
186 0,
187 usize::max_value(),
188 )
189 }
190
191 fn serialize(&self, target: &mut SerializeTarget<'_>, body: FragmentedBytesMut<'_, '_>) {
192 let mut header = &mut target.header;
193 let mut header = header.take_obj_front_zero::<ControlProtocolHeader>().unwrap();
194
195 let length = body
196 .len()
197 .try_into()
198 .ok()
199 .and_then(|c: u16| c.checked_add(self.constraints().header_len() as u16))
200 .unwrap();
201
202 header.code = self.code;
203 header.identifier = self.identifier;
204 header.length = U16::new(length);
205 }
206}
207
208pub struct ConfigurationPacket<B> {
210 body: B,
211}
212
213impl<B: SplitByteSlice> ParsablePacket<B, ()> for ConfigurationPacket<B> {
214 type Error = ParseError;
215
216 fn parse_metadata(&self) -> ParseMetadata {
217 ParseMetadata::from_packet(0, self.body.len(), 0)
218 }
219
220 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, Self::Error> {
221 Ok(Self { body: buffer.into_rest() })
222 }
223}
224
225#[derive(Default)]
227pub struct ConfigurationPacketBuilder;
228
229impl ConfigurationPacketBuilder {
230 pub fn new() -> Self {
232 Self {}
233 }
234}
235
236impl PacketBuilder for ConfigurationPacketBuilder {
237 fn constraints(&self) -> PacketConstraints {
238 PacketConstraints::new(0, 0, 0, usize::max_value())
239 }
240
241 fn serialize(&self, _target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {}
242}
243
244pub struct TerminationPacket<B> {
246 body: B,
247}
248
249impl<B: SplitByteSlice> ParsablePacket<B, ()> for TerminationPacket<B> {
250 type Error = ParseError;
251
252 fn parse_metadata(&self) -> ParseMetadata {
253 ParseMetadata::from_packet(0, self.body.len(), 0)
254 }
255
256 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, Self::Error> {
257 Ok(Self { body: buffer.into_rest() })
258 }
259}
260
261#[derive(Default)]
263pub struct TerminationPacketBuilder;
264
265impl TerminationPacketBuilder {
266 pub fn new() -> Self {
268 Self {}
269 }
270}
271
272impl PacketBuilder for TerminationPacketBuilder {
273 fn constraints(&self) -> PacketConstraints {
274 PacketConstraints::new(0, 0, 0, usize::max_value())
275 }
276
277 fn serialize(&self, _target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {}
278}
279
280pub struct CodeRejectPacket<B> {
282 body: B,
283}
284
285impl<B: SplitByteSlice> ParsablePacket<B, ()> for CodeRejectPacket<B> {
286 type Error = ParseError;
287
288 fn parse_metadata(&self) -> ParseMetadata {
289 ParseMetadata::from_packet(0, self.body.len(), 0)
290 }
291
292 fn parse<BV: BufferView<B>>(buffer: BV, _args: ()) -> Result<Self, Self::Error> {
293 Ok(Self { body: buffer.into_rest() })
294 }
295}
296
297#[derive(Default)]
299pub struct CodeRejectPacketBuilder;
300
301impl CodeRejectPacketBuilder {
302 pub fn new() -> Self {
304 Self {}
305 }
306}
307
308impl PacketBuilder for CodeRejectPacketBuilder {
309 fn constraints(&self) -> PacketConstraints {
310 PacketConstraints::new(0, 0, 0, usize::max_value())
311 }
312
313 fn serialize(&self, _target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {}
314}
315
316#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
317#[repr(C)]
318struct ProtocolRejectHeader {
319 rejected_protocol: U16,
320}
321
322impl ProtocolRejectHeader {
323 pub fn rejected_protocol(&self) -> u16 {
324 self.rejected_protocol.get()
325 }
326}
327
328pub struct ProtocolRejectPacket<B> {
330 header: Ref<B, ProtocolRejectHeader>,
331 body: B,
332}
333
334impl<B: SplitByteSlice> ProtocolRejectPacket<B> {
335 pub fn rejected_protocol(&self) -> u16 {
337 self.header.rejected_protocol()
338 }
339}
340
341impl<B: SplitByteSlice> ParsablePacket<B, ()> for ProtocolRejectPacket<B> {
342 type Error = ParseError;
343
344 fn parse_metadata(&self) -> ParseMetadata {
345 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
346 }
347
348 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
349 let header = buffer
350 .take_obj_front::<ProtocolRejectHeader>()
351 .ok_or(ParseError::InsufficientHeaderBytes)?;
352 Ok(Self { header, body: buffer.into_rest() })
353 }
354}
355
356pub struct ProtocolRejectPacketBuilder {
358 rejected_protocol: u16,
359}
360
361impl ProtocolRejectPacketBuilder {
362 pub fn new(rejected_protocol: u16) -> Self {
364 Self { rejected_protocol }
365 }
366}
367
368impl PacketBuilder for ProtocolRejectPacketBuilder {
369 fn constraints(&self) -> PacketConstraints {
370 PacketConstraints::new(
371 std::mem::size_of::<ProtocolRejectHeader>(),
372 0,
373 0,
374 usize::max_value(),
375 )
376 }
377
378 fn serialize(&self, target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {
379 let mut header =
380 (&mut target.header).take_obj_front_zero::<ProtocolRejectHeader>().unwrap();
381 header.rejected_protocol = U16::new(self.rejected_protocol);
382 }
383}
384
385#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
386#[repr(C)]
387struct EchoDiscardHeader {
388 magic_number: U32,
389}
390
391impl EchoDiscardHeader {
392 pub fn magic_number(&self) -> u32 {
393 self.magic_number.get()
394 }
395}
396
397pub struct EchoDiscardPacket<B> {
399 header: Ref<B, EchoDiscardHeader>,
400 body: B,
401}
402
403impl<B: SplitByteSlice> EchoDiscardPacket<B> {
404 pub fn magic_number(&self) -> u32 {
406 self.header.magic_number()
407 }
408}
409
410impl<B: SplitByteSlice> ParsablePacket<B, ()> for EchoDiscardPacket<B> {
411 type Error = ParseError;
412
413 fn parse_metadata(&self) -> ParseMetadata {
414 ParseMetadata::from_packet(Ref::bytes(&self.header).len(), self.body.len(), 0)
415 }
416
417 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
418 let header = buffer
419 .take_obj_front::<EchoDiscardHeader>()
420 .ok_or(ParseError::InsufficientHeaderBytes)?;
421 Ok(Self { header, body: buffer.into_rest() })
422 }
423}
424
425pub struct EchoDiscardPacketBuilder {
427 magic_number: u32,
428}
429
430impl EchoDiscardPacketBuilder {
431 pub fn new(magic_number: u32) -> Self {
433 Self { magic_number }
434 }
435}
436
437impl PacketBuilder for EchoDiscardPacketBuilder {
438 fn constraints(&self) -> PacketConstraints {
439 PacketConstraints::new(std::mem::size_of::<EchoDiscardHeader>(), 0, 0, usize::max_value())
440 }
441
442 fn serialize(&self, target: &mut SerializeTarget<'_>, _body: FragmentedBytesMut<'_, '_>) {
443 let mut header = (&mut target.header).take_obj_front_zero::<EchoDiscardHeader>().unwrap();
444 header.magic_number = U32::new(self.magic_number);
445 }
446}
447
448#[cfg(test)]
449mod tests {
450 use super::*;
451 use crate::records::options::{Options, OptionsSerializer};
452 use packet::{Buf, InnerPacketBuilder, ParseBuffer, Serializer};
453
454 #[fuchsia::test]
455 fn test_link_parse_serialize() {
456 let expected_link_options = [
457 link::ControlOption::MaximumReceiveUnit(0x8888),
458 link::ControlOption::AddressControlFieldCompression,
459 link::ControlOption::QualityProtocol(0xc025, vec![0xab, 0xcd, 0xef]),
460 link::ControlOption::MagicNumber(0x01234567),
461 ];
462
463 const EXPECT_BUFFER: [u8; 25] = [
464 0xc0, 0x21, 3, 0xe6, 0x00, 0x17, 1, 4, 0x05, 0xdc, 8, 2, 4, 7, 0xc0, 0x25, 0xab, 0xcd,
465 0xef, 5, 6, 0x01, 0x23, 0x45, 0x67,
466 ];
467
468 let buf: [u8; 25] = [
469 0xc0, 0x21, 1, 0xe6, 0x00, 0x17, 1, 4, 0x88, 0x88, 8, 2, 4, 7, 0xc0, 0x25, 0xab, 0xcd,
470 0xef, 5, 6, 0x01, 0x23, 0x45, 0x67,
471 ];
472
473 let mut buf = Buf::new(buf, ..);
474
475 let ppp = buf.parse::<PppPacket<_>>().unwrap();
476 let protocol = ppp.protocol();
477 assert_eq!(protocol, 0xc021);
478
479 let lcp = buf.parse::<ControlProtocolPacket<_>>().unwrap();
480 let code = lcp.code();
481 let identifier = lcp.identifier();
482 assert_eq!(code, 1);
483 assert_eq!(identifier, 0xe6);
484
485 let _configuration_packet = buf.parse::<ConfigurationPacket<_>>().unwrap();
486 let mut options: Vec<_> = Options::<_, link::ControlOptionsImpl>::parse(buf.as_ref())
487 .map(|options| options.iter().collect())
488 .unwrap();
489
490 assert_eq!(options, expected_link_options);
491
492 if let link::ControlOption::MaximumReceiveUnit(ref mut mru) = options[0] {
493 *mru = 0x05dc;
494 };
495
496 let buffer = OptionsSerializer::<link::ControlOptionsImpl, link::ControlOption, _>::new(
497 options.iter(),
498 )
499 .into_serializer()
500 .encapsulate(ControlProtocolPacketBuilder::new(3, identifier))
501 .encapsulate(PppPacketBuilder::new(protocol))
502 .serialize_vec_outer()
503 .ok()
504 .unwrap();
505
506 assert_eq!(buffer.as_ref(), EXPECT_BUFFER);
507 }
508
509 #[fuchsia::test]
510 fn test_ipv4_parse_serialize() {
511 let expected_ipv4_options = [
512 ipv4::ControlOption::Unrecognized(0xa, vec![0x01, 0x02, 0x03]),
513 ipv4::ControlOption::IpAddress(0xffee_ddcc),
514 ipv4::ControlOption::IpCompressionProtocol(0x002d, vec![0x89]),
515 ];
516 const EXPECT_BUFFER: [u8; 22] = [
517 0x80, 0x21, 4, 0x03, 0x00, 0x14, 0xa, 5, 0x01, 0x02, 0x03, 0x3, 6, 0xaa, 0xbb, 0xcc,
518 0xdd, 0x2, 5, 0x00, 0x2d, 0x89,
519 ];
520
521 let buf: [u8; 22] = [
522 0x80, 0x21, 1, 0x03, 0x00, 0x14, 0xa, 5, 0x01, 0x02, 0x03, 0x3, 6, 0xff, 0xee, 0xdd,
523 0xcc, 0x2, 5, 0x00, 0x2d, 0x89,
524 ];
525
526 let mut buf = Buf::new(buf, ..);
527
528 let ppp = buf.parse::<PppPacket<_>>().unwrap();
529 let protocol = ppp.protocol();
530 assert_eq!(protocol, 0x8021);
531
532 let lcp = buf.parse::<ControlProtocolPacket<_>>().unwrap();
533 let code = lcp.code();
534 let identifier = lcp.identifier();
535 assert_eq!(code, 1);
536 assert_eq!(identifier, 0x03);
537
538 let _configuration_packet = buf.parse::<ConfigurationPacket<_>>().unwrap();
539 let mut options: Vec<_> = Options::<_, ipv4::ControlOptionsImpl>::parse(buf.as_ref())
540 .map(|options| options.iter().collect())
541 .unwrap();
542
543 assert_eq!(options, expected_ipv4_options);
544
545 if let ipv4::ControlOption::IpAddress(ref mut address) = options[1] {
546 *address = 0xaabbccdd;
547 };
548
549 let buffer = OptionsSerializer::<ipv4::ControlOptionsImpl, ipv4::ControlOption, _>::new(
550 options.iter(),
551 )
552 .into_serializer()
553 .encapsulate(ControlProtocolPacketBuilder::new(4, identifier))
554 .encapsulate(PppPacketBuilder::new(protocol))
555 .serialize_vec_outer()
556 .ok()
557 .unwrap();
558
559 assert_eq!(buffer.as_ref(), EXPECT_BUFFER);
560 }
561
562 #[fuchsia::test]
563 fn test_ipv6_parse_serialize() {
564 let expected_ipv6_options = [
565 ipv6::ControlOption::Unrecognized(0x5, vec![0x99]),
566 ipv6::ControlOption::InterfaceIdentifier(0x0123_4567_890a_bcde),
567 ];
568
569 const EXPECT_BUFFER: [u8; 21] = [
570 0x80, 0x57, 2, 0x09, 0x00, 0x13, 0x5, 5, 0x99, 0x88, 0x77, 0x01, 10, 0x01, 0x23, 0x45,
571 0x67, 0x89, 0x0a, 0xbc, 0xde,
572 ];
573
574 let buf: [u8; 19] = [
575 0x80, 0x57, 1, 0x09, 0x00, 0x11, 0x5, 3, 0x99, 0x01, 10, 0x01, 0x23, 0x45, 0x67, 0x89,
576 0x0a, 0xbc, 0xde,
577 ];
578
579 let mut buf = Buf::new(buf, ..);
580
581 let ppp = buf.parse::<PppPacket<_>>().unwrap();
582 let protocol = ppp.protocol();
583 assert_eq!(protocol, 0x8057);
584
585 let lcp = buf.parse::<ControlProtocolPacket<_>>().unwrap();
586 let code = lcp.code();
587 let identifier = lcp.identifier();
588 assert_eq!(code, 1);
589 assert_eq!(identifier, 0x09);
590
591 let _configuration_packet = buf.parse::<ConfigurationPacket<_>>().unwrap();
592 let mut options: Vec<_> = Options::<_, ipv6::ControlOptionsImpl>::parse(buf.as_ref())
593 .map(|options| options.iter().collect())
594 .unwrap();
595
596 assert_eq!(options, expected_ipv6_options);
597
598 if let ipv6::ControlOption::Unrecognized(ref mut _type, ref mut data) = options[0] {
599 data.push(0x88);
600 data.push(0x77);
601 };
602
603 let buffer = OptionsSerializer::<ipv6::ControlOptionsImpl, ipv6::ControlOption, _>::new(
604 options.iter(),
605 )
606 .into_serializer()
607 .encapsulate(ControlProtocolPacketBuilder::new(2, identifier))
608 .encapsulate(PppPacketBuilder::new(protocol))
609 .serialize_vec_outer()
610 .ok()
611 .unwrap();
612
613 assert_eq!(buffer.as_ref(), EXPECT_BUFFER);
614 }
615}