Bug Summary

File:http/ngx_http.c
Location:line 748, column 31
Description:Access to field 'named_locations' results in a dereference of a null pointer (loaded from variable 'cscf')

Annotated Source Code

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