ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/inet_misc.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (19 years, 11 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/src/inet_misc.c
File size: 12414 byte(s)
Log Message:
- Fix svn:keywords

File Contents

# User Rev Content
1 adx 30 /* inet_misc.c - inet_pton and inet_ntop for those who don't have it.
2 knight 31 * $Id$
3 adx 30 *
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"