ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/inet_misc.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 5 months ago) by lusky
Content type: text/x-csrc
File size: 12414 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


File Contents

# Content
1 /* inet_misc.c - inet_pton and inet_ntop for those who don't have it.
2 * $Id$
3 *
4 * Copyright (c) 1983, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. */
34
35 /* This inet_aton() function was taken from the GNU C library and
36 * incorporated into ircd-hybrid for those systems which do not have this
37 * routine in their standard C libraries.
38 *
39 * The function was been extracted whole from the file inet_aton.c in
40 * Release 5.3.12 of the Linux C library, which is derived from the
41 * GNU C library, by Bryan Henderson in October 1996. The copyright
42 * notice from that file is below.
43 */
44
45 #include "stdinc.h"
46 #include "irc_res.h"
47
48 #ifdef NO_IN6ADDR_ANY
49 /* Stolen from glibc */
50 const struct in6_addr in6addr_any =
51 { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
52 #endif
53
54 #ifdef NO_INET_ATON
55 /*
56 * Check whether "cp" is a valid ascii representation
57 * of an Internet address and convert to a binary address.
58 * Returns 1 if the address is valid, 0 if not.
59 * This replaces inet_addr, the return value from which
60 * cannot distinguish between failure and a local broadcast address.
61 */
62 int
63 inet_aton(const char *cp, struct in_addr * addr)
64 {
65 unsigned int val;
66 int base,
67 n;
68 char c;
69 unsigned int parts[4];
70 unsigned int *pp = parts;
71
72 for (;;)
73 {
74 /*
75 * Collect number up to ``.''. Values are specified as for C:
76 * 0x=hex, 0=octal, other=decimal.
77 */
78 val = 0;
79 base = 10;
80 if (*cp == '0')
81 {
82 if (*++cp == 'x' || *cp == 'X')
83 base = 16, cp++;
84 else
85 base = 8;
86 }
87 while ((c = *cp) != '\0')
88 {
89 if (isdigit((unsigned char) c))
90 {
91 val = (val * base) + (c - '0');
92 cp++;
93 continue;
94 }
95 if (base == 16 && isxdigit((unsigned char) c))
96 {
97 val = (val << 4) +
98 (c + 10 - (islower((unsigned char) c) ? 'a' : 'A'));
99 cp++;
100 continue;
101 }
102 break;
103 }
104 if (*cp == '.')
105 {
106 /*
107 * Internet format: a.b.c.d a.b.c (with c treated as
108 * 16-bits) a.b (with b treated as 24 bits)
109 */
110 if (pp >= parts + 3 || val > 0xff)
111 return 0;
112 *pp++ = val, cp++;
113 }
114 else
115 break;
116 }
117
118 /*
119 * Check for trailing junk.
120 */
121 while (*cp)
122 if (!isspace((unsigned char) *cp++))
123 return 0;
124
125 /*
126 * Concoct the address according to the number of parts specified.
127 */
128 n = pp - parts + 1;
129 switch (n)
130 {
131
132 case 1: /* a -- 32 bits */
133 break;
134
135 case 2: /* a.b -- 8.24 bits */
136 if (val > 0xffffff)
137 return 0;
138 val |= parts[0] << 24;
139 break;
140
141 case 3: /* a.b.c -- 8.8.16 bits */
142 if (val > 0xffff)
143 return 0;
144 val |= (parts[0] << 24) | (parts[1] << 16);
145 break;
146
147 case 4: /* a.b.c.d -- 8.8.8.8 bits */
148 if (val > 0xff)
149 return 0;
150 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
151 break;
152 }
153 if (addr)
154 addr->s_addr = htonl(val);
155 return 1;
156 }
157
158 #endif /* NO_INET_ATON */
159
160 #ifdef NO_INET_NTOP
161 static const char *inet_ntop4(const unsigned char *src, char *dst,
162 size_t size);
163
164 #ifdef IPV6
165 static const char *inet_ntop6(const unsigned char *src, char *dst,
166 size_t size);
167 #endif
168
169 /* char *
170 * isc_net_ntop(af, src, dst, size)
171 * convert a network format address to presentation format.
172 * return:
173 * pointer to presentation format address (`dst'), or NULL (see errno).
174 * author:
175 * Paul Vixie, 1996.
176 */
177 const char *
178 inet_ntop(int af, const void *src, char *dst, size_t size)
179 {
180 switch (af) {
181 case AF_INET:
182 return (inet_ntop4(src, dst, size));
183 #ifdef IPV6
184 case AF_INET6:
185 return (inet_ntop6(src, dst, size));
186 #endif
187 default:
188 errno = EAFNOSUPPORT;
189 return (NULL);
190 }
191 /* NOTREACHED */
192 }
193
194 /* const char *
195 * inet_ntop4(src, dst, size)
196 * format an IPv4 address
197 * return:
198 * `dst' (as a const)
199 * notes:
200 * (1) uses no statics
201 * (2) takes a unsigned char* not an in_addr as input
202 * author:
203 * Paul Vixie, 1996.
204 */
205 static const char *
206 inet_ntop4(const unsigned char *src, char *dst, size_t size)
207 {
208 static const char *fmt = "%u.%u.%u.%u";
209 char tmp[sizeof "255.255.255.255"];
210
211 if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
212 {
213 errno = ENOSPC;
214 return (NULL);
215 }
216 strcpy(dst, tmp);
217
218 return (dst);
219 }
220
221 /* const char *
222 * isc_inet_ntop6(src, dst, size)
223 * convert IPv6 binary address into presentation (printable) format
224 * author:
225 * Paul Vixie, 1996.
226 */
227 #ifdef IPV6
228 static const char *
229 inet_ntop6(const unsigned char *src, char *dst, size_t size)
230 {
231 /*
232 * Note that int32_t and int16_t need only be "at least" large enough
233 * to contain a value of the specified size. On some systems, like
234 * Crays, there is no such thing as an integer variable with 16 bits.
235 * Keep this in mind if you think this function should have been coded
236 * to use pointer overlays. All the world's not a VAX.
237 */
238 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
239 struct { int base, len; } best, cur;
240 unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
241 int i;
242
243 /*
244 * Preprocess:
245 * Copy the input (bytewise) array into a wordwise array.
246 * Find the longest run of 0x00's in src[] for :: shorthanding.
247 */
248 memset(words, '\0', sizeof words);
249 for (i = 0; i < NS_IN6ADDRSZ; i++)
250 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
251 best.base = -1;
252 cur.base = -1;
253 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
254 if (words[i] == 0) {
255 if (cur.base == -1)
256 cur.base = i, cur.len = 1;
257 else
258 cur.len++;
259 } else {
260 if (cur.base != -1) {
261 if (best.base == -1 || cur.len > best.len)
262 best = cur;
263 cur.base = -1;
264 }
265 }
266 }
267 if (cur.base != -1) {
268 if (best.base == -1 || cur.len > best.len)
269 best = cur;
270 }
271 if (best.base != -1 && best.len < 2)
272 best.base = -1;
273
274 /*
275 * Format the result.
276 */
277 tp = tmp;
278 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
279 /* Are we inside the best run of 0x00's? */
280 if (best.base != -1 && i >= best.base &&
281 i < (best.base + best.len)) {
282 if (i == best.base)
283 *tp++ = ':';
284 continue;
285 }
286 /* Are we following an initial run of 0x00s or any real hex? */
287 if (i != 0)
288 *tp++ = ':';
289 /* Is this address an encapsulated IPv4? */
290 if (i == 6 && best.base == 0 &&
291 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
292 if (!inet_ntop4(src+12, tp,
293 sizeof tmp - (tp - tmp)))
294 return (NULL);
295 tp += strlen(tp);
296 break;
297 }
298 tp += sprintf(tp, "%x", words[i]);
299 }
300 /* Was it a trailing run of 0x00's? */
301 if (best.base != -1 && (best.base + best.len) ==
302 (NS_IN6ADDRSZ / NS_INT16SZ))
303 *tp++ = ':';
304 *tp++ = '\0';
305
306 /*
307 * Check for overflow, copy, and we're done.
308 */
309 if ((size_t)(tp - tmp) > size) {
310 errno = ENOSPC;
311 return (NULL);
312 }
313 strcpy(dst, tmp);
314 return (dst);
315 }
316 #endif /* IPV6 */
317
318 #endif /* NO_INET_NTOP */
319
320 #ifdef NO_INET_PTON
321
322 static int inet_pton4(const char *src, unsigned char *dst);
323 #ifdef IPV6
324 static int inet_pton6(const char *src, unsigned char *dst);
325 #endif
326
327 /* int
328 * inet_pton(af, src, dst)
329 * convert from presentation format (which usually means ASCII printable)
330 * to network format (which is usually some kind of binary format).
331 * return:
332 * 1 if the address was valid for the specified address family
333 * 0 if the address wasn't valid (`dst' is untouched in this case)
334 * -1 if some other error occurred (`dst' is untouched in this case, too)
335 * author:
336 * Paul Vixie, 1996.
337 */
338 int
339 inet_pton(int af,
340 const char *src,
341 void *dst)
342 {
343 switch (af) {
344 case AF_INET:
345 return (inet_pton4(src, dst));
346 #ifdef IPV6
347 case AF_INET6:
348 return (inet_pton6(src, dst));
349 #endif
350 default:
351 errno = EAFNOSUPPORT;
352 return (-1);
353 }
354 /* NOTREACHED */
355 }
356
357 /* int
358 * inet_pton4(src, dst)
359 * like inet_aton() but without all the hexadecimal and shorthand.
360 * return:
361 * 1 if `src' is a valid dotted quad, else 0.
362 * notice:
363 * does not touch `dst' unless it's returning 1.
364 * author:
365 * Paul Vixie, 1996.
366 */
367 static int
368 inet_pton4(src, dst)
369 const char *src;
370 unsigned char *dst;
371 {
372 static const char digits[] = "0123456789";
373 int saw_digit, octets, ch;
374 unsigned char tmp[NS_INADDRSZ], *tp;
375
376 saw_digit = 0;
377 octets = 0;
378 *(tp = tmp) = 0;
379 while ((ch = *src++) != '\0') {
380 const char *pch;
381
382 if ((pch = strchr(digits, ch)) != NULL) {
383 unsigned int new = *tp * 10 + (pch - digits);
384
385 if (new > 255)
386 return (0);
387 *tp = new;
388 if (! saw_digit) {
389 if (++octets > 4)
390 return (0);
391 saw_digit = 1;
392 }
393 } else if (ch == '.' && saw_digit) {
394 if (octets == 4)
395 return (0);
396 *++tp = 0;
397 saw_digit = 0;
398 } else
399 return (0);
400 }
401 if (octets < 4)
402 return (0);
403 memcpy(dst, tmp, NS_INADDRSZ);
404 return (1);
405 }
406
407 /* int
408 * inet_pton6(src, dst)
409 * convert presentation level address to network order binary form.
410 * return:
411 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
412 * notice:
413 * (1) does not touch `dst' unless it's returning 1.
414 * (2) :: in a full address is silently ignored.
415 * credit:
416 * inspired by Mark Andrews.
417 * author:
418 * Paul Vixie, 1996.
419 */
420 #ifdef IPV6
421 static int
422 inet_pton6(src, dst)
423 const char *src;
424 unsigned char *dst;
425 {
426 static const char xdigits_l[] = "0123456789abcdef",
427 xdigits_u[] = "0123456789ABCDEF";
428 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
429 const char *xdigits, *curtok;
430 int ch, saw_xdigit;
431 unsigned int val;
432
433 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
434 endp = tp + NS_IN6ADDRSZ;
435 colonp = NULL;
436 /* Leading :: requires some special handling. */
437 if (*src == ':')
438 if (*++src != ':')
439 return (0);
440 curtok = src;
441 saw_xdigit = 0;
442 val = 0;
443 while ((ch = *src++) != '\0') {
444 const char *pch;
445
446 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
447 pch = strchr((xdigits = xdigits_u), ch);
448 if (pch != NULL) {
449 val <<= 4;
450 val |= (pch - xdigits);
451 if (val > 0xffff)
452 return (0);
453 saw_xdigit = 1;
454 continue;
455 }
456 if (ch == ':') {
457 curtok = src;
458 if (!saw_xdigit) {
459 if (colonp)
460 return (0);
461 colonp = tp;
462 continue;
463 }
464 if (tp + NS_INT16SZ > endp)
465 return (0);
466 *tp++ = (unsigned char) (val >> 8) & 0xff;
467 *tp++ = (unsigned char) val & 0xff;
468 saw_xdigit = 0;
469 val = 0;
470 continue;
471 }
472 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
473 inet_pton4(curtok, tp) > 0) {
474 tp += NS_INADDRSZ;
475 saw_xdigit = 0;
476 break; /* '\0' was seen by inet_pton4(). */
477 }
478 return (0);
479 }
480 if (saw_xdigit) {
481 if (tp + NS_INT16SZ > endp)
482 return (0);
483 *tp++ = (unsigned char) (val >> 8) & 0xff;
484 *tp++ = (unsigned char) val & 0xff;
485 }
486 if (colonp != NULL) {
487 /*
488 * Since some memmove()'s erroneously fail to handle
489 * overlapping regions, we'll do the shift by hand.
490 */
491 const int n = tp - colonp;
492 int i;
493
494 for (i = 1; i <= n; i++) {
495 endp[- i] = colonp[n - i];
496 colonp[n - i] = 0;
497 }
498 tp = endp;
499 }
500 if (tp != endp)
501 return (0);
502 memcpy(dst, tmp, NS_IN6ADDRSZ);
503 return (1);
504 }
505 #endif /* IPV6 */
506
507 #endif /* NO_INET_PTON */

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision