From 7bd220adfc55f83aef286d79f41feed8b33bb4ee Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Mon, 19 Dec 2022 08:35:15 -0500
Subject: [PATCH] Console: Fix IPv6 searches for compressed/expanded address
 format

---
 .../i2p/router/web/helpers/NetDbRenderer.java | 47 ++++++++++++++++++-
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java
index d16478748b..39bb3fcfdf 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java
@@ -49,6 +49,7 @@ import net.i2p.router.transport.GeoIP;
 import net.i2p.router.web.HelperBase;
 import net.i2p.router.web.Messages;
 import net.i2p.router.web.WebAppStarter;
+import net.i2p.util.Addresses;
 import net.i2p.util.ConvertToHash;
 import net.i2p.util.Log;
 import net.i2p.util.ObjectCounter;
@@ -196,6 +197,7 @@ class NetDbRenderer {
             Set<RouterInfo> routers = _context.netDb().getRouters();
             int ipMode = 0;
             String ipArg = ip;  // save for error message
+            String altIPv6 = null;
             if (ip != null) {
                 if (ip.endsWith("/24")) {
                     ipMode = 1;
@@ -205,6 +207,13 @@ class NetDbRenderer {
                     ipMode = 3;
                 } else if (ip.indexOf(':') > 0) {
                     ipMode = 4;
+                    if (ip.endsWith("::")) {
+                        // truncate for prefix search
+                        ip = ip.substring(0, ip.length() - 1);
+                    } else {
+                        // We don't canonicalize as we search, so create alt string to check also
+                        altIPv6 = getAltIPv6(ip);
+                    }
                 }
                 if (ipMode > 0 && ipMode < 4) {
                     for (int i = 0; i < ipMode; i++) {
@@ -214,6 +223,15 @@ class NetDbRenderer {
                     }
                 }
             }
+            if (ipv6 != null) {
+                if (ipv6.endsWith("::")) {
+                    // truncate for prefix search
+                    ipv6 = ipv6.substring(0, ipv6.length() - 1);
+                } else {
+                    // We don't canonicalize as we search, so create alt string to check also
+                    altIPv6 = getAltIPv6(ipv6);
+                }
+            }
             String familyArg = family;  // save for error message
             if (family != null)
                 family = family.toLowerCase(Locale.US);
@@ -311,7 +329,8 @@ class NetDbRenderer {
                             }
                         } else {
                             String host = ra.getHost();
-                            if (host != null && host.startsWith(ip)) {
+                            if (host != null && (host.startsWith(ip) ||
+                                                 (altIPv6 != null && host.startsWith(altIPv6)))) {
                                 if (skipped < toSkip) {
                                     skipped++;
                                     break;
@@ -367,7 +386,8 @@ class NetDbRenderer {
                 } else if (ipv6 != null) {
                     for (RouterAddress ra : ri.getAddresses()) {
                         String host = ra.getHost();
-                        if (host != null && host.startsWith(ipv6)) {
+                        if (host != null && (host.startsWith(ipv6) ||
+                                             (altIPv6 != null && host.startsWith(altIPv6)))) {
                             if (skipped < toSkip) {
                                 skipped++;
                                 break;
@@ -1226,6 +1246,29 @@ class NetDbRenderer {
         return rv;
     }
 
+    /**
+     *  If ipv6 is in compressed form, return expanded form.
+     *  If ipv6 is in expanded form, return compressed form.
+     *  Else return null.
+     *
+     *  @param ip ipv6 only, not ending with ::
+     *  @return alt string or null
+     *  @since 0.9.57
+     */
+    private static String getAltIPv6(String ip) {
+        if (ip.contains("::")) {
+            // convert to expanded
+            byte[] bip = Addresses.getIP(ip);
+            if (bip != null)
+                return Addresses.toString(bip);
+        } else if (ip.contains(":0:")) {
+            // convert to canonical
+            // https://stackoverflow.com/questions/7043983/ipv6-address-into-compressed-form-in-java
+            return ip.replaceAll("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)", "::$2").replaceFirst("^0::","::");
+        }		
+        return null;
+    }
+
     /** translate a string */
     private String _t(String s) {
         return Messages.getString(s, _context);
-- 
GitLab