1*7b5038d7SDag-Erling Smørgrav /* $KAME: inet_pton.c,v 1.5 2001/08/20 02:32:40 itojun Exp $ */ 2*7b5038d7SDag-Erling Smørgrav 3*7b5038d7SDag-Erling Smørgrav /* Copyright (c) 1996 by Internet Software Consortium. 4*7b5038d7SDag-Erling Smørgrav * 5*7b5038d7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6*7b5038d7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7*7b5038d7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 8*7b5038d7SDag-Erling Smørgrav * 9*7b5038d7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 10*7b5038d7SDag-Erling Smørgrav * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 11*7b5038d7SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 12*7b5038d7SDag-Erling Smørgrav * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13*7b5038d7SDag-Erling Smørgrav * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14*7b5038d7SDag-Erling Smørgrav * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 15*7b5038d7SDag-Erling Smørgrav * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 16*7b5038d7SDag-Erling Smørgrav * SOFTWARE. 17*7b5038d7SDag-Erling Smørgrav */ 18*7b5038d7SDag-Erling Smørgrav 19*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 20*7b5038d7SDag-Erling Smørgrav 21*7b5038d7SDag-Erling Smørgrav #include <string.h> 22*7b5038d7SDag-Erling Smørgrav #include <stdio.h> 23*7b5038d7SDag-Erling Smørgrav #include <errno.h> 24*7b5038d7SDag-Erling Smørgrav 25*7b5038d7SDag-Erling Smørgrav /* 26*7b5038d7SDag-Erling Smørgrav * WARNING: Don't even consider trying to compile this on a system where 27*7b5038d7SDag-Erling Smørgrav * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 28*7b5038d7SDag-Erling Smørgrav */ 29*7b5038d7SDag-Erling Smørgrav 30*7b5038d7SDag-Erling Smørgrav static int inet_pton4 (const char *src, uint8_t *dst); 31*7b5038d7SDag-Erling Smørgrav static int inet_pton6 (const char *src, uint8_t *dst); 32*7b5038d7SDag-Erling Smørgrav 33*7b5038d7SDag-Erling Smørgrav /* 34*7b5038d7SDag-Erling Smørgrav * 35*7b5038d7SDag-Erling Smørgrav * The definitions we might miss. 36*7b5038d7SDag-Erling Smørgrav * 37*7b5038d7SDag-Erling Smørgrav */ 38*7b5038d7SDag-Erling Smørgrav #ifndef NS_INT16SZ 39*7b5038d7SDag-Erling Smørgrav #define NS_INT16SZ 2 40*7b5038d7SDag-Erling Smørgrav #endif 41*7b5038d7SDag-Erling Smørgrav 42*7b5038d7SDag-Erling Smørgrav #ifndef NS_IN6ADDRSZ 43*7b5038d7SDag-Erling Smørgrav #define NS_IN6ADDRSZ 16 44*7b5038d7SDag-Erling Smørgrav #endif 45*7b5038d7SDag-Erling Smørgrav 46*7b5038d7SDag-Erling Smørgrav #ifndef NS_INADDRSZ 47*7b5038d7SDag-Erling Smørgrav #define NS_INADDRSZ 4 48*7b5038d7SDag-Erling Smørgrav #endif 49*7b5038d7SDag-Erling Smørgrav 50*7b5038d7SDag-Erling Smørgrav /* int 51*7b5038d7SDag-Erling Smørgrav * inet_pton(af, src, dst) 52*7b5038d7SDag-Erling Smørgrav * convert from presentation format (which usually means ASCII printable) 53*7b5038d7SDag-Erling Smørgrav * to network format (which is usually some kind of binary format). 54*7b5038d7SDag-Erling Smørgrav * return: 55*7b5038d7SDag-Erling Smørgrav * 1 if the address was valid for the specified address family 56*7b5038d7SDag-Erling Smørgrav * 0 if the address wasn't valid (`dst' is untouched in this case) 57*7b5038d7SDag-Erling Smørgrav * -1 if some other error occurred (`dst' is untouched in this case, too) 58*7b5038d7SDag-Erling Smørgrav * author: 59*7b5038d7SDag-Erling Smørgrav * Paul Vixie, 1996. 60*7b5038d7SDag-Erling Smørgrav */ 61*7b5038d7SDag-Erling Smørgrav int 62*7b5038d7SDag-Erling Smørgrav inet_pton(af, src, dst) 63*7b5038d7SDag-Erling Smørgrav int af; 64*7b5038d7SDag-Erling Smørgrav const char *src; 65*7b5038d7SDag-Erling Smørgrav void *dst; 66*7b5038d7SDag-Erling Smørgrav { 67*7b5038d7SDag-Erling Smørgrav switch (af) { 68*7b5038d7SDag-Erling Smørgrav case AF_INET: 69*7b5038d7SDag-Erling Smørgrav return (inet_pton4(src, dst)); 70*7b5038d7SDag-Erling Smørgrav case AF_INET6: 71*7b5038d7SDag-Erling Smørgrav return (inet_pton6(src, dst)); 72*7b5038d7SDag-Erling Smørgrav default: 73*7b5038d7SDag-Erling Smørgrav #ifdef EAFNOSUPPORT 74*7b5038d7SDag-Erling Smørgrav errno = EAFNOSUPPORT; 75*7b5038d7SDag-Erling Smørgrav #else 76*7b5038d7SDag-Erling Smørgrav errno = ENOSYS; 77*7b5038d7SDag-Erling Smørgrav #endif 78*7b5038d7SDag-Erling Smørgrav return (-1); 79*7b5038d7SDag-Erling Smørgrav } 80*7b5038d7SDag-Erling Smørgrav /* NOTREACHED */ 81*7b5038d7SDag-Erling Smørgrav } 82*7b5038d7SDag-Erling Smørgrav 83*7b5038d7SDag-Erling Smørgrav /* int 84*7b5038d7SDag-Erling Smørgrav * inet_pton4(src, dst) 85*7b5038d7SDag-Erling Smørgrav * like inet_aton() but without all the hexadecimal and shorthand. 86*7b5038d7SDag-Erling Smørgrav * return: 87*7b5038d7SDag-Erling Smørgrav * 1 if `src' is a valid dotted quad, else 0. 88*7b5038d7SDag-Erling Smørgrav * notice: 89*7b5038d7SDag-Erling Smørgrav * does not touch `dst' unless it's returning 1. 90*7b5038d7SDag-Erling Smørgrav * author: 91*7b5038d7SDag-Erling Smørgrav * Paul Vixie, 1996. 92*7b5038d7SDag-Erling Smørgrav */ 93*7b5038d7SDag-Erling Smørgrav static int 94*7b5038d7SDag-Erling Smørgrav inet_pton4(src, dst) 95*7b5038d7SDag-Erling Smørgrav const char *src; 96*7b5038d7SDag-Erling Smørgrav uint8_t *dst; 97*7b5038d7SDag-Erling Smørgrav { 98*7b5038d7SDag-Erling Smørgrav static const char digits[] = "0123456789"; 99*7b5038d7SDag-Erling Smørgrav int saw_digit, octets, ch; 100*7b5038d7SDag-Erling Smørgrav uint8_t tmp[NS_INADDRSZ], *tp; 101*7b5038d7SDag-Erling Smørgrav 102*7b5038d7SDag-Erling Smørgrav saw_digit = 0; 103*7b5038d7SDag-Erling Smørgrav octets = 0; 104*7b5038d7SDag-Erling Smørgrav *(tp = tmp) = 0; 105*7b5038d7SDag-Erling Smørgrav while ((ch = *src++) != '\0') { 106*7b5038d7SDag-Erling Smørgrav const char *pch; 107*7b5038d7SDag-Erling Smørgrav 108*7b5038d7SDag-Erling Smørgrav if ((pch = strchr(digits, ch)) != NULL) { 109*7b5038d7SDag-Erling Smørgrav uint32_t new = *tp * 10 + (pch - digits); 110*7b5038d7SDag-Erling Smørgrav 111*7b5038d7SDag-Erling Smørgrav if (new > 255) 112*7b5038d7SDag-Erling Smørgrav return (0); 113*7b5038d7SDag-Erling Smørgrav *tp = new; 114*7b5038d7SDag-Erling Smørgrav if (! saw_digit) { 115*7b5038d7SDag-Erling Smørgrav if (++octets > 4) 116*7b5038d7SDag-Erling Smørgrav return (0); 117*7b5038d7SDag-Erling Smørgrav saw_digit = 1; 118*7b5038d7SDag-Erling Smørgrav } 119*7b5038d7SDag-Erling Smørgrav } else if (ch == '.' && saw_digit) { 120*7b5038d7SDag-Erling Smørgrav if (octets == 4) 121*7b5038d7SDag-Erling Smørgrav return (0); 122*7b5038d7SDag-Erling Smørgrav *++tp = 0; 123*7b5038d7SDag-Erling Smørgrav saw_digit = 0; 124*7b5038d7SDag-Erling Smørgrav } else 125*7b5038d7SDag-Erling Smørgrav return (0); 126*7b5038d7SDag-Erling Smørgrav } 127*7b5038d7SDag-Erling Smørgrav if (octets < 4) 128*7b5038d7SDag-Erling Smørgrav return (0); 129*7b5038d7SDag-Erling Smørgrav 130*7b5038d7SDag-Erling Smørgrav memcpy(dst, tmp, NS_INADDRSZ); 131*7b5038d7SDag-Erling Smørgrav return (1); 132*7b5038d7SDag-Erling Smørgrav } 133*7b5038d7SDag-Erling Smørgrav 134*7b5038d7SDag-Erling Smørgrav /* int 135*7b5038d7SDag-Erling Smørgrav * inet_pton6(src, dst) 136*7b5038d7SDag-Erling Smørgrav * convert presentation level address to network order binary form. 137*7b5038d7SDag-Erling Smørgrav * return: 138*7b5038d7SDag-Erling Smørgrav * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 139*7b5038d7SDag-Erling Smørgrav * notice: 140*7b5038d7SDag-Erling Smørgrav * (1) does not touch `dst' unless it's returning 1. 141*7b5038d7SDag-Erling Smørgrav * (2) :: in a full address is silently ignored. 142*7b5038d7SDag-Erling Smørgrav * credit: 143*7b5038d7SDag-Erling Smørgrav * inspired by Mark Andrews. 144*7b5038d7SDag-Erling Smørgrav * author: 145*7b5038d7SDag-Erling Smørgrav * Paul Vixie, 1996. 146*7b5038d7SDag-Erling Smørgrav */ 147*7b5038d7SDag-Erling Smørgrav static int 148*7b5038d7SDag-Erling Smørgrav inet_pton6(src, dst) 149*7b5038d7SDag-Erling Smørgrav const char *src; 150*7b5038d7SDag-Erling Smørgrav uint8_t *dst; 151*7b5038d7SDag-Erling Smørgrav { 152*7b5038d7SDag-Erling Smørgrav static const char xdigits_l[] = "0123456789abcdef", 153*7b5038d7SDag-Erling Smørgrav xdigits_u[] = "0123456789ABCDEF"; 154*7b5038d7SDag-Erling Smørgrav uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 155*7b5038d7SDag-Erling Smørgrav const char *xdigits, *curtok; 156*7b5038d7SDag-Erling Smørgrav int ch, saw_xdigit; 157*7b5038d7SDag-Erling Smørgrav uint32_t val; 158*7b5038d7SDag-Erling Smørgrav 159*7b5038d7SDag-Erling Smørgrav memset((tp = tmp), '\0', NS_IN6ADDRSZ); 160*7b5038d7SDag-Erling Smørgrav endp = tp + NS_IN6ADDRSZ; 161*7b5038d7SDag-Erling Smørgrav colonp = NULL; 162*7b5038d7SDag-Erling Smørgrav /* Leading :: requires some special handling. */ 163*7b5038d7SDag-Erling Smørgrav if (*src == ':') 164*7b5038d7SDag-Erling Smørgrav if (*++src != ':') 165*7b5038d7SDag-Erling Smørgrav return (0); 166*7b5038d7SDag-Erling Smørgrav curtok = src; 167*7b5038d7SDag-Erling Smørgrav saw_xdigit = 0; 168*7b5038d7SDag-Erling Smørgrav val = 0; 169*7b5038d7SDag-Erling Smørgrav while ((ch = *src++) != '\0') { 170*7b5038d7SDag-Erling Smørgrav const char *pch; 171*7b5038d7SDag-Erling Smørgrav 172*7b5038d7SDag-Erling Smørgrav if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 173*7b5038d7SDag-Erling Smørgrav pch = strchr((xdigits = xdigits_u), ch); 174*7b5038d7SDag-Erling Smørgrav if (pch != NULL) { 175*7b5038d7SDag-Erling Smørgrav val <<= 4; 176*7b5038d7SDag-Erling Smørgrav val |= (pch - xdigits); 177*7b5038d7SDag-Erling Smørgrav if (val > 0xffff) 178*7b5038d7SDag-Erling Smørgrav return (0); 179*7b5038d7SDag-Erling Smørgrav saw_xdigit = 1; 180*7b5038d7SDag-Erling Smørgrav continue; 181*7b5038d7SDag-Erling Smørgrav } 182*7b5038d7SDag-Erling Smørgrav if (ch == ':') { 183*7b5038d7SDag-Erling Smørgrav curtok = src; 184*7b5038d7SDag-Erling Smørgrav if (!saw_xdigit) { 185*7b5038d7SDag-Erling Smørgrav if (colonp) 186*7b5038d7SDag-Erling Smørgrav return (0); 187*7b5038d7SDag-Erling Smørgrav colonp = tp; 188*7b5038d7SDag-Erling Smørgrav continue; 189*7b5038d7SDag-Erling Smørgrav } 190*7b5038d7SDag-Erling Smørgrav if (tp + NS_INT16SZ > endp) 191*7b5038d7SDag-Erling Smørgrav return (0); 192*7b5038d7SDag-Erling Smørgrav *tp++ = (uint8_t) (val >> 8) & 0xff; 193*7b5038d7SDag-Erling Smørgrav *tp++ = (uint8_t) val & 0xff; 194*7b5038d7SDag-Erling Smørgrav saw_xdigit = 0; 195*7b5038d7SDag-Erling Smørgrav val = 0; 196*7b5038d7SDag-Erling Smørgrav continue; 197*7b5038d7SDag-Erling Smørgrav } 198*7b5038d7SDag-Erling Smørgrav if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 199*7b5038d7SDag-Erling Smørgrav inet_pton4(curtok, tp) > 0) { 200*7b5038d7SDag-Erling Smørgrav tp += NS_INADDRSZ; 201*7b5038d7SDag-Erling Smørgrav saw_xdigit = 0; 202*7b5038d7SDag-Erling Smørgrav break; /* '\0' was seen by inet_pton4(). */ 203*7b5038d7SDag-Erling Smørgrav } 204*7b5038d7SDag-Erling Smørgrav return (0); 205*7b5038d7SDag-Erling Smørgrav } 206*7b5038d7SDag-Erling Smørgrav if (saw_xdigit) { 207*7b5038d7SDag-Erling Smørgrav if (tp + NS_INT16SZ > endp) 208*7b5038d7SDag-Erling Smørgrav return (0); 209*7b5038d7SDag-Erling Smørgrav *tp++ = (uint8_t) (val >> 8) & 0xff; 210*7b5038d7SDag-Erling Smørgrav *tp++ = (uint8_t) val & 0xff; 211*7b5038d7SDag-Erling Smørgrav } 212*7b5038d7SDag-Erling Smørgrav if (colonp != NULL) { 213*7b5038d7SDag-Erling Smørgrav /* 214*7b5038d7SDag-Erling Smørgrav * Since some memmove()'s erroneously fail to handle 215*7b5038d7SDag-Erling Smørgrav * overlapping regions, we'll do the shift by hand. 216*7b5038d7SDag-Erling Smørgrav */ 217*7b5038d7SDag-Erling Smørgrav const int n = tp - colonp; 218*7b5038d7SDag-Erling Smørgrav int i; 219*7b5038d7SDag-Erling Smørgrav 220*7b5038d7SDag-Erling Smørgrav for (i = 1; i <= n; i++) { 221*7b5038d7SDag-Erling Smørgrav endp[- i] = colonp[n - i]; 222*7b5038d7SDag-Erling Smørgrav colonp[n - i] = 0; 223*7b5038d7SDag-Erling Smørgrav } 224*7b5038d7SDag-Erling Smørgrav tp = endp; 225*7b5038d7SDag-Erling Smørgrav } 226*7b5038d7SDag-Erling Smørgrav if (tp != endp) 227*7b5038d7SDag-Erling Smørgrav return (0); 228*7b5038d7SDag-Erling Smørgrav memcpy(dst, tmp, NS_IN6ADDRSZ); 229*7b5038d7SDag-Erling Smørgrav return (1); 230*7b5038d7SDag-Erling Smørgrav } 231