Discriminate between multiple virtual networks.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 52s

This commit is contained in:
feyris-tan 2026-06-14 21:29:10 +02:00
parent c3fff246d5
commit 1b01ed8553
32 changed files with 1025 additions and 591 deletions

View File

@ -19,3 +19,13 @@ These will have IP packets forwarded to.
|--|-----------|
| 1|PCAP Writer|
| 2|Discard |
#Network Types
These identify sources from which a network packet may come from.
|ID|Type |
|--|----------|
| 0|Reserved |
| 1|ATSC3 PLP |
| 2|MPEG-2 PID|
| 3|DVB MIS |
| 4|AAL5 |

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Atsc.A322
{
[VirtualNetworkId(1)]
internal class Atsc3PlpVirtualNetworkIdentifier : VirtualNetworkIdentifier
{
public ushort PlpId { get; }
public Atsc3PlpVirtualNetworkIdentifier(ushort plpId)
{
PlpId = plpId;
}
public override string GetCaptureFilenamePrefix()
{
return String.Format("atsc3plp{0}", PlpId);
}
public override string GetHumanReadableName()
{
return String.Format("ATSC3 PLP {0}", PlpId);
}
public override int GetIdentifier()
{
return PlpId;
}
}
}

View File

@ -155,9 +155,14 @@ namespace skyscraper8.Atsc.A322
}
}
private Atsc3PlpVirtualNetworkIdentifier networkIdentifier;
private void HandleIpv4(byte[] newPacketPayload)
{
_eventHandler?.OnIpDatagram(0x1ffd, newPacketPayload);
if (networkIdentifier == null)
{
networkIdentifier = new Atsc3PlpVirtualNetworkIdentifier(_plpId);
}
_eventHandler?.OnIpDatagram(networkIdentifier, newPacketPayload);
}
private void HandleLinkLayerSignalling(AdditionalHeaderForSignalingInformation signalingInformation, byte[] payload)

View File

