001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.server.dhcp.store;
021
022
023import java.net.InetAddress;
024import java.net.UnknownHostException;
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.Hashtable;
028import java.util.Iterator;
029import java.util.List;
030import java.util.Map;
031
032import javax.naming.Context;
033import javax.naming.NamingEnumeration;
034import javax.naming.NamingException;
035import javax.naming.directory.Attribute;
036import javax.naming.directory.Attributes;
037import javax.naming.directory.DirContext;
038import javax.naming.directory.InitialDirContext;
039import javax.naming.directory.SearchControls;
040import javax.naming.directory.SearchResult;
041
042import org.apache.directory.api.ldap.model.constants.SchemaConstants;
043import org.apache.directory.server.dhcp.DhcpException;
044import org.apache.directory.server.dhcp.messages.HardwareAddress;
045import org.apache.directory.server.dhcp.options.OptionsField;
046import org.apache.directory.server.dhcp.service.Lease;
047
048
049/**
050 * Very simple dummy/proof-of-concept implementation of a DhcpStore.
051 * 
052 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
053 */
054public class SimpleDhcpStore extends AbstractDhcpStore
055{
056    // a map of current leases
057    private Map leases = new HashMap();
058
059    private List subnets = new ArrayList();
060
061
062    //This will suppress PMD.AvoidUsingHardCodedIP warnings in this class
063    @SuppressWarnings("PMD.AvoidUsingHardCodedIP")
064    public SimpleDhcpStore()
065    {
066        try
067        {
068            subnets.add( new Subnet( InetAddress.getByName( "192.168.168.0" ),
069                InetAddress.getByName( "255.255.255.0" ), InetAddress.getByName( "192.168.168.159" ), InetAddress
070                    .getByName( "192.168.168.179" ) ) );
071        }
072        catch ( UnknownHostException e )
073        {
074            throw new RuntimeException( "Can't init", e );
075        }
076    }
077
078
079    protected DirContext getContext() throws NamingException
080    {
081        Hashtable env = new Hashtable();
082        env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
083        env.put( Context.PROVIDER_URL, "ldap://localhost:389/dc=tcat,dc=test" );
084
085        return new InitialDirContext( env );
086    }
087
088
089    /**
090     * @param hardwareAddress
091     * @param existingLease
092     * @return Lease
093     */
094    protected Lease findExistingLease( HardwareAddress hardwareAddress, Lease existingLease )
095    {
096        if ( leases.containsKey( hardwareAddress ) )
097        {
098            existingLease = ( Lease ) leases.get( hardwareAddress );
099        }
100
101        return existingLease;
102    }
103
104
105    /**
106     * @param hardwareAddress
107     * @return Host
108     * @throws DhcpException
109     */
110    protected Host findDesignatedHost( HardwareAddress hardwareAddress ) throws DhcpException
111    {
112        try
113        {
114            DirContext ctx = getContext();
115
116            try
117            {
118                String filter = "(&(objectclass=ipHost)(objectclass=ieee802Device)(macaddress={0}))";
119                SearchControls sc = new SearchControls();
120                sc.setCountLimit( 1 );
121                sc.setSearchScope( SearchControls.SUBTREE_SCOPE );
122                NamingEnumeration ne = ctx.search( "", filter, new Object[]
123                    { hardwareAddress.toString() }, sc );
124
125                if ( ne.hasMoreElements() )
126                {
127                    SearchResult sr = ( SearchResult ) ne.next();
128                    Attributes att = sr.getAttributes();
129                    Attribute ipHostNumberAttribute = att.get( "iphostnumber" );
130
131                    if ( ipHostNumberAttribute != null )
132                    {
133                        InetAddress clientAddress = InetAddress.getByName( ( String ) ipHostNumberAttribute.get() );
134                        Attribute cnAttribute = att.get( SchemaConstants.CN_AT );
135
136                        return new Host( cnAttribute != null ? ( String ) cnAttribute.get() : "unknown", clientAddress,
137                            hardwareAddress );
138                    }
139                }
140            }
141            catch ( Exception e )
142            {
143                throw new DhcpException( "Can't lookup lease", e );
144            }
145            finally
146            {
147                ctx.close();
148            }
149        }
150        catch ( NamingException e )
151        {
152            throw new DhcpException( "Can't lookup lease", e );
153        }
154
155        return null;
156    }
157
158
159    /**
160     * Find the subnet for the given client address.
161     * 
162     * @param clientAddress
163     * @return Subnet
164     */
165    protected Subnet findSubnet( InetAddress clientAddress )
166    {
167        for ( Iterator i = subnets.iterator(); i.hasNext(); )
168        {
169            Subnet subnet = ( Subnet ) i.next();
170
171            if ( subnet.contains( clientAddress ) )
172            {
173                return subnet;
174            }
175        }
176
177        return null;
178    }
179
180
181    /*
182     * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#updateLease(org.apache.directory.server.dhcp.service.Lease)
183     */
184    public void updateLease( Lease lease )
185    {
186        leases.put( lease.getHardwareAddress(), lease );
187    }
188
189
190    /*
191     * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#getOptions(org.apache.directory.server.dhcp.store.DhcpConfigElement)
192     */
193    protected OptionsField getOptions( DhcpConfigElement element )
194    {
195        // we don't have groups, classes, etc. yet.
196        return element.getOptions();
197    }
198
199
200    /*
201     * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#getProperties(org.apache.directory.server.dhcp.store.DhcpConfigElement)
202     */
203    protected Map getProperties( DhcpConfigElement element )
204    {
205        // we don't have groups, classes, etc. yet.
206        return element.getProperties();
207    }
208}