Beispiel #1
0
            public void SendKeepAlive(Guid guid)
            {
                EthernetLayer ethernetLayer = new EthernetLayer
                {
                    Source      = ownHardwareAddress,
                    Destination = ifHardwareAddress,
                    EtherType   = EthernetType.None,
                };
                IpV4Layer ipV4Layer = new IpV4Layer
                {
                    Source             = RoutingTable.connParams[guid].remoteIp,
                    CurrentDestination = ifProtocolAddress,
                    Fragmentation      = IpV4Fragmentation.None,
                    HeaderChecksum     = null, // Will be filled automatically.
                    Identification     = ipID,
                    Options            = IpV4Options.None,
                    Protocol           = IpV4Protocol.Tcp,
                    Ttl           = 128,
                    TypeOfService = 0,
                };
                TcpLayer tcpLayer = new TcpLayer
                {
                    SourcePort           = RoutingTable.connParams[guid].remotePort,
                    DestinationPort      = RoutingTable.connParams[guid].localPort,
                    Checksum             = null, // Will be filled automatically.
                    SequenceNumber       = IpFunctions.SubM32(RoutingTable.connParams[guid].seq, 1),
                    AcknowledgmentNumber = RoutingTable.connParams[guid].ack,
                    ControlBits          = TcpControlBits.Acknowledgment,
                    Window        = RoutingTable.connParams[guid].GetWindow(),
                    UrgentPointer = 0,
                    Options       = TcpOptions.None,
                };
                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, tcpLayer);

                SendPacket(builder.Build(DateTime.Now));
            }
 public void UpdateExpectedSeq(Packet packet)
 {
     this.expectedSeq = IpFunctions.AddM32(this.expectedSeq, (uint)packet.Ethernet.IpV4.Tcp.PayloadLength, (uint)((packet.Ethernet.IpV4.Tcp.ControlBits & (TcpControlBits.Fin | TcpControlBits.Synchronize)) > 0 ? 1 : 0));
 }
            public static RoutingObject GetInterface(Packet packet)
            {
                RequestAccess();
                RoutingObject routingObject = new RoutingObject();

                if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Tcp)
                {
                    ConnId connId = new ConnId(packet.Ethernet.IpV4.Tcp.SourcePort, packet.Ethernet.IpV4.Destination, packet.Ethernet.IpV4.Tcp.DestinationPort, IpV4Protocol.Tcp);
                    Guid   guid;
                    if (guidList.TryGetValue(connId, out guid))
                    {
                        connStatus[guid].timeStamp = DateTime.Now;
                        routingObject.response     = 0;
                        routingObject.ifIndex      = routingTable[guid];
                        routingObject.guid         = guid;
                        if ((packet.Ethernet.IpV4.Tcp.ControlBits & TcpControlBits.Reset) > 0)
                        {
                            connStatus[guid].localEPFin  = true;
                            connStatus[guid].remoteEPFin = true;
                            routingObject.response       = -1;
                            lock (connParams[guid])
                            {
                                connParams[guid].socket.Close();
                            }
                        }
                        else if ((packet.Ethernet.IpV4.Tcp.ControlBits & TcpControlBits.Fin) > 0)
                        {
                            routingObject.response = -2;
                        }
                        if (!connStatus[guid].localEPFin && packet.Ethernet.IpV4.Tcp.SequenceNumber == connStatus[guid].expectedSeq)
                        {
                            connStatus[guid].UpdateExpectedSeq(packet);
                            if (connStatus[guid].state == 2)
                            {
                                connStatus[guid].state = 3;
                            }
                        }
                        else if (packet.Ethernet.IpV4.Tcp.SequenceNumber == IpFunctions.SubM32(connStatus[guid].expectedSeq, 1) &&
                                 (packet.Ethernet.IpV4.Tcp.ControlBits & (TcpControlBits.Fin | TcpControlBits.Synchronize)) == 0 &&
                                 (packet.Ethernet.IpV4.Tcp.PayloadLength == 0 || packet.Ethernet.IpV4.Tcp.PayloadLength == 1) &&
                                 !connStatus[guid].remoteEPFin)
                        {
                            routingObject.response = -3; // KeepAlive
                        }
                        else
                        {
                            routingObject.response = -1;
                        }
                    }
                    else
                    {
                        if ((packet.Ethernet.IpV4.Tcp.ControlBits & TcpControlBits.Synchronize) == TcpControlBits.Synchronize)
                        {
                            guid = Guid.NewGuid();
                            guidList.TryAdd(connId, guid);
                            int routingInterface = LoadBalancer.routingInterface;
                            routingTable.TryAdd(guid, routingInterface);
                            connParams.TryAdd(guid, new ConnParams());
                            connParams[guid].ack = packet.Ethernet.IpV4.Tcp.SequenceNumber;
                            connParams[guid].UpdateAck(1);
                            connParams[guid].localPort  = packet.Ethernet.IpV4.Tcp.SourcePort;
                            connParams[guid].remoteIp   = packet.Ethernet.IpV4.Destination;
                            connParams[guid].remotePort = packet.Ethernet.IpV4.Tcp.DestinationPort;
                            connStatus.TryAdd(guid, new ConnStatus());
                            connStatus[guid].timeStamp   = DateTime.Now;
                            connStatus[guid].expectedSeq = packet.Ethernet.IpV4.Tcp.SequenceNumber;
                            connStatus[guid].UpdateExpectedSeq(packet);
                            connStatus[guid].state = 1;
                            foreach (TcpOption tcpOption in packet.Ethernet.IpV4.Tcp.Options.OptionsCollection)
                            {
                                if (tcpOption.OptionType == TcpOptionType.WindowScale)
                                {
                                    connParams[guid].windowScale = ((TcpOptionWindowScale)tcpOption).ScaleFactorLog;
                                }
                            }
                            connParams[guid].windowSize = packet.Ethernet.IpV4.Tcp.Window;
                            connParams[guid].freeWindow = (int)((packet.Ethernet.IpV4.Tcp.Window << RoutingTable.connParams[guid].windowScale) - (RoutingTable.connParams[guid].seq - packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber));
                            connParams[guid].socket     = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                            try
                            {
                                connParams[guid].socket.Bind(new IPEndPoint(new System.Net.IPAddress(physicalWorkers[routingInterface].ifProtocolAddressByte), 0));
                                connParams[guid].socket.BeginConnect(new IPEndPoint(new IPAddress(packet.Ethernet.IpV4.Destination.ToString().Split('.').Select(byte.Parse).ToArray()), (int)packet.Ethernet.IpV4.Tcp.DestinationPort), new AsyncCallback(physicalWorkers[routingInterface].ConnectCallback), guid);
                            }
                            catch (Exception)
                            {
                                connStatus[guid].localEPFin  = true;
                                connStatus[guid].remoteEPFin = true;
                            }
                        }
                        routingObject.response = -1;
                    }
                }
                else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Udp)
                {
                    ConnId connId = new ConnId(packet.Ethernet.IpV4.Udp.SourcePort, packet.Ethernet.IpV4.Destination, packet.Ethernet.IpV4.Udp.DestinationPort, IpV4Protocol.Udp);
                    Guid   guid;
                    if (guidList.TryGetValue(connId, out guid))
                    {
                        connStatus[guid].timeStamp = DateTime.Now;
                        routingObject.ifIndex      = routingTable[guid];
                        routingObject.guid         = guid;
                    }
                    else
                    {
                        guid = Guid.NewGuid();
                        guidList.TryAdd(connId, guid);
                        int routingInterface = LoadBalancer.routingInterface;
                        routingTable.TryAdd(guid, routingInterface);
                        connStatus.TryAdd(guid, new ConnStatus());
                        connStatus[guid].timeStamp = DateTime.Now;
                        routingObject.ifIndex      = routingInterface;
                        routingObject.guid         = guid;
                    }
                }
                else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.InternetControlMessageProtocol)
                {
                    routingObject = new RoutingObject(0, LoadBalancer.routingInterface);
                }
                else
                {
                    routingObject = new RoutingObject(-1, 0);
                }
                ReleaseAccess();
                return(routingObject);
            }
