Exemplo n.º 1
0
        static async Task ReadPcapAsync(string file, Action <MessageDirection, RfpIdentifier, ReadOnlyMemory <byte>, DateTimeOffset> messageCallback, CancellationToken cancellationToken)
        {
            using (var s = File.OpenRead(file))
            {
                var pcapHeader = new byte[24];
                var success    = await FillBufferAsync(s, pcapHeader, cancellationToken).ConfigureAwait(false);

                if (!success)
                {
                    return;
                }
                if (BinaryPrimitives.ReadUInt32BigEndian(pcapHeader) != 0xa1b2c3d4 || pcapHeader[23] != 0x01)
                {
                    Console.WriteLine("Invalid pcap file");
                    return;
                }
                var packetHeader = new byte[16 + 54];
                while (true)
                {
                    success = await FillBufferAsync(s, packetHeader, cancellationToken).ConfigureAwait(false);

                    if (!success)
                    {
                        return;
                    }
                    var           direction = packetHeader[16] == 0x02 ? MessageDirection.ToOmm : MessageDirection.FromOmm;
                    RfpIdentifier rfp;
                    if (direction == MessageDirection.FromOmm)
                    {
                        rfp = new RfpIdentifier(packetHeader.AsMemory(16, 6));
                    }
                    else
                    {
                        rfp = new RfpIdentifier(packetHeader.AsMemory(16 + 6, 6));
                    }
                    var length = BinaryPrimitives.ReadUInt32BigEndian(packetHeader.AsSpan(12));
                    var data   = new byte[length - 54];
                    success = await FillBufferAsync(s, data, cancellationToken).ConfigureAwait(false);

                    if (!success)
                    {
                        return;
                    }
                    var seconds      = BinaryPrimitives.ReadUInt32BigEndian(packetHeader);
                    var milliseconds = BinaryPrimitives.ReadUInt32BigEndian(packetHeader.AsSpan(4)) / 1000;
                    messageCallback(direction, rfp, data, DateTimeOffset.FromUnixTimeSeconds(seconds).AddMilliseconds(milliseconds));
                }
            }
        }
Exemplo n.º 2
0
        private async Task InjectAsync(RfpIdentifier rfp, ushort handle, MediaToneMessage.Tone[] tones, CancellationToken cancellationToken)
        {
            var message = new MediaToneMessage(handle, MediaDirection.TxRx, 0, Array.Empty <MediaToneMessage.Tone>());
            var data    = new byte[message.Length];

            message.Serialize(data);
            cancellationToken.ThrowIfCancellationRequested();
            await WriteAsync(MessageDirection.ToRfp, 0, rfp, data, cancellationToken);

            message = new MediaToneMessage(handle, MediaDirection.TxRx, 0, tones);
            data    = new byte[message.Length];
            message.Serialize(data);
            cancellationToken.ThrowIfCancellationRequested();
            await Task.Delay(1000, cancellationToken);

            await WriteAsync(MessageDirection.ToRfp, 0, rfp, data, cancellationToken);
        }
Exemplo n.º 3
0
        public async Task SubscribeAsync(ICollection <string> rfps, CancellationToken cancellationToken)
        {
            var filter = "0102 0000 0000 0000";
            var mask   = "ffff 0000 0000 0001";

            foreach (var rfp in rfps)
            {
                await AddHandlerAsync(0, rfp, "ffffffffffff", filter, mask, cancellationToken);
            }

            await FinishHandshakeAsync(cancellationToken);

            var setBusy = HexEncoding.HexToByte("0102000402040001");

            foreach (var rfp in rfps)
            {
                var rfpIdentifier = new RfpIdentifier(HexEncoding.HexToByte(rfp));
                await WriteAsync(MessageDirection.ToRfp, 0, rfpIdentifier, setBusy, cancellationToken);
            }
        }
Exemplo n.º 4
0
 private bool ShouldHandle(RfpIdentifier identifier, ReadOnlyMemory <byte> data)
 {
     if (!identifier.Matches(Mac, MacMask.Span))
     {
         return(false);
     }
     if (Filter.Length > data.Length)
     {
         return(false);
     }
     for (int i = 0; i < Filter.Length; i++)
     {
         var masked = data.Span[i] & FilterMask.Span[i];
         if (masked != Filter.Span[i])
         {
             return(false);
         }
     }
     return(true);
 }
