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