pcap_parser/data/
exported_pdu.rs1use crate::data::PacketData;
2use nom::bytes::streaming::{tag, take};
3use nom::multi::many_till;
4use nom::number::streaming::be_u16;
5use nom::IResult;
6use std::convert::TryFrom;
7
8pub const EXP_PDU_TAG_PROTO_NAME: u16 = 12;
11pub const EXP_PDU_TAG_DISSECTOR_TABLE_NAME: u16 = 14;
12
13pub const EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL: u16 = 32;
14
15#[derive(Debug)]
16pub struct ExportedTlv<'a> {
17 pub t: u16,
18 pub l: u16,
19 pub v: &'a [u8],
20}
21
22pub fn parse_exported_tlv(i: &[u8]) -> IResult<&[u8], ExportedTlv> {
23 let (i, t) = be_u16(i)?;
24 let (i, l) = be_u16(i)?;
25 let (i, v) = take(l)(i)?;
26 Ok((i, ExportedTlv { t, l, v }))
27}
28
29pub fn parse_many_exported_tlv(i: &[u8]) -> IResult<&[u8], Vec<ExportedTlv>> {
30 many_till(parse_exported_tlv, tag(b"\x00\x00\x00\x00"))(i).map(|(rem, (v, _))| (rem, v))
31}
32
33pub fn get_packetdata_wireshark_upper_pdu(i: &[u8], caplen: usize) -> Option<PacketData> {
37 if i.len() < caplen || caplen == 0 {
38 None
39 } else {
40 match parse_many_exported_tlv(i) {
41 Ok((rem, v)) => {
42 let proto_name = v
44 .iter()
45 .find(|tlv| tlv.t == EXP_PDU_TAG_DISSECTOR_TABLE_NAME)
46 .map(|tlv| tlv.v)?;
47 let ip_proto = v
49 .iter()
50 .find(|tlv| tlv.t == EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL && tlv.l >= 4)
51 .map(|tlv| {
52 let int_bytes = <[u8; 4]>::try_from(tlv.v).expect("Convert bytes to u32");
53 u32::from_be_bytes(int_bytes)
54 })?;
55 match proto_name {
56 b"ip.proto" => Some(PacketData::L4(ip_proto as u8, rem)),
57 _ => {
58 None
60 }
61 }
62 }
63 _ => None,
64 }
65 }
66}
67
68#[cfg(test)]
69pub mod tests {
70 use super::get_packetdata_wireshark_upper_pdu;
71 use crate::data::PacketData;
72 use hex_literal::hex;
73 pub const UPPER_PDU: &[u8] = &hex!(
74 "
7500 0e 00 08 69 70 2e 70 72 6f 74 6f 00 20 00 04
7600 00 00 11 00 00 00 00 00 58 20 20 20 ff ff 20
7763 20 68 20 a0 20 7f 20 8a 20 20 20 20 20 20 ff
78ff ff ff ff 20 00 00 00"
79 );
80 #[test]
81 fn test_wireshark_exported_pdu() {
82 match get_packetdata_wireshark_upper_pdu(UPPER_PDU, UPPER_PDU.len()) {
83 Some(PacketData::L4(proto, data)) => {
84 assert_eq!(proto, 17);
85 assert_eq!(data.len(), 32);
86 }
87 None => panic!("get_packetdata_wireshark_upper_pdu could not decode exported PDU"),
88 _ => panic!("unexpected result type from get_packetdata_wireshark_upper_pdu"),
89 }
90 }
91}