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); }
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)); } } }