@ -5,12 +5,13 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Atsc.A330;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Atsc.A322
{
internal interface IAtscPlpEventHandler
{
void OnIpDatagram(int pid, byte[] payload);
void OnIpDatagram(VirtualNetworkIdentifier pid, byte[] payload);
void OnAtsc3LinkMappingTable(ushort plp, AdditionalHeaderForSignalingInformation signalingInformation, LinkMappingTable lmt);
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Atsc.A324
{
[VirtualNetworkId(3)]
internal class StltpNetworkIdentifier : VirtualNetworkIdentifier
{
public StltpNetworkIdentifier()
{
this.guid = Guid.NewGuid();
}
private Guid guid;
public override string GetCaptureFilenamePrefix()
{
return "stltp";
}
public override string GetHumanReadableName()
{
return "ATSC3 STLTP";
}
public override int GetIdentifier()
{
return guid.GetHashCode();
}
}
}

View File

@ -115,7 +115,11 @@ namespace skyscraper8.Atsc.A324
}
break;
case 4: //Deliver the packet
context.OnIpDatagram(0x1fff, currentIpPacketBuffer.AsSpan().Slice(0, currentIpPacketBufferOffset).ToArray());
if (networkIdentifier == null)
{
networkIdentifier = new StltpNetworkIdentifier();
}
context.OnIpDatagram(networkIdentifier, currentIpPacketBuffer.AsSpan().Slice(0, currentIpPacketBufferOffset).ToArray());
stateMachineState = 1;
break;
default:
@ -125,6 +129,7 @@ namespace skyscraper8.Atsc.A324
processed = true;
}
private StltpNetworkIdentifier networkIdentifier;
private SkyscraperContext context;
public void SetContext(DateTime? currentTime, object skyscraperContext)
{

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb;
namespace skyscraper8.Dvb.DataBroadcasting
{
class DataBroadcastingException : DvbException
{
public DataBroadcastingException(string message) : base(message)
{
}
public DataBroadcastingException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -9,6 +9,8 @@ using log4net;
using skyscraper5.Ietf.Rfc768;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.IO;
using skyscraper8.Dvb.DataBroadcasting;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper5.Dvb.DataBroadcasting
{
@ -59,6 +61,8 @@ namespace skyscraper5.Dvb.DataBroadcasting
{
return;
}
EnsureVirtualNetworkIdentifier(sourcePid);
byte[] payload = ms.ReadBytes(length);
if (llcSnap)
{
@ -71,6 +75,7 @@ namespace skyscraper5.Dvb.DataBroadcasting
}
private bool announcedLlcTraffic;
private void HandleLlcSnap(int sourcePid, byte[] macAddress, byte[] payload)
{
@ -81,12 +86,28 @@ namespace skyscraper5.Dvb.DataBroadcasting
}
PhysicalAddress physicalAddress = new PhysicalAddress(macAddress);
EventHandler.OnLlcFrame((ushort)sourcePid, PhysicalAddress.None, physicalAddress, (ushort)payload.Length, payload);
EventHandler.OnLlcFrame(networkIdentifier, PhysicalAddress.None, physicalAddress, (ushort)payload.Length, payload);
}
private void HandleIpDatagram(int sourcePid, byte[] payload)
{
EventHandler.OnIpDatagram(sourcePid, payload);
EventHandler.OnIpDatagram(networkIdentifier, payload);
}
private PidNetworkIdentifier networkIdentifier;
private void EnsureVirtualNetworkIdentifier(int sourcePid)
{
if (networkIdentifier == null)
{
networkIdentifier = new PidNetworkIdentifier((ushort)sourcePid);
}
else
{
if (networkIdentifier.PID != sourcePid)
{
throw new DataBroadcastingException("Re-using the same MPE Decoder for multiple PIDs is not supported yet.");
}
}
}
}
}

View File

@ -5,15 +5,16 @@ using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Ietf.Rfc971;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper5.Dvb.DataBroadcasting
namespace skyscraper8.Dvb.DataBroadcasting
{
public interface IMultiprotocolEncapsulationEventHandler
{
void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet);
void OnIpDatagram(int sourcePid, byte[] payload);
void OnIpv4PacketArrival(VirtualNetworkIdentifier networkId, InternetHeader internetHeader, byte[] ipv4Packet);
void OnIpDatagram(VirtualNetworkIdentifier sourcePid, byte[] payload);
void OnLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
void OnLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
}

View File

@ -10,6 +10,7 @@ namespace skyscraper5.Dvb
{
class DvbException : Mpeg2Exception
{
public DvbException(string s, params object[] args)
: base(String.Format(s, args))
{

View File

@ -204,6 +204,7 @@ namespace skyscraper8.GS.GSE_BFBS
"A unknown frame type was encountered. Please share a sample of this stream.");
}
private MisNetworkIdentifier networkIdentifier;
private void HandleAssembledFrame(ushort protocolType, byte[] buffer, GseLabel label)
{
Context.UiJunction?.EnableUiFeature(SkyscraperUiFeature.GseAnalysis);
@ -222,7 +223,11 @@ namespace skyscraper8.GS.GSE_BFBS
//according to https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml it's private
return;
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e, buffer);
if (networkIdentifier == null)
{
networkIdentifier = new MisNetworkIdentifier(Context.GetMisId());
}
Context.IpOutput.OnIpDatagram(networkIdentifier, buffer);
return;
default:
throw new NotImplementedException(protocolType.ToString());

View File

@ -98,6 +98,7 @@ class GseHemReader : IMisHandler
}
}
private MisNetworkIdentifier networkIdentifier;
private void HandlePacket(GsePacket packet)
{
Context.UiJunction?.EnableUiFeature(SkyscraperUiFeature.GseAnalysis);
@ -107,7 +108,11 @@ class GseHemReader : IMisHandler
switch (packet.ProtocolType)
{
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e,packet.GseDataBytes);
if (networkIdentifier == null)
{
networkIdentifier = new MisNetworkIdentifier(Context.GetMisId());
}
Context.IpOutput.OnIpDatagram(networkIdentifier,packet.GseDataBytes);
return;
default:
logger.WarnFormat("This GSE-HEM stream contains traffic other than IP. IP is type 0x0800, but we got 0x{0:X4} here.", packet.ProtocolType);

View File

@ -150,12 +150,22 @@ public class GseWithRollingSyncByteReader : IMisHandler
throw new NotImplementedException();
}
private MisNetworkIdentifier networkIdentifier;
private void EnsureNetworkIdentifier()
{
if (networkIdentifier == null)
{
networkIdentifier = new MisNetworkIdentifier(Context.GetMisId());
}
}
private ulong aolSerial;
private void HandleProprietaryAolJunk(byte[] buffer, ushort protocolType)
{
if (buffer[0] == 0x45)
{
Context.IpOutput.OnIpDatagram(0x0118, buffer);
EnsureNetworkIdentifier();
Context.IpOutput.OnIpDatagram(networkIdentifier, buffer);
return;
}
/*aolSerial++;
@ -177,7 +187,8 @@ public class GseWithRollingSyncByteReader : IMisHandler
//according to https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml it's private
return;
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e, buffer);
EnsureNetworkIdentifier();
Context.IpOutput.OnIpDatagram(networkIdentifier, buffer);
return;
default:
if (warnedEthertypes == null)

View File

@ -109,6 +109,16 @@ internal class GseReader : IMisHandler
}
}
private MisNetworkIdentifier networkIdentifier;
private void EnsureNetworkIdentifier()
{
if (networkIdentifier == null)
{
networkIdentifier = new MisNetworkIdentifier(Context.GetMisId());
}
}
private bool[] warnedEthertypes;
private GseFragmentation[] fragmentations;
private void ProcessPacket(GsePacket child)
@ -123,7 +133,8 @@ internal class GseReader : IMisHandler
currentFragmentation.AddFragement(child);
if (currentFragmentation.Validate())
{
Context.IpOutput.OnIpDatagram(0x010e,currentFragmentation.GetGseDataBytes());
EnsureNetworkIdentifier();
Context.IpOutput.OnIpDatagram(networkIdentifier,currentFragmentation.GetGseDataBytes());
}
fragmentations[child.FragmentId.Value] = null;
@ -160,7 +171,8 @@ internal class GseReader : IMisHandler
switch (child.ProtocolType)
{
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e, child.GseDataBytes);
EnsureNetworkIdentifier();
Context.IpOutput.OnIpDatagram(networkIdentifier, child.GseDataBytes);
break;
default:
if (warnedEthertypes == null)

View File

@ -5,9 +5,9 @@ using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.src.InteractionChannel;
using skyscraper8.Dvb.DataBroadcasting;
using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GS

View File

@ -21,6 +21,7 @@ namespace skyscraper8.GS
private ILog logger;
private bool notified;
private MisNetworkIdentifier networkIdentifier;
public GsContextDto Context { get; set; }
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
@ -40,7 +41,11 @@ namespace skyscraper8.GS
foreach (byte[] packet in packets)
{
Context.IpOutput.OnIpDatagram(0x0118, packet);
if (networkIdentifier == null)
{
networkIdentifier = new MisNetworkIdentifier(Context.GetMisId());
}
Context.IpOutput.OnIpDatagram(networkIdentifier, packet);
}
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.GS
{
[VirtualNetworkId(3)]
internal class MisNetworkIdentifier : VirtualNetworkIdentifier
{
private readonly byte _getMisId;
public MisNetworkIdentifier(byte getMisId)
{
_getMisId = getMisId;
}
public override string GetCaptureFilenamePrefix()
{
return String.Format("mis{0}", _getMisId);
}
public override string GetHumanReadableName()
{
return String.Format("MIS {0}", _getMisId);
}
public override int GetIdentifier()
{
return _getMisId;
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using skyscraper5.Skyscraper.Plugins;
using skyscraper5.Skyscraper.Scraper;
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Ietf.Rfc4236_ULE
{
@ -33,17 +34,17 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
}
public void OnEthernetFrame(int pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents)
public void OnEthernetFrame(VirtualNetworkIdentifier pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents)
{
Score++;
}
public void OnLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
public void OnLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
{
Score++;
}
public void OnUleError(int pid, int errorNo)
public void OnUleError(VirtualNetworkIdentifier pid, int errorNo)
{
Score--;
}

View File

@ -4,12 +4,13 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Ietf.Rfc4236_ULE
{
internal interface UleEventHandler
{
void OnLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
void OnLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
/// <summary>
/// The UlePacketProcessor is supposed to call this whenever an Error occurs during deframing.
@ -20,6 +21,6 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
/// 1* for a CRC error.
/// 2* for an invalid adaptation field control.
/// </param>
void OnUleError(int pid, int errorNo);
void OnUleError(VirtualNetworkIdentifier pid, int errorNo);
}
}

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Ietf.Rfc4236_ULE
{
@ -22,10 +23,13 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
private MemoryStream reassemblyStream;
private long offset;
private PidNetworkIdentifier networkIdentifier;
public UlePacketProcessor(int pid, UleEventHandler eventHandler)
{
_pid = pid;
_eventHandler = eventHandler;
networkIdentifier = new PidNetworkIdentifier((ushort)pid);
}
public void PushPacket(TsPacket packet)
@ -34,7 +38,7 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
Span<byte> packetPayload = packet.GetPayload();
if (packetAdaptionField != null || packetPayload == null)
{
_eventHandler.OnUleError(_pid, 2);
_eventHandler.OnUleError(networkIdentifier, 2);
return;
}
if (packet.PayloadUnitStart)
@ -135,7 +139,7 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
bool crc = DvbCrc32.ValidateCrc(ms, 0, (int)ms.Length);
if (!crc)
{
_eventHandler.OnUleError(_pid, 1);
_eventHandler.OnUleError(networkIdentifier, 1);
return;
}
@ -202,7 +206,7 @@ namespace skyscraper8.Ietf.Rfc4236_ULE
PhysicalAddress source = new PhysicalAddress(ms.ReadBytes(6));
ushort etherType = ms.ReadUInt16BE();
byte[] contents = ms.ReadBytes(ms.GetAvailableBytes());
_eventHandler.OnLlcFrame((ushort)_pid, source, destination, etherType, contents);
_eventHandler.OnLlcFrame(networkIdentifier, source, destination, etherType, contents);
}
public void PacketLoss()

View File

@ -4,12 +4,13 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Skyscraper.Net
{
internal interface IpTrafficHandler : IDisposable
{
void HandleIpPacket(int pid, byte[] payload);
void HandleLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
void HandleIpPacket(VirtualNetworkIdentifier pid, byte[] payload);
void HandleLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents);
}
}

View File

@ -7,6 +7,7 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Skyscraper.Net
{
@ -20,12 +21,12 @@ namespace skyscraper8.Skyscraper.Net
}
public void HandleIpPacket(int pid, byte[] payload)
public void HandleIpPacket(VirtualNetworkIdentifier pid, byte[] payload)
{
}
public void HandleLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
public void HandleLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
{
}

View File

@ -9,6 +9,7 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper8.Skyscraper.Net.Pcap
{
@ -18,33 +19,33 @@ namespace skyscraper8.Skyscraper.Net.Pcap
internal class PcapIpTrafficHandler : IpTrafficHandler
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private PcapWriter[] pcapWritersIp;
private PcapWriter[] pcapWritersLlc;
private Dictionary<VirtualNetworkIdentifier,PcapWriter> pcapWritersIp;
private Dictionary<VirtualNetworkIdentifier,PcapWriter> pcapWritersLlc;
private DirectoryInfo outputDirectory;
public void HandleIpPacket(int pid, byte[] payload)
public void HandleIpPacket(VirtualNetworkIdentifier network, byte[] payload)
{
if (pcapWritersIp == null)
{
pcapWritersIp = new PcapWriter[0x2000];
pcapWritersIp = new Dictionary<VirtualNetworkIdentifier, PcapWriter>();
EnsureOutputdirExists();
}
if (pcapWritersIp[pid] == null)
if (!pcapWritersIp.ContainsKey(network))
{
string fname = String.Format("{0:X4},{1}.pcap", pid, DateTime.Now.Ticks);
string fname = String.Format("{0},{1}.pcap", network.GetCaptureFilenamePrefix(), DateTime.Now.Ticks);
if (outputDirectory != null)
{
fname = Path.Combine(outputDirectory.FullName, fname);
}
logger.InfoFormat("Opening file for writing: {0}", fname);
FileStream fs = File.OpenWrite(fname);
pcapWritersIp[pid] = new PcapWriter(fs, TcpdumpNetworkType.RawIp);
pcapWritersIp[network] = new PcapWriter(fs, TcpdumpNetworkType.RawIp);
}
pcapWritersIp[pid].WritePacket(payload);
pcapWritersIp[network].WritePacket(payload);
}
public void HandleLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType,
public void HandleLlcFrame(VirtualNetworkIdentifier network, PhysicalAddress source, PhysicalAddress destination, ushort etherType,
byte[] contents)
{
byte[] dstAddr = destination.GetAddressBytes();
@ -65,13 +66,13 @@ namespace skyscraper8.Skyscraper.Net.Pcap
if (pcapWritersLlc == null)
{
pcapWritersLlc = new PcapWriter[0x1fff];
pcapWritersLlc = new Dictionary<VirtualNetworkIdentifier, PcapWriter>();
EnsureOutputdirExists();
}
if (pcapWritersLlc[pid] == null)
if (pcapWritersLlc[network] == null)
{
string fname = String.Format("{0:X4},llc,{1}.pcap", pid, DateTime.Now.Ticks);
string fname = String.Format("{0:X4},llc,{1}.pcap", network, DateTime.Now.Ticks);
if (outputDirectory != null)
{
fname = Path.Combine(outputDirectory.FullName, fname);
@ -79,31 +80,10 @@ namespace skyscraper8.Skyscraper.Net.Pcap
logger.InfoFormat("Opening file for writing: {0}", fname);
FileStream fs = File.OpenWrite(fname);
pcapWritersLlc[pid] = new PcapWriter(fs, TcpdumpNetworkType.UserDefined);
pcapWritersLlc[network] = new PcapWriter(fs, TcpdumpNetworkType.UserDefined);
}
/*
byte[] ethernetFrame = new byte[contents.Length + 14];
Array.Copy(dstAddr, 0, ethernetFrame, 0, dstAddr.Length);
Array.Copy(srcAddr, 0, ethernetFrame, 6, srcAddr.Length);
byte[] etherTypeBytes = BitConverter.GetBytes(etherType);
if (BitConverter.IsLittleEndian)
{
ethernetFrame[12] = etherTypeBytes[1];
ethernetFrame[13] = etherTypeBytes[0];
}
else
{
ethernetFrame[12] = etherTypeBytes[0];
ethernetFrame[13] = etherTypeBytes[1];
}
Array.Copy(contents, 0, ethernetFrame, 14, contents.Length);
pcapWritersLlc[pid].WritePacket(ethernetFrame);*/
pcapWritersLlc[pid].WritePacket(contents);
pcapWritersLlc[network].WritePacket(contents);
}
@ -123,10 +103,17 @@ namespace skyscraper8.Skyscraper.Net.Pcap
{
if (pcapWritersIp != null)
{
for (int i = 0; i < pcapWritersIp.Length; i++)
foreach (KeyValuePair<VirtualNetworkIdentifier, PcapWriter> kvp in pcapWritersIp)
{
if (pcapWritersIp[i] != null)
pcapWritersIp[i].Dispose();
kvp.Value.Dispose();
}
}
if (pcapWritersLlc != null)
{
foreach (KeyValuePair<VirtualNetworkIdentifier, PcapWriter> kvp in pcapWritersLlc)
{
kvp.Value.Dispose();
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net
{
public class SkyscraperNetException : SkyscraperCoreException
{
public SkyscraperNetException()
{
}
public SkyscraperNetException(string message) : base(message)
{
}
public SkyscraperNetException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.VirtualNetworks
{
[VirtualNetworkId(4)]
internal class AtmAdaptationLayer5NetworkIdentifier : VirtualNetworkIdentifier
{
private VirtualNetworkIdentifier wrapped;
private int identifier;
public AtmAdaptationLayer5NetworkIdentifier(VirtualNetworkIdentifier wrapped)
{
this.wrapped = wrapped;
this.identifier = new Random().Next();
}
public override string GetCaptureFilenamePrefix()
{
return String.Format("AAL5,{0}", wrapped.GetCaptureFilenamePrefix());
}
public override string GetHumanReadableName()
{
return String.Format("AAL5 on {0}", wrapped.GetHumanReadableName());
}
public override int GetIdentifier()
{
return identifier;
}
private static Dictionary<VirtualNetworkIdentifier, AtmAdaptationLayer5NetworkIdentifier> wraps;
public static VirtualNetworkIdentifier GetWrap(VirtualNetworkIdentifier network)
{
if (wraps == null)
{
wraps = new Dictionary<VirtualNetworkIdentifier, AtmAdaptationLayer5NetworkIdentifier>();
}
if (wraps.ContainsKey(network))
{
return wraps[network];
}
else
{
AtmAdaptationLayer5NetworkIdentifier child = new AtmAdaptationLayer5NetworkIdentifier(network);
wraps.Add(network, child);
return child;
}
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.VirtualNetworks
{
/// <summary>
/// Use this identifier when a IP/Network packets are directly encapsulated into a PID, for example by MPE or ULE.
/// </summary>
[VirtualNetworkId(2)]
internal class PidNetworkIdentifier : VirtualNetworkIdentifier
{
public PidNetworkIdentifier(ushort pid)
{
this.PID = pid;
}
public override string GetCaptureFilenamePrefix()
{
string fname = String.Format("{0:X4}", PID);
return fname;
}
public override string GetHumanReadableName()
{
return String.Format("PID 0x{0:X4}", PID);
}
public override int GetIdentifier()
{
return PID;
}
public ushort PID { get; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.VirtualNetworks
{
public class VirtualNetworkException : SkyscraperNetException
{
public VirtualNetworkException()
{
}
public VirtualNetworkException(string message) : base(message)
{
}
public VirtualNetworkException(string message, Exception inner) : base(message, inner)
{
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.VirtualNetworks
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public sealed class VirtualNetworkIdAttribute : Attribute
{
public int NetworkTypeId { get; }
public VirtualNetworkIdAttribute(int NetworkTypeId)
{
this.NetworkTypeId = NetworkTypeId;
}
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.VirtualNetworks
{
public abstract class VirtualNetworkIdentifier
{
public abstract string GetCaptureFilenamePrefix();
public abstract string GetHumanReadableName();
/// <summary>
/// Get an network type dependant ID of the specific network. This can be for example a VLAN ID, or a PID.
/// </summary>
/// <returns>The type-dependant identifier of the network in question.</returns>
public abstract int GetIdentifier();
/// <summary>
/// Gets an identifier to identify a network type.
/// </summary>
/// <returns></returns>
/// <exception cref="VirtualNetworkException"></exception>
public int GetNetworkTypeId()
{
Type type = this.GetType();
object[] customAttributes = type.GetCustomAttributes(typeof(VirtualNetworkIdAttribute), false);
if (customAttributes == null)
throw new VirtualNetworkException("Could not get the virtual network id attributes.");
if (customAttributes.Length == 0)
throw new VirtualNetworkException("The virtual network id attribute was empty.");
VirtualNetworkIdAttribute vlanAttribute = customAttributes[0] as VirtualNetworkIdAttribute;
if (vlanAttribute.NetworkTypeId == 0)
throw new VirtualNetworkException("A virtual Network Type ID may not be zero.");
return vlanAttribute.NetworkTypeId;
}
public override string ToString()
{
return GetHumanReadableName();
}
}
}

View File

@ -32,6 +32,7 @@ using skyscraper8.InteractionChannel.Model2;
using skyscraper8.Ses;
using skyscraper8.Skyscraper.Drawing;
using skyscraper8.Skyscraper.FrequencyListGenerator;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
using skyscraper8.Skyscraper.Scraper;
using skyscraper8.T2MI.Packets;
@ -43,7 +44,7 @@ namespace skyscraper5.Skyscraper.Scraper
void NotifySdtService(SdtService sdtService);
void NotifyPatProgram(int pmtPid, ushort programId);
void NotifyPmtProgram(ProgramMapping result, int pmtPid);
void NotifyMpeTraffic(IpTrafficInfo iti, byte[] ipv4PacketLength);
void NotifyMpeTraffic(VirtualNetworkIdentifier networkId, IpTrafficInfo iti, byte[] ipv4PacketLength);
void NotifyAit(AitApplication aitApplication);
void DsmCcModuleAdd(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion);
void DsmCcModuleProgress(int elementaryPid, ushort moduleInfoModuleId, byte moduleInfoModuleVersion, double moduleInfoDownloadProgress);

View File

@ -92,9 +92,11 @@ using skyscraper8.Atsc.A322;
using skyscraper8.Atsc.A330;
using skyscraper8.Atsc.A331;
using skyscraper8.Atsc.A331.Schema;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
using RntParser = skyscraper5.Dvb.TvAnytime.RntParser;
using skyscraper8.Dvb.DataBroadcasting;
namespace skyscraper5.Skyscraper.Scraper
{
@ -1744,11 +1746,18 @@ namespace skyscraper5.Skyscraper.Scraper
}
private IpTrafficHandler ipTrafficHandler;
public void OnIpDatagram(int pid, byte[] payload)
public void OnIpDatagram(VirtualNetworkIdentifier networkId, byte[] payload)
{
UiJunction?.EnableUiFeature(SkyscraperUiFeature.IpTrafficAnalysis);
TeiOnOffFilter.SetExempt(pid);
PidNetworkIdentifier pidNetworkIdentifier = networkId as PidNetworkIdentifier;
if (pidNetworkIdentifier != null)
{
TeiOnOffFilter.SetExempt(pidNetworkIdentifier.PID);
}
if (ipTrafficHandler == null)
{
StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
@ -1759,7 +1768,7 @@ namespace skyscraper5.Skyscraper.Scraper
return;
}
ipTrafficHandler?.HandleIpPacket(pid, payload);
ipTrafficHandler?.HandleIpPacket(networkId, payload);
int ipVersion = (payload[0] & 0xf0) >> 4;
if (ipVersion == 4)
@ -1778,7 +1787,7 @@ namespace skyscraper5.Skyscraper.Scraper
return;
byte[] ipv4Packet = new byte[payload.Length - ihl];
Array.Copy(payload, ihl, ipv4Packet, 0, payload.Length - ihl);
OnIpv4PacketArrival(internetHeader, ipv4Packet);
OnIpv4PacketArrival(networkId, internetHeader, ipv4Packet);
}
else if (ipVersion == 6)
{
@ -1805,7 +1814,7 @@ namespace skyscraper5.Skyscraper.Scraper
InternetHeader ipv6Header = new InternetHeader(trafficClass, flowLabel, payloadLength, nextHeader, hopLimit, sourceAddress, destinationAddress);
if (ipv6Stream.GetAvailableBytes() >= payloadLength)
{
OnIpv4PacketArrival(ipv6Header, ipv6Stream.ReadBytes(payloadLength));
OnIpv4PacketArrival(networkId, ipv6Header, ipv6Stream.ReadBytes(payloadLength));
}
return;
}
@ -1852,7 +1861,7 @@ namespace skyscraper5.Skyscraper.Scraper
return result;
}
public void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet)
public void OnIpv4PacketArrival(VirtualNetworkIdentifier networkId, InternetHeader internetHeader, byte[] ipv4Packet)
{
//There are as many use cases as there are internet applications in these.
//Not really required to decode all of them, if you ask me.
@ -1870,11 +1879,11 @@ namespace skyscraper5.Skyscraper.Scraper
{
LogEvent(SkyscraperContextEvent.LearnDns, String.Format("{0} = {1}", DnsCache.LastLearned.Value, DnsCache.LastLearned.Key));
}
UiJunction?.NotifyMpeTraffic(iti, ipv4Packet);
UiJunction?.NotifyMpeTraffic(networkId, iti, ipv4Packet);
if (trafficInfos.Add(iti))
{
LogEvent(SkyscraperContextEvent.IpTraffic, iti.ToString());
LogEvent(SkyscraperContextEvent.IpTraffic, String.Format("[{0}] {1}",networkId.GetHumanReadableName(), iti.ToString()));
}
if (mpePlugins == null)
@ -3015,20 +3024,28 @@ namespace skyscraper5.Skyscraper.Scraper
lastEventTimestamp = DateTime.Now;
}
public void OnEthernetFrame(int pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents)
public void OnEthernetFrame(VirtualNetworkIdentifier network, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents)
{
if (Array.TrueForAll(contents, x => x == 0))
return;
TeiOnOffFilter.SetExempt(pid);
PidNetworkIdentifier pidId = network as PidNetworkIdentifier;
if (pidId != null)
{
TeiOnOffFilter.SetExempt(pidId.PID);
}
if (etherType <= 1500)
{
OnLlcFrame((ushort)pid, source, destination, etherType, contents);
OnLlcFrame(network, source, destination, etherType, contents);
return;
}
switch (etherType)
{
case 0x0800:
OnIpDatagram(pid, contents);
//IPv4
OnIpDatagram(network, contents);
return;
case 0x22e3:
//This is related to G.9961, a PowerLine standard specified by ITU-T T-REC-G.9961
@ -3045,7 +3062,8 @@ namespace skyscraper5.Skyscraper.Scraper
//This is an IPX Frame. We don't need it.
return;
case 0x86dd:
OnIpDatagram(pid, contents);
//IPv6
OnIpDatagram(network, contents);
return;
case 0x88e1:
//This is related to FRITZ!Powerline.
@ -3070,13 +3088,14 @@ namespace skyscraper5.Skyscraper.Scraper
//Something proprietary. No idea.
return;
case 0xf67f:
//ATM Adaptation Layer 5
if (contents[20] == 0xaa && contents[21] == 0xaa && contents[22] == 0x03 && contents[23] == 0x00 && contents[24] == 0x00 && contents[25] == 0x00)
{
(contents[26], contents[27]) = (contents[27], contents[26]);
ushort newEtherType = BitConverter.ToUInt16(contents, 26);
byte[] newPacket = new byte[contents.Length - 28];
Array.Copy(contents, 28, newPacket, 0, newPacket.Length);
OnEthernetFrame(pid, destination, source, newEtherType, newPacket);
OnEthernetFrame(AtmAdaptationLayer5NetworkIdentifier.GetWrap(network), destination, source, newEtherType, newPacket);
}
return;
case 0x94ad:
@ -3102,12 +3121,12 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
public void OnUleError(int pid, int errorNo)
public void OnUleError(VirtualNetworkIdentifier pid, int errorNo)
{
throw new NotImplementedException();
}
public void OnLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
public void OnLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
{
UiJunction?.EnableUiFeature(SkyscraperUiFeature.LlcSnapTrafficAnalysis);
if (ipTrafficHandler == null)
@ -3172,7 +3191,7 @@ namespace skyscraper5.Skyscraper.Scraper
PhysicalAddress ethernetSrc = llcStream.ReadMacAddress();
ushort ethernetType = llcStream.ReadUInt16BE();
byte[] ethernetPayload = llcStream.ReadBytes(llcStream.GetAvailableBytes());
OnEthernetFrame(pid, ethernetDst, ethernetSrc, ethernetType, ethernetPayload);
OnEthernetFrame(AtmAdaptationLayer5NetworkIdentifier.GetWrap(pid), ethernetDst, ethernetSrc, ethernetType, ethernetPayload);
return;
}
else

View File

@ -10,6 +10,8 @@ using skyscraper5.Ietf.Rfc2460;
using skyscraper5.Ietf.Rfc971;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.Dvb.DataBroadcasting;
using skyscraper8.Skyscraper.Net.VirtualNetworks;
namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
{
@ -36,12 +38,12 @@ namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
}
public void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet)
public void OnIpv4PacketArrival(VirtualNetworkIdentifier networkId, InternetHeader internetHeader, byte[] ipv4Packet)
{
Score++;
}
public void OnIpDatagram(int sourcePid, byte[] payload)
public void OnIpDatagram(VirtualNetworkIdentifier sourceNetwork, byte[] payload)
{
int ipVersion = (payload[0] & 0xf0) >> 4;
if (ipVersion == 4)
@ -66,7 +68,7 @@ namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
byte[] ipv4Packet = new byte[testLength];
Array.Copy(payload, ihl, ipv4Packet, 0, testLength);
OnIpv4PacketArrival(internetHeader, ipv4Packet);
OnIpv4PacketArrival(sourceNetwork, internetHeader, ipv4Packet);
}
else if (ipVersion == 6)
{
@ -87,7 +89,7 @@ namespace skyscraper5.Skyscraper.Scraper.StreamAutodetection.Contestants
}
}
public void OnLlcFrame(ushort pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
public void OnLlcFrame(VirtualNetworkIdentifier pid, PhysicalAddress source, PhysicalAddress destination, ushort etherType, byte[] contents)
{
Score++;
}