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