Bug Summary

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