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

« back to all changes in this revision

Viewing changes to srclib/apr/network_io/unix/sockaddr.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 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "apr_arch_networkio.h"
 
18
#include "apr_strings.h"
 
19
#include "apr.h"
 
20
#include "apr_lib.h"
 
21
#include "apr_strings.h"
 
22
#include "apr_private.h"
 
23
 
 
24
#if APR_HAVE_STDLIB_H
 
25
#include <stdlib.h>
 
26
#endif
 
27
 
 
28
#define APR_WANT_STRFUNC
 
29
#include "apr_want.h"
 
30
 
 
31
struct apr_ipsubnet_t {
 
32
    int family;
 
33
#if APR_HAVE_IPV6
 
34
    apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */
 
35
    apr_uint32_t mask[4];
 
36
#else
 
37
    apr_uint32_t sub[1];
 
38
    apr_uint32_t mask[1];
 
39
#endif
 
40
};
 
41
 
 
42
#if !defined(NETWARE) && !defined(WIN32)
 
43
#ifdef HAVE_SET_H_ERRNO
 
44
#define SET_H_ERRNO(newval) set_h_errno(newval)
 
45
#else
 
46
#define SET_H_ERRNO(newval) h_errno = (newval)
 
47
#endif
 
48
#else
 
49
#define SET_H_ERRNO(newval)
 
50
#endif
 
51
 
 
52
#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
 
53
    defined(HAVE_GETHOSTBYNAME_R)
 
54
/* This is the maximum size that may be returned from the reentrant
 
55
 * gethostbyname_r function.  If the system tries to use more, it
 
56
 * should return ERANGE.
 
57
 */
 
58
#define GETHOSTBYNAME_BUFLEN 512
 
59
#endif
 
60
 
 
61
#ifdef _WIN32_WCE
 
62
/* XXX: BS solution.  Need an HAVE_GETSERVBYNAME and actually
 
63
 * do something here, to provide the obvious proto mappings.
 
64
 */
 
65
static void *getservbyname(const char *name, const char *proto)
 
66
{
 
67
    return NULL;
 
68
}
 
69
#endif
 
70
 
 
71
static apr_status_t get_local_addr(apr_socket_t *sock)
 
72
{
 
73
    sock->local_addr->salen = sizeof(sock->local_addr->sa);
 
74
    if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa,
 
75
                    &sock->local_addr->salen) < 0) {
 
76
        return apr_get_netos_error();
 
77
    }
 
78
    else {
 
79
        sock->local_port_unknown = sock->local_interface_unknown = 0;
 
80
        /* XXX assumes sin_port and sin6_port at same offset */
 
81
        sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port);
 
82
        return APR_SUCCESS;
 
83
    }
 
84
}
 
85
 
 
86
static apr_status_t get_remote_addr(apr_socket_t *sock)
 
87
{
 
88
    sock->remote_addr->salen = sizeof(sock->remote_addr->sa);
 
89
    if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa,
 
90
                    &sock->remote_addr->salen) < 0) {
 
91
        return apr_get_netos_error();
 
92
    }
 
93
    else {
 
94
        sock->remote_addr_unknown = 0;
 
95
        /* XXX assumes sin_port and sin6_port at same offset */
 
96
        sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port);
 
97
        return APR_SUCCESS;
 
98
    }
 
99
}
 
100
 
 
101
APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr,
 
102
                                         apr_sockaddr_t *sockaddr)
 
103
{
 
104
    *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len);
 
105
    apr_inet_ntop(sockaddr->family,
 
106
                  sockaddr->ipaddr_ptr,
 
107
                  *addr,
 
108
                  sockaddr->addr_str_len);
 
109
#if APR_HAVE_IPV6
 
110
    if (sockaddr->family == AF_INET6 &&
 
111
        IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)) {
 
112
        /* This is an IPv4-mapped IPv6 address; drop the leading
 
113
         * part of the address string so we're left with the familiar
 
114
         * IPv4 format.
 
115
         */
 
116
        *addr += strlen("::ffff:");
 
117
    }
 
118
#endif
 
119
    return APR_SUCCESS;
 
120
}
 
121
 
 
122
void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port)
 
