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     */
020    package org.apache.directory.server.dhcp.store;
021    
022    
023    import java.net.InetAddress;
024    import java.net.UnknownHostException;
025    import java.util.ArrayList;
026    import java.util.HashMap;
027    import java.util.Hashtable;
028    import java.util.Iterator;
029    import java.util.List;
030    import java.util.Map;
031    
032    import javax.naming.Context;
033    import javax.naming.NamingEnumeration;
034    import javax.naming.NamingException;
035    import javax.naming.directory.Attribute;
036    import javax.naming.directory.Attributes;
037    import javax.naming.directory.DirContext;
038    import javax.naming.directory.InitialDirContext;
039    import javax.naming.directory.SearchControls;
040    import javax.naming.directory.SearchResult;
041    
042    import org.apache.directory.server.dhcp.DhcpException;
043    import org.apache.directory.server.dhcp.messages.HardwareAddress;
044    import org.apache.directory.server.dhcp.options.OptionsField;
045    import org.apache.directory.server.dhcp.service.Lease;
046    import org.apache.directory.shared.ldap.constants.SchemaConstants;
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     * @version $Rev: 545042 $, $Date: 2007-06-06 22:32:01 -0500 (Mi, 06 Jun 2007) $
054     */
055    public class SimpleDhcpStore extends AbstractDhcpStore
056    {
057        // private static final String DEFAULT_INITIAL_CONTEXT_FACTORY =
058        // "org.apache.directory.server.core.jndi.CoreContextFactory";
059    
060        // a map of current leases
061        private Map leases = new HashMap();
062    
063        private List subnets = new ArrayList();
064    
065    
066        public SimpleDhcpStore()
067        {
068            try
069            {
070                subnets.add( new Subnet( InetAddress.getByName( "192.168.168.0" ),
071                    InetAddress.getByName( "255.255.255.0" ), InetAddress.getByName( "192.168.168.159" ), InetAddress
072                        .getByName( "192.168.168.179" ) ) );
073            }
074            catch ( UnknownHostException e )
075            {
076                throw new RuntimeException( "Can't init", e );
077            }
078        }
079    
080    
081        protected DirContext getContext() throws NamingException
082        {
083            Hashtable env = new Hashtable();
084            env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
085            // env.put( Context.INITIAL_CONTEXT_FACTORY,
086            // DEFAULT_INITIAL_CONTEXT_FACTORY );
087            env.put( Context.PROVIDER_URL, "ldap://localhost:389/dc=tcat,dc=test" );
088    
089            return new InitialDirContext( env );
090        }
091    
092    
093        /**
094         * @param hardwareAddress
095         * @param existingLease
096         * @return Lease
097         */
098        protected Lease findExistingLease( HardwareAddress hardwareAddress, Lease existingLease )
099        {
100            if ( leases.containsKey( hardwareAddress ) )
101                existingLease = ( Lease ) leases.get( hardwareAddress );
102            return existingLease;
103        }
104    
105    
106        /**
107         * @param hardwareAddress
108         * @return Host
109         * @throws DhcpException
110         */
111        protected Host findDesignatedHost( HardwareAddress hardwareAddress ) throws DhcpException
112        {
113            try
114            {
115                DirContext ctx = getContext();
116                
117                try
118                {
119                    String filter = "(&(objectclass=ipHost)(objectclass=ieee802Device)(macaddress={0}))";
120                    SearchControls sc = new SearchControls();
121                    sc.setCountLimit( 1 );
122                    sc.setSearchScope( SearchControls.SUBTREE_SCOPE );
123                    NamingEnumeration ne = ctx.search( "", filter, new Object[]
124                        { hardwareAddress.toString() }, sc );
125    
126                    if ( ne.hasMoreElements() )
127                    {
128                        SearchResult sr = ( SearchResult ) ne.next();
129                        Attributes att = sr.getAttributes();
130                        Attribute ipHostNumberAttribute = att.get( "iphostnumber" );
131                        
132                        if ( ipHostNumberAttribute != null )
133                        {
134                            InetAddress clientAddress = InetAddress.getByName( ( String ) ipHostNumberAttribute.get() );
135                            Attribute cnAttribute = att.get( SchemaConstants.CN_AT );
136                            
137                            return new Host( cnAttribute != null ? ( String ) cnAttribute.get() : "unknown", clientAddress,
138                                hardwareAddress );
139                        }
140                    }
141                }
142                catch ( Exception e )
143                {
144                    throw new DhcpException( "Can't lookup lease", e );
145                }
146                finally
147                {
148                    ctx.close();
149                }
150            }
151            catch ( NamingException e )
152            {
153                throw new DhcpException( "Can't lookup lease", e );
154            }
155    
156            return null;
157        }
158    
159    
160        /**
161         * Find the subnet for the given client address.
162         * 
163         * @param clientAddress
164         * @return Subnet
165         */
166        protected Subnet findSubnet( InetAddress clientAddress )
167        {
168            for ( Iterator i = subnets.iterator(); i.hasNext(); )
169            {
170                Subnet subnet = ( Subnet ) i.next();
171                if ( subnet.contains( clientAddress ) )
172                    return subnet;
173            }
174            return null;
175        }
176    
177    
178        /*
179         * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#updateLease(org.apache.directory.server.dhcp.service.Lease)
180         */
181        public void updateLease( Lease lease )
182        {
183            leases.put( lease.getHardwareAddress(), lease );
184        }
185    
186    
187        /*
188         * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#getOptions(org.apache.directory.server.dhcp.store.DhcpConfigElement)
189         */
190        protected OptionsField getOptions( DhcpConfigElement element )
191        {
192            // we don't have groups, classes, etc. yet.
193            return element.getOptions();
194        }
195    
196    
197        /*
198         * @see org.apache.directory.server.dhcp.store.AbstractDhcpStore#getProperties(org.apache.directory.server.dhcp.store.DhcpConfigElement)
199         */
200        protected Map getProperties( DhcpConfigElement element )
201        {
202            // we don't have groups, classes, etc. yet.
203            return element.getProperties();
204        }
205    }