~ubuntu-branches/ubuntu/intrepid/apache2/intrepid

« back to all changes in this revision

Viewing changes to modules/proxy/proxy_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Fritsch
  • Date: 2007-10-18 19:35:40 UTC
  • mfrom: (0.13.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071018193540-u9bl0154m45xppyj
Tags: 2.2.6-2
* Avoid calling apr_pollset_poll() and accept_func() when the listening
  sockets have already been closed on graceful stop or reload. This
  hopefully fixes processes not being killed (closes: #445263, #447164)
  and the "Bad file descriptor: apr_socket_accept: (client socket)"
  error message (closes: #400918, #443310)
* Allow logresolve to process long lines (Closes: #331631)
* Remove duplicate config examples (Closes: #294662)
* Include README.backtrace describing how to create a backtrace
* Add CVE reference to 2.2.6-1 changelog entry

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 
50
50
#if !APR_CHARSET_EBCDIC
51
51
    ch = x[0];
52
 
    if (apr_isdigit(ch))
53
 
    i = ch - '0';
54
 
    else if (apr_isupper(ch))
55
 
    i = ch - ('A' - 10);
56
 
    else
57
 
    i = ch - ('a' - 10);
 
52
    if (apr_isdigit(ch)) {
 
53
        i = ch - '0';
 
54
    }
 
55
    else if (apr_isupper(ch)) {
 
56
        i = ch - ('A' - 10);
 
57
    }
 
58
    else {
 
59
        i = ch - ('a' - 10);
 
60
    }
58
61
    i <<= 4;
59
62
 
60
63
    ch = x[1];
61
 
    if (apr_isdigit(ch))
62
 
    i += ch - '0';
63
 
    else if (apr_isupper(ch))
64
 
    i += ch - ('A' - 10);
65
 
    else
66
 
    i += ch - ('a' - 10);
 
64
    if (apr_isdigit(ch)) {
 
65
        i += ch - '0';
 
66
    }
 
67
    else if (apr_isupper(ch)) {
 
68
        i += ch - ('A' - 10);
 
69
    }
 
70
    else {
 
71
        i += ch - ('a' - 10);
 
72
    }
67
73
    return i;
68
74
#else /*APR_CHARSET_EBCDIC*/
69
75
    /*
98
104
 
99
105
    x[0] = '%';
100
106
    i = (ch & 0xF0) >> 4;
101
 
    if (i >= 10)
102
 
    x[1] = ('A' - 10) + i;
103
 
    else
104
 
    x[1] = '0' + i;
 
107
    if (i >= 10) {
 
108
        x[1] = ('A' - 10) + i;
 
109
    }
 
110
    else {
 
111
        x[1] = '0' + i;
 
112
    }
105
113
 
106
114
    i = ch & 0x0F;
107
 
    if (i >= 10)
108
 
    x[2] = ('A' - 10) + i;
109
 
    else
110
 
    x[2] = '0' + i;
 
115
    if (i >= 10) {
 
116
        x[2] = ('A' - 10) + i;
 
117
    }
 
118
    else {
 
119
        x[2] = '0' + i;
 
120
    }
111
121
#else /*APR_CHARSET_EBCDIC*/
112
122
    static const char ntoa[] = { "0123456789ABCDEF" };
113
123
    char buf[1];
134
144
 * and encodes those which must be encoded, and does not touch
135
145
 * those which must not be touched.
136
146
 */
137
 
PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
138
 
    int forcedec, int proxyreq)
 
147
PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
 
148
                                       enum enctype t, int forcedec,
 
149
                                       int proxyreq)
139
150
{
140
151
    int i, j, ch;
141
152
    char *y;
150
161
 * it may be form-encoded. (Although RFC 1738 doesn't allow this -
151
162
 * it only permits ; / ? : @ = & as reserved chars.)
152
163
 */
153
 
    if (t == enc_path)
154
 
    allowed = "$-_.+!*'(),;:@&=";
155
 
    else if (t == enc_search)
156
 
    allowed = "$-_.!*'(),;:@&=";
157
 
    else if (t == enc_user)
158
 
    allowed = "$-_.+!*'(),;@&=";
159
 
    else if (t == enc_fpath)
160
 
    allowed = "$-_.+!*'(),?:@&=";
161
 
    else            /* if (t == enc_parm) */
162
 
    allowed = "$-_.+!*'(),?/:@&=";
 
164
    if (t == enc_path) {
 
165
        allowed = "~$-_.+!*'(),;:@&=";
 
166
    }
 
167
    else if (t == enc_search) {
 
168
        allowed = "$-_.!*'(),;:@&=";
 
169
    }
 
170
    else if (t == enc_user) {
 
171
        allowed = "$-_.+!*'(),;@&=";
 
172
    }
 
173
    else if (t == enc_fpath) {
 
174
        allowed = "$-_.+!*'(),?:@&=";
 
175
    }
 
176
    else {            /* if (t == enc_parm) */
 
177
        allowed = "$-_.+!*'(),?/:@&=";
 
178
    }
163
179
 
164
 
    if (t == enc_path)
165
 
    reserved = "/";
166
 
    else if (t == enc_search)
167
 
    reserved = "+";
168
 
    else
169
 
    reserved = "";
 
180
    if (t == enc_path) {
 
181
        reserved = "/";
 
182
    }
 
183
    else if (t == enc_search) {
 
184
        reserved = "+";
 
185
    }
 
186
    else {
 
187
        reserved = "";
 
188
    }
170
189
 
171
190
    y = apr_palloc(p, 3 * len + 1);
172
191
 
173
192
    for (i = 0, j = 0; i < len; i++, j++) {
174
193
/* always handle '/' first */
175
 
    ch = x[i];
176
 
    if (strchr(reserved, ch)) {
177
 
        y[j] = ch;
178
 
        continue;
179
 
    }
 
194
        ch = x[i];
 
195
        if (strchr(reserved, ch)) {
 
196
            y[j] = ch;
 
197
            continue;
 
198
        }
180
199
/*
181
200
 * decode it if not already done. do not decode reverse proxied URLs
182
201
 * unless specifically forced
183
202
 */
184
 
    if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
185
 
        if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2]))
186
 
        return NULL;
187
 
        ch = ap_proxy_hex2c(&x[i + 1]);
188
 
        i += 2;
189
 
        if (ch != 0 && strchr(reserved, ch)) {  /* keep it encoded */
190
 
        ap_proxy_c2hex(ch, &y[j]);
191
 
        j += 2;
192
 
        continue;
 
203
        if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
 
204
            if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) {
 
205
                return NULL;
 
206
            }
 
207
            ch = ap_proxy_hex2c(&x[i + 1]);
 
208
            i += 2;
 
209
            if (ch != 0 && strchr(reserved, ch)) {  /* keep it encoded */
 
210
                ap_proxy_c2hex(ch, &y[j]);
 
211
                j += 2;
 
212
                continue;
 
213
            }
193
214
        }
194
 
    }
