[BACK]Return to inet_pton.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / inet

Annotation of src/lib/libc/inet/inet_pton.c, Revision 1.8

1.8     ! christos    1: /*     $NetBSD: inet_pton.c,v 1.7 2009/04/12 17:07:17 christos Exp $   */
1.1       christos    2:
                      3: /*
                      4:  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
                      5:  * Copyright (c) 1996,1999 by Internet Software Consortium.
                      6:  *
                      7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     17:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19:
1.2       christos   20: #include <sys/cdefs.h>
1.1       christos   21: #if defined(LIBC_SCCS) && !defined(lint)
1.2       christos   22: #if 0
1.6       christos   23: static const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp";
1.2       christos   24: #else
1.8     ! christos   25: __RCSID("$NetBSD: inet_pton.c,v 1.7 2009/04/12 17:07:17 christos Exp $");
1.2       christos   26: #endif
1.1       christos   27: #endif /* LIBC_SCCS and not lint */
                     28:
                     29: #include "port_before.h"
1.2       christos   30:
                     31: #include "namespace.h"
1.1       christos   32: #include <sys/param.h>
                     33: #include <sys/types.h>
                     34: #include <sys/socket.h>
                     35: #include <netinet/in.h>
                     36: #include <arpa/inet.h>
                     37: #include <arpa/nameser.h>
1.8     ! christos   38: #include <stddef.h>
1.1       christos   39: #include <string.h>
1.2       christos   40: #include <assert.h>
                     41: #include <ctype.h>
1.1       christos   42: #include <errno.h>
1.2       christos   43:
1.1       christos   44: #include "port_after.h"
                     45:
1.2       christos   46: #ifdef __weak_alias
                     47: __weak_alias(inet_pton,_inet_pton)
                     48: #endif
                     49:
1.4       christos   50: /*%
1.1       christos   51:  * WARNING: Don't even consider trying to compile this on a system where
                     52:  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
                     53:  */
                     54:
1.2       christos   55: static int     inet_pton4(const char *src, u_char *dst, int pton);
                     56: static int     inet_pton6(const char *src, u_char *dst);
1.1       christos   57:
                     58: /* int
                     59:  * inet_pton(af, src, dst)
                     60:  *     convert from presentation format (which usually means ASCII printable)
                     61:  *     to network format (which is usually some kind of binary format).
                     62:  * return:
                     63:  *     1 if the address was valid for the specified address family
                     64:  *     0 if the address wasn't valid (`dst' is untouched in this case)
                     65:  *     -1 if some other error occurred (`dst' is untouched in this case, too)
                     66:  * author:
                     67:  *     Paul Vixie, 1996.
                     68:  */
                     69: int
1.2       christos   70: inet_pton(int af, const char *src, void *dst)
1.1       christos   71: {
1.2       christos   72:
                     73:        _DIAGASSERT(src != NULL);
                     74:        _DIAGASSERT(dst != NULL);
                     75:
1.1       christos   76:        switch (af) {
                     77:        case AF_INET:
1.2       christos   78:                return (inet_pton4(src, dst, 1));
1.1       christos   79:        case AF_INET6:
                     80:                return (inet_pton6(src, dst));
                     81:        default:
                     82:                errno = EAFNOSUPPORT;
                     83:                return (-1);
                     84:        }
                     85:        /* NOTREACHED */
                     86: }
                     87:
                     88: /* int
1.2       christos   89:  * inet_pton4(src, dst, pton)
                     90:  *     when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
                     91:  *     when last arg is 1: inet_pton(). decimal dotted-quad only.
1.1       christos   92:  * return:
1.2       christos   93:  *     1 if `src' is a valid input, else 0.
1.1       christos   94:  * notice:
                     95:  *     does not touch `dst' unless it's returning 1.
                     96:  * author:
                     97:  *     Paul Vixie, 1996.
                     98:  */
                     99: static int
