Browse Source

Decouple MinGW functionality

NX 7 years ago
parent
commit
26f60030e0
3 changed files with 430 additions and 207 deletions
  1. 14 207
      Source/Native/enet.h
  2. 194 0
      Source/Native/mingw/inet_ntop.c
  3. 222 0
      Source/Native/mingw/inet_pton.c

+ 14 - 207
Source/Native/enet.h

@@ -59,6 +59,11 @@
 // =======================================================================//
 
 #ifdef _WIN32
+    #ifdef __MINGW32__
+        #include "mingw/inet_ntop.c"
+        #include "mingw/inet_pton.c"
+    #endif
+
     #if defined(_MSC_VER) && defined(ENET_IMPLEMENTATION)
         #pragma warning(disable: 4267) /* size_t to int conversion */
         #pragma warning(disable: 4244) /* 64bit to 32bit int */
@@ -670,7 +675,7 @@ extern "C" {
         ENetBuffer            buffers[ENET_BUFFER_MAXIMUM];
         size_t                bufferCount;
         enet_uint8            compression;
-        ENetChecksumCallback  checksum;
+        ENetChecksumCallback  checksumCallback;
         enet_uint8            packetData[2][ENET_PROTOCOL_MAXIMUM_MTU];
         ENetAddress           receivedAddress;
         enet_uint8 *          receivedData;
@@ -2261,7 +2266,7 @@ extern "C" {
 
         headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof(ENetProtocolHeader) : (size_t)&((ENetProtocolHeader *)0)->sentTime);
 
-        if (host->checksum != NULL) {
+        if (host->checksumCallback != NULL) {
             headerSize += sizeof(enet_uint32);
         }
 
@@ -2298,7 +2303,7 @@ extern "C" {
             }
         #endif
 
-        if (host->checksum != NULL) {
+        if (host->checksumCallback != NULL) {
             enet_uint32 *checksum = (enet_uint32 *)&host->receivedData[headerSize - sizeof(enet_uint32)];
             enet_uint32 desiredChecksum = *checksum;
             ENetBuffer buffer;
@@ -2308,7 +2313,7 @@ extern "C" {
             buffer.data       = host->receivedData;
             buffer.dataLength = host->receivedDataLength;
 
-            if (host->checksum(&buffer, 1) != desiredChecksum) {
+            if (host->checksumCallback(&buffer, 1) != desiredChecksum) {
                 return 0;
             }
         }
@@ -2981,11 +2986,11 @@ extern "C" {
 
                 header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags);
 
-                if (host->checksum != NULL) {
+                if (host->checksumCallback != NULL) {
                     enet_uint32 *checksum = (enet_uint32 *)&headerData[host->buffers->dataLength];
                     *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0;
                     host->buffers->dataLength += sizeof(enet_uint32);
-                    *checksum = host->checksum(host->buffers, host->bufferCount);
+                    *checksum = host->checksumCallback(host->buffers, host->bufferCount);
                 }
 
                 #ifdef ENET_LZ4
@@ -3205,7 +3210,7 @@ extern "C" {
 
         fragmentLength = peer->mtu - sizeof(ENetProtocolHeader) - sizeof(ENetProtocolSendFragment);
 
-        if (peer->host->checksum != NULL) {
+        if (peer->host->checksumCallback != NULL) {
             fragmentLength -= sizeof(enet_uint32);
         }
 
@@ -4051,7 +4056,7 @@ extern "C" {
         host->commandCount                  = 0;
         host->bufferCount                   = 0;
         host->compression                   = 0;
-        host->checksum                      = NULL;
+        host->checksumCallback              = NULL;
         host->receivedAddress.host          = ENET_HOST_ANY;
         host->receivedAddress.port          = 0;
         host->receivedData                  = NULL;
@@ -5046,204 +5051,6 @@ extern "C" {
 // =======================================================================//
 
     #ifdef _WIN32
-        #ifdef __MINGW32__
-            const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) {
-                if (af == AF_INET) {
-                    struct sockaddr_in in;
-                    memset(&in, 0, sizeof(in));
-                    in.sin_family = AF_INET;
-                    memcpy(&in.sin_addr, src, sizeof(struct in_addr));
-                    getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
-
-                    return dst;
-                } else if (af == AF_INET6) {
-                    struct sockaddr_in6 in;
-                    memset(&in, 0, sizeof(in));
-                    in.sin6_family = AF_INET6;
-                    memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
-                    getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
-
-                    return dst;
-                }
-
-                return NULL;
-            }
-
-            #define NS_INADDRSZ  4
-            #define NS_IN6ADDRSZ 16
-            #define NS_INT16SZ   2
-
-            int inet_pton4(const char *src, char *dst) {
-                uint8_t tmp[NS_INADDRSZ], *tp;
-
-                int saw_digit = 0;
-                int octets = 0;
-                *(tp = tmp) = 0;
-
-                int ch;
-
-                while ((ch = *src++) != '\0') {
-                    if (ch >= '0' && ch <= '9') {
-                        uint32_t n = *tp * 10 + (ch - '0');
-
-                        if (saw_digit && *tp == 0)
-                            return 0;
-
-                        if (n > 255)
-                            return 0;
-
-                        *tp = n;
-
-                        if (!saw_digit) {
-                            if (++octets > 4) {
-                                return 0;
-                            }
-
-                            saw_digit = 1;
-                        }
-                    } else if (ch == '.' && saw_digit) {
-                        if (octets == 4) {
-                            return 0;
-                        }
-
-                        *++tp = 0;
-                        saw_digit = 0;
-                    } else
-                        return 0;
-                }
-
-                if (octets < 4) {
-                    return 0;
-                }
-
-                memcpy(dst, tmp, NS_INADDRSZ);
-
-                return 1;
-            }
-
-            int inet_pton6(const char *src, char *dst) {
-                static const char xdigits[] = "0123456789abcdef";
-                uint8_t tmp[NS_IN6ADDRSZ];
-
-                uint8_t *tp = (uint8_t*)memset(tmp, '\0', NS_IN6ADDRSZ);
-                uint8_t *endp = tp + NS_IN6ADDRSZ;
-                uint8_t *colonp = NULL;
-
-                /* Leading :: requires some special handling. */
-                if (*src == ':') {
-                    if (*++src != ':') {
-                        return 0;
-                    }
-                }
-
-                const char *curtok = src;
-                int saw_xdigit = 0;
-                uint32_t val = 0;
-                int ch;
-
-                while ((ch = tolower(*src++)) != '\0') {
-                    const char *pch = strchr(xdigits, ch);
-
-                    if (pch != NULL) {
-                        val <<= 4;
-                        val |= (pch - xdigits);
-
-                        if (val > 0xffff) {
-                            return 0;
-                        }
-
-                        saw_xdigit = 1;
-
-                        continue;
-                    }
-
-                    if (ch == ':') {
-                        curtok = src;
-                        if (!saw_xdigit) {
-                            if (colonp) {
-                                return 0;
-                            }
-
-                            colonp = tp;
-
-                            continue;
-                        } else if (*src == '\0') {
-                            return 0;
-                        }
-
-                        if (tp + NS_INT16SZ > endp) {
-                            return 0;
-                        }
-
-                        *tp++ = (uint8_t) (val >> 8) & 0xff;
-                        *tp++ = (uint8_t) val & 0xff;
-                        saw_xdigit = 0;
-                        val = 0;
-
-                        continue;
-                    }
-
-                    if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, (char *)tp) > 0) {
-                        tp += NS_INADDRSZ;
-                        saw_xdigit = 0;
-
-                        break; /* '\0' was seen by inet_pton4(). */
-                    }
-
-                    return 0;
-                }
-
-                if (saw_xdigit) {
-                    if (tp + NS_INT16SZ > endp) {
-                        return 0;
-                    }
-
-                    *tp++ = (uint8_t) (val >> 8) & 0xff;
-                    *tp++ = (uint8_t) val & 0xff;
-                }
-
-                if (colonp != NULL) {
-                    /*
-                     * Since some memmove()'s erroneously fail to handle
-                     * overlapping regions, we'll do the shift by hand.
-                     */
-                    const int n = tp - colonp;
-
-                    if (tp == endp) {
-                        return 0;
-                    }
-
-                    for (int i = 1; i <= n; i++) {
-                        endp[-i] = colonp[n - i];
-                        colonp[n - i] = 0;
-                    }
-
-                    tp = endp;
-                }
-
-                if (tp != endp) {
-                    return 0;
-                }
-
-                memcpy(dst, tmp, NS_IN6ADDRSZ);
-
-                return 1;
-            }
-
-            int inet_pton(int af, const char *src, struct in6_addr *dst) {
-                switch (af) {
-                    case AF_INET:
-                        return inet_pton4(src, (char *)dst);
-
-                    case AF_INET6:
-                        return inet_pton6(src, (char *)dst);
-
-                    default:
-                        return -1;
-                }
-            }
-        #endif
-
         int enet_initialize(void) {
             WORD versionRequested = MAKEWORD(1, 1);
             WSADATA wsaData;
@@ -5626,4 +5433,4 @@ extern "C" {
 }
 #endif
 #endif
-#endif
+#endif

+ 194 - 0
Source/Native/mingw/inet_ntop.c

@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_ntop.c,v 1.3.18.2 2005/11/03 23:02:22 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __FreeBSD__
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/9/sys/libkern/inet_ntop.c 213103 2010-09-24 15:01:45Z attilio $");
+#endif
+
+#if !defined(_WIN32)
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#else
+#include <ws2tcpip.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(_WIN32) && __FreeBSD_version < 700000
+#define strchr index
+#endif
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static char *inet_ntop4(const u_char * src, char *dst, socklen_t size);
+static char *inet_ntop6(const u_char * src, char *dst, socklen_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ *	convert a network format address to presentation format.
+ * return:
+ *	pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ *	Paul Vixie, 1996.
+ */
+char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
+{
+    switch (af) {
+    case AF_INET:
+        return (inet_ntop4(src, dst, size));
+    case AF_INET6:
+        return (inet_ntop6(src, dst, size));
+    default:
+        return (NULL);
+    }
+    /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ *	format an IPv4 address
+ * return:
+ *	`dst' (as a const)
+ * notes:
+ *	(1) uses no statics
+ *	(2) takes a u_char* not an in_addr as input
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static char *inet_ntop4(const u_char * src, char *dst, socklen_t size)
+{
+    static const char fmt[] = "%u.%u.%u.%u";
+    char tmp[sizeof "255.255.255.255"];
+    int l;
+
+    l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+    if (l <= 0 || (socklen_t) l >= size) {
+        return (NULL);
+    }
+//      strlcpy(dst, tmp, size);
+    memcpy(dst, tmp, size);
+    dst[size] = '\0';
+    return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ *	convert IPv6 binary address into presentation (printable) format
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static char *inet_ntop6(const u_char * src, char *dst, socklen_t size)
+{
+    /*
+     * Note that int32_t and int16_t need only be "at least" large enough
+     * to contain a value of the specified size.  On some systems, like
+     * Crays, there is no such thing as an integer variable with 16 bits.
+     * Keep this in mind if you think this function should have been coded
+     * to use pointer overlays.  All the world's not a VAX.
+     */
+    char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+    struct {
+        int base, len;
+    } best, cur;
+#define NS_IN6ADDRSZ	16
+#define NS_INT16SZ	2
+    u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+    int i;
+
+    /*
+     * Preprocess:
+     *      Copy the input (bytewise) array into a wordwise array.
+     *      Find the longest run of 0x00's in src[] for :: shorthanding.
+     */
+    memset(words, '\0', sizeof words);
+    for (i = 0; i < NS_IN6ADDRSZ; i++)
+        words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+    best.base = -1;
+    best.len = 0;
+    cur.base = -1;
+    cur.len = 0;
+    for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+        if (words[i] == 0) {
+            if (cur.base == -1)
+                cur.base = i, cur.len = 1;
+            else
+                cur.len++;
+        } else {
+            if (cur.base != -1) {
+                if (best.base == -1 || cur.len > best.len)
+                    best = cur;
+                cur.base = -1;
+            }
+        }
+    }
+    if (cur.base != -1) {
+        if (best.base == -1 || cur.len > best.len)
+            best = cur;
+    }
+    if (best.base != -1 && best.len < 2)
+        best.base = -1;
+
+    /*
+     * Format the result.
+     */
+    tp = tmp;
+    for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+        /* Are we inside the best run of 0x00's? */
+        if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
+            if (i == best.base)
+                *tp++ = ':';
+            continue;
+        }
+        /* Are we following an initial run of 0x00s or any real hex? */
+        if (i != 0)
+            *tp++ = ':';
+        /* Is this address an encapsulated IPv4? */
+        if (i == 6 && best.base == 0 && (best.len == 6 ||
+                                         (best.len == 7 && words[7] != 0x0001) ||
+                                         (best.len == 5 && words[5] == 0xffff))) {
+            if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
+                return (NULL);
+            tp += strlen(tp);
+            break;
+        }
+        tp += sprintf(tp, "%x", words[i]);
+    }
+    /* Was it a trailing run of 0x00's? */
+    if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
+        *tp++ = ':';
+    *tp++ = '\0';
+
+    /*
+     * Check for overflow, copy, and we're done.
+     */
+    if ((socklen_t) (tp - tmp) > size) {
+        return (NULL);
+    }
+    strcpy(dst, tmp);
+    return (dst);
+}
+/*! \file */

+ 222 - 0
Source/Native/mingw/inet_pton.c

@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_pton.c,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __FreeBSD__
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/9/sys/libkern/inet_pton.c 213103 2010-09-24 15:01:45Z attilio $");
+#endif
+
+#if !defined(_WIN32) 
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#else
+#include <ws2tcpip.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(_WIN32) && __FreeBSD_version < 700000
+#define strchr index
+#endif
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, u_char * dst);
+static int inet_pton6(const char *src, u_char * dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ *	convert from presentation format (which usually means ASCII printable)
+ *	to network format (which is usually some kind of binary format).
+ * return:
+ *	1 if the address was valid for the specified address family
+ *	0 if the address wasn't valid (`dst' is untouched in this case)
+ *	-1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ *	Paul Vixie, 1996.
+ */
+int inet_pton(int af, const char *src, void *dst)
+{
+    switch (af) {
+    case AF_INET:
+        return (inet_pton4(src, dst));
+    case AF_INET6:
+        return (inet_pton6(src, dst));
+    default:
+        return (-1);
+    }
+    /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ *	like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ *	1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ *	does not touch `dst' unless it's returning 1.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int inet_pton4(const char *src, u_char * dst)
+{
+    static const char digits[] = "0123456789";
+    int saw_digit, octets, ch;
+#define NS_INADDRSZ	4
+    u_char tmp[NS_INADDRSZ], *tp;
+
+    saw_digit = 0;
+    octets = 0;
+    *(tp = tmp) = 0;
+    while ((ch = *src++) != '\0') {
+        const char *pch;
+
+        if ((pch = strchr(digits, ch)) != NULL) {
+            u_int new = *tp * 10 + (pch - digits);
+
+            if (saw_digit && *tp == 0)
+                return (0);
+            if (new > 255)
+                return (0);
+            *tp = new;
+            if (!saw_digit) {
+                if (++octets > 4)
+                    return (0);
+                saw_digit = 1;
+            }
+        } else if (ch == '.' && saw_digit) {
+            if (octets == 4)
+                return (0);
+            *++tp = 0;
+            saw_digit = 0;
+        } else
+            return (0);
+    }
+    if (octets < 4)
+        return (0);
+    memcpy(dst, tmp, NS_INADDRSZ);
+    return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ *	convert presentation level address to network order binary form.
+ * return:
+ *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *	(1) does not touch `dst' unless it's returning 1.
+ *	(2) :: in a full address is silently ignored.
+ * credit:
+ *	inspired by Mark Andrews.
+ * author:
+ *	Paul Vixie, 1996.
+ */
+static int inet_pton6(const char *src, u_char * dst)
+{
+    static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF";
+#define NS_IN6ADDRSZ	16
+#define NS_INT16SZ	2
+    u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+    const char *xdigits, *curtok;
+    int ch, seen_xdigits;
+    u_int val;
+
+    memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+    endp = tp + NS_IN6ADDRSZ;
+    colonp = NULL;
+    /* Leading :: requires some special handling. */
+    if (*src == ':')
+        if (*++src != ':')
+            return (0);
+    curtok = src;
+    seen_xdigits = 0;
+    val = 0;
+    while ((ch = *src++) != '\0') {
+        const char *pch;
+
+        if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+            pch = strchr((xdigits = xdigits_u), ch);
+        if (pch != NULL) {
+            val <<= 4;
+            val |= (pch - xdigits);
+            if (++seen_xdigits > 4)
+                return (0);
+            continue;
+        }
+        if (ch == ':') {
+            curtok = src;
+            if (!seen_xdigits) {
+                if (colonp)
+                    return (0);
+                colonp = tp;
+                continue;
+            } else if (*src == '\0') {
+                return (0);
+            }
+            if (tp + NS_INT16SZ > endp)
+                return (0);
+            *tp++ = (u_char) (val >> 8) & 0xff;
+            *tp++ = (u_char) val & 0xff;
+            seen_xdigits = 0;
+            val = 0;
+            continue;
+        }
+        if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) {
+            tp += NS_INADDRSZ;
+            seen_xdigits = 0;
+            break;              /*%< '\\0' was seen by inet_pton4(). */
+        }
+        return (0);
+    }
+    if (seen_xdigits) {
+        if (tp + NS_INT16SZ > endp)
+            return (0);
+        *tp++ = (u_char) (val >> 8) & 0xff;
+        *tp++ = (u_char) val & 0xff;
+    }
+    if (colonp != NULL) {
+        /*
+         * Since some memmove()'s erroneously fail to handle
+         * overlapping regions, we'll do the shift by hand.
+         */
+        const int n = tp - colonp;
+        int i;
+
+        if (tp == endp)
+            return (0);
+        for (i = 1; i <= n; i++) {
+            endp[-i] = colonp[n - i];
+            colonp[n - i] = 0;
+        }
+        tp = endp;
+    }
+    if (tp != endp)
+        return (0);
+    memcpy(dst, tmp, NS_IN6ADDRSZ);
+    return (1);
+}
+/*! \file */