195
215
/* recode it, if necessary */
196
 
    if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
197
 
        ap_proxy_c2hex(ch, &y[j]);
198
 
        j += 2;
199
 
    }
200
 
    else
201
 
        y[j] = ch;
 
216
        if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
 
217
            ap_proxy_c2hex(ch, &y[j]);
 
218
            j += 2;
 
219
        }
 
220
        else {
 
221
            y[j] = ch;
 
222
        }
202
223
    }
203
224
    y[j] = '\0';
204
225
    return y;
223
244
    apr_port_t tmp_port;
224
245
    apr_status_t rv;
225
246
 
226
 
    if (url[0] != '/' || url[1] != '/')
227
 
    return "Malformed URL";
 
247
    if (url[0] != '/' || url[1] != '/') {
 
248
        return "Malformed URL";
 
249
    }
228
250
    host = url + 2;
229
251
    url = strchr(host, '/');
230
 
    if (url == NULL)
231
 
    url = "";
232
 
    else
233
 
    *(url++) = '\0';    /* skip seperating '/' */
 
252
    if (url == NULL) {
 
253
        url = "";
 
254
    }
 
255
    else {
 
256
        *(url++) = '\0';    /* skip seperating '/' */
 
257
    }
234
258
 
235
259
    /* find _last_ '@' since it might occur in user/password part */
236
260
    strp = strrchr(host, '@');
237
261
 
238
262
    if (strp != NULL) {
239
 
    *strp = '\0';
240
 
    user = host;
241
 
    host = strp + 1;
 
263
        *strp = '\0';
 
264
        user = host;
 
265
        host = strp + 1;
242
266
 
243
267
/* find password */
244
 
    strp = strchr(user, ':');
245
 
    if (strp != NULL) {
246
 
        *strp = '\0';
247
 
        password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1, 0);
248
 
        if (password == NULL)
249
 
        return "Bad %-escape in URL (password)";
250
 
    }
 
268
        strp = strchr(user, ':');
 
269
        if (strp != NULL) {
 
270
            *strp = '\0';
 
271
            password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1, 0);
 
272
            if (password == NULL) {
 
273
                return "Bad %-escape in URL (password)";
 
274
            }
 
275
        }
251
276
 
252
 
    user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1, 0);
253
 
    if (user == NULL)
254
 
        return "Bad %-escape in URL (username)";
 
277
        user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1, 0);
 
278
        if (user == NULL) {
 
279
            return "Bad %-escape in URL (username)";
 
280
        }
255
281
    }
256
282
    if (userp != NULL) {
257
 
    *userp = user;
 
283
        *userp = user;
258
284
    }
259
285
    if (passwordp != NULL) {
260
 
    *passwordp = password;
 
286
        *passwordp = password;
261
287
    }
262
288
 
263
289
    /*
280
306
    return NULL;
281
307
}
282
308
 
283
 
static const char * const lwday[7] =
284
 
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
285
 
 
286
309
/*
287
310
 * If the date is a valid RFC 850 date or asctime() date, then it
288
 
 * is converted to the RFC 1123 format, otherwise it is not modified.
289
 
 * This routine is not very fast at doing conversions, as it uses
290
 
 * sscanf and sprintf. However, if the date is already correctly
291
 
 * formatted, then it exits very quickly.
 
311
 * is converted to the RFC 1123 format.
292
312
 */
293
313
PROXY_DECLARE(const char *)
294
 
     ap_proxy_date_canon(apr_pool_t *p, const char *x1)
 
314
     ap_proxy_date_canon(apr_pool_t *p, const char *date)
295
315
{
296
 
    char *x = apr_pstrdup(p, x1);
297
 
    int wk, mday, year, hour, min, sec, mon;
298
 
    char *q, month[4], zone[4], week[4];
299
 
 
300
 
    q = strchr(x, ',');
301
 
    /* check for RFC 850 date */
302
 
    if (q != NULL && q - x > 3 && q[1] == ' ') {
303
 
    *q = '\0';
304
 
    for (wk = 0; wk < 7; wk++)
305
 
        if (strcmp(x, lwday[wk]) == 0)
306
 
        break;
307
 
    *q = ',';
308
 
    if (wk == 7)
309
 
        return x;       /* not a valid date */
310
 
    if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
311
 
        q[17] != ':' || strcmp(&q[20], " GMT") != 0)
312
 
        return x;
313
 
    if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
314
 
           &hour, &min, &sec, zone) != 7)
315
 
        return x;
316
 
    if (year < 70)
317
 
        year += 2000;
318
 
    else
319
 
        year += 1900;
320
 
    }
321
 
    else {
322
 
/* check for acstime() date */
323
 
    if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
324
 
        x[16] != ':' || x[19] != ' ' || x[24] != '\0')
325
 
        return x;
326
 
    if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
327
 
           &min, &sec, &year) != 7)
328
 
        return x;
329
 
    for (wk = 0; wk < 7; wk++)
330
 
        if (strcmp(week, apr_day_snames[wk]) == 0)
331
 
        break;
332
 
    if (wk == 7)
333
 
        return x;
334
 
    }
335
 
 
336
 
/* check date */
337
 
    for (mon = 0; mon < 12; mon++)
338
 
    if (strcmp(month, apr_month_snames[mon]) == 0)
