001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: /* $Id: InetAddressUtil.java 531479 2007-04-23 14:21:35Z andreas $ */
020:
021: package org.apache.lenya.net;
022:
023: import java.net.InetAddress;
024: import java.net.UnknownHostException;
025:
026: import org.apache.avalon.framework.logger.AbstractLogEnabled;
027: import org.apache.avalon.framework.logger.Logger;
028:
029: /**
030: * A utility class for InetAddress. Also see http://jodies.de/ipcalc
031: */
032: public class InetAddressUtil extends AbstractLogEnabled {
033:
034: /**
035: * Ctor.
036: * @param logger The logger.
037: */
038: public InetAddressUtil(Logger logger) {
039: enableLogging(logger);
040: }
041:
042: /**
043: * Checks if a subnet contains a specific IP address.
044: * @param network The network address.
045: * @param netmask The subnet mask.
046: * @param ip The IP address to check.
047: * @return A boolean value.
048: */
049: public boolean contains(InetAddress network, InetAddress netmask,
050: InetAddress ip) {
051: if (getLogger().isDebugEnabled()) {
052: getLogger()
053: .debug("=======================================");
054: getLogger().debug(
055: "Checking IP address: " + ip + " in " + network
056: + " / " + netmask);
057: }
058:
059: byte[] networkBytes = network.getAddress();
060: byte[] netmaskBytes = netmask.getAddress();
061: byte[] ipBytes = ip.getAddress();
062:
063: /* check IPv4/v6-compatibility or parameters: */
064: if (networkBytes.length != netmaskBytes.length
065: || netmaskBytes.length != ipBytes.length) {
066: /*
067: * FIXME: If network and netmask have the same size
068: * should already be checked whenever
069: * org.apache.lenya.ac.(impl.Abstract)IPRange
070: * is set. In that case the user should be notified
071: * of this configuration-error instead of silently
072: * accepting the buggy IPRange as one not matching
073: * any host!
074: * (Note that changes to the public API of IPRange
075: * and other classes would be necessary to fix this
076: * problem. This method and therefore this whole
077: * class would probably be obsolete in that case.)
078: */
079: if (getLogger().isDebugEnabled()) {
080: getLogger()
081: .debug(
082: "Network address "
083: + network
084: + ", subnet mask "
085: + netmask
086: + " and/or host address "
087: + ip
088: + " have different sizes! (return false ...)");
089: getLogger().debug(
090: "=======================================");
091: }
092: return false;
093: }
094:
095: /* Check if the masked network and ip addresses match: */
096: for (int i = 0; i < netmaskBytes.length; i++) {
097: int mask = netmaskBytes[i] & 0xff;
098: if ((networkBytes[i] & mask) != (ipBytes[i] & mask)) {
099: if (getLogger().isDebugEnabled()) {
100: getLogger().debug(
101: ip + " is not in " + network + " / "
102: + netmask);
103: getLogger().debug(
104: "=======================================");
105: }
106: return false;
107: }
108: }
109: if (getLogger().isDebugEnabled()) {
110: getLogger().debug(
111: ip + " is in " + network + " / " + netmask);
112: getLogger()
113: .debug("=======================================");
114: }
115: return true;
116: }
117:
118: /**
119: * Returns the n-th part of an InetAddress.
120: * @param ip The address.
121: * @param partNumber The number of the part.
122: * @return An integer value.
123: * @deprecated This was an internal implementation detail of the
124: * method {@link #contains} and should never have been
125: * made public. (And it's inefficient and unnecessary
126: * too, as well as broken for IPv6. ;-)
127: * Use <code>ip.getAddress()[partNumber]</code>
128: * instead.
129: */
130: public static int getClassPart(InetAddress ip, int partNumber) {
131: String[] parts = ip.getHostAddress().split("\\.");
132: String part = parts[partNumber];
133: return new Integer(part).intValue();
134: }
135:
136: /**
137: * Check netmask, e.g. 255.255.255.240 is fine, 255.255.240.16 is illegal (needs to be 255.255.240.0)
138: * @param netmask The netmask address.
139: * @return An integer value. -1 if illegal netmask, otherwise 0, 1, 2, 3
140: * @deprecated This was an internal implementation detail of the
141: * method {@link #contains} and should never have been
142: * made public. Furthermore it's broken for IPv6.
143: * (However, there is no real replacement. If you
144: * need this functionality, you should rewrite it
145: * yourself.)
146: */
147: public int checkNetmask(InetAddress netmask) {
148: String[] parts = netmask.getHostAddress().split("\\.");
149: Integer[] numbers = new Integer[4];
150: for (int i = 0; i < 4; i++) {
151: numbers[i] = new Integer(parts[i]);
152: }
153:
154: for (int i = 0; i < 4; i++) {
155: getLogger().debug(
156: ".checkNetmask(): Check part: " + numbers[i]);
157: if (0 <= numbers[i].intValue()
158: && numbers[i].intValue() <= 255) {
159: if (numbers[i].intValue() != 255) {
160: for (int k = i + 1; k < 4; k++) {
161: if (numbers[k].intValue() != 0) {
162: getLogger().error(
163: ".checkNetmask(): Illegal Netmask: "
164: + netmask);
165: return -1;
166: }
167: }
168: return i;
169: }
170: continue;
171: }
172: // FIXME: This check not really be necessary because java.net.UnknownHostException should be thrown long time before
173: getLogger().error(
174: ".checkNetmask(): Illegal Netmask: " + netmask);
175: return -1;
176: }
177: if (getLogger().isDebugEnabled()) {
178: getLogger().debug("All parts equal 255: " + netmask);
179: }
180: return 3;
181: }
182:
183: /**
184: * Converts a string to an IP addres.
185: * @param string The IP address, represented by a string.
186: * @return An InetAddress object.
187: * @throws UnknownHostException
188: * @deprecated This was an internal implementation detail of the
189: * method {@link #contains} and should never have been
190: * made public. (And it's unnecessary
191: * too, as well as broken for IPv6. ;-)
192: * Use <code>InetAddress.getByName(string)</code>
193: * instead.
194: */
195: public static InetAddress getAddress(String string)
196: throws UnknownHostException {
197: String[] strings = string.split("\\.");
198:
199: InetAddress address;
200: byte[] numbers = new byte[strings.length];
201: for (int i = 0; i < strings.length; i++) {
202: int number = Integer.parseInt(strings[i]);
203: if (number > 127) {
204: number = number - 256;
205: }
206: numbers[i] = (byte) number;
207: }
208:
209: address = InetAddress.getByAddress(numbers);
210: return address;
211: }
212:
213: }
|