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