source: web/old/remctl-2.14/portable/inet_aton.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 4.8 KB
Line 
1/*
2 * Replacement for a missing inet_aton.
3 *
4 * Provides the same functionality as the standard library routine
5 * inet_aton for those platforms that don't have it.  inet_aton is
6 * thread-safe.
7 *
8 * Written by Russ Allbery <rra@stanford.edu>
9 * This work is hereby placed in the public domain by its author.
10 */
11
12#include <config.h>
13#include <portable/system.h>
14#include <portable/socket.h>
15
16/*
17 * If we're running the test suite, rename inet_ntoa to avoid conflicts with
18 * the system version.
19 */
20#if TESTING
21# define inet_aton test_inet_aton
22int test_inet_aton(const char *, struct in_addr *);
23#endif
24
25int
26inet_aton(const char *s, struct in_addr *addr)
27{
28    unsigned long octet[4], address;
29    const char *p;
30    int base, i;
31    int part = 0;
32
33    if (s == NULL)
34        return 0;
35
36    /*
37     * Step through each period-separated part of the address.  If we see
38     * more than four parts, the address is invalid.
39     */
40    for (p = s; *p != 0; part++) {
41        if (part > 3)
42            return 0;
43
44        /*
45         * Determine the base of the section we're looking at.  Numbers are
46         * represented the same as in C; octal starts with 0, hex starts
47         * with 0x, and anything else is decimal.
48         */
49        if (*p == '0') {
50            p++;
51            if (*p == 'x') {
52                p++;
53                base = 16;
54            } else {
55                base = 8;
56            }
57        } else {
58            base = 10;
59        }
60
61        /*
62         * Make sure there's actually a number.  (A section of just "0"
63         * would set base to 8 and leave us pointing at a period; allow
64         * that.)
65         */
66        if (*p == '.' && base != 8)
67            return 0;
68        octet[part] = 0;
69
70        /*
71         * Now, parse this segment of the address.  For each digit, multiply
72         * the result so far by the base and then add the value of the digit.
73         * Be careful of arithmetic overflow in cases where an unsigned long
74         * is 32 bits; we need to detect it *before* we multiply by the base
75         * since otherwise we could overflow and wrap and then not detect the
76         * error.
77         */
78        for (; *p != 0 && *p != '.'; p++) {
79            if (octet[part] > 0xffffffffUL / base)
80                return 0;
81
82            /*
83             * Use a switch statement to parse each digit rather than assuming
84             * ASCII.  Probably pointless portability.
85             */
86            switch (*p) {
87            case '0':           i = 0;  break;
88            case '1':           i = 1;  break;
89            case '2':           i = 2;  break;
90            case '3':           i = 3;  break;
91            case '4':           i = 4;  break;
92            case '5':           i = 5;  break;
93            case '6':           i = 6;  break;
94            case '7':           i = 7;  break;
95            case '8':           i = 8;  break;
96            case '9':           i = 9;  break;
97            case 'A': case 'a': i = 10; break;
98            case 'B': case 'b': i = 11; break;
99            case 'C': case 'c': i = 12; break;
100            case 'D': case 'd': i = 13; break;
101            case 'E': case 'e': i = 14; break;
102            case 'F': case 'f': i = 15; break;
103            default:            return 0;
104            }
105            if (i >= base)
106                return 0;
107            octet[part] = (octet[part] * base) + i;
108        }
109
110        /*
111         * Advance over periods; the top of the loop will increment the count
112         * of parts we've seen.  We need a check here to detect an illegal
113         * trailing period.
114         */
115        if (*p == '.') {
116            p++;
117            if (*p == 0)
118                return 0;
119        }
120    }
121    if (part == 0)
122        return 0;
123
124    /* IPv4 allows three types of address specification:
125     *
126     *     a.b
127     *     a.b.c
128     *     a.b.c.d
129     *
130     * If there are fewer than four segments, the final segment accounts for
131     * all of the remaining portion of the address.  For example, in the a.b
132     * form, b is the final 24 bits of the address.  We also allow a simple
133     * number, which is interpreted as the 32-bit number corresponding to the
134     * full IPv4 address.
135     *
136     * The first for loop below ensures that any initial segments represent
137     * only 8 bits of the address and builds the upper portion of the IPv4
138     * address.  Then, the remaining segment is checked to make sure it's no
139     * bigger than the remaining space in the address and then is added into
140     * the result.
141     */
142    address = 0;
143    for (i = 0; i < part - 1; i++) {
144        if (octet[i] > 0xff)
145            return 0;
146        address |= octet[i] << (8 * (3 - i));
147    }
148    if (octet[i] > (0xffffffffUL >> (i * 8)))
149        return 0;
150    address |= octet[i];
151    if (addr != NULL)
152        addr->s_addr = htonl(address);
153    return 1;
154}
Note: See TracBrowser for help on using the repository browser.