Coverage Report

Created: 2026-05-16 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nginx/src/http/ngx_http.c
Line
Count
Source
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) Nginx, Inc.
5
 */
6
7
8
#include <ngx_config.h>
9
#include <ngx_core.h>
10
#include <ngx_http.h>
11
12
13
static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14
static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
15
    ngx_http_core_main_conf_t *cmcf);
16
static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
17
    ngx_http_core_main_conf_t *cmcf);
18
static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
19
    ngx_http_core_main_conf_t *cmcf);
20
21
static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
22
    ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
23
    ngx_http_listen_opt_t *lsopt);
24
static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
25
    ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
26
    ngx_http_listen_opt_t *lsopt);
27
static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
28
    ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
29
30
static char *ngx_http_merge_servers(ngx_conf_t *cf,
31
    ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
32
    ngx_uint_t ctx_index);
33
static char *ngx_http_merge_locations(ngx_conf_t *cf,
34
    ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
35
    ngx_uint_t ctx_index);
36
static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
37
    ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
38
static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
39
    ngx_http_core_loc_conf_t *pclcf);
40
static ngx_int_t ngx_http_escape_location_name(ngx_conf_t *cf,
41
    ngx_http_core_loc_conf_t *clcf);
42
static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
43
    const ngx_queue_t *two);
44
static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
45
    ngx_queue_t *locations);
46
static void ngx_http_create_locations_list(ngx_queue_t *locations,
47
    ngx_queue_t *q);
48
static ngx_http_location_tree_node_t *
49
    ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
50
    size_t prefix);
51
52
static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
53
    ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
54
static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
55
    ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
56
static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
57
static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
58
    const void *two);
59
60
static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
61
    ngx_http_conf_port_t *port);
62
static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
63
    ngx_http_conf_addr_t *addr);
64
static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
65
    ngx_http_conf_addr_t *addr);
66
#if (NGX_HAVE_INET6)
67
static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
68
    ngx_http_conf_addr_t *addr);
69
#endif
70
71
ngx_uint_t   ngx_http_max_module;
72
73
74
ngx_http_output_header_filter_pt  ngx_http_top_header_filter;
75
ngx_http_output_header_filter_pt  ngx_http_top_early_hints_filter;
76
ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
77
ngx_http_request_body_filter_pt   ngx_http_top_request_body_filter;
78
79
80
ngx_str_t  ngx_http_html_default_types[] = {
81
    ngx_string("text/html"),
82
    ngx_null_string
83
};
84
85
86
static ngx_command_t  ngx_http_commands[] = {
87
88
    { ngx_string("http"),
89
      NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
90
      ngx_http_block,
91
      0,
92
      0,
93
      NULL },
94
95
      ngx_null_command
96
};
97
98
99
static ngx_core_module_t  ngx_http_module_ctx = {
100
    ngx_string("http"),
101
    NULL,
102
    NULL
103
};
104
105
106
ngx_module_t  ngx_http_module = {
107
    NGX_MODULE_V1,
108
    &ngx_http_module_ctx,                  /* module context */
109
    ngx_http_commands,                     /* module directives */
110
    NGX_CORE_MODULE,                       /* module type */
111
    NULL,                                  /* init master */
112
    NULL,                                  /* init module */
113
    NULL,                                  /* init process */
114
    NULL,                                  /* init thread */
115
    NULL,                                  /* exit thread */
116
    NULL,                                  /* exit process */
117
    NULL,                                  /* exit master */
118
    NGX_MODULE_V1_PADDING
119
};
120
121
122
static char *
123
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
124
1
{
125
1
    char                        *rv;
126
1
    ngx_uint_t                   mi, m, s;
127
1
    ngx_conf_t                   pcf;
128
1
    ngx_http_module_t           *module;
129
1
    ngx_http_conf_ctx_t         *ctx;
130
1
    ngx_http_core_loc_conf_t    *clcf;
131
1
    ngx_http_core_srv_conf_t   **cscfp;
132
1
    ngx_http_core_main_conf_t   *cmcf;
133
134
1
    if (*(ngx_http_conf_ctx_t **) conf) {
135
0
        return "is duplicate";
136
0
    }
137
138
    /* the main http context */
139
140
1
    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
141
1
    if (ctx == NULL) {
142
0
        return NGX_CONF_ERROR;
143
0
    }
144
145
1
    *(ngx_http_conf_ctx_t **) conf = ctx;
146
147
148
    /* count the number of the http modules and set up their indices */
149
150
1
    ngx_http_max_module = ngx_count_modules(cf->cycle, NGX_HTTP_MODULE);
151
152
153
    /* the http main_conf context, it is the same in the all http contexts */
154
155
1
    ctx->main_conf = ngx_pcalloc(cf->pool,
156
1
                                 sizeof(void *) * ngx_http_max_module);
157
1
    if (ctx->main_conf == NULL) {
158
0
        return NGX_CONF_ERROR;
159
0
    }
160
161
162
    /*
163
     * the http null srv_conf context, it is used to merge
164
     * the server{}s' srv_conf's
165
     */
166
167
1
    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
168
1
    if (ctx->srv_conf == NULL) {
169
0
        return NGX_CONF_ERROR;
170
0
    }
171
172
173
    /*
174
     * the http null loc_conf context, it is used to merge
175
     * the server{}s' loc_conf's
176
     */
177
178
1
    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
179
1
    if (ctx->loc_conf == NULL) {
180
0
        return NGX_CONF_ERROR;
181
0
    }
182
183
184
    /*
185
     * create the main_conf's, the null srv_conf's, and the null loc_conf's
186
     * of the all http modules
187
     */
188
189
59
    for (m = 0; cf->cycle->modules[m]; m++) {
190
58
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
191
8
            continue;
192
8
        }
193
194
50
        module = cf->cycle->modules[m]->ctx;
195
50
        mi = cf->cycle->modules[m]->ctx_index;
196
197
50
        if (module->create_main_conf) {
198
11
            ctx->main_conf[mi] = module->create_main_conf(cf);
199
11
            if (ctx->main_conf[mi] == NULL) {
200
0
                return NGX_CONF_ERROR;
201
0
            }
202
11
        }
203
204
50
        if (module->create_srv_conf) {
205
7
            ctx->srv_conf[mi] = module->create_srv_conf(cf);
206
7
            if (ctx->srv_conf[mi] == NULL) {
207
0
                return NGX_CONF_ERROR;
208
0
            }
209
7
        }
210
211
50
        if (module->create_loc_conf) {
212
27
            ctx->loc_conf[mi] = module->create_loc_conf(cf);
213
27
            if (ctx->loc_conf[mi] == NULL) {
214
0
                return NGX_CONF_ERROR;
215
0
            }
216
27
        }
217
50
    }
218
219
1
    pcf = *cf;
220
1
    cf->ctx = ctx;
221
222
59
    for (m = 0; cf->cycle->modules[m]; m++) {
223
58
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
224
8
            continue;
225
8
        }
226
227
50
        module = cf->cycle->modules[m]->ctx;
228
229
50
        if (module->preconfiguration) {
230
13
            if (module->preconfiguration(cf) != NGX_OK) {
231
0
                return NGX_CONF_ERROR;
232
0
            }
233
13
        }
234
50
    }
235
236
    /* parse inside the http{} block */
237
238
1
    cf->module_type = NGX_HTTP_MODULE;
239
1
    cf->cmd_type = NGX_HTTP_MAIN_CONF;
240
1
    rv = ngx_conf_parse(cf, NULL);
241
242
1
    if (rv != NGX_CONF_OK) {
243
0
        goto failed;
244
0
    }
245
246
    /*
247
     * init http{} main_conf's, merge the server{}s' srv_conf's
248
     * and its location{}s' loc_conf's
249
     */
250
251
1
    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
252
1
    cscfp = cmcf->servers.elts;
253
254
59
    for (m = 0; cf->cycle->modules[m]; m++) {
255
58
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
256
8
            continue;
257
8
        }
258
259
50
        module = cf->cycle->modules[m]->ctx;
260
50
        mi = cf->cycle->modules[m]->ctx_index;
261
262
        /* init http{} main_conf's */
263
264
50
        if (module->init_main_conf) {
265
5
            rv = module->init_main_conf(cf, ctx->main_conf[mi]);
266
5
            if (rv != NGX_CONF_OK) {
267
0
                goto failed;
268
0
            }
269
5
        }
270
271
50
        rv = ngx_http_merge_servers(cf, cmcf, module, mi);
272
50
        if (rv != NGX_CONF_OK) {
273
0
            goto failed;
274
0
        }
275
50
    }
276
277
278
    /* create location trees */
