1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.jspf.core;
21
22 import java.net.UnknownHostException;
23
24 import org.apache.james.jspf.core.exceptions.PermErrorException;
25 import org.xbill.DNS.Address;
26
27 public class IPAddr {
28
29
30
31 private static final int MASK8 = 255;
32
33 private static final int MASK16 = 65535;
34
35 private int[] address = new int[4];
36
37 private int[] mask = new int[4];
38
39 private int maskLength = 32;
40
41 private int ipLength = 4;
42
43 private int ipRun = 4;
44
45 private String ipJoiner = ".";
46
47 private static String ipv4MappedRegex = "::FFFF:[1-9][0-9]{0,2}\\.[1-9][0-9]{0,2}\\.[1-9][0-9]{0,2}\\.[1-9][0-9]{0,2}";
48
49
50 private IPAddr() {
51
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65 public static IPAddr getAddress(String netAddress, int maskLength)
66 throws PermErrorException {
67 IPAddr returnAddress = new IPAddr();
68 returnAddress.stringToInternal(netAddress);
69 returnAddress.setMask(maskLength);
70 return returnAddress;
71 }
72
73
74
75
76
77 public static IPAddr getAddress(String netAddress)
78 throws PermErrorException {
79 IPAddr returnAddress = new IPAddr();
80 returnAddress.stringToInternal(netAddress);
81 returnAddress.setMask(returnAddress.maskLength);
82 return returnAddress;
83 }
84
85
86
87
88
89
90
91
92 public static boolean isIPAddr(String data) {
93 try {
94 getAddress(data);
95 return true;
96 } catch (PermErrorException e) {
97 return false;
98 }
99 }
100
101
102
103
104
105 private void setIP6Defaults() {
106 ipLength = 16;
107 ipJoiner = ":";
108 address = new int[8];
109 mask = new int[8];
110 ipRun = 8;
111 }
112
113
114
115
116
117
118
119 public void setMask(int maskLength) {
120 int startMask;
121 int shift;
122 int maskSize;
123
124 this.maskLength = maskLength;
125 if (ipLength == 4) {
126 if (!((maskLength > -1) && (maskLength < 33))) {
127 maskLength = 32;
128 }
129 maskSize = 8;
130 startMask = (maskLength - 1) / maskSize;
131 } else {
132 if (!((maskLength > -1) && (maskLength < 129))) {
133 maskLength = 128;
134 }
135 maskSize = 16;
136 startMask = (maskLength - 1) / maskSize;
137 }
138
139 for (int i = 0; i < ipRun; i++) {
140
141 if (i < startMask) {
142 mask[i] = MASK16;
143
144 } else if (i == startMask) {
145 shift = ((i + 1) * maskSize) - maskLength;
146 mask[i] = (MASK16 << shift) & MASK16;
147
148 } else {
149 mask[i] = 0;
150 }
151 }
152 }
153
154
155
156
157
158
159
160
161 public static String stripDot(String data) {
162
163 data = data.trim();
164
165 if (data.endsWith(".")) {
166 return data.substring(0, data.length() - 1);
167 } else {
168 return data;
169 }
170
171 }
172
173
174
175
176
177
178
179
180
181 private void stringToInternal(String netAddress) throws PermErrorException {
182 netAddress = stripDot(netAddress);
183
184 try {
185 byte[] bytes = Inet6Util.createByteArrayFromIPAddressString(netAddress);
186
187 if (bytes.length == 4) {
188 for (int i = 0; i < bytes.length; i++) {
189 address[i] = bytes[i];
190 }
191 } else if (bytes.length == 16) {
192 setIP6Defaults();
193 for (int i = 0; i < bytes.length / 2; i++) {
194 address[i] = unsigned(bytes[i * 2]) * 256
195 + unsigned(bytes[i * 2 + 1]);
196 }
197 } else {
198 throw new PermErrorException("Not a valid address: " + netAddress);
199 }
200 } catch (NumberFormatException e) {
201 throw new PermErrorException("Not a valid address: " + netAddress);
202 }
203 }
204
205
206
207
208
209
210
211 private String getHex(long data) {
212 StringBuffer fullHex = new StringBuffer();
213 fullHex.append("0000" + Long.toHexString(data).toUpperCase());
214 fullHex = fullHex.delete(0, fullHex.length() - 4);
215 return fullHex.toString();
216 }
217
218
219
220
221 public String getIPAddress() {
222 return getIPAddress(address);
223 }
224
225
226
227
228
229
230
231
232 private String getIPAddress(int[] addressData) {
233 StringBuffer createAddress = new StringBuffer();
234 int[] workingAddress;
235
236
237 if (ipLength == 4) {
238 workingAddress = get8BitAddress(addressData);
239
240 createAddress.append(workingAddress[0]);
241 for (int i = 1; i < ipRun; i++) {
242 createAddress.append(ipJoiner + workingAddress[i]);
243 }
244
245 } else {
246 workingAddress = addressData;
247
248 createAddress.append(getHex(workingAddress[0]));
249 for (int i = 1; i < ipRun; i++) {
250 createAddress.append(ipJoiner + getHex(workingAddress[i]));
251 }
252 }
253
254 return createAddress.toString();
255 }
256
257
258
259
260
261 public String getMaskedIPAddress() {
262 return getIPAddress(maskedAddress(address, mask));
263 }
264
265
266
267
268
269
270 public String getNibbleFormat() {
271 return getNibbleFormat(address);
272 }
273
274 private String getNibbleFormat(int[] address) {
275 StringBuffer sb = new StringBuffer();
276 int[] ip = address;
277 for (int i = 0; i < ip.length; i++) {
278 String hex = getHex(ip[i]);
279 for (int j = 0; j < hex.length(); j++) {
280 sb.append(hex.charAt(j));
281 if (i != ip.length -1 || j != hex.length() -1) {
282 sb.append(".");
283 }
284 }
285 }
286 return sb.toString();
287 }
288
289
290
291
292
293
294 public String getReverseIP() {
295 if(isIPV6(getIPAddress())) {
296 StringBuffer ip6 = new StringBuffer(getNibbleFormat());
297 return ip6.reverse().append(".ip6.arpa").toString();
298 }
299 return (getIPAddress(reverseIP(address)) + ".in-addr.arpa");
300 }
301
302
303
304
305
306
307
308
309 private int[] get8BitAddress(int[] addressData) {
310 int[] convertAddress = new int[4];
311 for (int i = 0; i < ipRun; i++) {
312 convertAddress[i] = addressData[i] & MASK8;
313 }
314 return convertAddress;
315 }
316
317
318
319
320
321
322
323
324
325
326 private int[] maskedAddress(int[] addressData, int[] maskData) {
327 int[] maskedAddress = new int[ipLength];
328
329 for (int i = 0; i < ipRun; i++) {
330 maskedAddress[i] = addressData[i] & maskData[i];
331 }
332 return maskedAddress;
333 }
334
335
336
337
338
339
340
341
342 private int[] reverseIP(int[] addressData) {
343 int[] reverseIP = new int[ipLength];
344 int temp;
345 for (int i = 0; i < ipRun; i++) {
346 temp = addressData[i];
347 reverseIP[i] = addressData[(ipRun - 1) - i];
348 reverseIP[(ipRun - 1) - i] = temp;
349 }
350 return reverseIP;
351 }
352
353
354
355
356
357
358 public int getMaskLength() {
359 return maskLength;
360 }
361
362
363 public String toString() {
364 return getIPAddress();
365 }
366
367 private int unsigned(byte data) {
368 return data >= 0 ? data : 256 + data;
369 }
370
371
372
373
374
375
376
377
378
379
380 public static String getInAddress(String ipAddress)
381 throws PermErrorException {
382 if (ipAddress == null) {
383 throw new PermErrorException(
384 "IP is not a valid ipv4 or ipv6 address");
385 } else if (Inet6Util.isValidIPV4Address(ipAddress)) {
386 return "in-addr";
387 } else if (Inet6Util.isValidIP6Address(ipAddress)) {
388 return "ip6";
389 } else {
390 throw new PermErrorException(
391 "IP is not a valid ipv4 or ipv6 address");
392 }
393 }
394
395
396
397
398
399
400
401
402 public static boolean isValidIP(String ip) {
403 return ip != null
404 && (Inet6Util.isValidIPV4Address(ip) || Inet6Util
405 .isValidIP6Address(ip));
406 }
407
408
409
410
411
412
413
414 public static boolean isIPV6(String ip) {
415 return Inet6Util.isValidIP6Address(ip);
416 }
417
418
419
420
421
422
423
424
425
426
427 public static String getReadableIP(String ip) {
428
429
430 if (Inet6Util.isValidIP6Address(ip)) {
431 try {
432 return getConvertedIP(ip);
433 } catch (UnknownHostException e) {
434
435 }
436 }
437 return ip;
438 }
439
440 private static String getConvertedIP(String ip) throws UnknownHostException {
441
442 return Address.getByName(ip).getHostAddress();
443 }
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 public static String getProperIpAddress(String ip) throws PermErrorException {
464 if (isIPV6(ip) && isIPV4MappedIP(ip)) {
465 try {
466 return getConvertedIP(ip);
467 } catch (UnknownHostException e) {
468 throw new PermErrorException("Invalid ipAddress: " + ip);
469 }
470 }
471 return ip;
472
473 }
474
475
476
477
478
479
480 private static boolean isIPV4MappedIP(String ip) {
481 return ip.toUpperCase().matches(ipv4MappedRegex);
482 }
483
484 }