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