279
280
2
    for (s = 0; s < cmcf->servers.nelts; s++) {
281
282
1
        clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
283
284
1
        if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) {
285
0
            return NGX_CONF_ERROR;
286
0
        }
287
288
1
        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
289
0
            return NGX_CONF_ERROR;
290
0
        }
291
1
    }
292
293
294
1
    if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
295
0
        return NGX_CONF_ERROR;
296
0
    }
297
298
1
    if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
299
0
        return NGX_CONF_ERROR;
300
0
    }
301
302
303
59
    for (m = 0; cf->cycle->modules[m]; m++) {
304
58
        if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
305
8
            continue;
306
8
        }
307
308
50
        module = cf->cycle->modules[m]->ctx;
309
310
50
        if (module->postconfiguration) {
311
26
            if (module->postconfiguration(cf) != NGX_OK) {
312
0
                return NGX_CONF_ERROR;
313
0
            }
314
26
        }
315
50
    }
316
317
1
    if (ngx_http_variables_init_vars(cf) != NGX_OK) {
318
0
        return NGX_CONF_ERROR;
319
0
    }
320
321
    /*
322
     * http{}'s cf->ctx was needed while the configuration merging
323
     * and in postconfiguration process
324
     */
325
326
1
    *cf = pcf;
327
328
329
1
    if (ngx_http_init_phase_handlers(cf, cmcf) != NGX_OK) {
330
0
        return NGX_CONF_ERROR;
331
0
    }
332
333
334
    /* optimize the lists of ports, addresses and server names */
335
336
1
    if (ngx_http_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
337
0
        return NGX_CONF_ERROR;
338
0
    }
339
340
1
    return NGX_CONF_OK;
341
342
0
failed:
343
344
0
    *cf = pcf;
345
346
0
    return rv;
347
1
}
348
349
350
static ngx_int_t
351
ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
352
1
{
353
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers,
354
1
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
355
1
        != NGX_OK)
356
0
    {
357
0
        return NGX_ERROR;
358
0
    }
359
360
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers,
361
1
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
362
1
        != NGX_OK)
363
0
    {
364
0
        return NGX_ERROR;
365
0
    }
366
367
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
368
1
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
369
1
        != NGX_OK)
370
0
    {
371
0
        return NGX_ERROR;
372
0
    }
373
374
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers,
375
1
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
376
1
        != NGX_OK)
377
0
    {
378
0
        return NGX_ERROR;
379
0
    }
380
381
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
382
1
                       cf->pool, 2, sizeof(ngx_http_handler_pt))
383
1
        != NGX_OK)
384
0
    {
385
0
        return NGX_ERROR;
386
0
    }
387
388
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers,
389
1
                       cf->pool, 2, sizeof(ngx_http_handler_pt))
390
1
        != NGX_OK)
391
0
    {
392
0
        return NGX_ERROR;
393
0
    }
394
395
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
396
1
                       cf->pool, 4, sizeof(ngx_http_handler_pt))
397
1
        != NGX_OK)
398
0
    {
399
0
        return NGX_ERROR;
400
0
    }
401
402
1
    if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
403
1
                       cf->pool, 1, sizeof(ngx_http_handler_pt))
404
1
        != NGX_OK)
405
0
    {
406
0
        return NGX_ERROR;
407
0
    }
408
409
1
    return NGX_OK;
410
1
}
411
412
413
static ngx_int_t
414
ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
415
1
{
416
1
    ngx_array_t         headers_in;
417
1
    ngx_hash_key_t     *hk;
418
1
    ngx_hash_init_t     hash;
419
1
    ngx_http_header_t  *header;
420
421
1
    if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
422
1
        != NGX_OK)
423
0
    {
424
0
        return NGX_ERROR;
425
0
    }
426
427
26
    for (header = ngx_http_headers_in; header->name.len; header++) {
428
25
        hk = ngx_array_push(&headers_in);
429
25
        if (hk == NULL) {
430
0
            return NGX_ERROR;
431
0
        }
432
433
25
        hk->key = header->name;
434
25
        hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
435
25
        hk->value = header;
436
25
    }
437
438
1
    hash.hash = &cmcf->headers_in_hash;
439
1
    hash.key = ngx_hash_key_lc;
440
1
    hash.max_size = 512;
441
1
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
442
1
    hash.name = "headers_in_hash";
443
1
    hash.pool = cf->pool;
444
1
    hash.temp_pool = NULL;
445
446
1
    if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
447
0
        return NGX_ERROR;
448
0
    }
449
450
1
    return NGX_OK;
451
1
}
452
453
454
static ngx_int_t
455
ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
456
1
{
457
1
    ngx_int_t                   j;
458
1
    ngx_uint_t                  i, n;
459
1
    ngx_uint_t                  find_config_index, use_rewrite, use_access;
460
1
    ngx_http_handler_pt        *h;
461
1
    ngx_http_phase_handler_t   *ph;
462
1
    ngx_http_phase_handler_pt   checker;
463
464
1
    cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
465
1
    cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
466
1
    find_config_index = 0;
467
1
    use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
468
1
    use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
469
470
1
    n = 1                  /* find config phase */
471
1
        + use_rewrite      /* post rewrite phase */
472
1
        + use_access;      /* post access phase */
473
474
11
    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
475
10
        n += cmcf->phases[i].handlers.nelts;
476
10
    }
477
478
1
    ph = ngx_pcalloc(cf->pool,
479
1
                     n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
480
1
    if (ph == NULL) {
481
0
        return NGX_ERROR;
482
0
    }
483
484
1
    cmcf->phase_engine.handlers = ph;
485
1
    n = 0;
486
487
11
    for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
488
10
        h = cmcf->phases[i].handlers.elts;
489
490
10
        switch (i) {
491
492
1
        case NGX_HTTP_SERVER_REWRITE_PHASE:
493
1
            if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
494
1
                cmcf->phase_engine.server_rewrite_index = n;
495
1
            }
496
1
            checker = ngx_http_core_rewrite_phase;
497
498
1
            break;
499
500
1
        case NGX_HTTP_FIND_CONFIG_PHASE:
501
1
            find_config_index = n;
502
503
1
            ph->checker = ngx_http_core_find_config_phase;
504
1
            n++;
505
1
            ph++;
506
507
1
            continue;
508
509
1
        case NGX_HTTP_REWRITE_PHASE:
510
1
            if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
511
1
                cmcf->phase_engine.location_rewrite_index = n;
512
1
            }
513
1
            checker = ngx_http_core_rewrite_phase;
514
515
1
            break;
516
517
1
        case NGX_HTTP_POST_REWRITE_PHASE:
518
1
            if (use_rewrite) {
519
1
                ph->checker = ngx_http_core_post_rewrite_phase;
520
1
                ph->next = find_config_index;
521
1
                n++;
522
1
                ph++;
523
1
            }
524
525
1
            continue;
526
527
1
        case NGX_HTTP_ACCESS_PHASE:
528
1
            checker = ngx_http_core_access_phase;
529
1
            n++;
530
1
            break;
531
532
1
        case NGX_HTTP_POST_ACCESS_PHASE:
533
1
            if (use_access) {
534
1
                ph->checker = ngx_http_core_post_access_phase;
535
1
                ph->next = n;
536
1
                ph++;
537
1
            }
538
539
1
            continue;
540
541
1
        case NGX_HTTP_CONTENT_PHASE:
542
1
            checker = ngx_http_core_content_phase;
543
1
            break;
544
545
3
        default:
546
3
            checker = ngx_http_core_generic_phase;
547
10
        }
548
549
7
        n += cmcf->phases[i].handlers.nelts;
550
551
18
        for (j = cmcf->phases[i].handlers.nelts - 1; j >= 0; j--) {
552
11
            ph->checker = checker;
553
11
            ph->handler = h[j];
554
11
            ph->next = n;
555
11
            ph++;
556
11
        }
557
7
    }
558
559
1
    return NGX_OK;
560
1
}
561
562
563
static char *
564
ngx_http_merge_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
565
    ngx_http_module_t *module, ngx_uint_t ctx_index)
