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

« back to all changes in this revision

Viewing changes to srclib/apr/network_io/unix/inet_pton.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
 
 
20
#if APR_HAVE_SYS_TYPES_H
 
21
#include <sys/types.h>
 
22
#endif
 
23
#if APR_HAVE_SYS_SOCKET_H
 
24
#include <sys/socket.h>
 
25
#endif
 
26
#if APR_HAVE_NETINET_IN_H
 
27
#include <netinet/in.h>
 
28
#endif
 
29
#if APR_HAVE_ARPA_INET_H
 
30
#include <arpa/inet.h>
 
31
#endif
 
32
#include <string.h>
 
33
#if APR_HAVE_ERRNO_H
 
34
#include <errno.h>
 
35
#endif
 
36
 
 
37
#ifndef IN6ADDRSZ
 
38
#define IN6ADDRSZ   16
 
39
#endif
 
40
 
 
41
#ifndef INT16SZ
 
42
#define INT16SZ sizeof(apr_int16_t)
 
43
#endif
 
44
 
 
45
#ifndef INADDRSZ
 
46
#define INADDRSZ    4
 
47
#endif
 
48
 
 
49
#ifndef __P
 
50
#define __P(x) x
 
51
#endif
 
52
 
 
53
#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT)
 
54
#define EAFNOSUPPORT WSAEAFNOSUPPORT
 
55
#endif
 
56
 
 
57
/*
 
58
 * WARNING: Don't even consider trying to compile this on a system where
 
59
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
 
60
 */
 
61
 
 
62
static int      inet_pton4 __P((const char *src, unsigned char *dst));
 
63
#if APR_HAVE_IPV6
 
64
static int      inet_pton6 __P((const char *src, unsigned char *dst));
 
65
#endif
 
66
 
 
67
/* int
 
68
 * inet_pton(af, src, dst)
 
69
 *      convert from presentation format (which usually means ASCII printable)
 
70
 *      to network format (which is usually some kind of binary format).
 
71
 * return:
 
72
 *      1 if the address was valid for the specified address family
 
73
 *      0 if the address wasn't valid (`dst' is untouched in this case)
 
74
 *      -1 if some other error occurred (`dst' is untouched in this case, too)
 
75
 * author:
 
76
 *      Paul Vixie, 1996.
 
77
 */
 
78
int
 
79
apr_inet_pton(int af, const char *src, void *dst)
 
80
{
 
81
        switch (af) {
 
82
        case AF_INET:
 
83
                return (inet_pton4(src, dst));
 
84
#if APR_HAVE_IPV6
 
85
        case AF_INET6:
 
86
                return (inet_pton6(src, dst));
 
87
#endif
 
88
        default:
 
89
                errno = EAFNOSUPPORT;
 
90
                return (-1);
 
91
        }
 
92
        /* NOTREACHED */
 
93
}
 
94
 
 
95
/* int
 
96
 * inet_pton4(src, dst)
 
97
 *      like inet_aton() but without all the hexadecimal and shorthand.
 
98
 * return:
 
99
 *      1 if `src' is a valid dotted quad, else 0.
 
100
 * notice:
 
101
 *      does not touch `dst' unless it's returning 1.
 
102
 * author:
 
103
 *      Paul Vixie, 1996.
 
104
 */
 
105
static int
 
106
inet_pton4(const char *src, unsigned char *dst)
 
107
{
 
108
    static const char digits[] = "0123456789";
 
109
    int saw_digit, octets, ch;
 
110
    unsigned char tmp[INADDRSZ], *tp;
 
111
 
 
112
    saw_digit = 0;
 
113
    octets = 0;
 
114
    *(tp = tmp) = 0;
 
115
    while ((ch = *src++) != '\0') {
 
116
        const char *pch;
 
117
 
 
118
        if ((pch = strchr(digits, ch)) != NULL) {
 
119
            unsigned int new = *tp * 10 + (unsigned int)(pch - digits);
 
120
 
 
121
            if (new > 255)
 
122
                return (0);
 
123
            *tp = new;
 
124
            if (! saw_digit) {
 
125
                if (++octets > 4)
 
126
                    return (0);
 
127
                saw_digit = 1;
 
128
            }
 
129
        } else if (ch == '.' && saw_digit) {
 
130
            if (octets == 4)
 
131
                return (0);
 
132
            *++tp = 0;
 
133
            saw_digit = 0;
 
134
        } else
 
135
                return (0);
 
136
    }
 
137
    if (octets < 4)
 
138
        return (0);
 
139
 
 
140
    memcpy(dst, tmp, INADDRSZ);
 
141
    return (1);
 
142
}
 
