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