| /*********************************************************************** |
| * 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; |
| } |
| } |