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