1.2       christos  100: inet_pton4(const char *src, u_char *dst, int pton)
1.1       christos  101: {
1.2       christos  102:        u_int32_t val;
                    103:        u_int digit, base;
1.8     ! christos  104:        ptrdiff_t n;
1.2       christos  105:        unsigned char c;
                    106:        u_int parts[4];
1.8     ! christos  107:        u_int *pp = parts;
1.1       christos  108:
1.2       christos  109:        _DIAGASSERT(src != NULL);
                    110:        _DIAGASSERT(dst != NULL);
1.1       christos  111:
1.2       christos  112:        c = *src;
                    113:        for (;;) {
                    114:                /*
                    115:                 * Collect number up to ``.''.
                    116:                 * Values are specified as for C:
                    117:                 * 0x=hex, 0=octal, isdigit=decimal.
                    118:                 */
                    119:                if (!isdigit(c))
                    120:                        return (0);
                    121:                val = 0; base = 10;
                    122:                if (c == '0') {
                    123:                        c = *++src;
                    124:                        if (c == 'x' || c == 'X')
                    125:                                base = 16, c = *++src;
                    126:                        else if (isdigit(c) && c != '9')
                    127:                                base = 8;
                    128:                }
                    129:                /* inet_pton() takes decimal only */
                    130:                if (pton && base != 10)
                    131:                        return (0);
                    132:                for (;;) {
                    133:                        if (isdigit(c)) {
                    134:                                digit = c - '0';
                    135:                                if (digit >= base)
                    136:                                        break;
                    137:                                val = (val * base) + digit;
                    138:                                c = *++src;
                    139:                        } else if (base == 16 && isxdigit(c)) {
                    140:                                digit = c + 10 - (islower(c) ? 'a' : 'A');
                    141:                                if (digit >= 16)
                    142:                                        break;
                    143:                                val = (val << 4) | digit;
                    144:                                c = *++src;
                    145:                        } else
                    146:                                break;
                    147:                }
                    148:                if (c == '.') {
                    149:                        /*
                    150:                         * Internet format:
                    151:                         *      a.b.c.d
                    152:                         *      a.b.c   (with c treated as 16 bits)
                    153:                         *      a.b     (with b treated as 24 bits)
                    154:                         *      a       (with a treated as 32 bits)
                    155:                         */
                    156:                        if (pp >= parts + 3)
1.1       christos  157:                                return (0);
1.2       christos  158:                        *pp++ = val;
                    159:                        c = *++src;
1.1       christos  160:                } else
1.2       christos  161:                        break;
                    162:        }
                    163:        /*
                    164:         * Check for trailing characters.
                    165:         */
                    166:        if (c != '\0' && !isspace(c))
                    167:                return (0);
                    168:        /*
                    169:         * Concoct the address according to
                    170:         * the number of parts specified.
                    171:         */
                    172:        n = pp - parts + 1;
                    173:        /* inet_pton() takes dotted-quad only.  it does not take shorthand. */
                    174:        if (pton && n != 4)
                    175:                return (0);
                    176:        switch (n) {
                    177:
                    178:        case 0:
                    179:                return (0);             /* initial nondigit */
                    180:
                    181:        case 1:                         /* a -- 32 bits */
                    182:                break;
                    183:
                    184:        case 2:                         /* a.b -- 8.24 bits */
                    185:                if (parts[0] > 0xff || val > 0xffffff)
1.1       christos  186:                        return (0);
1.2       christos  187:                val |= parts[0] << 24;
                    188:                break;
                    189:
                    190:        case 3:                         /* a.b.c -- 8.8.16 bits */
                    191:                if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
                    192:                        return (0);
                    193:                val |= (parts[0] << 24) | (parts[1] << 16);
                    194:                break;
                    195:
                    196:        case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
                    197:                if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
                    198:                        return (0);
                    199:                val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
                    200:                break;
                    201:        }
                    202:        if (dst) {
                    203:                val = htonl(val);
                    204:                memcpy(dst, &val, NS_INADDRSZ);
1.1       christos  205:        }
                    206:        return (1);
                    207: }
                    208:
                    209: /* int
                    210:  * inet_pton6(src, dst)
                    211:  *     convert presentation level address to network order binary form.
                    212:  * return:
                    213:  *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
                    214:  * notice:
                    215:  *     (1) does not touch `dst' unless it's returning 1.
                    216:  *     (2) :: in a full address is silently ignored.
                    217:  * credit:
                    218:  *     inspired by Mark Andrews.
                    219:  * author:
                    220:  *     Paul Vixie, 1996.
                    221:  */
                    222: static int
