10Sstevel@tonic-gate /* 2*132Srobinson * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*132Srobinson * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 6*132Srobinson /* 7*132Srobinson * Copyright (c) 1996 by Internet Software Consortium. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 100Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 110Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 140Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 150Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 160Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 170Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 180Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 190Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 200Sstevel@tonic-gate * SOFTWARE. 210Sstevel@tonic-gate */ 22*132Srobinson 230Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 240Sstevel@tonic-gate 250Sstevel@tonic-gate #include <stdlib.h> 260Sstevel@tonic-gate #include <ctype.h> 270Sstevel@tonic-gate #include <string.h> 280Sstevel@tonic-gate #include <strings.h> 290Sstevel@tonic-gate #include <netdb.h> 300Sstevel@tonic-gate #include <stdio.h> 310Sstevel@tonic-gate #include <arpa/inet.h> 320Sstevel@tonic-gate #include <netinet/in.h> 330Sstevel@tonic-gate #include <sys/socket.h> 340Sstevel@tonic-gate #include <errno.h> 350Sstevel@tonic-gate 36*132Srobinson static int inet_pton4(const char *src, uchar_t *dst); 37*132Srobinson static int inet_pton6(const char *src, uchar_t *dst); 380Sstevel@tonic-gate 39*132Srobinson /* 40*132Srobinson * int 410Sstevel@tonic-gate * inet_pton(af, src, dst) 420Sstevel@tonic-gate * convert from presentation format (which usually means ASCII printable) 430Sstevel@tonic-gate * to network format (which is usually some kind of binary format). 440Sstevel@tonic-gate * return: 450Sstevel@tonic-gate * 1 if the address was valid for the specified address family 460Sstevel@tonic-gate * 0 if the address wasn't valid (`dst' is untouched in this case) 470Sstevel@tonic-gate * -1 if some other error occurred (`dst' is untouched in this case, too) 480Sstevel@tonic-gate * author: 490Sstevel@tonic-gate * Paul Vixie, 1996. Taken from on297-gate:dns stuff 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate int 52*132Srobinson inet_pton(int af, const char *src, void *dst) 530Sstevel@tonic-gate { 540Sstevel@tonic-gate switch (af) { 550Sstevel@tonic-gate case AF_INET: 560Sstevel@tonic-gate return (inet_pton4(src, dst)); 570Sstevel@tonic-gate case AF_INET6: 580Sstevel@tonic-gate return (inet_pton6(src, dst)); 590Sstevel@tonic-gate default: 600Sstevel@tonic-gate errno = EAFNOSUPPORT; 610Sstevel@tonic-gate return (-1); 620Sstevel@tonic-gate } 630Sstevel@tonic-gate /* NOTREACHED */ 640Sstevel@tonic-gate } 650Sstevel@tonic-gate 66*132Srobinson /* 67*132Srobinson * int 680Sstevel@tonic-gate * inet_pton4(src, dst) 690Sstevel@tonic-gate * like inet_aton() but without all the hexadecimal and shorthand. 700Sstevel@tonic-gate * return: 710Sstevel@tonic-gate * 1 if `src' is a valid dotted quad, else 0. 720Sstevel@tonic-gate * notice: 730Sstevel@tonic-gate * does not touch `dst' unless it's returning 1. 740Sstevel@tonic-gate * 750Sstevel@tonic-gate */ 76*132Srobinson #define INADDRSZ 4 770Sstevel@tonic-gate #define IN6ADDRSZ 16 78*132Srobinson #define INT16SZ 2 79*132Srobinson 800Sstevel@tonic-gate static int 81*132Srobinson inet_pton4(const char *src, uchar_t *dst) 820Sstevel@tonic-gate { 830Sstevel@tonic-gate static const char digits[] = "0123456789"; 840Sstevel@tonic-gate int saw_digit, octets, ch; 85*132Srobinson uchar_t tmp[INADDRSZ], *tp; 860Sstevel@tonic-gate 870Sstevel@tonic-gate saw_digit = 0; 880Sstevel@tonic-gate octets = 0; 890Sstevel@tonic-gate *(tp = tmp) = 0; 900Sstevel@tonic-gate while ((ch = *src++) != '\0') { 910Sstevel@tonic-gate const char *pch; 920Sstevel@tonic-gate 930Sstevel@tonic-gate if ((pch = strchr(digits, ch)) != NULL) { 94*132Srobinson uint_t new = *tp * 10 + (pch - digits); 950Sstevel@tonic-gate 960Sstevel@tonic-gate if (new > 255) 970Sstevel@tonic-gate return (0); 980Sstevel@tonic-gate *tp = new; 99*132Srobinson if (!saw_digit) { 1000Sstevel@tonic-gate if (++octets > 4) 1010Sstevel@tonic-gate return (0); 1020Sstevel@tonic-gate saw_digit = 1; 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate } else if (ch == '.' && saw_digit) { 1050Sstevel@tonic-gate if (octets == 4) 1060Sstevel@tonic-gate return (0); 1070Sstevel@tonic-gate *++tp = 0; 1080Sstevel@tonic-gate saw_digit = 0; 1090Sstevel@tonic-gate } else 1100Sstevel@tonic-gate return (0); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate if (octets < 4) 1130Sstevel@tonic-gate return (0); 1140Sstevel@tonic-gate 115*132Srobinson (void) memcpy(dst, tmp, INADDRSZ); 1160Sstevel@tonic-gate return (1); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate 120*132Srobinson /* 121*132Srobinson * int 1220Sstevel@tonic-gate * inet_pton6(src, dst) 1230Sstevel@tonic-gate * convert presentation level address to network order binary form. 1240Sstevel@tonic-gate * return: 1250Sstevel@tonic-gate * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 1260Sstevel@tonic-gate * notice: 1270Sstevel@tonic-gate * (1) does not touch `dst' unless it's returning 1. 1280Sstevel@tonic-gate * (2) :: in a full address is silently ignored. 1290Sstevel@tonic-gate * credit: 1300Sstevel@tonic-gate * inspired by Mark Andrews. 1310Sstevel@tonic-gate * 1320Sstevel@tonic-gate */ 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate static int 136*132Srobinson inet_pton6(const char *src, uchar_t *dst) 1370Sstevel@tonic-gate { 1380Sstevel@tonic-gate static const char xdigits_l[] = "0123456789abcdef", 139*132Srobinson xdigits_u[] = "0123456789ABCDEF"; 140*132Srobinson uchar_t tmp[IN6ADDRSZ], *tp, *endp, *colonp; 1410Sstevel@tonic-gate const char *xdigits, *curtok; 1420Sstevel@tonic-gate int ch, saw_xdigit; 143*132Srobinson uint_t val; 1440Sstevel@tonic-gate 145*132Srobinson (void) memset((tp = tmp), '\0', IN6ADDRSZ); 1460Sstevel@tonic-gate endp = tp + IN6ADDRSZ; 1470Sstevel@tonic-gate colonp = NULL; 1480Sstevel@tonic-gate /* Leading :: requires some special handling. */ 1490Sstevel@tonic-gate if (*src == ':') 1500Sstevel@tonic-gate if (*++src != ':') 1510Sstevel@tonic-gate return (0); 1520Sstevel@tonic-gate curtok = src; 1530Sstevel@tonic-gate saw_xdigit = 0; 1540Sstevel@tonic-gate val = 0; 1550Sstevel@tonic-gate while ((ch = *src++) != '\0') { 1560Sstevel@tonic-gate const char *pch; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 1590Sstevel@tonic-gate pch = strchr((xdigits = xdigits_u), ch); 1600Sstevel@tonic-gate if (pch != NULL) { 1610Sstevel@tonic-gate val <<= 4; 1620Sstevel@tonic-gate val |= (pch - xdigits); 1630Sstevel@tonic-gate if (val > 0xffff) 1640Sstevel@tonic-gate return (0); 1650Sstevel@tonic-gate saw_xdigit = 1; 1660Sstevel@tonic-gate continue; 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate if (ch == ':') { 1690Sstevel@tonic-gate curtok = src; 1700Sstevel@tonic-gate if (!saw_xdigit) { 1710Sstevel@tonic-gate if (colonp) 1720Sstevel@tonic-gate return (0); 1730Sstevel@tonic-gate colonp = tp; 1740Sstevel@tonic-gate continue; 1750Sstevel@tonic-gate } else if (*src == '\0') { 1760Sstevel@tonic-gate return (0); 1770Sstevel@tonic-gate } 1780Sstevel@tonic-gate if (tp + INT16SZ > endp) 1790Sstevel@tonic-gate return (0); 180*132Srobinson *tp++ = (uchar_t)(val >> 8) & 0xff; 181*132Srobinson *tp++ = (uchar_t)val & 0xff; 1820Sstevel@tonic-gate saw_xdigit = 0; 1830Sstevel@tonic-gate val = 0; 1840Sstevel@tonic-gate continue; 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate if (ch == '.' && ((tp + INADDRSZ) <= endp) && 1870Sstevel@tonic-gate inet_pton4(curtok, tp) > 0) { 1880Sstevel@tonic-gate tp += INADDRSZ; 1890Sstevel@tonic-gate saw_xdigit = 0; 1900Sstevel@tonic-gate break; /* '\0' was seen by inet_pton4(). */ 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate return (0); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate if (saw_xdigit) { 1950Sstevel@tonic-gate if (tp + INT16SZ > endp) 1960Sstevel@tonic-gate return (0); 197*132Srobinson *tp++ = (uchar_t)(val >> 8) & 0xff; 198*132Srobinson *tp++ = (uchar_t)val & 0xff; 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate if (colonp != NULL) { 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * Since some memmove()'s erroneously fail to handle 2030Sstevel@tonic-gate * overlapping regions, we'll do the shift by hand. 2040Sstevel@tonic-gate */ 2050Sstevel@tonic-gate const int n = tp - colonp; 2060Sstevel@tonic-gate int i; 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate if (tp == endp) 2090Sstevel@tonic-gate return (0); 2100Sstevel@tonic-gate for (i = 1; i <= n; i++) { 2110Sstevel@tonic-gate endp[- i] = colonp[n - i]; 2120Sstevel@tonic-gate colonp[n - i] = 0; 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate tp = endp; 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate if (tp != endp) 2170Sstevel@tonic-gate return (0); 218*132Srobinson (void) memcpy(dst, tmp, IN6ADDRSZ); 2190Sstevel@tonic-gate return (1); 2200Sstevel@tonic-gate } 221