1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.util;
16
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19
20
21
22
23
24
25
26
27
28 public class SubnetUtils {
29
30 private static final String IP_ADDRESS = "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})";
31 private static final Pattern ADDRESS_PATTERN = Pattern.compile(IP_ADDRESS);
32 private static final String PARSE_FAIL = "Could not parse [%s]";
33 private static final long UNSIGNED_INT_MASK = 0x0FFFFFFFFL;
34
35 private final int netmask_;
36 private final int address_;
37 private final int network_;
38 private final int broadcast_;
39
40
41
42
43
44
45
46
47 public SubnetUtils(final String address, final String mask) {
48 address_ = toInteger(address);
49 netmask_ = toInteger(mask);
50
51 if ((netmask_ & -netmask_) - 1 != ~netmask_) {
52 throw new IllegalArgumentException(String.format(PARSE_FAIL, mask));
53 }
54
55 network_ = address_ & netmask_;
56 broadcast_ = network_ | ~netmask_;
57 }
58
59
60
61
62 private static int matchAddress(final Matcher matcher) {
63 int addr = 0;
64 for (int i = 1; i <= 4; ++i) {
65 final int n = rangeCheck(Integer.parseInt(matcher.group(i)), 0, 255);
66 addr |= (n & 0xff) << 8 * (4 - i);
67 }
68 return addr;
69 }
70
71
72
73
74 private static int rangeCheck(final int value, final int begin, final int end) {
75
76 if (value >= begin && value <= end) {
77 return value;
78 }
79 throw new IllegalArgumentException("Value [" + value + "] not in range [" + begin + "," + end + "]");
80 }
81
82
83
84
85 private static int toInteger(final String address) {
86 final Matcher matcher = ADDRESS_PATTERN.matcher(address);
87 if (matcher.matches()) {
88 return matchAddress(matcher);
89 }
90 throw new IllegalArgumentException(String.format(PARSE_FAIL, address));
91 }
92
93 private long broadcastLong() {
94 return broadcast_ & UNSIGNED_INT_MASK;
95 }
96
97 private int high() {
98 return broadcastLong() - networkLong() > 1 ? broadcast_ - 1 : 0;
99 }
100
101 private int low() {
102 return broadcastLong() - networkLong() > 1 ? network_ + 1 : 0;
103 }
104
105
106 private long networkLong() {
107 return network_ & UNSIGNED_INT_MASK;
108 }
109
110
111
112
113
114
115
116
117 private boolean isInRange(final int address) {
118 if (address == 0) {
119 return false;
120 }
121 final long addLong = address & UNSIGNED_INT_MASK;
122 final long lowLong = low() & UNSIGNED_INT_MASK;
123 final long highLong = high() & UNSIGNED_INT_MASK;
124 return addLong >= lowLong && addLong <= highLong;
125 }
126
127
128
129
130
131
132
133
134 public boolean isInRange(final String address) {
135 return isInRange(toInteger(address));
136 }
137 }