566
50
{
567
50
    char                        *rv;
568
50
    ngx_uint_t                   s;
569
50
    ngx_http_conf_ctx_t         *ctx, saved;
570
50
    ngx_http_core_loc_conf_t    *clcf;
571
50
    ngx_http_core_srv_conf_t   **cscfp;
572
573
50
    cscfp = cmcf->servers.elts;
574
50
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
575
50
    saved = *ctx;
576
50
    rv = NGX_CONF_OK;
577
578
100
    for (s = 0; s < cmcf->servers.nelts; s++) {
579
580
        /* merge the server{}s' srv_conf's */
581
582
50
        ctx->srv_conf = cscfp[s]->ctx->srv_conf;
583
584
50
        if (module->merge_srv_conf) {
585
2
            rv = module->merge_srv_conf(cf, saved.srv_conf[ctx_index],
586
2
                                        cscfp[s]->ctx->srv_conf[ctx_index]);
587
2
            if (rv != NGX_CONF_OK) {
588
0
                goto failed;
589
0
            }
590
2
        }
591
592
50
        if (module->merge_loc_conf) {
593
594
            /* merge the server{}'s loc_conf */
595
596
26
            ctx->loc_conf = cscfp[s]->ctx->loc_conf;
597
598
26
            rv = module->merge_loc_conf(cf, saved.loc_conf[ctx_index],
599
26
                                        cscfp[s]->ctx->loc_conf[ctx_index]);
600
26
            if (rv != NGX_CONF_OK) {
601
0
                goto failed;
602
0
            }
603
604
            /* merge the locations{}' loc_conf's */
605
606
26
            clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
607
608
26
            rv = ngx_http_merge_locations(cf, clcf->locations,
609
26
                                          cscfp[s]->ctx->loc_conf,
610
26
                                          module, ctx_index);
611
26
            if (rv != NGX_CONF_OK) {
612
0
                goto failed;
613
0
            }
614
26
        }
615
50
    }
616
617
50
failed:
618
619
50
    *ctx = saved;
620
621
50
    return rv;
622
50
}
623
624
625
static char *
626
ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations,
627
    void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index)
628
52
{
629
52
    char                       *rv;
630
52
    ngx_queue_t                *q;
631
52
    ngx_http_conf_ctx_t        *ctx, saved;
632
52
    ngx_http_core_loc_conf_t   *clcf;
633
52
    ngx_http_location_queue_t  *lq;
634
635
52
    if (locations == NULL) {
636
26
        return NGX_CONF_OK;
637
26
    }
638
639
26
    ctx = (ngx_http_conf_ctx_t *) cf->ctx;
640
26
    saved = *ctx;
641
642
26
    for (q = ngx_queue_head(locations);
643
52
         q != ngx_queue_sentinel(locations);
644
26
         q = ngx_queue_next(q))
645
26
    {
646
26
        lq = (ngx_http_location_queue_t *) q;
647
648
26
        clcf = lq->exact ? lq->exact : lq->inclusive;
649
26
        ctx->loc_conf = clcf->loc_conf;
650
651
26
        rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
652
26
                                    clcf->loc_conf[ctx_index]);
653
26
        if (rv != NGX_CONF_OK) {
654
0
            return rv;
655
0
        }
656
657
26
        rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf,
658
26
                                      module, ctx_index);
659
26
        if (rv != NGX_CONF_OK) {
660
0
            return rv;
661
0
        }
662
26
    }
663
664
26
    *ctx = saved;
665
666
26
    return NGX_CONF_OK;
667
26
}
668
669
670
static ngx_int_t
671
ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
672
    ngx_http_core_loc_conf_t *pclcf)
673
2
{
674
2
    ngx_uint_t                   n;
675
2
    ngx_queue_t                 *q, *locations, *named, tail;
676
2
    ngx_http_core_loc_conf_t    *clcf;
677
2
    ngx_http_location_queue_t   *lq;
678
2
    ngx_http_core_loc_conf_t   **clcfp;
679
2
#if (NGX_PCRE)
680
2
    ngx_uint_t                   r;
681
2
    ngx_queue_t                 *regex;
682
2
#endif
683
684
2
    locations = pclcf->locations;
685
686
2
    if (locations == NULL) {
687
1
        return NGX_OK;
688
1
    }
689
690
1
    ngx_queue_sort(locations, ngx_http_cmp_locations);
691
692
1
    named = NULL;
693
1
    n = 0;
694
1
#if (NGX_PCRE)
695
1
    regex = NULL;
696
1
    r = 0;
697
1
#endif
698
699
1
    for (q = ngx_queue_head(locations);
700
2
         q != ngx_queue_sentinel(locations);
701
1
         q = ngx_queue_next(q))
702
1
    {
703
1
        lq = (ngx_http_location_queue_t *) q;
704
705
1
        clcf = lq->exact ? lq->exact : lq->inclusive;
706
707
1
        if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
708
0
            return NGX_ERROR;
709
0
        }
710
711
1
#if (NGX_PCRE)
712
713
1
        if (clcf->regex) {
714
0
            r++;
715
716
0
            if (regex == NULL) {
717
0
                regex = q;
718
0
            }
719
720
0
            continue;
721
0
        }
722
723
1
#endif
724
725
1
        if (clcf->named) {
726
0
            n++;
727
728
0
            if (named == NULL) {
729
0
                named = q;
730
0
            }
731
732
0
            continue;
733
0
        }
734
735
1
        if (clcf->noname) {
736
0
            break;
737
0
        }
738
1
    }
739
740
1
    if (q != ngx_queue_sentinel(locations)) {
741
0
        ngx_queue_split(locations, q, &tail);
742
0
    }
743
744
1
    if (named) {
745
0
        clcfp = ngx_palloc(cf->pool,
746
0
                           (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
747
0
        if (clcfp == NULL) {
748
0
            return NGX_ERROR;
749
0
        }
750
751
0
        cscf->named_locations = clcfp;
752
753
0
        for (q = named;
754
0
             q != ngx_queue_sentinel(locations);
755
0
             q = ngx_queue_next(q))
756
0
        {
757
0
            lq = (ngx_http_location_queue_t *) q;
758
759
0
            *(clcfp++) = lq->exact;
760
0
        }
761
762
0
        *clcfp = NULL;
763
764
0
        ngx_queue_split(locations, named, &tail);
765
0
    }
766
767
1
#if (NGX_PCRE)
768
769
1
    if (regex) {
770
771
0
        clcfp = ngx_palloc(cf->pool,
772
0
                           (r + 1) * sizeof(ngx_http_core_loc_conf_t *));
773
0
        if (clcfp == NULL) {
774
0
            return NGX_ERROR;
775
0
        }
776
777
0
        pclcf->regex_locations = clcfp;
778
779
0
        for (q = regex;
780
0
             q != ngx_queue_sentinel(locations);
781
0
             q = ngx_queue_next(q))
782
0
        {
783
0
            lq = (ngx_http_location_queue_t *) q;
784
785
0
            *(clcfp++) = lq->exact;
786
0
        }
787
788
0
        *clcfp = NULL;
789
790
0
        ngx_queue_split(locations, regex, &tail);
791
0
    }
792
793
1
#endif
794
795
1
    return NGX_OK;
796
1
}
797
798
799
static ngx_int_t
800
ngx_http_init_static_location_trees(ngx_conf_t *cf,
801
    ngx_http_core_loc_conf_t *pclcf)
802
2
{
803
2
    ngx_queue_t                *q, *locations;
804
2
    ngx_http_core_loc_conf_t   *clcf;
805
2
    ngx_http_location_queue_t  *lq;
806
807
2
    locations = pclcf->locations;
808
809
2
    if (locations == NULL) {
810
1
        return NGX_OK;
811
1
    }
812
813
1
    if (ngx_queue_empty(locations)) {
814
0
        return NGX_OK;
815
0
    }
816
817
1
    for (q = ngx_queue_head(locations);
818
2
         q != ngx_queue_sentinel(locations);
819
1
         q = ngx_queue_next(q))
820
1
    {
821
1
        lq = (ngx_http_location_queue_t *) q;
822
823
1
        clcf = lq->exact ? lq->exact : lq->inclusive;
824
825
1
        if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
826
0
            return NGX_ERROR;
827
0
        }
828
1
    }
829
830
1
    if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
831
0
        return NGX_ERROR;
832
0
    }
833
834
1
    ngx_http_create_locations_list(locations, ngx_queue_head(locations));
835
836
1
    pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
837
1
    if (pclcf->static_locations == NULL) {
838
0
        return NGX_ERROR;
839
0
    }
840
841
1
    return NGX_OK;
842
1
}
843
844
845
ngx_int_t
846
ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations,
847
    ngx_http_core_loc_conf_t *clcf)
