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