~ubuntu-branches/debian/squeeze/nginx/squeeze

« back to all changes in this revision

Viewing changes to src/core/ngx_inet.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Tranchitella
  • Date: 2009-05-31 18:38:56 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20090531183856-3xhvf6wd0bw5556i
Tags: 0.7.59-1
* New upstream release, first in Debian for the 0.7 branch. Among other
  issues, it also fixes the problem with wildcard dns names used with SSL.
  (Closes: #515904)
* debian/watch: updated.
* debian/postinst: fixed a bashism. (Closes: #507913)
* debian/conf/nginx.conf: removed default_type. (Closes: #509390)
* debian/control: updated Standards-Version to 3.8.1, no changes needed.
* debian/NEWS.Debian: documented the issues with
  server_names_hash_bucket_size. (Closes: #524785)

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
#include <ngx_core.h>
9
9
 
10
10
 
11
 
static size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len);
12
 
 
13
 
 
14
 
/* AF_INET only */
 
11
#if (NGX_HAVE_INET6)
 
12
static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
 
13
#endif
 
14
static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
 
15
static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
 
16
static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
 
17
 
15
18
 
16
19
in_addr_t
17
20
ngx_inet_addr(u_char *text, size_t len)
56
59
}
57
60
 
58
61
 
59
 
/*
60
 
 * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as
61
 
 * "ngx_sprintf(text, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3])", however,
62
 
 * they had been implemented long before the ngx_sprintf() had appeared
63
 
 * and they are faster by 1.5-2.5 times, so it is worth to keep them.
64
 
 *
65
 
 * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
66
 
 * than using FreeBSD libc's snprintf().
67
 
 */
68
 
 
69
 
/* AF_INET only */
70
 
 
71
62
size_t
72
 
ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len)
 
63
ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
73
64
{
74
 
    u_char              *p;
75
 
    size_t               n;
76
 
    ngx_uint_t           i;
77
 
    struct sockaddr_in  *sin;
78
 
 
79
 
    if (len == 0) {
80
 
        return 0;
81
 
    }
82
 
 
83
 
    if (family != AF_INET) {
84
 
        return 0;
85
 
    }
86
 
 
87
 
    sin = (struct sockaddr_in *) sa;
88
 
    p = (u_char *) &sin->sin_addr;
89
 
 
90
 
    if (len > INET_ADDRSTRLEN) {
91
 
        len = INET_ADDRSTRLEN;
92
 
    }
93
 
 
94
 
    n = ngx_sprint_uchar(text, p[0], len);
95
 
 
96
 
    i = 1;
97
 
 
98
 
    do {
99
 
        if (len == n) {
100
 
            text[n - 1] = '\0';
101
 
            return n;
102
 
        }
103
 
 
104
 
        text[n++] = '.';
105
 
 
106
 
        if (len == n) {
107
 
            text[n - 1] = '\0';
108
 
            return n;
109
 
        }
110
 
 
111
 
        n += ngx_sprint_uchar(&text[n], p[i++], len - n);
112
 
 
113
 
    } while (i < 4);
114
 
 
115
 
    if (len == n) {
116
 
        text[n] = '\0';
 
65
    u_char               *p;
 
66
    struct sockaddr_in   *sin;
 
67
#if (NGX_HAVE_INET6)
 
68
    size_t                n;
 
69
    struct sockaddr_in6  *sin6;
 
70
#endif
 
71
 
 
72
    switch (sa->sa_family) {
 
73
 
 
74
    case AF_INET:
 
75
 
 
76
        sin = (struct sockaddr_in *) sa;
 
77
        p = (u_char *) &sin->sin_addr;
 
78
 
 
79
        if (port) {
 
80
            p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
 
81
                             p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
 
82
        } else {
 
83
            p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
 
84
                             p[0], p[1], p[2], p[3]);
 
85
        }
 
86
 
 
87
        return (p - text);
 
88
 
 
89
#if (NGX_HAVE_INET6)
 
90
 
 
91
    case AF_INET6:
 
92
 
 
93
        sin6 = (struct sockaddr_in6 *) sa;
 
94
 
 
95
        n = 0;
 
96
 
 
97
        if (port) {
 
98
            text[n++] = '[';
 
99
        }
 
100
 
 
101
        n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len);
 
102
 
 
103
        if (port) {
 
104
            n = ngx_sprintf(&text[1 + n], "]:%d",
 
105
                            ntohs(sin6->sin6_port)) - text;
 
106
        }
 
107
 
117
108
        return n;
 
109
#endif
 
110
 
 
111
    default:
 
112
        return 0;
118
113
    }
119
 
 
120
 
    text[n] = '\0';
121
 
 
122
 
    return n;
123
114
}
124
115
 
