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
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Local Imports
use community::Community;
use dst_as_path;
use error;
use ipaddress;
use types::ReadSeeker;
use utils::ReadBytesLocal;

// Std Lib Imports
use std::io::SeekFrom;

#[derive(Debug, Clone)]
pub enum FlowRecord {
    SampledHeader(SampledHeader), // Format 1
    SampledIpv4(SampledIpv4), // Format 3
    ExtendedSwitch(ExtendedSwitch), // Format 1001
    ExtendedRouter(ExtendedRouter), // Format 1002
    ExtendedGateway(ExtendedGateway), // Format 1003
    ExtendedUrl(ExtendedUrl), // Format 1005
    ExtendedMpls(ExtendedMpls), // Format 1006
    ExtendedMplsTunnel(ExtendedMplsTunnel), // Format 1008
}

impl ::utils::Decodeable for FlowRecord {
    fn read_and_decode(stream: &mut ReadSeeker) -> Result<FlowRecord, error::Error> {
        let format = try!(stream.be_read_u32());
        let length = try!(stream.be_read_u32());

        match format {
            1 => {
                let e = try!(SampledHeader::read_and_decode(stream));
                return Ok(FlowRecord::SampledHeader(e));
            }
            3 => {
                let e = try!(SampledIpv4::read_and_decode(stream));
                return Ok(FlowRecord::SampledIpv4(e));
            }
            1001 => {
                let e = try!(ExtendedSwitch::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedSwitch(e));
            }
            1002 => {
                let e = try!(ExtendedRouter::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedRouter(e));
            }
            1003 => {
                let e = try!(ExtendedGateway::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedGateway(e));
            }
            1005 => {
                let e = try!(ExtendedUrl::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedUrl(e));
            }
            1006 => {
                let e = try!(ExtendedMpls::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedMpls(e));
            }
            1008 => {
                let e = try!(ExtendedMplsTunnel::read_and_decode(stream));
                return Ok(FlowRecord::ExtendedMplsTunnel(e));
            }
            _ => {
                println!("DEBUG: Unknown FlowRecord type {0} skipping {1} bytes.",
                         format,
                         length);
                try!(stream.seek(SeekFrom::Current(length as i64)));
                return Err(error::Error::UnknownType(format!("Unknown FlowRecord type {0} \
                                                              skipping {1} bytes.",
                                                             format,
                                                             length)));
            }
        }
    }
}

add_decoder!{
#[derive(Debug, Clone, Default)]
pub struct ExtendedGateway {
    pub next_hop: ipaddress::IPAddress,
    pub asn: u32, // Autonomous system number of router
    pub src_as: u32, // Autonomous system number of source
    pub src_peer_as: u32,   /* Autonomous system number of source peer */
    pub dst_as_path: Vec<dst_as_path::DstASPath>, /* Autonomous system path to the destination */
    pub communities: Vec<Community>, // Communities associated with this route
    pub localpref: u32, // LocalPref associated with this route
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct ExtendedUrl {
   pub directoin: u32,   /* Direction of connection */
   pub url: String,               /* The HTTP request-line (see RFC 2616) */
   pub host: String,              /* The host field from the HTTP header */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct SampledIpv4 {
   pub length: u32,     /* The length of the IP packet excluding
                                  lower layer encapsulations */
   pub protocol: u32,   /* IP Protocol type
                                   (for example, TCP = 6, UDP = 17) */
   pub src_ip: ipaddress::IPAddress,            /* Source IP Address */
   pub dst_ip: ipaddress::IPAddress,            /* Destination IP Address */
   pub src_port: u32,   /* TCP/UDP source port number or equivalent */
   pub dst_port: u32,   /* TCP/UDP destination port number or equivalent */
   pub tcp_flags: u32,  /* TCP flags */
   pub tos: u32,        /* IP type of service */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct ExtendedSwitch {
   pub src_vlan: u32,     /* The 802.1Q VLAN id of incoming frame */
   pub src_priority: u32, /* The 802.1p priority of incoming frame */
   pub dst_vlan: u32,     /* The 802.1Q VLAN id of outgoing frame */
   pub dst_priority: u32, /* The 802.1p priority of outgoing frame */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct ExtendedRouter {
   pub nexthop: ipaddress::IPAddress,            /* IP address of next hop router */
   pub src_mask_len: u32,   /* Source address prefix mask
                                   (expressed as number of bits) */
   pub dst_mask_len: u32,   /* Destination address prefix mask
                                   (expressed as number of bits) */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct SampledHeader {
   // TODO: header_protocol should be an enum...
   pub protocol: u32,       /* Format of sampled header */
   pub frame_length: u32, /* Original length of packet before sampling. Note: For a layer 2
                             header_protocol, length is total number of octets of data received on
                             the network (excluding framing bits but including FCS octets).
                             Hardware limitations may prevent an exact reporting of the underlying
                             frame length, but an agent should attempt to be as accurate as
                             possible. Any octets added to the frame_length to compensate for
                             encapsulations removed by the underlying hardware must also be added
                             to the stripped count. */

   pub stripped: u32, /* The number of octets removed from the packet before extracting the
                         header<> octets. Trailing encapsulation data corresponding to any leading
                         encapsulations that were stripped must also be stripped. Trailing
                         encapsulation data for the outermost protocol layer included in the
                         sampled header must be stripped.

                         In the case of a non-encapsulated 802.3 packet stripped >= 4 since VLAN
                         tag information might have been stripped off in addition to the FCS.

                         Outer encapsulations that are ambiguous, or not one of the standard
                         header_protocol must be stripped. */
   pub header: Vec<u8>, /* Header bytes */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct ExtendedMplsTunnel {
   pub tunnel_lsp_name: String, /* Tunnel name */
   pub tunnel_id: u32,     /* Tunnel ID */
   pub tunnel_cos: u32,    /* Tunnel COS value */
}
}

add_decoder!{
#[derive(Debug, Clone)]
pub struct ExtendedMpls {
   pub nexthop: ipaddress::IPAddress,           /* Address of the next hop */
   pub in_stack: Vec<i32>,       /* Label stack of received packet */
   pub out_stack: Vec<i32>,      /* Label stack for transmitted packet */
}
}