-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse_inaddr.c
170 lines (138 loc) · 4.01 KB
/
parse_inaddr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*
* $Id: //devel/tools/main/nbtscan/parse_inaddr.c#1 $
*
* This is a replacment for the useful but not [yet] portable
* inet_aton() function. The user passes in a pointer to what
* purports to be a dots-and-digits IP address, and this function
* cracks it apart, storing it into the pointed-to unsigned long.
*
* Return value is 0 on error and nonzero if all is well. This
* function is a better interface than inet_addr() becauser it is
* able to recognize all the possible addresses, including
* 255.255.255.255. This is an error return for inet_addr().
*
* This function /strictly/ implements dots-and-digits, so it's
* not possible to fool it with the usual very large decimal
* number tricks. It also does not permit any deviation from
* the exact requirements of dotted-quads.
*/
#ifndef COMMONFILE
# define COMMONFILE "libcommon.h"
#endif
#include COMMONFILE
#include <ctype.h>
#include "penlib.h"
/*
* scan_digits()
*
* Advance along the string scanning the digits seen, returning
* TRUE if all is well and FALSE if not. We return failure if there
* are no digits found or if the scanned number is out of range of
* an IP octet (0..255).
*
* We also pass the character that should be seen immediately
* after the digit sequence and return failure if this is not found.
*/
static int scan_digits(const char **pstring, int *pdigit, char after)
{
assert( pstring != 0);
assert(*pstring != 0);
assert( pdigit != 0);
#undef P
#define P (*pstring)
#undef N
#define N (*pdigit)
N = 0;
if ( ! isdigit(*P) ) return FALSE;
while ( isdigit(*P) )
N = (N * 10) + (*P++ - '0');
if ( N >= 256 ) return FALSE;
if ( *P++ != after ) return FALSE;
return TRUE;
#undef P
#undef N
}
int parse_inaddr(const char *cp, unsigned long *inp)
{
int a = 0,
b = 0,
c = 0,
d = 0;
assert(cp != 0);
assert(inp != 0);
*inp = (unsigned long) -1; /* same as INADDR_NONE */
if ( ! scan_digits(&cp, &a, '.' ) ) return FALSE;
if ( ! scan_digits(&cp, &b, '.' ) ) return FALSE;
if ( ! scan_digits(&cp, &c, '.' ) ) return FALSE;
if ( ! scan_digits(&cp, &d, '\0') ) return FALSE;
*inp = build_ipaddr_from_octets(a, b, c, d);
return TRUE;
}
/*------------------------------------------------------------------------
* TEST HARNESS
*
* This function will be in the center of our little universe, so
* we really want to make sure that it works correctly. This is a
* test harness that uses a table of known values and compares them
* with the result of the function.
*
* As failures are found, add them to this table for testing!
*/
#ifdef TESTING
static const struct tester {
const char *remote;
int expect_rc;
unsigned long expect_addr; /* HOST word order! */
} table[] = {
/* all legal addresses */
{ "209.60.37.2", TRUE, 0xFFFFFFFF },
{ "209.60.37.255", TRUE, 0xFFFFFFFF },
{ "127.0.0.1", TRUE, 0x7F000001 },
/* odd values, but are legal */
{ "0.0.0.0", TRUE, 0x00000000 },
{ "255.255.255.255", TRUE, 0xFFFFFFFF },
/* all have out-of-range values */
{ "256.255.255.255", FALSE, 0xFFFFFFFF },
{ "255.256.256.255", FALSE, 0xFFFFFFFF },
{ "255.255.256.255", FALSE, 0xFFFFFFFF },
{ "255.255.255.256", FALSE, 0xFFFFFFFF },
{ "127.0.0.2000", FALSE, 0xFFFFFFFF },
{ "127.0.0.2000", FALSE, 0xFFFFFFFF },
{ "-1.0.0.0", FALSE, 0xFFFFFFFF },
{ 0 }
};
#define SF(x) ((x) ? "success" : "failure")
int main()
{
const struct tester *ptest;
printf("parse_inaddr() test driver\n");
for ( ptest = table; ptest->remote != 0; ptest++ )
{
int rc;
unsigned long result_addr,
should_be;
should_be = ptest->expect_addr);
rc = parse_inaddr(ptest->remote, &result_addr) != 0;
/*
printf("string %s, rc = %d, expected = %s\n",
ptest->remote,
rc,
SF(ptest->expect_rc));
*/
/* rc == 0 -> failure */
/* rc != 0 -> successd */
if ( rc != ptest->expect_rc )
{
printf("ERROR: for string \"%s\"\n", ptest->remote);
printf(" expected %s, got %s\n",
SF(ptest->expect_rc), SF(rc));
}
else
{
printf("%s OK for string \"%s\"\n",
SF(rc),
ptest->remote);
}
}
}
#endif /* TESTING */