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 &lt;droden at gmail.com&gt;
+ * @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 &lt;droden at gmail.com&gt;
+ * @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 &lt;droden at gmail.com&gt;
  * @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 &lt;droden at gmail.com&gt;
+ * @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 &lt;droden at gmail.com&gt;
+ * @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 &lt;droden at gmail.com&gt;
+ * @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


Reply via email to