17c478bd9Sstevel@tonic-gate /* 2*e8031f0aSraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 361961e0fSrobinson * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 661961e0fSrobinson /* 761961e0fSrobinson * Copyright (c) 1996 by Internet Software Consortium. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 107c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 117c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 147c478bd9Sstevel@tonic-gate * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 157c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 167c478bd9Sstevel@tonic-gate * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 177c478bd9Sstevel@tonic-gate * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 187c478bd9Sstevel@tonic-gate * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 197c478bd9Sstevel@tonic-gate * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 207c478bd9Sstevel@tonic-gate * SOFTWARE. 217c478bd9Sstevel@tonic-gate */ 2261961e0fSrobinson 237c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 247c478bd9Sstevel@tonic-gate 25*e8031f0aSraf #include "mt.h" 267c478bd9Sstevel@tonic-gate #include <stdlib.h> 277c478bd9Sstevel@tonic-gate #include <ctype.h> 287c478bd9Sstevel@tonic-gate #include <string.h> 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <netdb.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 337c478bd9Sstevel@tonic-gate #include <netinet/in.h> 347c478bd9Sstevel@tonic-gate #include <sys/socket.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate 3761961e0fSrobinson static int inet_pton4(const char *src, uchar_t *dst); 3861961e0fSrobinson static int inet_pton6(const char *src, uchar_t *dst); 397c478bd9Sstevel@tonic-gate 4061961e0fSrobinson /* 4161961e0fSrobinson * int 427c478bd9Sstevel@tonic-gate * inet_pton(af, src, dst) 437c478bd9Sstevel@tonic-gate * convert from presentation format (which usually means ASCII printable) 447c478bd9Sstevel@tonic-gate * to network format (which is usually some kind of binary format). 457c478bd9Sstevel@tonic-gate * return: 467c478bd9Sstevel@tonic-gate * 1 if the address was valid for the specified address family 477c478bd9Sstevel@tonic-gate * 0 if the address wasn't valid (`dst' is untouched in this case) 487c478bd9Sstevel@tonic-gate * -1 if some other error occurred (`dst' is untouched in this case, too) 497c478bd9Sstevel@tonic-gate * author: 507c478bd9Sstevel@tonic-gate * Paul Vixie, 1996. Taken from on297-gate:dns stuff 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate int 5361961e0fSrobinson inet_pton(int af, const char *src, void *dst) 547c478bd9Sstevel@tonic-gate { 557c478bd9Sstevel@tonic-gate switch (af) { 567c478bd9Sstevel@tonic-gate case AF_INET: 577c478bd9Sstevel@tonic-gate return (inet_pton4(src, dst)); 587c478bd9Sstevel@tonic-gate case AF_INET6: 597c478bd9Sstevel@tonic-gate return (inet_pton6(src, dst)); 607c478bd9Sstevel@tonic-gate default: 617c478bd9Sstevel@tonic-gate errno = EAFNOSUPPORT; 627c478bd9Sstevel@tonic-gate return (-1); 637c478bd9Sstevel@tonic-gate } 647c478bd9Sstevel@tonic-gate /* NOTREACHED */ 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate 6761961e0fSrobinson /* 6861961e0fSrobinson * int 697c478bd9Sstevel@tonic-gate * inet_pton4(src, dst) 707c478bd9Sstevel@tonic-gate * like inet_aton() but without all the hexadecimal and shorthand. 717c478bd9Sstevel@tonic-gate * return: 727c478bd9Sstevel@tonic-gate * 1 if `src' is a valid dotted quad, else 0. 737c478bd9Sstevel@tonic-gate * notice: 747c478bd9Sstevel@tonic-gate * does not touch `dst' unless it's returning 1. 757c478bd9Sstevel@tonic-gate * 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate #define INADDRSZ 4 787c478bd9Sstevel@tonic-gate #define IN6ADDRSZ 16 797c478bd9Sstevel@tonic-gate #define INT16SZ 2 8061961e0fSrobinson 817c478bd9Sstevel@tonic-gate static int 8261961e0fSrobinson inet_pton4(const char *src, uchar_t *dst) 837c478bd9Sstevel@tonic-gate { 847c478bd9Sstevel@tonic-gate static const char digits[] = "0123456789"; 857c478bd9Sstevel@tonic-gate int saw_digit, octets, ch; 8661961e0fSrobinson uchar_t tmp[INADDRSZ], *tp; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate saw_digit = 0; 897c478bd9Sstevel@tonic-gate octets = 0; 907c478bd9Sstevel@tonic-gate *(tp = tmp) = 0; 917c478bd9Sstevel@tonic-gate while ((ch = *src++) != '\0') { 927c478bd9Sstevel@tonic-gate const char *pch; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate if ((pch = strchr(digits, ch)) != NULL) { 9561961e0fSrobinson uint_t new = *tp * 10 + (pch - digits); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate if (new > 255) 987c478bd9Sstevel@tonic-gate return (0); 997c478bd9Sstevel@tonic-gate *tp = new; 1007c478bd9Sstevel@tonic-gate if (!saw_digit) { 1017c478bd9Sstevel@tonic-gate if (++octets > 4) 1027c478bd9Sstevel@tonic-gate return (0); 1037c478bd9Sstevel@tonic-gate saw_digit = 1; 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate } else if (ch == '.' && saw_digit) { 1067c478bd9Sstevel@tonic-gate if (octets == 4) 1077c478bd9Sstevel@tonic-gate return (0); 1087c478bd9Sstevel@tonic-gate *++tp = 0; 1097c478bd9Sstevel@tonic-gate saw_digit = 0; 1107c478bd9Sstevel@tonic-gate } else 1117c478bd9Sstevel@tonic-gate return (0); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate if (octets < 4) 1147c478bd9Sstevel@tonic-gate return (0); 1157c478bd9Sstevel@tonic-gate 11661961e0fSrobinson (void) memcpy(dst, tmp, INADDRSZ); 1177c478bd9Sstevel@tonic-gate return (1); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate 12161961e0fSrobinson /* 12261961e0fSrobinson * int 1237c478bd9Sstevel@tonic-gate * inet_pton6(src, dst) 1247c478bd9Sstevel@tonic-gate * convert presentation level address to network order binary form. 1257c478bd9Sstevel@tonic-gate * return: 1267c478bd9Sstevel@tonic-gate * 1 if `src' is a valid [RFC1884 2.2] address, else 0. 1277c478bd9Sstevel@tonic-gate * notice: 1287c478bd9Sstevel@tonic-gate * (1) does not touch `dst' unless it's returning 1. 1297c478bd9Sstevel@tonic-gate * (2) :: in a full address is silently ignored. 1307c478bd9Sstevel@tonic-gate * credit: 1317c478bd9Sstevel@tonic-gate * inspired by Mark Andrews. 1327c478bd9Sstevel@tonic-gate * 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static int 13761961e0fSrobinson inet_pton6(const char *src, uchar_t *dst) 1387c478bd9Sstevel@tonic-gate { 1397c478bd9Sstevel@tonic-gate static const char xdigits_l[] = "0123456789abcdef", 1407c478bd9Sstevel@tonic-gate xdigits_u[] = "0123456789ABCDEF"; 14161961e0fSrobinson uchar_t tmp[IN6ADDRSZ], *tp, *endp, *colonp; 1427c478bd9Sstevel@tonic-gate const char *xdigits, *curtok; 1437c478bd9Sstevel@tonic-gate int ch, saw_xdigit; 14461961e0fSrobinson uint_t val; 1457c478bd9Sstevel@tonic-gate 14661961e0fSrobinson (void) memset((tp = tmp), '\0', IN6ADDRSZ); 1477c478bd9Sstevel@tonic-gate endp = tp + IN6ADDRSZ; 1487c478bd9Sstevel@tonic-gate colonp = NULL; 1497c478bd9Sstevel@tonic-gate /* Leading :: requires some special handling. */ 1507c478bd9Sstevel@tonic-gate if (*src == ':') 1517c478bd9Sstevel@tonic-gate if (*++src != ':') 1527c478bd9Sstevel@tonic-gate return (0); 1537c478bd9Sstevel@tonic-gate curtok = src; 1547c478bd9Sstevel@tonic-gate saw_xdigit = 0; 1557c478bd9Sstevel@tonic-gate val = 0; 1567c478bd9Sstevel@tonic-gate while ((ch = *src++) != '\0') { 1577c478bd9Sstevel@tonic-gate const char *pch; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 1607c478bd9Sstevel@tonic-gate pch = strchr((xdigits = xdigits_u), ch); 1617c478bd9Sstevel@tonic-gate if (pch != NULL) { 1627c478bd9Sstevel@tonic-gate val <<= 4; 1637c478bd9Sstevel@tonic-gate val |= (pch - xdigits); 1647c478bd9Sstevel@tonic-gate if (val > 0xffff) 1657c478bd9Sstevel@tonic-gate return (0); 1667c478bd9Sstevel@tonic-gate saw_xdigit = 1; 1677c478bd9Sstevel@tonic-gate continue; 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate if (ch == ':') { 1707c478bd9Sstevel@tonic-gate curtok = src; 1717c478bd9Sstevel@tonic-gate if (!saw_xdigit) { 1727c478bd9Sstevel@tonic-gate if (colonp) 1737c478bd9Sstevel@tonic-gate return (0); 1747c478bd9Sstevel@tonic-gate colonp = tp; 1757c478bd9Sstevel@tonic-gate continue; 1767c478bd9Sstevel@tonic-gate } else if (*src == '\0') { 1777c478bd9Sstevel@tonic-gate return (0); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate if (tp + INT16SZ > endp) 1807c478bd9Sstevel@tonic-gate return (0); 18161961e0fSrobinson *tp++ = (uchar_t)(val >> 8) & 0xff; 18261961e0fSrobinson *tp++ = (uchar_t)val & 0xff; 1837c478bd9Sstevel@tonic-gate saw_xdigit = 0; 1847c478bd9Sstevel@tonic-gate val = 0; 1857c478bd9Sstevel@tonic-gate continue; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate if (ch == '.' && ((tp + INADDRSZ) <= endp) && 1887c478bd9Sstevel@tonic-gate inet_pton4(curtok, tp) > 0) { 1897c478bd9Sstevel@tonic-gate tp += INADDRSZ; 1907c478bd9Sstevel@tonic-gate saw_xdigit = 0; 1917c478bd9Sstevel@tonic-gate break; /* '\0' was seen by inet_pton4(). */ 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate return (0); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate if (saw_xdigit) { 1967c478bd9Sstevel@tonic-gate if (tp + INT16SZ > endp) 1977c478bd9Sstevel@tonic-gate return (0); 19861961e0fSrobinson *tp++ = (uchar_t)(val >> 8) & 0xff; 19961961e0fSrobinson *tp++ = (uchar_t)val & 0xff; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate if (colonp != NULL) { 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Since some memmove()'s erroneously fail to handle 2047c478bd9Sstevel@tonic-gate * overlapping regions, we'll do the shift by hand. 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate const int n = tp - colonp; 2077c478bd9Sstevel@tonic-gate int i; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (tp == endp) 2107c478bd9Sstevel@tonic-gate return (0); 2117c478bd9Sstevel@tonic-gate for (i = 1; i <= n; i++) { 2127c478bd9Sstevel@tonic-gate endp[- i] = colonp[n - i]; 2137c478bd9Sstevel@tonic-gate colonp[n - i] = 0; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate tp = endp; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate if (tp != endp) 2187c478bd9Sstevel@tonic-gate return (0); 21961961e0fSrobinson (void) memcpy(dst, tmp, IN6ADDRSZ); 2207c478bd9Sstevel@tonic-gate return (1); 2217c478bd9Sstevel@tonic-gate } 222