using Cosmos.System.Network.IPv4; using System; using Cosmos.System.Network.IPv4.UDP.DNS; using Cosmos.System.Network.Config; using System.Collections.Generic; using Cosmos.HAL; /* * PROJECT: Aura Operating System Development * CONTENT: DHCP - DHCP Core * PROGRAMMER(S): Alexy DA CRUZ */ namespace Cosmos.System.Network.IPv4.UDP.DHCP { /// /// DHCPClient class. Used to manage the DHCP connection to a server. /// public class DHCPClient : UdpClient { // /// Is DHCP ascked check variable /// private bool asked = false; /// /// Get the IP address of the DHCP server /// /// public static Address DHCPServerAddress(NetworkDevice networkDevice) { return NetworkConfig.Get(networkDevice).DefaultGateway; } /// /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 53 exists. public DHCPClient() : base(68) { } /// /// Receive data /// /// timeout value, default 5000ms /// time value (-1 = timeout) /// Thrown on fatal error (contact support). private int Receive(int timeout = 5000) { int second = 0; int _deltaT = 0; while (rxBuffer.Count < 1) { if (second > (timeout / 1000)) { return -1; } if (_deltaT != RTC.Second) { second++; _deltaT = RTC.Second; } } var packet = new DHCPPacket(rxBuffer.Dequeue().RawData); if (packet.MessageType == 2) //Boot Reply { if (packet.RawData[284] == 0x02) //Offer packet received { return SendRequestPacket(packet.Client, packet.Server); } else if (packet.RawData[284] == 0x05 || packet.RawData[284] == 0x06) //ACK or NAK DHCP packet received { var ack = new DHCPAck(packet.RawData); if (asked) { Apply(ack, true); } else { Apply(ack); } } } return second; } /// /// Send a packet to the DHCP server to make the address available again /// public void SendReleasePacket() { foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { Address source = IPConfig.FindNetwork(DHCPServerAddress(networkDevice)); var dhcp_release = new DHCPRelease(source, DHCPServerAddress(networkDevice), networkDevice.MACAddress); OutgoingBuffer.AddPacket(dhcp_release); NetworkStack.Update(); NetworkStack.RemoveAllConfigIP(); IPConfig.Enable(networkDevice, new Address(0, 0, 0, 0), new Address(0, 0, 0, 0), new Address(0, 0, 0, 0)); } Close(); } /// /// Send a packet to find the DHCP server and tell that we want a new IP address /// /// time value (-1 = timeout) public int SendDiscoverPacket() { NetworkStack.RemoveAllConfigIP(); foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { IPConfig.Enable(networkDevice, new Address(0, 0, 0, 0), new Address(0, 0, 0, 0), new Address(0, 0, 0, 0)); var dhcp_discover = new DHCPDiscover(networkDevice.MACAddress); OutgoingBuffer.AddPacket(dhcp_discover); NetworkStack.Update(); asked = true; } return Receive(); } /// /// Send a request to apply the new IP configuration /// /// time value (-1 = timeout) private int SendRequestPacket(Address RequestedAddress, Address DHCPServerAddress) { foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { var dhcp_request = new DHCPRequest(networkDevice.MACAddress, RequestedAddress, DHCPServerAddress); OutgoingBuffer.AddPacket(dhcp_request); NetworkStack.Update(); } return Receive(); } /* * Method called to applied the differents options received in the DHCP packet ACK **/ /// /// Apply the new IP configuration received. /// /// DHCPOption class using the packetData from the received dhcp packet. /// Enable/Disable the displaying of messages about DHCP applying and conf. Disabled by default. /// private void Apply(DHCPAck packet, bool message = false) { NetworkStack.RemoveAllConfigIP(); //cf. Roadmap. (have to change this, because some network interfaces are not configured in dhcp mode) [have to be done in 0.5.x] foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { if (packet.Client.ToString() == null || packet.Client.ToString() == null || packet.Client.ToString() == null || packet.Client.ToString() == null) { throw new Exception("Parsing DHCP ACK Packet failed, can't apply network configuration."); } else { if (message) { Global.mDebugger.Send("[DHCP ACK][" + networkDevice.Name + "] Packet received, applying IP configuration..."); Global.mDebugger.Send(" IP Address : " + packet.Client.ToString()); Global.mDebugger.Send(" Subnet mask : " + packet.Subnet.ToString()); Global.mDebugger.Send(" Gateway : " + packet.Server.ToString()); Global.mDebugger.Send(" DNS server : " + packet.DNS.ToString()); } IPConfig.Enable(networkDevice, packet.Client, packet.Subnet, packet.Server); DNSConfig.Add(packet.DNS); if (message) { Global.mDebugger.Send("[DHCP CONFIG][" + networkDevice.Name + "] IP configuration applied."); asked = false; } } } Close(); } } }