848
1
{
849
1
    ngx_http_location_queue_t  *lq;
850
851
1
    if (*locations == NULL) {
852
1
        *locations = ngx_palloc(cf->temp_pool,
853
1
                                sizeof(ngx_http_location_queue_t));
854
1
        if (*locations == NULL) {
855
0
            return NGX_ERROR;
856
0
        }
857
858
1
        ngx_queue_init(*locations);
859
1
    }
860
861
1
    lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
862
1
    if (lq == NULL) {
863
0
        return NGX_ERROR;
864
0
    }
865
866
1
    if (clcf->exact_match
867
1
#if (NGX_PCRE)
868
1
        || clcf->regex
869
1
#endif
870
1
        || clcf->named || clcf->noname)
871
0
    {
872
0
        lq->exact = clcf;
873
0
        lq->inclusive = NULL;
874
875
1
    } else {
876
1
        lq->exact = NULL;
877
1
        lq->inclusive = clcf;
878
1
    }
879
880
1
    lq->name = &clcf->name;
881
1
    lq->file_name = cf->conf_file->file.name.data;
882
1
    lq->line = cf->conf_file->line;
883
884
1
    ngx_queue_init(&lq->list);
885
886
1
    ngx_queue_insert_tail(*locations, &lq->queue);
887
888
1
    if (ngx_http_escape_location_name(cf, clcf) != NGX_OK) {
889
0
        return NGX_ERROR;
890
0
    }
891
892
1
    return NGX_OK;
893
1
}
894
895
896
static ngx_int_t
897
ngx_http_escape_location_name(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf)
898
1
{
899
1
    u_char     *p;
900
1
    size_t      len;
901
1
    uintptr_t   escape;
902
903
1
    escape = 2 * ngx_escape_uri(NULL, clcf->name.data, clcf->name.len,
904
1
                                NGX_ESCAPE_URI);
905
906
1
    if (escape) {
907
0
        len = clcf->name.len + escape;
908
909
0
        p = ngx_pnalloc(cf->pool, len);
910
0
        if (p == NULL) {
911
0
            return NGX_ERROR;
912
0
        }
913
914
0
        clcf->escaped_name.len = len;
915
0
        clcf->escaped_name.data = p;
916
917
0
        ngx_escape_uri(p, clcf->name.data, clcf->name.len, NGX_ESCAPE_URI);
918
919
1
    } else {
920
1
        clcf->escaped_name = clcf->name;
921
1
    }
922
923
1
    return NGX_OK;
924
1
}
925
926
927
static ngx_int_t
928
ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two)
929
0
{
930
0
    ngx_int_t                   rc;
931
0
    ngx_http_core_loc_conf_t   *first, *second;
932
0
    ngx_http_location_queue_t  *lq1, *lq2;
933
934
0
    lq1 = (ngx_http_location_queue_t *) one;
935
0
    lq2 = (ngx_http_location_queue_t *) two;
936
937
0
    first = lq1->exact ? lq1->exact : lq1->inclusive;
938
0
    second = lq2->exact ? lq2->exact : lq2->inclusive;
939
940
0
    if (first->noname && !second->noname) {
941
        /* shift no named locations to the end */
942
0
        return 1;
943
0
    }
944
945
0
    if (!first->noname && second->noname) {
946
        /* shift no named locations to the end */
947
0
        return -1;
948
0
    }
949
950
0
    if (first->noname || second->noname) {
951
        /* do not sort no named locations */
952
0
        return 0;
953
0
    }
954
955
0
    if (first->named && !second->named) {
956
        /* shift named locations to the end */
957
0
        return 1;
958
0
    }
959
960
0
    if (!first->named && second->named) {
961
        /* shift named locations to the end */
962
0
        return -1;
963
0
    }
964
965
0
    if (first->named && second->named) {
966
0
        return ngx_strcmp(first->name.data, second->name.data);
967
0
    }
968
969
0
#if (NGX_PCRE)
970
971
0
    if (first->regex && !second->regex) {
972
        /* shift the regex matches to the end */
973
0
        return 1;
974
0
    }
975
976
0
    if (!first->regex && second->regex) {
977
        /* shift the regex matches to the end */
978
0
        return -1;
979
0
    }
980
981
0
    if (first->regex || second->regex) {
982
        /* do not sort the regex matches */
983
0
        return 0;
984
0
    }
985
986
0
#endif
987
988
0
    rc = ngx_filename_cmp(first->name.data, second->name.data,
989
0
                          ngx_min(first->name.len, second->name.len) + 1);
990
991
0
    if (rc == 0 && !first->exact_match && second->exact_match) {
992
        /* an exact match must be before the same inclusive one */
993
0
        return 1;
994
0
    }
995
996
0
    return rc;
997
0
}
998
999
1000
static ngx_int_t
1001
ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations)
1002
1
{
1003
1
    ngx_queue_t                *q, *x;
1004
1
    ngx_http_location_queue_t  *lq, *lx;
1005
1006
1
    q = ngx_queue_head(locations);
1007
1008
1
    while (q != ngx_queue_last(locations)) {
1009
1010
0
        x = ngx_queue_next(q);
1011
1012
0
        lq = (ngx_http_location_queue_t *) q;
1013
0
        lx = (ngx_http_location_queue_t *) x;
1014
1015
0
        if (lq->name->len == lx->name->len
1016
0
            && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len)
1017
0
               == 0)
1018
0
        {
1019
0
            if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) {
1020
0
                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1021
0
                              "duplicate location \"%V\" in %s:%ui",
1022
0
                              lx->name, lx->file_name, lx->line);
1023
1024
0
                return NGX_ERROR;
1025
0
            }
1026
1027
0
            lq->inclusive = lx->inclusive;
1028
1029
0
            ngx_queue_remove(x);
1030
1031
0
            continue;
1032
0
        }
1033
1034
0
        q = ngx_queue_next(q);
1035
0
    }
1036
1037
1
    return NGX_OK;
1038
1
}
1039
1040
1041
static void
1042
ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q)
1043
1
{
1044
1
    u_char                     *name;
1045
1
    size_t                      len;
1046
1
    ngx_queue_t                *x, tail;
1047
1
    ngx_http_location_queue_t  *lq, *lx;
1048
1049
1
    if (q == ngx_queue_last(locations)) {
1050
1
        return;
1051
1
    }
1052
1053
0
    lq = (ngx_http_location_queue_t *) q;
1054
1055
0
    if (lq->inclusive == NULL) {
1056
0
        ngx_http_create_locations_list(locations, ngx_queue_next(q));
1057
0
        return;
1058
0
    }
1059
1060
0
    len = lq->name->len;
1061
0
    name = lq->name->data;
1062
1063
0
    for (x = ngx_queue_next(q);
1064
0
         x != ngx_queue_sentinel(locations);
1065
0
         x = ngx_queue_next(x))
1066
0
    {
1067
0
        lx = (ngx_http_location_queue_t *) x;
1068
1069
0
        if (len > lx->name->len
1070
0
            || ngx_filename_cmp(name, lx->name->data, len) != 0)
1071
0
        {
1072
0
            break;
1073
0
        }
1074
0
    }
1075
1076
0
    q = ngx_queue_next(q);
1077
1078
0
    if (q == x) {
1079
0
        ngx_http_create_locations_list(locations, x);
1080
0
        return;
1081
0
    }
1082
1083
0
    ngx_queue_split(locations, q, &tail);
1084
0
    ngx_queue_add(&lq->list, &tail);
1085
1086
0
    if (x == ngx_queue_sentinel(locations)) {
1087
0
        ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1088
0
        return;
1089
0
    }
1090
1091
0
    ngx_queue_split(&lq->list, x, &tail);
1092
0
    ngx_queue_add(locations, &tail);
1093
1094
0
    ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1095
1096
0
    ngx_http_create_locations_list(locations, x);
1097
0
}
1098
1099
1100
/*
1101
 * to keep cache locality for left leaf nodes, allocate nodes in following
1102
 * order: node, left subtree, right subtree, inclusive subtree
1103
 */
1104
1105
static ngx_http_location_tree_node_t *
1106
ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations,
1107
    size_t prefix)
1108
1
{
1109
1
    size_t                          len;
1110
1
    ngx_queue_t                    *q, tail;
1111
1
    ngx_http_location_queue_t      *lq;
1112
1
    ngx_http_location_tree_node_t  *node;
1113
1114
1
    q = ngx_queue_middle(locations);
1115
1116
1
    lq = (ngx_http_location_queue_t *) q;
1117
1
    len = lq->name->len - prefix;
1118
1119
1
    node = ngx_palloc(cf->pool,
1120
1
                      offsetof(ngx_http_location_tree_node_t, name) + len);
1121
1
    if (node == NULL) {
1122
0
        return NULL;
1123
0
    }
1124
1125
1
    node->left = NULL;
1126
1
    node->right = NULL;
1127
1
    node->tree = NULL;
1128
1
    node->exact = lq->exact;
1129
1
    node->inclusive = lq->inclusive;
1130
1131
1
    node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect)
1132
1
                           || (lq->inclusive && lq->inclusive->auto_redirect));
1133
1134
1
    node->len = (u_short) len;
1135
1
    ngx_memcpy(node->name, &lq->name->data[prefix], len);
1136
1137
1
    ngx_queue_split(locations, q, &tail);
