Author: bombe
Date: 2006-05-03 21:28:27 +0000 (Wed, 03 May 2006)
New Revision: 8600
Added:
trunk/freenet/src/freenet/io/AddressIdentifier.java
trunk/freenet/src/freenet/io/AddressMatcher.java
trunk/freenet/src/freenet/io/Inet6AddressMatcher.java
trunk/freenet/src/test/AddressIdentifierTest.java
trunk/freenet/src/test/Inet6AddressMatcherTest.java
Modified:
trunk/freenet/src/freenet/io/Inet4AddressMatcher.java
trunk/freenet/src/freenet/io/NetworkInterface.java
trunk/freenet/src/freenet/node/Version.java
Log:
preliminary support for ipv6 interfaces for *.bindTo and *.allowedHosts
Added: trunk/freenet/src/freenet/io/AddressIdentifier.java
===================================================================
--- trunk/freenet/src/freenet/io/AddressIdentifier.java 2006-05-01 22:20:02 UTC
(rev 8599)
+++ trunk/freenet/src/freenet/io/AddressIdentifier.java 2006-05-03 21:28:27 UTC
(rev 8600)
@@ -0,0 +1,76 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.io;
+
+import java.util.regex.Pattern;
+
+/**
+ * Identifies numeric IP addresses. This class is currently capable of
+ * recognizing:
+ * <ul>
+ * <li>IPv4 unabridged (a.b.c.d)</li>
+ * <li>IPv4 abridged (a.b.d or a.d)</li>
+ * <li>IPv6 unabridged (a:b:c:d:e:f:g:h)</li>
+ * </ul>
+ *
+ * @author David Roden <droden at gmail.com>
+ * @version $Id$
+ */
+public class AddressIdentifier {
+
+ public static class AddressType {
+
+ public static final AddressType OTHER = new
AddressType("Other");
+ public static final AddressType IPv4 = new AddressType("IPv4");
+ public static final AddressType IPv6 = new AddressType("IPv6");
+
+ private final String name;
+
+ private AddressType(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ }
+
+ /**
+ * Tries to detemine the address type of the given address.
+ *
+ * @param address
+ * The address to determine the type of
+ * @return {@link AddressType#OTHER} if <code>address</code> is a
+ * hostname, {@link AddressType#IPv4} or {@link
AddressType#IPv6}
+ * otherwise
+ */
+ public static AddressType getAddressType(String address) {
+ String byteRegex = "([01]?[0-9]?[0-9]?|2[0-4][0-9]|25[0-5])";
+ String ipv4AddressRegex = byteRegex + "\\.(" + byteRegex +
"\\.)?(" + byteRegex + "\\.)?" + byteRegex;
+ if (Pattern.matches(ipv4AddressRegex, address)) {
+ return AddressType.IPv4;
+ }
+ String wordRegex = "([0-9a-fA-F]{1,4})";
+ String ipv6AddressRegex = wordRegex + "?:" + wordRegex + ":" +
wordRegex + ":" + wordRegex + ":" + wordRegex + ":" + wordRegex + ":" +
wordRegex + ":" + wordRegex;
+ if (Pattern.matches(ipv6AddressRegex, address)) {
+ return AddressType.IPv6;
+ }
+ return AddressType.OTHER;
+ }
+
+}
Property changes on: trunk/freenet/src/freenet/io/AddressIdentifier.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: trunk/freenet/src/freenet/io/AddressMatcher.java
===================================================================
--- trunk/freenet/src/freenet/io/AddressMatcher.java 2006-05-01 22:20:02 UTC
(rev 8599)
+++ trunk/freenet/src/freenet/io/AddressMatcher.java 2006-05-03 21:28:27 UTC
(rev 8600)
@@ -0,0 +1,29 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.io;
+
+import java.net.InetAddress;
+
+/**
+ * @author David Roden <droden at gmail.com>
+ * @version $Id$
+ */
+public interface AddressMatcher {
+
+ public boolean matches(InetAddress address);
+
+}
Property changes on: trunk/freenet/src/freenet/io/AddressMatcher.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/freenet/src/freenet/io/Inet4AddressMatcher.java
===================================================================
--- trunk/freenet/src/freenet/io/Inet4AddressMatcher.java 2006-05-01
22:20:02 UTC (rev 8599)
+++ trunk/freenet/src/freenet/io/Inet4AddressMatcher.java 2006-05-03
21:28:27 UTC (rev 8600)
@@ -17,6 +17,7 @@
package freenet.io;
import java.net.Inet4Address;
+import java.net.InetAddress;
import java.util.StringTokenizer;
/**
@@ -34,7 +35,7 @@
* @author David Roden <droden at gmail.com>
* @version $Id$
*/
-public class Inet4AddressMatcher {
+public class Inet4AddressMatcher implements AddressMatcher {
/** The address of this matcher */
private int address;
@@ -96,7 +97,7 @@
* @return <code>true</code> if <code>inetAddress</code> matches the
* specification of this matcher, <code>false</code> otherwise
*/
- public boolean matches(Inet4Address inetAddress) {
+ public boolean matches(InetAddress inetAddress) {
int matchAddress = convertToBytes(inetAddress.getHostAddress());
return (matchAddress & networkMask) == (address & networkMask);
}
Added: trunk/freenet/src/freenet/io/Inet6AddressMatcher.java
===================================================================
--- trunk/freenet/src/freenet/io/Inet6AddressMatcher.java 2006-05-01
22:20:02 UTC (rev 8599)
+++ trunk/freenet/src/freenet/io/Inet6AddressMatcher.java 2006-05-03
21:28:27 UTC (rev 8600)
@@ -0,0 +1,87 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package freenet.io;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.Arrays;
+import java.util.StringTokenizer;
+
+/**
+ * @author David Roden <droden at gmail.com>
+ * @version $Id$
+ */
+public class Inet6AddressMatcher implements AddressMatcher {
+
+ private byte[] address;
+ private byte[] netmask;
+
+ public Inet6AddressMatcher(String pattern) {
+ if (pattern.indexOf('/') != -1) {
+ address = convertToBytes(pattern.substring(0,
pattern.indexOf('/')));
+ String netmaskString =
pattern.substring(pattern.indexOf('/') + 1).trim();
+ if (netmaskString.indexOf(':') != -1) {
+ netmask = convertToBytes(netmaskString);
+ } else {
+ netmask = new byte[16];
+ int bits = Integer.parseInt(netmaskString);
+ for (int index = 0; index < 16; index++) {
+ netmask[index] = (byte) (255 << (8 -
Math.min(bits, 8)));
+ bits = Math.max(bits - 8, 0);
+ }
+ }
+ } else {
+ address = convertToBytes(pattern);
+ netmask = new byte[16];
+ Arrays.fill(netmask, (byte) 0xff);
+ }
+ if (address.length != 16) {
+ throw new IllegalArgumentException("address is not
IPv6");
+ }
+ }
+
+ private byte[] convertToBytes(String address) {
+ StringTokenizer addressTokens = new StringTokenizer(address,
":");
+ if (addressTokens.countTokens() != 8) {
+ throw new IllegalArgumentException(address + " is not
an IPv6 address.");
+ }
+ byte[] addressBytes = new byte[16];
+ int count = 0;
+ while (addressTokens.hasMoreTokens()) {
+ int addressWord =
Integer.parseInt(addressTokens.nextToken(), 16);
+ addressBytes[count * 2] = (byte) ((addressWord >> 8) &
0xff);
+ addressBytes[count * 2 + 1] = (byte) (addressWord &
0xff);
+ count++;
+ }
+ return addressBytes;
+ }
+
+ public boolean matches(InetAddress address) {
+ byte[] addressBytes = address.getAddress();
+ for (int index = 0; index < 16; index++) {
+ if ((addressBytes[index] & netmask[index]) !=
(this.address[index] & netmask[index])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static boolean matches(String pattern, Inet6Address address) {
+ return new Inet6AddressMatcher(pattern).matches(address);
+ }
+
+}
Property changes on: trunk/freenet/src/freenet/io/Inet6AddressMatcher.java
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: trunk/freenet/src/freenet/io/NetworkInterface.java
===================================================================
--- trunk/freenet/src/freenet/io/NetworkInterface.java 2006-05-01 22:20:02 UTC
(rev 8599)
+++ trunk/freenet/src/freenet/io/NetworkInterface.java 2006-05-03 21:28:27 UTC
(rev 8600)
@@ -17,7 +17,6 @@
package freenet.io;
import java.io.IOException;
-import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -31,6 +30,7 @@
import java.util.Map;
import java.util.StringTokenizer;
+import freenet.io.AddressIdentifier.AddressType;
import freenet.support.Logger;
/**
@@ -51,8 +51,8 @@
/** List of allowed hosts. */
protected final List/* <String> */allowedHosts = new ArrayList();
- /** Maps allowed hosts to IPv4 address matchers, if possible. */
- protected final Map/* <String, Inet4AddressMatcher> */addressMatchers =
new HashMap();
+ /** Maps allowed hosts to address matchers, if possible. */
+ protected final Map/* <String, AddressMatcher> */addressMatchers = new
HashMap();
/** Queue of accepted client connections. */
protected final List/* <Socket> */acceptedSockets = new ArrayList();
@@ -95,22 +95,31 @@
* list is in effect immediately after this method has finished.
*
* @param allowedHosts
- * The new list of allowed hosts
+ * The new list of allowed hosts s
*/
public void setAllowedHosts(String allowedHosts) {
StringTokenizer allowedHostsTokens = new
StringTokenizer(allowedHosts, ",");
+ List newAllowedHosts = new ArrayList();
+ Map newAddressMatchers = new HashMap();
+ while (allowedHostsTokens.hasMoreTokens()) {
+ String allowedHost =
allowedHostsTokens.nextToken().trim();
+ newAllowedHosts.add(allowedHost);
+ String hostname = allowedHost;
+ if (allowedHost.indexOf('/') != -1) {
+ hostname = allowedHost.substring(0,
allowedHost.indexOf('/'));
+ }
+ AddressType addressType =
AddressIdentifier.getAddressType(hostname);
+ if (addressType == AddressType.IPv4) {
+ newAddressMatchers.put(allowedHost, new
Inet4AddressMatcher(allowedHost));
+ } else if (addressType == AddressType.IPv6) {
+ newAddressMatchers.put(allowedHost, new
Inet6AddressMatcher(allowedHost));
+ }
+ }
synchronized (syncObject) {
this.allowedHosts.clear();
+ this.allowedHosts.addAll(newAllowedHosts);
this.addressMatchers.clear();
- while (allowedHostsTokens.hasMoreTokens()) {
- String allowedHost =
allowedHostsTokens.nextToken().trim();
- this.allowedHosts.add(allowedHost);
- if (allowedHost.equals("*")) {
- addressMatchers.put("*", new
Inet4AddressMatcher("0.0.0.0/0"));
- } else if
(!Character.isLetter(allowedHost.charAt(0))) {
- addressMatchers.put(allowedHost, new
Inet4AddressMatcher(allowedHost));
- }
- }
+ this.addressMatchers.putAll(newAddressMatchers);
}
}
@@ -256,11 +265,11 @@
Iterator hosts =
allowedHosts.iterator();
while (!addressMatched &&
hosts.hasNext()) {
String host = (String)
hosts.next();
- Inet4AddressMatcher
matcher = (Inet4AddressMatcher) addressMatchers.get(host);
+ AddressMatcher matcher
= (AddressMatcher) addressMatchers.get(host);
if (matcher != null) {
- addressMatched
= matcher.matches((Inet4Address) clientAddress);
+ addressMatched
= matcher.matches(clientAddress);
} else {
- addressMatched
= clientHostName.equalsIgnoreCase(host);
+ addressMatched
= "*".equals(clientHostName) || clientHostName.equalsIgnoreCase(host);
}
}
}
Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-05-01 22:20:02 UTC (rev
8599)
+++ trunk/freenet/src/freenet/node/Version.java 2006-05-03 21:28:27 UTC (rev
8600)
@@ -20,7 +20,7 @@
public static final String protocolVersion = "1.0";
/** The build number of the current revision */
- private static final int buildNumber = 669;
+ private static final int buildNumber = 670;
/** Oldest build of Fred we will talk to */
private static final int lastGoodBuild = 591;
Added: trunk/freenet/src/test/AddressIdentifierTest.java
===================================================================
--- trunk/freenet/src/test/AddressIdentifierTest.java 2006-05-01 22:20:02 UTC
(rev 8599)
+++ trunk/freenet/src/test/AddressIdentifierTest.java 2006-05-03 21:28:27 UTC
(rev 8600)
@@ -0,0 +1,54 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package test;
+
+import junit.framework.TestCase;
+import freenet.io.AddressIdentifier;
+import freenet.io.AddressIdentifier.AddressType;
+
+/**
+ * Test case for the {@link freenet.io.AddressIdentifier} class.
+ *
+ * @author David Roden <droden at gmail.com>
+ * @version $Id$
+ */
+public class AddressIdentifierTest extends TestCase {
+
+ public void test() {
+ /* test real IPv4 addresses */
+ assertEquals(AddressType.IPv4,
AddressIdentifier.getAddressType("0.0.0.0"));
+ assertEquals(AddressType.IPv4,
AddressIdentifier.getAddressType("127.0.0.1"));
+ assertEquals(AddressType.IPv4,
AddressIdentifier.getAddressType("255.255.255.255"));
+ /* in case you didn't know: 183.24.17 = 183.24.0.17 */
+ assertEquals(AddressType.IPv4,
AddressIdentifier.getAddressType("183.24.17"));
+ /* and 127.1 = 127.0.0.1 */
+ assertEquals(AddressType.IPv4,
AddressIdentifier.getAddressType("127.1"));
+
+ /* test fake IPv4 addresses */
+ assertEquals(AddressType.OTHER,
AddressIdentifier.getAddressType("192.168.370.12"));
+ assertEquals(AddressType.OTHER,
AddressIdentifier.getAddressType("127.0.0.0.1"));
+
+ /* test real unabridged IPv6 addresses */
+ assertEquals(AddressType.IPv6,
AddressIdentifier.getAddressType("0:0:0:0:0:0:0:1"));
+ assertEquals(AddressType.IPv6,
AddressIdentifier.getAddressType("fe80:0:0:0:203:dff:fe22:420f"));
+
+ /* test fake IPv6 addresses */
+ assertEquals(AddressType.OTHER,
AddressIdentifier.getAddressType("1:2:3:4:5:6:7:8:9"));
+ assertEquals(AddressType.OTHER,
AddressIdentifier.getAddressType("12345:6:7:8:9"));
+ }
+
+}
Property changes on: trunk/freenet/src/test/AddressIdentifierTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: trunk/freenet/src/test/Inet6AddressMatcherTest.java
===================================================================
--- trunk/freenet/src/test/Inet6AddressMatcherTest.java 2006-05-01 22:20:02 UTC
(rev 8599)
+++ trunk/freenet/src/test/Inet6AddressMatcherTest.java 2006-05-03 21:28:27 UTC
(rev 8600)
@@ -0,0 +1,65 @@
+/*
+ * freenet0.7 -
+ * Copyright (C) 2006 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package test;
+
+import java.net.InetAddress;
+
+import junit.framework.TestCase;
+import freenet.io.Inet6AddressMatcher;
+
+/**
+ * Test case for the {@link freenet.io.Inet6AddressMatcher} class. Contains
some
+ * very basic tests. Feel free to add more complicated tests!
+ *
+ * @author David Roden <droden at gmail.com>
+ * @version $Id$
+ */
+public class Inet6AddressMatcherTest extends TestCase {
+
+ public void test() throws Exception {
+ Inet6AddressMatcher matcher = new
Inet6AddressMatcher("0:0:0:0:0:0:0:0/0");
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:203:dff:fe22:420f")));
+
+ matcher = new
Inet6AddressMatcher("fe80:0:0:0:203:dff:fe22:420f/64");
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:203:dff:fe22:420f")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0204:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("fe81:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("0:0:0:0:0:0:0:1")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0:0:0:1")));
+
+ matcher = new
Inet6AddressMatcher("fe80:0:0:0:203:dff:fe22:420f/ffff:ffff:ffff:ffff:0:0:0:0");
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:203:dff:fe22:420f")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0204:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("fe81:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("0:0:0:0:0:0:0:1")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0:0:0:1")));
+
+ matcher = new
Inet6AddressMatcher("fe80:0:0:0:203:dff:fe22:420f/128");
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:203:dff:fe22:420f")));
+ assertEquals(true,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0204:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("fe81:0:0:0:0203:0dff:fe22:420f")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("0:0:0:0:0:0:0:1")));
+ assertEquals(false,
matcher.matches(InetAddress.getByName("fe80:0:0:0:0:0:0:1")));
+ }
+
+}
Property changes on: trunk/freenet/src/test/Inet6AddressMatcherTest.java
___________________________________________________________________
Name: svn:keywords
+ Id