339
 
        break;
340
 
    if (mon == 12)
341
 
    return x;
342
 
 
343
 
    q = apr_palloc(p, 30);
344
 
    apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", apr_day_snames[wk],
345
 
       mday, apr_month_snames[mon], year, hour, min, sec);
346
 
    return q;
 
316
    apr_status_t rv;
 
317
    char* ndate;
 
318
 
 
319
    apr_time_t time = apr_date_parse_http(date);
 
320
    if (!time) {
 
321
        return date;
 
322
    }
 
323
 
 
324
    ndate = apr_palloc(p, APR_RFC822_DATE_LEN);
 
325
    rv = apr_rfc822_date(ndate, time);
 
326
    if (rv != APR_SUCCESS) {
 
327
        return date;
 
328
    }
 
329
 
 
330
    return ndate;
347
331
}
348
332
 
349
333
PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
389
373
    len = strlen(val);
390
374
 
391
375
    while (list != NULL) {
392
 
    p = ap_strchr_c(list, ',');
393
 
    if (p != NULL) {
394
 
        i = p - list;
395
 
        do
396
 
        p++;
397
 
        while (apr_isspace(*p));
398
 
    }
399
 
    else
400
 
        i = strlen(list);
 
376
        p = ap_strchr_c(list, ',');
 
377
        if (p != NULL) {
 
378
            i = p - list;
 
379
            do {
 
380
                p++;
 
381
            } while (apr_isspace(*p));
 
382
        }
 
383
        else {
 
384
            i = strlen(list);
 
385
        }
401
386
 
402
 
    while (i > 0 && apr_isspace(list[i - 1]))
403
 
        i--;
404
 
    if (i == len && strncasecmp(list, val, len) == 0)
405
 
        return 1;
406
 
    list = p;
 
387
        while (i > 0 && apr_isspace(list[i - 1])) {
 
388
            i--;
 
389
        }
 
390
        if (i == len && strncasecmp(list, val, len) == 0) {
 
391
            return 1;
 
392
        }
 
393
        list = p;
407
394
    }
408
395
    return 0;
409
396
}
423
410
    len = strlen(val);
424
411
 
425
412
    while (list != NULL) {
426
 
    p = ap_strchr_c(list, ',');
427
 
    if (p != NULL) {
428
 
        i = p - list;
429
 
        do
430
 
        p++;
431
 
        while (apr_isspace(*p));
432
 
    }
433
 
    else
434
 
        i = strlen(list);
 
413
        p = ap_strchr_c(list, ',');
 
414
        if (p != NULL) {
 
415
            i = p - list;
 
416
            do {
 
417
                p++;
 
418
            } while (apr_isspace(*p));
 
419
        }
 
420
        else {
 
421
            i = strlen(list);
 
422
        }
435
423
 
436
 
    while (i > 0 && apr_isspace(list[i - 1]))
437
 
        i--;
438
 
    if (i == len && strncasecmp(list, val, len) == 0) {
439
 
        /* do nothing */
440
 
    }
441
 
    else {
442
 
        if (new)
443
 
        new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
444
 
        else
445
 
        new = apr_pstrndup(pool, list, i);
446
 
    }
447
 
    list = p;
 
424
        while (i > 0 && apr_isspace(list[i - 1])) {
 
425
            i--;
 
426
        }
 
427
        if (i == len && strncasecmp(list, val, len) == 0) {
 
428
            /* do nothing */
 
429
        }
 
430
        else {
 
431
            if (new) {
 
432
                new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
 
433
            }
 
434
            else {
 
435
                new = apr_pstrndup(pool, list, i);
 
436
            }
 
437
        }
 
438
        list = p;
448
439
    }
449
440
    return new;
450
441
}
458
449
    unsigned int j;
459
450
 
460
451
    for (i = 0, j = 0; i < 8; i++) {
461
 
    ch = x[i];
462
 
    j <<= 4;
463
 
    if (apr_isdigit(ch))
464
 
        j |= ch - '0';
465
 
    else if (apr_isupper(ch))
466
 
        j |= ch - ('A' - 10);
467
 
    else
468
 
        j |= ch - ('a' - 10);
469
 
    }
470
 
    if (j == 0xffffffff)
471
 
    return -1;      /* so that it works with 8-byte ints */
472
 
    else
473
 
    return j;
 
452
        ch = x[i];
 
453
        j <<= 4;
 
454
        if (apr_isdigit(ch)) {
 
455
            j |= ch - '0';
 
456
        }
 
457
        else if (apr_isupper(ch)) {
 
458
            j |= ch - ('A' - 10);
 
459
        }
 
460
        else {
 
461
            j |= ch - ('a' - 10);
 
462
        }
 
463
    }
 
464
    if (j == 0xffffffff) {
 
465
        return -1;      /* so that it works with 8-byte ints */
 
466
    }
 
467
    else {
 
468
        return j;
 
469
    }
474
470
}
475
471
 
476
472
/*
482
478
    unsigned int j = t;
483
479
 
484
480
    for (i = 7; i >= 0; i--) {
485
 
    ch = j & 0xF;
486
 
    j >>= 4;
487
 
    if (ch >= 10)
488
 
        y[i] = ch + ('A' - 10);
489
 
    else
490
 
        y[i] = ch + '0';
 
481
        ch = j & 0xF;
 
482
        j >>= 4;
 
483
        if (ch >= 10) {
 
484
            y[i] = ch + ('A' - 10);
 
485
        }
 
486
        else {
 
487
            y[i] = ch + '0';
 
488
        }
491
489
    }
492
490
    y[8] = '\0';
493
491
}
520
518
    char *url, *user = NULL, *password = NULL, *err, *host;
521
519
    apr_port_t port;
522
520
 
523
 
    if (r->hostname != NULL)
524
 
    return r->hostname;
 
521
    if (r->hostname != NULL) {
 
522
        return r->hostname;
 
523
    }
525
524
 
526
525
    /* Set url to the first char after "scheme://" */
527
 
    if ((url = strchr(r->uri, ':')) == NULL
528
 
    || url[1] != '/' || url[2] != '/')