143
 
 
144
#if APR_HAVE_IPV6
 
145
/* int
 
146
 * inet_pton6(src, dst)
 
147
 *      convert presentation level address to network order binary form.
 
148
 * return:
 
149
 *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
 
150
 * notice:
 
151
 *      (1) does not touch `dst' unless it's returning 1.
 
152
 *      (2) :: in a full address is silently ignored.
 
153
 * credit:
 
154
 *      inspired by Mark Andrews.
 
155
 * author:
 
156
 *      Paul Vixie, 1996.
 
157
 */
 
158
static int
 
159
inet_pton6(const char *src, unsigned char *dst)
 
160
{
 
161
        static const char xdigits_l[] = "0123456789abcdef",
 
162
                          xdigits_u[] = "0123456789ABCDEF";
 
163
        unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
 
164
        const char *xdigits, *curtok;
 
165
        int ch, saw_xdigit;
 
166
        unsigned int val;
 
167
 
 
168
        memset((tp = tmp), '\0', IN6ADDRSZ);
 
169
        endp = tp + IN6ADDRSZ;
 
170
        colonp = NULL;
 
171
        /* Leading :: requires some special handling. */
 
172
        if (*src == ':')
 
173
                if (*++src != ':')
 
174
                        return (0);
 
175
        curtok = src;
 
176
        saw_xdigit = 0;
 
177
        val = 0;
 
178
        while ((ch = *src++) != '\0') {
 
179
                const char *pch;
 
180
 
 
181
                if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
 
182
                        pch = strchr((xdigits = xdigits_u), ch);
 
183
                if (pch != NULL) {
 
184
                        val <<= 4;
 
185
                        val |= (pch - xdigits);
 
186
                        if (val > 0xffff)
 
187
                                return (0);
 
188
                        saw_xdigit = 1;
 
189
                        continue;
 
190
                }
 
191
                if (ch == ':') {
 
192
                        curtok = src;
 
193
                        if (!saw_xdigit) {
 
194
                                if (colonp)
 
195
                                        return (0);
 
196
                                colonp = tp;
 
197
                                continue;
 
198
                        }
 
199
                        if (tp + INT16SZ > endp)
 
200
                                return (0);
 
201
                        *tp++ = (unsigned char) (val >> 8) & 0xff;
 
202
                        *tp++ = (unsigned char) val & 0xff;
 
203
                        saw_xdigit = 0;
 
204
                        val = 0;
 
205
                        continue;
 
206
                }
 
207
                if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
 
208
                    inet_pton4(curtok, tp) > 0) {
 
209
                        tp += INADDRSZ;
 
210
                        saw_xdigit = 0;
 
211
                        break;  /* '\0' was seen by inet_pton4(). */
 
212
                }
 
213
                return (0);
 
214
        }
 
215
        if (saw_xdigit) {
 
216
                if (tp + INT16SZ > endp)
 
217
                        return (0);
 
218
                *tp++ = (unsigned char) (val >> 8) & 0xff;
 
219
                *tp++ = (unsigned char) val & 0xff;
 
220
        }
 
221
        if (colonp != NULL) {
 
222
                /*
 
223
                 * Since some memmove()'s erroneously fail to handle
 
224
                 * overlapping regions, we'll do the shift by hand.
 
225
                 */
 
226
                const int n = tp - colonp;
 
227
                int i;
 
228
 
 
229
                for (i = 1; i <= n; i++) {
 
230
                        endp[- i] = colonp[n - i];
 
231
                        colonp[n - i] = 0;
 
232
                }
 
233
                tp = endp;
 
234
        }
 
235
        if (tp != endp)
 
236
                return (0);
 
237
        memcpy(dst, tmp, IN6ADDRSZ);
 
238
        return (1);
 
239
}
 
240
#endif