Annotation of embedaddon/ntp/lib/isc/inet_pton.c, revision 1.1.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>