529
 
    return NULL;
 
526
    if ((url = strchr(r->uri, ':')) == NULL || url[1] != '/' || url[2] != '/') {
 
527
        return NULL;
 
528
    }
530
529
 
531
530
    url = apr_pstrdup(r->pool, &url[1]);    /* make it point to "//", which is what proxy_canon_netloc expects */
532
531
 
533
532
    err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
534
533
 
535
 
    if (err != NULL)
536
 
    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
537
 
             "%s", err);
 
534
    if (err != NULL) {
 
535
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", err);
 
536
    }
538
537
 
539
538
    r->hostname = host;
540
539
 
567
566
 
568
567
    /* Iterate over up to 4 (dotted) quads. */
569
568
    for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
570
 
    char *tmp;
571
 
 
572
 
    if (*addr == '/' && quads > 0)  /* netmask starts here. */
573
 
        break;
574
 
 
575
 
    if (!apr_isdigit(*addr))
576
 
        return 0;       /* no digit at start of quad */
577
 
 
578
 
    ip_addr[quads] = strtol(addr, &tmp, 0);
579
 
 
580
 
    if (tmp == addr)    /* expected a digit, found something else */
581
 
        return 0;
582
 
 
583
 
    if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
584
 
        /* invalid octet */
585
 
        return 0;
586
 
    }
587
 
 
588
 
    addr = tmp;
589
 
 
590
 
    if (*addr == '.' && quads != 3)
591
 
        ++addr;     /* after the 4th quad, a dot would be illegal */
592
 
    }
593
 
 
594
 
    for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
595
 
    This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
569
        char *tmp;
 
570
 
 
571
        if (*addr == '/' && quads > 0) {  /* netmask starts here. */
 
572
            break;
 
573
        }
 
574
 
 
575
        if (!apr_isdigit(*addr)) {
 
576
            return 0;       /* no digit at start of quad */
 
577
        }
 
578
 
 
579
        ip_addr[quads] = strtol(addr, &tmp, 0);
 
580
 
 
581
        if (tmp == addr) {  /* expected a digit, found something else */
 
582
            return 0;
 
583
        }
 
584
 
 
585
        if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
 
586
            /* invalid octet */
 
587
            return 0;
 
588
        }
 
589
 
 
590
        addr = tmp;
 
591
 
 
592
        if (*addr == '.' && quads != 3) {
 
593
            ++addr;     /* after the 4th quad, a dot would be illegal */
 
594
        }
 
595
    }
 
596
 
 
597
    for (This->addr.s_addr = 0, i = 0; i < quads; ++i) {
 
598
        This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
599
    }
596
600
 
597
601
    if (addr[0] == '/' && apr_isdigit(addr[1])) {   /* net mask follows: */
598
 
    char *tmp;
599
 
 
600
 
    ++addr;
601
 
 
602
 
    bits = strtol(addr, &tmp, 0);
603
 
 
604
 
    if (tmp == addr)    /* expected a digit, found something else */
605
 
        return 0;
606
 
 
607
 
    addr = tmp;
608
 
 
609
 
    if (bits < 0 || bits > 32)  /* netmask must be between 0 and 32 */
610
 
        return 0;
 
602
        char *tmp;
 
603
 
 
604
        ++addr;
 
605
 
 
606
        bits = strtol(addr, &tmp, 0);
 
607
 
 
608
        if (tmp == addr) {   /* expected a digit, found something else */
 
609
            return 0;
 
610
        }
 
611
 
 
612
        addr = tmp;
 
613
 
 
614
        if (bits < 0 || bits > 32) { /* netmask must be between 0 and 32 */
 
615
            return 0;
 
616
        }
611
617
 
612
618
    }
613
619
    else {
614
 
    /*
615
 
     * Determine (i.e., "guess") netmask by counting the
616
 
     * number of trailing .0's; reduce #quads appropriately
617
 
     * (so that 192.168.0.0 is equivalent to 192.168.)
618
 
     */
619
 
    while (quads > 0 && ip_addr[quads - 1] == 0)
620
 
        --quads;
621
 
 
622
 
    /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
623
 
    if (quads < 1)
624
 
        return 0;
625
 
 
626
 
    /* every zero-byte counts as 8 zero-bits */
627
 
    bits = 8 * quads;
628
 
 
629
 
    if (bits != 32)     /* no warning for fully qualified IP address */
 
620
        /*
 
621
         * Determine (i.e., "guess") netmask by counting the
 
622
         * number of trailing .0's; reduce #quads appropriately
 
623
         * (so that 192.168.0.0 is equivalent to 192.168.)
 
624
         */
 
625
        while (quads > 0 && ip_addr[quads - 1] == 0) {
 
626
            --quads;
 
627
        }
 
628
 
 
629
        /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
 
630
        if (quads < 1) {
 
631
            return 0;
 
632
        }
 
633
 
 
634
        /* every zero-byte counts as 8 zero-bits */
 
635
        bits = 8 * quads;
 
636
 
 
637
        if (bits != 32) {     /* no warning for fully qualified IP address */
630
638
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
631
 
          "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld",
632
 
         inet_ntoa(This->addr), bits);
 
639
                         "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld",
 
640
                         inet_ntoa(This->addr), bits);
 
641
        }
633
642
    }
634
643
 
635
644
    This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
636
645
 
637
646
    if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
638
647
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
639
 
        "Warning: NetMask and IP-Addr disagree in %s/%ld",
640
 
        inet_ntoa(This->addr), bits);
641
 
    This->addr.s_addr &= This->mask.s_addr;
 
648
                     "Warning: NetMask and IP-Addr disagree in %s/%ld",
 
649
                     inet_ntoa(This->addr), bits);
 
650
        This->addr.s_addr &= This->mask.s_addr;
642
651
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
643
 
        "         Set to %s/%ld",
644
 
        inet_ntoa(This->addr), bits);
 
652
                     "         Set to %s/%ld", inet_ntoa(This->addr), bits);
645
653
    }
646
654
 
647
655
    if (*addr == '\0') {
648
 
    This->matcher = proxy_match_ipaddr;
649
 
    return 1;
650
 
    }
