first working
This commit is contained in:
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"name": "BIG pcap",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "airstream.py",
|
||||
"console": "integratedTerminal",
|
||||
"args": "--pcap FSTDaircraft.pcapng -s all"
|
||||
}
|
||||
]
|
||||
}
|
||||
165
0.csv
Normal file
165
0.csv
Normal file
@@ -0,0 +1,165 @@
|
||||
Src IP,Src Port,Dst IP,Dst Port,Proto,Pkts,Bytes,Duration,Overview:Avg Size,Overview:Avg TimeΔ,Overview:Time 1σ,Overview:Pkt/s,Overview:B/s,Chapter10:Channels,Chapter10:Seq Errors,Chapter10:Pkt/s,Ch10Analog:Channels,Ch10Analog:Data Gaps,Ch10Analog:Overrange,Ch10Analog:Underrange,Ch10Analog:Pkt/s,Ch10TMATS:Versions,Ch10TMATS:Config Changes,Ch10TMATS:G-Records,Ch10TMATS:R-Records,Ch10TMATS:M-Records,Ch10PCM:Channels,Ch10PCM:Sync Errors,Ch10PCM:Bit Slips,Ch10PCM:Minor Frames,Ch10PCM:Major Frames,Ch10Time:Time Sources,Ch10Time:Format Changes,Ch10Time:Leap Seconds,Ch10Time:Discontinuities,Ch10Time:Max Delta,IENA:Key Fields,IENA:Seq Gaps,IENA:Pkt/s,PTP:Sync,PTP:Follow Up,PTP:Delay Req,PTP:Delay Resp,PTP:Announce,PTPSync:Sync Msgs,PTPSync:Follow-ups,PTPSync:Two-step,PTPSync:One-step,PTPSync:Clock IDs,PTPSync:Avg Interval,PTPAnnounce:Announce,PTPAnnounce:GM Changes,PTPAnnounce:Priority Changes,PTPAnnounce:Grandmasters,PTPAnnounce:Clock Classes,PTPDelay:Delay Req,PTPDelay:Delay Resp,PTPDelay:PDelay Req,PTPDelay:PDelay Resp,PTPDelay:Avg RTT
|
||||
192.168.6.194,49153,239.1.2.10,8400,UDP,4610,949660,46.09,206.0,0.01,0.000132,100.0,20604.6,0,0,100.0,0,0,0,0,100.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.142,49153,239.1.2.10,8400,UDP,4609,949454,46.08,206.0,0.01,0.000207,100.0,20604.5,0,0,100.0,0,0,0,0,100.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,100.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.161,49153,239.1.2.10,8400,UDP,461,592846,46.02,1286.0,0.100043,0.000233,10.0,12882.4,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.146,49154,239.1.2.10,8400,UDP,2446,3154768,46.08,1289.8,0.018847,0.004598,53.1,68462.9,0,0,53.1,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.133,49153,239.1.2.10,8400,UDP,2305,2964230,46.08,1286.0,0.02,0.000119,50.0,64328.0,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.191,49153,239.1.2.10,8400,UDP,2305,2964230,46.08,1286.0,0.02,0.000146,50.0,64328.1,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.210,49153,239.1.2.10,8400,UDP,2304,2962944,46.08,1286.0,0.020009,0.000436,50.0,64300.0,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.151,49153,239.1.2.10,8400,UDP,2304,2962944,46.06,1286.0,0.02,0.000102,50.0,64328.2,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.220,49153,239.1.2.10,8400,UDP,2305,2964230,46.08,1286.0,0.02,0.000103,50.0,64328.3,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.146,49153,239.1.2.10,8400,UDP,2304,2962944,46.06,1286.0,0.02,0.000147,50.0,64328.3,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.145,49154,239.1.2.10,8400,UDP,2445,3153482,46.06,1289.8,0.018846,0.004591,53.1,68464.9,0,0,53.1,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.131,49154,239.1.2.10,8400,UDP,2445,3152730,46.06,1289.5,0.018846,0.004601,53.1,68448.6,0,0,53.1,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,53.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.149,49153,239.1.2.10,8400,UDP,2304,2962944,46.06,1286.0,0.02,0.00011,50.0,64328.2,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.113,49153,239.1.2.10,8400,UDP,2304,2962944,46.06,1286.0,0.02,0.000104,50.0,64328.2,0,0,50.0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.184,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.1,0.00011,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.173,49154,239.1.2.10,8400,UDP,1063,1368898,46.05,1287.8,0.043362,0.016909,23.1,29726.3,0,0,23.1,0,0,0,0,23.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.165,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.1,0.000123,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.214,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.1,0.000122,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.169,49153,239.1.2.10,8400,UDP,460,591560,45.902,1286.0,0.100003,0.000129,10.0,12887.6,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.150,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.099999,8.2e-05,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.112,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.099999,8.5e-05,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.133,49153,239.1.2.10,8400,UDP,461,592846,46.0,1286.0,0.099999,8.4e-05,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.181,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.1,0.00012,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.217,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.099999,9.6e-05,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.148,49153,239.1.2.10,8400,UDP,450,578700,45.9,1286.0,0.102227,0.047141,9.8,12607.9,0,0,9.8,0,0,0,0,9.8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.145,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.1,8.8e-05,10.0,12888.0,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.115,49153,239.1.2.10,8400,UDP,413,531118,45.9,1286.0,0.111407,0.034757,9.0,11571.3,0,0,9.0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.168,49153,239.1.2.10,8400,UDP,428,550408,45.9,1286.0,0.107494,0.028905,9.3,11991.5,0,0,9.3,0,0,0,0,9.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.166,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.099999,0.00011,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.129,49153,239.1.2.10,8400,UDP,418,537548,45.9,1286.0,0.110072,0.030921,9.1,11711.3,0,0,9.1,0,0,0,0,9.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.197,49153,239.1.2.10,8400,UDP,414,532404,45.9,1286.0,0.111138,0.034442,9.0,11599.2,0,0,9.0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.163,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.1,0.000105,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.161,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.1,9.1e-05,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.200,49153,239.1.2.10,8400,UDP,460,591560,45.9,1286.0,0.1,9e-05,10.0,12888.1,0,0,10.0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.164,49153,239.1.2.10,8400,UDP,433,556838,45.9,1286.0,0.10625,0.072155,9.4,12131.6,0,0,9.4,0,0,0,0,9.4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.165,49153,239.1.2.10,8400,UDP,430,552980,45.9,1286.0,0.106993,0.069639,9.4,12047.5,0,0,9.4,0,0,0,0,9.4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.192,49153,239.1.2.10,8400,UDP,449,577414,45.9,1286.0,0.102455,0.015464,9.8,12579.8,0,0,9.8,0,0,0,0,9.8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.162,49153,239.1.2.10,8400,UDP,230,47380,45.801,206.0,0.200005,0.002143,5.0,1034.5,0,0,5.0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.150,49153,239.1.2.10,8400,UDP,230,47380,45.797,206.0,0.199987,0.002347,5.0,1034.6,0,0,5.0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.175,49153,239.1.2.10,8400,UDP,229,47174,45.798,206.0,0.200868,0.013255,5.0,1030.0,0,0,5.0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.130,49153,239.1.2.10,8400,UDP,230,47380,45.798,206.0,0.199993,0.002432,5.0,1034.5,0,0,5.0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.164,49153,239.1.2.10,8400,UDP,230,295780,45.806,1286.0,0.200026,0.003326,5.0,6457.2,0,0,5.0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.155,49153,239.1.2.10,8400,UDP,209,268774,45.79,1286.0,0.220145,0.064008,4.6,5869.7,0,0,4.6,0,0,0,0,4.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.113,319,224.0.1.129,319,UDP,4,344,36.519,86.0,12.172929,2.167395,0.1,9.4,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
10.106.30.117,320,224.0.1.129,320,UDP,591,56506,45.669,95.6,0.077406,0.089672,12.9,1237.3,0,0,12.9,0,0,0,0,12.9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12.9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
10.106.30.117,319,224.0.1.129,319,UDP,46,3956,45.002,86.0,1.000047,0.021243,1.0,87.9,0,0,1.0,0,0,0,0,1.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.126,319,224.0.1.129,319,UDP,6,516,36.521,86.0,7.304178,3.883921,0.2,14.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.118,49153,239.1.2.10,8400,UDP,403,518258,44.901,1286.0,0.111694,0.100134,9.0,11542.3,0,0,9.0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.164,319,224.0.1.129,319,UDP,7,602,43.182,86.0,7.197,4.365507,0.2,13.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.212,49153,239.1.2.10,8400,UDP,23,29578,44.003,1286.0,2.000114,0.001948,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.166,49153,239.1.2.10,8400,UDP,23,29578,44.001,1286.0,2.000055,0.001313,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.110,49153,239.1.2.10,8400,UDP,23,29578,44.0,1286.0,2.00001,0.002433,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.130,49153,239.1.2.10,8400,UDP,23,29578,44.002,1286.0,2.00009,0.002297,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.148,49153,239.1.2.10,8400,UDP,23,29578,44.001,1286.0,2.000052,0.001085,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.160,49154,239.1.2.10,8400,UDP,161,216246,45.116,1343.1,0.281972,0.395227,3.6,4793.2,0,0,3.6,0,0,0,0,3.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.149,49153,239.1.2.10,8400,UDP,23,29578,43.998,1286.0,1.999914,0.002068,0.5,672.3,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.163,319,224.0.1.129,319,UDP,6,516,34.713,86.0,6.942651,3.544789,0.2,14.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.213,49153,239.1.2.10,8400,UDP,23,29578,43.997,1286.0,1.999857,0.001747,0.5,672.3,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.218,319,224.0.1.129,319,UDP,4,344,39.372,86.0,13.123877,2.928612,0.1,8.7,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.216,319,224.0.1.129,319,UDP,7,602,32.702,86.0,5.45035,4.434816,0.2,18.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.146,319,224.0.1.129,319,UDP,7,602,45.086,86.0,7.514355,4.53908,0.2,13.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.151,319,224.0.1.129,319,UDP,9,774,42.44,86.0,5.304996,3.348239,0.2,18.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.161,319,224.0.1.129,319,UDP,6,516,42.609,86.0,8.521825,5.146987,0.1,12.1,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.161,319,224.0.1.129,319,UDP,5,430,44.269,86.0,11.067135,1.661814,0.1,9.7,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.220,319,224.0.1.129,319,UDP,8,688,35.465,86.0,5.066482,3.870116,0.2,19.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.112,49153,239.1.2.10,8400,UDP,23,29578,44.0,1286.0,1.999991,7.3e-05,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
10.106.30.115,5010,239.0.1.133,5010,UDP,46,7084,45.027,154.0,1.000609,0.047616,1.0,157.3,0,0,1.0,0,0,0,0,1.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.191,319,224.0.1.129,319,UDP,5,430,44.046,86.0,11.011573,3.299827,0.1,9.8,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.158,319,224.0.1.129,319,UDP,4,344,44.299,86.0,14.766266,1.152442,0.1,7.8,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.167,319,224.0.1.129,319,UDP,6,516,34.878,86.0,6.975532,3.498272,0.2,14.8,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.111,49153,239.1.2.10,8400,UDP,23,29578,43.998,1286.0,1.999913,0.001061,0.5,672.3,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.132,319,224.0.1.129,319,UDP,6,516,41.051,86.0,8.210203,4.501499,0.1,12.6,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.111,319,224.0.1.129,319,UDP,5,430,35.432,86.0,8.85792,5.805048,0.1,12.1,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.154,319,224.0.1.129,319,UDP,5,430,32.009,86.0,8.002179,5.179198,0.2,13.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.169,319,224.0.1.129,319,UDP,4,344,32.731,86.0,10.910293,4.105734,0.1,10.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.148,319,224.0.1.129,319,UDP,7,602,38.779,86.0,6.463108,4.364559,0.2,15.5,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.110,319,224.0.1.129,319,UDP,10,860,41.203,86.0,4.578104,4.472113,0.2,20.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.164,319,224.0.1.129,319,UDP,6,516,43.599,86.0,8.719832,5.640652,0.1,11.8,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.154,49153,239.1.2.10,8400,UDP,23,29578,44.004,1286.0,2.000198,0.002351,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.178,49153,239.1.2.10,8400,UDP,23,29578,44.002,1286.0,2.000079,0.001387,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.111,49153,239.1.2.10,8400,UDP,23,29578,43.999,1286.0,1.999934,0.002509,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.159,49153,239.1.2.10,8400,UDP,23,29578,43.999,1286.0,1.999962,0.002397,0.5,672.2,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.209,319,224.0.1.129,319,UDP,7,602,36.511,86.0,6.085097,4.606922,0.2,16.5,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.203,319,224.0.1.129,319,UDP,5,430,38.222,86.0,9.555579,5.983865,0.1,11.2,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.184,319,224.0.1.129,319,UDP,5,430,26.359,86.0,6.589804,6.192937,0.2,16.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.212,319,224.0.1.129,319,UDP,6,516,40.598,86.0,8.11954,4.426785,0.1,12.7,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.206,319,224.0.1.129,319,UDP,11,946,40.448,86.0,4.044849,4.201274,0.3,23.4,0,0,0.3,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.181,319,224.0.1.129,319,UDP,10,860,38.016,86.0,4.223996,3.347284,0.3,22.6,0,0,0.3,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.166,319,224.0.1.129,319,UDP,5,430,34.495,86.0,8.623754,4.090838,0.1,12.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.172,319,224.0.1.129,319,UDP,8,688,32.613,86.0,4.659041,4.890259,0.2,21.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.162,49153,239.1.2.10,8400,UDP,22,28292,34.5,1286.0,1.642867,7.070268,0.6,820.1,0,0,0.6,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.163,49153,239.1.2.10,8400,UDP,20,25720,34.402,1286.0,1.810637,7.432277,0.6,747.6,0,0,0.6,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.211,49153,239.1.2.10,8400,UDP,20,25720,34.402,1286.0,1.810622,7.432305,0.6,747.6,0,0,0.6,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.219,49153,239.1.2.10,8400,UDP,19,24434,34.303,1286.0,1.905726,7.635845,0.6,712.3,0,0,0.6,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.127,319,224.0.1.129,319,UDP,9,774,37.052,86.0,4.631533,3.237616,0.2,20.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.130,319,224.0.1.129,319,UDP,6,516,32.863,86.0,6.572551,4.912905,0.2,15.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.208,319,224.0.1.129,319,UDP,5,430,34.182,86.0,8.545524,5.282449,0.1,12.6,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.171,319,224.0.1.129,319,UDP,6,516,41.104,86.0,8.220866,2.382756,0.1,12.6,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.150,319,224.0.1.129,319,UDP,6,516,41.261,86.0,8.2523,5.698831,0.1,12.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.207,319,224.0.1.129,319,UDP,6,516,34.052,86.0,6.810426,6.546633,0.2,15.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.174,319,224.0.1.129,319,UDP,5,430,34.86,86.0,8.714951,5.557099,0.1,12.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.125,319,224.0.1.129,319,UDP,6,516,39.781,86.0,7.956158,5.051183,0.2,13.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.144,319,224.0.1.129,319,UDP,6,516,37.44,86.0,7.487997,4.005579,0.2,13.8,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.118,319,224.0.1.129,319,UDP,9,774,40.929,86.0,5.116173,5.082163,0.2,18.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.165,319,224.0.1.129,319,UDP,8,688,38.251,86.0,5.464416,4.903232,0.2,18.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.194,319,224.0.1.129,319,UDP,6,516,39.78,86.0,7.955976,3.919858,0.2,13.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.146,319,224.0.1.129,319,UDP,8,688,31.662,86.0,4.523099,5.358957,0.3,21.7,0,0,0.3,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.159,319,224.0.1.129,319,UDP,8,688,39.157,86.0,5.593842,4.170994,0.2,17.6,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.168,319,224.0.1.129,319,UDP,7,602,37.178,86.0,6.196341,5.103783,0.2,16.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.131,319,224.0.1.129,319,UDP,6,516,39.8,86.0,7.960082,4.150032,0.2,13.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.201,319,224.0.1.129,319,UDP,5,430,28.865,86.0,7.216178,4.7987,0.2,14.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.166,319,224.0.1.129,319,UDP,7,602,39.891,86.0,6.648537,5.122631,0.2,15.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.189,319,224.0.1.129,319,UDP,5,430,37.371,86.0,9.342736,6.498406,0.1,11.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.111,319,224.0.1.129,319,UDP,7,602,29.697,86.0,4.949463,3.767283,0.2,20.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.149,319,224.0.1.129,319,UDP,5,430,37.973,86.0,9.493294,6.103851,0.1,11.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.155,319,224.0.1.129,319,UDP,5,430,36.731,86.0,9.182694,7.523286,0.1,11.7,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.145,319,224.0.1.129,319,UDP,5,430,28.512,86.0,7.128005,4.238535,0.2,15.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.204,319,224.0.1.129,319,UDP,6,516,39.097,86.0,7.819482,4.543602,0.2,13.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.129,319,224.0.1.129,319,UDP,5,430,29.332,86.0,7.332979,4.682394,0.2,14.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.134,319,224.0.1.129,319,UDP,7,602,31.445,86.0,5.240851,4.621927,0.2,19.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.169,319,224.0.1.129,319,UDP,4,344,33.292,86.0,11.097321,2.343491,0.1,10.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.112,319,224.0.1.129,319,UDP,8,688,34.032,86.0,4.861688,2.928379,0.2,20.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.128,49153,239.1.2.10,8400,UDP,19,24434,37.998,1286.0,2.111021,0.471804,0.5,643.0,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.152,319,224.0.1.129,319,UDP,4,344,34.766,86.0,11.588596,2.929211,0.1,9.9,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.150,319,224.0.1.129,319,UDP,3,258,25.091,86.0,12.545264,2.439569,0.1,10.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.128,319,224.0.1.129,319,UDP,5,430,28.112,86.0,7.028085,6.929328,0.2,15.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.142,319,224.0.1.129,319,UDP,7,602,37.558,86.0,6.259691,4.739393,0.2,16.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.141,319,224.0.1.129,319,UDP,6,516,35.817,86.0,7.163342,5.686353,0.2,14.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.173,319,224.0.1.129,319,UDP,5,430,38.1,86.0,9.524951,6.434794,0.1,11.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.214,319,224.0.1.129,319,UDP,6,516,32.909,86.0,6.581718,4.919554,0.2,15.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.130,319,224.0.1.129,319,UDP,6,516,36.64,86.0,7.328085,6.200818,0.2,14.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.125,319,224.0.1.129,319,UDP,5,430,24.249,86.0,6.062152,5.320428,0.2,17.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.210,319,224.0.1.129,319,UDP,4,344,36.685,86.0,12.228269,2.177304,0.1,9.4,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.149,319,224.0.1.129,319,UDP,7,602,36.026,86.0,6.0043,2.980242,0.2,16.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.142,319,224.0.1.129,319,UDP,4,344,27.776,86.0,9.258506,6.406249,0.1,12.4,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.152,319,224.0.1.129,319,UDP,4,344,32.056,86.0,10.685259,5.635126,0.1,10.7,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.165,319,224.0.1.129,319,UDP,4,344,36.327,86.0,12.109128,1.960391,0.1,9.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.162,319,224.0.1.129,319,UDP,6,516,33.397,86.0,6.679302,4.771083,0.2,15.5,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.1.1,319,224.0.1.129,319,UDP,6,516,32.838,86.0,6.567656,3.786976,0.2,15.7,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
0.0.0.0,68,255.255.255.255,67,UDP,3,1050,34.652,350.0,17.326135,7.850539,0.1,30.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.178,319,224.0.1.129,319,UDP,4,344,25.87,86.0,8.623368,3.750274,0.2,13.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.115,319,224.0.1.129,319,UDP,4,344,27.657,86.0,9.21893,2.212154,0.1,12.4,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.133,319,224.0.1.129,319,UDP,4,344,30.422,86.0,10.140536,7.76124,0.1,11.3,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.142,49153,239.1.2.10,8400,UDP,18,23148,35.999,1286.0,2.117566,0.484844,0.5,643.0,0,0,0.5,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.213,319,224.0.1.129,319,UDP,4,344,32.566,86.0,10.855309,3.223699,0.1,10.6,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.200,319,224.0.1.129,319,UDP,5,430,32.271,86.0,8.067727,5.309976,0.2,13.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.160,319,224.0.1.129,319,UDP,4,344,28.477,86.0,9.492486,7.880677,0.1,12.1,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.217,319,224.0.1.129,319,UDP,4,344,29.98,86.0,9.993465,4.654799,0.1,11.5,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.185,319,224.0.1.129,319,UDP,3,258,28.938,86.0,14.469163,1.31987,0.1,8.9,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.133,319,224.0.1.129,319,UDP,5,430,28.069,86.0,7.017292,4.175806,0.2,15.3,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.175,319,224.0.1.129,319,UDP,4,344,24.667,86.0,8.222474,6.770674,0.2,13.9,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.122,319,224.0.1.129,319,UDP,7,602,35.159,86.0,5.85981,5.678298,0.2,17.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.151,319,224.0.1.129,319,UDP,5,430,33.587,86.0,8.396728,4.989681,0.1,12.8,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.112,319,224.0.1.129,319,UDP,6,516,30.133,86.0,6.026505,5.83794,0.2,17.1,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.143,319,224.0.1.129,319,UDP,5,430,25.358,86.0,6.339618,4.699212,0.2,17.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.170,319,224.0.1.129,319,UDP,6,516,19.706,86.0,3.941216,2.849791,0.3,26.2,0,0,0.3,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.131,319,224.0.1.129,319,UDP,7,602,28.437,86.0,4.739563,4.642557,0.2,21.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.197,319,224.0.1.129,319,UDP,4,344,29.762,86.0,9.920579,3.661659,0.1,11.6,0,0,0.1,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.145,319,224.0.1.129,319,UDP,5,430,30.823,86.0,7.705734,3.558499,0.2,14.0,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.148,319,224.0.1.129,319,UDP,5,430,30.277,86.0,7.56925,4.641159,0.2,14.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.192,319,224.0.1.129,319,UDP,5,430,27.889,86.0,6.972166,5.219693,0.2,15.4,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.7.128,319,224.0.1.129,319,UDP,4,344,18.901,86.0,6.300387,6.09843,0.2,18.2,0,0,0.2,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
10.106.30.117,0,224.0.0.22,0,2,3,180,4.488,60.0,2.243994,3.032118,0.7,40.1,0,0,0.7,0,0,0,0,0.7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
192.168.6.1,5353,224.0.0.251,5353,UDP,4,344,1.005,86.0,0.334957,0.578808,4.0,342.3,0,0,4.0,0,0,0,0,4.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4.0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
|
BIN
1 PTPGM.pcapng
Normal file
BIN
1 PTPGM.pcapng
Normal file
Binary file not shown.
BIN
FSTDaircraft.pcapng
Normal file
BIN
FSTDaircraft.pcapng
Normal file
Binary file not shown.
61
airstream.py
Executable file
61
airstream.py
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
from scapy.all import get_if_list
|
||||
|
||||
from frametypes import FRAME_TYPES
|
||||
from core.analyzer import PacketFlowAnalyzer
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Airstream - Packet Flow Analyzer")
|
||||
p.add_argument('-p', '--pcap', help='PCAP file')
|
||||
p.add_argument('-i', '--interface', help='Network interface')
|
||||
p.add_argument('-c', '--count', type=int, default=100, help='Packet count (default: 100)')
|
||||
p.add_argument('-l', '--list-interfaces', action='store_true', help='List interfaces')
|
||||
p.add_argument('-o', '--output', help='CSV output file')
|
||||
p.add_argument('-s', '--stats', nargs='+', choices=list(FRAME_TYPES.keys()) + ['all'],
|
||||
default=['overview'], help='Statistics types to use (default: overview, use "all" for all types)')
|
||||
|
||||
args = p.parse_args()
|
||||
|
||||
if args.list_interfaces:
|
||||
print("Interfaces:", *get_if_list(), sep='\n ')
|
||||
return
|
||||
|
||||
if not (args.pcap or args.interface):
|
||||
p.error("Specify --pcap or --interface")
|
||||
|
||||
# Handle 'all' option
|
||||
if 'all' in args.stats:
|
||||
selected_stats = list(FRAME_TYPES.keys())
|
||||
stats_classes = list(FRAME_TYPES.values())
|
||||
else:
|
||||
selected_stats = args.stats
|
||||
stats_classes = [FRAME_TYPES[s] for s in args.stats]
|
||||
|
||||
print(f"Using stats: {', '.join(selected_stats)}")
|
||||
|
||||
analyzer = PacketFlowAnalyzer(stats_classes)
|
||||
|
||||
try:
|
||||
if args.pcap:
|
||||
analyzer.analyze_pcap(args.pcap)
|
||||
else:
|
||||
analyzer.analyze_live(args.interface, args.count)
|
||||
|
||||
analyzer.print_summary()
|
||||
|
||||
if args.output:
|
||||
analyzer.summary().to_csv(args.output, index=False)
|
||||
print(f"Saved: {args.output}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nInterrupted")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
179
airstream_pyshark.py
Executable file
179
airstream_pyshark.py
Executable file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Airstream PyShark Proof of Concept
|
||||
===================================
|
||||
|
||||
Alternative implementation using PyShark for enhanced protocol support.
|
||||
|
||||
Key Features:
|
||||
- Uses Wireshark dissectors for comprehensive protocol decoding
|
||||
- Supports custom Lua dissectors automatically
|
||||
- Provides Wireshark display filter support
|
||||
- Can decode any protocol that Wireshark understands
|
||||
|
||||
Requirements:
|
||||
- pip install pyshark
|
||||
- Wireshark/tshark must be installed on the system
|
||||
|
||||
Usage:
|
||||
./airstream_pyshark.py -p capture.pcap
|
||||
./airstream_pyshark.py -i eth0 -c 100
|
||||
./airstream_pyshark.py -p capture.pcap --filter "tcp.port==80"
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
try:
|
||||
import pyshark
|
||||
except ImportError:
|
||||
print("Error: pyshark not installed. Run: pip install pyshark")
|
||||
sys.exit(1)
|
||||
|
||||
from pyshark_poc.analyzer import PySharkAnalyzer
|
||||
from pyshark_poc.stats import STATS_TYPES
|
||||
|
||||
|
||||
def get_interfaces():
|
||||
"""Get list of available network interfaces."""
|
||||
try:
|
||||
# PyShark doesn't provide interface listing directly
|
||||
# Use tshark command
|
||||
import subprocess
|
||||
result = subprocess.run(['tshark', '-D'], capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
interfaces = []
|
||||
for line in result.stdout.strip().split('\n'):
|
||||
# Parse lines like "1. eth0"
|
||||
parts = line.split('. ', 1)
|
||||
if len(parts) == 2:
|
||||
interfaces.append(parts[1].split(' ')[0])
|
||||
return interfaces
|
||||
except:
|
||||
pass
|
||||
return ["Unable to list interfaces - tshark may not be installed"]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Airstream PyShark - Enhanced packet flow analyzer with Wireshark dissector support",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
Analyze PCAP file:
|
||||
%(prog)s -p capture.pcap
|
||||
|
||||
Live capture with filter:
|
||||
%(prog)s -i eth0 -c 1000 --filter "tcp.port==443"
|
||||
|
||||
Use BPF filter for capture:
|
||||
%(prog)s -i eth0 --bpf "port 80 or port 443"
|
||||
|
||||
Export to CSV:
|
||||
%(prog)s -p capture.pcap -o results.csv
|
||||
|
||||
PyShark Advantages:
|
||||
- Full Wireshark protocol decoding
|
||||
- Custom Lua dissector support
|
||||
- Advanced display filters
|
||||
- Automatic field extraction
|
||||
"""
|
||||
)
|
||||
|
||||
# Input sources
|
||||
input_group = parser.add_mutually_exclusive_group()
|
||||
input_group.add_argument('-p', '--pcap', help='PCAP file to analyze')
|
||||
input_group.add_argument('-i', '--interface', help='Network interface for live capture')
|
||||
|
||||
# Capture options
|
||||
parser.add_argument('-c', '--count', type=int, default=100,
|
||||
help='Number of packets to capture (default: 100)')
|
||||
|
||||
# Filtering options
|
||||
parser.add_argument('--filter', '--display-filter', dest='display_filter',
|
||||
help='Wireshark display filter (e.g., "tcp.port==80")')
|
||||
parser.add_argument('--bpf', '--bpf-filter', dest='bpf_filter',
|
||||
help='BPF capture filter for live capture (e.g., "port 80")')
|
||||
|
||||
# Output options
|
||||
parser.add_argument('-o', '--output', help='CSV output file')
|
||||
|
||||
# Statistics options
|
||||
parser.add_argument('-s', '--stats', nargs='+',
|
||||
choices=list(STATS_TYPES.keys()) + ['all'],
|
||||
default=['overview'],
|
||||
help='Statistics types to use (default: overview)')
|
||||
|
||||
# Utility options
|
||||
parser.add_argument('-l', '--list-interfaces', action='store_true',
|
||||
help='List available network interfaces')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Verbose output')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Handle interface listing
|
||||
if args.list_interfaces:
|
||||
print("Available interfaces:")
|
||||
for iface in get_interfaces():
|
||||
print(f" {iface}")
|
||||
return
|
||||
|
||||
# Validate input
|
||||
if not (args.pcap or args.interface):
|
||||
parser.error("Specify either --pcap or --interface")
|
||||
|
||||
# Handle statistics selection
|
||||
if 'all' in args.stats:
|
||||
selected_stats = list(STATS_TYPES.keys())
|
||||
stats_classes = list(STATS_TYPES.values())
|
||||
else:
|
||||
selected_stats = args.stats
|
||||
stats_classes = [STATS_TYPES[s] for s in args.stats]
|
||||
|
||||
print(f"Using stats: {', '.join(selected_stats)}")
|
||||
|
||||
# Create analyzer
|
||||
analyzer = PySharkAnalyzer(stats_classes)
|
||||
|
||||
try:
|
||||
# Perform analysis
|
||||
if args.pcap:
|
||||
analyzer.analyze_pcap(args.pcap, display_filter=args.display_filter)
|
||||
else:
|
||||
analyzer.analyze_live(
|
||||
args.interface,
|
||||
args.count,
|
||||
display_filter=args.display_filter,
|
||||
bpf_filter=args.bpf_filter
|
||||
)
|
||||
|
||||
# Print results
|
||||
analyzer.print_summary()
|
||||
|
||||
# Show protocol distribution if verbose
|
||||
if args.verbose:
|
||||
print("\nProtocol distribution:")
|
||||
protocol_summary = analyzer.get_protocol_summary()
|
||||
if not protocol_summary.empty:
|
||||
print(protocol_summary.to_string(index=False))
|
||||
|
||||
# Save to CSV if requested
|
||||
if args.output:
|
||||
df = analyzer.summary()
|
||||
df.to_csv(args.output, index=False)
|
||||
print(f"\nSaved results to: {args.output}")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nInterrupted by user")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
if args.verbose:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5
core/__init__.py
Normal file
5
core/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from core.analyzer import PacketFlowAnalyzer
|
||||
from core.models import FlowKey
|
||||
from core.stats import MultiStats
|
||||
|
||||
__all__ = ['PacketFlowAnalyzer', 'FlowKey', 'MultiStats']
|
||||
BIN
core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/analyzer.cpython-313.pyc
Normal file
BIN
core/__pycache__/analyzer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/models.cpython-313.pyc
Normal file
BIN
core/__pycache__/models.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/stats.cpython-313.pyc
Normal file
BIN
core/__pycache__/stats.cpython-313.pyc
Normal file
Binary file not shown.
72
core/analyzer.py
Normal file
72
core/analyzer.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from collections import defaultdict
|
||||
from typing import Optional, List, Type
|
||||
|
||||
import pandas as pd
|
||||
from scapy.all import PcapReader, IP, TCP, UDP, sniff
|
||||
from tabulate import tabulate
|
||||
|
||||
from frametypes import FrameTypeInterface, FRAME_TYPES
|
||||
from core.models import FlowKey
|
||||
from core.stats import MultiStats
|
||||
|
||||
|
||||
class PacketFlowAnalyzer:
|
||||
def __init__(self, stats_classes: List[Type[FrameTypeInterface]] = None):
|
||||
if stats_classes is None:
|
||||
stats_classes = [FRAME_TYPES['overview']]
|
||||
self.stats_classes = stats_classes
|
||||
self.flows = defaultdict(lambda: MultiStats(stats_classes))
|
||||
|
||||
def _get_flow_key(self, pkt) -> Optional[FlowKey]:
|
||||
if not pkt.haslayer(IP):
|
||||
return None
|
||||
|
||||
ip = pkt[IP]
|
||||
if pkt.haslayer(TCP):
|
||||
return FlowKey(ip.src, pkt[TCP].sport, ip.dst, pkt[TCP].dport, "TCP")
|
||||
elif pkt.haslayer(UDP):
|
||||
return FlowKey(ip.src, pkt[UDP].sport, ip.dst, pkt[UDP].dport, "UDP")
|
||||
else:
|
||||
return FlowKey(ip.src, 0, ip.dst, 0, str(ip.proto))
|
||||
|
||||
def _process(self, pkt):
|
||||
key = self._get_flow_key(pkt)
|
||||
if key:
|
||||
self.flows[key].add(float(pkt.time), len(pkt), pkt)
|
||||
|
||||
def analyze_pcap(self, file: str):
|
||||
print(f"Analyzing: {file}")
|
||||
for pkt in PcapReader(file):
|
||||
self._process(pkt)
|
||||
print(f"Found {len(self.flows)} flows")
|
||||
|
||||
def analyze_live(self, iface: str, count: int = 100):
|
||||
print(f"Capturing {count} packets on {iface}")
|
||||
sniff(iface=iface, prn=self._process, count=count)
|
||||
print(f"Found {len(self.flows)} flows")
|
||||
|
||||
def summary(self) -> pd.DataFrame:
|
||||
rows = []
|
||||
for k, multi_stats in self.flows.items():
|
||||
row = {
|
||||
'Src IP': k.src_ip,
|
||||
'Src Port': k.src_port,
|
||||
'Dst IP': k.dst_ip,
|
||||
'Dst Port': k.dst_port,
|
||||
'Proto': k.protocol
|
||||
}
|
||||
if k.extended_type:
|
||||
row['Type'] = k.extended_type
|
||||
row.update(multi_stats.get_combined_summary())
|
||||
rows.append(row)
|
||||
return pd.DataFrame(rows)
|
||||
|
||||
def print_summary(self):
|
||||
df = self.summary()
|
||||
if df.empty:
|
||||
print("No flows detected")
|
||||
return
|
||||
|
||||
print(f"\n{len(df)} flows:")
|
||||
print(tabulate(df, headers='keys', tablefmt='plain', showindex=False))
|
||||
print(f"\nTotals: {df['Pkts'].sum()} packets, {df['Bytes'].sum()} bytes")
|
||||
12
core/models.py
Normal file
12
core/models.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FlowKey:
|
||||
src_ip: str
|
||||
src_port: int
|
||||
dst_ip: str
|
||||
dst_port: int
|
||||
protocol: str
|
||||
extended_type: Optional[str] = None # For extended frame types like IENA, Chapter 10, etc.
|
||||
31
core/stats.py
Normal file
31
core/stats.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from typing import Dict, List, Any, Type
|
||||
|
||||
from scapy.all import Packet
|
||||
|
||||
from frametypes import FrameTypeInterface
|
||||
|
||||
|
||||
class MultiStats:
|
||||
"""Container for multiple stats instances."""
|
||||
def __init__(self, stats_classes: List[Type[FrameTypeInterface]]):
|
||||
self.stats_instances = [cls() for cls in stats_classes]
|
||||
self.stats_classes = stats_classes
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
for stats in self.stats_instances:
|
||||
stats.add(timestamp, size, packet)
|
||||
|
||||
def get_combined_summary(self) -> Dict[str, Any]:
|
||||
"""Combine summaries from all stats instances."""
|
||||
combined = {}
|
||||
for i, stats in enumerate(self.stats_instances):
|
||||
summary = stats.get_summary_dict()
|
||||
class_name = self.stats_classes[i].__name__.replace('Stats', '')
|
||||
# Add prefix to avoid column name conflicts
|
||||
for key, value in summary.items():
|
||||
if key in ['Pkts', 'Bytes', 'Duration']: # Common columns
|
||||
if i == 0: # Only include once
|
||||
combined[key] = value
|
||||
else:
|
||||
combined[f"{class_name}:{key}"] = value
|
||||
return combined
|
||||
44
frametypes/__init__.py
Normal file
44
frametypes/__init__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""Frame type implementations for packet analysis."""
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
from .overview import Overview
|
||||
from .chapter10 import Chapter10Stats
|
||||
from .ch10_analog import Ch10AnalogStats
|
||||
from .ch10_tmats import Ch10TMATSStats
|
||||
from .ch10_pcm import Ch10PCMStats
|
||||
from .ch10_time import Ch10TimeStats
|
||||
from .iena import IENAStats
|
||||
from .ptp import PTPStats
|
||||
from .ptp_sync import PTPSyncStats
|
||||
from .ptp_announce import PTPAnnounceStats
|
||||
from .ptp_delay import PTPDelayStats
|
||||
|
||||
__all__ = [
|
||||
'FrameTypeInterface',
|
||||
'Overview',
|
||||
'Chapter10Stats',
|
||||
'Ch10AnalogStats',
|
||||
'Ch10TMATSStats',
|
||||
'Ch10PCMStats',
|
||||
'Ch10TimeStats',
|
||||
'IENAStats',
|
||||
'PTPStats',
|
||||
'PTPSyncStats',
|
||||
'PTPAnnounceStats',
|
||||
'PTPDelayStats',
|
||||
]
|
||||
|
||||
# Registry of available frame type classes
|
||||
FRAME_TYPES = {
|
||||
'overview': Overview,
|
||||
'chapter10': Chapter10Stats,
|
||||
'ch10-analog': Ch10AnalogStats,
|
||||
'ch10-tmats': Ch10TMATSStats,
|
||||
'ch10-pcm': Ch10PCMStats,
|
||||
'ch10-time': Ch10TimeStats,
|
||||
'iena': IENAStats,
|
||||
'ptp': PTPStats,
|
||||
'ptp-sync': PTPSyncStats,
|
||||
'ptp-announce': PTPAnnounceStats,
|
||||
'ptp-delay': PTPDelayStats
|
||||
}
|
||||
BIN
frametypes/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/base.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ch10_analog.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ch10_analog.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ch10_pcm.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ch10_pcm.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ch10_time.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ch10_time.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ch10_tmats.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ch10_tmats.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/chapter10.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/chapter10.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/iena.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/iena.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/overview.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/overview.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ptp.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ptp.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ptp_announce.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ptp_announce.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ptp_delay.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ptp_delay.cpython-313.pyc
Normal file
Binary file not shown.
BIN
frametypes/__pycache__/ptp_sync.cpython-313.pyc
Normal file
BIN
frametypes/__pycache__/ptp_sync.cpython-313.pyc
Normal file
Binary file not shown.
29
frametypes/base.py
Normal file
29
frametypes/base.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
|
||||
class FrameTypeInterface(ABC):
|
||||
def __init__(self):
|
||||
self.name: str = ""
|
||||
self.frames_list = []
|
||||
self.bytes = 0
|
||||
|
||||
def get_name(self):
|
||||
"""Return the interface's name"""
|
||||
return self.name
|
||||
|
||||
@abstractmethod
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
"""Add a packet to the statistics."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
"""Return a dictionary of statistics for the tabular report."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
"""Return column definitions as [(column_name, format_spec), ...]"""
|
||||
pass
|
||||
56
frametypes/ch10_analog.py
Normal file
56
frametypes/ch10_analog.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Ch10AnalogStats(FrameTypeInterface):
|
||||
"""Chapter 10 Analog Data Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "Chapter 10 Analog"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.channel_ids = set()
|
||||
self.sample_counts = defaultdict(int)
|
||||
self.data_gaps = 0
|
||||
self.overrange_count = 0
|
||||
self.underrange_count = 0
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, decode Ch10 analog headers
|
||||
# Extract channel ID, sample count, check for over/underrange
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Duration': round(duration, 3),
|
||||
'Channels': len(self.channel_ids),
|
||||
'Data Gaps': self.data_gaps,
|
||||
'Overrange': self.overrange_count,
|
||||
'Underrange': self.underrange_count,
|
||||
'Pkt/s': round(self.count / duration, 1) if duration > 0 else 0
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Channels', 'd'),
|
||||
('Data Gaps', 'd'),
|
||||
('Overrange', 'd'),
|
||||
('Underrange', 'd'),
|
||||
('Pkt/s', '.1f')
|
||||
]
|
||||
54
frametypes/ch10_pcm.py
Normal file
54
frametypes/ch10_pcm.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Ch10PCMStats(FrameTypeInterface):
|
||||
"""Chapter 10 PCM (Pulse Code Modulation) Data Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "Chapter 10 PCM"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.channel_ids = set()
|
||||
self.frame_sync_errors = 0
|
||||
self.bit_slip_events = 0
|
||||
self.minor_frame_count = 0
|
||||
self.major_frame_count = 0
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, decode PCM frame structure
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Duration': round(duration, 3),
|
||||
'Channels': len(self.channel_ids),
|
||||
'Sync Errors': self.frame_sync_errors,
|
||||
'Bit Slips': self.bit_slip_events,
|
||||
'Minor Frames': self.minor_frame_count,
|
||||
'Major Frames': self.major_frame_count
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Channels', 'd'),
|
||||
('Sync Errors', 'd'),
|
||||
('Bit Slips', 'd'),
|
||||
('Minor Frames', 'd'),
|
||||
('Major Frames', 'd')
|
||||
]
|
||||
52
frametypes/ch10_time.py
Normal file
52
frametypes/ch10_time.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Ch10TimeStats(FrameTypeInterface):
|
||||
"""Chapter 10 Time Data Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "Chapter 10 Time"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.time_sources = set()
|
||||
self.time_format_changes = 0
|
||||
self.leap_second_events = 0
|
||||
self.time_discontinuities = 0
|
||||
self.max_time_delta = 0
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, decode time packets
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Time Sources': len(self.time_sources),
|
||||
'Format Changes': self.time_format_changes,
|
||||
'Leap Seconds': self.leap_second_events,
|
||||
'Discontinuities': self.time_discontinuities,
|
||||
'Max Delta': round(self.max_time_delta, 6)
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Time Sources', 'd'),
|
||||
('Format Changes', 'd'),
|
||||
('Leap Seconds', 'd'),
|
||||
('Discontinuities', 'd'),
|
||||
('Max Delta', '.6f')
|
||||
]
|
||||
52
frametypes/ch10_tmats.py
Normal file
52
frametypes/ch10_tmats.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Ch10TMATSStats(FrameTypeInterface):
|
||||
"""Chapter 10 TMATS (Telemetry Attributes Transfer Standard) Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "Chapter 10 TMATS"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.tmats_versions = set()
|
||||
self.configuration_changes = 0
|
||||
self.g_records = 0 # Data source records
|
||||
self.r_records = 0 # Tape/storage records
|
||||
self.m_records = 0 # Multiplexing/modulation records
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, parse TMATS records
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Versions': len(self.tmats_versions),
|
||||
'Config Changes': self.configuration_changes,
|
||||
'G-Records': self.g_records,
|
||||
'R-Records': self.r_records,
|
||||
'M-Records': self.m_records
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Versions', 'd'),
|
||||
('Config Changes', 'd'),
|
||||
('G-Records', 'd'),
|
||||
('R-Records', 'd'),
|
||||
('M-Records', 'd')
|
||||
]
|
||||
57
frametypes/chapter10.py
Normal file
57
frametypes/chapter10.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Chapter10Stats(FrameTypeInterface):
|
||||
"""General Chapter 10 Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "Chapter 10"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.channel_ids = set()
|
||||
self.data_types = defaultdict(int)
|
||||
self.sequence_errors = 0
|
||||
self.last_sequence = {}
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# Simulate Chapter 10 specific processing
|
||||
# In real implementation, decode Chapter 10 headers
|
||||
if packet:
|
||||
# Example: extract channel ID and data type from payload
|
||||
# channel_id = extract_channel_id(packet)
|
||||
# data_type = extract_data_type(packet)
|
||||
# sequence = extract_sequence_number(packet)
|
||||
pass
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Duration': round(duration, 3),
|
||||
'Channels': len(self.channel_ids),
|
||||
'Seq Errors': self.sequence_errors,
|
||||
'Pkt/s': round(self.count / duration, 1) if duration > 0 else 0
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Channels', 'd'),
|
||||
('Seq Errors', 'd'),
|
||||
('Pkt/s', '.1f')
|
||||
]
|
||||
53
frametypes/iena.py
Normal file
53
frametypes/iena.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class IENAStats(FrameTypeInterface):
|
||||
"""IENA Protocol Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "IENA"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.key_fields = set()
|
||||
self.sequence_gaps = 0
|
||||
self.last_sequence = None
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# Simulate IENA specific processing
|
||||
if packet:
|
||||
# Example: extract IENA key field and sequence
|
||||
# key_field = extract_iena_key(packet)
|
||||
# sequence = extract_iena_sequence(packet)
|
||||
pass
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Duration': round(duration, 3),
|
||||
'Key Fields': len(self.key_fields),
|
||||
'Seq Gaps': self.sequence_gaps,
|
||||
'Pkt/s': round(self.count / duration, 1) if duration > 0 else 0
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Key Fields', 'd'),
|
||||
('Seq Gaps', 'd'),
|
||||
('Pkt/s', '.1f')
|
||||
]
|
||||
64
frametypes/overview.py
Normal file
64
frametypes/overview.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import statistics
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class Overview(FrameTypeInterface):
|
||||
def __init__(self):
|
||||
self.name = "Overview"
|
||||
self.count = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.Tdeltas = []
|
||||
self.bytes = 0
|
||||
self.frames_list = []
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
self.frames_list.append(packet)
|
||||
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
else:
|
||||
self.Tdeltas.append(timestamp - self.last_time)
|
||||
self.last_time = timestamp
|
||||
|
||||
@property
|
||||
def duration(self): return (self.last_time or 0) - (self.first_time or 0)
|
||||
@property
|
||||
def avg_size(self): return self.bytes / self.count if self.count else 0
|
||||
@property
|
||||
def avg_delta(self): return statistics.mean(self.Tdeltas) if self.Tdeltas else 0
|
||||
@property
|
||||
def std_delta(self): return statistics.stdev(self.Tdeltas) if len(self.Tdeltas) > 1 else 0
|
||||
@property
|
||||
def pkt_rate(self): return self.count / self.duration if self.duration > 0 else 0
|
||||
@property
|
||||
def byte_rate(self): return self.bytes / self.duration if self.duration > 0 else 0
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Bytes': self.bytes,
|
||||
'Duration': round(self.duration, 3),
|
||||
'Avg Size': round(self.avg_size, 1),
|
||||
'Avg TimeΔ': round(self.avg_delta, 6),
|
||||
'Time 1σ': round(self.std_delta, 6),
|
||||
'Pkt/s': round(self.pkt_rate, 1),
|
||||
'B/s': round(self.byte_rate, 1)
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Bytes', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Avg Size', '.1f'),
|
||||
('Avg Delta', '.6f'),
|
||||
('Std Delta', '.6f'),
|
||||
('Pkt/s', '.1f'),
|
||||
('B/s', '.1f')
|
||||
]
|
||||
56
frametypes/ptp.py
Normal file
56
frametypes/ptp.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class PTPStats(FrameTypeInterface):
|
||||
"""General PTP Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "PTP"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.sync_messages = 0
|
||||
self.follow_up_messages = 0
|
||||
self.delay_req_messages = 0
|
||||
self.delay_resp_messages = 0
|
||||
self.announce_messages = 0
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# Simulate PTP message type counting
|
||||
if packet:
|
||||
# Example: decode PTP message type
|
||||
# msg_type = extract_ptp_message_type(packet)
|
||||
pass
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Duration': round(duration, 3),
|
||||
'Sync': self.sync_messages,
|
||||
'Follow Up': self.follow_up_messages,
|
||||
'Delay Req': self.delay_req_messages,
|
||||
'Delay Resp': self.delay_resp_messages,
|
||||
'Announce': self.announce_messages
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Duration', '.3f'),
|
||||
('Sync', 'd'),
|
||||
('Follow Up', 'd'),
|
||||
('Delay Req', 'd'),
|
||||
('Delay Resp', 'd'),
|
||||
('Announce', 'd')
|
||||
]
|
||||
51
frametypes/ptp_announce.py
Normal file
51
frametypes/ptp_announce.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from collections import defaultdict
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class PTPAnnounceStats(FrameTypeInterface):
|
||||
"""PTP Announce Message Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "PTP Announce"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.announce_count = 0
|
||||
self.grandmaster_changes = 0
|
||||
self.priority_changes = 0
|
||||
self.grandmaster_ids = set()
|
||||
self.clock_classes = defaultdict(int)
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, decode PTP announce messages
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Announce': self.announce_count,
|
||||
'GM Changes': self.grandmaster_changes,
|
||||
'Priority Changes': self.priority_changes,
|
||||
'Grandmasters': len(self.grandmaster_ids),
|
||||
'Clock Classes': len(self.clock_classes)
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Announce', 'd'),
|
||||
('GM Changes', 'd'),
|
||||
('Priority Changes', 'd'),
|
||||
('Grandmasters', 'd'),
|
||||
('Clock Classes', 'd')
|
||||
]
|
||||
53
frametypes/ptp_delay.py
Normal file
53
frametypes/ptp_delay.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import statistics
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class PTPDelayStats(FrameTypeInterface):
|
||||
"""PTP Delay Request/Response Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "PTP Delay"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.delay_req_count = 0
|
||||
self.delay_resp_count = 0
|
||||
self.pdelay_req_count = 0
|
||||
self.pdelay_resp_count = 0
|
||||
self.round_trip_times = []
|
||||
self.asymmetry_values = []
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, match delay requests with responses
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
avg_rtt = statistics.mean(self.round_trip_times) if self.round_trip_times else 0
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Delay Req': self.delay_req_count,
|
||||
'Delay Resp': self.delay_resp_count,
|
||||
'PDelay Req': self.pdelay_req_count,
|
||||
'PDelay Resp': self.pdelay_resp_count,
|
||||
'Avg RTT': round(avg_rtt * 1000, 3) # Convert to ms
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Delay Req', 'd'),
|
||||
('Delay Resp', 'd'),
|
||||
('PDelay Req', 'd'),
|
||||
('PDelay Resp', 'd'),
|
||||
('Avg RTT', '.3f')
|
||||
]
|
||||
58
frametypes/ptp_sync.py
Normal file
58
frametypes/ptp_sync.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import statistics
|
||||
from typing import Dict, List, Any
|
||||
from scapy.all import Packet
|
||||
|
||||
from .base import FrameTypeInterface
|
||||
|
||||
|
||||
class PTPSyncStats(FrameTypeInterface):
|
||||
"""PTP Sync Message Statistics"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.name = "PTP Sync"
|
||||
self.count = 0
|
||||
self.bytes = 0
|
||||
self.first_time = None
|
||||
self.last_time = None
|
||||
self.sync_count = 0
|
||||
self.follow_up_count = 0
|
||||
self.two_step_count = 0
|
||||
self.one_step_count = 0
|
||||
self.sync_intervals = []
|
||||
self.clock_ids = set()
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Packet):
|
||||
self.count += 1
|
||||
self.bytes += size
|
||||
if self.first_time is None:
|
||||
self.first_time = timestamp
|
||||
else:
|
||||
if self.last_time and self.sync_count > 0:
|
||||
self.sync_intervals.append(timestamp - self.last_time)
|
||||
self.last_time = timestamp
|
||||
|
||||
# In real implementation, decode PTP sync messages
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
duration = (self.last_time or 0) - (self.first_time or 0)
|
||||
avg_interval = statistics.mean(self.sync_intervals) if self.sync_intervals else 0
|
||||
return {
|
||||
'Pkts': self.count,
|
||||
'Sync Msgs': self.sync_count,
|
||||
'Follow-ups': self.follow_up_count,
|
||||
'Two-step': self.two_step_count,
|
||||
'One-step': self.one_step_count,
|
||||
'Clock IDs': len(self.clock_ids),
|
||||
'Avg Interval': round(avg_interval, 6)
|
||||
}
|
||||
|
||||
def get_column_definitions(self) -> List[tuple]:
|
||||
return [
|
||||
('Pkts', 'd'),
|
||||
('Sync Msgs', 'd'),
|
||||
('Follow-ups', 'd'),
|
||||
('Two-step', 'd'),
|
||||
('One-step', 'd'),
|
||||
('Clock IDs', 'd'),
|
||||
('Avg Interval', '.6f')
|
||||
]
|
||||
64
lua_dissectors/README.md
Normal file
64
lua_dissectors/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Lua Dissectors for Airstream PyShark
|
||||
|
||||
This directory contains example Lua dissectors that can be used with Wireshark/tshark to decode custom protocols in PyShark.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Copy the Lua dissector files to your Wireshark plugins directory:
|
||||
- **Linux/Mac**: `~/.local/lib/wireshark/plugins/` or `~/.config/wireshark/plugins/`
|
||||
- **Windows**: `%APPDATA%\Wireshark\plugins\`
|
||||
|
||||
2. Restart Wireshark/tshark or reload Lua plugins (Ctrl+Shift+L in Wireshark)
|
||||
|
||||
3. The dissectors will automatically be available to PyShark
|
||||
|
||||
## Example Custom Protocol Dissector
|
||||
|
||||
The `example_custom_protocol.lua` demonstrates:
|
||||
- Creating a custom protocol dissector
|
||||
- Defining protocol fields
|
||||
- Parsing packet structure
|
||||
- Registering for specific UDP ports
|
||||
- Heuristic dissection
|
||||
|
||||
## Using with PyShark
|
||||
|
||||
Once installed, PyShark will automatically use these dissectors:
|
||||
|
||||
```python
|
||||
import pyshark
|
||||
|
||||
# Capture with custom dissector
|
||||
capture = pyshark.FileCapture('capture.pcap')
|
||||
for packet in capture:
|
||||
if hasattr(packet, 'custom'):
|
||||
print(f"Custom packet: {packet.custom.msg_type}")
|
||||
```
|
||||
|
||||
## Creating Your Own Dissectors
|
||||
|
||||
1. Copy `example_custom_protocol.lua` as a template
|
||||
2. Modify the protocol name, fields, and parsing logic
|
||||
3. Register for appropriate ports or use heuristic detection
|
||||
4. Place in Wireshark plugins directory
|
||||
|
||||
## Benefits for Airstream
|
||||
|
||||
Custom Lua dissectors enable:
|
||||
- Decoding proprietary protocols (IENA, Chapter 10, etc.)
|
||||
- Adding metadata extraction
|
||||
- Protocol-specific statistics
|
||||
- Enhanced filtering capabilities
|
||||
|
||||
## Testing Dissectors
|
||||
|
||||
Test your dissector in Wireshark GUI first:
|
||||
1. Open a capture file
|
||||
2. Check if protocol appears in packet list
|
||||
3. Verify field extraction in packet details
|
||||
4. Use display filters like `custom.msg_type == 1`
|
||||
|
||||
Then use with airstream_pyshark.py:
|
||||
```bash
|
||||
./airstream_pyshark.py -p capture.pcap --filter "custom"
|
||||
```
|
||||
97
lua_dissectors/example_custom_protocol.lua
Normal file
97
lua_dissectors/example_custom_protocol.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
-- Example Custom Protocol Dissector for Wireshark/PyShark
|
||||
-- Place this file in your Wireshark plugins directory:
|
||||
-- Linux/Mac: ~/.local/lib/wireshark/plugins/ or ~/.wireshark/plugins/
|
||||
-- Windows: %APPDATA%\Wireshark\plugins\
|
||||
--
|
||||
-- This dissector will automatically be available to PyShark via tshark
|
||||
|
||||
-- Create protocol
|
||||
local custom_proto = Proto("custom", "Custom Airstream Protocol")
|
||||
|
||||
-- Define fields
|
||||
local fields = {
|
||||
magic = ProtoField.uint32("custom.magic", "Magic Number", base.HEX),
|
||||
version = ProtoField.uint8("custom.version", "Version", base.DEC),
|
||||
msg_type = ProtoField.uint8("custom.msg_type", "Message Type", base.DEC, {
|
||||
[1] = "Data",
|
||||
[2] = "Control",
|
||||
[3] = "Status",
|
||||
[4] = "Telemetry"
|
||||
}),
|
||||
length = ProtoField.uint16("custom.length", "Payload Length", base.DEC),
|
||||
sequence = ProtoField.uint32("custom.sequence", "Sequence Number", base.DEC),
|
||||
timestamp = ProtoField.uint64("custom.timestamp", "Timestamp", base.DEC),
|
||||
payload = ProtoField.bytes("custom.payload", "Payload")
|
||||
}
|
||||
|
||||
-- Add fields to protocol
|
||||
custom_proto.fields = fields
|
||||
|
||||
-- Dissector function
|
||||
function custom_proto.dissector(buffer, pinfo, tree)
|
||||
-- Validate minimum length
|
||||
if buffer:len() < 20 then
|
||||
return
|
||||
end
|
||||
|
||||
-- Check magic number (example: 0xABCD1234)
|
||||
local magic = buffer(0,4):uint()
|
||||
if magic ~= 0xABCD1234 then
|
||||
return -- Not our protocol
|
||||
end
|
||||
|
||||
-- Set protocol column in packet list
|
||||
pinfo.cols.protocol:set("CUSTOM")
|
||||
|
||||
-- Create subtree for our protocol
|
||||
local subtree = tree:add(custom_proto, buffer(), "Custom Airstream Protocol")
|
||||
|
||||
-- Add fields to tree
|
||||
subtree:add(fields.magic, buffer(0,4))
|
||||
subtree:add(fields.version, buffer(4,1))
|
||||
|
||||
local msg_type = buffer(5,1):uint()
|
||||
subtree:add(fields.msg_type, buffer(5,1))
|
||||
|
||||
subtree:add(fields.length, buffer(6,2))
|
||||
subtree:add(fields.sequence, buffer(8,4))
|
||||
subtree:add(fields.timestamp, buffer(12,8))
|
||||
|
||||
-- Add payload if present
|
||||
local payload_len = buffer(6,2):uint()
|
||||
if buffer:len() >= 20 + payload_len then
|
||||
subtree:add(fields.payload, buffer(20, payload_len))
|
||||
end
|
||||
|
||||
-- Update info column with summary
|
||||
local type_names = {[1]="Data", [2]="Control", [3]="Status", [4]="Telemetry"}
|
||||
local type_name = type_names[msg_type] or "Unknown"
|
||||
pinfo.cols.info:set(string.format("%s (Seq=%d, Len=%d)",
|
||||
type_name,
|
||||
buffer(8,4):uint(),
|
||||
payload_len))
|
||||
end
|
||||
|
||||
-- Register dissector for specific UDP port
|
||||
local udp_port = DissectorTable.get("udp.port")
|
||||
udp_port:add(9999, custom_proto) -- Listen on UDP port 9999
|
||||
|
||||
-- Also register as heuristic dissector for UDP
|
||||
local function heuristic_checker(buffer, pinfo, tree)
|
||||
-- Check if this might be our protocol
|
||||
if buffer:len() < 20 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check magic number
|
||||
local magic = buffer(0,4):uint()
|
||||
if magic == 0xABCD1234 then
|
||||
custom_proto.dissector(buffer, pinfo, tree)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Register heuristic dissector
|
||||
custom_proto:register_heuristic("udp", heuristic_checker)
|
||||
146
pyshark_poc/README.md
Normal file
146
pyshark_poc/README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# PyShark Proof of Concept for Airstream
|
||||
|
||||
This is an alternative implementation of Airstream using PyShark instead of Scapy. PyShark leverages Wireshark's powerful dissector engine for comprehensive protocol support.
|
||||
|
||||
## Key Advantages
|
||||
|
||||
### 1. **Full Wireshark Protocol Support**
|
||||
- Automatically uses ALL installed Wireshark dissectors
|
||||
- Supports 2000+ protocols out of the box
|
||||
- Better decoding for complex protocols (PTP, IENA, Chapter 10)
|
||||
|
||||
### 2. **Custom Dissector Support**
|
||||
- Any Lua dissector installed in Wireshark works automatically
|
||||
- See `lua_dissectors/` for examples
|
||||
- No code changes needed to support new protocols
|
||||
|
||||
### 3. **Advanced Filtering**
|
||||
- Full Wireshark display filter syntax
|
||||
- BPF capture filters for performance
|
||||
- Protocol-specific field access
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Install PyShark (requires tshark/Wireshark)
|
||||
pip install pyshark
|
||||
|
||||
# On macOS
|
||||
brew install wireshark
|
||||
|
||||
# On Ubuntu/Debian
|
||||
sudo apt-get install tshark
|
||||
|
||||
# On RHEL/CentOS
|
||||
sudo yum install wireshark
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Basic PCAP analysis
|
||||
./airstream_pyshark.py -p capture.pcap
|
||||
|
||||
# Live capture with filter
|
||||
./airstream_pyshark.py -i eth0 -c 1000 --filter "tcp.port==443"
|
||||
|
||||
# Use BPF filter for efficient capture
|
||||
./airstream_pyshark.py -i eth0 --bpf "port 80 or port 443"
|
||||
|
||||
# Export results to CSV
|
||||
./airstream_pyshark.py -p capture.pcap -o results.csv
|
||||
|
||||
# Use PTP-specific statistics
|
||||
./airstream_pyshark.py -p ptp_traffic.pcap -s ptp
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
airstream_pyshark.py # Main entry point (CLI)
|
||||
pyshark_poc/
|
||||
├── __init__.py # Package initialization
|
||||
├── analyzer.py # PySharkAnalyzer class
|
||||
├── models.py # Data models (FlowKey)
|
||||
├── stats.py # Statistics classes
|
||||
└── README.md # This file
|
||||
|
||||
lua_dissectors/ # Custom Wireshark dissectors
|
||||
├── example_custom_protocol.lua
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Performance Comparison
|
||||
|
||||
| Aspect | Scapy | PyShark |
|
||||
|--------|-------|---------|
|
||||
| Packet Parsing Speed | Faster | Slower (XML overhead) |
|
||||
| Protocol Support | Limited | Comprehensive |
|
||||
| Custom Dissectors | Python only | Lua + C |
|
||||
| Memory Usage | Lower | Higher |
|
||||
| Dependencies | Python only | Requires tshark |
|
||||
|
||||
## When to Use PyShark
|
||||
|
||||
✅ **Use PyShark when:**
|
||||
- You need comprehensive protocol decoding
|
||||
- Working with proprietary protocols
|
||||
- Need Wireshark's advanced filtering
|
||||
- Protocol accuracy is critical
|
||||
|
||||
❌ **Use Scapy when:**
|
||||
- Performance is critical
|
||||
- Need packet crafting/modification
|
||||
- Minimal dependencies required
|
||||
- Simple protocol analysis
|
||||
|
||||
## Custom Protocol Support
|
||||
|
||||
To add custom protocol support:
|
||||
|
||||
1. Create a Lua dissector (see `lua_dissectors/example_custom_protocol.lua`)
|
||||
2. Install in Wireshark plugins directory
|
||||
3. PyShark automatically uses it
|
||||
|
||||
Example accessing custom fields:
|
||||
```python
|
||||
# After installing custom dissector
|
||||
capture = pyshark.FileCapture('custom_protocol.pcap')
|
||||
for packet in capture:
|
||||
if hasattr(packet, 'custom'):
|
||||
print(f"Message type: {packet.custom.msg_type}")
|
||||
print(f"Sequence: {packet.custom.sequence}")
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
1. **Performance**: Slower than Scapy due to XML parsing overhead
|
||||
2. **Dependencies**: Requires Wireshark/tshark installation
|
||||
3. **Read-only**: Cannot modify or craft packets
|
||||
4. **Platform-specific**: tshark paths may vary
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
- [ ] Parallel packet processing
|
||||
- [ ] Caching for improved performance
|
||||
- [ ] Integration with existing frametypes
|
||||
- [ ] Protocol-specific analyzers
|
||||
- [ ] Real-time streaming analysis
|
||||
- [ ] Custom field extractors
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
# Test with sample PCAP
|
||||
./airstream_pyshark.py -p "1 PTPGM.pcapng"
|
||||
|
||||
# List available interfaces
|
||||
./airstream_pyshark.py -l
|
||||
|
||||
# Verbose mode for debugging
|
||||
./airstream_pyshark.py -p capture.pcap -v
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
This PyShark implementation provides a powerful alternative when comprehensive protocol support is needed. While it trades performance for functionality, it enables analysis of complex protocols that would be difficult to implement in pure Python.
|
||||
20
pyshark_poc/__init__.py
Normal file
20
pyshark_poc/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
PyShark-based proof of concept for Airstream packet analyzer.
|
||||
|
||||
This module provides an alternative implementation using PyShark
|
||||
to leverage Wireshark's dissector capabilities.
|
||||
"""
|
||||
|
||||
from .analyzer import PySharkAnalyzer
|
||||
from .models import FlowKey
|
||||
from .stats import MultiStats, BaseStats, OverviewStats, PTPStats, STATS_TYPES
|
||||
|
||||
__all__ = [
|
||||
'PySharkAnalyzer',
|
||||
'FlowKey',
|
||||
'MultiStats',
|
||||
'BaseStats',
|
||||
'OverviewStats',
|
||||
'PTPStats',
|
||||
'STATS_TYPES'
|
||||
]
|
||||
BIN
pyshark_poc/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
pyshark_poc/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
pyshark_poc/__pycache__/analyzer.cpython-313.pyc
Normal file
BIN
pyshark_poc/__pycache__/analyzer.cpython-313.pyc
Normal file
Binary file not shown.
BIN
pyshark_poc/__pycache__/models.cpython-313.pyc
Normal file
BIN
pyshark_poc/__pycache__/models.cpython-313.pyc
Normal file
Binary file not shown.
BIN
pyshark_poc/__pycache__/stats.cpython-313.pyc
Normal file
BIN
pyshark_poc/__pycache__/stats.cpython-313.pyc
Normal file
Binary file not shown.
187
pyshark_poc/analyzer.py
Normal file
187
pyshark_poc/analyzer.py
Normal file
@@ -0,0 +1,187 @@
|
||||
import pyshark
|
||||
from collections import defaultdict
|
||||
from typing import Optional, List, Type, Union
|
||||
import pandas as pd
|
||||
from tabulate import tabulate
|
||||
|
||||
from .models import FlowKey
|
||||
from .stats import MultiStats, BaseStats, STATS_TYPES
|
||||
|
||||
|
||||
class PySharkAnalyzer:
|
||||
"""Packet flow analyzer using PyShark for Wireshark dissector support."""
|
||||
|
||||
def __init__(self, stats_classes: Optional[List[Type[BaseStats]]] = None):
|
||||
if stats_classes is None:
|
||||
stats_classes = [STATS_TYPES['overview']]
|
||||
self.stats_classes = stats_classes
|
||||
self.flows = defaultdict(lambda: MultiStats(stats_classes))
|
||||
self.packet_count = 0
|
||||
|
||||
def _get_flow_key(self, packet) -> Optional[FlowKey]:
|
||||
"""Extract flow key from PyShark packet."""
|
||||
try:
|
||||
# Check for IP layer
|
||||
if not hasattr(packet, 'ip'):
|
||||
return None
|
||||
|
||||
src_ip = packet.ip.src
|
||||
dst_ip = packet.ip.dst
|
||||
protocol = packet.transport_layer if hasattr(packet, 'transport_layer') else 'IP'
|
||||
|
||||
# Get ports based on protocol
|
||||
src_port = 0
|
||||
dst_port = 0
|
||||
|
||||
if hasattr(packet, 'tcp'):
|
||||
src_port = int(packet.tcp.srcport)
|
||||
dst_port = int(packet.tcp.dstport)
|
||||
protocol = 'TCP'
|
||||
elif hasattr(packet, 'udp'):
|
||||
src_port = int(packet.udp.srcport)
|
||||
dst_port = int(packet.udp.dstport)
|
||||
protocol = 'UDP'
|
||||
|
||||
# Check for extended protocol types
|
||||
extended_type = None
|
||||
if hasattr(packet, 'ptp'):
|
||||
extended_type = 'PTP'
|
||||
# Add more protocol detection here as needed
|
||||
|
||||
return FlowKey(src_ip, src_port, dst_ip, dst_port, protocol, extended_type)
|
||||
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
def _process_packet(self, packet):
|
||||
"""Process a single packet."""
|
||||
key = self._get_flow_key(packet)
|
||||
if key:
|
||||
# Get timestamp and size
|
||||
timestamp = float(packet.sniff_timestamp) if hasattr(packet, 'sniff_timestamp') else 0
|
||||
size = int(packet.length) if hasattr(packet, 'length') else 0
|
||||
|
||||
self.flows[key].add(timestamp, size, packet)
|
||||
self.packet_count += 1
|
||||
|
||||
def analyze_pcap(self, file: str, display_filter: Optional[str] = None):
|
||||
"""Analyze packets from a PCAP file."""
|
||||
print(f"Analyzing: {file}")
|
||||
if display_filter:
|
||||
print(f"Filter: {display_filter}")
|
||||
|
||||
try:
|
||||
# Use FileCapture for PCAP files
|
||||
capture = pyshark.FileCapture(
|
||||
file,
|
||||
display_filter=display_filter,
|
||||
use_json=True, # Use JSON output for better performance
|
||||
include_raw=False # Don't include raw packet data
|
||||
)
|
||||
|
||||
# Process packets
|
||||
for packet in capture:
|
||||
self._process_packet(packet)
|
||||
# Show progress every 1000 packets
|
||||
if self.packet_count % 1000 == 0:
|
||||
print(f" Processed {self.packet_count} packets...")
|
||||
|
||||
capture.close()
|
||||
print(f"Found {len(self.flows)} flows from {self.packet_count} packets")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error analyzing PCAP: {e}")
|
||||
|
||||
def analyze_live(self, interface: str, count: int = 100,
|
||||
display_filter: Optional[str] = None,
|
||||
bpf_filter: Optional[str] = None):
|
||||
"""Capture and analyze packets from a live interface."""
|
||||
print(f"Capturing {count} packets on {interface}")
|
||||
if display_filter:
|
||||
print(f"Display filter: {display_filter}")
|
||||
if bpf_filter:
|
||||
print(f"BPF filter: {bpf_filter}")
|
||||
|
||||
try:
|
||||
# Use LiveCapture for live capture
|
||||
capture = pyshark.LiveCapture(
|
||||
interface=interface,
|
||||
display_filter=display_filter,
|
||||
bpf_filter=bpf_filter,
|
||||
use_json=True,
|
||||
include_raw=False
|
||||
)
|
||||
|
||||
# Capture packets
|
||||
capture.sniff(packet_count=count)
|
||||
|
||||
# Process captured packets
|
||||
for packet in capture:
|
||||
self._process_packet(packet)
|
||||
|
||||
capture.close()
|
||||
print(f"Found {len(self.flows)} flows from {self.packet_count} packets")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during live capture: {e}")
|
||||
|
||||
def summary(self) -> pd.DataFrame:
|
||||
"""Generate summary DataFrame of all flows."""
|
||||
rows = []
|
||||
for key, multi_stats in self.flows.items():
|
||||
row = {
|
||||
'Src IP': key.src_ip,
|
||||
'Src Port': key.src_port,
|
||||
'Dst IP': key.dst_ip,
|
||||
'Dst Port': key.dst_port,
|
||||
'Proto': key.protocol
|
||||
}
|
||||
if key.extended_type:
|
||||
row['Type'] = key.extended_type
|
||||
row.update(multi_stats.get_combined_summary())
|
||||
rows.append(row)
|
||||
|
||||
# Sort by packet count descending
|
||||
df = pd.DataFrame(rows)
|
||||
if not df.empty and 'Pkts' in df.columns:
|
||||
df = df.sort_values('Pkts', ascending=False)
|
||||
return df
|
||||
|
||||
def print_summary(self):
|
||||
"""Print formatted summary of flows."""
|
||||
df = self.summary()
|
||||
if df.empty:
|
||||
print("No flows detected")
|
||||
return
|
||||
|
||||
print(f"\n{len(df)} flows:")
|
||||
print(tabulate(df, headers='keys', tablefmt='plain', showindex=False))
|
||||
|
||||
if 'Pkts' in df.columns and 'Bytes' in df.columns:
|
||||
print(f"\nTotals: {df['Pkts'].sum()} packets, {df['Bytes'].sum()} bytes")
|
||||
|
||||
def get_protocol_summary(self) -> pd.DataFrame:
|
||||
"""Get summary grouped by protocol."""
|
||||
df = self.summary()
|
||||
if df.empty:
|
||||
return df
|
||||
|
||||
# Group by protocol
|
||||
protocol_summary = df.groupby('Proto').agg({
|
||||
'Pkts': 'sum',
|
||||
'Bytes': 'sum'
|
||||
}).reset_index()
|
||||
|
||||
return protocol_summary
|
||||
|
||||
def apply_wireshark_filter(self, display_filter: str):
|
||||
"""
|
||||
Apply a Wireshark display filter to the analysis.
|
||||
This demonstrates PyShark's ability to use Wireshark's filtering.
|
||||
"""
|
||||
filtered_flows = defaultdict(lambda: MultiStats(self.stats_classes))
|
||||
|
||||
# This would require re-processing with the filter
|
||||
# Shown here as an example of the capability
|
||||
print(f"Note: To apply Wireshark filters, re-analyze with display_filter parameter")
|
||||
return filtered_flows
|
||||
13
pyshark_poc/models.py
Normal file
13
pyshark_poc/models.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FlowKey:
|
||||
"""Flow identifier for network traffic analysis."""
|
||||
src_ip: str
|
||||
src_port: int
|
||||
dst_ip: str
|
||||
dst_port: int
|
||||
protocol: str
|
||||
extended_type: Optional[str] = None # For extended frame types like IENA, Chapter 10, etc.
|
||||
145
pyshark_poc/stats.py
Normal file
145
pyshark_poc/stats.py
Normal file
@@ -0,0 +1,145 @@
|
||||
from typing import Dict, List, Any, Type, Optional
|
||||
import time
|
||||
|
||||
|
||||
class BaseStats:
|
||||
"""Base statistics class for packet flow analysis."""
|
||||
|
||||
def __init__(self):
|
||||
self.packet_count = 0
|
||||
self.byte_count = 0
|
||||
self.first_timestamp = None
|
||||
self.last_timestamp = None
|
||||
self.packet_sizes = []
|
||||
self.inter_arrival_times = []
|
||||
self.last_packet_time = None
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Any):
|
||||
"""Add a packet to statistics."""
|
||||
self.packet_count += 1
|
||||
self.byte_count += size
|
||||
self.packet_sizes.append(size)
|
||||
|
||||
if self.first_timestamp is None:
|
||||
self.first_timestamp = timestamp
|
||||
self.last_timestamp = timestamp
|
||||
|
||||
if self.last_packet_time is not None:
|
||||
delta = timestamp - self.last_packet_time
|
||||
self.inter_arrival_times.append(delta)
|
||||
self.last_packet_time = timestamp
|
||||
|
||||
# Call protocol-specific handler
|
||||
self._process_packet(packet)
|
||||
|
||||
def _process_packet(self, packet: Any):
|
||||
"""Override in subclasses for protocol-specific processing."""
|
||||
pass
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
"""Get summary statistics as dictionary."""
|
||||
duration = (self.last_timestamp - self.first_timestamp) if self.first_timestamp and self.last_timestamp else 0
|
||||
|
||||
summary = {
|
||||
'Pkts': self.packet_count,
|
||||
'Bytes': self.byte_count,
|
||||
'Duration': round(duration, 3) if duration else 0,
|
||||
'Avg Size': round(sum(self.packet_sizes) / len(self.packet_sizes), 1) if self.packet_sizes else 0,
|
||||
}
|
||||
|
||||
if self.inter_arrival_times:
|
||||
avg_delta = sum(self.inter_arrival_times) / len(self.inter_arrival_times)
|
||||
summary['Avg TimeΔ'] = round(avg_delta, 6)
|
||||
|
||||
# Calculate standard deviation
|
||||
if len(self.inter_arrival_times) > 1:
|
||||
mean = avg_delta
|
||||
variance = sum((x - mean) ** 2 for x in self.inter_arrival_times) / len(self.inter_arrival_times)
|
||||
std_dev = variance ** 0.5
|
||||
summary['Time 1σ'] = round(std_dev, 6)
|
||||
else:
|
||||
summary['Time 1σ'] = 0
|
||||
else:
|
||||
summary['Avg TimeΔ'] = 0
|
||||
summary['Time 1σ'] = 0
|
||||
|
||||
if duration > 0:
|
||||
summary['Pkt/s'] = round(self.packet_count / duration, 1)
|
||||
summary['B/s'] = round(self.byte_count / duration, 1)
|
||||
else:
|
||||
summary['Pkt/s'] = 0
|
||||
summary['B/s'] = 0
|
||||
|
||||
return summary
|
||||
|
||||
|
||||
class OverviewStats(BaseStats):
|
||||
"""Overview statistics for general packet analysis."""
|
||||
pass
|
||||
|
||||
|
||||
class PTPStats(BaseStats):
|
||||
"""PTP-specific statistics."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.ptp_message_types = {}
|
||||
|
||||
def _process_packet(self, packet: Any):
|
||||
"""Process PTP-specific packet information."""
|
||||
# Check if packet has PTP layer
|
||||
if hasattr(packet, 'ptp'):
|
||||
try:
|
||||
msg_type = packet.ptp.v2_messagetype if hasattr(packet.ptp, 'v2_messagetype') else 'unknown'
|
||||
self.ptp_message_types[msg_type] = self.ptp_message_types.get(msg_type, 0) + 1
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_summary_dict(self) -> Dict[str, Any]:
|
||||
summary = super().get_summary_dict()
|
||||
# Add PTP-specific metrics
|
||||
if self.ptp_message_types:
|
||||
summary['PTP Types'] = str(self.ptp_message_types)
|
||||
return summary
|
||||
|
||||
|
||||
class MultiStats:
|
||||
"""Container for multiple stats instances."""
|
||||
|
||||
def __init__(self, stats_classes: Optional[List[Type[BaseStats]]] = None):
|
||||
if stats_classes is None:
|
||||
stats_classes = [OverviewStats]
|
||||
self.stats_instances = [cls() for cls in stats_classes]
|
||||
self.stats_classes = stats_classes
|
||||
|
||||
def add(self, timestamp: float, size: int, packet: Any):
|
||||
"""Add packet to all stats instances."""
|
||||
for stats in self.stats_instances:
|
||||
stats.add(timestamp, size, packet)
|
||||
|
||||
def get_combined_summary(self) -> Dict[str, Any]:
|
||||
"""Combine summaries from all stats instances."""
|
||||
combined = {}
|
||||
for i, stats in enumerate(self.stats_instances):
|
||||
summary = stats.get_summary_dict()
|
||||
class_name = self.stats_classes[i].__name__.replace('Stats', '')
|
||||
|
||||
# Add prefix to avoid column name conflicts
|
||||
for key, value in summary.items():
|
||||
if key in ['Pkts', 'Bytes', 'Duration']: # Common columns
|
||||
if i == 0: # Only include once
|
||||
combined[key] = value
|
||||
else:
|
||||
# Only add prefix if we have multiple stats classes
|
||||
if len(self.stats_classes) > 1:
|
||||
combined[f"{class_name}:{key}"] = value
|
||||
else:
|
||||
combined[key] = value
|
||||
return combined
|
||||
|
||||
|
||||
# Stats registry for easy lookup
|
||||
STATS_TYPES = {
|
||||
'overview': OverviewStats,
|
||||
'ptp': PTPStats,
|
||||
}
|
||||
Reference in New Issue
Block a user