1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use nom::IResult;
use nom::le_u32;
use block::RawBlock;
use options::{parse_options,Options};
use util;

pub const TY: u32 = 0x00000006;

//    0                   1                   2                   3
//    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//    +---------------------------------------------------------------+
//  0 |                    Block Type = 0x00000006                    |
//    +---------------------------------------------------------------+
//  4 |                      Block Total Length                       |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  8 |                         Interface ID                          |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 12 |                        Timestamp (High)                       |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 16 |                        Timestamp (Low)                        |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 20 |                         Captured Len                          |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 24 |                          Packet Len                           |
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// 28 /                                                               /
//    /                          Packet Data                          /
//    /          /* variable length, aligned to 32 bits */            /
//    /                                                               /
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//    /                                                               /
//    /                      Options (variable)                       /
//    /                                                               /
//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//    |                      Block Total Length                       |
//    +---------------------------------------------------------------+

named!(enhanced_packet_body<&[u8],EnhancedPacket>,
       chain!(
           interface_id: le_u32 ~
           timestamp_hi: le_u32 ~
           timestamp_lo: le_u32 ~
           captured_len: le_u32 ~
           packet_len: le_u32 ~

           // Captured Len: number of bytes captured from the packet (i.e. the length of the Packet
           // Data field). It will be the minimum value among the actual Packet Length and the
           // snapshot length (defined in Figure 9). The value of this field does not include the
           // padding bytes added at the end of the Packet Data field to align the Packet Data
           // Field to a 32-bit boundary
           data: take!(captured_len as usize) ~
           take!(util::pad_to_32bits(captured_len as usize)) ~
           options: parse_options? ,

           ||{
               EnhancedPacket {
                   ty: TY,
                   block_length: 0,
                   interface_id: interface_id,
                   timestamp_hi: timestamp_hi,
                   timestamp_lo: timestamp_lo,
                   captured_len: captured_len,
                   packet_len: packet_len,
                   data: data,
                   options: options,
                   check_length: 0,
               }
           }
           )
       );

pub fn parse(blk: RawBlock) -> EnhancedPacket {
    match enhanced_packet_body(blk.body) {
        // FIXME(richo) actually do something with the leftover bytes
        IResult::Done(_, mut block) => {
            block.block_length = blk.block_length;
            block.check_length = blk.check_length;
            block
        },
        _ => {
            panic!("Couldn't unpack this section_header");
        }
    }
}

#[derive(Debug)]
pub struct EnhancedPacket<'a> {
    pub ty: u32,
    pub block_length: u32,
    pub interface_id: u32,
    pub timestamp_hi: u32,
    pub timestamp_lo: u32,
    pub captured_len: u32,
    pub packet_len: u32,
    pub data: &'a [u8],
    pub options: Option<Options<'a>>,
    pub check_length: u32,
}