651
 
    else
652
 
    return (*addr == '\0'); /* okay iff we've parsed the whole string */
 
656
        This->matcher = proxy_match_ipaddr;
 
657
        return 1;
 
658
    }
 
659
    else {
 
660
        return (*addr == '\0'); /* okay iff we've parsed the whole string */
 
661
    }
653
662
}
654
663
 
655
664
/* Return TRUE if addr represents an IP address (or an IP network address) */
659
668
    struct in_addr addr, *ip;
660
669
    const char *host = proxy_get_host_of_request(r);
661
670
 
662
 
    if (host == NULL)   /* oops! */
 
671
    if (host == NULL) {   /* oops! */
663
672
       return 0;
 
673
    }
664
674
 
665
675
    memset(&addr, '\0', sizeof addr);
666
676
    memset(ip_addr, '\0', sizeof ip_addr);
667
677
 
668
678
    if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
669
 
    for (addr.s_addr = 0, i = 0; i < 4; ++i)
670
 
        addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
679
        for (addr.s_addr = 0, i = 0; i < 4; ++i) {
 
680
            addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
 
681
        }
671
682
 
672
 
    if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
 
683
        if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
673
684
#if DEBUGGING
674
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
685
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
675
686
                         "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
676
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
687
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
677
688
                         "%s/", inet_ntoa(This->addr));
678
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
689
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
679
690
                         "%s", inet_ntoa(This->mask));
680
691
#endif
681
 
        return 1;
682
 
    }
 
692
            return 1;
 
693
        }
683
694
#if DEBUGGING
684
 
    else {
685
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
695
        else {
 
696
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
686
697
                         "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
687
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
698
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
688
699
                         "%s/", inet_ntoa(This->addr));
689
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
700
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
690
701
                         "%s", inet_ntoa(This->mask));
691
 
    }
 
702
        }
692
703
#endif
693
704
    }
694
705
    else {
695
 
    struct apr_sockaddr_t *reqaddr;
 
706
        struct apr_sockaddr_t *reqaddr;
696
707
 
697
708
        if (apr_sockaddr_info_get(&reqaddr, host, APR_UNSPEC, 0, 0, r->pool)
698
 
        != APR_SUCCESS) {
 
709
            != APR_SUCCESS) {
699
710
#if DEBUGGING
700
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
701
 
             "2)IP-NoMatch: hostname=%s msg=Host not found",
702
 
             host);
 
711
            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
712
             "2)IP-NoMatch: hostname=%s msg=Host not found", host);
703
713
#endif
704
 
        return 0;
705
 
    }
 
714
            return 0;
 
715
        }
706
716
 
707
 
    /* Try to deal with multiple IP addr's for a host */
708
 
    /* FIXME: This needs to be able to deal with IPv6 */
709
 
    while (reqaddr) {
710
 
        ip = (struct in_addr *) reqaddr->ipaddr_ptr;
711
 
        if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) {
712
 
#if DEBUGGING
713
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
714
 
                 "3)IP-Match: %s[%s] <-> ", host,
715
 
                 inet_ntoa(*ip));
716
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
717
 
                 "%s/", inet_ntoa(This->addr));
718
 
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
719
 
                 "%s", inet_ntoa(This->mask));
720
 
#endif
721
 
        return 1;
722
 
        }
723
 
#if DEBUGGING
724
 
        else {
725
 
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
726
 
                 "3)IP-NoMatch: %s[%s] <-> ", host,
727
 
                 inet_ntoa(*ip));
728
 
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
729
 
                 "%s/", inet_ntoa(This->addr));
730
 
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
731
 
                 "%s", inet_ntoa(This->mask));
732
 
        }
733
 
#endif
734
 
        reqaddr = reqaddr->next;
735
 
    }
 
717
        /* Try to deal with multiple IP addr's for a host */
 
718
        /* FIXME: This needs to be able to deal with IPv6 */
 
719
        while (reqaddr) {
 
720
            ip = (struct in_addr *) reqaddr->ipaddr_ptr;
 
721
            if (This->addr.s_addr == (ip->s_addr & This->mask.s_addr)) {
 
722
#if DEBUGGING
 
723
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
724
                             "3)IP-Match: %s[%s] <-> ", host, inet_ntoa(*ip));
 
725
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
726
                             "%s/", inet_ntoa(This->addr));
 
727
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
728
                             "%s", inet_ntoa(This->mask));
 
729
#endif
 
730
                return 1;
 
731
            }
 
732
#if DEBUGGING
 
733
            else {
 
734
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
735
                             "3)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(*ip));
 
736
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
737
                             "%s/", inet_ntoa(This->addr));
 
738
                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
 
739
                             "%s", inet_ntoa(This->mask));
 
740
            }
 
741
#endif
 
742
            reqaddr = reqaddr->next;
 
743
        }
736
744
    }
737
745
 
738
746
    return 0;
745
753
    int i;
746
754
 
747
755
    /* Domain name must start with a '.' */
748
 
    if (addr[0] != '.')
 
756
    if (addr[0] != '.') {
749
757
        return 0;
 
758
    }
750
759
 
751
760
    /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
752
 
    for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
 
761
    for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i) {
753
762
        continue;
 
763
    }
754
764
 
755
765
#if 0
756
766
    if (addr[i] == ':') {
760
770
    }
761
771
#endif
762
772
 
763
 
    if (addr[i] != '\0')
 
773
    if (addr[i] != '\0') {
764
774
        return 0;
 
775
    }
765
776
 
766
777
    /* Strip trailing dots */
767
 
    for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
 
778
    for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i) {
768
779
        addr[i] = '\0';
 
780
    }
769
781
 
770
782
    This->matcher = proxy_match_domainname;
771
783
    return 1;
777
789
    const char *host = proxy_get_host_of_request(r);
778
790
    int d_len = strlen(This->name), h_len;
779
791
 
780
 
    if (host == NULL)       /* some error was logged already */
 
792
    if (host == NULL) {      /* some error was logged already */
781
793
        return 0;
 
794
    }
782
795
 