1.2       christos  223: inet_pton6(const char *src, u_char *dst)
1.1       christos  224: {
                    225:        static const char xdigits_l[] = "0123456789abcdef",
                    226:                          xdigits_u[] = "0123456789ABCDEF";
                    227:        u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
                    228:        const char *xdigits, *curtok;
1.4       christos  229:        int ch, seen_xdigits;
1.1       christos  230:        u_int val;
                    231:
1.2       christos  232:        _DIAGASSERT(src != NULL);
                    233:        _DIAGASSERT(dst != NULL);
                    234:
1.1       christos  235:        memset((tp = tmp), '\0', NS_IN6ADDRSZ);
                    236:        endp = tp + NS_IN6ADDRSZ;
                    237:        colonp = NULL;
                    238:        /* Leading :: requires some special handling. */
                    239:        if (*src == ':')
                    240:                if (*++src != ':')
                    241:                        return (0);
                    242:        curtok = src;
1.4       christos  243:        seen_xdigits = 0;
1.1       christos  244:        val = 0;
                    245:        while ((ch = *src++) != '\0') {
                    246:                const char *pch;
                    247:
                    248:                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
                    249:                        pch = strchr((xdigits = xdigits_u), ch);
                    250:                if (pch != NULL) {
                    251:                        val <<= 4;
1.8     ! christos  252:                        val |= (int)(pch - xdigits);
1.4       christos  253:                        if (++seen_xdigits > 4)
1.1       christos  254:                                return (0);
                    255:                        continue;
                    256:                }
                    257:                if (ch == ':') {
                    258:                        curtok = src;
1.4       christos  259:                        if (!seen_xdigits) {
1.1       christos  260:                                if (colonp)
                    261:                                        return (0);
                    262:                                colonp = tp;
                    263:                                continue;
1.2       christos  264:                        } else if (*src == '\0')
1.1       christos  265:                                return (0);
1.3       lukem     266:                        if (tp + NS_INT16SZ > endp)
1.1       christos  267:                                return (0);
                    268:                        *tp++ = (u_char) (val >> 8) & 0xff;
                    269:                        *tp++ = (u_char) val & 0xff;
1.4       christos  270:                        seen_xdigits = 0;
1.1       christos  271:                        val = 0;
                    272:                        continue;
                    273:                }
                    274:                if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
1.2       christos  275:                    inet_pton4(curtok, tp, 1) > 0) {
1.1       christos  276:                        tp += NS_INADDRSZ;
1.4       christos  277:                        seen_xdigits = 0;
                    278:                        break;  /*%< '\\0' was seen by inet_pton4(). */
1.1       christos  279:                }
                    280:                return (0);
                    281:        }
1.4       christos  282:        if (seen_xdigits) {
1.1       christos  283:                if (tp + NS_INT16SZ > endp)
                    284:                        return (0);
                    285:                *tp++ = (u_char) (val >> 8) & 0xff;
                    286:                *tp++ = (u_char) val & 0xff;
                    287:        }
                    288:        if (colonp != NULL) {
                    289:                /*
                    290:                 * Since some memmove()'s erroneously fail to handle
                    291:                 * overlapping regions, we'll do the shift by hand.
                    292:                 */
1.8     ! christos  293:                const ptrdiff_t n = tp - colonp;
1.1       christos  294:                int i;
                    295:
                    296:                if (tp == endp)
                    297:                        return (0);
                    298:                for (i = 1; i <= n; i++) {
                    299:                        endp[- i] = colonp[n - i];
                    300:                        colonp[n - i] = 0;
                    301:                }
                    302:                tp = endp;
                    303:        }
                    304:        if (tp != endp)
                    305:                return (0);
                    306:        memcpy(dst, tmp, NS_IN6ADDRSZ);
                    307:        return (1);
                    308: }
1.4       christos  309:
                    310: /*! \file */

CVSweb <webmaster@jp.NetBSD.org>