123
{
 
124
    addr->family = family;
 
125
    addr->sa.sin.sin_family = family;
 
126
    if (port) {
 
127
        /* XXX IPv6: assumes sin_port and sin6_port at same offset */
 
128
        addr->sa.sin.sin_port = htons(port);
 
129
        addr->port = port;
 
130
    }
 
131
 
 
132
    if (family == APR_INET) {
 
133
        addr->salen = sizeof(struct sockaddr_in);
 
134
        addr->addr_str_len = 16;
 
135
        addr->ipaddr_ptr = &(addr->sa.sin.sin_addr);
 
136
        addr->ipaddr_len = sizeof(struct in_addr);
 
137
    }
 
138
#if APR_HAVE_IPV6
 
139
    else if (family == APR_INET6) {
 
140
        addr->salen = sizeof(struct sockaddr_in6);
 
141
        addr->addr_str_len = 46;
 
142
        addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr);
 
143
        addr->ipaddr_len = sizeof(struct in6_addr);
 
144
    }
 
145
#endif
 
146
}
 
147
 
 
148
APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa,
 
149
                                           apr_interface_e which,
 
150
                                           apr_socket_t *sock)
 
151
{
 
152
    if (which == APR_LOCAL) {
 
153
        if (sock->local_interface_unknown || sock->local_port_unknown) {
 
154
            apr_status_t rv = get_local_addr(sock);
 
155
 
 
156
            if (rv != APR_SUCCESS) {
 
157
                return rv;
 
158
            }
 
159
        }
 
160
        *sa = sock->local_addr;
 
161
    }
 
162
    else if (which == APR_REMOTE) {
 
163
        if (sock->remote_addr_unknown) {
 
164
            apr_status_t rv = get_remote_addr(sock);
 
165
 
 
166
            if (rv != APR_SUCCESS) {
 
167
                return rv;
 
168
            }
 
169
        }
 
170
        *sa = sock->remote_addr;
 
171
    }
 
172
    else {
 
173
        *sa = NULL;
 
174
        return APR_EINVAL;
 
175
    }
 
176
    return APR_SUCCESS;
 
177
}
 
178
 
 
179
APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr,
 
180
                                              char **scope_id,
 
181
                                              apr_port_t *port,
 
182
                                              const char *str,
 
183
                                              apr_pool_t *p)
 
184
{
 
185
    const char *ch, *lastchar;
 
186
    int big_port;
 
187
    apr_size_t addrlen;
 
188
 
 
189
    *addr = NULL;         /* assume not specified */
 
190
    *scope_id = NULL;     /* assume not specified */
 
191
    *port = 0;            /* assume not specified */
 
192
 
 
193
    /* First handle the optional port number.  That may be all that
 
194
     * is specified in the string.
 
195
     */
 
196
    ch = lastchar = str + strlen(str) - 1;
 
197
    while (ch >= str && apr_isdigit(*ch)) {
 
198
        --ch;
 
199
    }
 
200
 
 
201
    if (ch < str) {       /* Entire string is the port. */
 
202
        big_port = atoi(str);
 
203
        if (big_port < 1 || big_port > 65535) {
 
204
            return APR_EINVAL;
 
205
        }
 
206
        *port = big_port;
 
207
        return APR_SUCCESS;
 
208
    }
 
209
 
 
210
    if (*ch == ':' && ch < lastchar) { /* host and port number specified */
 
211
        if (ch == str) {               /* string starts with ':' -- bad */
 
212
            return APR_EINVAL;
 
213
        }
 
214
        big_port = atoi(ch + 1);
 
215
        if (big_port < 1 || big_port > 65535) {
 
216
            return APR_EINVAL;
 
217
        }
 
218
        *port = big_port;
 
219
        lastchar = ch - 1;
 
220
    }
 
221
 
 
222
    /* now handle the hostname */
 
223
    addrlen = lastchar - str + 1;
 
224
 
 
225
/* XXX we don't really have to require APR_HAVE_IPV6 for this; 
 
226
 * just pass char[] for ipaddr (so we don't depend on struct in6_addr)
 
227
 * and always define APR_INET6 
 
228
 */
 
229
#if APR_HAVE_IPV6
 
230
    if (*str == '[') {
 
231
        const char *end_bracket = memchr(str, ']', addrlen);
 
232
        struct in6_addr ipaddr;
 
233
        const char *scope_delim;
 
234
 
 
235
        if (!end_bracket || end_bracket != lastchar) {
 
236
            *port = 0;
 
237
            return APR_EINVAL;
 
238
        }
 
239
 
 
240
        /* handle scope id; this is the only context where it is allowed */
 
241
        scope_delim = memchr(str, '%', addrlen);
 
242
        if (scope_delim) {
 
243
            if (scope_delim == end_bracket - 1) { /* '%' without scope id */
 
244
                *port = 0;
 
245
                return APR_EINVAL;
 
246
            }
 
247
            addrlen = scope_delim - str - 1;
 
248
            *scope_id = apr_palloc(p, end_bracket - scope_delim);
 
249
            memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1);
 
250
            (*scope_id)[end_bracket - scope_delim - 1] = '\0';
 
251
        }
 
252
        else {
 
253
            addrlen = addrlen - 2; /* minus 2 for '[' and ']' */
 
254
        }
 
255
 
 
256
        *addr = apr_palloc(p, addrlen + 1);
 
257
        memcpy(*addr,
 
258
               str + 1,
 
259
               addrlen);
 
260
        (*addr)[addrlen] = '\0';
 
261
        if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) {
 
262
            *addr = NULL;
 
263
            *scope_id = NULL;
 
264
            *port = 0;
 
265
            return APR_EINVAL;
 
266
        }
 
