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.Arrays;
026    
027    
028    /**
029     * The definition of a Subnet.
030     * 
031     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
032     * @version $Rev: 545042 $, $Date: 2007-06-06 22:32:01 -0500 (Mi, 06 Jun 2007) $
033     */
034    public class Subnet extends DhcpConfigElement
035    {
036        /** the subnet's address */
037        private final InetAddress address;
038    
039        /** the subnet's netmask */
040        private final InetAddress netmask;
041    
042        /** the subnet's range: minimum address in range */
043        private InetAddress rangeMin;
044    
045        /** the subnet's range: maximum address in range */
046        private InetAddress rangeMax;
047    
048    
049        public Subnet(InetAddress address, InetAddress netmask, InetAddress rangeMin, InetAddress rangeMax)
050        {
051            // mask address to match subnet
052            byte masked[] = netmask.getAddress();
053            byte addrBytes[] = netmask.getAddress();
054            for ( int i = 0; i < addrBytes.length; i++ )
055                masked[i] &= addrBytes[i];
056    
057            if ( !Arrays.equals( masked, addrBytes ) )
058                try
059                {
060                    address = InetAddress.getByAddress( masked );
061                }
062                catch ( UnknownHostException e )
063                {
064                    // ignore - doesn't happen.
065                }
066    
067            this.address = address;
068            this.netmask = netmask;
069            this.rangeMin = rangeMin;
070            this.rangeMax = rangeMax;
071        }
072    
073    
074        public InetAddress getAddress()
075        {
076            return address;
077        }
078    
079    
080        public InetAddress getNetmask()
081        {
082            return netmask;
083        }
084    
085    
086        public InetAddress getRangeMax()
087        {
088            return rangeMax;
089        }
090    
091    
092        public void setRangeMax( InetAddress rangeMax )
093        {
094            this.rangeMax = rangeMax;
095        }
096    
097    
098        public InetAddress getRangeMin()
099        {
100            return rangeMin;
101        }
102    
103    
104        public void setRangeMin( InetAddress rangeMin )
105        {
106            this.rangeMin = rangeMin;
107        }
108    
109    
110        /**
111         * Check whether the given client address resides within this subnet and
112         * possibly range.
113         * 
114         * @param clientAddress
115         * @return boolean
116         */
117        public boolean contains( InetAddress clientAddress )
118        {
119            // check address type
120            if ( !clientAddress.getClass().equals( address.getClass() ) )
121                return false;
122    
123            byte client[] = clientAddress.getAddress();
124            byte masked[] = netmask.getAddress();
125            for ( int i = 0; i < masked.length; i++ )
126                masked[i] &= client[i];
127    
128            return Arrays.equals( masked, address.getAddress() );
129        }
130    
131    
132        /**
133         * Check whether the specified address is within the range for this subnet.
134         * 
135         * @param clientAddress
136         * @return boolean
137         */
138        public boolean isInRange( InetAddress clientAddress )
139        {
140            byte client[] = clientAddress.getAddress();
141            byte masked[] = netmask.getAddress();
142            for ( int i = 0; i < masked.length; i++ )
143                masked[i] &= client[i];
144    
145            if ( null != rangeMin )
146                if ( arrayComp( masked, rangeMin.getAddress() ) < 0 )
147                    return false;
148    
149            if ( null != rangeMin )
150                if ( arrayComp( masked, rangeMax.getAddress() ) > 0 )
151                    return false;
152    
153            return true;
154        }
155    
156    
157        private static int arrayComp( byte a1[], byte a2[] )
158        {
159            for ( int i = 0; i < a1.length && i < a2.length; i++ )
160            {
161                if ( a1[i] != a2[i] )
162                    return ( a1[i] & 0xff ) - ( a2[i] & 0xff );
163            }
164    
165            return a1.length - a2.length;
166        }
167    }