1138
1139
1
    if (ngx_queue_empty(locations)) {
1140
        /*
1141
         * ngx_queue_split() insures that if left part is empty,
1142
         * then right one is empty too
1143
         */
1144
1
        goto inclusive;
1145
1
    }
1146
1147
0
    node->left = ngx_http_create_locations_tree(cf, locations, prefix);
1148
0
    if (node->left == NULL) {
1149
0
        return NULL;
1150
0
    }
1151
1152
0
    ngx_queue_remove(q);
1153
1154
0
    if (ngx_queue_empty(&tail)) {
1155
0
        goto inclusive;
1156
0
    }
1157
1158
0
    node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1159
0
    if (node->right == NULL) {
1160
0
        return NULL;
1161
0
    }
1162
1163
1
inclusive:
1164
1165
1
    if (ngx_queue_empty(&lq->list)) {
1166
1
        return node;
1167
1
    }
1168
1169
0
    node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1170
0
    if (node->tree == NULL) {
1171
0
        return NULL;
1172
0
    }
1173
1174
0
    return node;
1175
0
}
1176
1177
1178
ngx_int_t
1179
ngx_http_add_listen(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1180
    ngx_http_listen_opt_t *lsopt)
1181
1
{
1182
1
    in_port_t                   p;
1183
1
    ngx_uint_t                  i;
1184
1
    struct sockaddr            *sa;
1185
1
    ngx_http_conf_port_t       *port;
1186
1
    ngx_http_core_main_conf_t  *cmcf;
1187
1188
1
    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1189
1190
1
    if (cmcf->ports == NULL) {
1191
1
        cmcf->ports = ngx_array_create(cf->temp_pool, 2,
1192
1
                                       sizeof(ngx_http_conf_port_t));
1193
1
        if (cmcf->ports == NULL) {
1194
0
            return NGX_ERROR;
1195
0
        }
1196
1
    }
1197
1198
1
    sa = lsopt->sockaddr;
1199
1
    p = ngx_inet_get_port(sa);
1200
1201
1
    port = cmcf->ports->elts;
1202
1
    for (i = 0; i < cmcf->ports->nelts; i++) {
1203
1204
0
        if (p != port[i].port
1205
0
            || lsopt->type != port[i].type
1206
0
            || sa->sa_family != port[i].family)
1207
0
        {
1208
0
            continue;
1209
0
        }
1210
1211
        /* a port is already in the port list */
1212
1213
0
        return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
1214
0
    }
1215
1216
    /* add a port to the port list */
1217
1218
1
    port = ngx_array_push(cmcf->ports);
1219
1
    if (port == NULL) {
1220
0
        return NGX_ERROR;
1221
0
    }
1222
1223
1
    port->family = sa->sa_family;
1224
1
    port->type = lsopt->type;
1225
1
    port->port = p;
1226
1
    port->addrs.elts = NULL;
1227
1228
1
    return ngx_http_add_address(cf, cscf, port, lsopt);
1229
1
}
1230
1231
1232
static ngx_int_t
1233
ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1234
    ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
1235
0
{
1236
0
    ngx_uint_t             i, default_server, proxy_protocol,
1237
0
                           protocols, protocols_prev;
1238
0
    ngx_http_conf_addr_t  *addr;
1239
#if (NGX_HTTP_SSL)
1240
    ngx_uint_t             ssl;
1241
#endif
1242
0
#if (NGX_HTTP_V2)
1243
0
    ngx_uint_t             http2;
1244
0
#endif
1245
#if (NGX_HTTP_V3)
1246
    ngx_uint_t             quic;
1247
#endif
1248
1249
    /*
1250
     * we cannot compare whole sockaddr struct's as kernel
1251
     * may fill some fields in inherited sockaddr struct's
1252
     */
1253
1254
0
    addr = port->addrs.elts;
1255
1256
0
    for (i = 0; i < port->addrs.nelts; i++) {
1257
1258
0
        if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen,
1259
0
                             addr[i].opt.sockaddr,
1260
0
                             addr[i].opt.socklen, 0)
1261
0
            != NGX_OK)
1262
0
        {
1263
0
            continue;
1264
0
        }
1265
1266
        /* the address is already in the address list */
1267
1268
0
        if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
1269
0
            return NGX_ERROR;
1270
0
        }
1271
1272
        /* preserve default_server bit during listen options overwriting */
1273
0
        default_server = addr[i].opt.default_server;
1274
1275
0
        proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
1276
0
        protocols = lsopt->proxy_protocol;
1277
0
        protocols_prev = addr[i].opt.proxy_protocol;
1278
1279
#if (NGX_HTTP_SSL)
1280
        ssl = lsopt->ssl || addr[i].opt.ssl;
1281
        protocols |= lsopt->ssl << 1;
1282
        protocols_prev |= addr[i].opt.ssl << 1;
1283
#endif
1284
0
#if (NGX_HTTP_V2)
1285
0
        http2 = lsopt->http2 || addr[i].opt.http2;
1286
0
        protocols |= lsopt->http2 << 2;
1287
0
        protocols_prev |= addr[i].opt.http2 << 2;
1288
0
#endif
1289
#if (NGX_HTTP_V3)
1290
        quic = lsopt->quic || addr[i].opt.quic;
1291
#endif
1292
1293
0
        if (lsopt->set) {
1294
1295
0
            if (addr[i].opt.set) {
1296
0
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1297
0
                                   "duplicate listen options for %V",
1298
0
                                   &addr[i].opt.addr_text);
1299
0
                return NGX_ERROR;
1300
0
            }
1301
1302
0
            addr[i].opt = *lsopt;
1303
0
        }
1304
1305
        /* check the duplicate "default" server for this address:port */
1306
1307
0
        if (lsopt->default_server) {
1308
1309
0
            if (default_server) {
1310
0
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1311
0
                                   "a duplicate default server for %V",
1312
0
                                   &addr[i].opt.addr_text);
1313
0
                return NGX_ERROR;
1314
0
            }
1315
1316
0
            default_server = 1;
1317
0
            addr[i].default_server = cscf;
1318
0
        }
1319
1320
        /* check for conflicting protocol options */
1321
1322
0
        if ((protocols | protocols_prev) != protocols_prev) {
1323
1324
            /* options added */
1325
1326
0
            if ((addr[i].opt.set && !lsopt->set)
1327
0
                || addr[i].protocols_changed
1328
0
                || (protocols | protocols_prev) != protocols)
1329
0
            {
1330
0
                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1331
0
                                   "protocol options redefined for %V",
1332
0
                                   &addr[i].opt.addr_text);
1333
0
            }
1334
1335
0
            addr[i].protocols = protocols_prev;
1336
0
            addr[i].protocols_set = 1;
1337
0
            addr[i].protocols_changed = 1;
1338
1339
0
        } else if ((protocols_prev | protocols) != protocols) {
1340
1341
            /* options removed */
1342
1343
0
            if (lsopt->set
1344
0
                || (addr[i].protocols_set && protocols != addr[i].protocols))
1345
0
            {
1346
0
                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1347
0
                                   "protocol options redefined for %V",
1348
0
                                   &addr[i].opt.addr_text);
1349
0
            }
1350
1351
0
            addr[i].protocols = protocols;
1352
0
            addr[i].protocols_set = 1;
1353
0
            addr[i].protocols_changed = 1;
1354
1355
0
        } else {
1356
1357
            /* the same options */
1358
1359
0
            if ((lsopt->set && addr[i].protocols_changed)
1360
0
                || (addr[i].protocols_set && protocols != addr[i].protocols))
1361
0
            {
1362
0
                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1363
0
                                   "protocol options redefined for %V",
1364
0
                                   &addr[i].opt.addr_text);
1365
0
            }
1366
1367
0
            addr[i].protocols = protocols;
1368
0
            addr[i].protocols_set = 1;
1369
0
        }
1370
1371
0
        addr[i].opt.default_server = default_server;
1372
0
        addr[i].opt.proxy_protocol = proxy_protocol;
1373
#if (NGX_HTTP_SSL)
1374
        addr[i].opt.ssl = ssl;
1375
#endif
1376
0
#if (NGX_HTTP_V2)
1377
0
        addr[i].opt.http2 = http2;
1378
0
#endif
1379
#if (NGX_HTTP_V3)
1380
        addr[i].opt.quic = quic;
1381
#endif
1382
1383
0
        return NGX_OK;
1384
0
    }
1385
1386
    /* add the address to the addresses list that bound to this port */
1387
1388
0
    return ngx_http_add_address(cf, cscf, port, lsopt);
1389
0
}
1390
1391
1392
/*
1393
 * add the server address, the server names and the server core module
1394
 * configurations to the port list
1395
 */
1396
1397
static ngx_int_t
1398
ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1399
    ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