267
    }
 
268
    else 
 
269
#endif
 
270
    {
 
271
        /* XXX If '%' is not a valid char in a DNS name, we *could* check 
 
272
         *     for bogus scope ids first.
 
273
         */
 
274
        *addr = apr_palloc(p, addrlen + 1);
 
275
        memcpy(*addr, str, addrlen);
 
276
        (*addr)[addrlen] = '\0';
 
277
    }
 
278
    return APR_SUCCESS;
 
279
}
 
280
 
 
281
#if defined(HAVE_GETADDRINFO)
 
282
 
 
283
static apr_status_t call_resolver(apr_sockaddr_t **sa,
 
284
                                  const char *hostname, apr_int32_t family,
 
285
                                  apr_port_t port, apr_int32_t flags, 
 
286
                                  apr_pool_t *p)
 
287
{
 
288
    struct addrinfo hints, *ai, *ai_list;
 
289
    apr_sockaddr_t *prev_sa;
 
290
    int error;
 
291
    char *servname = NULL; 
 
292
 
 
293
    memset(&hints, 0, sizeof(hints));
 
294
    hints.ai_family = family;
 
295
    hints.ai_socktype = SOCK_STREAM;
 
296
#ifdef HAVE_GAI_ADDRCONFIG
 
297
    if (family == APR_UNSPEC) {
 
298
        /* By default, only look up addresses using address types for
 
299
         * which a local interface is configured, i.e. no IPv6 if no
 
300
         * IPv6 interfaces configured. */
 
301
        hints.ai_flags = AI_ADDRCONFIG;
 
302
    }
 
303
#endif
 
304
    if(hostname == NULL) {
 
305
#ifdef AI_PASSIVE 
 
306
        /* If hostname is NULL, assume we are trying to bind to all
 
307
         * interfaces. */
 
308
        hints.ai_flags |= AI_PASSIVE;
 
309
#endif
 
310
        /* getaddrinfo according to RFC 2553 must have either hostname
 
311
         * or servname non-NULL.
 
312
         */
 
313
#ifdef OSF1
 
314
        /* The Tru64 5.0 getaddrinfo() can only resolve services given
 
315
         * by the name listed in /etc/services; a numeric or unknown
 
316
         * servname gets an EAI_SERVICE error.  So just resolve the
 
317
         * appropriate anyaddr and fill in the port later. */
 
318
        hostname = family == AF_INET6 ? "::" : "0.0.0.0";
 
319
        servname = NULL;
 
320
#ifdef AI_NUMERICHOST
 
321
        hints.ai_flags |= AI_NUMERICHOST;
 
322
#endif
 
323
#else
 
324
#ifdef _AIX
 
325
        /* But current AIX getaddrinfo() doesn't like servname = "0";
 
326
         * the "1" won't hurt since we use the port parameter to fill
 
327
         * in the returned socket addresses later
 
328
         */
 
329
        if (!port) {
 
330
            servname = "1";
 
331
        }
 
332
        else
 
333
#endif /* _AIX */
 
334
        servname = apr_itoa(p, port);
 
335
#endif /* OSF1 */
 
336
    }
 
337
    error = getaddrinfo(hostname, servname, &hints, &ai_list);
 
338
#ifdef HAVE_GAI_ADDRCONFIG
 
339
    if (error == EAI_BADFLAGS && family == APR_UNSPEC) {
 
340
        /* Retry with no flags if AI_ADDRCONFIG was rejected. */
 
341
        hints.ai_flags = 0;
 
342
        error = getaddrinfo(hostname, servname, &hints, &ai_list);
 
343
    }
 
344
#endif
 
345
    if (error) {
 
346
#ifndef WIN32
 
347
        if (error == EAI_SYSTEM) {
 
348
            return errno;
 
349
        }
 
350
        else 
 
351
#endif
 
352
        {
 
353
            /* issues with representing this with APR's error scheme:
 
354
             * glibc uses negative values for these numbers, perhaps so 
 
355
             * they don't conflict with h_errno values...  Tru64 uses 
 
356
             * positive values which conflict with h_errno values
 
357
             */
 
358
#if defined(NEGATIVE_EAI)
 
359
            error = -error;
 
360
#endif
 
361
            return error + APR_OS_START_EAIERR;
 
362
        }
 
363
    }
 
364
 
 
365
    prev_sa = NULL;
 
366
    ai = ai_list;
 
367
    while (ai) { /* while more addresses to report */
 
368
        apr_sockaddr_t *new_sa;
 
369
 
 
370
        /* Ignore anything bogus: getaddrinfo in some old versions of
 
371
         * glibc will return AF_UNIX entries for APR_UNSPEC+AI_PASSIVE
 
372
         * lookups. */
 
373
        if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
 
374
            ai = ai->ai_next;
 
375
            continue;
 
376
        }
 
377
 
 
378
        new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
 
379
 
 
380
        new_sa->pool = p;
 
381
        memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen);
 
