1e66f31c5Sopenharmony_ci/* 2e66f31c5Sopenharmony_ci * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3e66f31c5Sopenharmony_ci * Copyright (c) 1996-1999 by Internet Software Consortium. 4e66f31c5Sopenharmony_ci * 5e66f31c5Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any 6e66f31c5Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 7e66f31c5Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 8e66f31c5Sopenharmony_ci * 9e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10e66f31c5Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11e66f31c5Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12e66f31c5Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13e66f31c5Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14e66f31c5Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15e66f31c5Sopenharmony_ci * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16e66f31c5Sopenharmony_ci */ 17e66f31c5Sopenharmony_ci 18e66f31c5Sopenharmony_ci#include <stdio.h> 19e66f31c5Sopenharmony_ci#include <string.h> 20e66f31c5Sopenharmony_ci#include <stdint.h> 21e66f31c5Sopenharmony_ci 22e66f31c5Sopenharmony_ci#include "uv.h" 23e66f31c5Sopenharmony_ci#include "uv-common.h" 24e66f31c5Sopenharmony_ci 25e66f31c5Sopenharmony_ci#define UV__INET_ADDRSTRLEN 16 26e66f31c5Sopenharmony_ci#define UV__INET6_ADDRSTRLEN 46 27e66f31c5Sopenharmony_ci 28e66f31c5Sopenharmony_ci 29e66f31c5Sopenharmony_cistatic int inet_ntop4(const unsigned char *src, char *dst, size_t size); 30e66f31c5Sopenharmony_cistatic int inet_ntop6(const unsigned char *src, char *dst, size_t size); 31e66f31c5Sopenharmony_cistatic int inet_pton4(const char *src, unsigned char *dst); 32e66f31c5Sopenharmony_cistatic int inet_pton6(const char *src, unsigned char *dst); 33e66f31c5Sopenharmony_ci 34e66f31c5Sopenharmony_ci 35e66f31c5Sopenharmony_ciint uv_inet_ntop(int af, const void* src, char* dst, size_t size) { 36e66f31c5Sopenharmony_ci switch (af) { 37e66f31c5Sopenharmony_ci case AF_INET: 38e66f31c5Sopenharmony_ci return (inet_ntop4(src, dst, size)); 39e66f31c5Sopenharmony_ci case AF_INET6: 40e66f31c5Sopenharmony_ci return (inet_ntop6(src, dst, size)); 41e66f31c5Sopenharmony_ci default: 42e66f31c5Sopenharmony_ci return UV_EAFNOSUPPORT; 43e66f31c5Sopenharmony_ci } 44e66f31c5Sopenharmony_ci /* NOTREACHED */ 45e66f31c5Sopenharmony_ci} 46e66f31c5Sopenharmony_ci 47e66f31c5Sopenharmony_ci 48e66f31c5Sopenharmony_cistatic int inet_ntop4(const unsigned char *src, char *dst, size_t size) { 49e66f31c5Sopenharmony_ci static const char fmt[] = "%u.%u.%u.%u"; 50e66f31c5Sopenharmony_ci char tmp[UV__INET_ADDRSTRLEN]; 51e66f31c5Sopenharmony_ci int l; 52e66f31c5Sopenharmony_ci 53e66f31c5Sopenharmony_ci l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); 54e66f31c5Sopenharmony_ci if (l <= 0 || (size_t) l >= size) { 55e66f31c5Sopenharmony_ci return UV_ENOSPC; 56e66f31c5Sopenharmony_ci } 57e66f31c5Sopenharmony_ci uv__strscpy(dst, tmp, size); 58e66f31c5Sopenharmony_ci return 0; 59e66f31c5Sopenharmony_ci} 60e66f31c5Sopenharmony_ci 61e66f31c5Sopenharmony_ci 62e66f31c5Sopenharmony_cistatic int inet_ntop6(const unsigned char *src, char *dst, size_t size) { 63e66f31c5Sopenharmony_ci /* 64e66f31c5Sopenharmony_ci * Note that int32_t and int16_t need only be "at least" large enough 65e66f31c5Sopenharmony_ci * to contain a value of the specified size. On some systems, like 66e66f31c5Sopenharmony_ci * Crays, there is no such thing as an integer variable with 16 bits. 67e66f31c5Sopenharmony_ci * Keep this in mind if you think this function should have been coded 68e66f31c5Sopenharmony_ci * to use pointer overlays. All the world's not a VAX. 69e66f31c5Sopenharmony_ci */ 70e66f31c5Sopenharmony_ci char tmp[UV__INET6_ADDRSTRLEN], *tp; 71e66f31c5Sopenharmony_ci struct { int base, len; } best, cur; 72e66f31c5Sopenharmony_ci unsigned int words[sizeof(struct in6_addr) / sizeof(uint16_t)]; 73e66f31c5Sopenharmony_ci int i; 74e66f31c5Sopenharmony_ci 75e66f31c5Sopenharmony_ci /* 76e66f31c5Sopenharmony_ci * Preprocess: 77e66f31c5Sopenharmony_ci * Copy the input (bytewise) array into a wordwise array. 78e66f31c5Sopenharmony_ci * Find the longest run of 0x00's in src[] for :: shorthanding. 79e66f31c5Sopenharmony_ci */ 80e66f31c5Sopenharmony_ci memset(words, '\0', sizeof words); 81e66f31c5Sopenharmony_ci for (i = 0; i < (int) sizeof(struct in6_addr); i++) 82e66f31c5Sopenharmony_ci words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); 83e66f31c5Sopenharmony_ci best.base = -1; 84e66f31c5Sopenharmony_ci best.len = 0; 85e66f31c5Sopenharmony_ci cur.base = -1; 86e66f31c5Sopenharmony_ci cur.len = 0; 87e66f31c5Sopenharmony_ci for (i = 0; i < (int) ARRAY_SIZE(words); i++) { 88e66f31c5Sopenharmony_ci if (words[i] == 0) { 89e66f31c5Sopenharmony_ci if (cur.base == -1) 90e66f31c5Sopenharmony_ci cur.base = i, cur.len = 1; 91e66f31c5Sopenharmony_ci else 92e66f31c5Sopenharmony_ci cur.len++; 93e66f31c5Sopenharmony_ci } else { 94e66f31c5Sopenharmony_ci if (cur.base != -1) { 95e66f31c5Sopenharmony_ci if (best.base == -1 || cur.len > best.len) 96e66f31c5Sopenharmony_ci best = cur; 97e66f31c5Sopenharmony_ci cur.base = -1; 98e66f31c5Sopenharmony_ci } 99e66f31c5Sopenharmony_ci } 100e66f31c5Sopenharmony_ci } 101e66f31c5Sopenharmony_ci if (cur.base != -1) { 102e66f31c5Sopenharmony_ci if (best.base == -1 || cur.len > best.len) 103e66f31c5Sopenharmony_ci best = cur; 104e66f31c5Sopenharmony_ci } 105e66f31c5Sopenharmony_ci if (best.base != -1 && best.len < 2) 106e66f31c5Sopenharmony_ci best.base = -1; 107e66f31c5Sopenharmony_ci 108e66f31c5Sopenharmony_ci /* 109e66f31c5Sopenharmony_ci * Format the result. 110e66f31c5Sopenharmony_ci */ 111e66f31c5Sopenharmony_ci tp = tmp; 112e66f31c5Sopenharmony_ci for (i = 0; i < (int) ARRAY_SIZE(words); i++) { 113e66f31c5Sopenharmony_ci /* Are we inside the best run of 0x00's? */ 114e66f31c5Sopenharmony_ci if (best.base != -1 && i >= best.base && 115e66f31c5Sopenharmony_ci i < (best.base + best.len)) { 116e66f31c5Sopenharmony_ci if (i == best.base) 117e66f31c5Sopenharmony_ci *tp++ = ':'; 118e66f31c5Sopenharmony_ci continue; 119e66f31c5Sopenharmony_ci } 120e66f31c5Sopenharmony_ci /* Are we following an initial run of 0x00s or any real hex? */ 121e66f31c5Sopenharmony_ci if (i != 0) 122e66f31c5Sopenharmony_ci *tp++ = ':'; 123e66f31c5Sopenharmony_ci /* Is this address an encapsulated IPv4? */ 124e66f31c5Sopenharmony_ci if (i == 6 && best.base == 0 && (best.len == 6 || 125e66f31c5Sopenharmony_ci (best.len == 7 && words[7] != 0x0001) || 126e66f31c5Sopenharmony_ci (best.len == 5 && words[5] == 0xffff))) { 127e66f31c5Sopenharmony_ci int err = inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)); 128e66f31c5Sopenharmony_ci if (err) 129e66f31c5Sopenharmony_ci return err; 130e66f31c5Sopenharmony_ci tp += strlen(tp); 131e66f31c5Sopenharmony_ci break; 132e66f31c5Sopenharmony_ci } 133e66f31c5Sopenharmony_ci tp += snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]); 134e66f31c5Sopenharmony_ci } 135e66f31c5Sopenharmony_ci /* Was it a trailing run of 0x00's? */ 136e66f31c5Sopenharmony_ci if (best.base != -1 && (best.base + best.len) == ARRAY_SIZE(words)) 137e66f31c5Sopenharmony_ci *tp++ = ':'; 138e66f31c5Sopenharmony_ci *tp++ = '\0'; 139e66f31c5Sopenharmony_ci if ((size_t) (tp - tmp) > size) 140e66f31c5Sopenharmony_ci return UV_ENOSPC; 141e66f31c5Sopenharmony_ci uv__strscpy(dst, tmp, size); 142e66f31c5Sopenharmony_ci return 0; 143e66f31c5Sopenharmony_ci} 144e66f31c5Sopenharmony_ci 145e66f31c5Sopenharmony_ci 146e66f31c5Sopenharmony_ciint uv_inet_pton(int af, const char* src, void* dst) { 147e66f31c5Sopenharmony_ci if (src == NULL || dst == NULL) 148e66f31c5Sopenharmony_ci return UV_EINVAL; 149e66f31c5Sopenharmony_ci 150e66f31c5Sopenharmony_ci switch (af) { 151e66f31c5Sopenharmony_ci case AF_INET: 152e66f31c5Sopenharmony_ci return (inet_pton4(src, dst)); 153e66f31c5Sopenharmony_ci case AF_INET6: { 154e66f31c5Sopenharmony_ci int len; 155e66f31c5Sopenharmony_ci char tmp[UV__INET6_ADDRSTRLEN], *s, *p; 156e66f31c5Sopenharmony_ci s = (char*) src; 157e66f31c5Sopenharmony_ci p = strchr(src, '%'); 158e66f31c5Sopenharmony_ci if (p != NULL) { 159e66f31c5Sopenharmony_ci s = tmp; 160e66f31c5Sopenharmony_ci len = p - src; 161e66f31c5Sopenharmony_ci if (len > UV__INET6_ADDRSTRLEN-1) 162e66f31c5Sopenharmony_ci return UV_EINVAL; 163e66f31c5Sopenharmony_ci memcpy(s, src, len); 164e66f31c5Sopenharmony_ci s[len] = '\0'; 165e66f31c5Sopenharmony_ci } 166e66f31c5Sopenharmony_ci return inet_pton6(s, dst); 167e66f31c5Sopenharmony_ci } 168e66f31c5Sopenharmony_ci default: 169e66f31c5Sopenharmony_ci return UV_EAFNOSUPPORT; 170e66f31c5Sopenharmony_ci } 171e66f31c5Sopenharmony_ci /* NOTREACHED */ 172e66f31c5Sopenharmony_ci} 173e66f31c5Sopenharmony_ci 174e66f31c5Sopenharmony_ci 175e66f31c5Sopenharmony_cistatic int inet_pton4(const char *src, unsigned char *dst) { 176e66f31c5Sopenharmony_ci static const char digits[] = "0123456789"; 177e66f31c5Sopenharmony_ci int saw_digit, octets, ch; 178e66f31c5Sopenharmony_ci unsigned char tmp[sizeof(struct in_addr)], *tp; 179e66f31c5Sopenharmony_ci 180e66f31c5Sopenharmony_ci saw_digit = 0; 181e66f31c5Sopenharmony_ci octets = 0; 182e66f31c5Sopenharmony_ci *(tp = tmp) = 0; 183e66f31c5Sopenharmony_ci while ((ch = *src++) != '\0') { 184e66f31c5Sopenharmony_ci const char *pch; 185e66f31c5Sopenharmony_ci 186e66f31c5Sopenharmony_ci if ((pch = strchr(digits, ch)) != NULL) { 187e66f31c5Sopenharmony_ci unsigned int nw = *tp * 10 + (pch - digits); 188e66f31c5Sopenharmony_ci 189e66f31c5Sopenharmony_ci if (saw_digit && *tp == 0) 190e66f31c5Sopenharmony_ci return UV_EINVAL; 191e66f31c5Sopenharmony_ci if (nw > 255) 192e66f31c5Sopenharmony_ci return UV_EINVAL; 193e66f31c5Sopenharmony_ci *tp = nw; 194e66f31c5Sopenharmony_ci if (!saw_digit) { 195e66f31c5Sopenharmony_ci if (++octets > 4) 196e66f31c5Sopenharmony_ci return UV_EINVAL; 197e66f31c5Sopenharmony_ci saw_digit = 1; 198e66f31c5Sopenharmony_ci } 199e66f31c5Sopenharmony_ci } else if (ch == '.' && saw_digit) { 200e66f31c5Sopenharmony_ci if (octets == 4) 201e66f31c5Sopenharmony_ci return UV_EINVAL; 202e66f31c5Sopenharmony_ci *++tp = 0; 203e66f31c5Sopenharmony_ci saw_digit = 0; 204e66f31c5Sopenharmony_ci } else 205e66f31c5Sopenharmony_ci return UV_EINVAL; 206e66f31c5Sopenharmony_ci } 207e66f31c5Sopenharmony_ci if (octets < 4) 208e66f31c5Sopenharmony_ci return UV_EINVAL; 209e66f31c5Sopenharmony_ci memcpy(dst, tmp, sizeof(struct in_addr)); 210e66f31c5Sopenharmony_ci return 0; 211e66f31c5Sopenharmony_ci} 212e66f31c5Sopenharmony_ci 213e66f31c5Sopenharmony_ci 214e66f31c5Sopenharmony_cistatic int inet_pton6(const char *src, unsigned char *dst) { 215e66f31c5Sopenharmony_ci static const char xdigits_l[] = "0123456789abcdef", 216e66f31c5Sopenharmony_ci xdigits_u[] = "0123456789ABCDEF"; 217e66f31c5Sopenharmony_ci unsigned char tmp[sizeof(struct in6_addr)], *tp, *endp, *colonp; 218e66f31c5Sopenharmony_ci const char *xdigits, *curtok; 219e66f31c5Sopenharmony_ci int ch, seen_xdigits; 220e66f31c5Sopenharmony_ci unsigned int val; 221e66f31c5Sopenharmony_ci 222e66f31c5Sopenharmony_ci memset((tp = tmp), '\0', sizeof tmp); 223e66f31c5Sopenharmony_ci endp = tp + sizeof tmp; 224e66f31c5Sopenharmony_ci colonp = NULL; 225e66f31c5Sopenharmony_ci /* Leading :: requires some special handling. */ 226e66f31c5Sopenharmony_ci if (*src == ':') 227e66f31c5Sopenharmony_ci if (*++src != ':') 228e66f31c5Sopenharmony_ci return UV_EINVAL; 229e66f31c5Sopenharmony_ci curtok = src; 230e66f31c5Sopenharmony_ci seen_xdigits = 0; 231e66f31c5Sopenharmony_ci val = 0; 232e66f31c5Sopenharmony_ci while ((ch = *src++) != '\0') { 233e66f31c5Sopenharmony_ci const char *pch; 234e66f31c5Sopenharmony_ci 235e66f31c5Sopenharmony_ci if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 236e66f31c5Sopenharmony_ci pch = strchr((xdigits = xdigits_u), ch); 237e66f31c5Sopenharmony_ci if (pch != NULL) { 238e66f31c5Sopenharmony_ci val <<= 4; 239e66f31c5Sopenharmony_ci val |= (pch - xdigits); 240e66f31c5Sopenharmony_ci if (++seen_xdigits > 4) 241e66f31c5Sopenharmony_ci return UV_EINVAL; 242e66f31c5Sopenharmony_ci continue; 243e66f31c5Sopenharmony_ci } 244e66f31c5Sopenharmony_ci if (ch == ':') { 245e66f31c5Sopenharmony_ci curtok = src; 246e66f31c5Sopenharmony_ci if (!seen_xdigits) { 247e66f31c5Sopenharmony_ci if (colonp) 248e66f31c5Sopenharmony_ci return UV_EINVAL; 249e66f31c5Sopenharmony_ci colonp = tp; 250e66f31c5Sopenharmony_ci continue; 251e66f31c5Sopenharmony_ci } else if (*src == '\0') { 252e66f31c5Sopenharmony_ci return UV_EINVAL; 253e66f31c5Sopenharmony_ci } 254e66f31c5Sopenharmony_ci if (tp + sizeof(uint16_t) > endp) 255e66f31c5Sopenharmony_ci return UV_EINVAL; 256e66f31c5Sopenharmony_ci *tp++ = (unsigned char) (val >> 8) & 0xff; 257e66f31c5Sopenharmony_ci *tp++ = (unsigned char) val & 0xff; 258e66f31c5Sopenharmony_ci seen_xdigits = 0; 259e66f31c5Sopenharmony_ci val = 0; 260e66f31c5Sopenharmony_ci continue; 261e66f31c5Sopenharmony_ci } 262e66f31c5Sopenharmony_ci if (ch == '.' && ((tp + sizeof(struct in_addr)) <= endp)) { 263e66f31c5Sopenharmony_ci int err = inet_pton4(curtok, tp); 264e66f31c5Sopenharmony_ci if (err == 0) { 265e66f31c5Sopenharmony_ci tp += sizeof(struct in_addr); 266e66f31c5Sopenharmony_ci seen_xdigits = 0; 267e66f31c5Sopenharmony_ci break; /*%< '\\0' was seen by inet_pton4(). */ 268e66f31c5Sopenharmony_ci } 269e66f31c5Sopenharmony_ci } 270e66f31c5Sopenharmony_ci return UV_EINVAL; 271e66f31c5Sopenharmony_ci } 272e66f31c5Sopenharmony_ci if (seen_xdigits) { 273e66f31c5Sopenharmony_ci if (tp + sizeof(uint16_t) > endp) 274e66f31c5Sopenharmony_ci return UV_EINVAL; 275e66f31c5Sopenharmony_ci *tp++ = (unsigned char) (val >> 8) & 0xff; 276e66f31c5Sopenharmony_ci *tp++ = (unsigned char) val & 0xff; 277e66f31c5Sopenharmony_ci } 278e66f31c5Sopenharmony_ci if (colonp != NULL) { 279e66f31c5Sopenharmony_ci /* 280e66f31c5Sopenharmony_ci * Since some memmove()'s erroneously fail to handle 281e66f31c5Sopenharmony_ci * overlapping regions, we'll do the shift by hand. 282e66f31c5Sopenharmony_ci */ 283e66f31c5Sopenharmony_ci const int n = tp - colonp; 284e66f31c5Sopenharmony_ci int i; 285e66f31c5Sopenharmony_ci 286e66f31c5Sopenharmony_ci if (tp == endp) 287e66f31c5Sopenharmony_ci return UV_EINVAL; 288e66f31c5Sopenharmony_ci for (i = 1; i <= n; i++) { 289e66f31c5Sopenharmony_ci endp[- i] = colonp[n - i]; 290e66f31c5Sopenharmony_ci colonp[n - i] = 0; 291e66f31c5Sopenharmony_ci } 292e66f31c5Sopenharmony_ci tp = endp; 293e66f31c5Sopenharmony_ci } 294e66f31c5Sopenharmony_ci if (tp != endp) 295e66f31c5Sopenharmony_ci return UV_EINVAL; 296e66f31c5Sopenharmony_ci memcpy(dst, tmp, sizeof tmp); 297e66f31c5Sopenharmony_ci return 0; 298e66f31c5Sopenharmony_ci} 299