1
/* Id: inet_pton.c,v 1.5 2001/04/13 15:24:35 lukem Exp */
2
/* $NetBSD: inet_pton.c,v 1.16 2000/02/07 18:51:02 itojun Exp $ */
4
/* Copyright (c) 1996 by Internet Software Consortium.
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
10
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
11
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
13
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
16
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20
#include <net-snmp/net-snmp-config.h>
22
#ifndef HAVE_INET_PTON
24
#if HAVE_ARPA_NAMESER_H
25
#include <arpa/nameser.h>
29
* Net-SNMP Win32 additions
38
#define EAFNOSUPPORT WSAEAFNOSUPPORT
52
* End of Net-SNMP Win32 additions
60
* WARNING: Don't even consider trying to compile this on a system where
61
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
64
static int inet_pton4(const char *src, u_char *dst, int pton);
66
static int inet_pton6(const char *src, u_char *dst);
70
* inet_pton(af, src, dst)
71
* convert from presentation format (which usually means ASCII printable)
72
* to network format (which is usually some kind of binary format).
74
* 1 if the address was valid for the specified address family
75
* 0 if the address wasn't valid (`dst' is untouched in this case)
76
* -1 if some other error occurred (`dst' is untouched in this case, too)
81
inet_pton(af, src, dst)
89
return (inet_pton4(src, dst, 1));
92
return (inet_pton6(src, dst));
102
* inet_pton4(src, dst, pton)
103
* when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
104
* when last arg is 1: inet_pton(). decimal dotted-quad only.
106
* 1 if `src' is a valid input, else 0.
108
* does not touch `dst' unless it's returning 1.
113
inet_pton4(src, dst, pton)
123
register u_int *pp = parts;
128
* Collect number up to ``.''.
129
* Values are specified as for C:
130
* 0x=hex, 0=octal, isdigit=decimal.
137
if (c == 'x' || c == 'X')
138
base = 16, c = *++src;
139
else if (isdigit(c) && c != '9')
142
/* inet_pton() takes decimal only */
143
if (pton && base != 10)
150
val = (val * base) + digit;
152
} else if (base == 16 && isxdigit(c)) {
153
digit = c + 10 - (islower(c) ? 'a' : 'A');
156
val = (val << 4) | digit;
165
* a.b.c (with c treated as 16 bits)
166
* a.b (with b treated as 24 bits)
167
* a (with a treated as 32 bits)
177
* Check for trailing characters.
179
if (c != '\0' && !isspace(c))
182
* Concoct the address according to
183
* the number of parts specified.
186
/* inet_pton() takes dotted-quad only. it does not take shorthand. */
192
return (0); /* initial nondigit */
194
case 1: /* a -- 32 bits */
197
case 2: /* a.b -- 8.24 bits */
198
if (parts[0] > 0xff || val > 0xffffff)
200
val |= parts[0] << 24;
203
case 3: /* a.b.c -- 8.8.16 bits */
204
if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
206
val |= (parts[0] << 24) | (parts[1] << 16);
209
case 4: /* a.b.c.d -- 8.8.8.8 bits */
210
if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
212
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
217
memcpy(dst, &val, INADDRSZ);
224
* inet_pton6(src, dst)
225
* convert presentation level address to network order binary form.
227
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
229
* (1) does not touch `dst' unless it's returning 1.
230
* (2) :: in a full address is silently ignored.
232
* inspired by Mark Andrews.
241
static const char xdigits_l[] = "0123456789abcdef",
242
xdigits_u[] = "0123456789ABCDEF";
243
u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
244
const char *xdigits, *curtok;
248
memset((tp = tmp), '\0', IN6ADDRSZ);
249
endp = tp + IN6ADDRSZ;
251
/* Leading :: requires some special handling. */
258
while ((ch = *src++) != '\0') {
261
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
262
pch = strchr((xdigits = xdigits_u), ch);
265
val |= (pch - xdigits);
278
} else if (*src == '\0')
280
if (tp + INT16SZ > endp)
282
*tp++ = (u_char) (val >> 8) & 0xff;
283
*tp++ = (u_char) val & 0xff;
288
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
289
inet_pton4(curtok, tp, 1) > 0) {
292
break; /* '\0' was seen by inet_pton4(). */
297
if (tp + INT16SZ > endp)
299
*tp++ = (u_char) (val >> 8) & 0xff;
300
*tp++ = (u_char) val & 0xff;
302
if (colonp != NULL) {
304
* Since some memmove()'s erroneously fail to handle
305
* overlapping regions, we'll do the shift by hand.
307
const int n = tp - colonp;
312
for (i = 1; i <= n; i++) {
313
endp[- i] = colonp[n - i];
320
memcpy(dst, tmp, IN6ADDRSZ);
325
#endif /* HAVE_INET_PTON */