382
        apr_sockaddr_vars_set(new_sa, ai->ai_family, port);
 
383
 
 
384
        if (!prev_sa) { /* first element in new list */
 
385
            if (hostname) {
 
386
                new_sa->hostname = apr_pstrdup(p, hostname);
 
387
            }
 
388
            *sa = new_sa;
 
389
        }
 
390
        else {
 
391
            new_sa->hostname = prev_sa->hostname;
 
392
            prev_sa->next = new_sa;
 
393
        }
 
394
 
 
395
        prev_sa = new_sa;
 
396
        ai = ai->ai_next;
 
397
    }
 
398
    freeaddrinfo(ai_list);
 
399
    return APR_SUCCESS;
 
400
}
 
401
 
 
402
static apr_status_t find_addresses(apr_sockaddr_t **sa, 
 
403
                                   const char *hostname, apr_int32_t family,
 
404
                                   apr_port_t port, apr_int32_t flags, 
 
405
                                   apr_pool_t *p)
 
406
{
 
407
    if (flags & APR_IPV4_ADDR_OK) {
 
408
        apr_status_t error = call_resolver(sa, hostname, AF_INET, port, flags, p);
 
409
 
 
410
#if APR_HAVE_IPV6
 
411
        if (error) {
 
412
            family = AF_INET6; /* try again */
 
413
        }
 
414
        else
 
415
#endif
 
416
        return error;
 
417
    }
 
418
#if APR_HAVE_IPV6
 
419
    else if (flags & APR_IPV6_ADDR_OK) {
 
420
        apr_status_t error = call_resolver(sa, hostname, AF_INET6, port, flags, p);
 
421
 
 
422
        if (error) {
 
423
            family = AF_INET; /* try again */
 
424
        }
 
425
        else {
 
426
            return APR_SUCCESS;
 
427
        }
 
428
    }
 
429
#endif
 
430
 
 
431
    return call_resolver(sa, hostname, family, port, flags, p);
 
432
}
 
433
 
 
434
#else /* end of HAVE_GETADDRINFO code */
 
435
 
 
436
static apr_status_t find_addresses(apr_sockaddr_t **sa, 
 
437
                                   const char *hostname, apr_int32_t family,
 
438
                                   apr_port_t port, apr_int32_t flags, 
 
439
                                   apr_pool_t *p)
 
440
{
 
441
    struct hostent *hp;
 
442
    apr_sockaddr_t *prev_sa;
 
443
    int curaddr;
 
444
#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
 
445
    defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
 
446
#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
 
447
    struct hostent_data hd;
 
448
#else
 
449
    /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be
 
450
     * bumped. */
 
451
    char tmp[GETHOSTBYNAME_BUFLEN];
 
452
#endif
 
453
    int hosterror;
 
454
#endif
 
455
    struct hostent hs;
 
456
    struct in_addr ipaddr;
 
457
    char *addr_list[2];
 
458
    const char *orig_hostname = hostname;
 
459
 
 
460
    if (hostname == NULL) {
 
461
        /* if we are given a NULL hostname, assume '0.0.0.0' */
 
462
        hostname = "0.0.0.0";
 
463
    }
 
464
 
 
465
    if (*hostname >= '0' && *hostname <= '9' &&
 
466
        strspn(hostname, "0123456789.") == strlen(hostname)) {
 
467
 
 
468
        ipaddr.s_addr = inet_addr(hostname);
 
469
        addr_list[0] = (char *)&ipaddr;
 
470
        addr_list[1] = NULL; /* just one IP in list */
 
471
        hs.h_addr_list = (char **)addr_list;
 
472
        hp = &hs;
 
473
    }
 
474
    else {
 
475
#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \
 
476
    defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS)
 
477
#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
 
478
        /* AIX, HP/UX, D/UX et alia */
 
479
        gethostbyname_r(hostname, &hs, &hd);
 
480
        hp = &hs;
 
481
#else
 
482
#if defined(GETHOSTBYNAME_R_GLIBC2)
 
483
        /* Linux glibc2+ */
 
484
        gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, 
 
485
                        &hp, &hosterror);
 
