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