root/usr/src/lib/libc/port/inet/inet_network.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/*      All Rights Reserved     */

/*
 * University Copyright- Copyright (c) 1982, 1986, 1988
 * The Regents of the University of California
 * All Rights Reserved
 *
 * University Acknowledgment- Portions of this document are derived from
 * software developed by the University of California, Berkeley, and its
 * contributors.
 */

#include "lint.h"

#include <sys/types.h>

#include <netinet/in.h>

#include <ctype.h>

/*
 * Internet network address interpretation routine.
 * The library routines call this routine to interpret
 * network numbers.
 */
in_addr_t
inet_network(const char *cp)
{
        in_addr_t val;
        int base;
        ptrdiff_t n;
        char c;
        in_addr_t parts[4], *pp = parts;
        int i;

again:
        val = 0; base = 10;
        if (*cp == '0') {
                if (*++cp == 'x' || *cp == 'X')
                        base = 16, cp++;
                else
                        base = 8;
        }
        while ((c = *cp) != '\0') {
                if (isdigit(c)) {
                        if ((c - '0') >= base)
                                break;
                        val = (val * base) + (c - '0');
                        cp++;
                        continue;
                }
                if (base == 16 && isxdigit(c)) {
                        val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
                        cp++;
                        continue;
                }
                break;
        }
        if (pp >= parts + 4 || val > 0xff)
                return ((in_addr_t)-1);
        *pp++ = val;
        if (*cp == '.') {
                cp++;
                goto again;
        }
        if (*cp != '\0' && !isspace(*cp))
                return ((in_addr_t)-1);
        n = pp - parts;
        for (val = 0, i = 0; i < n; i++) {
                val <<= 8;
                val |= parts[i];
        }
        return (val);
}