486
#else
 
487
        /* Solaris, Irix et alia */
 
488
        hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1,
 
489
                             &hosterror);
 
490
#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
 
491
        if (!hp) {
 
492
            return (hosterror + APR_OS_START_SYSERR);
 
493
        }
 
494
#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
 
495
#else
 
496
        hp = gethostbyname(hostname);
 
497
#endif
 
498
 
 
499
        if (!hp) {
 
500
#ifdef WIN32
 
501
            return apr_get_netos_error();
 
502
#else
 
503
            return (h_errno + APR_OS_START_SYSERR);
 
504
#endif
 
505
        }
 
506
    }
 
507
 
 
508
    prev_sa = NULL;
 
509
    curaddr = 0;
 
510
    while (hp->h_addr_list[curaddr]) {
 
511
        apr_sockaddr_t *new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t));
 
512
 
 
513
        new_sa->pool = p;
 
514
        new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr];
 
515
        apr_sockaddr_vars_set(new_sa, AF_INET, port);
 
516
 
 
517
        if (!prev_sa) { /* first element in new list */
 
518
            if (orig_hostname) {
 
519
                new_sa->hostname = apr_pstrdup(p, orig_hostname);
 
520
            }
 
521
            *sa = new_sa;
 
522
        }
 
523
        else {
 
524
            new_sa->hostname = prev_sa->hostname;
 
525
            prev_sa->next = new_sa;
 
526
        }
 
527
 
 
528
        prev_sa = new_sa;
 
529
        ++curaddr;
 
530
    }
 
531
 
 
532
    return APR_SUCCESS;
 
533
}
 
534
 
 
535
#endif /* end of !HAVE_GETADDRINFO code */
 
536
 
 
537
APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
 
538
                                                const char *hostname, 
 
539
                                                apr_int32_t family, apr_port_t port,
 
540
                                                apr_int32_t flags, apr_pool_t *p)
 
541
{
 
542
    apr_int32_t masked;
 
543
    *sa = NULL;
 
544
 
 
545
    if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) {
 
546
        if (!hostname ||
 
547
            family != APR_UNSPEC ||
 
548
            masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) {
 
549
            return APR_EINVAL;
 
550
        }
 
551
#if !APR_HAVE_IPV6
 
552
        if (flags & APR_IPV6_ADDR_OK) {
 
553
            return APR_ENOTIMPL;
 
554
        }
 
555
#endif
 
556
    }
 
557
#if !APR_HAVE_IPV6
 
558
    /* What may happen is that APR is not IPv6-enabled, but we're still
 
559
     * going to call getaddrinfo(), so we have to tell the OS we only
 
560
     * want IPv4 addresses back since we won't know what to do with
 
561
     * IPv6 addresses.
 
562
     */
 
563
    if (family == APR_UNSPEC) {
 
564
        family = APR_INET;
 
565
    }
 
566
#endif
 
567
 
 
568
    return find_addresses(sa, hostname, family, port, flags, p);
 
569
}
 
570
 
 
571
APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
 
572
                                          apr_sockaddr_t *sockaddr,
 
573
                                          apr_int32_t flags)
 
