Example #1
0
        public override ILayer ExtractLayer()
        {
            IcmpDestinationUnreachableLayer unreachableLayer = new IcmpDestinationUnreachableLayer();

            unreachableLayer.Code     = (IcmpCodeDestinationUnreachable)this.Code;
            unreachableLayer.Checksum = new ushort?(this.Checksum);
            unreachableLayer.NextHopMaximumTransmissionUnit = this.NextHopMaximumTransmissionUnit;
            return((ILayer)unreachableLayer);
        }
Example #2
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));
                    }

                }
            }
            //public Packet CreateDhcpPacket(int optionsSize, byte[] options, bool firstPacket, byte[] clientIp = null)
            //{
            //    EthernetLayer ethernetLayer = new EthernetLayer
            //    {
            //        Source = ifHardwareAddress,
            //        Destination = new MacAddress("FF:FF:FF:FF:FF:FF"),
            //        EtherType = EthernetType.None,
            //    };

            //    IpV4Layer ipV4Layer = new IpV4Layer
            //    {
            //        Source = new IpV4Address("0.0.0.0"),
            //        CurrentDestination = new IpV4Address("255.255.255.255"),
            //        Fragmentation = IpV4Fragmentation.None,
            //        HeaderChecksum = null, // Will be filled automatically.
            //        Identification = ipID,
            //        Options = IpV4Options.None,
            //        Protocol = null,
            //        Ttl = 128,
            //        TypeOfService = 0,
            //    };

            //    UdpLayer udpLayer = new UdpLayer
            //    {
            //        SourcePort = 68,
            //        DestinationPort = 67,
            //        Checksum = null, // Will be filled automatically.
            //        CalculateChecksumValue = true,
            //    };

            //    Dhcp dhcpLayer = new Dhcp(optionsSize);
            //    if (firstPacket)
            //        dhcpId = dhcpLayer.Id;
            //    else
            //        dhcpLayer.Id = dhcpId;
            //    if (clientIp != null)
            //        dhcpLayer.ClientIp = clientIp;
            //    dhcpLayer.ClientHardwareAddress = ifHardwareAddressByte;
            //    dhcpLayer.Options = options;


            //    PayloadLayer payloadLayer = new PayloadLayer
            //    {
            //        Data = new Datagram(dhcpLayer.toByteArray()),
            //    };

            //    PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, udpLayer, payloadLayer);
            //    return builder.Build(DateTime.Now);
            //}
            //public void SendArp()
            //{
            //    EthernetLayer ethernetLayer = new EthernetLayer
            //    {
            //        Source = ifHardwareAddress,
            //        Destination = new MacAddress("FF:FF:FF:FF:FF:FF"),
            //        EtherType = EthernetType.None,
            //    };

            //    ArpLayer arpLayer = new ArpLayer
            //    {
            //        ProtocolType = EthernetType.IpV4,
            //        Operation = ArpOperation.Request,
            //        SenderHardwareAddress = ifHardwareAddressByte.AsReadOnly(),
            //        SenderProtocolAddress = ownProtocolAddressByte.AsReadOnly(),
            //        TargetHardwareAddress = new byte[] { 0, 0, 0, 0, 0, 0 }.AsReadOnly(),
            //        TargetProtocolAddress = gatewayProtocolAddressByte.AsReadOnly(),
            //    };

            //    PacketBuilder builder = new PacketBuilder(ethernetLayer, arpLayer);
            //    SendPacket(builder.Build(DateTime.Now));
            //}
            //public void ReceiveIpAddress()
            //{
            //    int retries = 0;
            //    int timewait = 0;
            //    dhcpState = 0;
            //    arpState = 0;

            //    byte[] options;
            //    while (true)
            //    {
            //        if (dhcpState == 1 && retries > 1 ||
            //            dhcpState == 3 && retries > 1)
            //        {
            //            dhcpState = 6;
            //            offeredIp = BitConverter.GetBytes(ifProtocolAddress.ToValue() & ifProtocolMask.ToValue() + 1).Reverse().ToArray();
            //        }
            //        if (dhcpState == 0 || dhcpState == 1 && timewait > 10)
            //        {
            //            options = new byte[]
            //        { 
            //            53, 1, 1,
            //            61, 7, 1, 0x0A, 0x03, 0x03, 0x03, 0x03, (byte)dhcpClientId,
            //            12, 4, 78, 77, 76, 66,
            //            60, 8, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30,
            //            255,
            //            0, 0, 0,
            //        };
            //            SendPacket(CreateDhcpPacket(32, options, true));
            //            if (dhcpState == 0)
            //                retries = 0;
            //            else
            //                retries++;
            //            timewait = 0;
            //            dhcpState = 1;
            //        }
            //        else if (dhcpState == 2 || dhcpState == 3 && timewait > 10)
            //        {
            //            options = new byte[]
            //        { 
            //            53, 1, 3,
            //            61, 7, 1, 0x0A, 0x03, 0x03, 0x03, 0x03, (byte)dhcpClientId,
            //            12, 4, 78, 77, 76, 66,
            //            50, 4, offeredIp[0], offeredIp[1], offeredIp[2], offeredIp[3],
            //            54, 4, dhcpServer[0], dhcpServer[1], dhcpServer[2], dhcpServer[3],
            //            60, 8, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30,
            //            255,
            //            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            //        };
            //            SendPacket(CreateDhcpPacket(60, options, false));
            //            if (dhcpState == 2)
            //                retries = 0;
            //            else
            //                retries++;
            //            timewait = 0;
            //            dhcpState = 3;
            //        }
            //        else if (dhcpState == 4 && arpState == 1 && retries > 1)
            //        {
            //            if ((BitConverter.ToUInt32(offeredIp.Reverse().ToArray(), 0) + 1 & ifProtocolMask.ToValue()) !=
            //                (ifProtocolAddress.ToValue() & ifProtocolMask.ToValue()))
            //            {
            //                Global.WriteLog("DHCP: IP " + offeredIp.SequenceToString(".") + " is in a different network!");
            //                offeredIp = BitConverter.GetBytes(ifProtocolAddress.ToValue() & ifProtocolMask.ToValue() + 1).Reverse().ToArray();
            //                dhcpState = 6;
            //                arpState = 0;
            //                continue;
            //            }
            //            dhcpState = 5;
            //            arpState = 0;
            //            Global.WriteLog("DHCP: IP " + offeredIp.SequenceToString(".") + " OK!");
            //            dhcpClientId++;
            //            ownProtocolAddressByte = offeredIp;
            //            ownProtocolAddressString = ownProtocolAddressByte.SequenceToString(".");
            //            ownProtocolAddress = new IpV4Address(ownProtocolAddressString);
            //            SendArp();
            //            break;
            //        }
            //        else if (dhcpState == 4 && arpState == 0 || dhcpState == 4 && arpState == 1 && timewait > 10)
            //        {
            //            EthernetLayer ethernetLayer = new EthernetLayer
            //            {
            //                Source = ifHardwareAddress,
            //                Destination = new MacAddress("FF:FF:FF:FF:FF:FF"),
            //                EtherType = EthernetType.None,
            //            };

            //            ArpLayer arpLayer = new ArpLayer
            //            {
            //                ProtocolType = EthernetType.IpV4,
            //                Operation = ArpOperation.Request,
            //                SenderHardwareAddress = ifHardwareAddressByte.AsReadOnly(),
            //                SenderProtocolAddress = new byte[] { 0, 0, 0, 0 }.AsReadOnly(),
            //                TargetHardwareAddress = new byte[] { 0, 0, 0, 0, 0, 0 }.AsReadOnly(),
            //                TargetProtocolAddress = offeredIp.AsReadOnly(),
            //            };

            //            PacketBuilder builder = new PacketBuilder(ethernetLayer, arpLayer);
            //            SendPacket(builder.Build(DateTime.Now));
            //            if (arpState == 0)
            //                retries = 0;
            //            else
            //                retries++;
            //            timewait = 0;
            //            arpState = 1;
            //        }
            //        else if (dhcpState == 4 && arpState == 2)
            //        {
            //            Global.WriteLog("DHCP: IP " + offeredIp.SequenceToString(".") + " is already used!");
            //            options = new byte[]
            //        { 
            //            53, 1, 4,
            //            61, 7, 1, 0x0A, 0x03, 0x03, 0x03, 0x03, (byte)dhcpClientId,
            //            50, 4, offeredIp[0], offeredIp[1], offeredIp[2], offeredIp[3],
            //            54, 4, dhcpServer[0], dhcpServer[1], dhcpServer[2], dhcpServer[3],
            //            255,
            //            //0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
            //        };
            //            SendPacket(CreateDhcpPacket(25, options, false, offeredIp));
            //            arpState = 0;
            //            dhcpState = 0;
            //        }
            //        else if (dhcpState == 6 && arpState == 1 && retries > 1)
            //        {
            //            dhcpState = 5;
            //            arpState = 0;
            //            Global.WriteLog("IPAlloc: IP " + offeredIp.SequenceToString(".") + " OK!");
            //            dhcpClientId++;
            //            ownProtocolAddressByte = offeredIp;
            //            ownProtocolAddressString = ownProtocolAddressByte.SequenceToString(".");
            //            ownProtocolAddress = new IpV4Address(ownProtocolAddressString);
            //            SendArp();
            //            break;
            //        }
            //        else if (dhcpState == 6 && arpState == 0 || dhcpState == 6 && arpState == 1 && timewait > 10)
            //        {
            //            EthernetLayer ethernetLayer = new EthernetLayer
            //            {
            //                Source = ifHardwareAddress,
            //                Destination = new MacAddress("FF:FF:FF:FF:FF:FF"),
            //                EtherType = EthernetType.None,
            //            };

            //            ArpLayer arpLayer = new ArpLayer
            //            {
            //                ProtocolType = EthernetType.IpV4,
            //                Operation = ArpOperation.Request,
            //                SenderHardwareAddress = ifHardwareAddressByte.AsReadOnly(),
            //                SenderProtocolAddress = new byte[] { 0, 0, 0, 0 }.AsReadOnly(),
            //                TargetHardwareAddress = new byte[] { 0, 0, 0, 0, 0, 0 }.AsReadOnly(),
            //                TargetProtocolAddress = offeredIp.AsReadOnly(),
            //            };

            //            PacketBuilder builder = new PacketBuilder(ethernetLayer, arpLayer);
            //            SendPacket(builder.Build(DateTime.Now));
            //            if (arpState == 0)
            //                retries = 0;
            //            else
            //                retries++;
            //            timewait = 0;
            //            arpState = 1;
            //        }
            //        else if (dhcpState == 6 && arpState == 2)
            //        {
            //            if ((BitConverter.ToUInt32(offeredIp.Reverse().ToArray(), 0) + 1 & ifProtocolMask.ToValue()) !=
            //                (ifProtocolAddress.ToValue() & ifProtocolMask.ToValue()))
            //            {
            //                Global.WriteLog("IPAlloc: Couldn't allocate IP address!");
            //                break;
            //            }
            //            Global.WriteLog("IPAlloc: IP " + offeredIp.SequenceToString(".") + " is already used!");
            //            offeredIp = BitConverter.GetBytes((BitConverter.ToUInt32(offeredIp.Reverse().ToArray(), 0) + 1)).Reverse().ToArray();
            //            arpState = 0;
            //        }
            //        Thread.Sleep(100);
            //        timewait++;
            //    }
            //}

            public void ReceivePackets()
            {
                // Retrieve the device list from the local machine
                IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;

                // Find the NPF device of the interface
                PacketDevice selectedDevice = null;
                for (int i = 0; i != allDevices.Count; ++i)
                {
                    LivePacketDevice device = allDevices[i];
                    if (device.Name.ToUpper().Contains(Guid.ToString().ToUpper()))
                    {
                        selectedDevice = device;
                        break;
                    }
                }

                if (selectedDevice == null)
                {
                    Initialized.Set();
                    Global.ShowTrayTip("Load Balancer", "Interface " + Name + " not captured by WinPcap.", System.Windows.Forms.ToolTipIcon.Warning);
                    Global.WriteLog("Load Balancer: Interface " + Name + " not captured by WinPcap.");
                    return;
                }

                try
                {
                    using (communicator = selectedDevice.Open(65536, PacketDeviceOpenAttributes.MaximumResponsiveness, 1000))
                    {
                        Global.WriteLog("Load Balancer: Listening on " + Name + "...");
                        //communicator.SetFilter("(ether dst " + ifHardwareAddressString + " and (ip or arp)) or (ether dst FF:FF:FF:FF:FF:FF and arp)");
                        communicator.SetFilter("(ether dst " + ifHardwareAddressString + " and ip and (udp or icmp))");
                        Initialized.Set();
                        communicator.ReceivePackets(0, (packet) =>
                        {
                            if (!ThreadActive.IsSet)
                            {
                                communicator.Break();
                                return;
                            }
                            //if (ownProtocolAddressString == null)
                            //{
                            //    if (packet.Ethernet.IpV4.Udp.SourcePort == 67 && packet.Ethernet.IpV4.Udp.DestinationPort == 68 && (PublicVars.dhcpState == 1 || PublicVars.dhcpState == 3))
                            //    {
                            //        Dhcp dhcpReply = new Dhcp(packet.Ethernet.IpV4.Udp.Payload.ToArray());
                            //        if (PublicVars.dhcpId == dhcpReply.Id && dhcpReply.MessageType == 2)
                            //        {
                            //            if (dhcpReply.getOption((int)DhcpOptionCode.DhcpMsgType)[0] == 2)
                            //            {
                            //                PublicVars.offeredIp = dhcpReply.YourIp;
                            //                PublicVars.dhcpServer = dhcpReply.getOption((int)DhcpOptionCode.DhcpServerId);
                            //                PublicVars.dhcpState = 2;
                            //            }
                            //            else if (dhcpReply.getOption((int)DhcpOptionCode.DhcpMsgType)[0] == 5)
                            //            {
                            //                PublicVars.dhcpState = 4;
                            //            }
                            //            else if (dhcpReply.getOption((int)DhcpOptionCode.DhcpMsgType)[0] == 6)
                            //            {
                            //                PublicVars.offeredIp = null;
                            //                PublicVars.dhcpState = 0;
                            //                PublicVars.dhcpId = 0;
                            //            }
                            //        }
                            //    }
                            //    else if (packet.Ethernet.EtherType == EthernetType.Arp && PublicVars.arpState == 1)
                            //    {
                            //        if (packet.Ethernet.Arp.SenderProtocolAddress.SequenceEqual(PublicVars.offeredIp))
                            //            PublicVars.arpState = 2;
                            //    }
                            //}
                            //if (packet.Ethernet.EtherType == EthernetType.Arp)
                            //{
                            //    if (packet.Ethernet.Arp.TargetProtocolAddress.SequenceEqual(ownProtocolAddressByte) &&
                            //        packet.Ethernet.Arp.Operation == ArpOperation.Request)
                            //    {
                            //        EthernetLayer ethernetLayer = new EthernetLayer
                            //        {
                            //            Source = ifHardwareAddress,
                            //            Destination = packet.Ethernet.Source,
                            //            EtherType = EthernetType.None,
                            //        };

                            //        ArpLayer arpLayer = new ArpLayer
                            //        {
                            //            ProtocolType = EthernetType.IpV4,
                            //            Operation = ArpOperation.Reply,
                            //            SenderHardwareAddress = ifHardwareAddressByte.AsReadOnly(),
                            //            SenderProtocolAddress = packet.Ethernet.Arp.TargetProtocolAddress,
                            //            TargetHardwareAddress = packet.Ethernet.Arp.SenderHardwareAddress,
                            //            TargetProtocolAddress = packet.Ethernet.Arp.SenderProtocolAddress,
                            //        };

                            //        PacketBuilder builder = new PacketBuilder(ethernetLayer, arpLayer);
                            //        communicator.SendPacket(builder.Build(DateTime.Now));
                            //    }
                            //}
                            if (tapWorker.Initialized.IsSet)
                            {
                                if (packet.Ethernet.IpV4.Length > MTU) // only UDP and ICMP
                                {
                                    EthernetLayer ethernetLayer = new EthernetLayer
                                    {
                                        Source = ifHardwareAddress,
                                        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.Fragmentation.Options == IpV4FragmentationOptions.DoNotFragment ||
                                packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.None && packet.Ethernet.IpV4.Fragmentation.Offset == 0)
                                {
                                    if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.InternetControlMessageProtocol)
                                    {

                                        if (packet.Ethernet.IpV4.Destination == ifProtocolAddress)
                                            if ((packet.Ethernet.IpV4.Icmp.MessageType == IcmpMessageType.EchoReply || packet.Ethernet.IpV4.Fragmentation.Offset > 0))
                                            {
                                                EthernetLayer ethernetLayer = new EthernetLayer
                                                {
                                                    Source = tapWorker.ownHardwareAddress,
                                                    Destination = tapWorker.ifHardwareAddress,
                                                    EtherType = EthernetType.None,
                                                };
                                                IpV4Layer ipV4Layer = new IpV4Layer
                                                {
                                                    Source = packet.Ethernet.IpV4.Source,
                                                    CurrentDestination = tapWorker.ifProtocolAddress,
                                                    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 = packet.Ethernet.IpV4.Ttl,
                                                    TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                                                };
                                                PayloadLayer payloadLayer = new PayloadLayer
                                                {
                                                    Data = new Datagram(packet.Ethernet.IpV4.Payload.ToArray()),
                                                };
                                                PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, payloadLayer);
                                                tapWorker.SendPacket(builder.Build(DateTime.Now));
                                            }
                                    }
                                    //else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Tcp)
                                    //{
                                    //    if (packet.Ethernet.IpV4.Destination == ifProtocolAddress)
                                    //    {
                                    //        lock (RoutingTable.lockObj)
                                    //            routingObject = RoutingTable.TranslateBack(packet);
                                    //        if (routingObject.ifIndex == -1)
                                    //            return;
                                    //        EthernetLayer ethernetLayer = new EthernetLayer
                                    //        {
                                    //            Source = TapWorker.ownHardwareAddress,
                                    //            Destination = TapWorker.ifHardwareAddress,
                                    //            EtherType = packet.Ethernet.EtherType,
                                    //        };
                                    //        IpV4Layer ipV4Layer = new IpV4Layer
                                    //        {
                                    //            Source = packet.Ethernet.IpV4.Source,
                                    //            CurrentDestination = TapWorker.ifProtocolAddress,
                                    //            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 = packet.Ethernet.IpV4.Ttl,
                                    //            TypeOfService = packet.Ethernet.IpV4.TypeOfService,
                                    //        };
                                    //        TcpLayer tcpLayer = new TcpLayer
                                    //        {
                                    //            SourcePort = packet.Ethernet.IpV4.Tcp.SourcePort,
                                    //            DestinationPort = routingObject.localPort,
                                    //            Checksum = null, // Will be filled automatically.
                                    //            SequenceNumber = packet.Ethernet.IpV4.Tcp.SequenceNumber,
                                    //            AcknowledgmentNumber = routingObject.ack,
                                    //            ControlBits = packet.Ethernet.IpV4.Tcp.ControlBits,
                                    //            Window = packet.Ethernet.IpV4.Tcp.Window,
                                    //            UrgentPointer = packet.Ethernet.IpV4.Tcp.UrgentPointer,
                                    //            Options = packet.Ethernet.IpV4.Tcp.Options,
                                    //        };
                                    //        PayloadLayer payloadLayer = new PayloadLayer
                                    //        {
                                    //            Data = new Datagram(packet.Ethernet.IpV4.Tcp.Payload.ToArray()),
                                    //        };
                                    //        PacketBuilder builder = new PacketBuilder(ethernetLayer, ipV4Layer, tcpLayer, payloadLayer);
                                    //        MainThread.tapWorker.SendPacket(builder.Build(DateTime.Now));
                                    //    }
                                    //}
                                    else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Udp)
                                    {
                                        if (packet.Ethernet.IpV4.Destination == ifProtocolAddress)
                                        {
                                            phyRoutingObject = RoutingTable.IsUdpConn(packet);
                                            if (phyRoutingObject.ifIndex == -1)
                                                return;
                                            EthernetLayer ethernetLayer = new EthernetLayer
                                            {
                                                Source = tapWorker.ownHardwareAddress,
                                                Destination = tapWorker.ifHardwareAddress,
                                                EtherType = packet.Ethernet.EtherType,
                                            };
                                            IpV4Layer ipV4Layer = new IpV4Layer
                                            {
                                                Source = packet.Ethernet.IpV4.Source,
                                                CurrentDestination = tapWorker.ifProtocolAddress,
                                                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 = packet.Ethernet.IpV4.Ttl,
                                                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);
                                            tapWorker.SendPacket(builder.Build(DateTime.Now));
                                        }
                                    }
                                }
                                else if (packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.MoreFragments ||
                                    packet.Ethernet.IpV4.Fragmentation.Options == IpV4FragmentationOptions.None && packet.Ethernet.IpV4.Fragmentation.Offset > 0)
                                {
                                    // TODO: fix warning spam
                                    if (Global.Config.LoadBalancer.ShowTrayTipsWarnings)
                                        Global.ShowTrayTip("Load Balancer", "IP fragmentation detected on " + Name + ".\n\nIP fragmentation is not supported.", ToolTipIcon.Warning);
                                    Global.WriteLog("Load Balancer: IP fragmentation detected on " + Name);
                                    //fragments = fragBuffer.Add(packet);
                                    //if (fragments != null)
                                    //    for (int i = 0; i < fragments.Count; i++)
                                    //    {
                                    //        IpV4Handler(fragments[i], fragments);
                                    //    }
                                }
                            }
                        });
                    }
                }
                catch (Exception e)
                {
                    if (ThreadActive.IsSet)
                    {
                        ThreadActive.Reset();
                        Global.WriteLog("Load Balancer: " + Name + " has disconnected");
                        if (Global.Config.Gadget.Debug)
                            Global.WriteLog(e.ToString());
                        Global.ShowTrayTip("Load Balancer", Name + " has disconnected", System.Windows.Forms.ToolTipIcon.Warning);
                    }
                }
            }