125
116
 
126
117
size_t
127
118
ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
128
119
{
129
 
    u_char      *p;
130
 
    size_t       n;
131
 
    ngx_uint_t   i;
132
 
 
133
 
    if (len == 0) {
134
 
        return 0;
135
 
    }
136
 
 
137
 
    if (family != AF_INET) {
138
 
        return 0;
139
 
    }
140
 
 
141
 
    p = (u_char *) addr;
142
 
 
143
 
    if (len > INET_ADDRSTRLEN) {
144
 
        len = INET_ADDRSTRLEN;
145
 
    }
146
 
 
147
 
    n = ngx_sprint_uchar(text, p[0], len);
148
 
 
149
 
    i = 1;
150
 
 
151
 
    do {
152
 
        if (len == n) {
153
 
            text[n - 1] = '\0';
154
 
            return n;
155
 
        }
156
 
 
157
 
        text[n++] = '.';
158
 
 
159
 
        if (len == n) {
160
 
            text[n - 1] = '\0';
161
 
            return n;
162
 
        }
163
 
 
164
 
        n += ngx_sprint_uchar(&text[n], p[i++], len - n);
165
 
 
166
 
    } while (i < 4);
167
 
 
168
 
    if (len == n) {
169
 
        text[n] = '\0';
170
 
        return n;
171
 
    }
172
 
 
173
 
    text[n] = '\0';
174
 
 
175
 
    return n;
 
120
    u_char  *p;
 
121
 
 
122
    switch (family) {
 
123
 
 
124
    case AF_INET:
 
125
 
 
126
        p = addr;
 
127
 
 
128
        return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
 
129
                            p[0], p[1], p[2], p[3])
 
130
               - text;
 
131
 
 
132
#if (NGX_HAVE_INET6)
 
133
 
 
134
    case AF_INET6:
 
135
        return ngx_inet6_ntop(addr, text, len);
 
136
 
 
137
#endif
 
138
 
 
139
    default:
 
140
        return 0;
 
141
    }
176
142
}
177
143
 
178
144
 
 
145
#if (NGX_HAVE_INET6)
 
146
 
179
147
static size_t
180
 
ngx_sprint_uchar(u_char *text, u_char c, size_t len)
 
148
ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
181
149
{
182
 
    size_t      n;
183
 
    ngx_uint_t  c1, c2;
184
 
 
 
150
    u_char      *dst;
 
151
    size_t       max, n;
 
152
    ngx_uint_t   i, zero, last;
 
153
 
 
154
    if (len < NGX_INET6_ADDRSTRLEN) {
 
155
        return 0;
 
156
    }
 
157
 
 
158
    zero = (ngx_uint_t) -1;
 
159
    last = (ngx_uint_t) -1;
 
160
    max = 1;
185
161
    n = 0;
186
162
 
187
 
    if (len == n) {
188
 
        return n;
189
 
    }
190
 
 
191
 
    c1 = c / 100;
192
 
 
193
 
    if (c1) {
194
 
        *text++ = (u_char) (c1 + '0');
195
 
        n++;
196
 
 
197
 
        if (len == n) {
198
 
            return n;
199
 
        }
200
 
    }
201
 
 
202
 
    c2 = (c % 100) / 10;
203
 
 
204
 
    if (c1 || c2) {
205
 
        *text++ = (u_char) (c2 + '0');
206
 
        n++;
207
 
 
208
 
        if (len == n) {
209
 
            return n;
210
 
        }
211
 
    }
212
 
 
213
 
    c2 = c % 10;
214
 
 
215
 
    *text = (u_char) (c2 + '0');
216
 
    n++;
217
 
 
218
 
    return n;
 
163
    for (i = 0; i < 16; i += 2) {
 
164
 
 
165
        if (p[i] || p[i + 1]) {
 
166
 
 
167
            if (max < n) {
 
168
                zero = last;
 
169
                max = n;
 
170
            }
 
171
 
 
172
            n = 0;
 
173
            continue;
 
174
        }
 
175
 
 
176
        if (n++ == 0) {
 
177
            last = i;
 
178
        }
 
179
    }
 
180
 
 
181
    if (max < n) {
 
182
        zero = last;
 
183
        max = n;
 
184
    }
 
185
 
 
186
    dst = text;
 
187
    n = 16;
 
188
 
 
189
    if (zero == 0) {
 
190
 
 
191
        if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
 
192
            || (max == 6)
 
193
            || (max == 7 && p[14] != 0 && p[15] != 1))
 
194
        {
 
195
            n = 12;
 
196
        }
 
197
 
 
198
        *dst++ = ':';
 
199
    }
 