Exemplo n.º 5
0
        public Subscription(ClientConnection client, CancellationTokenSource cancellationTokenSource, byte priority, Memory <byte> mac, ReadOnlyMemory <byte> macMask, Memory <byte> filter, ReadOnlyMemory <byte> filterMask, bool handle)
        {
            if (mac.Length != RfpIdentifier.Length)
            {
                throw new Exception("invalid mac length");
            }
            if (macMask.Length != RfpIdentifier.Length)
            {
                throw new Exception("invalid mac mask length");
            }
            if (filter.Length != filterMask.Length)
            {
                throw new Exception("filter and filter mask length must match");
            }
            _cts = cancellationTokenSource;

            Client   = client;
            Priority = priority;

            var masked = mac.Span;

            for (int i = 0; i < masked.Length; i++)
            {
                masked[i] &= macMask.Span[i];
            }
            Mac     = new RfpIdentifier(mac);
            MacMask = macMask;

            masked = filter.Span;
            for (int i = 0; i < masked.Length; i++)
            {
                masked[i] &= filterMask.Span[i];
            }
            Filter        = filter;
            FilterMask    = filterMask;
            HandleMessage = handle;
        }
Exemplo n.º 6
0
            protected override async Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
            {
                if (_omm && direction == MessageDirection.ToOmm)
                {
                    await WriteAsync(direction, messageId, rfp, data, cancellationToken).ConfigureAwait(false);

                    return;
                }

                await WriteAsync(direction, messageId, rfp, ReadOnlyMemory <byte> .Empty, cancellationToken);
                await WriteAsync(_omm?MessageDirection.ToOmm : MessageDirection.ToRfp, 0, rfp, _ping, cancellationToken);
            }
Exemplo n.º 7
0
        protected override void WritePacketHeader(byte[] header, MessageDirection direction, uint messageId, RfpIdentifier rfp, ReadOnlyMemory <byte> data)
        {
            var span = header.AsSpan();

            rfp.CopyTo(header);
            rfp.CopyTo(span.Slice(6));
            if (direction == MessageDirection.FromOmm)
            {
                span[6] = 0x02;
            }
            else
            {
                span[0] = 0x02;
            }
            span[12] = 0x08;

            span    = span.Slice(14);
            span[0] = 0x45;                                                                            //version + IHL
            span[1] = 0x10;                                                                            //tos
            BinaryPrimitives.WriteUInt16BigEndian(span.Slice(2), (ushort)(span.Length + data.Length)); //total length
            BinaryPrimitives.WriteUInt16BigEndian(span.Slice(4), (ushort)messageId);                   //identification
            BinaryPrimitives.WriteUInt16BigEndian(span.Slice(6), 0x4000);                              // flags
            span[8] = 0xff;                                                                            //ttl
            span[9] = 6;                                                                               //protocol
            if (direction == MessageDirection.ToOmm)
            {
                rfp.CopyTo(span.Slice(10)); //source address
                span[12] = 127;
                span[16] = 127;             //destination address
                span[17] = 0;
                span[18] = 0;
                span[19] = 1;
            }
            else
            {
                rfp.CopyTo(span.Slice(14)); //destination address
                span[16] = 127;
                span[12] = 127;             //source address
                span[13] = 0;
                span[14] = 0;
                span[15] = 1;
            }
            span = span.Slice(20);
            int seq;
            int ack;

            if (direction == MessageDirection.ToOmm)
            {
                seq = _rfpSequenceNumbers.AddOrUpdate(rfp, x => data.Length, (x, i) => i + data.Length);
                ack = _ommSequenceNumbers.GetOrAdd(rfp, 1);
                BinaryPrimitives.WriteUInt16BigEndian(span, 54321);          //source port
                BinaryPrimitives.WriteUInt16BigEndian(span.Slice(2), 16321); //destination port
            }
            else
            {
                seq = _ommSequenceNumbers.AddOrUpdate(rfp, x => data.Length, (x, i) => i + data.Length);
                ack = _rfpSequenceNumbers.GetOrAdd(rfp, 1);
                BinaryPrimitives.WriteUInt16BigEndian(span, 16321);          //source port
                BinaryPrimitives.WriteUInt16BigEndian(span.Slice(2), 54321); //destination port
            }
            BinaryPrimitives.WriteInt32BigEndian(span.Slice(4), seq - data.Length);
            BinaryPrimitives.WriteInt32BigEndian(span.Slice(8), ack);
            span[12] = 0x50;        //data offset
            span[13] = 0b0001_0000; //flags
            span[14] = 0xff;        //window size
            span[15] = 0xff;
        }
