private void SetIaPdT1(DhcpLink clientLink, DhcpV6IaPdOption iaPdOption, long minPreferredLifetime) { float t1 = DhcpServerPolicies.EffectivePolicyAsFloat(this.clientLink.GetLink(), Property.IA_PD_T1); if ((t1 > 1)) { log.Debug(("Setting IA_PD T1 to configured number of seconds: " + t1)); // if T1 is greater than one, then treat it as an // absolute value which specifies the number of seconds iaPdOption.SetT1(((long)(t1))); } else { // if T1 is less than one and greater than or equal to zero, // then treat is as a percentage of the minimum preferred lifetime // unless the minimum preferred lifetime is infinity (0xffffffff) if ((minPreferredLifetime == 4294967295)) { log.Debug(("Setting IA_PD T1 to minPreferredLifetime of infinity: " + minPreferredLifetime)); iaPdOption.SetT1(minPreferredLifetime); } else if ((t1 >= 0)) { // zero means let the client decide log.Debug(("Setting IA_PD T1 to configured ratio=" + (t1 + (" of minPreferredLifetime=" + minPreferredLifetime)))); iaPdOption.SetT1(((long)((t1 * minPreferredLifetime)))); } else { log.Debug(("Setting IA_PD T1 to standard ratio=0.5" + (" of minPreferredLifetime=" + minPreferredLifetime))); iaPdOption.SetT1(((long)((0.5 * minPreferredLifetime)))); } } }
/// <summary> /// Release an IaAddress. If policy dictates, the address will be deleted, /// otherwise the state will be marked as released instead. In either case, /// a DDNS delete will be issued for the address binding. /// </summary> /// <param name="ia">iaAddr the IaAddress to be released</param> /// <param name="iaAddr">iaAddr the IaAddress to be released</param> public void ReleaseIaAddress(IdentityAssoc ia, IaAddress iaAddr) { try { log.Info("Releasing address: " + iaAddr.GetIpAddress().ToString()); //DdnsDelete(ia, iaAddr); if (DhcpServerPolicies.GlobalPolicyAsBoolean( Property.BINDING_MANAGER_DELETE_OLD_BINDINGS)) { iaMgr.DeleteIaAddr(iaAddr); // free the address only if it is deleted from the db, // otherwise, we will get a unique constraint violation // if another client obtains this released IP address FreeAddress(iaAddr.GetIpAddress()); } else { iaAddr.SetStartTime(DateTime.Now); iaAddr.SetPreferredEndTime(DateTime.Now); iaAddr.SetValidEndTime(DateTime.Now); iaAddr.SetState(IaAddress.RELEASED); iaMgr.UpdateIaAddr(iaAddr); log.Info("Address released: " + iaAddr.ToString()); } } catch (Exception ex) { log.Error("Failed to release address"); } }
//Populate v4 options. //@param link the link //@param configObj the config object or null if none protected void PopulateV4Reply(DhcpLink dhcpLink, DhcpV4OptionConfigObject configObj) { string sname = DhcpServerPolicies.EffectivePolicy(_requestMsg, configObj, dhcpLink.GetLink(), Property.V4_HEADER_SNAME); if (!String.IsNullOrEmpty(sname)) { _replyMsg.SetsName(sname); } string filename = DhcpServerPolicies.EffectivePolicy(_requestMsg, configObj, dhcpLink.GetLink(), Property.V4_HEADER_FILENAME); if (!String.IsNullOrEmpty(filename)) { _replyMsg.SetFile(filename); } Dictionary <int, DhcpOption> optionMap = _dhcpServerConfig.EffectiveV4AddrOptions(_requestMsg, dhcpLink, configObj); if (DhcpServerPolicies.EffectivePolicyAsBoolean(configObj, dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY)) { optionMap = RequestedOptions(optionMap, _requestMsg); } _replyMsg.PutAllDhcpOptions(optionMap); // copy the relay agent info option from request to reply // in order to echo option back to router as required if (_requestMsg.HasOption(DhcpConstants.V4OPTION_RELAY_INFO)) { _requestMsg.PutDhcpOption(_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_RELAY_INFO)); } }
/** * Callback from the ExpireTimerTask started when the lease was granted. * NOT CURRENTLY USED * * @param iaPrefix the ia prefix */ public void ExpireIaPrefix(IaPrefix iaPrefix) { try { if (DhcpServerPolicies.GlobalPolicyAsBoolean( Property.BINDING_MANAGER_DELETE_OLD_BINDINGS)) { log.Debug("Deleting expired prefix: " + iaPrefix.GetIpAddress()); iaMgr.DeleteIaPrefix(iaPrefix); // free the prefix only if it is deleted from the db, // otherwise, we will get a unique constraint violation // if another client obtains this released prefix FreeAddress(iaPrefix.GetIpAddress()); } else { iaPrefix.SetStartTime(DateTime.Now); iaPrefix.SetPreferredEndTime(DateTime.Now); iaPrefix.SetValidEndTime(DateTime.Now); iaPrefix.SetState(IaPrefix.EXPIRED); log.Debug("Updating expired prefix: " + iaPrefix.GetIpAddress()); iaMgr.UpdateIaPrefix(iaPrefix); } } catch (Exception ex) { log.Error("Failed to expire address"); } }
/** * Builds a binding pool from an V4AddressPool using the given link and filter. * * @param pool the V4AddressPool to wrap as an V4AddressBindingPool * @param link the link * @param linkFilter the link filter * * @return the binding pool * * @throws DhcpServerConfigException if there is a problem parsing the configured range */ protected V4AddressBindingPool BuildV4BindingPool(v4AddressPool pool, link link, linkFilter linkFilter) { V4AddressBindingPool bp = new V4AddressBindingPool(pool); long leasetime = DhcpServerPolicies.EffectivePolicyAsLong(bp, link, Property.V4_DEFAULT_LEASETIME); bp.SetLeasetime(leasetime); bp.SetLinkFilter(linkFilter); List <IPAddress> usedIps = iaMgr.FindExistingIPs(bp.GetStartAddress(), bp.GetEndAddress()); if ((usedIps != null) && usedIps.Count > 0) { foreach (IPAddress ip in usedIps) { //TODO: for the quickest startup?... // set IP as used without checking if the binding has expired // let the reaper thread deal with all binding cleanup activity bp.SetUsed(ip); } } log.Info("Built v4 address binding pool: " + bp.GetStartAddress().ToString() + "-" + bp.GetEndAddress().ToString() + " size=" + bp.GetSize()); return(bp); }
/** * Builds a binding pool from an PrefixPool using the given link and filter. * * @param pool the AddressPool to wrap as an PrefixBindingPool * @param link the link * @param linkFilter the link filter * * @return the binding pool * * @throws DhcpServerConfigException if there is a problem parsing the configured range */ protected V6PrefixBindingPool BuildV6BindingPool(v6PrefixPool pool, link link, linkFilter linkFilter) { V6PrefixBindingPool bp = new V6PrefixBindingPool(pool); long pLifetime = DhcpServerPolicies.EffectivePolicyAsLong(bp, link, Property.PREFERRED_LIFETIME); bp.SetPreferredLifetime(pLifetime); long vLifetime = DhcpServerPolicies.EffectivePolicyAsLong(bp, link, Property.VALID_LIFETIME); bp.SetValidLifetime(vLifetime); bp.SetLinkFilter(linkFilter); List <IPAddress> usedIps = iaMgr.FindExistingIPs(bp.GetStartAddress(), bp.GetEndAddress()); if ((usedIps != null) && usedIps.Count > 0) { foreach (IPAddress ip in usedIps) { //TODO: for the quickest startup?... // set IP as used without checking if the binding has expired // let the reaper thread deal with all binding cleanup activity bp.SetUsed(ip); } } log.Info("Built prefix binding pool: " + bp.GetStartAddress().ToString() + "-" + bp.GetEndAddress().ToString() + ", size=" + bp.GetSize()); return(bp); }
/// <summary> /// 是否開啟快速提交模式 /// </summary> /// <param name="requestMsg"></param> /// <param name="clientLink"></param> /// <returns></returns> private bool IsRapidCommit(DhcpV6Message requestMsg, link clientLink) { if ((requestMsg.HasOption(DhcpConstants.V6OPTION_RAPID_COMMIT) && DhcpServerPolicies.EffectivePolicyAsBoolean(requestMsg, clientLink, Property.SUPPORT_RAPID_COMMIT))) { return(true); } return(false); }
protected void PopulatePrefixOptions(DhcpV6IaPrefixOption iaPrefixOption, DhcpLink dhcpLink, DhcpV6OptionConfigObject configObj) { Dictionary <int, DhcpOption> optionMap = dhcpServerConfig.EffectivePrefixOptions(this.requestMsg, dhcpLink, configObj); if (DhcpServerPolicies.EffectivePolicyAsBoolean(configObj, dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY)) { optionMap = this.RequestedOptions(optionMap, this.requestMsg); } iaPrefixOption.PutAllDhcpOptions(optionMap); }
protected void PopulatePrefixOptions(DhcpV6IaPrefixOption iaPrefixOption) { Dictionary <int, DhcpOption> optionMap = dhcpServerConfig.EffectivePrefixOptions(this.requestMsg); if (DhcpServerPolicies.GlobalPolicyAsBoolean(Property.SEND_REQUESTED_OPTIONS_ONLY)) { optionMap = this.RequestedOptions(optionMap, this.requestMsg); } iaPrefixOption.PutAllDhcpOptions(optionMap); }
protected override void StartReaper() { //TODO: separate properties for address/prefix binding managers? long reaperStartupDelay = DhcpServerPolicies.GlobalPolicyAsLong(Property.BINDING_MANAGER_REAPER_STARTUP_DELAY); long reaperRunPeriod = DhcpServerPolicies.GlobalPolicyAsLong(Property.BINDING_MANAGER_REAPER_RUN_PERIOD); //reaper = new Timer("BindingReaper"); //reaper.schedule(new ReaperTimerTask(), reaperStartupDelay, reaperRunPeriod); }
/// <summary> /// Populate reply msg options. /// </summary> /// <param name="dhcpLink">the link</param> protected void PopulateReplyMsgOptions(DhcpLink dhcpLink) { Dictionary <int, DhcpOption> optionMap = dhcpServerConfig.EffectiveMsgOptions(this.requestMsg, dhcpLink); if (DhcpServerPolicies.EffectivePolicyAsBoolean(dhcpLink.GetLink(), Property.SEND_REQUESTED_OPTIONS_ONLY)) { optionMap = this.RequestedOptions(optionMap, this.requestMsg); } replyMsg.PutAllDhcpOptions(optionMap); }
/// <summary> /// Gets the next available address in this address pool. /// </summary> /// <returns>the next available address</returns> public IPAddress GetNextAvailableAddress() { Monitor.Enter(_lock); try { if (freeList != null) { BigInteger next = freeList.GetNextFree(); if (next.IntValue() != 0) { try { IPAddress ip = new IPAddress(next.GetBytes()); int pingCheckTimeout = DhcpServerPolicies.GlobalPolicyAsInt(Property.V4_PINGCHECK_TIMEOUT); if (pingCheckTimeout > 0) { try { if (CheckIPIsUsed(ip, pingCheckTimeout)) { log.Warn("Next free address answered ping check: " + ip.ToString()); SetUsed(ip); return(GetNextAvailableAddress()); // try again } log.InfoFormat("Assign IPv4 Address : {0}", ip.ToString()); } catch (IOException ex) { log.Error("Failed to perform v4 ping check: " + ex); } } return(ip); } catch (Exception ex) { log.Error("Unable to build IPv4 address from next free: " + ex); } } } } catch (Exception ex) { log.Error("Unable to build IPv4 address from next free: " + ex); } finally { Monitor.Exit(_lock); } return(null); }
private void SetIaPdT2(DhcpLink clientLink, DhcpV6IaPdOption iaPdOption, long minPreferredLifetime) { float t2 = DhcpServerPolicies.EffectivePolicyAsFloat(this.clientLink.GetLink(), Property.IA_PD_T2); if ((t2 > 1)) { log.Debug(("Setting IA_PD T2 to configured number of seconds: " + t2)); iaPdOption.SetT2(((long)(t2))); } else { // if T2 is less than one and greater than or equal to zero, // then treat is as a percentage of the minimum preferred lifetime // unless the minimum preferred lifetime is infinity (0xffffffff) if ((minPreferredLifetime == 4294967295)) { log.Debug(("Setting IA_PD T2 to minPreferredLifetime of infinity: " + minPreferredLifetime)); iaPdOption.SetT2(minPreferredLifetime); } else if ((t2 >= 0)) { // zero means let the client decide log.Debug(("Setting IA_PD T2 to configured ratio=" + (t2 + (" of minPreferredLifetime=" + minPreferredLifetime)))); iaPdOption.SetT2(((long)((t2 * minPreferredLifetime)))); } else { log.Debug(("Setting IA_PD T2 to standard ratio=0.8" + (" of minPreferredLifetime=" + minPreferredLifetime))); iaPdOption.SetT2(((long)((0.8 * minPreferredLifetime)))); } } // ensure that T2 >= T1 if ((iaPdOption.GetT2() < iaPdOption.GetT1())) { log.Warn((" IA_PD T2(" + (iaPdOption.GetT2() + (")" + (" < IA_PD T1(" + (iaPdOption.GetT1() + "): setting T2=T1")))))); iaPdOption.SetT2(iaPdOption.GetT1()); } }
public List <IaAddress> FindUnusedIaAddresses(IPAddress startAddr, IPAddress endAddr) { long offerExpireMillis = DhcpServerPolicies.GlobalPolicyAsLong(Property.BINDING_MANAGER_OFFER_EXPIRATION); long offerExpiration = OpaqueDataUtil.GetCurrentMilli() - offerExpireMillis; List <DhcpLease> leases = _DhcpLeaseData.Where(d => ((d.GetState() == IaAddress.ADVERTISED && d.GetStartTime() <= new DateTime(offerExpiration)) | (d.GetState() == IaAddress.EXPIRED | d.GetState() == IaAddress.RELEASED)) && d.GetIpAddress().GetLong() >= startAddr.GetLong() && d.GetIpAddress().GetLong() <= endAddr.GetLong()). OrderBy(s => s.GetState()). ThenBy(t => t.GetValidEndTime()). //ThenBy(d => d.GetIpAddress()) ToList(); return(ToIaAddresses(leases)); }
private bool IsIgnoredMac(byte[] chAddr) { string ignoredMacPolicy = DhcpServerPolicies.GlobalPolicy(Property.V4_IGNORED_MACS); if (ignoredMacPolicy != null) { string[] ignoredMacs = ignoredMacPolicy.Split(','); if (ignoredMacs != null) { foreach (var ignoredMac in ignoredMacs) { if (ignoredMac.Trim().ToUpper().Equals(Util.ToHexString(chAddr).ToUpper())) { return(true); } } } } return(false); }
/// <summary> /// Gets the next available address in this address pool. /// </summary> /// <returns>the next available address</returns> public IPAddress GetNextAvailableAddress() { Debug.Assert(CheckIPIsUsed != null, "V6AddressBindingPool --GetNextAvailableAddress-- CheckIPIsUsed = null"); if (freeList != null) { BigInteger next = freeList.GetNextFree(); if (next.IntValue() != 0) { try { byte[] nextByte = next.GetBytes(); IPAddress ip = new IPAddress(next.GetBytes()); int pingCheckTimeout = DhcpServerPolicies.GlobalPolicyAsInt(Property.V4_PINGCHECK_TIMEOUT); if (pingCheckTimeout > 0) { try { if (CheckIPIsUsed(ip, pingCheckTimeout)) { log.Warn("Next free address answered ping check: " + ip.ToString()); SetUsed(ip); return(GetNextAvailableAddress()); // try again } log.InfoFormat("Assign IPv6 Address : {0}", ip.ToString()); } catch (IOException ex) { log.Error("Failed to perform v4 ping check: " + ex); } } return(ip); } catch (Exception ex) { log.Error("Unable to build IPv6 address from next free: " + ex); } } } return(null); }
/* (non-Javadoc) * @see java.lang.Runnable#run() */ //public void Run() //{ // SetupPolicies(configObj, lifetime); // try // { // if (doForwardUpdate) // { // ForwardDdnsUpdate fwdUpdate = new ForwardDdnsUpdate(fqdn, addr, duid); // fwdUpdate.SetServer(fwdServer); // fwdUpdate.SetZone(fwdZone); // fwdUpdate.SetTtl(fwdTtl); // fwdUpdate.SetTsigKeyName(fwdTsigKeyName); // fwdUpdate.SetTsigAlgorithm(fwdTsigAlgorithm); // fwdUpdate.SetTsigKeyData(fwdTsigKeyData); // if (!isDelete) // callback.FwdAddComplete(fwdUpdate.SendAdd()); // else // callback.FwdDeleteComplete(fwdUpdate.SendDelete()); // } // ReverseDdnsUpdate revUpdate = new ReverseDdnsUpdate(fqdn, addr, duid); // revUpdate.SetServer(revServer); // revUpdate.SetZone(revZone); // revUpdate.SetRevZoneBitLength(revZoneBitLength); // revUpdate.SetTtl(revTtl); // revUpdate.SetTsigKeyName(revTsigKeyName); // revUpdate.SetTsigAlgorithm(revTsigAlgorithm); // revUpdate.SetTsigKeyData(revTsigKeyData); // if (!isDelete) // callback.RevAddComplete(revUpdate.SendAdd()); // else // callback.RevDeleteComplete(revUpdate.SendDelete()); // } // catch (Exception ex) // { // log.Error(ex, "Failure performing DDNS updates"); // callback.FwdAddComplete(false); // callback.FwdDeleteComplete(false); // callback.RevAddComplete(false); // callback.RevDeleteComplete(false); // } //} /** * Sets the up policies. * * @param addrBindingPool the new up policies */ private void SetupPolicies(DhcpConfigObject addrBindingPool, long lifetime) { sync = DhcpServerPolicies.EffectivePolicyAsbool(requestMsg, addrBindingPool, clientLink, Property.DDNS_SYNCHRONIZE); string zone = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_NAME); if ((zone != null) && !string.IsNullOrEmpty(zone)) { fwdZone = zone; } zone = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_NAME); if ((zone != null) && !string.IsNullOrEmpty(zone)) { revZone = zone; } revZoneBitLength = DhcpServerPolicies.EffectivePolicyAsInt(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_BITLENGTH); long ttl = 0; float ttlFloat = DhcpServerPolicies.EffectivePolicyAsFloat(requestMsg, addrBindingPool, clientLink, Property.DDNS_TTL); if (ttlFloat < 1) { // if less than one, then percentage of lifetime seconds ttl = (long)(lifetime * ttlFloat); } else { // if greater than one, then absolute number of seconds ttl = (long)ttlFloat; } fwdTtl = ttl; ttlFloat = DhcpServerPolicies.EffectivePolicyAsFloat(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_TTL); if (ttlFloat < 1) { // if less than one, then percentage of lifetime seconds fwdTtl = (long)(lifetime * ttlFloat); } else { // if greater than one, then absolute number of seconds fwdTtl = (long)ttlFloat; } revTtl = ttl; ttlFloat = DhcpServerPolicies.EffectivePolicyAsFloat(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_TTL); if (ttlFloat < 1) { // if less than one, then percentage of lifetime seconds revTtl = (long)(lifetime * ttlFloat); } else { // if greater than one, then absolute number of seconds revTtl = (long)ttlFloat; } string server = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_SERVER); fwdServer = server; revServer = server; server = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_SERVER); if ((server != null) && !string.IsNullOrEmpty(server)) { fwdServer = server; } server = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_SERVER); if ((server != null) && !string.IsNullOrEmpty(server)) { revServer = server; } string tsigKeyName = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_TSIG_KEYNAME); fwdTsigKeyName = tsigKeyName; revTsigKeyName = tsigKeyName; tsigKeyName = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_TSIG_KEYNAME); if ((tsigKeyName != null) && !string.IsNullOrEmpty(tsigKeyName)) { fwdTsigKeyName = tsigKeyName; } tsigKeyName = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_TSIG_KEYNAME); if ((tsigKeyName != null) && !string.IsNullOrEmpty(tsigKeyName)) { revTsigKeyName = tsigKeyName; } string tsigAlgorithm = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_TSIG_ALGORITHM); fwdTsigAlgorithm = tsigAlgorithm; revTsigAlgorithm = tsigAlgorithm; tsigAlgorithm = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_TSIG_ALGORITHM); if ((tsigAlgorithm != null) && !string.IsNullOrEmpty(tsigAlgorithm)) { fwdTsigAlgorithm = tsigAlgorithm; } tsigAlgorithm = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_TSIG_ALGORITHM); if ((tsigAlgorithm != null) && !string.IsNullOrEmpty(tsigAlgorithm)) { revTsigAlgorithm = tsigAlgorithm; } string tsigKeyData = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_TSIG_KEYDATA); fwdTsigKeyData = tsigKeyData; revTsigKeyData = tsigKeyData; tsigKeyData = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_FORWARD_ZONE_TSIG_KEYDATA); if ((tsigKeyData != null) && !string.IsNullOrEmpty(tsigKeyData)) { fwdTsigKeyData = tsigKeyData; } tsigKeyData = DhcpServerPolicies.EffectivePolicy(requestMsg, addrBindingPool, clientLink, Property.DDNS_REVERSE_ZONE_TSIG_KEYDATA); if ((tsigKeyData != null) && !string.IsNullOrEmpty(tsigKeyData)) { revTsigKeyData = tsigKeyData; } }
public override bool Process() { // If the server cannot find a client entry for the IA and the server // determines that the addresses in the IA are not appropriate for the // link to which the client's interface is attached according to the // server's explicit configuration information, the server MAY send a // Reply message to the client containing the client's IA, with the // lifetimes for the addresses in the IA set to zero. This Reply // constitutes an explicit notification to the client that the addresses // in the IA are no longer valid. In this situation, if the server does // not send a Reply message it silently discards the Rebind message. // // If the server finds that any of the addresses are no longer // appropriate for the link to which the client is attached, the server // returns the address to the client with lifetimes of 0. // // If the server finds the addresses in the IA for the client then the // server SHOULD send back the IA to the client with new lifetimes and // T1/T2 times. bool sendReply = true; DhcpV6ClientIdOption clientIdOption = requestMsg.GetDhcpClientIdOption(); List <DhcpV6IaNaOption> iaNaOptions = requestMsg.GetIaNaOptions(); if (((iaNaOptions != null) && iaNaOptions.Count > 0)) { V6NaAddrBindingManager bindingMgr = dhcpServerConfig.GetNaAddrBindingMgr(); if ((bindingMgr != null)) { foreach (DhcpV6IaNaOption dhcpIaNaOption in iaNaOptions) { log.Info(("Processing IA_NA Rebind: " + dhcpIaNaOption.ToString())); Binding binding = bindingMgr.FindCurrentBinding(clientLink, clientIdOption, dhcpIaNaOption, requestMsg); if ((binding != null)) { // zero out the lifetimes of any invalid addresses if (!AllIaAddrsOnLink(dhcpIaNaOption, clientLink)) { replyMsg.AddIaNaOption(dhcpIaNaOption); } else { binding = bindingMgr.UpdateBinding(binding, clientLink, clientIdOption, dhcpIaNaOption, requestMsg, IdentityAssoc.COMMITTED, _clientV4IP); if ((binding != null)) { AddBindingToReply(clientLink, binding); bindings.Add(binding); } else { AddIaNaOptionStatusToReply(dhcpIaNaOption, DhcpConstants.V6STATUS_CODE_NOADDRSAVAIL); } } } else if (DhcpServerPolicies.EffectivePolicyAsBoolean(requestMsg, clientLink.GetLink(), Property.VERIFY_UNKNOWN_REBIND)) { // zero out the lifetimes of any invalid addresses AllIaAddrsOnLink(dhcpIaNaOption, clientLink); replyMsg.AddIaNaOption(dhcpIaNaOption); } } } else { log.Error(("Unable to process IA_NA Rebind:" + " No NaAddrBindingManager available")); } } List <DhcpV6IaTaOption> iaTaOptions = requestMsg.GetIaTaOptions(); if (((iaTaOptions != null) && iaTaOptions.Count > 0)) { V6TaAddrBindingManager bindingMgr = dhcpServerConfig.GetTaAddrBindingMgr(); if ((bindingMgr != null)) { foreach (DhcpV6IaTaOption dhcpIaTaOption in iaTaOptions) { log.Info(("Processing IA_TA Rebind: " + dhcpIaTaOption.ToString())); Binding binding = bindingMgr.FindCurrentBinding(clientLink, clientIdOption, dhcpIaTaOption, requestMsg); if ((binding != null)) { // zero out the lifetimes of any invalid addresses if (!AllIaAddrsOnLink(dhcpIaTaOption, clientLink)) { replyMsg.AddIaTaOption(dhcpIaTaOption); } else { binding = bindingMgr.UpdateBinding(binding, clientLink, clientIdOption, dhcpIaTaOption, requestMsg, IdentityAssoc.COMMITTED, _clientV4IP); if ((binding != null)) { AddBindingToReply(clientLink, binding); bindings.Add(binding); } else { AddIaTaOptionStatusToReply(dhcpIaTaOption, DhcpConstants.V6STATUS_CODE_NOADDRSAVAIL); } } } else if (DhcpServerPolicies.EffectivePolicyAsBoolean(requestMsg, clientLink.GetLink(), Property.VERIFY_UNKNOWN_REBIND)) { // zero out the lifetimes of any invalid addresses AllIaAddrsOnLink(dhcpIaTaOption, clientLink); replyMsg.AddIaTaOption(dhcpIaTaOption); } } } else { log.Error(("Unable to process IA_TA Rebind:" + " No TaAddrBindingManager available")); } } List <DhcpV6IaPdOption> iaPdOptions = requestMsg.GetIaPdOptions(); if (((iaPdOptions != null) && iaPdOptions.Count > 0)) { V6PrefixBindingManager bindingMgr = dhcpServerConfig.GetPrefixBindingMgr(); if ((bindingMgr != null)) { foreach (DhcpV6IaPdOption dhcpIaPdOption in iaPdOptions) { log.Info(("Processing IA_PD Rebind: " + dhcpIaPdOption.ToString())); Binding binding = bindingMgr.FindCurrentBinding(clientLink, clientIdOption, dhcpIaPdOption, requestMsg); if ((binding != null)) { // zero out the lifetimes of any invalid addresses if (!AllIaPrefixesOnLink(dhcpIaPdOption, clientLink)) { replyMsg.AddIaPdOption(dhcpIaPdOption); } else { binding = bindingMgr.UpdateBinding(binding, clientLink, clientIdOption, dhcpIaPdOption, requestMsg, IdentityAssoc.COMMITTED, _clientV4IP); if ((binding != null)) { AddBindingToReply(clientLink, binding); bindings.Add(binding); } else { AddIaPdOptionStatusToReply(dhcpIaPdOption, DhcpConstants.V6STATUS_CODE_NOPREFIXAVAIL); } } } else if (DhcpServerPolicies.EffectivePolicyAsBoolean(requestMsg, clientLink.GetLink(), Property.VERIFY_UNKNOWN_REBIND)) { // zero out the lifetimes of any invalid addresses AllIaPrefixesOnLink(dhcpIaPdOption, clientLink); replyMsg.AddIaPdOption(dhcpIaPdOption); } } } else { log.Error(("Unable to process IA_PD Rebind:" + " No PrefixBindingManager available")); } } if ((bindings.Count == 0 && !DhcpServerPolicies.EffectivePolicyAsBoolean(requestMsg, clientLink.GetLink(), Property.VERIFY_UNKNOWN_REBIND))) { sendReply = false; } if (sendReply) { replyMsg.SetMessageType(DhcpConstants.V6MESSAGE_TYPE_REPLY); if (bindings.Count == 0) { PopulateReplyMsgOptions(clientLink); ProcessDdnsUpdates(true); } } return(sendReply); }
protected void ProcessDdnsUpdates(bool sendUpdates) { bool doForwardUpdate = true; DhcpV4ClientFqdnOption clientFqdnOption = (DhcpV4ClientFqdnOption)_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_CLIENT_FQDN); DhcpV4HostnameOption hostnameOption = (DhcpV4HostnameOption)_requestMsg.GetDhcpOption(DhcpConstants.V4OPTION_HOSTNAME); if (clientFqdnOption == null && hostnameOption == null) { //TODO allow name generation? log.Debug("No Client FQDN nor hostname option in request. Skipping DDNS update processing."); return; } string fqdn = ""; string domain = DhcpServerPolicies.DffectivePolicy(_clientLink.GetLink(), Property.DDNS_DOMAIN); DhcpV4ClientFqdnOption replyFqdnOption = null; if (clientFqdnOption != null) { replyFqdnOption = new DhcpV4ClientFqdnOption(); replyFqdnOption.SetDomainName(clientFqdnOption.GetDomainName()); replyFqdnOption.SetUpdateABit(false); replyFqdnOption.SetOverrideBit(false); replyFqdnOption.SetNoUpdateBit(false); replyFqdnOption.SetEncodingBit(clientFqdnOption.GetEncodingBit()); replyFqdnOption.SetRcode1((short)0xff); // RFC 4702 says server should set to 255 replyFqdnOption.SetRcode2((short)0xff); // RFC 4702 says server should set to 255 fqdn = clientFqdnOption.GetDomainName(); if ((fqdn == null) || (fqdn.Length <= 0)) { log.Error("Client FQDN option domain name is null/empty. No DDNS udpates performed."); replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates _replyMsg.PutDhcpOption(replyFqdnOption); return; } string policy = DhcpServerPolicies.EffectivePolicy(_requestMsg, _clientLink.GetLink(), Property.DDNS_UPDATE); log.Info("Server configuration for ddns.update policy: " + policy); if ((policy == null) || policy.Contains("none")) { log.Info("Server configuration for ddns.update policy is null or 'none'." + " No DDNS updates performed."); replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates _replyMsg.PutDhcpOption(replyFqdnOption); return; } if (clientFqdnOption.GetNoUpdateBit() && policy.Contains("honorNoUpdate")) { log.Info("Client FQDN NoUpdate flag set. Server configured to honor request." + " No DDNS updates performed."); replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates _replyMsg.PutDhcpOption(replyFqdnOption); //TODO: RFC 4704 Section 6.1 // ...the server SHOULD delete any RRs that it previously added // via DNS updates for the client. return; } if (!clientFqdnOption.GetUpdateABit() && policy.Contains("honorNoA")) { log.Info("Client FQDN NoA flag set. Server configured to honor request." + " No FORWARD DDNS updates performed."); doForwardUpdate = false; } else { replyFqdnOption.SetUpdateABit(true); // server will do update if (!clientFqdnOption.GetUpdateABit()) { replyFqdnOption.SetOverrideBit(true); // tell client that we overrode request flag } } if (!String.IsNullOrEmpty(domain)) { log.Info("Server configuration for domain policy: " + domain); // if there is a configured domain, then replace the domain provide by the client int dot = fqdn.IndexOf('.'); if (dot > 0) { fqdn = fqdn.Substring(0, dot + 1) + domain; } else { fqdn = fqdn + "." + domain; } replyFqdnOption.SetDomainName(fqdn); } // since the client DID send option 81, return it in the reply _replyMsg.PutDhcpOption(replyFqdnOption); } else { // The client did not send an FQDN option, so we'll try to formulate the FQDN // from the hostname option combined with the DDNS_DOMAIN policy setting. // A replyFqdnOption is fabricated to be stored with the binding for use // with the release/expire binding processing to remove the DDNS entry. replyFqdnOption = new DhcpV4ClientFqdnOption(); fqdn = hostnameOption.GetString(); if (!String.IsNullOrEmpty(domain)) { log.Info("Server configuration for domain policy: " + domain); fqdn = fqdn + "." + domain; // since the client did NOT send option 81, do not put // the fabricated fqdnOption into the reply packet // but set the option so that is can be used below // when storing the fqdnOption to the database, so // that it can be used if/when the lease expires replyFqdnOption.SetDomainName(fqdn); // server will do the A record update, so set the flag // for the option stored in the database, so server will // remove the A record when the lease expires replyFqdnOption.SetUpdateABit(true); } else { log.Error("No DDNS domain configured. No DDNS udpates performed."); replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates _replyMsg.PutDhcpOption(replyFqdnOption); return; } } if (sendUpdates) { foreach (Binding binding in _bindings) { if (binding.GetState() == Binding.COMMITTED) { HashSet <BindingObject> bindingObjs = binding.GetBindingObjects(); if (bindingObjs != null) { foreach (var bindingObj in bindingObjs) { V4BindingAddress bindingAddr = (V4BindingAddress)bindingObj; DhcpConfigObject configObj = bindingAddr.GetConfigObj(); DdnsCallback ddnsComplete = new DhcpV4DdnsComplete(bindingAddr, replyFqdnOption); DdnsUpdater ddns = new DdnsUpdater(_requestMsg, _clientLink.GetLink(), configObj, bindingAddr.GetIpAddress(), fqdn, _requestMsg.GetChAddr(), configObj.GetValidLifetime(), doForwardUpdate, false, ddnsComplete); ddns.ProcessUpdates(); } } } } } }
protected void ProcessDdnsUpdates(bool sendUpdates) { DhcpV6ClientFqdnOption clientFqdnOption = ((DhcpV6ClientFqdnOption)(this.requestMsg.GetDhcpOption(DhcpConstants.V6OPTION_CLIENT_FQDN))); if ((clientFqdnOption == null)) { // TODO allow name generation? log.Debug("No Client FQDN option in request. Skipping DDNS update processing."); return; } bool includeFqdnOptionInReply = false; if (((this.requestMsg.GetRequestedOptionCodes() != null) && this.requestMsg.GetRequestedOptionCodes().Contains(DhcpConstants.V6OPTION_CLIENT_FQDN))) { // RFC 4704 section 6 says: // Servers MUST only include a Client FQDN option in ADVERTISE and REPLY // messages if the client included a Client FQDN option and the Client // FQDN option is requested by the Option Request option in the client's // message to which the server is responding. includeFqdnOptionInReply = true; } DhcpV6ClientFqdnOption replyFqdnOption = new DhcpV6ClientFqdnOption(); replyFqdnOption.SetDomainName(clientFqdnOption.GetDomainName()); replyFqdnOption.SetUpdateAaaaBit(false); replyFqdnOption.SetOverrideBit(false); replyFqdnOption.SetNoUpdateBit(false); string fqdn = clientFqdnOption.GetDomainName(); if (((fqdn == null) || (fqdn.Length <= 0))) { log.Error("Client FQDN option domain name is null/empty. No DDNS udpates performed."); if (includeFqdnOptionInReply) { replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates this.replyMsg.PutDhcpOption(replyFqdnOption); } return; } String policy = DhcpServerPolicies.EffectivePolicy(this.requestMsg, this.clientLink.GetLink(), Property.DDNS_UPDATE); log.Info(("Server configuration for ddns.update policy: " + policy)); if (((policy == null) || policy.ToLower() == "none")) { log.Info(("Server configuration for ddns.update policy is null or \'none\'." + " No DDNS updates performed.")); if (includeFqdnOptionInReply) { replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates this.replyMsg.PutDhcpOption(replyFqdnOption); } return; } if ((clientFqdnOption.GetNoUpdateBit() && policy.ToLower() == "honorNoUpdate".ToLower())) { log.Info(("Client FQDN NoUpdate flag set. Server configured to honor request." + " No DDNS updates performed.")); if (includeFqdnOptionInReply) { replyFqdnOption.SetNoUpdateBit(true); // tell client that server did no updates this.replyMsg.PutDhcpOption(replyFqdnOption); } // TODO: RFC 4704 Section 6.1 // ...the server SHOULD delete any RRs that it previously added // via DNS updates for the client. return; } bool doForwardUpdate = true; if ((!clientFqdnOption.GetUpdateAaaaBit() && policy.ToLower() == "honorNoAAAA".ToLower())) { log.Info(("Client FQDN NoAAAA flag set. Server configured to honor request." + " No FORWARD DDNS updates performed.")); doForwardUpdate = false; } else { replyFqdnOption.SetUpdateAaaaBit(true); // server will do update if (!clientFqdnOption.GetUpdateAaaaBit()) { replyFqdnOption.SetOverrideBit(true); } // tell client that we overrode request flag } string domain = DhcpServerPolicies.EffectivePolicy(this.clientLink.GetLink(), Property.DDNS_DOMAIN); if (((domain != null) && domain.Count() > 0)) { log.Info(("Server configuration for domain policy: " + domain)); // if there is a configured domain, then replace the domain provide by the client int dot = fqdn.IndexOf('.'); if ((dot > 0)) { fqdn = (fqdn.Substring(0, (dot + 1)) + domain); } else { fqdn = (fqdn + ("." + domain)); } replyFqdnOption.SetDomainName(fqdn); } if (includeFqdnOptionInReply) { this.replyMsg.PutDhcpOption(replyFqdnOption); } if (sendUpdates) { foreach (Binding binding in this.bindings) { if ((binding.GetState() == Binding.COMMITTED)) { HashSet <BindingObject> bindingObjs = binding.GetBindingObjects(); if ((bindingObjs != null)) { foreach (BindingObject bindingObj in bindingObjs) { V6BindingAddress bindingAddr = ((V6BindingAddress)(bindingObj)); DhcpConfigObject configObj = bindingAddr.GetConfigObj(); DdnsCallback ddnsComplete = new DhcpV6DdnsComplete(bindingAddr, replyFqdnOption); DdnsUpdater ddns = new DdnsUpdater(this.requestMsg, this.clientLink.GetLink(), configObj, bindingAddr.GetIpAddress(), fqdn, this.requestMsg.GetDhcpClientIdOption().GetDuid(), configObj.GetValidLifetime(), doForwardUpdate, false, ddnsComplete); ddns.ProcessUpdates(); } } } } } }