public IPAddress GetIPAddress(DhcpOption option) { byte[] data = this[option]; CheckSize(data, 4); return(DhcpMessage.ReadIPAddress(data, 0)); }
public ushort GetUInt16(DhcpOption option) { byte[] data = this[option]; CheckSize(data, 2); return(DhcpMessage.ReadUInt16(data, 0)); }
public uint GetUInt32(DhcpOption option) { byte[] data = this[option]; CheckSize(data, 4); return(DhcpMessage.ReadUInt32(data, 0)); }
private async void SendResponse(UdpClient client, DhcpMessage message) { if (message.Options.MessageType == DhcpMessageType.Offer || message.Options.MessageType == DhcpMessageType.Acknowledge) { message.Options.SetValue(DhcpOption.SubnetMask, _subnetMask); } else if (message.Options.MessageType != DhcpMessageType.NoAcknowledge) { throw new DhcpMessageException($"Cannot send '{message.Options.MessageType}' messages from a server.", message); } message.Options.SetValue(DhcpOption.ServerIdentifier, _localEndPoint.Address); try { byte[] messageBytes = message.GetBytes(); var remoteEndPoint = new IPEndPoint(message.ClientIPAddress.Equals(IPAddress.Any) ? IPAddress.Broadcast : message.ClientIPAddress, ReplyPort); await client.SendAsync(messageBytes, messageBytes.Length, remoteEndPoint).ConfigureAwait(false); OnResponseSent(message); } catch (SocketException ex) { OnSocketError(ex); } catch (ObjectDisposedException) { } }
internal DhcpMessage CreateMessage() { // [X] = handled here // [S] = handled by DhcpServer // Field DHCPOFFER DHCPACK DHCPNAK // ----- --------- ------- ------- // [X] 'op' BOOTREPLY BOOTREPLY BOOTREPLY // [X] 'htype' Copy Copy Copy // [X] 'hlen' Copy Copy Copy // [ ] 'hops' - - - // [X] 'xid' Copy Copy Copy // [ ] 'secs' - - - // [ ] 'ciaddr' - Copy - // [X] 'yiaddr' IP address offered IP address assigned - // [ ] 'siaddr' - - - // [X] 'flags' Copy Copy Copy // [X] 'giaddr' Copy Copy Copy // [X] 'chaddr' Copy Copy Copy // [ ] 'sname' Server name/options Server name/options - // [ ] 'file' Boot file/options Boot file/options - // [ ] 'options' options options // Option DHCPOFFER DHCPACK DHCPNAK // ------ --------- ------- ------- // [ ] Requested IP address MUST NOT MUST NOT MUST NOT // [X] IP address lease time MUST MUST (DHCPREQUEST) MUST NOT // MUST NOT (DHCPINFORM) // [ ] Use 'file'/'sname' fields MAY MAY MUST NOT // [X] DHCP message type DHCPOFFER DHCPACK DHCPNAK // [ ] Parameter request list MUST NOT MUST NOT MUST NOT // [ ] Message SHOULD SHOULD SHOULD // [ ] Client identifier MUST NOT MUST NOT MAY // [ ] Vendor class identifier MAY MAY MAY // [X] Server identifier MUST MUST MUST // [ ] Maximum message size MUST NOT MUST NOT MUST NOT // [S] Subnet mask MAY MAY MUST NOT // [ ] All others MAY MAY MUST NOT var response = new DhcpMessage(DhcpOpcode.BootReply, DhcpMessageType.Offer) { HardwareAddressType = SourceMessage.HardwareAddressType, HardwareAddressLength = SourceMessage.HardwareAddressLength, TransactionID = SourceMessage.TransactionID, YourClientIPAddress = OfferedIPAddress, Flags = SourceMessage.Flags, RelayAgentIPAddress = SourceMessage.RelayAgentIPAddress, ClientMacAddress = SourceMessage.ClientMacAddress, }; response.Options.SetValue(DhcpOption.IPAddressLeaseTime, LeaseSeconds); return(response); }
private DhcpDiscoverResult(DhcpMessage sourceMessage, IPAddress offeredIPAddress, uint leaseSeconds) { if (sourceMessage.Options.MessageType != DhcpMessageType.Discover) { throw new ArgumentException("Source message must be a Discover type.", nameof(sourceMessage)); } SourceMessage = sourceMessage; OfferedIPAddress = offeredIPAddress; LeaseSeconds = leaseSeconds; }
private DhcpRequestResult(DhcpMessage sourceMessage, string errorMessage) { if (sourceMessage.Options.MessageType != DhcpMessageType.Request) { throw new ArgumentException("Source message must be a Request type.", nameof(sourceMessage)); } SourceMessage = sourceMessage; MessageType = DhcpMessageType.NoAcknowledge; ErrorMessage = errorMessage; }
private DhcpRequestResult(DhcpMessage sourceMessage, IPAddress assignedIPAddress, uint leaseSeconds) { if (sourceMessage.Options.MessageType != DhcpMessageType.Request) { throw new ArgumentException("Source message must be a Request type.", nameof(sourceMessage)); } SourceMessage = sourceMessage; MessageType = DhcpMessageType.Acknowledge; AssignedIPAddress = assignedIPAddress; LeaseSeconds = leaseSeconds; }
/// <summary> /// This method is called when a request message is recieved. /// </summary> /// <param name="message">The request message recived.</param> /// <returns>The acknowledge or no-acknowledge message to respond with, otherwise null for no response.</returns> protected abstract DhcpRequestResult?OnRequestReceived(DhcpMessage message);
/// <summary> /// Creates an offer based on a source request message. /// </summary> public static DhcpDiscoverResult CreateOffer(DhcpMessage sourceMessage, IPAddress offeredIPAddress, uint leaseSeconds) { return(new DhcpDiscoverResult(sourceMessage, offeredIPAddress, leaseSeconds)); }
private async void RunReceiveLoopAsync(UdpClient udpClient) { while (true) { UdpReceiveResult result; try { result = await udpClient.ReceiveAsync().ConfigureAwait(false); } catch (SocketException ex) { Stop(); OnSocketError(ex); return; } catch (ObjectDisposedException) { return; } DhcpMessage message; try { message = new DhcpMessage(result.Buffer); } catch (InvalidDataException ex) { OnMessageError(ex); continue; } if (!message.RelayAgentIPAddress.Equals(IPAddress.Any)) { OnMessageError(new DhcpMessageException("Relayed DHCP messages are not supported.", message)); continue; } if (message.OpCode != DhcpOpcode.BootRequest) { OnMessageError(new DhcpMessageException("Invalid op code.", message)); continue; } switch (message.Options.MessageType) { case DhcpMessageType.Discover: var discoverResult = OnDiscoverReceived(message); if (discoverResult != null) { SendResponse(udpClient, discoverResult.CreateMessage()); } break; case DhcpMessageType.Request: if (message.Options.ServerIdentifier?.Equals(_localEndPoint.Address) == false) { continue; } var requestResult = OnRequestReceived(message); if (requestResult != null) { SendResponse(udpClient, requestResult.CreateMessage()); } break; case DhcpMessageType.Release: OnReleaseReceived(message); break; case DhcpMessageType.Decline: OnDeclineReceived(message); break; default: OnMessageError(new DhcpMessageException("Invalid DhcpMessageType received.", message)); break; } } }
/// <summary> /// This method is called anytime a response has been successfully sent. /// </summary> /// <param name="message">The response sent.</param> protected abstract void OnResponseSent(DhcpMessage message);
/// <summary> /// This method is called when an inform message is received. /// </summary> /// <param name="message">The inform message received.</param> protected abstract void OnInformReceived(DhcpMessage message);
/// <summary> /// This method is called when a release message is received. /// </summary> /// <param name="message">The release message received.</param> protected abstract void OnReleaseReceived(DhcpMessage message);
/// <summary> /// This method is called when a decline message is received. /// </summary> /// <param name="message">The decline message received.</param> protected abstract void OnDeclineReceived(DhcpMessage message);
public static DhcpRequestResult CreateAcknowledgement(DhcpMessage sourceMessage, IPAddress assignedIPAddress, uint leaseSeconds) { return(new DhcpRequestResult(sourceMessage, assignedIPAddress, leaseSeconds)); }
public static DhcpRequestResult CreateNoAcknowledgement(DhcpMessage sourceMessage, string errorMessage) { return(new DhcpRequestResult(sourceMessage, errorMessage)); }
/// <summary> /// This method is called when a discover message is received. /// </summary> /// <param name="message">The discover message received.</param> /// <returns>An offer message to respond with, otherwise null for no response.</returns> protected abstract DhcpDiscoverResult?OnDiscoverReceived(DhcpMessage message);