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