/// <summary> /// Process INFORM message type. /// </summary> private void DhcpInform(DhcpMessageEventArgs args) { #region Pre-Processing // Start pre-process validation // if the client provided a ServerID option, then it MUST // match our configured ServerID, otherwise ignore the request InternetAddress serverIdentifier = new InternetAddress(args.RequestOptions.ServerIdentifier); //InternetAddress localServerIdentifier = new InternetAddress(((IPEndPoint)_dhcpSocket.LocalEndPoint).Address.GetAddressBytes()); InternetAddress localServerIdentifier = new InternetAddress(this.InterfaceAddress); if (!serverIdentifier.Equals(localServerIdentifier)) { Logger.WriteDebug(this, "Ignoring INFORM message: " + "Requested ServerId: " + serverIdentifier.ToString() + " Local ServerId: " + localServerIdentifier.ToString()); return; // if processing should not continue } // End pre-Process validation #endregion Pre-Processing this.SendAck(args); }
/// <summary> /// Send response message back to remote client. /// </summary> private void SendReply(DhcpMessageEventArgs args) { // set global headers args.ResponseMessage.Operation = OperationCode.BootReply; args.ResponseMessage.Hardware = args.RequestMessage.Hardware; args.ResponseMessage.HardwareAddressLength = args.RequestMessage.HardwareAddressLength; args.ResponseMessage.SessionId = args.RequestMessage.SessionId; args.ResponseMessage.Flags = args.RequestMessage.Flags; args.ResponseMessage.RelayAgentAddress = args.RequestMessage.RelayAgentAddress; args.ResponseMessage.ClientHardwareAddress = args.RequestMessage.ClientHardwareAddress; if (!StringUtility.IsNullOrEmpty(this._serverName)) { args.ResponseMessage.ServerName = Encoding.UTF8.GetBytes(this._serverName); } if (!StringUtility.IsNullOrEmpty(this._bootFileName)) { args.ResponseMessage.BootFileName = Encoding.UTF8.GetBytes(this._bootFileName); } // set global options //args.ResponseMessage.AddOption(DhcpOption.ServerIdentifier, ((IPEndPoint)_dhcpSocket.LocalEndPoint).Address.GetAddressBytes()); args.ResponseMessage.AddOption(DhcpOption.ServerIdentifier, (this.InterfaceAddress.GetAddressBytes())); // determin the proper ip address and port for sendto InternetAddress relayAgentAddress = args.RequestMessage.RelayAgentAddress; InternetAddress clientAddress = args.RequestMessage.ClientAddress; if (!relayAgentAddress.Equals(InternetAddress.Any)) { args.Channel.RemoteEndpoint = new IPEndPoint(relayAgentAddress.ToIPAddress(), Constants.DHCP_SERVICE_PORT); } else { if (!clientAddress.Equals(InternetAddress.Any)) { args.Channel.RemoteEndpoint = new IPEndPoint(clientAddress.ToIPAddress(), Constants.DHCP_CLIENT_PORT); } else { args.Channel.RemoteEndpoint = new IPEndPoint(InternetAddress.Broadcast.ToIPAddress(), Constants.DHCP_CLIENT_PORT); } } try { args.Channel.SendTo(args.ResponseMessage.ToArray(), args.Channel.RemoteEndpoint); Logger.WriteDebug(this, "PACKET with message id " + args.ResponseMessage.SessionId.ToHexString("0x") + " successfully sent to client endpoint " + args.Channel.RemoteEndpoint.ToString()); Logger.WriteDebug(args.ResponseMessage.ToString()); OnDhcpMessageSent(this, args); } catch (SocketException ex) { Logger.WriteError(this, ex.Message + "Socket Error Code: " + ex.ErrorCode.ToString(), ex); } catch (Exception ex) { Logger.WriteError(this, "Error Message:" + ex.Message.ToString(), ex); } }
/// <summary> /// Process INFORM message type. /// </summary> private void DhcpInform(DhcpMessageEventArgs args) { #region Pre-Processing // Start pre-process validation // if the client provided a ServerID option, then it MUST // match our configured ServerID, otherwise ignore the request InternetAddress serverIdentifier = new InternetAddress(args.RequestOptions.ServerIdentifier); //InternetAddress localServerIdentifier = new InternetAddress(((IPEndPoint)_dhcpSocket.LocalEndPoint).Address.GetAddressBytes()); InternetAddress localServerIdentifier = new InternetAddress(this.InterfaceAddress); if (!serverIdentifier.Equals(localServerIdentifier)) { Logger.WriteDebug(this, "Ignoring INFORM message: " + "Requested ServerId: " + serverIdentifier.ToString() + " Local ServerId: " + localServerIdentifier.ToString()); return; // if processing should not continue } // End pre-Process validation #endregion Pre-Processing this.SendAck(args); }
/// <summary> /// Process REQUEST message type. /// </summary> private void DhcpRequest(DhcpMessageEventArgs args) { RequestState requestState; #region Pre-Processing // Start pre-process validation //--------------------------------------------------------------------- //| |INIT-REBOOT |SELECTING |RENEWING |REBINDING | //--------------------------------------------------------------------- //|broad/unicast |broadcast |broadcast |unicast |broadcast | //|server-ip |MUST NOT |MUST |MUST NOT |MUST NOT | //|requested-ip |MUST |MUST |MUST NOT |MUST NOT | //|ciaddr |zero |zero |IP address |IP address| //--------------------------------------------------------------------- // first determine what KIND of request we are dealing with if (args.RequestMessage.ClientAddress.Equals(InternetAddress.Any)) { // the ciAddr MUST be 0.0.0.0 for Init-Reboot and Selecting if (args.RequestOptions.AddressRequest == null) { // init-reboot MUST NOT have server-id option requestState = RequestState.InitReboot; } else { // selecting MUST have server-id option requestState = RequestState.Selecting; } } else { // the ciAddr MUST NOT be 0.0.0.0 for Renew and Rebind if (!args.RequestMessage.IsBroadcast) { // renew is unicast // NOTE: this will not happen if the v4 broadcast interface used at startup, // but handling of DHCPv4 renew/rebind is the same anyway requestState = RequestState.Renewing; } else { // rebind is broadcast requestState = RequestState.Rebinding; } } if ((requestState == RequestState.InitReboot) || (requestState == RequestState.Selecting)) { if (args.RequestOptions.AddressRequest == null) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: Requested IP option is null"); return; // if processing should not continue } if (requestState == RequestState.Selecting) { // if the client provided a ServerID option, then it MUST // match our configured ServerID, otherwise ignore the request InternetAddress serverIdentifier = new InternetAddress(args.RequestOptions.ServerIdentifier); //InternetAddress localServerIdentifier = new InternetAddress(((IPEndPoint)_dhcpSocket.LocalEndPoint).Address.GetAddressBytes()); InternetAddress localServerIdentifier = new InternetAddress(this.InterfaceAddress); if (!serverIdentifier.Equals(localServerIdentifier)) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: " + "Requested ServerId: " + serverIdentifier.ToString() + " Local ServerId: " + localServerIdentifier.ToString()); return; // if processing should not continue } } } else { // type == Renewing or Rebinding if (args.RequestOptions.AddressRequest != null) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: " + "Requested IP option is not null"); return; // if processing should not continue } } // End pre-process validation #endregion Pre-Processing Logger.WriteDebug(this, "Processing REQUEST " + RequestStateString.GetName(requestState) + " message"); //TODO: should also check for ip on link if (args.RequestOptions.AddressRequest != null) { args.ResponseBinding.Address = new InternetAddress(args.RequestOptions.AddressRequest); } BindingLease assignment = _bindmgr.GetAssigned(args.ResponseBinding); if (assignment == null) { args.ResponseMessage.AddOption(DhcpOption.DhcpMessage, Encoding.UTF8.GetBytes("No binding available for client")); Logger.WriteDebug(this, "REQUEST " + RequestStateString.GetName(requestState) + " message: No binding available for client sending NAK"); this.SendNak(args); } else { this.SendAck(args, assignment); this.OnLeaseAcknowledged(this, new DhcpLeaseEventArgs(assignment.Address, assignment)); } }
/// <summary> /// Process REQUEST message type. /// </summary> private void DhcpRequest(DhcpMessageEventArgs args) { RequestState requestState; #region Pre-Processing // Start pre-process validation //--------------------------------------------------------------------- //| |INIT-REBOOT |SELECTING |RENEWING |REBINDING | //--------------------------------------------------------------------- //|broad/unicast |broadcast |broadcast |unicast |broadcast | //|server-ip |MUST NOT |MUST |MUST NOT |MUST NOT | //|requested-ip |MUST |MUST |MUST NOT |MUST NOT | //|ciaddr |zero |zero |IP address |IP address| //--------------------------------------------------------------------- // first determine what KIND of request we are dealing with if (args.RequestMessage.ClientAddress.Equals(InternetAddress.Any)) { // the ciAddr MUST be 0.0.0.0 for Init-Reboot and Selecting if (args.RequestOptions.AddressRequest == null) { // init-reboot MUST NOT have server-id option requestState = RequestState.InitReboot; } else { // selecting MUST have server-id option requestState = RequestState.Selecting; } } else { // the ciAddr MUST NOT be 0.0.0.0 for Renew and Rebind if (!args.RequestMessage.IsBroadcast) { // renew is unicast // NOTE: this will not happen if the v4 broadcast interface used at startup, // but handling of DHCPv4 renew/rebind is the same anyway requestState = RequestState.Renewing; } else { // rebind is broadcast requestState = RequestState.Rebinding; } } if ((requestState == RequestState.InitReboot) || (requestState == RequestState.Selecting)) { if (args.RequestOptions.AddressRequest == null) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: Requested IP option is null"); return; // if processing should not continue } if (requestState == RequestState.Selecting) { // if the client provided a ServerID option, then it MUST // match our configured ServerID, otherwise ignore the request InternetAddress serverIdentifier = new InternetAddress(args.RequestOptions.ServerIdentifier); //InternetAddress localServerIdentifier = new InternetAddress(((IPEndPoint)_dhcpSocket.LocalEndPoint).Address.GetAddressBytes()); InternetAddress localServerIdentifier = new InternetAddress(this.InterfaceAddress); if (!serverIdentifier.Equals(localServerIdentifier)) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: " + "Requested ServerId: " + serverIdentifier.ToString() + " Local ServerId: " + localServerIdentifier.ToString()); return; // if processing should not continue } } } else { // type == Renewing or Rebinding if (args.RequestOptions.AddressRequest != null) { Logger.WriteDebug(this, "Ignoring REQUEST " + RequestStateString.GetName(requestState) + " message: " + "Requested IP option is not null"); return; // if processing should not continue } } // End pre-process validation #endregion Pre-Processing Logger.WriteDebug(this, "Processing REQUEST " + RequestStateString.GetName(requestState) + " message"); //TODO: should also check for ip on link if (args.RequestOptions.AddressRequest != null) { args.ResponseBinding.Address = new InternetAddress(args.RequestOptions.AddressRequest); } BindingLease assignment = _bindmgr.GetAssigned(args.ResponseBinding); if (assignment == null) { args.ResponseMessage.AddOption(DhcpOption.DhcpMessage, Encoding.UTF8.GetBytes("No binding available for client")); Logger.WriteDebug(this, "REQUEST " + RequestStateString.GetName(requestState) + " message: No binding available for client sending NAK"); this.SendNak(args); } else { this.SendAck(args, assignment); this.OnLeaseAcknowledged(this, new DhcpLeaseEventArgs(assignment.Address, assignment)); } }