1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """IPFIX utilities library. Provides classes that allow scapy to work
18 Template and data sets in one packet are not supported.
19 Option template sets (Set_ID = 3) are not supported.
23 from scapy.all import Packet, bind_layers
24 from scapy.fields import *
25 from scapy.layers.inet import UDP
26 from scapy.contrib.ppi_geotag import UTCTimeField
29 class IPFIXHandler(object):
30 """Class for handling IPFIX packets. To use, create instance of class before
31 dissecting IPFIX packets with scapy, then run update_template every time
32 an IPFIX template packet is received."""
35 4: ByteField("Protocol_ID", 0x00),
36 7: ShortField("src_port", 0),
37 8: IPField("IPv4_src", ""),
38 11: ShortField("dst_port", 0),
39 12: IPField("IPv4_dst", ""),
40 86: LongField("packetTotalCount", 0),
41 180: ShortField("udp_src_port", 0),
42 181: ShortField("udp_dst_port", 0),
43 182: ShortField("tcp_src_port", 0),
44 183: ShortField("tcp_dst_port", 0),
48 """Initializer, registers IPFIX header and template layers with scapy.
50 bind_layers(UDP, IPFIXHeader, dport=4739)
51 bind_layers(IPFIXHeader, IPFIXTemplate, Set_ID=2)
53 def update_template(self, packet):
54 """Updates IPFIXData class with new data template. Registers IPFIX data
55 layer with scapy using the new template.
57 :param packet: Packet containing an IPFIX template.
58 :type packet: scapy.Ether
60 template_list = packet['IPFIX template'].Template
61 template_id = packet['IPFIX template'].Template_ID
63 IPFIXData.fields_desc = []
64 for item in template_list[::2]:
66 IPFIXData.fields_desc.append(self.template_elements[item])
69 "Unknown IPFIX template element with ID {0}".format(item))
70 bind_layers(IPFIXHeader, IPFIXData, Set_ID=template_id)
71 # if the packet doesn't end here, assume it contains more data sets
72 bind_layers(IPFIXData, IPFIXData)
75 class IPFIXHeader(Packet):
76 """Class for IPFIX header."""
78 fields_desc = [StrFixedLenField("Version", 0x000a, length=2),
79 ShortField("Message Length", 0),
80 UTCTimeField("Timestamp(UTC)", ""),
81 IntField("Sequence Number", 0),
82 IntField("Observation Domain ID", 0),
83 ShortField("Set_ID", 0),
84 ShortField("Set_Length", 0)
88 class IPFIXTemplate(Packet):
89 """Class for IPFIX template layer."""
90 name = "IPFIX template"
91 fields_desc = [ShortField("Template_ID", 256),
92 ShortField("nFields", 2),
93 FieldListField("Template", [], ShortField("type_len", ""),
94 count_from=lambda p: p.nFields*2)
98 class IPFIXData(Packet):
99 """Class for IPFIX data layer. Needs to be updated with
100 a template before use."""
101 name = "IPFIX flow data"