1400
1
{
1401
1
    ngx_http_conf_addr_t  *addr;
1402
1403
1
    if (port->addrs.elts == NULL) {
1404
1
        if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1405
1
                           sizeof(ngx_http_conf_addr_t))
1406
1
            != NGX_OK)
1407
0
        {
1408
0
            return NGX_ERROR;
1409
0
        }
1410
1
    }
1411
1412
#if (NGX_HTTP_V2 && NGX_HTTP_SSL                                              \
1413
     && !defined TLSEXT_TYPE_application_layer_protocol_negotiation)
1414
1415
    if (lsopt->http2 && lsopt->ssl) {
1416
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1417
                           "nginx was built with OpenSSL that lacks ALPN "
1418
                           "support, HTTP/2 is not enabled for %V",
1419
                           &lsopt->addr_text);
1420
    }
1421
1422
#endif
1423
1424
1
    addr = ngx_array_push(&port->addrs);
1425
1
    if (addr == NULL) {
1426
0
        return NGX_ERROR;
1427
0
    }
1428
1429
1
    addr->opt = *lsopt;
1430
1
    addr->protocols = 0;
1431
1
    addr->protocols_set = 0;
1432
1
    addr->protocols_changed = 0;
1433
1
    addr->hash.buckets = NULL;
1434
1
    addr->hash.size = 0;
1435
1
    addr->wc_head = NULL;
1436
1
    addr->wc_tail = NULL;
1437
1
#if (NGX_PCRE)
1438
1
    addr->nregex = 0;
1439
1
    addr->regex = NULL;
1440
1
#endif
1441
1
    addr->default_server = cscf;
1442
1
    addr->servers.elts = NULL;
1443
1444
1
    return ngx_http_add_server(cf, cscf, addr);
1445
1
}
1446
1447
1448
/* add the server core module configuration to the address:port */
1449
1450
static ngx_int_t
1451
ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1452
    ngx_http_conf_addr_t *addr)
1453
1
{
1454
1
    ngx_uint_t                  i;
1455
1
    ngx_http_core_srv_conf_t  **server;
1456
1457
1
    if (addr->servers.elts == NULL) {
1458
1
        if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
1459
1
                           sizeof(ngx_http_core_srv_conf_t *))
1460
1
            != NGX_OK)
1461
0
        {
1462
0
            return NGX_ERROR;
1463
0
        }
1464
1465
1
    } else {
1466
0
        server = addr->servers.elts;
1467
0
        for (i = 0; i < addr->servers.nelts; i++) {
1468
0
            if (server[i] == cscf) {
1469
0
                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1470
0
                                   "a duplicate listen %V",
1471
0
                                   &addr->opt.addr_text);
1472
0
                return NGX_ERROR;
1473
0
            }
1474
0
        }
1475
0
    }
1476
1477
1
    server = ngx_array_push(&addr->servers);
1478
1
    if (server == NULL) {
1479
0
        return NGX_ERROR;
1480
0
    }
1481
1482
1
    *server = cscf;
1483
1484
1
    return NGX_OK;
1485
1
}
1486
1487
1488
static ngx_int_t
1489
ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1490
    ngx_array_t *ports)
1491
1
{
1492
1
    ngx_uint_t             p, a;
1493
1
    ngx_http_conf_port_t  *port;
1494
1
    ngx_http_conf_addr_t  *addr;
1495
1496
1
    if (ports == NULL) {
1497
0
        return NGX_OK;
1498
0
    }
1499
1500
1
    port = ports->elts;
1501
2
    for (p = 0; p < ports->nelts; p++) {
1502
1503
1
        ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1504
1
                 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
1505
1506
        /*
1507
         * check whether all name-based servers have the same
1508
         * configuration as a default server for given address:port
1509
         */
1510
1511
1
        addr = port[p].addrs.elts;
1512
2
        for (a = 0; a < port[p].addrs.nelts; a++) {
1513
1514
1
            if (addr[a].servers.nelts > 1
1515
1
#if (NGX_PCRE)
1516
1
                || addr[a].default_server->captures
1517
1
#endif
1518
1
               )
1519
1
            {
1520
1
                if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
1521
0
                    return NGX_ERROR;
1522
0
                }
1523
1
            }
1524
1
        }
1525
1526
1
        if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
1527
0
            return NGX_ERROR;
1528
0
        }
1529
1
    }
1530
1531
1
    return NGX_OK;
1532
1
}
1533
1534
1535
static ngx_int_t
1536
ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1537
    ngx_http_conf_addr_t *addr)
1538
1
{
1539
1
    ngx_int_t                   rc;
1540
1
    ngx_uint_t                  n, s;
1541
1
    ngx_hash_init_t             hash;
1542
1
    ngx_hash_keys_arrays_t      ha;
1543
1
    ngx_http_server_name_t     *name;
1544
1
    ngx_http_core_srv_conf_t  **cscfp;
1545
1
#if (NGX_PCRE)
1546
1
    ngx_uint_t                  regex, i;
1547
1548
1
    regex = 0;
1549
1
#endif
1550
1551
1
    ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1552
1553
1
    ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
1554
1
    if (ha.temp_pool == NULL) {
1555
0
        return NGX_ERROR;
1556
0
    }
1557
1558
1
    ha.pool = cf->pool;
1559
1560
1
    if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1561
0
        goto failed;
1562
0
    }
1563
1564
1
    cscfp = addr->servers.elts;
1565
1566
2
    for (s = 0; s < addr->servers.nelts; s++) {
1567
1568
1
        name = cscfp[s]->server_names.elts;
1569
1570
2
        for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1571
1572
1
#if (NGX_PCRE)
1573
1
            if (name[n].regex) {
1574
1
                regex++;
1575
1
                continue;
1576
1
            }
1577
0
#endif
1578
1579
0
            rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
1580
0
                                  NGX_HASH_WILDCARD_KEY);
1581
1582
0
            if (rc == NGX_ERROR) {
1583
0
                goto failed;
1584
0
            }
1585
1586
0
            if (rc == NGX_DECLINED) {
1587
0
                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1588
0
                              "invalid server name or wildcard \"%V\" on %V",
1589
0
                              &name[n].name, &addr->opt.addr_text);
1590
0
                goto failed;
1591
0
            }
1592
1593
0
            if (rc == NGX_BUSY) {
1594
0
                ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1595
0
                              "conflicting server name \"%V\" on %V, ignored",
1596
0
                              &name[n].name, &addr->opt.addr_text);
1597
0
            }
1598
0
        }
1599
1
    }
1600
1601
1
    hash.key = ngx_hash_key_lc;
1602
1
    hash.max_size = cmcf->server_names_hash_max_size;
1603
1
    hash.bucket_size = cmcf->server_names_hash_bucket_size;
1604
1
    hash.name = "server_names_hash";
1605
1
    hash.pool = cf->pool;
1606
1607
1
    if (ha.keys.nelts) {
1608
0
        hash.hash = &addr->hash;
1609
0
        hash.temp_pool = NULL;
1610
1611
0
        if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1612
0
            goto failed;
1613
0
        }
1614
0
    }
1615
1616
1
    if (ha.dns_wc_head.nelts) {
1617
1618
0
        ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1619
0
                  sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1620
1621
0
        hash.hash = NULL;
1622
0
        hash.temp_pool = ha.temp_pool;
1623
1624
0
        if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1625
0
                                   ha.dns_wc_head.nelts)
1626
0
            != NGX_OK)
1627
0
        {
1628
0
            goto failed;
1629
0
        }
1630
1631
0
        addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
1632
0
    }
1633
1634
1
    if (ha.dns_wc_tail.nelts) {
1635
1636
0
        ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1637
0
                  sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1638
1639
0
        hash.hash = NULL;
1640
0
        hash.temp_pool = ha.temp_pool;
1641
1642
0
        if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1643
0
                                   ha.dns_wc_tail.nelts)
1644
0
            != NGX_OK)
1645
0
        {
1646
0
            goto failed;
1647
0
        }
1648
1649
0
        addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1650
0
    }
1651
1652
1
    ngx_destroy_pool(ha.temp_pool);
1653
1654
1
#if (NGX_PCRE)
1655
1656
1
    if (regex == 0) {
1657
0
        return NGX_OK;
1658
0
    }
1659
1660
1
    addr->nregex = regex;
1661
1
    addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1662
1
    if (addr->regex == NULL) {
1663
0
        return NGX_ERROR;
1664
0
    }
1665
1666
1
    i = 0;
1667
1668
2
    for (s = 0; s < addr->servers.nelts; s++) {
1669
1670
1
        name = cscfp[s]->server_names.elts;
1671
1672
2
        for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1673
1
            if (name[n].regex) {
1674
1
                addr->regex[i++] = name[n];
1675
1
            }
1676
1
        }
