diff --git a/skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs b/skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs index 5418d86..3ff6b71 100644 --- a/skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs +++ b/skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs @@ -20,12 +20,12 @@ namespace skyscraper8.Ietf.Rfc4236_ULE public override void Dispose() { - throw new NotImplementedException(); + } public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext) { - throw new NotImplementedException(); + skyscraperContext.DvbContext.RegisterPacketProcessor(pid, new UlePacketProcessor(pid, skyscraperContext)); } public override void Introduce(ProgramContext programContext) diff --git a/skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs b/skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs index b2a8883..e7d3aea 100644 --- a/skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs +++ b/skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs @@ -1,16 +1,19 @@ -using System; +using log4net; +using skyscraper5.Mpeg2; +using skyscraper5.Skyscraper.IO; +using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; -using skyscraper5.Mpeg2; -using skyscraper5.Skyscraper.IO; namespace skyscraper8.Ietf.Rfc4236_ULE { internal class UlePacketProcessor : ITsPacketProcessor, IPayloadUnitDecoder { + private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); + private readonly int _pid; private readonly UleEventHandler _eventHandler; @@ -150,14 +153,46 @@ namespace skyscraper8.Ietf.Rfc4236_ULE switch (typeField) { + case 0: + OnTestSndu(pdu); + break; case 1: OnBridgedFrame(pdu); break; + case 0x0100: + OnExtensionPadding(pdu); + break; + case 0x0800: + OnIpv4Payload(pdu); + break; + case 0x86dd: + OnIpv6Payload(pdu); + break; default: throw new NotImplementedException(String.Format("ULE Type 0x{0:X4}", typeField)); } } + private void OnIpv6Payload(byte[] pdu) + { + logger.Fatal("IPv6 Payload not yet implemented!"); + } + + private void OnIpv4Payload(byte[] pdu) + { + logger.Fatal("IPv4 Payload not yet implemented!"); + } + + private void OnExtensionPadding(byte[] pdu) + { + logger.Fatal("Extension Padding not yet implemented."); + } + + private void OnTestSndu(byte[] pdu) + { + logger.Fatal("Test SNDU not yet implemented!"); + } + private void OnBridgedFrame(byte[] pdu) { MemoryStream ms = new MemoryStream(pdu, false); diff --git a/skyscraper8/Ietf/Rfc971_IPv4/InternetHeader.cs b/skyscraper8/Ietf/Rfc971_IPv4/InternetHeader.cs index 77a64d8..9c05e04 100644 --- a/skyscraper8/Ietf/Rfc971_IPv4/InternetHeader.cs +++ b/skyscraper8/Ietf/Rfc971_IPv4/InternetHeader.cs @@ -1,5 +1,6 @@ using System.IO; using System.Net; +using System.Net.Sockets; using skyscraper5.Skyscraper.IO; namespace skyscraper5.Ietf.Rfc971 @@ -50,6 +51,24 @@ namespace skyscraper5.Ietf.Rfc971 CalculateChecksum(ipv4Header, IHL); } + public InternetHeader(int trafficClass, int flowLabel, ushort payloadLength, byte nextHeader, byte hopLimit, IPAddress sourceAddress, IPAddress destinationAddress) + { + DestinationAddress = destinationAddress; + SourceAddress = sourceAddress; + Protocol = nextHeader; + TimeToLive = hopLimit; + TotalLength = (ushort)(payloadLength + 40); + + if (DestinationAddress.AddressFamily == AddressFamily.InterNetworkV6) + Version = 6; + else if (DestinationAddress.AddressFamily == AddressFamily.InterNetwork) + Version = 4; + else + throw new NotSupportedException(DestinationAddress.AddressFamily.ToString()); + + ChecksumValid = true; + } + public int HeaderLength { get; private set; } private void CalculateChecksum(byte[] buffer, int ihl) diff --git a/skyscraper8/Skyscraper/Net/IpTrafficInfo.cs b/skyscraper8/Skyscraper/Net/IpTrafficInfo.cs index 9a47231..319846b 100644 --- a/skyscraper8/Skyscraper/Net/IpTrafficInfo.cs +++ b/skyscraper8/Skyscraper/Net/IpTrafficInfo.cs @@ -20,6 +20,15 @@ namespace skyscraper5.Skyscraper.Net return child; } + internal static IpTrafficInfo FromIPAddresses(IPAddress source, IPAddress destination, byte protocol) + { + IpTrafficInfo child = new IpTrafficInfo(); + child.Source = source; + child.Target = destination; + child.Protocol = protocol; + return child; + } + public IPAddress Source { get; set; } public IPAddress Target { get; set; } @@ -56,6 +65,7 @@ namespace skyscraper5.Skyscraper.Net case 41: return "IPv6!"; case 47: return "GRE!"; case 50: return "ESP"; + case 58: return "ICMPv6"; case 83: return "VINES"; case 88: return "EIGRP"; case 89: return "OSPF"; diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs index 9631f33..960cdf0 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs @@ -72,6 +72,7 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Text; +using skyscraper8.Ietf.Rfc4236_ULE; using skyscraper8.Skyscraper.Scraper.Storage; using Tsubasa.IO; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; @@ -85,7 +86,7 @@ namespace skyscraper5.Skyscraper.Scraper UpdateNotificationEventHandler, DataCarouselEventHandler, RdsEventHandler, IScte35EventHandler, IAutodetectionEventHandler, IRstEventHandler, IRntEventHandler, IMultiprotocolEncapsulationEventHandler, ObjectCarouselEventHandler, T2MIEventHandler, IDisposable, IFrameGrabberEventHandler, IntEventHandler, IRctEventHandler, IGsEventHandler, ISkyscraperContext, IDocsisEventHandler, AbertisDecoderEventHandler, Id3Handler, - InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler + InteractionChannelHandler, SgtEventHandler, IDvbNipEventHandler, UleEventHandler { public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true; public const bool ALLOW_FFMPEG_FRAMEGRABBER = true; @@ -1665,7 +1666,25 @@ namespace skyscraper5.Skyscraper.Scraper } else if (ipVersion == 6) { - //throw new NotSupportedException("IPv6"); + MemoryStream ipv6Stream = new MemoryStream(payload, false); + byte byteA = ipv6Stream.ReadUInt8(); + byte byteB = ipv6Stream.ReadUInt8(); + + int trafficClass = (byteA & 0x0f) << 4; + trafficClass = ((byteB & 0xf0) >> 4); + + int flowLabel = (byteB & 0x0f) << 16; + flowLabel += ipv6Stream.ReadUInt16BE(); + + ushort payloadLength = ipv6Stream.ReadUInt16BE(); + byte nextHeader = ipv6Stream.ReadUInt8(); + byte hopLimit = ipv6Stream.ReadUInt8(); + + IPAddress sourceAddress = new IPAddress(ipv6Stream.ReadBytes(16)); + IPAddress destinationAddress = new IPAddress(ipv6Stream.ReadBytes(16)); + InternetHeader ipv6Header = new InternetHeader(trafficClass, flowLabel, payloadLength, nextHeader, hopLimit, sourceAddress, destinationAddress); + OnIpv4PacketArrival(ipv6Header, ipv6Stream.ReadBytes(payloadLength)); + return; } else { @@ -1703,6 +1722,7 @@ namespace skyscraper5.Skyscraper.Scraper trafficInfo.TargetName = DnsCache.GetDnsName(trafficInfo.Target); return result; } + public void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet) { //There are as many use cases as there are internet applications in these. @@ -2686,5 +2706,126 @@ namespace skyscraper5.Skyscraper.Scraper { lastEventTimestamp = DateTime.Now; } + + public void OnEthernetFrame(int pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents) + { + if (etherType <= 1500) + { + OnLlcFrame(etherType, contents); + return; + } + switch (etherType) + { + case 0x0800: + OnIpDatagram(pid, contents); + return; + case 0x22e3: + //This is related to G.9961, a PowerLine standard specified by ITU-T T-REC-G.9961 + //I don't think we need this. + return; + case 0x0806: + //This is an ARP Frame. We don't need it. + return; + case 0x8137: + //This is an IPX Frame. We don't need it. + return; + case 0x86dd: + OnIpDatagram(pid, contents); + return; + case 0x88e1: + //This is related to FRITZ!Powerline. + //Probably very proprietary and undocumented, so I guess we'll discard it. + return; + case 0x890d: + //IEEE Std 802.11 - Fast Roaming Remote Request (802.11r) + //These seem to happen when one moves from one Wi-Fi Access Point to another. We probably don't need that one. + return; + case 0x8912: + //Related to mediaxtream, see https://de.wikipedia.org/wiki/Mediaxtream + //Probably not very interesting. + return; + case 0x9001: + //3Com(Bridge) XNS Sys Mgmt + //Can't say anything about these. I don't have any 3Com equipment. + return; + default: + throw new NotImplementedException(String.Format("EtherType: 0x{0:X4}", etherType)); + } + } + + public void OnUleError(int pid, int errorNo) + { + throw new NotImplementedException(); + } + + public void OnLlcFrame(ushort etherType, byte[] contents) + { + MemoryStream llcStream = new MemoryStream(contents, true); + byte dsap = llcStream.ReadUInt8(); + byte ssap = llcStream.ReadUInt8(); + if (dsap == 0x00 || ssap == 0x00) + { + //This is a NULL frame. It can be discarded either way. + return; + } + if (dsap == 0x42 || ssap == 0x42) + { + //This is a Spanning Tree Frame. We probably don't need it. + return; + } + if (dsap == 0xe0 || ssap == 0xe0) + { + //This is a Novell Netware Frame. We don't need to bother with it. + return; + } + + if (dsap == 0xaa || ssap == 0xaa) + { + byte snapType = llcStream.ReadUInt8(); + if (snapType == 0x03) + { + byte[] oui = llcStream.ReadBytes(3); + ushort snapProtocolId = llcStream.ReadUInt16BE(); + if (snapProtocolId == 0x809b) + { + //This is an AppleTalk Frame. We probably don't need it. + return; + } + else if (snapProtocolId == 0x8137) + { + //This is an IPX Frame. We probably don't need it. + return; + } + else if (snapProtocolId == 0x2000) + { + //This is from Cisco's Discovery Protocol (CDP). Probably not interesting. + return; + } + else + { + throw new NotImplementedException(String.Format("SNAP Frame, OUI = {0:X2}-{1:X2}-{2:X2}, Protocol ID = 0x{3:X4}", oui[0], oui[1], oui[2], snapProtocolId)); + } + } + else + { + throw new NotImplementedException(String.Format("LLC/SNAP Type 0x{0:X2}", snapType)); + } + } + + if (dsap == 0xff || ssap == 0xff) + { + ushort llcLength = llcStream.ReadUInt16BE(); + if (llcLength == etherType) + { + //TEST or XID PDU, likely unneeded. + return; + } + else + { + throw new NotImplementedException("LLC/SNAP (2)"); + } + } + throw new NotImplementedException("LLC/SNAP"); + } } } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs index 1169b89..feae0ab 100644 --- a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs +++ b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs @@ -1253,8 +1253,12 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory return dnsRecords.Count(x => x.RecordType.Item1 == 1); } + private Dictionary _ipStringToName; public string DnsIpToName(IPAddress source) { + if (_ipStringToName == null) + return null; + throw new NotImplementedException(); } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs index 9cee83b..d9ae595 100644 --- a/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs +++ b/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs @@ -50,9 +50,17 @@ namespace skyscraper8.Skyscraper.Scraper.Storage throw new NotImplementedException(); } + public class NullToken + { + + } + public object[] GetPluginConnector() { - throw new NotImplementedException(); + return new object[1] + { + new NullToken() + }; } public void Ping()