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  * The canonical version of this file is maintained in the rra-c-util package,
9  * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
10  *
11  * Written by Russ Allbery <eagle@eyrie.org>
12  * Copyright 2000-2001, 2017, 2019-2020 Russ Allbery <eagle@eyrie.org>
13  * Copyright 2008, 2011, 2014
14  *     The Board of Trustees of the Leland Stanford Junior University
15  *
16  * Copying and distribution of this file, with or without modification, are
17  * permitted in any medium without royalty provided the copyright notice and
18  * this notice are preserved.  This file is offered as-is, without any
19  * warranty.
20  *
21  * SPDX-License-Identifier: FSFAP
22  */
23 
24 #include "config.h"
25 #include "portable/socket.h"
26 #include "portable/system.h"
27 
28 /*
29  * If we're running the test suite, rename inet_aton to avoid conflicts with
30  * the system version.
31  */
32 #if TESTING
33 #    undef inet_aton
34 #    define inet_aton test_inet_aton
35 int test_inet_aton(const char *, struct in_addr *);
36 #endif
37 
38 int
inet_aton(const char * s,struct in_addr * addr)39 inet_aton(const char *s, struct in_addr *addr)
40 {
41     unsigned octet[4];
42     uint32_t address;
43     const char *p;
44     unsigned int base, i;
45     unsigned int part = 0;
46 
47     if (s == NULL)
48         return 0;
49 
50     /*
51      * Step through each period-separated part of the address.  If we see
52      * more than four parts, the address is invalid.
53      */
54     for (p = s; *p != 0; part++) {
55         if (part > 3)
56             return 0;
57 
58         /*
59          * Determine the base of the section we're looking at.  Numbers are
60          * represented the same as in C; octal starts with 0, hex starts
61          * with 0x, and anything else is decimal.
62          */
63         if (*p == '0') {
64             p++;
65             if (*p == 'x') {
66                 p++;
67                 base = 16;
68             } else {
69                 base = 8;
70             }
71         } else {
72             base = 10;
73         }
74 
75         /*
76          * Make sure there's actually a number.  (A section of just "0"
77          * would set base to 8 and leave us pointing at a period; allow
78          * that.)
79          */
80         if (*p == '.' && base != 8)
81             return 0;
82         octet[part] = 0;
83 
84         /*
85          * Now, parse this segment of the address.  For each digit, multiply
86          * the result so far by the base and then add the value of the digit.
87          * Be careful of arithmetic overflow in cases where an unsigned long
88          * is 32 bits; we need to detect it *before* we multiply by the base
89          * since otherwise we could overflow and wrap and then not detect the
90          * error.
91          */
92         for (; *p != 0 && *p != '.'; p++) {
93             if (octet[part] > 0xffffffffUL / base)
94                 return 0;
95 
96             /*
97              * Use a switch statement to parse each digit rather than assuming
98              * ASCII.  Probably pointless portability.
99              */
100             /* clang-format off */
101             switch (*p) {
102             case '0':           i = 0;  break;
103             case '1':           i = 1;  break;
104             case '2':           i = 2;  break;
105             case '3':           i = 3;  break;
106             case '4':           i = 4;  break;
107             case '5':           i = 5;  break;
108             case '6':           i = 6;  break;
109             case '7':           i = 7;  break;
110             case '8':           i = 8;  break;
111             case '9':           i = 9;  break;
112             case 'A': case 'a': i = 10; break;
113             case 'B': case 'b': i = 11; break;
114             case 'C': case 'c': i = 12; break;
115             case 'D': case 'd': i = 13; break;
116             case 'E': case 'e': i = 14; break;
117             case 'F': case 'f': i = 15; break;
118             default:            return 0;
119             }
120             /* clang-format on */
121             if (i >= base)
122                 return 0;
123             octet[part] = (octet[part] * base) + i;
124         }
125 
126         /*
127          * Advance over periods; the top of the loop will increment the count
128          * of parts we've seen.  We need a check here to detect an illegal
129          * trailing period.
130          */
131         if (*p == '.') {
132             p++;
133             if (*p == 0)
134                 return 0;
135         }
136     }
137     if (part == 0)
138         return 0;
139 
140     /* IPv4 allows three types of address specification:
141      *
142      *     a.b
143      *     a.b.c
144      *     a.b.c.d
145      *
146      * If there are fewer than four segments, the final segment accounts for
147      * all of the remaining portion of the address.  For example, in the a.b
148      * form, b is the final 24 bits of the address.  We also allow a simple
149      * number, which is interpreted as the 32-bit number corresponding to the
150      * full IPv4 address.
151      *
152      * The first for loop below ensures that any initial segments represent
153      * only 8 bits of the address and builds the upper portion of the IPv4
154      * address.  Then, the remaining segment is checked to make sure it's no
155      * bigger than the remaining space in the address and then is added into
156      * the result.
157      */
158     address = 0;
159     for (i = 0; i < part - 1; i++) {
160         if (octet[i] > 0xff)
161             return 0;
162         address |= octet[i] << (8 * (3 - i));
163     }
164     if (octet[i] > (0xffffffffUL >> (i * 8)))
165         return 0;
166     address |= octet[i];
167     if (addr != NULL)
168         addr->s_addr = htonl(address);
169     return 1;
170 }
171