~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/network_io/unix/inet_ntop.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

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