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