Changeset: df35bc83e5f5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/df35bc83e5f5
Modified Files:
        gdk/gdk_atoms.c
Branch: inet4+6
Log Message:

Implemented reading and writing IPv4-mapped IPv6 addresses.
E.g. ::ffff:192.168.2.128 which is the result of converting IPv4 address
192.168.2.128 to IPv6.
See https://en.wikipedia.org/wiki/IPv6_address#Representation


diffs (98 lines):

diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c
--- a/gdk/gdk_atoms.c
+++ b/gdk/gdk_atoms.c
@@ -1517,10 +1517,11 @@ INET6fromString(const char *svalue, size
        }
        int dcolpos = -1;
        int i;
+       int maybeip4 = 0;
        for (i = 0; i < 8; i++) {
                if (s[0] == ':' && s[1] == ':') {
                        if (dcolpos >= 0) {
-                               GDKerror("Invalid IPv6 address.");
+                               GDKerror("Invalid IPv6 address: multiple ::.");
                                goto bailout;
                        }
                        dcolpos = i;
@@ -1531,13 +1532,54 @@ INET6fromString(const char *svalue, size
                if (*s == 0 || (brkt && *s == ']'))
                        break;
                char *e;
-               unsigned long ul = strtoul(s, &e, 16);
+               unsigned long ul;
+               if (maybeip4 == 1 && (dcolpos == -1 ? i == 6 : i < 6)) {
+                       ul = strtoul(s, &e, 10);
+                       if (e > s && *e == '.') {
+                               /* address such as ::ffff:192.0.2.128
+                                * i.e. an IPv4 address inside an
+                                * IPv6 */
+                               if (ul > 255) {
+                                       GDKerror("Invalid IPv6 address.");
+                                       goto bailout;
+                               }
+                               s = e + 1;
+                               unsigned long u2 = strtoul(s, &e, 10);
+                               if (e == s || *e != '.' || u2 > 255) {
+                                       GDKerror("Invalid IPv6 address.");
+                                       goto bailout;
+                               }
+                               i6.oct[i++] = (uint16_t) ((ul << 8) | u2);
+                               s = e + 1;
+                               ul = strtoul(s, &e, 10);
+                               if (e == s || *e != '.' || ul > 255) {
+                                       GDKerror("Invalid IPv6 address.");
+                                       goto bailout;
+                               }
+                               s = e + 1;
+                               u2 = strtoul(s, &e, 10);
+                               if (e == s || u2 > 255) {
+                                       GDKerror("Invalid IPv6 address.");
+                                       goto bailout;
+                               }
+                               i6.oct[i++] = (uint16_t) ((ul << 8) | u2);
+                               s = e;
+                               break;
+                       }
+               }
+               ul = strtoul(s, &e, 16);
                if (e == s || ul > 65535) {
                        GDKerror("Invalid IPv6 address.");
                        goto bailout;
                }
                i6.oct[i] = (uint16_t) ul;
                s = e;
+               if (maybeip4 == 0) {
+                       if (ul == 0xFFFF)
+                               maybeip4 = 1;
+                       else if (ul != 0)
+                               maybeip4 = -1;
+               }
        }
        if (brkt) {
                if (*s != ']') {
@@ -1559,6 +1601,10 @@ INET6fromString(const char *svalue, size
        }
        while (GDKisspace(*s))
                s++;
+       if (*s) {
+               GDKerror("Garbage at end of IPv6 address.");
+               goto bailout;
+       }
 
        **retval = i6;
        return (ssize_t) (s - svalue);
@@ -1634,6 +1680,14 @@ INET6toString(str *retval, size_t *len, 
        if (mrl1 < 0)
                mrl1 = 8;
        int pos = 0;
+       if (mrl1 == 0 && mrl == 5 && value->oct[5] == 0xFFFF) {
+               pos += snprintf(*retval + pos, *len - pos,
+                               "::%x:%d.%d.%d.%d",
+                               value->oct[5], value->oct[6] >> 8,
+                               value->oct[6] & 0xFF, value->oct[7] >> 8,
+                               value->oct[7] & 0xFF);
+               return pos;
+       }
        for (int i = 0; i < mrl1; i++) {
                if (i > 0)
                        (*retval)[pos++] = ':';
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to