783
796
    h_len = strlen(host);
784
797
 
785
798
    /* @@@ do this within the setup? */
786
799
    /* Ignore trailing dots in domain comparison: */
787
 
    while (d_len > 0 && This->name[d_len - 1] == '.')
 
800
    while (d_len > 0 && This->name[d_len - 1] == '.') {
788
801
        --d_len;
789
 
    while (h_len > 0 && host[h_len - 1] == '.')
 
802
    }
 
803
    while (h_len > 0 && host[h_len - 1] == '.') {
790
804
        --h_len;
 
805
    }
791
806
    return h_len > d_len
792
807
        && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
793
808
}
800
815
    int i;
801
816
 
802
817
    /* Host names must not start with a '.' */
803
 
    if (host[0] == '.')
 
818
    if (host[0] == '.') {
804
819
        return 0;
805
 
 
 
820
    }
806
821
    /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
807
822
    for (i = 0; apr_isalnum(host[i]) || host[i] == '-' || host[i] == '.'; ++i);
808
823
 
809
 
    if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS)
 
824
    if (host[i] != '\0' || apr_sockaddr_info_get(&addr, host, APR_UNSPEC, 0, 0, p) != APR_SUCCESS) {
810
825
        return 0;
 
826
    }
811
827
 
812
828
    This->hostaddr = addr;
813
829
 
814
830
    /* Strip trailing dots */
815
 
    for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i)
 
831
    for (i = strlen(host) - 1; i > 0 && host[i] == '.'; --i) {
816
832
        host[i] = '\0';
 
833
    }
817
834
 
818
835
    This->matcher = proxy_match_hostname;
819
836
    return 1;
827
844
    int h2_len;
828
845
    int h1_len;
829
846
 
830
 
    if (host == NULL || host2 == NULL)
 
847
    if (host == NULL || host2 == NULL) {
831
848
        return 0; /* oops! */
 
849
    }
832
850
 
833
851
    h2_len = strlen(host2);
834
852
    h1_len = strlen(host);
845
863
#endif
846
864
 
847
865
    /* Ignore trailing dots in host2 comparison: */
848
 
    while (h2_len > 0 && host2[h2_len - 1] == '.')
 
866
    while (h2_len > 0 && host2[h2_len - 1] == '.') {
849
867
        --h2_len;
850
 
    while (h1_len > 0 && host[h1_len - 1] == '.')
 
868
    }
 
869
    while (h1_len > 0 && host[h1_len - 1] == '.') {
851
870
        --h1_len;
 
871
    }
852
872
    return h1_len == h2_len
853
873
        && strncasecmp(host, host2, h1_len) == 0;
854
874
}
955
975
                *eos = 1;
956
976
            }
957
977
            else {
958
 
                if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) {
 
978
                if (APR_SUCCESS != (rv = apr_bucket_read(e,
 
979
                                                         (const char **)&response,
 
980
                                                         &len,
 
981
                                                         APR_BLOCK_READ))) {
959
982
                    return rv;
960
983
                }
961
984
                /*
1150
1173
    int i;
1151
1174
 
1152
1175
    c = strchr(uri, ':');
1153
 
    if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0')
 
1176
    if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
1154
1177
       return NULL;
 
1178
    }
1155
1179
    /* remove path from uri */
1156
 
    if ((c = strchr(c + 3, '/')))
 
1180
    if ((c = strchr(c + 3, '/'))) {
1157
1181
        *c = '\0';
 
1182
    }
1158
1183
    balancer = (proxy_balancer *)conf->balancers->elts;
1159
1184
    for (i = 0; i < conf->balancers->nelts; i++) {
1160
 
        if (strcasecmp(balancer->name, uri) == 0)
 
1185
        if (strcasecmp(balancer->name, uri) == 0) {
1161
1186
            return balancer;
 
1187
        }
1162
1188
        balancer++;
1163
1189
    }
1164
1190
    return NULL;
1215
1241
    proxy_worker *max_worker = NULL;
1216
1242
    int max_match = 0;
1217
1243
    int url_length;
 
1244
    int min_match;
1218
1245
    int worker_name_length;
1219
1246
    const char *c;
1220
1247
    char *url_copy;
1221
1248
    int i;
1222
1249
 
1223
1250
    c = ap_strchr_c(url, ':');
1224
 
    if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0')
 
1251
    if (c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') {
1225
1252
       return NULL;
 
1253
    }
1226
1254
 
1227
1255
    url_copy = apr_pstrdup(p, url);
1228
1256
    url_length = strlen(url);
1239
1267
        pathstart = url_copy + (c - url);
1240
1268
        *pathstart = '\0';
1241
1269
        ap_str_tolower(url_copy);
 
1270
        min_match = strlen(url_copy);
1242
1271
        *pathstart = '/';
1243
 
    } else {
 
1272
    }
 
1273
    else {
1244
1274
        ap_str_tolower(url_copy);
 
1275
        min_match = strlen(url_copy);
1245
1276
    }
1246
1277
 
1247
1278
    worker = (proxy_worker *)conf->workers->elts;
1248
1279
 
1249
1280
    /*
1250
1281
     * Do a "longest match" on the worker name to find the worker that
1251
 
     * fits best to the URL.
 
1282
     * fits best to the URL, but keep in mind that we must have at least
 
1283
     * a minimum matching of length min_match such that
 
1284
     * scheme://hostname[:port] matches between worker and url.
1252
1285
     */
1253
1286
    for (i = 0; i < conf->workers->nelts; i++) {
1254
1287
        if ( ((worker_name_length = strlen(worker->name)) <= url_length)
 
1288
           && (worker_name_length >= min_match)
1255
1289
           && (worker_name_length > max_match)
1256
1290
           && (strncmp(url_copy, worker->name, worker_name_length) == 0) ) {
1257
1291
            max_worker = worker;
1419
1453
                                         proxy_server_conf *conf)
1420
1454
{
1421
1455
    int access_status;
1422
 
    if (balancer)
 
1456
    if (balancer) {
1423
1457
        access_status = proxy_run_post_request(worker, balancer, r, conf);
 
1458
    }
1424
1459
    else {
1425
 
 
1426
 
 
1427
1460
        access_status = OK;
1428
1461
    }
1429
1462
 
1471
1504
        }
1472
1505
#endif
1473
1506
 
 
1507
        rv = apr_socket_opt_set(*newsock, APR_TCP_NODELAY, 1);
 
1508
        if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
 
1509
             ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
 
1510
                          "apr_socket_opt_set(APR_TCP_NODELAY): "
 
1511
                          "Failed to set");
 
