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