2 # IPFIX support for Scapy (RFC7011)
4 from scapy.all import (
14 from scapy.layers.inet import UDP
17 # IPFIX Information Elements http://www.iana.org/assignments/ipfix/ipfix.xhtml
18 information_elements = {
20 2: "packetDeltaCount",
22 4: "protocolIdentifier",
23 5: "ipClassOfService",
25 7: "sourceTransportPort",
26 8: "sourceIPv4Address",
27 9: "sourceIPv4PrefixLength",
28 10: "ingressInterface",
29 11: "destinationTransportPort",
30 12: "destinationIPv4Address",
31 13: "destinationIPv4PrefixLength",
32 14: "egressInterface",
33 15: "ipNextHopIPv4Address",
34 16: "bgpSourceAsNumber",
35 17: "bgpDestinationAsNumber",
36 18: "bgpNextHopIPv4Address",
37 19: "postMCastPacketDeltaCount",
38 20: "postMCastOctetDeltaCount",
39 21: "flowEndSysUpTime",
40 22: "flowStartSysUpTime",
41 23: "postOctetDeltaCount",
42 24: "postPacketDeltaCount",
43 25: "minimumIpTotalLength",
44 26: "maximumIpTotalLength",
45 27: "sourceIPv6Address",
46 28: "destinationIPv6Address",
47 29: "sourceIPv6PrefixLength",
48 30: "destinationIPv6PrefixLength",
50 32: "icmpTypeCodeIPv4",
52 34: "samplingInterval",
53 35: "samplingAlgorithm",
54 36: "flowActiveTimeout",
55 37: "flowIdleTimeout",
58 40: "exportedOctetTotalCount",
59 41: "exportedMessageTotalCount",
60 42: "exportedFlowRecordTotalCount",
62 44: "sourceIPv4Prefix",
63 45: "destinationIPv4Prefix",
64 46: "mplsTopLabelType",
65 47: "mplsTopLabelIPv4Address",
68 50: "samplerRandomInterval",
72 54: "fragmentIdentification",
73 55: "postIpClassOfService",
74 56: "sourceMacAddress",
75 57: "postDestinationMacAddress",
80 62: "ipNextHopIPv6Address",
81 63: "bgpNextHopIPv6Address",
82 64: "ipv6ExtensionHeaders",
83 70: "mplsTopLabelStackSection",
84 71: "mplsLabelStackSection2",
85 72: "mplsLabelStackSection3",
86 73: "mplsLabelStackSection4",
87 74: "mplsLabelStackSection5",
88 75: "mplsLabelStackSection6",
89 76: "mplsLabelStackSection7",
90 77: "mplsLabelStackSection8",
91 78: "mplsLabelStackSection9",
92 79: "mplsLabelStackSection10",
93 80: "destinationMacAddress",
94 81: "postSourceMacAddress",
96 83: "interfaceDescription",
98 85: "octetTotalCount",
99 86: "packetTotalCount",
100 87: "flagsAndSamplerId",
101 88: "fragmentOffset",
102 89: "forwardingStatus",
103 90: "mplsVpnRouteDistinguisher",
104 91: "mplsTopLabelPrefixLength",
105 92: "srcTrafficIndex",
106 93: "dstTrafficIndex",
107 94: "applicationDescription",
109 96: "applicationName",
110 98: "postIpDiffServCodePoint",
111 99: "multicastReplicationFactor",
113 101: "classificationEngineId",
114 102: "layer2packetSectionOffset",
115 103: "layer2packetSectionSize",
116 104: "layer2packetSectionData",
117 128: "bgpNextAdjacentAsNumber",
118 129: "bgpPrevAdjacentAsNumber",
119 130: "exporterIPv4Address",
120 131: "exporterIPv6Address",
121 132: "droppedOctetDeltaCount",
122 133: "droppedPacketDeltaCount",
123 134: "droppedOctetTotalCount",
124 135: "droppedPacketTotalCount",
125 136: "flowEndReason",
126 137: "commonPropertiesId",
127 138: "observationPointId",
128 139: "icmpTypeCodeIPv6",
129 140: "mplsTopLabelIPv6Address",
132 143: "meteringProcessId",
133 144: "exportingProcessId",
135 146: "wlanChannelId",
138 149: "observationDomainId",
139 150: "flowStartSeconds",
140 151: "flowEndSeconds",
141 152: "flowStartMilliseconds",
142 153: "flowEndMilliseconds",
143 154: "flowStartMicroseconds",
144 155: "flowEndMicroseconds",
145 156: "flowStartNanoseconds",
146 157: "flowEndNanoseconds",
147 158: "flowStartDeltaMicroseconds",
148 159: "flowEndDeltaMicroseconds",
149 160: "systemInitTimeMilliseconds",
150 161: "flowDurationMilliseconds",
151 162: "flowDurationMicroseconds",
152 163: "observedFlowTotalCount",
153 164: "ignoredPacketTotalCount",
154 165: "ignoredOctetTotalCount",
155 166: "notSentFlowTotalCount",
156 167: "notSentPacketTotalCount",
157 168: "notSentOctetTotalCount",
158 169: "destinationIPv6Prefix",
159 170: "sourceIPv6Prefix",
160 171: "postOctetTotalCount",
161 172: "postPacketTotalCount",
162 173: "flowKeyIndicator",
163 174: "postMCastPacketTotalCount",
164 175: "postMCastOctetTotalCount",
169 180: "udpSourcePort",
170 181: "udpDestinationPort",
171 182: "tcpSourcePort",
172 183: "tcpDestinationPort",
173 184: "tcpSequenceNumber",
174 185: "tcpAcknowledgementNumber",
175 186: "tcpWindowSize",
176 187: "tcpUrgentPointer",
177 188: "tcpHeaderLength",
178 189: "ipHeaderLength",
179 190: "totalLengthIPv4",
180 191: "payloadLengthIPv6",
182 193: "nextHeaderIPv6",
183 194: "mplsPayloadLength",
184 195: "ipDiffServCodePoint",
186 197: "fragmentFlags",
187 198: "octetDeltaSumOfSquares",
188 199: "octetTotalSumOfSquares",
189 200: "mplsTopLabelTTL",
190 201: "mplsLabelStackLength",
191 202: "mplsLabelStackDepth",
192 203: "mplsTopLabelExp",
193 204: "ipPayloadLength",
194 205: "udpMessageLength",
199 210: "paddingOctets",
200 211: "collectorIPv4Address",
201 212: "collectorIPv6Address",
202 213: "exportInterface",
203 214: "exportProtocolVersion",
204 215: "exportTransportProtocol",
205 216: "collectorTransportPort",
206 217: "exporterTransportPort",
207 218: "tcpSynTotalCount",
208 219: "tcpFinTotalCount",
209 220: "tcpRstTotalCount",
210 221: "tcpPshTotalCount",
211 222: "tcpAckTotalCount",
212 223: "tcpUrgTotalCount",
213 224: "ipTotalLength",
214 225: "postNATSourceIPv4Address",
215 226: "postNATDestinationIPv4Address",
216 227: "postNAPTSourceTransportPort",
217 228: "postNAPTDestinationTransportPort",
218 229: "natOriginatingAddressRealm",
220 231: "initiatorOctets",
221 232: "responderOctets",
222 233: "firewallEvent",
226 237: "postMplsTopLabelExp",
227 238: "tcpWindowScale",
228 239: "biflowDirection",
229 240: "ethernetHeaderLength",
230 241: "ethernetPayloadLength",
231 242: "ethernetTotalLength",
233 244: "dot1qPriority",
234 245: "dot1qCustomerVlanId",
235 246: "dot1qCustomerPriority",
239 250: "pseudoWireType",
240 251: "pseudoWireControlWord",
241 252: "ingressPhysicalInterface",
242 253: "egressPhysicalInterface",
243 254: "postDot1qVlanId",
244 255: "postDot1qCustomerVlanId",
246 257: "postIpPrecedence",
247 258: "collectionTimeMilliseconds",
248 259: "exportSctpStreamId",
249 260: "maxExportSeconds",
250 261: "maxFlowEndSeconds",
251 262: "messageMD5Checksum",
253 264: "minExportSeconds",
254 265: "minFlowStartSeconds",
257 268: "maxFlowEndMicroseconds",
258 269: "maxFlowEndMilliseconds",
259 270: "maxFlowEndNanoseconds",
260 271: "minFlowStartMicroseconds",
261 272: "minFlowStartMilliseconds",
262 273: "minFlowStartNanoseconds",
263 274: "collectorCertificate",
264 275: "exporterCertificate",
265 276: "dataRecordsReliability",
266 277: "observationPointType",
267 278: "newConnectionDeltaCount",
268 279: "connectionSumDurationSeconds",
269 280: "connectionTransactionId",
270 281: "postNATSourceIPv6Address",
271 282: "postNATDestinationIPv6Address",
274 285: "anonymizationFlags",
275 286: "anonymizationTechnique",
276 287: "informationElementIndex",
277 288: "p2pTechnology",
278 289: "tunnelTechnology",
279 290: "encryptedTechnology",
281 292: "subTemplateList",
282 293: "subTemplateMultiList",
283 294: "bgpValidityState",
287 298: "initiatorPackets",
288 299: "responderPackets",
289 300: "observationDomainName",
290 301: "selectionSequenceId",
292 303: "informationElementId",
293 304: "selectorAlgorithm",
294 305: "samplingPacketInterval",
295 306: "samplingPacketSpace",
296 307: "samplingTimeInterval",
297 308: "samplingTimeSpace",
299 310: "samplingPopulation",
300 311: "samplingProbability",
301 312: "dataLinkFrameSize",
302 313: "ipHeaderPacketSection",
303 314: "ipPayloadPacketSection",
304 315: "dataLinkFrameSection",
305 316: "mplsLabelStackSection",
306 317: "mplsPayloadPacketSection",
307 318: "selectorIdTotalPktsObserved",
308 319: "selectorIdTotalPktsSelected",
309 320: "absoluteError",
310 321: "relativeError",
311 322: "observationTimeSeconds",
312 323: "observationTimeMilliseconds",
313 324: "observationTimeMicroseconds",
314 325: "observationTimeNanoseconds",
315 326: "digestHashValue",
316 327: "hashIPPayloadOffset",
317 328: "hashIPPayloadSize",
318 329: "hashOutputRangeMin",
319 330: "hashOutputRangeMax",
320 331: "hashSelectedRangeMin",
321 332: "hashSelectedRangeMax",
322 333: "hashDigestOutput",
323 334: "hashInitialiserValue",
327 338: "confidenceLevel",
328 339: "informationElementDataType",
329 340: "informationElementDescription",
330 341: "informationElementName",
331 342: "informationElementRangeBegin",
332 343: "informationElementRangeEnd",
333 344: "informationElementSemantics",
334 345: "informationElementUnits",
335 346: "privateEnterpriseNumber",
336 347: "virtualStationInterfaceId",
337 348: "virtualStationInterfaceName",
338 349: "virtualStationUUID",
339 350: "virtualStationName",
340 351: "layer2SegmentId",
341 352: "layer2OctetDeltaCount",
342 353: "layer2OctetTotalCount",
343 354: "ingressUnicastPacketTotalCount",
344 355: "ingressMulticastPacketTotalCount",
345 356: "ingressBroadcastPacketTotalCount",
346 357: "egressUnicastPacketTotalCount",
347 358: "egressBroadcastPacketTotalCount",
348 359: "monitoringIntervalStartMilliSeconds",
349 360: "monitoringIntervalEndMilliSeconds",
350 361: "portRangeStart",
352 363: "portRangeStepSize",
353 364: "portRangeNumPorts",
354 365: "staMacAddress",
355 366: "staIPv4Address",
356 367: "wtpMacAddress",
357 368: "ingressInterfaceType",
358 369: "egressInterfaceType",
359 370: "rtpSequenceNumber",
361 372: "applicationCategoryName",
362 373: "applicationSubCategoryName",
363 374: "applicationGroupName",
364 375: "originalFlowsPresent",
365 376: "originalFlowsInitiated",
366 377: "originalFlowsCompleted",
367 378: "distinctCountOfSourceIPAddress",
368 379: "distinctCountOfDestinationIPAddress",
369 380: "distinctCountOfSourceIPv4Address",
370 381: "distinctCountOfDestinationIPv4Address",
371 382: "distinctCountOfSourceIPv6Address",
372 383: "distinctCountOfDestinationIPv6Address",
373 384: "valueDistributionMethod",
374 385: "rfc3550JitterMilliseconds",
375 386: "rfc3550JitterMicroseconds",
376 387: "rfc3550JitterNanoseconds",
378 389: "dot1qCustomerDEI",
379 390: "flowSelectorAlgorithm",
380 391: "flowSelectedOctetDeltaCount",
381 392: "flowSelectedPacketDeltaCount",
382 393: "flowSelectedFlowDeltaCount",
383 394: "selectorIDTotalFlowsObserved",
384 395: "selectorIDTotalFlowsSelected",
385 396: "samplingFlowInterval",
386 397: "samplingFlowSpacing",
387 398: "flowSamplingTimeInterval",
388 399: "flowSamplingTimeSpacing",
389 400: "hashFlowDomain",
390 401: "transportOctetDeltaCount",
391 402: "transportPacketDeltaCount",
392 403: "originalExporterIPv4Address",
393 404: "originalExporterIPv6Address",
394 405: "originalObservationDomainId",
395 406: "intermediateProcessId",
396 407: "ignoredDataRecordTotalCount",
397 408: "dataLinkFrameType",
398 409: "sectionOffset",
399 410: "sectionExportedOctets",
400 411: "dot1qServiceInstanceTag",
401 412: "dot1qServiceInstanceId",
402 413: "dot1qServiceInstancePriority",
403 414: "dot1qCustomerSourceMacAddress",
404 415: "dot1qCustomerDestinationMacAddress",
405 417: "postLayer2OctetDeltaCount",
406 418: "postMCastLayer2OctetDeltaCount",
407 420: "postLayer2OctetTotalCount",
408 421: "postMCastLayer2OctetTotalCount",
409 422: "minimumLayer2TotalLength",
410 423: "maximumLayer2TotalLength",
411 424: "droppedLayer2OctetDeltaCount",
412 425: "droppedLayer2OctetTotalCount",
413 426: "ignoredLayer2OctetTotalCount",
414 427: "notSentLayer2OctetTotalCount",
415 428: "layer2OctetDeltaSumOfSquares",
416 429: "layer2OctetTotalSumOfSquares",
417 430: "layer2FrameDeltaCount",
418 431: "layer2FrameTotalCount",
419 432: "pseudoWireDestinationIPv4Address",
420 433: "ignoredLayer2FrameTotalCount",
421 434: "mibObjectValueInteger",
422 435: "mibObjectValueOctetString",
423 436: "mibObjectValueOID",
424 437: "mibObjectValueBits",
425 438: "mibObjectValueIPAddress",
426 439: "mibObjectValueCounter",
427 440: "mibObjectValueGauge",
428 441: "mibObjectValueTimeTicks",
429 442: "mibObjectValueUnsigned",
430 443: "mibObjectValueTable",
431 444: "mibObjectValueRow",
432 445: "mibObjectIdentifier",
433 446: "mibSubIdentifier",
434 447: "mibIndexIndicator",
435 448: "mibCaptureTimeSemantics",
436 449: "mibContextEngineID",
437 450: "mibContextName",
438 451: "mibObjectName",
439 452: "mibObjectDescription",
440 453: "mibObjectSyntax",
441 454: "mibModuleName",
444 457: "httpStatusCode",
445 458: "sourceTransportPortsLimit",
446 459: "httpRequestMethod",
447 460: "httpRequestHost",
448 461: "httpRequestTarget",
449 462: "httpMessageVersion",
450 466: "natQuotaExceededEvent",
451 471: "maxSessionEntries",
452 472: "maxBIBEntries",
453 473: "maxEntriesPerUser",
454 475: "maxFragmentsPendingReassembly",
461 ShortField("version", 10),
462 ShortField("length", None),
463 IntField("exportTime", None),
464 IntField("sequenceNumber", 1),
465 IntField("observationDomainID", 1),
469 class FieldSpecifier(Packet):
470 name = "Field Specifier"
472 ShortEnumField("informationElement", None, information_elements),
473 ShortField("fieldLength", None),
476 def extract_padding(self, s):
480 class Template(Packet):
483 ShortField("templateID", 256),
484 FieldLenField("fieldCount", None, count_of="fields"),
486 "templateFields", [], FieldSpecifier, count_from=lambda p: p.fieldCount
494 StrLenField("data", "", length_from=lambda p: p.underlayer.length - 4)
497 def extract_padding(self, s):
503 fields_desc = [ShortField("setID", 256), ShortField("length", None)]
505 def guess_payload_class(self, payload):
508 elif self.setID > 255:
511 return Packet.guess_payload_class(self, payload)
514 bind_layers(IPFIX, Set)
515 bind_layers(UDP, IPFIX, dport=4739)
519 """IPFIX data set decoder"""
524 def add_template(self, template):
528 :param template: IPFIX template
530 templateID = template.templateID
533 for field in template.templateFields:
534 fields.append({"name": field.informationElement, "len": field.fieldLength})
535 rec_len += field.fieldLength
536 self._templates.append({"id": templateID, "fields": fields, "rec_len": rec_len})
538 def decode_data_set(self, data_set):
542 :param data_set: IPFIX data set
543 :returns: List of decoded data records.
546 for template in self._templates:
547 if template["id"] == data_set.setID:
549 d = data_set[Data].data
550 for i in range(len(d) // template["rec_len"]):
552 for field in template["fields"]:
553 f = d[offset : offset + field["len"]]
554 offset += field["len"]
555 record.update({field["name"]: f})