/* * 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 V4AddressBindingPool.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.io.IOException; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Timer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.jagornet.dhcp.db.IaAddress; import com.jagornet.dhcp.option.v4.DhcpV4ConfigOptions; import com.jagornet.dhcp.server.config.DhcpServerConfigException; import com.jagornet.dhcp.server.config.DhcpServerPolicies; import com.jagornet.dhcp.server.config.DhcpV4OptionConfigObject; import com.jagornet.dhcp.server.config.DhcpServerPolicies.Property; import com.jagornet.dhcp.util.Util; import com.jagornet.dhcp.xml.FiltersType; import com.jagornet.dhcp.xml.LinkFilter; import com.jagornet.dhcp.xml.PoliciesType; import com.jagornet.dhcp.xml.V4AddressPool; /** * The Class V4AddressBindingPool. A wrapper class for a configured V4AddressPool * for handling runtime activity for that pool. * * @author A. Gregory Rabil */ public class V4AddressBindingPool implements BindingPool, DhcpV4OptionConfigObject { private static Logger log = LoggerFactory.getLogger(V4AddressBindingPool.class); protected Range range; protected FreeList freeList; protected long leasetime; protected V4AddressPool pool; protected DhcpV4ConfigOptions v4ConfigOptions; protected LinkFilter linkFilter; protected Timer reaper; /** * Instantiates a new binding pool. * * @param pool the pool * * @throws DhcpServerConfigException if the AddressPool definition is invalid */ public V4AddressBindingPool(V4AddressPool pool) throws DhcpServerConfigException { this.pool = pool; try { this.range = new Range(pool.getRange()); } catch (NumberFormatException ex) { log.error("Invalid AddressPool definition", ex); throw new DhcpServerConfigException("Invalid AddressPool definition", ex); } catch (UnknownHostException ex) { log.error("Invalid AddressPool definition", ex); throw new DhcpServerConfigException("Invalid AddressPool definition", ex); } freeList = new FreeList(new BigInteger(range.getStartAddress().getAddress()), new BigInteger(range.getEndAddress().getAddress())); reaper = new Timer(pool.getRange()+"_Reaper"); v4ConfigOptions = new DhcpV4ConfigOptions(pool.getConfigOptions()); } /** * Gets the range. * * @return the range */ public Range getRange() { return range; } /** * Gets the next available address in this address pool. * * @return the next available address */ public InetAddress getNextAvailableAddress() { if (freeList != null) { BigInteger next = freeList.getNextFree(); if (next != null) { try { InetAddress ip = InetAddress.getByAddress(next.toByteArray()); int pingCheckTimeout = DhcpServerPolicies.globalPolicyAsInt(Property.V4_PINGCHECK_TIMEOUT); if (pingCheckTimeout > 0) { try { if (ip.isReachable(pingCheckTimeout)) { log.warn("Next free address answered ping check: " + ip.getHostAddress()); setUsed(ip); return getNextAvailableAddress(); // try again } } catch (IOException ex) { log.error("Failed to perform v4 ping check: " + ex); } } return ip; } catch (UnknownHostException ex) { log.error("Unable to build IPv4 address from next free: " + ex); } } } return null; } /** * Sets an IP address in this address pool as used. * * @param addr the address to set used */ public void setUsed(InetAddress addr) { if (contains(addr)) { freeList.setUsed(new BigInteger(addr.getAddress())); } } /** * Sets an IP address in this address pool as free. * * @param addr the address to set free */ public void setFree(InetAddress addr) { if (contains(addr)) { freeList.setFree(new BigInteger(addr.getAddress())); } } /** * Start expire timer task. * * @param iaAddr the ia addr * @param secsUntilExpiration the secs until expiration */ public void startExpireTimerTask(IaAddress iaAddr, long secsUntilExpiration) { // convert delay from seconds (lifetime) --> milliseconds (delay) // reaper.schedule(new ExpireTimerTask(iaAddr), secsUntilExpiration*1000); } /** * Test if the given address is contained within this address pool. * * @param addr the address to test for containment in this address pool * * @return true, if successful */ public boolean contains(InetAddress addr) { if ((Util.compareInetAddrs(addr, range.getStartAddress()) >= 0) && (Util.compareInetAddrs(addr, range.getEndAddress()) <= 0)) { return true; } return false; } /** * Gets the start address. * * @return the start address */ public InetAddress getStartAddress() { return range.getStartAddress(); } /** * Sets the start address. * * @param startAddress the new start address */ public void setStartAddress(InetAddress startAddress) { range.setEndAddress(startAddress); } /** * Gets the end address. * * @return the end address */ public InetAddress getEndAddress() { return range.getEndAddress(); } /** * Sets the end address. * * @param endAddress the new end address */ public void setEndAddress(InetAddress endAddress) { range.setEndAddress(endAddress); } /** * Gets the leasetime. * * @return the leasetime */ public long getLeasetime() { return leasetime; } /** * Gets the leasetime ms. * * @return the leasetime ms */ public long getLeasetimeMs() { return leasetime*1000; } /** * Sets the leasetime. * * @param leasetime the new leasetime */ public void setLeasetime(long leasetime) { this.leasetime = leasetime; } /** * Gets the pool. * * @return the pool */ public V4AddressPool getV4AddressPool() { return pool; } /** * Sets the pool. * * @param pool the new pool */ public void setV4AddressPool(V4AddressPool pool) { this.pool = pool; } /** * Gets the link filter. * * @return the link filter */ public LinkFilter getLinkFilter() { return linkFilter; } /** * Sets the link filter. * * @param linkFilter the new link filter */ public void setLinkFilter(LinkFilter linkFilter) { this.linkFilter = linkFilter; } public DhcpV4ConfigOptions getV4ConfigOptions() { return v4ConfigOptions; } public void setV4ConfigOptions(DhcpV4ConfigOptions v4ConfigOptions) { this.v4ConfigOptions = v4ConfigOptions; } public String toString() { return range.getStartAddress().getHostAddress() + "-" + range.getEndAddress().getHostAddress(); } public String freeListToString() { return freeList.toString(); } @Override public long getPreferredLifetime() { // TODO: check this overloaded use of v6 interface return getLeasetime(); } @Override public long getValidLifetime() { // TODO: check this overloaded use of v6 interface return getLeasetime(); } @Override public long getPreferredLifetimeMs() { // TODO: check this overloaded use of v6 interface return getLeasetimeMs(); } @Override public long getValidLifetimeMs() { // TODO: check this overloaded use of v6 interface return getLeasetimeMs(); } @Override public FiltersType getFilters() { if (pool != null) return pool.getFilters(); return null; } @Override public PoliciesType getPolicies() { if (pool != null) return pool.getPolicies(); return null; } public BigInteger getSize() { return range.size(); } }