From 688f0357a581b6711c8e2b2410e43d31b78d35ce Mon Sep 17 00:00:00 2001
From: Hari Babu <haribabuk@fast.au.fujitsu.com>
Date: Mon, 7 Nov 2016 16:36:14 +1100
Subject: [PATCH] INET ipv6 default zone support

::1%0 is the default zone that is used for the global addresses
Add the support for INET to ignore the default zone and store
the actual IP address.

Once the Zone id related stuff gets standardized, lets support
storing all zoneid data as part of IP address.
---
 src/backend/utils/adt/inet_net_pton.c | 12 +++++++++++-
 src/test/regress/expected/inet.out    | 21 +++++++++++++++++++--
 src/test/regress/sql/inet.sql         | 10 ++++++++--
 3 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/src/backend/utils/adt/inet_net_pton.c b/src/backend/utils/adt/inet_net_pton.c
index b8fa7d2..368f369 100644
--- a/src/backend/utils/adt/inet_net_pton.c
+++ b/src/backend/utils/adt/inet_net_pton.c
@@ -513,6 +512,17 @@ inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
 		}
 		if (ch == '/' && getbits(src, &bits) > 0)
 			break;
+		if (ch == '%')
+		{
+			if (*src == '\0')
+				goto enoent;
+
+			ch = *src++;
+			if (ch != '0' || (*src != '\0' && *src != '/'))
+				goto enoent;
+			continue;
+		}
+
 		goto enoent;
 	}
 	if (saw_xdigit)
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index be9427e..55d0867 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -19,8 +19,8 @@ INSERT INTO INET_TBL (c, i) VALUES ('10.1', '10.1.2.3/16');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
-INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1', '10:23::f1/64');
-INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000/113', '10:23::ffff');
+INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1%0', '10:23::f1%0/64');
+INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000%0/113', '10:23::ffff%0');
 INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24');
 -- check that CIDR rejects invalid input:
 INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.168.1.226');
@@ -43,6 +43,23 @@ ERROR:  invalid cidr value: "ffff:ffff:ffff:ffff::/24"
 LINE 1: INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:fff...
                                                  ^
 DETAIL:  Value has bits set to right of mask.
+-- check for ipv6 default zoneid rejects
+INSERT INTO INET_TBL (c, i) VALUES ('::1%01', '::1%0');
+ERROR:  invalid input syntax for type cidr: "::1%01"
+LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('::1%01', '::1%0');
+                                            ^
+INSERT INTO INET_TBL (c, i) VALUES ('::1%0', '::1%01');
+ERROR:  invalid input syntax for type inet: "::1%01"
+LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('::1%0', '::1%01');
+                                                     ^
+INSERT INTO INET_TBL (c, i) VALUES ('::1%0%1', '::1%0%1');
+ERROR:  invalid input syntax for type cidr: "::1%0%1"
+LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('::1%0%1', '::1%0%1');
+                                            ^
+INSERT INTO INET_TBL (c, i) VALUES ('::1%', '::1/24%');
+ERROR:  invalid input syntax for type cidr: "::1%"
+LINE 1: INSERT INTO INET_TBL (c, i) VALUES ('::1%', '::1/24%');
+                                            ^
 SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
  ten |        cidr        |       inet       
 -----+--------------------+------------------
diff --git a/src/test/regress/sql/inet.sql b/src/test/regress/sql/inet.sql
index 880e115..57fb411 100644
--- a/src/test/regress/sql/inet.sql
+++ b/src/test/regress/sql/inet.sql
@@ -20,8 +20,8 @@ INSERT INTO INET_TBL (c, i) VALUES ('10.1', '10.1.2.3/16');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '10.1.2.3/8');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '11.1.2.3/8');
 INSERT INTO INET_TBL (c, i) VALUES ('10', '9.1.2.3/8');
-INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1', '10:23::f1/64');
-INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000/113', '10:23::ffff');
+INSERT INTO INET_TBL (c, i) VALUES ('10:23::f1%0', '10:23::f1%0/64');
+INSERT INTO INET_TBL (c, i) VALUES ('10:23::8000%0/113', '10:23::ffff%0');
 INSERT INTO INET_TBL (c, i) VALUES ('::ffff:1.2.3.4', '::4.3.2.1/24');
 -- check that CIDR rejects invalid input:
 INSERT INTO INET_TBL (c, i) VALUES ('192.168.1.2/30', '192.168.1.226');
@@ -29,6 +29,12 @@ INSERT INTO INET_TBL (c, i) VALUES ('1234::1234::1234', '::1.2.3.4');
 -- check that CIDR rejects invalid input when converting from text:
 INSERT INTO INET_TBL (c, i) VALUES (cidr('192.168.1.2/30'), '192.168.1.226');
 INSERT INTO INET_TBL (c, i) VALUES (cidr('ffff:ffff:ffff:ffff::/24'), '::192.168.1.226');
+-- check for ipv6 default zoneid rejects
+INSERT INTO INET_TBL (c, i) VALUES ('::1%01', '::1%0');
+INSERT INTO INET_TBL (c, i) VALUES ('::1%0', '::1%01');
+INSERT INTO INET_TBL (c, i) VALUES ('::1%0%1', '::1%0%1');
+INSERT INTO INET_TBL (c, i) VALUES ('::1%', '::1/24%');
+
 SELECT '' AS ten, c AS cidr, i AS inet FROM INET_TBL;
 
 -- now test some support functions
-- 
2.7.4.windows.1