1512
        }
 
1513
 
1474
1514
        /* Set a timeout on the socket */
1475
1515
        if (conf->timeout_set == 1) {
1476
1516
            apr_socket_timeout_set(*newsock, conf->timeout);
1512
1552
     * If the connection pool is NULL the worker
1513
1553
     * cleanup has been run. Just return.
1514
1554
     */
1515
 
    if (!worker->cp)
 
1555
    if (!worker->cp) {
1516
1556
        return APR_SUCCESS;
 
1557
    }
1517
1558
 
1518
1559
#if APR_HAS_THREADS
1519
1560
    /* Sanity check: Did we already return the pooled connection? */
1545
1586
        worker->cp->conn = conn;
1546
1587
    }
1547
1588
 
1548
 
    /* Allways return the SUCCESS */
 
1589
    /* Always return the SUCCESS */
1549
1590
    return APR_SUCCESS;
1550
1591
}
1551
1592
 
1583
1624
    proxy_conn_rec *conn = (proxy_conn_rec *)resource;
1584
1625
 
1585
1626
    /* Destroy the pool only if not called from reslist_destroy */
1586
 
    if (conn->worker->cp->pool)
 
1627
    if (conn->worker->cp->pool) {
1587
1628
        apr_pool_destroy(conn->pool);
 
1629
    }
1588
1630
 
1589
1631
    return APR_SUCCESS;
1590
1632
}
1646
1688
              worker->name);
1647
1689
        return;
1648
1690
    }
1649
 
    if (worker->route)
 
1691
    if (worker->route) {
1650
1692
        strcpy(worker->s->route, worker->route);
1651
 
    else
 
1693
    }
 
1694
    else {
1652
1695
        *worker->s->route = '\0';
1653
 
    if (worker->redirect)
 
1696
    }
 
1697
    if (worker->redirect) {
1654
1698
        strcpy(worker->s->redirect, worker->redirect);
1655
 
    else
 
1699
    }
 
1700
    else {
1656
1701
        *worker->s->redirect = '\0';
 
1702
    }
1657
1703
 
1658
1704
    worker->s->status |= (worker->status | PROXY_WORKER_INITIALIZED);
1659
1705
 
1673
1719
    }
1674
1720
 
1675
1721
    /* Set default parameters */
1676
 
    if (!worker->retry)
 
1722
    if (!worker->retry) {
1677
1723
        worker->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
 
1724
    }
1678
1725
    /* By default address is reusable */
1679
1726
    worker->is_address_reusable = 1;
1680
1727
 
1682
1729
    ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
1683
1730
    if (mpm_threads > 1) {
1684
1731
        /* Set hard max to no more then mpm_threads */
1685
 
        if (worker->hmax == 0 || worker->hmax > mpm_threads)
 
1732
        if (worker->hmax == 0 || worker->hmax > mpm_threads) {
1686
1733
            worker->hmax = mpm_threads;
1687
 
        if (worker->smax == 0 || worker->smax > worker->hmax)
 
1734
        }
 
1735
        if (worker->smax == 0 || worker->smax > worker->hmax) {
1688
1736
            worker->smax = worker->hmax;
 
1737
        }
1689
1738
        /* Set min to be lower then smax */
1690
 
        if (worker->min > worker->smax)
 
1739
        if (worker->min > worker->smax) {
1691
1740
            worker->min = worker->smax;
 
1741
        }
1692
1742
    }
1693
1743
    else {
1694
1744
        /* This will supress the apr_reslist creation */
1712
1762
 
1713
1763
#if (APR_MAJOR_VERSION > 0)
1714
1764
        /* Set the acquire timeout */
1715
 
        if (rv == APR_SUCCESS && worker->acquire_set)
 
1765
        if (rv == APR_SUCCESS && worker->acquire_set) {
1716
1766
            apr_reslist_timeout_set(worker->cp->res, worker->acquire);
 
1767
        }
1717
1768
#endif
1718
1769
    }
1719
1770
    else
1747
1798
                         proxy_function, worker->hostname);
1748
1799
            return OK;
1749
1800
        }
1750
 
        else
 
1801
        else {
1751
1802
            return DECLINED;
 
1803
        }
1752
1804
    }
1753
 
    else
 
1805
    else {
1754
1806
        return OK;
 
1807
    }
1755
1808
}
1756
1809
 
