/* * Copyright 2009-2014 Jagornet Technologies, LLC. All Rights Reserved. * * This software is the proprietary information of Jagornet Technologies, LLC. * Use is subject to license terms. * */ /* * This file BaseAddrBindingManager.java is part of Jagornet DHCP. * * Jagornet DHCP is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jagornet DHCP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jagornet DHCP. If not, see <http://www.gnu.org/licenses/>. * */ package com.jagornet.dhcp.server.request.binding; import java.util.Collection; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jagornet.dhcp.db.IaAddress; import com.jagornet.dhcp.db.IdentityAssoc; import com.jagornet.dhcp.server.config.DhcpServerPolicies; import com.jagornet.dhcp.server.config.DhcpServerPolicies.Property; import com.jagornet.dhcp.util.Util; /** * The Class BaseAddressBindingManager. * Second-level abstract class that extends BaseBindingManager to * add behavior specific to address bindings. * * @author A. Gregory Rabil */ public abstract class BaseAddrBindingManager extends BaseBindingManager { private static Logger log = LoggerFactory.getLogger(BaseAddrBindingManager.class); public BaseAddrBindingManager() { super(); } protected 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); } /** * Perform the DDNS delete processing when a lease is released or expired. * * @param iaAddr the released or expired IaAddress */ protected abstract void ddnsDelete(IdentityAssoc ia, IaAddress iaAddr); /** * Return the IA type for this binding. This is a hack to allow consolidated * code in this base class (i.e. expireAddresses) for use by the subclasses. * * @return */ protected abstract byte getIaType(); /** * 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. * * @param iaAddr the IaAddress to be released */ public void releaseIaAddress(IdentityAssoc ia, IaAddress iaAddr) { try { log.info("Releasing address: " + iaAddr.getIpAddress().getHostAddress()); 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(null); iaAddr.setPreferredEndTime(null); iaAddr.setValidEndTime(null); iaAddr.setState(IaAddress.RELEASED); iaMgr.updateIaAddr(iaAddr); log.info("Address released: " + iaAddr.toString()); } } catch (Exception ex) { log.error("Failed to release address", ex); } } /** * Decline an IaAddress. This is done when the client declines an address. * Perform a DDNS delete just in case it was already registered, then mark * the address as declined (unavailable). * * @param iaAddr the declined IaAddress. */ public void declineIaAddress(IdentityAssoc ia, IaAddress iaAddr) { try { log.info("Declining address: " + iaAddr.getIpAddress().getHostAddress()); ddnsDelete(ia, iaAddr); iaAddr.setStartTime(null); iaAddr.setPreferredEndTime(null); iaAddr.setValidEndTime(null); iaAddr.setState(IaAddress.DECLINED); iaMgr.updateIaAddr(iaAddr); log.info("Address declined: " + iaAddr.toString()); } catch (Exception ex) { log.error("Failed to decline address", ex); } } /** * Callback from the ExpireTimerTask started when the lease was granted. * * @param iaAddr the ia addr */ public void expireIaAddress(IdentityAssoc ia, IaAddress iaAddr) { try { log.info("Expiring: " + iaAddr.toString()); ddnsDelete(ia, iaAddr); if (DhcpServerPolicies.globalPolicyAsBoolean( Property.BINDING_MANAGER_DELETE_OLD_BINDINGS)) { log.debug("Deleting expired address: " + iaAddr.getIpAddress()); 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(null); iaAddr.setPreferredEndTime(null); iaAddr.setValidEndTime(null); iaAddr.setState(IaAddress.EXPIRED); log.debug("Updating expired address: " + iaAddr.getIpAddress()); iaMgr.updateIaAddr(iaAddr); } } catch (Exception ex) { log.error("Failed to expire address", ex); } } /** * Callback from the ReaperTimerTask started when the BindingManager initialized. * Find any expired addresses as of now, and expire them already. */ public void expireAddresses() { List<IdentityAssoc> expiredIAs = iaMgr.findExpiredIAs(getIaType()); if ((expiredIAs != null) && !expiredIAs.isEmpty()) { log.info("Found " + expiredIAs.size() + " expired bindings of type: " + IdentityAssoc.iaTypeToString(getIaType())); for (IdentityAssoc ia : expiredIAs) { Collection<? extends IaAddress> expiredAddrs = ia.getIaAddresses(); if ((expiredAddrs != null) && !expiredAddrs.isEmpty()) { // due to the implementation of findExpiredIAs, each IdentityAssoc // SHOULD have only one IaAddress within it to be expired log.info("Found " + expiredAddrs.size() + " expired bindings for IA: " + "duid=" + Util.toHexString(ia.getDuid()) + " iaid=" + ia.getIaid()); for (IaAddress iaAddress : expiredAddrs) { expireIaAddress(ia, iaAddress); } } } } } /** * The Class ReaperTimerTask. */ class ReaperTimerTask extends TimerTask { /* (non-Javadoc) * @see java.util.TimerTask#run() */ @Override public void run() { // log.debug("Expiring addresses..."); expireAddresses(); } } }