Beispiel #4
0
            public void IpV4Handler(Packet packet, IList <Packet> packetList = null)
            {
                if (packet.Ethernet.IpV4.Length > MTU)
                {
                    EthernetLayer ethernetLayer = new EthernetLayer
                    {
                        Source      = ownHardwareAddress,
                        Destination = packet.Ethernet.Source,
                        EtherType   = EthernetType.None,
                    };
                    IpV4Layer ipV4Layer = new IpV4Layer
                    {
                        Source             = packet.Ethernet.IpV4.Destination,
                        CurrentDestination = packet.Ethernet.IpV4.Source,
                        Fragmentation      = packet.Ethernet.IpV4.Fragmentation,
                        HeaderChecksum     = null, // Will be filled automatically.
                        Identification     = 123,
                        Options            = packet.Ethernet.IpV4.Options,
                        Protocol           = packet.Ethernet.IpV4.Protocol,
                        Ttl           = packet.Ethernet.IpV4.Ttl,
                        TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                    };
                    IcmpDestinationUnreachableLayer icmpLayer = new IcmpDestinationUnreachableLayer
                    {
                        Code = IcmpCodeDestinationUnreachable.FragmentationNeededAndDoNotFragmentSet,
                        NextHopMaximumTransmissionUnit = (ushort)MTU,
                    };

                    PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer);
                    SendPacket(builder.Build(DateTime.Now));
                    // TODO: fix warning spam
                    if (Global.Config.LoadBalancer.ShowTrayTipsWarnings)
                    {
                        Global.ShowTrayTip("Load Balancer", "IP packet larger than the MTU detected on " + Name + ".\n\nIP fragmentation is not supported.", ToolTipIcon.Warning);
                    }
                    Global.WriteLog("Load Balancer: IP packet larger than the MTU detected on " + Name);
                    return;
                }
                if (packet.Ethernet.IpV4.Ttl < 2)
                {
                    EthernetLayer ethernetLayer = new EthernetLayer
                    {
                        Source      = ownHardwareAddress,
                        Destination = packet.Ethernet.Source,
                        EtherType   = EthernetType.None,
                    };
                    IpV4Layer ipV4Layer = new IpV4Layer
                    {
                        Source             = ownProtocolAddress,
                        CurrentDestination = packet.Ethernet.IpV4.Source,
                        Fragmentation      = packet.Ethernet.IpV4.Fragmentation,
                        HeaderChecksum     = null, // Will be filled automatically.
                        Identification     = 123,
                        Options            = packet.Ethernet.IpV4.Options,
                        Protocol           = packet.Ethernet.IpV4.Protocol,
                        Ttl           = packet.Ethernet.IpV4.Ttl,
                        TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                    };
                    IcmpTimeExceededLayer icmpLayer = new IcmpTimeExceededLayer
                    {
                        Code = 0,
                    };

                    PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, icmpLayer, packet.Ethernet.IpV4.ExtractLayer(), packet.Ethernet.IpV4.Payload.ExtractLayer());
                    SendPacket(builder.Build(DateTime.Now));
                    return;
                }
                if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.InternetControlMessageProtocol)
                {
                    if (packet.Ethernet.IpV4.Destination == ownProtocolAddress)
                    {
                        if ((packet.Ethernet.IpV4.Icmp.MessageType == IcmpMessageType.Echo || packet.Ethernet.IpV4.Fragmentation.Offset > 0))
                        {
                            EthernetLayer ethernetLayer = new EthernetLayer
                            {
                                Source      = ownHardwareAddress,
                                Destination = packet.Ethernet.Source,
                                EtherType   = EthernetType.None,
                            };
                            IpV4Layer ipV4Layer = new IpV4Layer
                            {
                                Source             = packet.Ethernet.IpV4.Destination,
                                CurrentDestination = packet.Ethernet.IpV4.Source,
                                Fragmentation      = packet.Ethernet.IpV4.Fragmentation,
                                HeaderChecksum     = null, // Will be filled automatically.
                                Identification     = 123,
                                Options            = packet.Ethernet.IpV4.Options,
                                Protocol           = packet.Ethernet.IpV4.Protocol,
                                Ttl           = packet.Ethernet.IpV4.Ttl,
                                TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                            };
                            if (packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.DoNotFragment ||
                                packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.None && packet.Ethernet.IpV4.Fragmentation.Offset == 0)
                            {
                                byte[] icmpPacket = packet.Ethernet.IpV4.Payload.ToArray();
                                icmpPacket[0] = 0;
                                icmpPacket[2] = 0;
                                icmpPacket[3] = 0;
                                ushort checksum = IpFunctions.ComputeIpChecksum(icmpPacket);
                                icmpPacket[2] = (byte)(checksum >> 8);
                                icmpPacket[3] = (byte)(checksum & 0xff);
                                PayloadLayer payloadLayer = new PayloadLayer
                                {
                                    Data = new Datagram(icmpPacket),
                                };
                                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, payloadLayer);
                                SendPacket(builder.Build(DateTime.Now));
                            }
                            else if (packet.Ethernet.IpV4.Fragmentation.Offset == 0 && packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.MoreFragments)
                            {
                                byte[] icmpHeader = packet.Ethernet.IpV4.Payload.ToArray();
                                icmpHeader[0] = 0;
                                icmpHeader[2] = 0;
                                icmpHeader[3] = 0;
                                int icmpPacketLength = icmpHeader.Length;
                                for (int i = 1; i < packetList.Count; i++)
                                {
                                    icmpPacketLength += packetList[i].Ethernet.IpV4.Payload.ToArray().Length;
                                }
                                byte[] icmpPacket = new byte[icmpPacketLength];
                                Buffer.BlockCopy(icmpHeader, 0, icmpPacket, 0, icmpHeader.Length);
                                icmpPacketLength = icmpHeader.Length;
                                for (int i = 1; i < packetList.Count; i++)
                                {
                                    Buffer.BlockCopy(packetList[i].Ethernet.IpV4.Payload.ToArray(), 0, icmpPacket, icmpPacketLength, packetList[i].Ethernet.IpV4.Payload.ToArray().Length);
                                    icmpPacketLength += packetList[i].Ethernet.IpV4.Payload.ToArray().Length;
                                }
                                ushort checksum = IpFunctions.ComputeIpChecksum(icmpPacket);
                                icmpHeader[2] = (byte)(checksum >> 8);
                                icmpHeader[3] = (byte)(checksum & 0xff);
                                PayloadLayer payloadLayer = new PayloadLayer
                                {
                                    Data = new Datagram(icmpHeader),
                                };
                                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, payloadLayer);
                                SendPacket(builder.Build(DateTime.Now));
                            }
                            else
                            {
                                PayloadLayer payloadLayer = new PayloadLayer
                                {
                                    Data = new Datagram(packet.Ethernet.IpV4.Payload.ToArray()),
                                };
                                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, payloadLayer);
                                SendPacket(builder.Build(DateTime.Now));
                            }
                        }
                    }
                    else if (packet.Ethernet.IpV4.Source == ifProtocolAddress)
                    {
                        if ((packet.Ethernet.IpV4.Icmp.MessageType == IcmpMessageType.Echo || packet.Ethernet.IpV4.Fragmentation.Offset > 0))
                        {
                            {
                                tapRoutingObject = RoutingTable.GetInterface(packet);
                                if (tapRoutingObject.response == -1)
                                {
                                    return;
                                }
                                EthernetLayer ethernetLayer = new EthernetLayer
                                {
                                    Source      = physicalWorkers[tapRoutingObject.ifIndex].ifHardwareAddress,
                                    Destination = physicalWorkers[tapRoutingObject.ifIndex].gatewayHardwareAddress,
                                    EtherType   = EthernetType.None,
                                };
                                IpV4Layer ipV4Layer = new IpV4Layer
                                {
                                    Source             = physicalWorkers[tapRoutingObject.ifIndex].ifProtocolAddress,
                                    CurrentDestination = packet.Ethernet.IpV4.Destination,
                                    Fragmentation      = packet.Ethernet.IpV4.Fragmentation,
                                    HeaderChecksum     = null, // Will be filled automatically.
                                    Identification     = packet.Ethernet.IpV4.Identification,
                                    Options            = packet.Ethernet.IpV4.Options,
                                    Protocol           = packet.Ethernet.IpV4.Protocol,
                                    Ttl           = (byte)(packet.Ethernet.IpV4.Ttl - 1),
                                    TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                                };
                                PayloadLayer payloadLayer = new PayloadLayer
                                {
                                    Data = new Datagram(packet.Ethernet.IpV4.Payload.ToArray()),
                                };
                                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, payloadLayer);
                                physicalWorkers[tapRoutingObject.ifIndex].SendPacket(builder.Build(DateTime.Now));
                            }
                        }
                    }
                }
                else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Tcp)
                {
                    if (packet.Ethernet.IpV4.Source == ifProtocolAddress)
                    {
                        tapRoutingObject = RoutingTable.GetInterface(packet);
                        if (tapRoutingObject.response == -1)
                        {
                            return;
                        }
                        if (tapRoutingObject.response == -3)
                        {
                            lock (RoutingTable.connParams[tapRoutingObject.guid])
                                SendAck(tapRoutingObject.guid);
                            return;
                        }
                        lock (RoutingTable.connParams[tapRoutingObject.guid])
                        {
                            RoutingTable.connParams[tapRoutingObject.guid].freeWindow = (int)((packet.Ethernet.IpV4.Tcp.Window << RoutingTable.connParams[tapRoutingObject.guid].windowScale) - (RoutingTable.connParams[tapRoutingObject.guid].seq - packet.Ethernet.IpV4.Tcp.AcknowledgmentNumber));
                            if (RoutingTable.connParams[tapRoutingObject.guid].windowFull)
                            {
                                if (RoutingTable.connParams[tapRoutingObject.guid].freeWindow > RoutingTable.connParams[tapRoutingObject.guid].bytesReceived)
                                {
                                    SendData(tapRoutingObject.guid, RoutingTable.connParams[tapRoutingObject.guid].bytesReceived);
                                    RoutingTable.connParams[tapRoutingObject.guid].freeWindow -= RoutingTable.connParams[tapRoutingObject.guid].bytesReceived;
                                    RoutingTable.connParams[tapRoutingObject.guid].windowFull  = false;
                                    RoutingTable.connParams[tapRoutingObject.guid].UpdateSeq(RoutingTable.connParams[tapRoutingObject.guid].bytesReceived);
                                    try
                                    {
                                        RoutingTable.connParams[tapRoutingObject.guid].socket.BeginReceive(RoutingTable.connParams[tapRoutingObject.guid].receivingBuffer, 0, RoutingTable.connParams[tapRoutingObject.guid].receivingBuffer.Count(), 0, new AsyncCallback(physicalWorkers[tapRoutingObject.ifIndex].ReceiveCallback), tapRoutingObject.guid);
                                    }
                                    catch (Exception)
                                    {
                                        RoutingTable.RequestAccess();
                                        if (!RoutingTable.connStatus[tapRoutingObject.guid].remoteEPFin)
                                        {
                                            tapWorker.SendRst(tapRoutingObject.guid);
                                        }
                                        RoutingTable.connStatus[tapRoutingObject.guid].remoteEPFin = true;
                                        RoutingTable.connStatus[tapRoutingObject.guid].localEPFin  = true;
                                        RoutingTable.ReleaseAccess();
                                    }
                                }
                            }
                        }
                        if (packet.Ethernet.IpV4.Tcp.PayloadLength > 0 || tapRoutingObject.response == -2)
                        {
                            physicalWorkers[tapRoutingObject.ifIndex].SendData(packet, tapRoutingObject.guid);
                        }
                    }
                }
                else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Udp)
                {
                    if (packet.Ethernet.IpV4.Source == ifProtocolAddress)
                    {
                        tapRoutingObject = RoutingTable.GetInterface(packet);
                        if (tapRoutingObject.response == -1)
                        {
                            return;
                        }
                        EthernetLayer ethernetLayer = new EthernetLayer
                        {
                            Source      = physicalWorkers[tapRoutingObject.ifIndex].ifHardwareAddress,
                            Destination = physicalWorkers[tapRoutingObject.ifIndex].gatewayHardwareAddress,
                            EtherType   = packet.Ethernet.EtherType,
                        };

                        IpV4Layer ipV4Layer = new IpV4Layer
                        {
                            Source             = physicalWorkers[tapRoutingObject.ifIndex].ifProtocolAddress,
                            CurrentDestination = packet.Ethernet.IpV4.Destination,
                            Fragmentation      = packet.Ethernet.IpV4.Fragmentation,
                            HeaderChecksum     = null, // Will be filled automatically.
                            Identification     = packet.Ethernet.IpV4.Identification,
                            Options            = packet.Ethernet.IpV4.Options,
                            Protocol           = packet.Ethernet.IpV4.Protocol,
                            Ttl           = (byte)(packet.Ethernet.IpV4.Ttl - 1),
                            TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                        };
                        UdpLayer udpLayer = new UdpLayer
                        {
                            SourcePort             = packet.Ethernet.IpV4.Udp.SourcePort,
                            DestinationPort        = packet.Ethernet.IpV4.Udp.DestinationPort,
                            Checksum               = null, // Will be filled automatically.
                            CalculateChecksumValue = packet.Ethernet.IpV4.Udp.IsChecksumOptional,
                        };
                        PayloadLayer payloadLayer = new PayloadLayer
                        {
                            Data = new Datagram(packet.Ethernet.IpV4.Udp.Payload.ToArray()),
                        };
                        PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, udpLayer, payloadLayer);
                        physicalWorkers[tapRoutingObject.ifIndex].SendPacket(builder.Build(DateTime.Now));
                    }
                }
            }