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