1677
1
    }
1678
1679
1
#endif
1680
1681
1
    return NGX_OK;
1682
1683
0
failed:
1684
1685
0
    ngx_destroy_pool(ha.temp_pool);
1686
1687
0
    return NGX_ERROR;
1688
1
}
1689
1690
1691
static ngx_int_t
1692
ngx_http_cmp_conf_addrs(const void *one, const void *two)
1693
0
{
1694
0
    ngx_http_conf_addr_t  *first, *second;
1695
1696
0
    first = (ngx_http_conf_addr_t *) one;
1697
0
    second = (ngx_http_conf_addr_t *) two;
1698
1699
0
    if (first->opt.wildcard) {
1700
        /* a wildcard address must be the last resort, shift it to the end */
1701
0
        return 1;
1702
0
    }
1703
1704
0
    if (second->opt.wildcard) {
1705
        /* a wildcard address must be the last resort, shift it to the end */
1706
0
        return -1;
1707
0
    }
1708
1709
0
    if (first->opt.bind && !second->opt.bind) {
1710
        /* shift explicit bind()ed addresses to the start */
1711
0
        return -1;
1712
0
    }
1713
1714
0
    if (!first->opt.bind && second->opt.bind) {
1715
        /* shift explicit bind()ed addresses to the start */
1716
0
        return 1;
1717
0
    }
1718
1719
    /* do not sort by default */
1720
1721
0
    return 0;
1722
0
}
1723
1724
1725
static int ngx_libc_cdecl
1726
ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1727
0
{
1728
0
    ngx_hash_key_t  *first, *second;
1729
1730
0
    first = (ngx_hash_key_t *) one;
1731
0
    second = (ngx_hash_key_t *) two;
1732
1733
0
    return ngx_dns_strcmp(first->key.data, second->key.data);
1734
0
}
1735
1736
1737
static ngx_int_t
1738
ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
1739
1
{
1740
1
    ngx_uint_t                 i, last, bind_wildcard;
1741
1
    ngx_listening_t           *ls;
1742
1
    ngx_http_port_t           *hport;
1743
1
    ngx_http_conf_addr_t      *addr;
1744
1745
1
    addr = port->addrs.elts;
1746
1
    last = port->addrs.nelts;
1747
1748
    /*
1749
     * If there is a binding to an "*:port" then we need to bind() to
1750
     * the "*:port" only and ignore other implicit bindings.  The bindings
1751
     * have been already sorted: explicit bindings are on the start, then
1752
     * implicit bindings go, and wildcard binding is in the end.
1753
     */
1754
1755
1
    if (addr[last - 1].opt.wildcard) {
1756
0
        addr[last - 1].opt.bind = 1;
1757
0
        bind_wildcard = 1;
1758
1759
1
    } else {
1760
1
        bind_wildcard = 0;
1761
1
    }
1762
1763
1
    i = 0;
1764
1765
2
    while (i < last) {
1766
1767
1
        if (bind_wildcard && !addr[i].opt.bind) {
1768
0
            i++;
1769
0
            continue;
1770
0
        }
1771
1772
1
        ls = ngx_http_add_listening(cf, &addr[i]);
1773
1
        if (ls == NULL) {
1774
0
            return NGX_ERROR;
1775
0
        }
1776
1777
1
        hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1778
1
        if (hport == NULL) {
1779
0
            return NGX_ERROR;
1780
0
        }
1781
1782
1
        ls->servers = hport;
1783
1784
1
        hport->naddrs = i + 1;
1785
1786
1
        switch (ls->sockaddr->sa_family) {
1787
1788
0
#if (NGX_HAVE_INET6)
1789
0
        case AF_INET6:
1790
0
            if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
1791
0
                return NGX_ERROR;
1792
0
            }
1793
0
            break;
1794
0
#endif
1795
1
        default: /* AF_INET */
1796
1
            if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1797
0
                return NGX_ERROR;
1798
0
            }
1799
1
            break;
1800
1
        }
1801
1802
1
        addr++;
1803
1
        last--;
1804
1
    }
1805
1806
1
    return NGX_OK;
1807
1
}
1808
1809
1810
static ngx_listening_t *
1811
ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1812
1
{
1813
1
    ngx_listening_t           *ls;
1814
1
    ngx_http_core_loc_conf_t  *clcf;
1815
1
    ngx_http_core_srv_conf_t  *cscf;
1816
1817
1
    ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
1818
1
    if (ls == NULL) {
1819
0
        return NULL;
1820
0
    }
1821
1822
1
    ls->addr_ntop = 1;
1823
1824
1
    ls->handler = ngx_http_init_connection;
1825
1826
1
    cscf = addr->default_server;
1827
1
    ls->pool_size = cscf->connection_pool_size;
1828
1829
1
    clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1830
1831
1
    ls->logp = clcf->error_log;
1832
1
    ls->log.data = &ls->addr_text;
1833
1
    ls->log.handler = ngx_accept_log_error;
1834
1835
#if (NGX_WIN32)
1836
    {
1837
    ngx_iocp_conf_t  *iocpcf = NULL;
1838
1839
    if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
1840
        iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1841
    }
1842
    if (iocpcf && iocpcf->acceptex_read) {
1843
        ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1844
    }
1845
    }
1846
#endif
1847
1848
1
    ls->type = addr->opt.type;
1849
1
    ls->protocol = addr->opt.protocol;
1850
1
    ls->backlog = addr->opt.backlog;
1851
1
    ls->rcvbuf = addr->opt.rcvbuf;
1852
1
    ls->sndbuf = addr->opt.sndbuf;
1853
1854
1
    ls->keepalive = addr->opt.so_keepalive;
1855
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
1856
    ls->keepidle = addr->opt.tcp_keepidle;
1857
    ls->keepintvl = addr->opt.tcp_keepintvl;
1858
    ls->keepcnt = addr->opt.tcp_keepcnt;
1859
#endif
1860
1861
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1862
    ls->accept_filter = addr->opt.accept_filter;
1863
#endif
1864
1865
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1866
    ls->deferred_accept = addr->opt.deferred_accept;
1867
#endif
1868
1869
1
#if (NGX_HAVE_INET6)
1870
1
    ls->ipv6only = addr->opt.ipv6only;
1871
1
#endif
1872
1873
#if (NGX_HAVE_SETFIB)
1874
    ls->setfib = addr->opt.setfib;
1875
#endif
1876
1877
#if (NGX_HAVE_TCP_FASTOPEN)
1878
    ls->fastopen = addr->opt.fastopen;
1879
#endif
1880
1881
#if (NGX_HAVE_REUSEPORT)
1882
    ls->reuseport = addr->opt.reuseport;
1883
#endif
1884
1885
1
    ls->wildcard = addr->opt.wildcard;
1886
1887
#if (NGX_HTTP_V3)
1888
    ls->quic = addr->opt.quic;
1889
#endif
1890
1891
1
    return ls;
1892
1
}
1893
1894
1895
static ngx_int_t
1896
ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1897
    ngx_http_conf_addr_t *addr)
1898
1
{
1899
1
    ngx_uint_t                 i;
1900
1
    ngx_http_in_addr_t        *addrs;
1901
1
    struct sockaddr_in        *sin;
1902
1
    ngx_http_virtual_names_t  *vn;
1903
1904
1
    hport->addrs = ngx_pcalloc(cf->pool,
1905
1
                               hport->naddrs * sizeof(ngx_http_in_addr_t));
1906
1
    if (hport->addrs == NULL) {
1907
0
        return NGX_ERROR;
1908
0
    }
1909
1910
1
    addrs = hport->addrs;
1911
1912
2
    for (i = 0; i < hport->naddrs; i++) {
1913
1914
1
        sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
1915
1
        addrs[i].addr = sin->sin_addr.s_addr;
1916
1
        addrs[i].conf.default_server = addr[i].default_server;
1917
#if (NGX_HTTP_SSL)
1918
        addrs[i].conf.ssl = addr[i].opt.ssl;
1919
#endif
1920
1
#if (NGX_HTTP_V2)
1921
1
        addrs[i].conf.http2 = addr[i].opt.http2;
1922
1
#endif
1923
#if (NGX_HTTP_V3)
1924
        addrs[i].conf.quic = addr[i].opt.quic;
1925
#endif
1926
1
        addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
1927
1928
1
        if (addr[i].hash.buckets == NULL
1929
1
            && (addr[i].wc_head == NULL
1930
0
                || addr[i].wc_head->hash.buckets == NULL)
1931
1
            && (addr[i].wc_tail == NULL
1932
0
                || addr[i].wc_tail->hash.buckets == NULL)
1933
1
#if (NGX_PCRE)
1934
1
            && addr[i].nregex == 0
1935
1
#endif
1936
1
            )
1937
0
        {
1938
0
            continue;
1939
0
        }
1940
1941
1
        vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1942
1
        if (vn == NULL) {
1943
0
            return NGX_ERROR;
1944
0
        }
1945
1946
1
        addrs[i].conf.virtual_names = vn;
1947
1948
1
        vn->names.hash = addr[i].hash;
1949
1
        vn->names.wc_head = addr[i].wc_head;
1950
1
        vn->names.wc_tail = addr[i].wc_tail;
1951
1
#if (NGX_PCRE)
1952
1
        vn->nregex = addr[i].nregex;
1953
1
        vn->regex = addr[i].regex;
1954
1
#endif
1955
1
    }
1956
1957
1
    return NGX_OK;
1958
1
}
1959
1960
1961
#if (NGX_HAVE_INET6)
1962
1963
static ngx_int_t
1964
ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1965
    ngx_http_conf_addr_t *addr)