200
 
 
201
    for (i = 0; i < n; i += 2) {
 
202
 
 
203
        if (i == zero) {
 
204
            *dst++ = ':';
 
205
            i += (max - 1) * 2;
 
206
            continue;
 
207
        }
 
208
 
 
209
        dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
 
210
 
 
211
        if (i < 14) {
 
212
            *dst++ = ':';
 
213
        }
 
214
    }
 
215
 
 
216
    if (n == 12) {
 
217
        dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
 
218
    }
 
219
 
 
220
    return dst - text;
219
221
}
220
222
 
 
223
#endif
 
224
 
221
225
 
222
226
/* AF_INET only */
223
227
 
224
228
ngx_int_t
225
 
ngx_ptocidr(ngx_str_t *text, void *cidr)
 
229
ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
226
230
{
227
 
    ngx_int_t         m;
228
 
    ngx_uint_t        i;
229
 
    ngx_inet_cidr_t  *in_cidr;
230
 
 
231
 
    in_cidr = cidr;
232
 
 
233
 
    for (i = 0; i < text->len; i++) {
234
 
        if (text->data[i] == '/') {
235
 
            break;
236
 
        }
237
 
    }
238
 
 
239
 
    if (i == text->len) {
240
 
        return NGX_ERROR;
241
 
    }
242
 
 
243
 
    text->data[i] = '\0';
244
 
    in_cidr->addr = inet_addr((char *) text->data);
245
 
    text->data[i] = '/';
246
 
    if (in_cidr->addr == INADDR_NONE) {
247
 
        return NGX_ERROR;
248
 
    }
249
 
 
250
 
    m = ngx_atoi(&text->data[i + 1], text->len - (i + 1));
251
 
    if (m == NGX_ERROR) {
252
 
        return NGX_ERROR;
253
 
    }
254
 
 
255
 
    if (m == 0) {
 
231
    u_char     *addr, *mask, *last;
 
232
    ngx_int_t   shift;
 
233
 
 
234
    addr = text->data;
 
235
    last = addr + text->len;
 
236
 
 
237
    mask = ngx_strlchr(addr, last, '/');
 
238
 
 
239
    cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
 
240
 
 
241
    if (cidr->u.in.addr == INADDR_NONE) {
 
242
        return NGX_ERROR;
 
243
    }
 
244
 
 
245
    if (mask == NULL) {
 
246
        cidr->family = AF_INET;
 
247
        cidr->u.in.mask = 0xffffffff;
 
248
        return NGX_OK;
 
249
    }
 
250
 
 
251
    mask++;
 
252
 
 
253
    shift = ngx_atoi(mask, last - mask);
 
254
    if (shift == NGX_ERROR) {
 
255
        return NGX_ERROR;
 
256
    }
 
257
 
 
258
    cidr->family = AF_INET;
 
259
 
 
260
    if (shift == 0) {
256
261
 
257
262
        /* the x86 compilers use the shl instruction that shifts by modulo 32 */
258
263
 
259
 
        in_cidr->mask = 0;
260
 
        return NGX_OK;
261
 
    }
262
 
 
263
 
    in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m))));
264
 
 
265
 
    if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
266
 
        return NGX_OK;
267
 
    }
268
 
 
269
 
    in_cidr->addr &= in_cidr->mask;
 
264
        cidr->u.in.mask = 0;
 
265
 
 
266
        if (cidr->u.in.addr == 0) {
 
267
            return NGX_OK;
 
268
        }
 
269
 
 
270
        return NGX_DONE;
 
271
    }
 
272
 
 
273
    cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
 
274
 
 
275
    if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
 
276
        return NGX_OK;
 
277
    }
 
278
 
 
279
    cidr->u.in.addr &= cidr->u.in.mask;
270
280
 
