blob: 971dd3fe2aa0fb705f58d34d07c358b7355c5c5d [file] [log] [blame]
/***********************************************************************
* Copyright (c) 2000-2006 The Apache Software Foundation. *
* All rights reserved. *
* ------------------------------------------------------------------- *
* Licensed under the Apache License, Version 2.0 (the "License"); you *
* may not use this file except in compliance with the License. You *
* may obtain a copy of the License at: *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, software *
* distributed under the License is distributed on an "AS IS" BASIS, *
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
* implied. See the License for the specific language governing *
* permissions and limitations under the License. *
***********************************************************************/
package org.apache.qpid.util;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class NetMatcher
{
private ArrayList networks;
public void initInetNetworks(final Collection nets)
{
networks = new ArrayList();
for (Iterator iter = nets.iterator(); iter.hasNext(); )
{
try
{
InetNetwork net = InetNetwork.getFromString((String) iter.next());
if (!networks.contains(net))
{
networks.add(net);
}
}
catch (java.net.UnknownHostException uhe)
{
log("Cannot resolve address: " + uhe.getMessage());
}
}
networks.trimToSize();
}
public void initInetNetworks(final String[] nets)
{
networks = new ArrayList();
for (int i = 0; i < nets.length; i++)
{
try
{
InetNetwork net = InetNetwork.getFromString(nets[i]);
if (!networks.contains(net))
{
networks.add(net);
}
}
catch (java.net.UnknownHostException uhe)
{
log("Cannot resolve address: " + uhe.getMessage());
}
}
networks.trimToSize();
}
public boolean matchInetNetwork(final String hostIP)
{
InetAddress ip = null;
try
{
ip = InetAddress.getByName(hostIP);
}
catch (java.net.UnknownHostException uhe)
{
log("Cannot resolve address for " + hostIP + ": " + uhe.getMessage());
}
boolean sameNet = false;
if (ip != null)
{
for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
{
InetNetwork network = (InetNetwork) iter.next();
sameNet = network.contains(ip);
}
}
return sameNet;
}
public boolean matchInetNetwork(final InetAddress ip)
{
boolean sameNet = false;
for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
{
InetNetwork network = (InetNetwork) iter.next();
sameNet = network.contains(ip);
}
return sameNet;
}
public NetMatcher()
{
}
public NetMatcher(final String[] nets)
{
initInetNetworks(nets);
}
public NetMatcher(final Collection nets)
{
initInetNetworks(nets);
}
public String toString() {
return networks.toString();
}
protected void log(String s) { }
}
class InetNetwork
{
/*
* Implements network masking, and is compatible with RFC 1518 and
* RFC 1519, which describe CIDR: Classless Inter-Domain Routing.
*/
private InetAddress network;
private InetAddress netmask;
public InetNetwork(InetAddress ip, InetAddress netmask)
{
network = maskIP(ip, netmask);
this.netmask = netmask;
}
public boolean contains(final String name) throws java.net.UnknownHostException
{
return network.equals(maskIP(InetAddress.getByName(name), netmask));
}
public boolean contains(final InetAddress ip)
{
return network.equals(maskIP(ip, netmask));
}
public String toString()
{
return network.getHostAddress() + "/" + netmask.getHostAddress();
}
public int hashCode()
{
return maskIP(network, netmask).hashCode();
}
public boolean equals(Object obj)
{
return (obj != null) && (obj instanceof InetNetwork) &&
((((InetNetwork)obj).network.equals(network)) && (((InetNetwork)obj).netmask.equals(netmask)));
}
public static InetNetwork getFromString(String netspec) throws java.net.UnknownHostException
{
if (netspec.endsWith("*"))
{
netspec = normalizeFromAsterisk(netspec);
}
else
{
int iSlash = netspec.indexOf('/');
if (iSlash == -1)
{
netspec += "/255.255.255.255";
}
else if (netspec.indexOf('.', iSlash) == -1)
{
netspec = normalizeFromCIDR(netspec);
}
}
return new InetNetwork(InetAddress.getByName(netspec.substring(0, netspec.indexOf('/'))),
InetAddress.getByName(netspec.substring(netspec.indexOf('/') + 1)));
}
public static InetAddress maskIP(final byte[] ip, final byte[] mask)
{
try
{
return getByAddress(new byte[]
{
(byte) (mask[0] & ip[0]),
(byte) (mask[1] & ip[1]),
(byte) (mask[2] & ip[2]),
(byte) (mask[3] & ip[3])
});
}
catch(Exception _) {}
{
return null;
}
}
public static InetAddress maskIP(final InetAddress ip, final InetAddress mask)
{
return maskIP(ip.getAddress(), mask.getAddress());
}
/*
* This converts from an uncommon "wildcard" CIDR format
* to "address + mask" format:
*
* * => 000.000.000.0/000.000.000.0
* xxx.* => xxx.000.000.0/255.000.000.0
* xxx.xxx.* => xxx.xxx.000.0/255.255.000.0
* xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0
*/
static private String normalizeFromAsterisk(final String netspec)
{
String[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" };
char[] srcb = netspec.toCharArray();
int octets = 0;
for (int i = 1; i < netspec.length(); i++)
{
if (srcb[i] == '.')
{
octets++;
}
}
return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]);
}
/*
* RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR)
* This converts from "prefix + prefix-length" format to
* "address + mask" format, e.g. from xxx.xxx.xxx.xxx/yy
* to xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy.
*/
static private String normalizeFromCIDR(final String netspec)
{
final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1));
final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1);
return netspec.substring(0, netspec.indexOf('/') + 1) +
Integer.toString(mask >> 24 & 0xFF, 10) + "." +
Integer.toString(mask >> 16 & 0xFF, 10) + "." +
Integer.toString(mask >> 8 & 0xFF, 10) + "." +
Integer.toString(mask >> 0 & 0xFF, 10);
}
private static java.lang.reflect.Method getByAddress = null;
static {
try {
Class inetAddressClass = Class.forName("java.net.InetAddress");
Class[] parameterTypes = { byte[].class };
getByAddress = inetAddressClass.getMethod("getByAddress", parameterTypes);
} catch (Exception e) {
getByAddress = null;
}
}
private static InetAddress getByAddress(byte[] ip) throws java.net.UnknownHostException
{
InetAddress addr = null;
if (getByAddress != null)
{
try
{
addr = (InetAddress) getByAddress.invoke(null, new Object[] { ip });
}
catch (IllegalAccessException e)
{
}
catch (java.lang.reflect.InvocationTargetException e)
{
}
}
if (addr == null) {
addr = InetAddress.getByName
(
Integer.toString(ip[0] & 0xFF, 10) + "." +
Integer.toString(ip[1] & 0xFF, 10) + "." +
Integer.toString(ip[2] & 0xFF, 10) + "." +
Integer.toString(ip[3] & 0xFF, 10)
);
}
return addr;
}
}