Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 83 additions & 122 deletions mina-core/src/main/java/org/apache/mina/filter/firewall/Subnet.java
Original file line number Diff line number Diff line change
@@ -1,62 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

package org.apache.mina.filter.firewall;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;

import org.apache.mina.filter.util.SubnetUtils;
import org.apache.mina.filter.util.SubnetUtils6;

/**
* A IP subnet using the CIDR notation. Currently, only IP version 4
* address are supported.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
* A IP subnet using the CIDR notation. Currently, only IP version 4
* address are supported.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class Subnet {

private static final int IP_MASK_V4 = 0x80000000;

private static final long IP_MASK_V6 = 0x8000000000000000L;

private static final int BYTE_MASK = 0xFF;

private InetAddress subnet;

/** An int representation of a subnet for IPV4 addresses */
private int subnetInt;

/** An long representation of a subnet for IPV6 addresses */
private long subnetLong;
private SubnetUtils subnetUtils;
private SubnetUtils6 subnetUtils6;

private long subnetMask;

private int suffix;
boolean isIpv6;

/**
* Creates a subnet from CIDR notation. For example, the subnet
* 192.168.0.0/24 would be created using the {@link InetAddress}
* 192.168.0.0 and the mask 24.
* @param subnet The {@link InetAddress} of the subnet
* @param mask The mask
*/
* Creates a subnet from CIDR notation. For example, the subnet
* 192.168.0.0/24 would be created using the {@link InetAddress}
* 192.168.0.0 and the mask 24.
*
* @param subnet The {@link InetAddress} of the subnet
* @param mask The mask
*/
public Subnet(InetAddress subnet, int mask) {
if (subnet == null) {
throw new IllegalArgumentException("Subnet address can not be null");
Expand All @@ -68,110 +59,80 @@ public Subnet(InetAddress subnet, int mask) {

if (subnet instanceof Inet4Address) {
// IPV4 address
if ((mask < 0) || (mask > 32)) {
throw new IllegalArgumentException("Mask has to be an integer between 0 and 32 for an IPV4 address");
} else {
this.subnet = subnet;
subnetInt = toInt(subnet);
this.suffix = mask;

// binary mask for this subnet
this.subnetMask = IP_MASK_V4 >> (mask - 1);
}
} else {
// IPV6 address
if ((mask < 0) || (mask > 128)) {
throw new IllegalArgumentException("Mask has to be an integer between 0 and 128 for an IPV6 address");
} else {
this.subnet = subnet;
subnetLong = toLong(subnet);
this.suffix = mask;

// binary mask for this subnet
this.subnetMask = IP_MASK_V6 >> (mask - 1);
}
}
}

/**
* Converts an IP address into an integer
*/
private int toInt(InetAddress inetAddress) {
byte[] address = inetAddress.getAddress();
int result = 0;

for (int i = 0; i < address.length; i++) {
result <<= 8;
result |= address[i] & BYTE_MASK;
}

return result;
}

/**
* Converts an IP address into a long
*/
private long toLong(InetAddress inetAddress) {
byte[] address = inetAddress.getAddress();
long result = 0;

for (int i = 0; i < address.length; i++) {
result <<= 8;
result |= address[i] & BYTE_MASK;
}

return result;
}

/**
* Converts an IP address to a subnet using the provided mask
*
* @param address
* The address to convert into a subnet
* @return The subnet as an integer
*/
private long toSubnet(InetAddress address) {
if (address instanceof Inet4Address) {
return toInt(address) & (int) subnetMask;
this.subnetUtils = new SubnetUtils(subnet.getHostAddress() + "/" + mask);
this.subnetUtils.setInclusiveHostCount(true);
isIpv6 = false;
} else {
return toLong(address) & subnetMask;
this.subnetUtils6 = new SubnetUtils6(subnet.getHostAddress(), mask);
isIpv6 = true;
}
}

/**
* Checks if the {@link InetAddress} is within this subnet
* @param address The {@link InetAddress} to check
* @return True if the address is within this subnet, false otherwise
*/
* Checks if the {@link InetAddress} is within this subnet
* @param address The {@link InetAddress} to check
* @return True if the address is within this subnet, false otherwise
*/
public boolean inSubnet(InetAddress address) {
if (address.isAnyLocalAddress()) {
return true;
}

if (address instanceof Inet4Address) {
return (int) toSubnet(address) == subnetInt;
if (this.isIpv6 ) {
if (address instanceof Inet6Address) {
return subnetUtils6.getInfo().isInRange( (Inet6Address) address);
} else {
return false;
}
} else {
return toSubnet(address) == subnetLong;
if (address instanceof Inet4Address) {
byte[] bytes = address.getAddress();
int value = ((bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8) |
(bytes[3] & 0xFF);
return subnetUtils.getInfo().isInRange(value);
} else {
return false;
}
}
}

/**
* @see Object#toString()
*/
* @see Object#toString()
*/
@Override
public String toString() {
return subnet.getHostAddress() + "/" + suffix;
if (this.isIpv6 ) {
return subnetUtils6.getInfo().getCidrSignature();
} else {
return subnetUtils.getInfo().getCidrSignature();
}

}

@Override
public boolean equals(Object obj) {

if (this == obj) {
return true;
}

if (!(obj instanceof Subnet)) {
return false;
}

Subnet other = (Subnet) obj;

return other.subnetInt == subnetInt && other.suffix == suffix;
if (this.isIpv6 != other.isIpv6) {
return false;
}

if (this.isIpv6 ) {
return this.subnetUtils6.getInfo().getCidrSignature().equals(other.subnetUtils6.getInfo().getCidrSignature());
} else {
return this.subnetUtils.getInfo().getCidrSignature().equals(other.subnetUtils.getInfo().getCidrSignature());
}
}

}
Loading
Loading