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