574
{
 
575
#if defined(HAVE_GETNAMEINFO)
 
576
    int rc;
 
577
#if defined(NI_MAXHOST)
 
578
    char tmphostname[NI_MAXHOST];
 
579
#else
 
580
    char tmphostname[256];
 
581
#endif
 
582
 
 
583
    /* don't know if it is portable for getnameinfo() to set h_errno;
 
584
     * clear it then see if it was set */
 
585
    SET_H_ERRNO(0);
 
586
 
 
587
    /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return
 
588
     * a numeric address string if it fails to resolve the host name;
 
589
     * that is *not* what we want here
 
590
     *
 
591
     * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
 
592
     * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
 
593
     */
 
594
#if APR_HAVE_IPV6
 
595
    if (sockaddr->family == AF_INET6 &&
 
596
        IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
 
597
        struct sockaddr_in tmpsa;
 
598
        tmpsa.sin_family = AF_INET;
 
599
        tmpsa.sin_port = 0;
 
600
        tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3];
 
601
#ifdef SIN6_LEN
 
602
        tmpsa.sin_len = sizeof(tmpsa);
 
603
#endif
 
604
 
 
605
        rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
 
606
                         tmphostname, sizeof(tmphostname), NULL, 0,
 
607
                         flags != 0 ? flags : NI_NAMEREQD);
 
608
    }
 
609
    else
 
610
#endif
 
611
    rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
 
612
                     tmphostname, sizeof(tmphostname), NULL, 0,
 
613
                     flags != 0 ? flags : NI_NAMEREQD);
 
614
    if (rc != 0) {
 
615
        *hostname = NULL;
 
616
 
 
617
#ifndef WIN32
 
618
        /* something went wrong. Look at the EAI_ error code */
 
619
        if (rc == EAI_SYSTEM) {
 
620
            /* EAI_SYSTEM      System error returned in errno. */
 
621
            /* IMHO, Implementations that set h_errno a simply broken. */
 
622
            if (h_errno) { /* for broken implementations which set h_errno */
 
623
                return h_errno + APR_OS_START_SYSERR;
 
624
            }
 
625
            else { /* "normal" case */
 
626
                return errno + APR_OS_START_SYSERR;
 
627
            }
 
628
        }
 
629
        else 
 
630
#endif
 
631
        {
 
632
#if defined(NEGATIVE_EAI)
 
633
            if (rc < 0) rc = -rc;
 
634
#endif
 
635
            return rc + APR_OS_START_EAIERR; /* return the EAI_ error */
 
636
        }
 
637
    }
 
638
    *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, 
 
639
                                                 tmphostname);
 
640
    return APR_SUCCESS;
 
641
#else
 
642
#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \
 
643
    defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)
 
644
#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
 
645
    struct hostent_data hd;
 
646
#else
 
647
    char tmp[GETHOSTBYNAME_BUFLEN];
 
648
#endif
 
649
    int hosterror;
 
650
    struct hostent hs, *hptr;
 
651
 
 
652
#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
 
653
    /* AIX, HP/UX, D/UX et alia */
 
654
    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
 
655
                  sizeof(struct in_addr), AF_INET, &hs, &hd);
 
656
    hptr = &hs;
 
657
#else
 
658
#if defined(GETHOSTBYNAME_R_GLIBC2)
 
659
    /* Linux glibc2+ */
 
660
    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
 
661
                    sizeof(struct in_addr), AF_INET,
 
662
                    &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
 
663
#else
 
664
    /* Solaris, Irix et alia */
 
665
    hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
 
666
                           sizeof(struct in_addr), AF_INET,
 
667
                           &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
 
668
#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
 
669
    if (!hptr) {
 
670
        *hostname = NULL;
 
671
        return hosterror + APR_OS_START_SYSERR;
 
672
    }
 
673
#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
 
674
#else
 
675
    struct hostent *hptr;
 
676
    hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, 
 
677
                         sizeof(struct in_addr), AF_INET);
 
678
#endif
 
679
 
 
680
    if (hptr) {
 
681
        *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name);
 
682
        return APR_SUCCESS;
 
683
    }
 
684
    *hostname = NULL;
 
685
#if defined(WIN32)
 
686
    return apr_get_netos_error();
 
687
#elif defined(OS2)
 
688
    return h_errno;
 
689
#else
 
690
    return h_errno + APR_OS_START_SYSERR;
 
691
#endif
 
692
#endif
 
693
}
 
694
 
 
695
APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr,
 
696
                                            const char *servname)
 
697
{
 
698
    struct servent *se;
 
699
 
 
700
    if (servname == NULL)
 
701
        return APR_EINVAL;
 
702
 
 
703
    if ((se = getservbyname(servname, NULL)) != NULL){
 
704
        sockaddr->port = htons(se->s_port);
 
705
        sockaddr->servname = apr_pstrdup(sockaddr->pool, servname);
 
706
        sockaddr->sa.sin.sin_port = se->s_port;
 
707
        return APR_SUCCESS;
 
708
    }
 
709
    return errno;
 
710
}
 
711
 
 
712
#define V4MAPPED_EQUAL(a,b)                                   \
 