271
281
    return NGX_DONE;
272
282
}
275
285
ngx_int_t
276
286
ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
277
287
{
278
 
    u_char              *p, *host, *port_start;
279
 
    size_t               len, port_len;
280
 
    ngx_int_t            port;
281
 
    ngx_uint_t           i;
282
 
    struct hostent      *h;
 
288
    u_char  *p;
 
289
 
 
290
    p = u->url.data;
 
291
 
 
292
    if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
 
293
        return ngx_parse_unix_domain_url(pool, u);
 
294
    }
 
295
 
 
296
    if ((p[0] == ':' || p[0] == '/') && !u->listen) {
 
297
        u->err = "invalid host";
 
298
        return NGX_ERROR;
 
299
    }
 
300
 
 
301
    if (p[0] == '[') {
 
302
        return ngx_parse_inet6_url(pool, u);
 
303
    }
 
304
 
 
305
    return ngx_parse_inet_url(pool, u);
 
306
}
 
307
 
 
308
 
 
309
static ngx_int_t
 
310
ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
 
311
{
283
312
#if (NGX_HAVE_UNIX_DOMAIN)
 
313
    u_char              *path, *uri, *last;
 
314
    size_t               len;
284
315
    struct sockaddr_un  *saun;
285
 
#endif
286
316
 
287
317
    len = u->url.len;
288
 
    p = u->url.data;
289
 
 
290
 
    if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
291
 
 
292
 
#if (NGX_HAVE_UNIX_DOMAIN)
293
 
 
294
 
        p += 5;
295
 
        len -= 5;
296
 
 
297
 
        u->uri.len = len;
298
 
        u->uri.data = p;
299
 
 
300
 
        if (u->uri_part) {
301
 
            for (i = 0; i < len; i++) {
302
 
 
303
 
                if (p[i] == ':') {
304
 
                    len = i;
305
 
 
306
 
                    u->uri.len -= len + 1;
307
 
                    u->uri.data += len + 1;
308
 
 
309
 
                    break;
310
 
                }
311
 
            }
312
 
        }
 
318
    path = u->url.data;
 
319
 
 
320
    path += 5;
 
321
    len -= 5;
 
322
 
 
323
    if (u->uri_part) {
 
324
 
 
325
        last = path + len;
 
326
        uri = ngx_strlchr(path, last, ':');
 
327
 
 
328
        if (uri) {
 
329
            len = uri - path;
 
330
            uri++;
 
331
            u->uri.len = last - uri;
 
332
            u->uri.data = uri;
 
333
        }
 
334
    }
 
335
 
 
336
    if (len == 0) {
 
337
        u->err = "no path in the unix domain socket";
 
338
        return NGX_ERROR;
 
339
    }
 
340
 
 
341
    u->host.len = len++;
 
342
    u->host.data = path;
 
343
 
 
344
    if (len > sizeof(saun->sun_path)) {
 
345
        u->err = "too long path in the unix domain socket";
 
346
        return NGX_ERROR;
 
347
    }
 
348
 
 
349
    u->socklen = sizeof(struct sockaddr_un);
 
350
    saun = (struct sockaddr_un *) &u->sockaddr;
 
351
    saun->sun_family = AF_UNIX;
 
352
    (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
 
353
 
 
354
    u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
 
355
    if (u->addrs == NULL) {
 
356
        return NGX_ERROR;
 
357
    }
 
358
 
 
359
    saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
 
360
    if (saun == NULL) {
 
361
        return NGX_ERROR;
 
362
    }
 
363
 
 
364
    u->family = AF_UNIX;
 
365
    u->naddrs = 1;
 
366
 
 
367
    saun->sun_family = AF_UNIX;
 
368
    (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
 
369
 
 
370
    u->addrs[0].sockaddr = (struct sockaddr *) saun;
 
371
    u->addrs[0].socklen = sizeof(struct sockaddr_un);
 
372
    u->addrs[0].name.len = len + 4;
 
373
    u->addrs[0].name.data = u->url.data;
 
374
 
 
375
    return NGX_OK;
 
376
 
 
377
#else
 
378
 
 
379
    u->err = "the unix domain sockets are not supported on this platform";
 
380
 
 
381
    return NGX_ERROR;
 
382
 
 
383
#endif
 
384
}
 
385
 
 
386
 
 
387
static ngx_int_t
 
388
ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
 
389
{
 
390
    u_char              *p, *host, *port, *last, *uri, *args;
 
391
    size_t               len;
 
392
    ngx_int_t            n;
 
393
    struct hostent      *h;
 
394
    struct sockaddr_in  *sin;
 
395
 
 
396
    u->socklen = sizeof(struct sockaddr_in);
 
397
    sin = (struct sockaddr_in *) &u->sockaddr;
 
398
    sin->sin_family = AF_INET;
 
399
 
 
400
    u->family = AF_INET;
 
401
 
 
402
    host = u->url.data;
 
403
 
 
404
    last = host + u->url.len;
 
405
 
 
406
    port = ngx_strlchr(host, last, ':');
 
407
 
 
408
    uri = ngx_strlchr(host, last, '/');
 
409
 
 
410
    args = ngx_strlchr(host, last, '?');
 
411
 
 
412
    if (args) {
 
413
        if (uri == NULL) {
 
414
            uri = args;
 
415
 
 
416
        } else if (args < uri) {
 
417
            uri = args;
 
418
        }
 
419
    }
 
420
 
 
421
    if (uri) {
 
422
        if (u->listen || !u->uri_part) {
 
423
            u->err = "invalid host";
 
424
            return NGX_ERROR;
 
425
        }
 
426
 
 
427
        u->uri.len = last - uri;
 
428
        u->uri.data = uri;
 
429
 
 
430
        last = uri;
 
431
 
 
432
        if (uri < port) {
 
433
            port = NULL;
 
434
        }
 
435
    }
 
436
 
 
437
    if (port) {
 
438
        port++;
 
439
 
 
440
        len = last - port;
313
441
 
314
442
        if (len == 0) {
315
 
            u->err = "no path in the unix domain socket";
316
 
            return NGX_ERROR;
317
 
        }
318
 
 
319
 
        if (len + 1 > sizeof(saun->sun_path)) {
320
 
            u->err = "too long path in the unix domain socket";
321
 
            return NGX_ERROR;
322
 
        }
323
 
 
324
 
        u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
325
 
        if (u->addrs == NULL) {
326
 
            return NGX_ERROR;
327
 
        }
328
 
 
329
 
        saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
330
 
        if (saun == NULL) {
331
 
            return NGX_ERROR;
332
 
        }
333
 
 
334
 
        u->naddrs = 1;
335
 
 
336
 
        saun->sun_family = AF_UNIX;
337
 
        (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
338
 
 
339
 
        u->addrs[0].sockaddr = (struct sockaddr *) saun;
340
 
        u->addrs[0].socklen = sizeof(struct sockaddr_un);
341
 
        u->addrs[0].name.len = len + 5;
342
 
        u->addrs[0].name.data = u->url.data;
343
 
 
344
 
        u->host.len = len;
345
 
        u->host.data = p;
346
 
 
347
 
        u->unix_socket = 1;
348
 
 
 
443
            u->err = "invalid port";
 
444
            return NGX_ERROR;
 
445
        }
 
446
 
 
447
        n = ngx_atoi(port, len);
 
448
 
 
449
        if (n < 1 || n > 65536) {
 
450
            u->err = "invalid port";
 
451
            return NGX_ERROR;
 
452
        }
 
453
 
 
454
        u->port = (in_port_t) n;
 
455
        sin->sin_port = htons((in_port_t) n);
 
456
 
 
457
        u->port_text.len = len;
 
458
        u->port_text.data = port;
 
459
 
 
460
        last = port - 1;
 
461
 
 
462
    } else {
 
463
        if (uri == NULL) {
 
464
 
 
465
            if (u->listen) {
 
466
 
 
467
                /* test value as port only */
 
468
 
 
469
                n = ngx_atoi(host, last - host);
 
470
 
 
471
                if (n != NGX_ERROR) {
 
472
 
 
473
                    if (n < 1 || n > 65536) {
 
474
                        u->err = "invalid port";
 
475
                        return NGX_ERROR;
 
476
                    }
 
477
 
 
478
                    u->port = (in_port_t) n;
 
479
                    sin->sin_port = htons((in_port_t) n);
 
480
 
 
481
                    u->port_text.len = last - host;
 
482
                    u->port_text.data = host;
 
483
 
 
484
                    u->wildcard = 1;
 
485
 
 
486
                    return NGX_OK;
 
487
                }
 
488
            }
 
489
        }
 
490
 
 
491
        u->no_port = 1;
 
492
    }
 
493
 
 
494
    len = last - host;
 
495
 
 
496
    if (len == 0) {
 
497
        u->err = "no host";
 
498
        return NGX_ERROR;
 
499
    }
 
500
 
 
501
    if (len == 1 && *host == '*') {
 
502
        len = 0;
 
503
    }
 
504
 
 
505
    u->host.len = len;
 
506
    u->host.data = host;
 
507
 
 
508
    if (u->no_resolve) {
349
509
        return NGX_OK;
350
 
 
351
 
#else
352
 
        u->err = "the unix domain sockets are not supported on this platform";
353
 
 
354
 
        return NGX_ERROR;
355
 
 
356
 
#endif
357
 
    }
358
 
 
359
 
    if ((p[0] == ':' || p[0] == '/') && !u->listen) {
360
 
        u->err = "invalid host";
361
 
        return NGX_ERROR;
362
 
    }
363
 
 
364
 
    u->host.data = p;
365
 
 
366
 
    port_start = NULL;
367
 
    port_len = 0;
368
 
 
369
 
    for (i = 0; i < len; i++) {
370
 
 
371
 
        if (p[i] == ':') {
372
 
            port_start = &p[i + 1];
373
 
            u->host.len = i;
374
 
 
375
 
            if (!u->uri_part) {
376
 
                port_len = len - (i + 1);
377
 
                break;
378
 
            }
379
 
        }
380
 
 
381
 
        if (p[i] == '/') {
382
 
            u->uri.len = len - i;
383
 
            u->uri.data = &p[i];
384
 
 
385
 
            if (u->host.len == 0) {
386
 
                u->host.len = i;
387
 
            }
388
 
 
389
 
            if (port_start == NULL) {
390
 
                u->no_port = 1;
391
 
                goto no_port;
392
 
            }
393
 
 
394
 
            port_len = &p[i] - port_start;
395
 
 
396
 
            if (port_len == 0) {
397
 
                u->err = "invalid port";
398
 
                return NGX_ERROR;
399
 
            }
400
 
 
401
 
            break;
402
 
        }
403
 
    }
404
 
 
405
 
    if (port_start) {
406
 
 
407
 
        if (port_len == 0) {
408
 
            port_len = &p[i] - port_start;
409
 
 
410
 
            if (port_len == 0) {
411
 
                u->err = "invalid port";
412
 
                return NGX_ERROR;
413
 
            }
414
 
        }
415
 
 
416
 
        port = ngx_atoi(port_start, port_len);
417
 
 
418
 
        if (port == NGX_ERROR || port < 1 || port > 65536) {
419
 
            u->err = "invalid port";
 
510
    }
 
511
 
 
512
    if (len++) {
 
513
 
 
514
        p = ngx_alloc(len, pool->log);
 
515
        if (p == NULL) {
420
516
            return NGX_ERROR;
421
517
        }
422
518
 
423
 
        u->port_text.len = port_len;
424
 
        u->port_text.data = port_start;
 
519
        (void) ngx_cpystrn(p, host, len);
 
520
 
 
521
        sin->sin_addr.s_addr = inet_addr((const char *) p);
 
522
 
 
523
        if (sin->sin_addr.s_addr == INADDR_NONE) {
 
524
            h = gethostbyname((const char *) p);
 
525
 
 
526
            if (h == NULL || h->h_addr_list[0] == NULL) {
 
527
                ngx_free(p);
 
528
                u->err = "host not found";
 
529
                return NGX_ERROR;
 
530
            }
 
531
 
 
532
            sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
 
533
        }
 
534
 
 
535
        if (sin->sin_addr.s_addr == INADDR_ANY) {
 
536
            u->wildcard = 1;
 
537
        }
 
538
 
 
539
        ngx_free(p);
425
540
 
426
541
    } else {
427
 
        port = ngx_atoi(p, len);
428
 
 
429
 
        if (port == NGX_ERROR) {
430
 
            u->host.len = len;
431
 
            u->no_port = 1;
432
 
 
433
 
            goto no_port;
434
 
        }
435
 
 
 
542
        sin->sin_addr.s_addr = INADDR_ANY;
436
543
        u->wildcard = 1;
437
544
    }
438
545
 
439
 
    u->port = (in_port_t) port;
440
 
 
441
 
no_port:
 
546
    if (u->no_port) {
 
547
        u->port = u->default_port;
 
548
        sin->sin_port = htons(u->default_port);
 
549
    }
442
550
 
443
551
    if (u->listen) {
444
 
 
445
 
        if (u->port == 0) {
446
 
            if (u->default_port == 0) {
447
 
                u->err = "no port";
448
 
                return NGX_ERROR;
449
 
            }
450
 
 
451
 
            u->port = u->default_port;
452
 
        }
453
 
 
454
 
        if (u->host.len == 1 && u->host.data[0] == '*') {
455
 
            u->host.len = 0;
456
 
        }
457
 
 
458
 
        /* AF_INET only */
459
 
 
460
 
        if (u->host.len) {
461
 
 
462
 
            host = ngx_alloc(u->host.len + 1, pool->log);
463
 
            if (host == NULL) {
464
 
                return NGX_ERROR;
465
 
            }
466
 
 
467
 
            (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
468
 
 
469
 
            u->addr.in_addr = inet_addr((const char *) host);
470
 
 
471
 
            if (u->addr.in_addr == INADDR_NONE) {
472
 
                h = gethostbyname((const char *) host);
473
 
 
474
 
                if (h == NULL || h->h_addr_list[0] == NULL) {
475
 
                    ngx_free(host);
476
 
                    u->err = "host not found";
477
 
                    return NGX_ERROR;
478
 
                }
479
 
 
480
 
                u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
481
 
            }
482
 
 
483
 
            ngx_free(host);
484
 
 
485
 
        } else {
486
 
            u->addr.in_addr = INADDR_ANY;
487
 
        }
488
 
 
489
 
        return NGX_OK;
490
 
    }
491
 
 
492
 
    if (u->host.len == 0) {
493
 
        u->err = "no host";
494
 
        return NGX_ERROR;
495
 
    }
496
 
 
497
 
    if (u->no_resolve) {
498
 
        return NGX_OK;
499
 
    }
500
 
 
501
 
    if (u->no_port) {
502
 
        u->port = u->default_port;
503
 
    }
504
 
 
505
 
    if (u->port == 0) {
506
 
        u->err = "no port";
507
 
        return NGX_ERROR;
 
552
        return NGX_OK;
508
553
    }
509
554
 
510
555
    if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
515
560
}
516
561
 
517
562
 
 
563
static ngx_int_t
 
564
ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
 
565
{
 
566
#if (NGX_HAVE_INET6)
 
567
    int                   rc;
 
568
    u_char               *p, *host, *port, *last, *uri;
 
569
    size_t                len;
 
570
    ngx_int_t             n;
 
571
    struct sockaddr_in6  *sin6;
 
572
 
 
573
    u->socklen = sizeof(struct sockaddr_in6);
 
574
    sin6 = (struct sockaddr_in6 *) &u->sockaddr;
 
575
    sin6->sin6_family = AF_INET6;
 
576
 
 
577
    host = u->url.data + 1;
 
578
 
 
579
    last = u->url.data + u->url.len;
 
580
 
 
581
    p = ngx_strlchr(host, last, ']');
 
582
 
 
583
    if (p == NULL) {
 
584
        u->err = "invalid host";
 
585
        return NGX_ERROR;
 
586
    }
 
587
 
 
588
    if (last - p) {
 
589
 
 
590
        port = p + 1;
 
591
 
 
592
        uri = ngx_strlchr(port, last, '/');
 
593
 
 
594
        if (uri) {
 
595
            if (u->listen || !u->uri_part) {
 
596
                u->err = "invalid host";
 
597
                return NGX_ERROR;
 
598
            }
 
599
 
 
600
            u->uri.len = last - uri;
 
601
            u->uri.data = uri;
 
602
        }
 
603
 
 
604
        if (*port == ':') {
 
605
            port++;
 
606
 
 
607
            len = last - port;
 
608
 
 
609
            if (len == 0) {
 
610
                u->err = "invalid port";
 
611
                return NGX_ERROR;
 
612
            }
 
613
 
 
614
            n = ngx_atoi(port, len);
 
615
 
 
616
            if (n < 1 || n > 65536) {
 
617
                u->err = "invalid port";
 
618
                return NGX_ERROR;
 
619
            }
 
620
 
 
621
            u->port = (in_port_t) n;
 
622
            sin6->sin6_port = htons((in_port_t) n);
 
623
 
 
624
            u->port_text.len = len;
 
625
            u->port_text.data = port;
 
626
 
 
627
        } else {
 
628
            u->no_port = 1;
 
629
        }
 
630
    }
 
631
 
 
632
    len = p - host;
 
633
 
 
634
    if (len == 0) {
 
635
        u->err = "no host";
 
636
        return NGX_ERROR;
 
637
    }
 
638
 
 
639
    u->host.len = len++;
 
640
    u->host.data = host;
 
641
 
 
642
    p = ngx_alloc(len, pool->log);
 
643
    if (p == NULL) {
 
644
        return NGX_ERROR;
 
645
    }
 
646
 
 
647
    (void) ngx_cpystrn(p, host, len);
 
648
 
 
649
#if (NGX_WIN32)
 
650
 
 
651
    rc = WSAStringToAddress((char *) p, AF_INET6, NULL,
 
652
                            (SOCKADDR *) sin6, &u->socklen);
 
653
    rc = !rc;
 
654
 
 
655
    if (u->port) {
 
656
        sin6->sin6_port = htons(u->port);
 
657
    }
 
658
 
 
659
#else
 
660
 
 
661
    rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
 
662
 
 
663
#endif
 
664
 
 
665
    ngx_free(p);
 
666
 
 
667
    if (rc == 0) {
 
668
        u->err = "invalid IPv6 address";
 
669
        return NGX_ERROR;
 
670
    }
 
671
 
 
672
    if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 
673
        u->wildcard = 1;
 
674
    }
 
675
 
 
676
    u->family = AF_INET6;
 
677
 
 
678
    if (u->no_resolve) {
 
679
        return NGX_OK;
 
680
    }
 
681
 
 
682
    if (u->no_port) {
 
683
        u->port = u->default_port;
 
684
        sin6->sin6_port = htons(u->default_port);
 
685
    }
 
686
 
 
687
    return NGX_OK;
 
688
 
 
689
#else
 
690
 
 
691
    u->err = "the INET6 sockets are not supported on this platform";
 
692
 
 
693
    return NGX_ERROR;
 
694
 
 
695
#endif
 
696
}
 
697
 
 
698
 
518
699
ngx_int_t
519
700
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
520
701
{
521
702
    u_char              *p, *host;
522
703
    size_t               len;
 
704
    in_port_t            port;
523
705
    in_addr_t            in_addr;
524
706
    ngx_uint_t           i;
525
707
    struct hostent      *h;
534
716
 
535
717
    /* AF_INET only */
536
718
 
 
719
    port = htons(u->port);
 
720
 
537
721
    in_addr = inet_addr((char *) host);
538
722
 
539
723
    if (in_addr == INADDR_NONE) {
570
754
            }
571
755
 
572
756
            sin->sin_family = AF_INET;
573
 
            sin->sin_port = htons(u->port);
 
757
            sin->sin_port = port;
574
758
            sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
575
759
 
576
760
            u->addrs[i].sockaddr = (struct sockaddr *) sin;
577
761
            u->addrs[i].socklen = sizeof(struct sockaddr_in);
578
762
 
579
 
            len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
 
763
            len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
580
764
 
581
 
            p = ngx_palloc(pool, len);
 
765
            p = ngx_pnalloc(pool, len);
582
766
            if (p == NULL) {
583
767
                return NGX_ERROR;
584
768
            }
585
769
 
586
 
            len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, p, len);
 
770
            len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
587
771
 
588
 
            u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p;
 
772
            u->addrs[i].name.len = len;
589
773
            u->addrs[i].name.data = p;
590
774
        }
591
775
 
608
792
        u->naddrs = 1;
609
793
 
610
794
        sin->sin_family = AF_INET;
611
 
        sin->sin_port = htons(u->port);
 
795
        sin->sin_port = port;
612
796
        sin->sin_addr.s_addr = in_addr;
613
797
 
614
798
        u->addrs[0].sockaddr = (struct sockaddr *) sin;
615
799
        u->addrs[0].socklen = sizeof(struct sockaddr_in);
616
800
 
617
 
        p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
 
801
        p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
618
802
        if (p == NULL) {
619
803
            return NGX_ERROR;
620
804
        }
621
805
 
622
 
        u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
 
806
        u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
 
807
                                           &u->host, ntohs(port)) - p;
623
808
        u->addrs[0].name.data = p;
624
809
    }
625
810