Exemplo n.º 8
0
 protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
 {
     return(Task.CompletedTask);
 }
Exemplo n.º 9
0
 protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
 {
     try
     {
         var ies = data.Slice(14);
         while (!ies.IsEmpty)
         {
             var current = ies.Span[0];
             if (current > SignalType)
             {
                 break;
             }
             if (current >= 128)
             {
                 //fixed length
                 if (current >= 224)
                 {
                     if (ies.Length < 2)
                     {
                         break;
                     }
                     if (current == SignalType)
                     {
                         ies.Span[1] = 0x41;
                         Console.WriteLine("patched alerting pattern");
                     }
                     ies = ies.Slice(2);
                 }
                 else
                 {
                     ies = ies.Slice(1);
                 }
             }
             else
             {
                 if (ies.Length < 2)
                 {
                     break;
                 }
                 var length = ies.Span[1];
                 ies = ies.Slice(2);
                 if (current == (byte)NwkVariableLengthElementType.PortableIdentity)
                 {
                     //portable identity
                     var ie = new NwkIePortableIdentity(ies);
                     if (ie.IdentityType == NwkIePortableIdentity.PortableIdentityType.IPUI)
                     {
                         if (ie.Ipui.Put == NwkIePortableIdentity.IPUITypeCoding.O && ies.Length >= 5)
                         {
                             var span = ies.Slice(3).Span;
                             var emc  = (ushort)((span[0] & 0xf) << 12 | (span[1] << 4) | (span[2] >> 4));
                             if (!EMCs.Contains(emc))
                             {
                                 break;
                             }
                         }
                     }
                 }
                 if (ies.Length < length)
                 {
                     break;
                 }
                 ies = ies.Slice(length);
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex);
     }
     return(WriteAsync(direction, messageId, rfp, data, cancellationToken));
 }
Exemplo n.º 10
0
 public RfpConnectionTracker(RfpIdentifier rfp, MacConnectionTracker tracker)
 {
     _tracker = tracker;
     Rfp      = rfp;
 }
Exemplo n.º 11
0
 public RfpConnectionTracker(RfpIdentifier rfp)
     : this(rfp, new MacConnectionTracker())
 {
 }
Exemplo n.º 12
0
 protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
 {
     try
     {
         var length = data.Span[15];
         if (length == 8)
         {
             var iedata = data.Slice(16);
             var ie     = new NwkIePortableIdentity(iedata);
             if (ie.IdentityType == NwkIePortableIdentity.PortableIdentityType.IPUI)
             {
                 var ipui = ie.Ipui;
                 if (ipui.Put == NwkIePortableIdentity.IPUITypeCoding.O)
                 {
                     if (direction == MessageDirection.FromOmm)
                     {
                         var emc = (ushort)(ipui.Number >> 20);
                         if (EMCs.Contains(emc))
                         {
                             Console.WriteLine(data.ToHex());
                             var span = iedata.Span;
                             span[2]  = (byte)(0x10 | (emc >> 12));
                             span[3]  = (byte)(0xff & (emc >> 4));
                             span[4]  = (byte)((0xf & emc) << 4);
                             span[4] |= (byte)(ipui.Number >> 16 & 0xf);
                             BinaryPrimitives.WriteUInt16BigEndian(span.Slice(5), (ushort)ipui.Number);
                             span[7] = 0x00;
                             Console.WriteLine($"shifted   {data.ToHex()}");
                         }
                     }
                     else
                     {
                         var emc = (ushort)(ipui.Number >> 28);
                         if (EMCs.Contains(emc))
                         {
                             Console.WriteLine(data.ToHex());
                             //00000080 b0100301 400fdf
                             var span = iedata.Span;
                             span[2] = 0x10;
                             span[3] = (byte)(emc >> 12);
                             BinaryPrimitives.WriteUInt32BigEndian(span.Slice(4), (uint)(ipui.Number >> 8));
                             Console.WriteLine($"unshifted {data.ToHex()}");
                         }
                     }
                 }
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine(ex);
         Console.WriteLine(data.ToHex());
     }
     return(WriteAsync(direction, messageId, rfp, data, cancellationToken));
 }
Exemplo n.º 13
0
 protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 14
0
        protected override async Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
        {
            var packetheaderlength = PacketHeaderSize;
            var packetData         = PreprocessData(data);
            var timestamp          = DateTimeOffset.UtcNow;
            var header             = new byte[16];

            BinaryPrimitives.WriteUInt32BigEndian(header, (uint)timestamp.ToUnixTimeSeconds());
            BinaryPrimitives.WriteUInt32BigEndian(header.AsSpan(4), (uint)timestamp.Millisecond * 1000);
            BinaryPrimitives.WriteUInt32BigEndian(header.AsSpan(8), (uint)(packetData.Length + packetheaderlength));
            BinaryPrimitives.WriteUInt32BigEndian(header.AsSpan(12), (uint)(packetData.Length + packetheaderlength));
            await _file.WriteAsync(header, cancellationToken).ConfigureAwait(false);

            header = new byte[packetheaderlength];
            WritePacketHeader(header, direction, messageId, rfp, packetData);

            await _file.WriteAsync(header, cancellationToken).ConfigureAwait(false);

            await _file.WriteAsync(packetData, cancellationToken).ConfigureAwait(false);
        }
Exemplo n.º 15
0
 protected abstract void WritePacketHeader(byte[] header, MessageDirection direction, uint messageId, RfpIdentifier rfp, ReadOnlyMemory <byte> data);
Exemplo n.º 16
0
        static async Task Main(string[] args)
        {
            string socketname = "client.sock";
            bool   showHelp   = false;
            string mac        = null;
            bool   omm        = false;
            var    options    = new OptionSet
            {
                { "s|socket=", "socket path", x => socketname = x },
                { "r|rfp=", "rfp MAC address", x => mac = x },
                { "o|omm", "generate traffic to omm", x => omm = x != null },
                { "h|help", "show help", x => showHelp = x != null },
            };

            try
            {
                if (options.Parse(args).Count > 0)
                {
                    showHelp = true;
                }
            }
            catch (OptionException ex)
            {
                Console.Error.Write("rfpproxytraffic: ");
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine("Try 'dotnet rfpproxytraffic.dll --help' for more information");
                return;
            }
            if (String.IsNullOrEmpty(mac))
            {
                showHelp = true;
            }
            if (showHelp)
            {
                options.WriteOptionDescriptions(Console.Error);
                return;
            }
            try
            {
                using (var cts = new CancellationTokenSource())
                    using (var client = new TrafficClient(omm, socketname))
                    {
                        Console.CancelKeyPress += (s, e) =>
                        {
                            e.Cancel = true;
                            cts.Cancel();
                            client.Stop();
                        };
                        client.Log += (s, e) =>
                        {
                            Console.Write(e.Direction == LogDirection.Read ? "< " : "> ");
                            Console.WriteLine(e.Message);
                        };
                        var rfp = new RfpIdentifier(HexEncoding.HexToByte(mac));
                        if (omm)
                        {
                            await client.AddHandlerAsync(0, mac, "ffffffffffff", "00030008deadbeefbabefefe", "ffffffffffffffffffffffff", cts.Token);
                        }
                        else
                        {
                            await client.AddHandlerAsync(0, mac, "ffffffffffff", "010e0018ac1417010f", "ffffffffffffffff0f", cts.Token);
                        }
                        await client.FinishHandshakeAsync(cts.Token);

                        if (omm)
                        {
                            await client.WriteAsync(MessageDirection.ToOmm, 0, rfp, HexEncoding.HexToByte("00030008deadbeefbabefefe"), cts.Token);
                        }
                        else
                        {
                            await client.WriteAsync(MessageDirection.ToRfp, 0, rfp, HexEncoding.HexToByte("010e000cac1417010f00000000000000"), cts.Token);
                        }
                        await client.RunAsync(cts.Token);
                    }
            }
            catch (OperationCanceledException)
            {
            }
            catch (SocketException ex) when(ex.SocketErrorCode == SocketError.OperationAborted)
            {
            }
        }
Exemplo n.º 17
0
 protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
 {
     Console.WriteLine("suppressed SYS_LED");
     return(WriteAsync(direction, messageId, rfp, Array.Empty <byte>(), cancellationToken));
 }
Exemplo n.º 18
0
        protected override Task OnMessageAsync(MessageDirection direction, uint messageId, RfpIdentifier rfp, Memory <byte> data, CancellationToken cancellationToken)
        {
            if (data.Length < 6)
            {
                return(Task.CompletedTask);
            }
            var hdl = BinaryPrimitives.ReadUInt16LittleEndian(data.Span.Slice(4));

            if (data.Span[1] == 2)
            {
                if (data.Span[0] == 0)
                {
                    //NACK
                    if (direction == MessageDirection.ToOmm)
                    {
                        //suppress
                        return(WriteAsync(direction, messageId, rfp, Memory <byte> .Empty, cancellationToken));
                    }
                }
                else
                {
                    //MEDIA_CLOSE
                    OnClose(hdl);
                }
            }
            else if (data.Span[1] == 9)
            {
                //MEDIA_DTMF
                return(OnDtmfAsync(rfp, hdl, data, cancellationToken));
            }
            return(Task.CompletedTask);
        }
Exemplo n.º 19
0
        protected override void WritePacketHeader(byte[] header, MessageDirection direction, uint messageId, RfpIdentifier rfp, ReadOnlyMemory <byte> data)
        {
            rfp.CopyTo(header);
            rfp.CopyTo(header.AsSpan(6));
            if (direction == MessageDirection.FromOmm)
            {
                header[6] = 0x02;
            }
            else
            {
                header[0] = 0x02;
            }
            header[12] = 0xa0;

            BinaryPrimitives.WriteUInt16BigEndian(header.AsSpan(14), (ushort)data.Length);
            header[16] = 0xba;
            header[17] = 0xbe;
        }
Exemplo n.º 20
0
            public void OnMessage(MessageDirection direction, RfpIdentifier rfp, ReadOnlyMemory <byte> data, DateTimeOffset timestamp)
            {
                if (data.IsEmpty)
                {
                    return;
                }
                AaMiDeMessage        message;
                string               prefix;
                MacConnectionTracker reassembler;

                if (direction == MessageDirection.FromOmm)
                {
                    reassembler = _ommTracker;
                    prefix      = "OMM:";
                }
                else
                {
                    reassembler = _rfpTracker;
                    prefix      = "RFP:";
                }
                try
                {
                    message = AaMiDeMessage.Create(data, reassembler.Get(rfp));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"{timestamp:yyyy/MM/dd HH:mm:ss.fff} {prefix}{rfp} Cannot parse {data.ToHex()}");
                    Console.WriteLine(ex);
                    return;
                }

                if (message is DnmMessage dnm)
                {
                    if (dnm.Payload is MacDisIndPayload || dnm.DnmType == DnmType.MacDisReq)
                    {
                        RfpConnectionTracker rfpTracker;
                        if (direction == MessageDirection.FromOmm)
                        {
                            rfpTracker = _rfpTracker.Get(rfp);
                        }
                        else
                        {
                            rfpTracker = _ommTracker.Get(rfp);
                        }
                        var nwk = rfpTracker.Get(dnm.MCEI);
                        nwk.Close();
                    }
                    else if (dnm.Payload is MacConIndPayload macConInd)
                    {
                        RfpConnectionTracker rfpTracker;
                        if (direction == MessageDirection.FromOmm)
                        {
                            rfpTracker = _rfpTracker.Get(rfp);
                        }
                        else
                        {
                            rfpTracker = _ommTracker.Get(rfp);
                        }
                        var nwk = rfpTracker.Get(dnm.MCEI);
                        nwk.Open(macConInd);
                    }
                }
                if (_unknown && !message.HasUnknown)
                {
                    return;
                }
                Console.Write($"{timestamp:yyyy/MM/dd HH:mm:ss.fff} {prefix}{rfp} ");
                message.Log(Console.Out);
                Console.WriteLine();
                if (_logRaw)
                {
                    Console.Write("\t");
                    int i    = 0;
                    var span = data.Span;
                    for (; i < span.Length - 4; i += 4)
                    {
                        Console.Write(span.Slice(i, 4).ToHex());
                        Console.Write(' ');
                    }
                    Console.WriteLine(span.Slice(i).ToHex());
                }
                return;
            }