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