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