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>