1966
0
{
1967
0
    ngx_uint_t                 i;
1968
0
    ngx_http_in6_addr_t       *addrs6;
1969
0
    struct sockaddr_in6       *sin6;
1970
0
    ngx_http_virtual_names_t  *vn;
1971
1972
0
    hport->addrs = ngx_pcalloc(cf->pool,
1973
0
                               hport->naddrs * sizeof(ngx_http_in6_addr_t));
1974
0
    if (hport->addrs == NULL) {
1975
0
        return NGX_ERROR;
1976
0
    }
1977
1978
0
    addrs6 = hport->addrs;
1979
1980
0
    for (i = 0; i < hport->naddrs; i++) {
1981
1982
0
        sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
1983
0
        addrs6[i].addr6 = sin6->sin6_addr;
1984
0
        addrs6[i].conf.default_server = addr[i].default_server;
1985
#if (NGX_HTTP_SSL)
1986
        addrs6[i].conf.ssl = addr[i].opt.ssl;
1987
#endif
1988
0
#if (NGX_HTTP_V2)
1989
0
        addrs6[i].conf.http2 = addr[i].opt.http2;
1990
0
#endif
1991
#if (NGX_HTTP_V3)
1992
        addrs6[i].conf.quic = addr[i].opt.quic;
1993
#endif
1994
0
        addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
1995
1996
0
        if (addr[i].hash.buckets == NULL
1997
0
            && (addr[i].wc_head == NULL
1998
0
                || addr[i].wc_head->hash.buckets == NULL)
1999
0
            && (addr[i].wc_tail == NULL
2000
0
                || addr[i].wc_tail->hash.buckets == NULL)
2001
0
#if (NGX_PCRE)
2002
0
            && addr[i].nregex == 0
2003
0
#endif
2004
0
            )
2005
0
        {
2006
0
            continue;
2007
0
        }
2008
2009
0
        vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
2010
0
        if (vn == NULL) {
2011
0
            return NGX_ERROR;
2012
0
        }
2013
2014
0
        addrs6[i].conf.virtual_names = vn;
2015
2016
0
        vn->names.hash = addr[i].hash;
2017
0
        vn->names.wc_head = addr[i].wc_head;
2018
0
        vn->names.wc_tail = addr[i].wc_tail;
2019
0
#if (NGX_PCRE)
2020
0
        vn->nregex = addr[i].nregex;
2021
0
        vn->regex = addr[i].regex;
2022
0
#endif
2023
0
    }
2024
2025
0
    return NGX_OK;
2026
0
}
2027
2028
#endif
2029
2030
2031
char *
2032
ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2033
0
{
2034
0
    char  *p = conf;
2035
2036
0
    ngx_array_t     **types;
2037
0
    ngx_str_t        *value, *default_type;
2038
0
    ngx_uint_t        i, n, hash;
2039
0
    ngx_hash_key_t   *type;
2040
2041
0
    types = (ngx_array_t **) (p + cmd->offset);
2042
2043
0
    if (*types == (void *) -1) {
2044
0
        return NGX_CONF_OK;
2045
0
    }
2046
2047
0
    default_type = cmd->post;
2048
2049
0
    if (*types == NULL) {
2050
0
        *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2051
0
        if (*types == NULL) {
2052
0
            return NGX_CONF_ERROR;
2053
0
        }
2054
2055
0
        if (default_type) {
2056
0
            type = ngx_array_push(*types);
2057
0
            if (type == NULL) {
2058
0
                return NGX_CONF_ERROR;
2059
0
            }
2060
2061
0
            type->key = *default_type;
2062
0
            type->key_hash = ngx_hash_key(default_type->data,
2063
0
                                          default_type->len);
2064
0
            type->value = (void *) 4;
2065
0
        }
2066
0
    }
2067
2068
0
    value = cf->args->elts;
2069
2070
0
    for (i = 1; i < cf->args->nelts; i++) {
2071
2072
0
        if (value[i].len == 1 && value[i].data[0] == '*') {
2073
0
            *types = (void *) -1;
2074
0
            return NGX_CONF_OK;
2075
0
        }
2076
2077
0
        hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2078
0
        value[i].data[value[i].len] = '\0';
2079
2080
0
        type = (*types)->elts;
2081
0
        for (n = 0; n < (*types)->nelts; n++) {
2082
2083
0
            if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2084
0
                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2085
0
                                   "duplicate MIME type \"%V\"", &value[i]);
2086
0
                goto next;
2087
0
            }
2088
0
        }
2089
2090
0
        type = ngx_array_push(*types);
2091
0
        if (type == NULL) {
2092
0
            return NGX_CONF_ERROR;
2093
0
        }
2094
2095
0
        type->key = value[i];
2096
0
        type->key_hash = hash;
2097
0
        type->value = (void *) 4;
2098
2099
0
    next:
2100
2101
0
        continue;
2102
0
    }
2103
2104
0
    return NGX_CONF_OK;
2105
0
}
2106
2107
2108
char *
2109
ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
2110
    ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
2111
    ngx_str_t *default_types)
2112
6
{
2113
6
    ngx_hash_init_t  hash;
2114
2115
6
    if (*keys) {
2116
2117
0
        if (*keys == (void *) -1) {
2118
0
            return NGX_CONF_OK;
2119
0
        }
2120
2121
0
        hash.hash = types_hash;
2122
0
        hash.key = NULL;
2123
0
        hash.max_size = 2048;
2124
0
        hash.bucket_size = 64;
2125
0
        hash.name = "test_types_hash";
2126
0
        hash.pool = cf->pool;
2127
0
        hash.temp_pool = NULL;
2128
2129
0
        if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
2130
0
            return NGX_CONF_ERROR;
2131
0
        }
2132
2133
0
        return NGX_CONF_OK;
2134
0
    }
2135
2136
6
    if (prev_types_hash->buckets == NULL) {
2137
2138
3
        if (*prev_keys == NULL) {
2139
2140
3
            if (ngx_http_set_default_types(cf, prev_keys, default_types)
2141
3
                != NGX_OK)
2142
0
            {
2143
0
                return NGX_CONF_ERROR;
2144
0
            }
2145
2146
3
        } else if (*prev_keys == (void *) -1) {
2147
0
            *keys = *prev_keys;
2148
0
            return NGX_CONF_OK;
2149
0
        }
2150
2151
3
        hash.hash = prev_types_hash;
2152
3
        hash.key = NULL;
2153
3
        hash.max_size = 2048;
2154
3
        hash.bucket_size = 64;
2155
3
        hash.name = "test_types_hash";
2156
3
        hash.pool = cf->pool;
2157
3
        hash.temp_pool = NULL;
2158
2159
3
        if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
2160
3
            != NGX_OK)
2161
0
        {
2162
0
            return NGX_CONF_ERROR;
2163
0
        }
2164
3
    }
2165
2166
6
    *types_hash = *prev_types_hash;
2167
2168
6
    return NGX_CONF_OK;
2169
2170
6
}
2171
2172
2173
ngx_int_t
2174
ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2175
    ngx_str_t *default_type)
2176
3
{
2177
3
    ngx_hash_key_t  *type;
2178
2179
3
    *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2180
3
    if (*types == NULL) {
2181
0
        return NGX_ERROR;
2182
0
    }
2183
2184
11
    while (default_type->len) {
2185
2186
8
        type = ngx_array_push(*types);
2187
8
        if (type == NULL) {
2188
0
            return NGX_ERROR;
2189
0
        }
2190
2191
8
        type->key = *default_type;
2192
8
        type->key_hash = ngx_hash_key(default_type->data,
2193
8
                                      default_type->len);
2194
8
        type->value = (void *) 4;
2195
2196
8
        default_type++;
2197
8
    }
2198
2199
3
    return NGX_OK;
2200
3
}