713
((a)->sa.sin.sin_family == AF_INET &&                         \
 
714
 (b)->sa.sin.sin_family == AF_INET6 &&                        \
 
715
 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) &&  \
 
716
 !memcmp((a)->ipaddr_ptr,                                     \
 
717
         &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12],  \
 
718
         (a)->ipaddr_len))
 
719
 
 
720
APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1,
 
721
                                    const apr_sockaddr_t *addr2)
 
722
{
 
723
    if (addr1->ipaddr_len == addr2->ipaddr_len &&
 
724
        !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) {
 
725
        return 1;
 
726
    }
 
727
#if APR_HAVE_IPV6
 
728
    if (V4MAPPED_EQUAL(addr1, addr2)) {
 
729
        return 1;
 
730
    }
 
731
    if (V4MAPPED_EQUAL(addr2, addr1)) {
 
732
        return 1;
 
733
    }
 
734
#endif
 
735
    return 0; /* not equal */
 
736
}
 
737
 
 
738
static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network)
 
739
{
 
740
    /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
 
741
    int shift;
 
742
    char *s, *t;
 
743
    int octet;
 
744
    char buf[sizeof "255.255.255.255"];
 
745
 
 
746
    if (strlen(network) < sizeof buf) {
 
747
        strcpy(buf, network);
 
748
    }
 
749
    else {
 
750
        return APR_EBADIP;
 
751
    }
 
752
 
 
753
    /* parse components */
 
754
    s = buf;
 
755
    ipsub->sub[0] = 0;
 
756
    ipsub->mask[0] = 0;
 
757
    shift = 24;
 
758
    while (*s) {
 
759
        t = s;
 
760
        if (!apr_isdigit(*t)) {
 
761
            return APR_EBADIP;
 
762
        }
 
763
        while (apr_isdigit(*t)) {
 
764
            ++t;
 
765
        }
 
766
        if (*t == '.') {
 
767
            *t++ = 0;
 
768
        }
 
769
        else if (*t) {
 
770
            return APR_EBADIP;
 
771
        }
 
772
        if (shift < 0) {
 
773
            return APR_EBADIP;
 
774
        }
 
775
        octet = atoi(s);
 
776
        if (octet < 0 || octet > 255) {
 
777
            return APR_EBADIP;
 
778
        }
 
779
        ipsub->sub[0] |= octet << shift;
 
780
        ipsub->mask[0] |= 0xFFUL << shift;
 
781
        s = t;
 
782
        shift -= 8;
 
783
    }
 
784
    ipsub->sub[0] = ntohl(ipsub->sub[0]);
 
785
    ipsub->mask[0] = ntohl(ipsub->mask[0]);
 
786
    ipsub->family = AF_INET;
 
787
    return APR_SUCCESS;
 
788
}
 
789
 
 
790
/* return values:
 
791
 * APR_EINVAL     not an IP address; caller should see if it is something else
 
792
 * APR_BADIP      IP address portion is is not valid
 
793
 * APR_BADMASK    mask portion is not valid
 
794
 */
 
795
 
 
796
static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed)
 
797
{
 
798
    /* supported flavors of IP:
 
799
     *
 
800
     * . IPv6 numeric address string (e.g., "fe80::1")
 
801
     * 
 
802
     *   IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address.
 
803
     *
 
804
     * . IPv4 numeric address string (e.g., "127.0.0.1")
 
805
     *
 
806
     * . IPv4 network string (e.g., "9.67")
 
807
     *
 
808
     *   IMPORTANT: This network form is only allowed if network_allowed is on.
 
809
     */
 
810
    int rc;
 
811
 
 
812
#if APR_HAVE_IPV6
 
813
    rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub);
 
814
    if (rc == 1) {
 
815
        if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) {
 
816
            /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6
 
817
             * addresses; this of course forces the user to specify IPv4 addresses
 
818
             * in a.b.c.d style instead of ::ffff:a.b.c.d style.
 
819
             */
 
820
            return APR_EBADIP;
 
821
        }
 
822
        ipsub->family = AF_INET6;
 
823
    }
 
824
    else
 
825
#endif
 
826
    {
 
827
        rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub);
 
828
        if (rc == 1) {
 
829
            ipsub->family = AF_INET;
 
830
        }
 
831
    }
 
832
    if (rc != 1) {
 
833
        if (network_allowed) {
 
834
            return parse_network(ipsub, ipstr);
 
835
        }
 
836
        else {
 
837
            return APR_EBADIP;
 
838
        }
 
839
    }
 
840
    return APR_SUCCESS;
 