1757
1810
PROXY_DECLARE(int) ap_proxy_acquire_connection(const char *proxy_function,
1780
1833
#endif
1781
1834
    {
1782
1835
        /* create the new connection if the previous was destroyed */
1783
 
        if (!worker->cp->conn)
 
1836
        if (!worker->cp->conn) {
1784
1837
            connection_constructor((void **)conn, worker, worker->cp->pool);
 
1838
        }
1785
1839
        else {
1786
1840
            *conn = worker->cp->conn;
1787
1841
            worker->cp->conn = NULL;
1881
1935
     *
1882
1936
     * TODO: Handle this much better...
1883
1937
     */
1884
 
    if (!conn->hostname || !worker->is_address_reusable ||   
 
1938
    if (!conn->hostname || !worker->is_address_reusable ||
1885
1939
         (r->connection->keepalives &&
1886
1940
         (r->proxyreq == PROXYREQ_PROXY || r->proxyreq == PROXYREQ_REVERSE) &&
1887
1941
         (strcasecmp(conn->hostname, uri->hostname) != 0) ) ) {
1888
1942
        if (proxyname) {
1889
1943
            conn->hostname = apr_pstrdup(conn->pool, proxyname);
1890
1944
            conn->port = proxyport;
1891
 
        } else {
 
1945
        }
 
1946
        else {
1892
1947
            conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
1893
1948
            conn->port = uri->port;
1894
1949
        }
1928
1983
                         "proxy: unlock");
1929
1984
        }
1930
1985
    }
1931
 
    else
 
1986
    else {
1932
1987
        conn->addr = worker->cp->addr;
 
1988
    }
1933
1989
 
1934
1990
    if (err != APR_SUCCESS) {
1935
1991
        return ap_proxyerror(r, HTTP_BAD_GATEWAY,
1942
1998
        server_port = ap_get_server_port(r);
1943
1999
        if (ap_is_default_port(server_port, r)) {
1944
2000
            strcpy(server_portstr,"");
1945
 
        } else {
 
2001
        }
 
2002
        else {
1946
2003
            apr_snprintf(server_portstr, server_portstr_size, ":%d",
1947
2004
                         server_port);
1948
2005
        }
1958
2015
    return OK;
1959
2016
}
1960
2017
 
 
2018
#define USE_ALTERNATE_IS_CONNECTED 1
 
2019
 
 
2020
#if !defined(APR_MSG_PEEK) && defined(MSG_PEEK)
 
2021
#define APR_MSG_PEEK MSG_PEEK
 
2022
#endif
 
2023
 
 
2024
#if USE_ALTERNATE_IS_CONNECTED && defined(APR_MSG_PEEK)
 
2025
static int is_socket_connected(apr_socket_t *socket)
 
2026
{
 
2027
    apr_pollfd_t pfds[1];
 
2028
    apr_status_t status;
 
2029
    apr_int32_t  nfds;
 
2030
 
 
2031
    pfds[0].reqevents = APR_POLLIN;
 
2032
    pfds[0].desc_type = APR_POLL_SOCKET;
 
2033
    pfds[0].desc.s = socket;
 
2034
 
 
2035
    do {
 
2036
        status = apr_poll(&pfds[0], 1, &nfds, 0);
 
2037
    } while (APR_STATUS_IS_EINTR(status));
 
2038
 
 
2039
    if (status == APR_SUCCESS && nfds == 1 &&
 
2040
        pfds[0].rtnevents == APR_POLLIN) {
 
2041
        apr_sockaddr_t unused;
 
2042
        apr_size_t len = 1;
 
2043
        char buf[1];
 
2044
        /* The socket might be closed in which case
 
2045
         * the poll will return POLLIN.
 
2046
         * If there is no data available the socket
 
2047
         * is closed.
 
2048
         */
 
2049
        status = apr_socket_recvfrom(&unused, socket, APR_MSG_PEEK,
 
2050
                                     &buf[0], &len);
 
2051
        if (status == APR_SUCCESS && len)
 
2052
            return 1;
 
2053
        else
 
2054
            return 0;
 
2055
    }
 
2056
    else if (APR_STATUS_IS_EAGAIN(status)) {
 
2057
        return 1;
 
2058
    }
 
2059
    return 0;
 
2060
 
 
2061
}
 
2062
#else
1961
2063
static int is_socket_connected(apr_socket_t *sock)
1962
2064
 
1963
2065
{
1979
2081
    else
1980
2082
        return 1;
1981
2083
}
 
2084
#endif /* USE_ALTERNATE_IS_CONNECTED */
1982
2085
 
1983
2086
PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
1984
2087
                                            proxy_conn_rec *conn,
1990
2093
    int loglevel;
1991
2094
    apr_sockaddr_t *backend_addr = conn->addr;
1992
2095
    apr_socket_t *newsock;
 
2096
    void *sconf = s->module_config;
 
2097
    proxy_server_conf *conf =
 
2098
        (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
1993
2099
 
1994
2100
    if (conn->sock) {
1995
2101
        /*
2000
2106
        if (!(connected = is_socket_connected(conn->sock))) {
2001
2107
            apr_socket_close(conn->sock);
2002
2108
            conn->sock = NULL;
 
2109
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
 
2110
                         "proxy: %s: backend socket is disconnected.",
 
2111
                         proxy_function);
2003
2112
        }
2004
2113
    }
2005
2114
    while (backend_addr && !connected) {
2031
2140
        }
2032
2141
#endif
2033
2142
 
 
2143
        rv = apr_socket_opt_set(newsock, APR_TCP_NODELAY, 1);
 
2144
        if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
 
2145
             ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
 
2146
                          "apr_socket_opt_set(APR_TCP_NODELAY): "
 
2147
                          "Failed to set");
 
2148
        }
 
2149
 
2034
2150
        /* Set a timeout on the socket */
2035
2151
        if (worker->timeout_set == 1) {
2036
2152
            apr_socket_timeout_set(newsock, worker->timeout);
2037
2153
        }
 
2154
        else if (conf->timeout_set == 1) {
 
2155
            apr_socket_timeout_set(newsock, conf->timeout);
 
2156
        }
2038
2157
        else {
2039
2158
             apr_socket_timeout_set(newsock, s->timeout);
2040
2159
        }
2098
2217
{
2099
2218
    apr_sockaddr_t *backend_addr = conn->addr;
2100
2219
    int rc;
 
2220
    apr_interval_time_t current_timeout;
2101
2221
 
2102
2222
    /*
2103
2223
     * The socket is now open, create a new backend server connection
2147
2267
                 "proxy: %s: connection complete to %pI (%s)",
2148
2268
                 proxy_function, backend_addr, conn->hostname);
2149
2269
 
 
2270
    /*
 
2271
     * save the timout of the socket because core_pre_connection
 
2272
     * will set it to base_server->timeout
 
2273
     * (core TimeOut directive).
 
2274
     */
 
2275
    apr_socket_timeout_get(conn->sock, &current_timeout);
2150
2276
    /* set up the connection filters */
2151
2277
    rc = ap_run_pre_connection(conn->connection, conn->sock);
2152
2278
    if (rc != OK && rc != DONE) {
2156
2282
                     proxy_function, rc);
2157
2283
        return rc;
2158
2284
    }
 
2285
    apr_socket_timeout_set(conn->sock, current_timeout);
2159
2286
 
2160
2287
    return OK;
2161
2288
}