1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
18 package org.apache.james.util;
19
20 import java.net.InetAddress;
21 import java.util.Collection;
22 import java.util.ArrayList;
23 import java.util.Iterator;
24
25 public class NetMatcher
26 {
27 private ArrayList networks;
28
29 public void initInetNetworks(final Collection nets)
30 {
31 networks = new ArrayList();
32 for (Iterator iter = nets.iterator(); iter.hasNext(); ) try
33 {
34 InetNetwork net = InetNetwork.getFromString((String) iter.next());
35 if (!networks.contains(net)) networks.add(net);
36 }
37 catch (java.net.UnknownHostException uhe)
38 {
39 log("Cannot resolve address: " + uhe.getMessage());
40 }
41 networks.trimToSize();
42 }
43
44 public void initInetNetworks(final String[] nets)
45 {
46 networks = new ArrayList();
47 for (int i = 0; i < nets.length; i++) try
48 {
49 InetNetwork net = InetNetwork.getFromString(nets[i]);
50 if (!networks.contains(net)) networks.add(net);
51 }
52 catch (java.net.UnknownHostException uhe)
53 {
54 log("Cannot resolve address: " + uhe.getMessage());
55 }
56 networks.trimToSize();
57 }
58
59 public boolean matchInetNetwork(final String hostIP)
60 {
61 InetAddress ip = null;
62
63 try
64 {
65 ip = org.apache.james.dnsserver.DNSServer.getByName(hostIP);
66 }
67 catch (java.net.UnknownHostException uhe)
68 {
69 log("Cannot resolve address for " + hostIP + ": " + uhe.getMessage());
70 }
71
72 boolean sameNet = false;
73
74 if (ip != null) for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
75 {
76 InetNetwork network = (InetNetwork) iter.next();
77 sameNet = network.contains(ip);
78 }
79 return sameNet;
80 }
81
82 public boolean matchInetNetwork(final InetAddress ip)
83 {
84 boolean sameNet = false;
85
86 for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); )
87 {
88 InetNetwork network = (InetNetwork) iter.next();
89 sameNet = network.contains(ip);
90 }
91 return sameNet;
92 }
93
94 public NetMatcher()
95 {
96 }
97
98 public NetMatcher(final String[] nets)
99 {
100 initInetNetworks(nets);
101 }
102
103 public NetMatcher(final Collection nets)
104 {
105 initInetNetworks(nets);
106 }
107
108 public String toString() {
109 return networks.toString();
110 }
111
112 protected void log(String s) { }
113 }
114
115 class InetNetwork
116 {
117
118
119
120
121
122 private InetAddress network;
123 private InetAddress netmask;
124
125 public InetNetwork(InetAddress ip, InetAddress netmask)
126 {
127 network = maskIP(ip, netmask);
128 this.netmask = netmask;
129 }
130
131 public boolean contains(final String name) throws java.net.UnknownHostException
132 {
133 return network.equals(maskIP(org.apache.james.dnsserver.DNSServer.getByName(name), netmask));
134 }
135
136 public boolean contains(final InetAddress ip)
137 {
138 return network.equals(maskIP(ip, netmask));
139 }
140
141 public String toString()
142 {
143 return network.getHostAddress() + "/" + netmask.getHostAddress();
144 }
145
146 public int hashCode()
147 {
148 return maskIP(network, netmask).hashCode();
149 }
150
151 public boolean equals(Object obj)
152 {
153 return (obj != null) && (obj instanceof InetNetwork) &&
154 ((((InetNetwork)obj).network.equals(network)) && (((InetNetwork)obj).netmask.equals(netmask)));
155 }
156
157 public static InetNetwork getFromString(String netspec) throws java.net.UnknownHostException
158 {
159 if (netspec.endsWith("*")) netspec = normalizeFromAsterisk(netspec);
160 else
161 {
162 int iSlash = netspec.indexOf('/');
163 if (iSlash == -1) netspec += "/255.255.255.255";
164 else if (netspec.indexOf('.', iSlash) == -1) netspec = normalizeFromCIDR(netspec);
165 }
166
167 return new InetNetwork(org.apache.james.dnsserver.DNSServer.getByName(netspec.substring(0, netspec.indexOf('/'))),
168 org.apache.james.dnsserver.DNSServer.getByName(netspec.substring(netspec.indexOf('/') + 1)));
169 }
170
171 public static InetAddress maskIP(final byte[] ip, final byte[] mask)
172 {
173 try
174 {
175 return getByAddress(new byte[]
176 {
177 (byte) (mask[0] & ip[0]),
178 (byte) (mask[1] & ip[1]),
179 (byte) (mask[2] & ip[2]),
180 (byte) (mask[3] & ip[3])
181 });
182 }
183 catch(Exception _) {}
184 {
185 return null;
186 }
187 }
188
189 public static InetAddress maskIP(final InetAddress ip, final InetAddress mask)
190 {
191 return maskIP(ip.getAddress(), mask.getAddress());
192 }
193
194
195
196
197
198
199
200
201
202
203 static private String normalizeFromAsterisk(final String netspec)
204 {
205 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" };
206 char[] srcb = netspec.toCharArray();
207 int octets = 0;
208 for (int i = 1; i < netspec.length(); i++) {
209 if (srcb[i] == '.') octets++;
210 }
211 return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]);
212 }
213
214
215
216
217
218
219
220 static private String normalizeFromCIDR(final String netspec)
221 {
222 final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1));
223 final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1);
224
225 return netspec.substring(0, netspec.indexOf('/') + 1) +
226 Integer.toString(mask >> 24 & 0xFF, 10) + "." +
227 Integer.toString(mask >> 16 & 0xFF, 10) + "." +
228 Integer.toString(mask >> 8 & 0xFF, 10) + "." +
229 Integer.toString(mask >> 0 & 0xFF, 10);
230 }
231
232 private static java.lang.reflect.Method getByAddress = null;
233
234 static {
235 try {
236 Class inetAddressClass = Class.forName("java.net.InetAddress");
237 Class[] parameterTypes = { byte[].class };
238 getByAddress = inetAddressClass.getMethod("getByAddress", parameterTypes);
239 } catch (Exception e) {
240 getByAddress = null;
241 }
242 }
243
244 private static InetAddress getByAddress(byte[] ip) throws java.net.UnknownHostException
245 {
246 InetAddress addr = null;
247 if (getByAddress != null) try {
248 addr = (InetAddress) getByAddress.invoke(null, new Object[] { ip });
249 } catch (IllegalAccessException e) {
250 } catch (java.lang.reflect.InvocationTargetException e) {
251 }
252
253 if (addr == null) {
254 addr = InetAddress.getByName
255 (
256 Integer.toString(ip[0] & 0xFF, 10) + "." +
257 Integer.toString(ip[1] & 0xFF, 10) + "." +
258 Integer.toString(ip[2] & 0xFF, 10) + "." +
259 Integer.toString(ip[3] & 0xFF, 10)
260 );
261 }
262 return addr;
263 }
264 }