841
}
 
842
 
 
843
static int looks_like_ip(const char *ipstr)
 
844
{
 
845
    if (strchr(ipstr, ':')) {
 
846
        /* definitely not a hostname; assume it is intended to be an IPv6 address */
 
847
        return 1;
 
848
    }
 
849
 
 
850
    /* simple IPv4 address string check */
 
851
    while ((*ipstr == '.') || apr_isdigit(*ipstr))
 
852
        ipstr++;
 
853
    return (*ipstr == '\0');
 
854
}
 
855
 
 
856
static void fix_subnet(apr_ipsubnet_t *ipsub)
 
857
{
 
858
    /* in case caller specified more bits in network address than are
 
859
     * valid according to the mask, turn off the extra bits
 
860
     */
 
861
    int i;
 
862
 
 
863
    for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) {
 
864
        ipsub->sub[i] &= ipsub->mask[i];
 
865
    }
 
866
}
 
867
 
 
868
/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */
 
869
APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr, 
 
870
                                              const char *mask_or_numbits, apr_pool_t *p)
 
871
{
 
872
    apr_status_t rv;
 
873
    char *endptr;
 
874
    long bits, maxbits = 32;
 
875
 
 
876
    /* filter out stuff which doesn't look remotely like an IP address; this helps 
 
877
     * callers like mod_access which have a syntax allowing hostname or IP address;
 
878
     * APR_EINVAL tells the caller that it was probably not intended to be an IP
 
879
     * address
 
880
     */
 
881
    if (!looks_like_ip(ipstr)) {
 
882
        return APR_EINVAL;
 
883
    }
 
884
 
 
885
    *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t));
 
886
 
 
887
    /* assume ipstr is an individual IP address, not a subnet */
 
888
    memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask);
 
889
 
 
890
    rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL);
 
891
    if (rv != APR_SUCCESS) {
 
892
        return rv;
 
893
    }
 
894
 
 
895
    if (mask_or_numbits) {
 
896
#if APR_HAVE_IPV6
 
897
        if ((*ipsub)->family == AF_INET6) {
 
898
            maxbits = 128;
 
899
        }
 
900
#endif
 
901
        bits = strtol(mask_or_numbits, &endptr, 10);
 
902
        if (*endptr == '\0' && bits > 0 && bits <= maxbits) {
 
903
            /* valid num-bits string; fill in mask appropriately */
 
904
            int cur_entry = 0;
 
905
            apr_int32_t cur_bit_value;
 
906
 
 
907
            memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask);
 
908
            while (bits > 32) {
 
909
                (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */
 
910
                bits -= 32;
 
911
                ++cur_entry;
 
912
            }
 
913
            cur_bit_value = 0x80000000;
 
914
            while (bits) {
 
915
                (*ipsub)->mask[cur_entry] |= cur_bit_value;
 
916
                --bits;
 
917
                cur_bit_value /= 2;
 
918
            }
 
919
            (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]);
 
920
        }
 
921
        else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 &&
 
922
            (*ipsub)->family == AF_INET) {
 
923
            /* valid IPv4 netmask */
 
924
        }
 
925
        else {
 
926
            return APR_EBADMASK;
 
927
        }
 
928
    }
 
929
 
 
930
    fix_subnet(*ipsub);
 
931
 
 
932
    return APR_SUCCESS;
 
933
}
 
934
 
 
935
APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa)
 
936
{
 
937
#if APR_HAVE_IPV6
 
938
    /* XXX This line will segv on Win32 build with APR_HAVE_IPV6,
 
939
     * but without the IPV6 drivers installed.
 
940
     */
 
941
    if (sa->sa.sin.sin_family == AF_INET) {
 
942
        if (ipsub->family == AF_INET &&
 
943
            ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) {
 
944
            return 1;
 
945
        }
 
946
    }
 
947
    else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) {
 
948
        if (ipsub->family == AF_INET &&
 
949
            (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) {
 
950
            return 1;
 
951
        }
 
952
    }
 
953
    else {
 
954
        apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr;
 
955
 
 
956
        if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] &&
 
957
            (addr[1] & ipsub->mask[1]) == ipsub->sub[1] &&
 
958
            (addr[2] & ipsub->mask[2]) == ipsub->sub[2] &&
 
959
            (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) {
 
960
            return 1;
 
961
        }
 
962
    }
 
963
#else
 
964
    if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) {
 
965
        return 1;
 
966
    }
 
967
#endif /* APR_HAVE_IPV6 */
 
968
    return 0; /* no match */
 
969
}