0
|
1 /* compatibility hack for systems without any IPv6 support */ |
|
2 |
|
3 /* |
|
4 * Copyright (c) 1996-1999 by Internet Software Consortium. |
|
5 * |
|
6 * Permission to use, copy, modify, and distribute this software for any |
|
7 * purpose with or without fee is hereby granted, provided that the above |
|
8 * copyright notice and this permission notice appear in all copies. |
|
9 * |
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS |
|
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES |
|
12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE |
|
13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
|
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
|
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS |
|
16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
|
17 * SOFTWARE. |
|
18 */ |
|
19 |
|
20 /* Rhyolite Software DCC 1.3.103-1.6 $Revision$ */ |
|
21 |
|
22 |
|
23 #include "dcc_defs.h" |
|
24 |
|
25 #include <sys/types.h> |
|
26 |
|
27 #ifndef DCC_WIN32 |
|
28 #include <netinet/in.h> |
|
29 #endif |
|
30 #ifdef HAVE_ARPA_NAMESER_H |
|
31 #include <arpa/nameser.h> |
|
32 #endif |
|
33 |
|
34 |
|
35 #ifndef NS_IN6ADDRSZ |
|
36 #define NS_IN6ADDRSZ 16 |
|
37 #endif |
|
38 #ifndef NS_INT16SZ |
|
39 #define NS_INT16SZ 2 |
|
40 #endif |
|
41 |
|
42 #ifdef SPRINTF_CHAR |
|
43 # define SPRINTF(x) strlen(sprintf/**/x) |
|
44 #else |
|
45 # define SPRINTF(x) ((size_t)sprintf x) |
|
46 #endif |
|
47 |
|
48 /* |
|
49 * WARNING: Don't even consider trying to compile this on a system where |
|
50 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. |
|
51 */ |
|
52 |
|
53 static const char *inet_ntop4(const u_char *src, char *dst, size_t size); |
|
54 static const char *inet_ntop6(const u_char *src, char *dst, size_t size); |
|
55 |
|
56 /* char * |
|
57 * inet_ntop(af, src, dst, size) |
|
58 * convert a network format address to presentation format. |
|
59 * return: |
|
60 * pointer to presentation format address (`dst'), or NULL (see errno). |
|
61 * author: |
|
62 * Paul Vixie, 1996. |
|
63 */ |
|
64 const char * |
|
65 dcc_inet_ntop(int af, const void *src, char *dst, size_t size) |
|
66 { |
|
67 switch (af) { |
|
68 case AF_INET: |
|
69 return (inet_ntop4(src, dst, size)); |
|
70 case AF_INET6: |
|
71 return (inet_ntop6(src, dst, size)); |
|
72 default: |
|
73 #ifdef DCC_WIN32 |
|
74 WSASetLastError(WSAEPROTONOSUPPORT); |
|
75 #else |
|
76 errno = EAFNOSUPPORT; |
|
77 #endif |
|
78 return (NULL); |
|
79 } |
|
80 /* NOTREACHED */ |
|
81 } |
|
82 |
|
83 /* const char * |
|
84 * inet_ntop4(src, dst, size) |
|
85 * format an IPv4 address |
|
86 * return: |
|
87 * `dst' (as a const) |
|
88 * notes: |
|
89 * (1) uses no statics |
|
90 * (2) takes a u_char* not an in_addr as input |
|
91 * author: |
|
92 * Paul Vixie, 1996. |
|
93 */ |
|
94 static const char * |
|
95 inet_ntop4(src, dst, size) |
|
96 const u_char *src; |
|
97 char *dst; |
|
98 size_t size; |
|
99 { |
|
100 static const char fmt[] = "%u.%u.%u.%u"; |
|
101 char tmp[sizeof "255.255.255.255"]; |
|
102 |
|
103 if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { |
|
104 #ifdef DCC_WIN32 |
|
105 WSASetLastError(ENOSPC); |
|
106 #else |
|
107 errno = ENOSPC; |
|
108 #endif |
|
109 return (NULL); |
|
110 } |
|
111 strcpy(dst, tmp); |
|
112 return (dst); |
|
113 } |
|
114 |
|
115 /* const char * |
|
116 * inet_ntop6(src, dst, size) |
|
117 * convert IPv6 binary address into presentation (printable) format |
|
118 * author: |
|
119 * Paul Vixie, 1996. |
|
120 */ |
|
121 static const char * |
|
122 inet_ntop6(src, dst, size) |
|
123 const u_char *src; |
|
124 char *dst; |
|
125 size_t size; |
|
126 { |
|
127 /* |
|
128 * Note that int32_t and int16_t need only be "at least" large enough |
|
129 * to contain a value of the specified size. On some systems, like |
|
130 * Crays, there is no such thing as an integer variable with 16 bits. |
|
131 * Keep this in mind if you think this function should have been coded |
|
132 * to use pointer overlays. All the world's not a VAX. |
|
133 */ |
|
134 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; |
|
135 struct { int base, len; } best, cur; |
|
136 u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; |
|
137 int i; |
|
138 |
|
139 /* |
|
140 * Preprocess: |
|
141 * Copy the input (bytewise) array into a wordwise array. |
|
142 * Find the longest run of 0x00's in src[] for :: shorthanding. |
|
143 */ |
|
144 memset(words, '\0', sizeof words); |
|
145 for (i = 0; i < NS_IN6ADDRSZ; i++) |
|
146 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); |
|
147 best.base = -1; |
|
148 best.len = 0; |
|
149 cur.base = -1; |
|
150 cur.len = 0; |
|
151 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { |
|
152 if (words[i] == 0) { |
|
153 if (cur.base == -1) |
|
154 cur.base = i, cur.len = 1; |
|
155 else |
|
156 cur.len++; |
|
157 } else { |
|
158 if (cur.base != -1) { |
|
159 if (best.base == -1 || cur.len > best.len) |
|
160 best = cur; |
|
161 cur.base = -1; |
|
162 } |
|
163 } |
|
164 } |
|
165 if (cur.base != -1) { |
|
166 if (best.base == -1 || cur.len > best.len) |
|
167 best = cur; |
|
168 } |
|
169 if (best.base != -1 && best.len < 2) |
|
170 best.base = -1; |
|
171 |
|
172 /* |
|
173 * Format the result. |
|
174 */ |
|
175 tp = tmp; |
|
176 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { |
|
177 /* Are we inside the best run of 0x00's? */ |
|
178 if (best.base != -1 && i >= best.base && |
|
179 i < (best.base + best.len)) { |
|
180 if (i == best.base) |
|
181 *tp++ = ':'; |
|
182 continue; |
|
183 } |
|
184 /* Are we following an initial run of 0x00s or any real hex? */ |
|
185 if (i != 0) |
|
186 *tp++ = ':'; |
|
187 /* Is this address an encapsulated IPv4? */ |
|
188 if (i == 6 && best.base == 0 && |
|
189 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { |
|
190 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) |
|
191 return (NULL); |
|
192 tp += strlen(tp); |
|
193 break; |
|
194 } |
|
195 tp += SPRINTF((tp, "%x", words[i])); |
|
196 } |
|
197 /* Was it a trailing run of 0x00's? */ |
|
198 if (best.base != -1 && (best.base + best.len) == |
|
199 (NS_IN6ADDRSZ / NS_INT16SZ)) |
|
200 *tp++ = ':'; |
|
201 *tp++ = '\0'; |
|
202 |
|
203 /* |
|
204 * Check for overflow, copy, and we're done. |
|
205 */ |
|
206 if ((size_t)(tp - tmp) > size) { |
|
207 #ifdef DCC_WIN32 |
|
208 WSASetLastError(ENOSPC); |
|
209 #else |
|
210 errno = ENOSPC; |
|
211 #endif |
|
212 return (NULL); |
|
213 } |
|
214 strcpy(dst, tmp); |
|
215 return (dst); |
|
216 } |