Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/libkern/inet_pton.c
34820 views
1
/*
2
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3
* Copyright (c) 1996,1999 by Internet Software Consortium.
4
*
5
* Permission to use, copy, modify, and distribute this software for any
6
* purpose with or without fee is hereby granted, provided that the above
7
* copyright notice and this permission notice appear in all copies.
8
*
9
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
*/
17
18
#include <sys/param.h>
19
#include <sys/socket.h>
20
#include <sys/systm.h>
21
22
#include <netinet/in.h>
23
24
/*%
25
* WARNING: Don't even consider trying to compile this on a system where
26
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
27
*/
28
29
static int inet_pton4(const char *src, u_char *dst);
30
static int inet_pton6(const char *src, u_char *dst);
31
32
/* int
33
* inet_pton(af, src, dst)
34
* convert from presentation format (which usually means ASCII printable)
35
* to network format (which is usually some kind of binary format).
36
* return:
37
* 1 if the address was valid for the specified address family
38
* 0 if the address wasn't valid (`dst' is untouched in this case)
39
* -1 if some other error occurred (`dst' is untouched in this case, too)
40
* author:
41
* Paul Vixie, 1996.
42
*/
43
int
44
inet_pton(int af, const char *src, void *dst)
45
{
46
switch (af) {
47
case AF_INET:
48
return (inet_pton4(src, dst));
49
case AF_INET6:
50
return (inet_pton6(src, dst));
51
default:
52
return (-1);
53
}
54
/* NOTREACHED */
55
}
56
57
/* int
58
* inet_pton4(src, dst)
59
* like inet_aton() but without all the hexadecimal and shorthand.
60
* return:
61
* 1 if `src' is a valid dotted quad, else 0.
62
* notice:
63
* does not touch `dst' unless it's returning 1.
64
* author:
65
* Paul Vixie, 1996.
66
*/
67
static int
68
inet_pton4(const char *src, u_char *dst)
69
{
70
static const char digits[] = "0123456789";
71
int saw_digit, octets, ch;
72
#define NS_INADDRSZ 4
73
u_char tmp[NS_INADDRSZ], *tp;
74
75
saw_digit = 0;
76
octets = 0;
77
*(tp = tmp) = 0;
78
while ((ch = *src++) != '\0') {
79
const char *pch;
80
81
if ((pch = strchr(digits, ch)) != NULL) {
82
u_int new = *tp * 10 + (pch - digits);
83
84
if (saw_digit && *tp == 0)
85
return (0);
86
if (new > 255)
87
return (0);
88
*tp = new;
89
if (!saw_digit) {
90
if (++octets > 4)
91
return (0);
92
saw_digit = 1;
93
}
94
} else if (ch == '.' && saw_digit) {
95
if (octets == 4)
96
return (0);
97
*++tp = 0;
98
saw_digit = 0;
99
} else
100
return (0);
101
}
102
if (octets < 4)
103
return (0);
104
memcpy(dst, tmp, NS_INADDRSZ);
105
return (1);
106
}
107
108
/* int
109
* inet_pton6(src, dst)
110
* convert presentation level address to network order binary form.
111
* return:
112
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
113
* notice:
114
* (1) does not touch `dst' unless it's returning 1.
115
* (2) :: in a full address is silently ignored.
116
* credit:
117
* inspired by Mark Andrews.
118
* author:
119
* Paul Vixie, 1996.
120
*/
121
static int
122
inet_pton6(const char *src, u_char *dst)
123
{
124
static const char xdigits_l[] = "0123456789abcdef",
125
xdigits_u[] = "0123456789ABCDEF";
126
#define NS_IN6ADDRSZ 16
127
#define NS_INT16SZ 2
128
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
129
const char *xdigits, *curtok;
130
int ch, seen_xdigits;
131
u_int val;
132
133
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
134
endp = tp + NS_IN6ADDRSZ;
135
colonp = NULL;
136
/* Leading :: requires some special handling. */
137
if (*src == ':')
138
if (*++src != ':')
139
return (0);
140
curtok = src;
141
seen_xdigits = 0;
142
val = 0;
143
while ((ch = *src++) != '\0') {
144
const char *pch;
145
146
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
147
pch = strchr((xdigits = xdigits_u), ch);
148
if (pch != NULL) {
149
val <<= 4;
150
val |= (pch - xdigits);
151
if (++seen_xdigits > 4)
152
return (0);
153
continue;
154
}
155
if (ch == ':') {
156
curtok = src;
157
if (!seen_xdigits) {
158
if (colonp)
159
return (0);
160
colonp = tp;
161
continue;
162
} else if (*src == '\0') {
163
return (0);
164
}
165
if (tp + NS_INT16SZ > endp)
166
return (0);
167
*tp++ = (u_char) (val >> 8) & 0xff;
168
*tp++ = (u_char) val & 0xff;
169
seen_xdigits = 0;
170
val = 0;
171
continue;
172
}
173
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
174
inet_pton4(curtok, tp) > 0) {
175
tp += NS_INADDRSZ;
176
seen_xdigits = 0;
177
break; /*%< '\\0' was seen by inet_pton4(). */
178
}
179
return (0);
180
}
181
if (seen_xdigits) {
182
if (tp + NS_INT16SZ > endp)
183
return (0);
184
*tp++ = (u_char) (val >> 8) & 0xff;
185
*tp++ = (u_char) val & 0xff;
186
}
187
if (colonp != NULL) {
188
/*
189
* Since some memmove()'s erroneously fail to handle
190
* overlapping regions, we'll do the shift by hand.
191
*/
192
const int n = tp - colonp;
193
int i;
194
195
if (tp == endp)
196
return (0);
197
for (i = 1; i <= n; i++) {
198
endp[- i] = colonp[n - i];
199
colonp[n - i] = 0;
200
}
201
tp = endp;
202
}
203
if (tp != endp)
204
return (0);
205
memcpy(dst, tmp, NS_IN6ADDRSZ);
206
return (1);
207
}
208
209
/*! \file */
210
211