1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11
12
13 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14 static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
15 ngx_http_core_main_conf_t *cmcf);
16 static ngx_int_t ngx_http_init_headers_in_hash(ngx_conf_t *cf,
17 ngx_http_core_main_conf_t *cmcf);
18 static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
19 ngx_http_core_main_conf_t *cmcf);
20
21 static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
22 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
23 ngx_http_listen_opt_t *lsopt);
24 static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
25 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
26 ngx_http_listen_opt_t *lsopt);
27 static ngx_int_t ngx_http_add_server(ngx_conf_t *cf,
28 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
29
30 static char *ngx_http_merge_servers(ngx_conf_t *cf,
31 ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
32 ngx_uint_t ctx_index);
33 static char *ngx_http_merge_locations(ngx_conf_t *cf,
34 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
35 ngx_uint_t ctx_index);
36 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf,
37 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf);
38 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf,
39 ngx_http_core_loc_conf_t *pclcf);
40 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one,
41 const ngx_queue_t *two);
42 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf,
43 ngx_queue_t *locations);
44 static void ngx_http_create_locations_list(ngx_queue_t *locations,
45 ngx_queue_t *q);
46 static 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
50 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
51 ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
52 static 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);
54 static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
55 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
56 const void *two);
57
58 static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
59 ngx_http_conf_port_t *port);
60 static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
61 ngx_http_conf_addr_t *addr);
62 static 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)
65 static 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
69 ngx_uint_t ngx_http_max_module;
70
71
72 ngx_http_output_header_filter_pt ngx_http_top_header_filter;
73 ngx_http_output_body_filter_pt ngx_http_top_body_filter;
74 ngx_http_request_body_filter_pt ngx_http_top_request_body_filter;
75
76
77 ngx_str_t ngx_http_html_default_types[] = {
78 ngx_string("text/html"),
79 ngx_null_string
80 };
81
82
83 static ngx_command_t ngx_http_commands[] = {
84
85 { ngx_string("http"),
86 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
87 ngx_http_block,
88 0,
89 0,
90 NULL },
91
92 ngx_null_command
93 };
94
95
96 static ngx_core_module_t ngx_http_module_ctx = {
97 ngx_string("http"),
98 NULL,
99 NULL
100 };
101
102
103 ngx_module_t ngx_http_module = {
104 NGX_MODULE_V1,
105 &ngx_http_module_ctx, /* module context */
106 ngx_http_commands, /* module directives */
107 NGX_CORE_MODULE, /* module type */
108 NULL, /* init master */
109 NULL, /* init module */
110 NULL, /* init process */
111 NULL, /* init thread */
112 NULL, /* exit thread */
113 NULL, /* exit process */
114 NULL, /* exit master */
115 NGX_MODULE_V1_PADDING
116 };
117
118
119 static char *
ngx_http_block(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)120 ngx_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) {
139 return NGX_CONF_ERROR;
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_MODULE);
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) {
155 return NGX_CONF_ERROR;
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) {
166 return NGX_CONF_ERROR;
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) {
177 return NGX_CONF_ERROR;
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_MODULE) {
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) {
197 return NGX_CONF_ERROR;
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) {
204 return NGX_CONF_ERROR;
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) {
211 return NGX_CONF_ERROR;
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_MODULE) {
221 continue;
222 }
223
224 module = cf->cycle->modules[m]->ctx;
225
226 if (module->preconfiguration) {
227 if (module->preconfiguration(cf) != NGX_OK) {
228 return NGX_CONF_ERROR;
229 }
230 }
231 }
232
233 /* parse inside the http{} block */
234
235 cf->module_type = NGX_HTTP_MODULE;
236 cf->cmd_type = NGX_HTTP_MAIN_CONF;
237 rv = ngx_conf_parse(cf, NULL);
238
239 if (rv != NGX_CONF_OK) {
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_MODULE) {
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) {
264 goto failed;
265 }
266 }
267
268 rv = ngx_http_merge_servers(cf, cmcf, module, mi);
269 if (rv != NGX_CONF_OK) {
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_OK) {
282 return NGX_CONF_ERROR;
283 }
284
285 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) {
286 return NGX_CONF_ERROR;
287 }
288 }
289
290
291 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) {
292 return NGX_CONF_ERROR;
293 }
294
295 if (ngx_http_init_headers_in_hash(cf, cmcf) != NGX_OK) {
296 return NGX_CONF_ERROR;
297 }
298
299
300 for (m = 0; cf->cycle->modules[m]; m++) {
301 if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE) {
302 continue;
303 }
304
305 module = cf->cycle->modules[m]->ctx;
306
307 if (module->postconfiguration) {
308 if (module->postconfiguration(cf) != NGX_OK) {
309 return NGX_CONF_ERROR;
310 }
311 }
312 }
313
314 if (ngx_http_variables_init_vars(cf) != NGX_OK) {
315 return NGX_CONF_ERROR;
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_OK) {
327 return NGX_CONF_ERROR;
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_OK) {
334 return NGX_CONF_ERROR;
335 }
336
337 return NGX_CONF_OK;
338
339 failed:
340
341 *cf = pcf;
342
343 return rv;
344 }
345
346
347 static ngx_int_t
ngx_http_init_phases(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf)348 ngx_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_OK)
353 {
354 return NGX_ERROR;
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_OK)
360 {
361 return NGX_ERROR;
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_OK)
367 {
368 return NGX_ERROR;
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_OK)
374 {
375 return NGX_ERROR;
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_OK)
381 {
382 return NGX_ERROR;
383 }
384
385 if (ngx_array_init(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers,
386 cf->pool, 2, sizeof(ngx_http_handler_pt))
387 != NGX_OK)
388 {
389 return NGX_ERROR;
390 }
391
392 if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
393 cf->pool, 4, sizeof(ngx_http_handler_pt))
394 != NGX_OK)
395 {
396 return NGX_ERROR;
397 }
398
399 if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
400 cf->pool, 1, sizeof(ngx_http_handler_pt))
401 != NGX_OK)
402 {
403 return NGX_ERROR;
404 }
405
406 return NGX_OK;
407 }
408
409
410 static ngx_int_t
ngx_http_init_headers_in_hash(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf)411 ngx_http_init_headers_in_hash(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
412 {
413 ngx_array_t headers_in;
414 ngx_hash_key_t *hk;
415 ngx_hash_init_t hash;
416 ngx_http_header_t *header;
417
418 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
419 != NGX_OK)
420 {
421 return NGX_ERROR;
422 }
423
424 for (header = ngx_http_headers_in; header->name.len; header++) {
425 hk = ngx_array_push(&headers_in);
426 if (hk == NULL) {
427 return NGX_ERROR;
428 }
429
430 hk->key = header->name;
431 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
432 hk->value = header;
433 }
434
435 hash.hash = &cmcf->headers_in_hash;
436 hash.key = ngx_hash_key_lc;
437 hash.max_size = 512;
438 hash.bucket_size = ngx_align(64, ngx_cacheline_size);
439 hash.name = "headers_in_hash";
440 hash.pool = cf->pool;
441 hash.temp_pool = NULL;
442
443 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
444 return NGX_ERROR;
445 }
446
447 return NGX_OK;
448 }
449
450
451 static ngx_int_t
ngx_http_init_phase_handlers(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf)452 ngx_http_init_phase_handlers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf)
453 {
454 ngx_int_t j;
455 ngx_uint_t i, n;
456 ngx_uint_t find_config_index, use_rewrite, use_access;
457 ngx_http_handler_pt *h;
458 ngx_http_phase_handler_t *ph;
459 ngx_http_phase_handler_pt checker;
460
461 cmcf->phase_engine.server_rewrite_index = (ngx_uint_t) -1;
462 cmcf->phase_engine.location_rewrite_index = (ngx_uint_t) -1;
463 find_config_index = 0;
464 use_rewrite = cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts ? 1 : 0;
465 use_access = cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts ? 1 : 0;
466
467 n = 1 /* find config phase */
468 + use_rewrite /* post rewrite phase */
469 + use_access; /* post access phase */
470
471 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
472 n += cmcf->phases[i].handlers.nelts;
473 }
474
475 ph = ngx_pcalloc(cf->pool,
476 n * sizeof(ngx_http_phase_handler_t) + sizeof(void *));
477 if (ph == NULL) {
478 return NGX_ERROR;
479 }
480
481 cmcf->phase_engine.handlers = ph;
482 n = 0;
483
484 for (i = 0; i < NGX_HTTP_LOG_PHASE; i++) {
485 h = cmcf->phases[i].handlers.elts;
486
487 switch (i) {
488
489 case NGX_HTTP_SERVER_REWRITE_PHASE:
490 if (cmcf->phase_engine.server_rewrite_index == (ngx_uint_t) -1) {
491 cmcf->phase_engine.server_rewrite_index = n;
492 }
493 checker = ngx_http_core_rewrite_phase;
494
495 break;
496
497 case NGX_HTTP_FIND_CONFIG_PHASE:
498 find_config_index = n;
499
500 ph->checker = ngx_http_core_find_config_phase;
501 n++;
502 ph++;
503
504 continue;
505
506 case NGX_HTTP_REWRITE_PHASE:
507 if (cmcf->phase_engine.location_rewrite_index == (ngx_uint_t) -1) {
508 cmcf->phase_engine.location_rewrite_index = n;
509 }
510 checker = ngx_http_core_rewrite_phase;
511
512 break;
513
514 case NGX_HTTP_POST_REWRITE_PHASE:
515 if (use_rewrite) {
516 ph->checker = ngx_http_core_post_rewrite_phase;
517 ph->next = find_config_index;
518 n++;
519 ph++;
520 }
521
522 continue;
523
524 case NGX_HTTP_ACCESS_PHASE:
525 checker = ngx_http_core_access_phase;
526 n++;
527 break;
528
529 case NGX_HTTP_POST_ACCESS_PHASE:
530 if (use_access) {
531 ph->checker = ngx_http_core_post_access_phase;
532 ph->next = 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_OK;
557 }
558
559
560 static char *
ngx_http_merge_servers(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf,ngx_http_module_t * module,ngx_uint_t ctx_index)561 ngx_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;
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) {
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) {
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) {
609 goto failed;
610 }
611 }
612 }
613
614 failed:
615
616 *ctx = saved;
617
618 return rv;
619 }
620
621
622 static char *
ngx_http_merge_locations(ngx_conf_t * cf,ngx_queue_t * locations,void ** loc_conf,ngx_http_module_t * module,ngx_uint_t ctx_index)623 ngx_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) {
633 return NGX_CONF_OK;
634 }
635
636 ctx = (ngx_http_conf_ctx_t *) cf->ctx;
637 saved = *ctx;
638
639 for (q = ngx_queue_head(locations);
640 q != ngx_queue_sentinel(locations);
641 q = ngx_queue_next(q))
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) {
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) {
657 return rv;
658 }
659 }
660
661 *ctx = saved;
662
663 return NGX_CONF_OK;
664 }
665
666
667 static ngx_int_t
ngx_http_init_locations(ngx_conf_t * cf,ngx_http_core_srv_conf_t * cscf,ngx_http_core_loc_conf_t * pclcf)668 ngx_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_PCRE)
677 ngx_uint_t r;
678 ngx_queue_t *regex;
679 #endif
680
681 locations = pclcf->locations;
682
683 if (locations == NULL) {
684 return NGX_OK;
685 }
686
687 ngx_queue_sort(locations, ngx_http_cmp_locations);
688
689 named = NULL;
690 n = 0;
691 #if (NGX_PCRE)
692 regex = NULL;
693 r = 0;
694 #endif
695
696 for (q = ngx_queue_head(locations);
697 q != ngx_queue_sentinel(locations);
698 q = ngx_queue_next(q))
699 {
700 lq = (ngx_http_location_queue_t *) q;
701
702 clcf = lq->exact ? lq->exact : lq->inclusive;
703
704 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) {
705 return NGX_ERROR;
706 }
707
708 #if (NGX_PCRE)
709
710 if (clcf->regex) {
711 r++;
712
713 if (regex == NULL) {
714 regex = q;
715 }
716
717 continue;
718 }
719
720 #endif
721
722 if (clcf->named) {
723 n++;
724
725 if (named == NULL) {
726 named = q;
727 }
728
729 continue;
730 }
731
732 if (clcf->noname) {
733 break;
734 }
735 }
736
737 if (q != ngx_queue_sentinel(locations)) {
738 ngx_queue_split(locations, q, &tail);
739 }
740
741 if (named) {
742 clcfp = ngx_palloc(cf->pool,
743 (n + 1) * sizeof(ngx_http_core_loc_conf_t *));
744 if (clcfp == NULL) {
745 return NGX_ERROR;
746 }
747
748 cscf->named_locations = clcfp;
749
750 for (q = named;
751 q != ngx_queue_sentinel(locations);
752 q = ngx_queue_next(q))
753 {
754 lq = (ngx_http_location_queue_t *) q;
755
756 *(clcfp++) = lq->exact;
757 }
758
759 *clcfp = NULL;
760
761 ngx_queue_split(locations, named, &tail);
762 }
763
764 #if (NGX_PCRE)
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) {
771 return NGX_ERROR;
772 }
773
774 pclcf->regex_locations = clcfp;
775
776 for (q = regex;
777 q != ngx_queue_sentinel(locations);
778 q = ngx_queue_next(q))
779 {
780 lq = (ngx_http_location_queue_t *) q;
781
782 *(clcfp++) = lq->exact;
783 }
784
785 *clcfp = NULL;
786
787 ngx_queue_split(locations, regex, &tail);
788 }
789
790 #endif
791
792 return NGX_OK;
793 }
794
795
796 static ngx_int_t
ngx_http_init_static_location_trees(ngx_conf_t * cf,ngx_http_core_loc_conf_t * pclcf)797 ngx_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) {
807 return NGX_OK;
808 }
809
810 if (ngx_queue_empty(locations)) {
811 return NGX_OK;
812 }
813
814 for (q = ngx_queue_head(locations);
815 q != ngx_queue_sentinel(locations);
816 q = ngx_queue_next(q))
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_OK) {
823 return NGX_ERROR;
824 }
825 }
826
827 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) {
828 return NGX_ERROR;
829 }
830
831 ngx_http_create_locations_list(locations, ngx_queue_head(locations));
832
833 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0);
834 if (pclcf->static_locations == NULL) {
835 return NGX_ERROR;
836 }
837
838 return NGX_OK;
839 }
840
841
842 ngx_int_t
ngx_http_add_location(ngx_conf_t * cf,ngx_queue_t ** locations,ngx_http_core_loc_conf_t * clcf)843 ngx_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) {
849 *locations = ngx_palloc(cf->temp_pool,
850 sizeof(ngx_http_location_queue_t));
851 if (*locations == NULL) {
852 return NGX_ERROR;
853 }
854
855 ngx_queue_init(*locations);
856 }
857
858 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t));
859 if (lq == NULL) {
860 return NGX_ERROR;
861 }
862
863 if (clcf->exact_match
864 #if (NGX_PCRE)
865 || clcf->regex
866 #endif
867 || clcf->named || clcf->noname)
868 {
869 lq->exact = clcf;
870 lq->inclusive = NULL;
871
872 } else {
873 lq->exact = NULL;
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);
882
883 ngx_queue_insert_tail(*locations, &lq->queue);
884
885 return NGX_OK;
886 }
887
888
889 static ngx_int_t
ngx_http_cmp_locations(const ngx_queue_t * one,const ngx_queue_t * two)890 ngx_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);
929 }
930
931 #if (NGX_PCRE)
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) + 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
962 static ngx_int_t
ngx_http_join_exact_locations(ngx_conf_t * cf,ngx_queue_t * locations)963 ngx_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);
969
970 while (q != ngx_queue_last(locations)) {
971
972 x = ngx_queue_next(q);
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,
983 "duplicate location \"%V\" in %s:%ui",
984 lx->name, lx->file_name, lx->line);
985
986 return NGX_ERROR;
987 }
988
989 lq->inclusive = lx->inclusive;
990
991 ngx_queue_remove(x);
992
993 continue;
994 }
995
996 q = ngx_queue_next(q);
997 }
998
999 return NGX_OK;
1000 }
1001
1002
1003 static void
ngx_http_create_locations_list(ngx_queue_t * locations,ngx_queue_t * q)1004 ngx_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)) {
1012 return;
1013 }
1014
1015 lq = (ngx_http_location_queue_t *) q;
1016
1017 if (lq->inclusive == NULL) {
1018 ngx_http_create_locations_list(locations, ngx_queue_next(q));
1019 return;
1020 }
1021
1022 len = lq->name->len;
1023 name = lq->name->data;
1024
1025 for (x = ngx_queue_next(q);
1026 x != ngx_queue_sentinel(locations);
1027 x = ngx_queue_next(x))
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);
1039
1040 if (q == x) {
1041 ngx_http_create_locations_list(locations, x);
1042 return;
1043 }
1044
1045 ngx_queue_split(locations, q, &tail);
1046 ngx_queue_add(&lq->list, &tail);
1047
1048 if (x == ngx_queue_sentinel(locations)) {
1049 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
1050 return;
1051 }
1052
1053 ngx_queue_split(&lq->list, x, &tail);
1054 ngx_queue_add(locations, &tail);
1055
1056 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list));
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
1067 static ngx_http_location_tree_node_t *
ngx_http_create_locations_tree(ngx_conf_t * cf,ngx_queue_t * locations,size_t prefix)1068 ngx_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) + len);
1083 if (node == NULL) {
1084 return NULL;
1085 }
1086
1087 node->left = NULL;
1088 node->right = NULL;
1089 node->tree = NULL;
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);
1098
1099 ngx_queue_split(locations, q, &tail);
1100
1101 if (ngx_queue_empty(locations)) {
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) {
1111 return NULL;
1112 }
1113
1114 ngx_queue_remove(q);
1115
1116 if (ngx_queue_empty(&tail)) {
1117 goto inclusive;
1118 }
1119
1120 node->right = ngx_http_create_locations_tree(cf, &tail, prefix);
1121 if (node->right == NULL) {
1122 return NULL;
1123 }
1124
1125 inclusive:
1126
1127 if (ngx_queue_empty(&lq->list)) {
1128 return node;
1129 }
1130
1131 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len);
1132 if (node->tree == NULL) {
1133 return NULL;
1134 }
1135
1136 return node;
1137 }
1138
1139
1140 ngx_int_t
ngx_http_add_listen(ngx_conf_t * cf,ngx_http_core_srv_conf_t * cscf,ngx_http_listen_opt_t * lsopt)1141 ngx_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 ngx_http_conf_port_t *port;
1148 ngx_http_core_main_conf_t *cmcf;
1149
1150 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1151
1152 if (cmcf->ports == NULL) {
1153 cmcf->ports = ngx_array_create(cf->temp_pool, 2,
1154 sizeof(ngx_http_conf_port_t));
1155 if (cmcf->ports == NULL) {
1156 return NGX_ERROR;
1157 }
1158 }
1159
1160 sa = lsopt->sockaddr;
1161 p = ngx_inet_get_port(sa);
1162
1163 port = cmcf->ports->elts;
1164 for (i = 0; i < cmcf->ports->nelts; i++) {
1165
1166 if (p != port[i].port || sa->sa_family != port[i].family) {
1167 continue;
1168 }
1169
1170 /* a port is already in the port list */
1171
1172 return ngx_http_add_addresses(cf, cscf, &port[i], lsopt);
1173 }
1174
1175 /* add a port to the port list */
1176
1177 port = ngx_array_push(cmcf->ports);
1178 if (port == NULL) {
1179 return NGX_ERROR;
1180 }
1181
1182 port->family = sa->sa_family;
1183 port->port = p;
1184 port->addrs.elts = NULL;
1185
1186 return ngx_http_add_address(cf, cscf, port, lsopt);
1187 }
1188
1189
1190 static ngx_int_t
ngx_http_add_addresses(ngx_conf_t * cf,ngx_http_core_srv_conf_t * cscf,ngx_http_conf_port_t * port,ngx_http_listen_opt_t * lsopt)1191 ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1192 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
1193 {
1194 ngx_uint_t i, default_server, proxy_protocol;
1195 ngx_http_conf_addr_t *addr;
1196 #if (NGX_HTTP_SSL)
1197 ngx_uint_t ssl;
1198 #endif
1199 #if (NGX_HTTP_V2)
1200 ngx_uint_t http2;
1201 #endif
1202
1203 /*
1204 * we cannot compare whole sockaddr struct's as kernel
1205 * may fill some fields in inherited sockaddr struct's
1206 */
1207
1208 addr = port->addrs.elts;
1209
1210 for (i = 0; i < port->addrs.nelts; i++) {
1211
1212 if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen,
1213 addr[i].opt.sockaddr,
1214 addr[i].opt.socklen, 0)
1215 != NGX_OK)
1216 {
1217 continue;
1218 }
1219
1220 /* the address is already in the address list */
1221
1222 if (ngx_http_add_server(cf, cscf, &addr[i]) != NGX_OK) {
1223 return NGX_ERROR;
1224 }
1225
1226 /* preserve default_server bit during listen options overwriting */
1227 default_server = addr[i].opt.default_server;
1228
1229 proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
1230
1231 #if (NGX_HTTP_SSL)
1232 ssl = lsopt->ssl || addr[i].opt.ssl;
1233 #endif
1234 #if (NGX_HTTP_V2)
1235 http2 = lsopt->http2 || addr[i].opt.http2;
1236 #endif
1237
1238 if (lsopt->set) {
1239
1240 if (addr[i].opt.set) {
1241 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1242 "duplicate listen options for %V",
1243 &addr[i].opt.addr_text);
1244 return NGX_ERROR;
1245 }
1246
1247 addr[i].opt = *lsopt;
1248 }
1249
1250 /* check the duplicate "default" server for this address:port */
1251
1252 if (lsopt->default_server) {
1253
1254 if (default_server) {
1255 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1256 "a duplicate default server for %V",
1257 &addr[i].opt.addr_text);
1258 return NGX_ERROR;
1259 }
1260
1261 default_server = 1;
1262 addr[i].default_server = cscf;
1263 }
1264
1265 addr[i].opt.default_server = default_server;
1266 addr[i].opt.proxy_protocol = proxy_protocol;
1267 #if (NGX_HTTP_SSL)
1268 addr[i].opt.ssl = ssl;
1269 #endif
1270 #if (NGX_HTTP_V2)
1271 addr[i].opt.http2 = http2;
1272 #endif
1273
1274 return NGX_OK;
1275 }
1276
1277 /* add the address to the addresses list that bound to this port */
1278
1279 return ngx_http_add_address(cf, cscf, port, lsopt);
1280 }
1281
1282
1283 /*
1284 * add the server address, the server names and the server core module
1285 * configurations to the port list
1286 */
1287
1288 static ngx_int_t
ngx_http_add_address(ngx_conf_t * cf,ngx_http_core_srv_conf_t * cscf,ngx_http_conf_port_t * port,ngx_http_listen_opt_t * lsopt)1289 ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1290 ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
1291 {
1292 ngx_http_conf_addr_t *addr;
1293
1294 if (port->addrs.elts == NULL) {
1295 if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
1296 sizeof(ngx_http_conf_addr_t))
1297 != NGX_OK)
1298 {
1299 return NGX_ERROR;
1300 }
1301 }
1302
1303 #if (NGX_HTTP_V2 && NGX_HTTP_SSL \
1304 && !defined TLSEXT_TYPE_application_layer_protocol_negotiation \
1305 && !defined TLSEXT_TYPE_next_proto_neg)
1306
1307 if (lsopt->http2 && lsopt->ssl) {
1308 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1309 "nginx was built with OpenSSL that lacks ALPN "
1310 "and NPN support, HTTP/2 is not enabled for %V",
1311 &lsopt->addr_text);
1312 }
1313
1314 #endif
1315
1316 addr = ngx_array_push(&port->addrs);
1317 if (addr == NULL) {
1318 return NGX_ERROR;
1319 }
1320
1321 addr->opt = *lsopt;
1322 addr->hash.buckets = NULL;
1323 addr->hash.size = 0;
1324 addr->wc_head = NULL;
1325 addr->wc_tail = NULL;
1326 #if (NGX_PCRE)
1327 addr->nregex = 0;
1328 addr->regex = NULL;
1329 #endif
1330 addr->default_server = cscf;
1331 addr->servers.elts = NULL;
1332
1333 return ngx_http_add_server(cf, cscf, addr);
1334 }
1335
1336
1337 /* add the server core module configuration to the address:port */
1338
1339 static ngx_int_t
ngx_http_add_server(ngx_conf_t * cf,ngx_http_core_srv_conf_t * cscf,ngx_http_conf_addr_t * addr)1340 ngx_http_add_server(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
1341 ngx_http_conf_addr_t *addr)
1342 {
1343 ngx_uint_t i;
1344 ngx_http_core_srv_conf_t **server;
1345
1346 if (addr->servers.elts == NULL) {
1347 if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
1348 sizeof(ngx_http_core_srv_conf_t *))
1349 != NGX_OK)
1350 {
1351 return NGX_ERROR;
1352 }
1353
1354 } else {
1355 server = addr->servers.elts;
1356 for (i = 0; i < addr->servers.nelts; i++) {
1357 if (server[i] == cscf) {
1358 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1359 "a duplicate listen %V",
1360 &addr->opt.addr_text);
1361 return NGX_ERROR;
1362 }
1363 }
1364 }
1365
1366 server = ngx_array_push(&addr->servers);
1367 if (server == NULL) {
1368 return NGX_ERROR;
1369 }
1370
1371 *server = cscf;
1372
1373 return NGX_OK;
1374 }
1375
1376
1377 static ngx_int_t
ngx_http_optimize_servers(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf,ngx_array_t * ports)1378 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1379 ngx_array_t *ports)
1380 {
1381 ngx_uint_t p, a;
1382 ngx_http_conf_port_t *port;
1383 ngx_http_conf_addr_t *addr;
1384
1385 if (ports == NULL) {
1386 return NGX_OK;
1387 }
1388
1389 port = ports->elts;
1390 for (p = 0; p < ports->nelts; p++) {
1391
1392 ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
1393 sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
1394
1395 /*
1396 * check whether all name-based servers have the same
1397 * configuration as a default server for given address:port
1398 */
1399
1400 addr = port[p].addrs.elts;
1401 for (a = 0; a < port[p].addrs.nelts; a++) {
1402
1403 if (addr[a].servers.nelts > 1
1404 #if (NGX_PCRE)
1405 || addr[a].default_server->captures
1406 #endif
1407 )
1408 {
1409 if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
1410 return NGX_ERROR;
1411 }
1412 }
1413 }
1414
1415 if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
1416 return NGX_ERROR;
1417 }
1418 }
1419
1420 return NGX_OK;
1421 }
1422
1423
1424 static ngx_int_t
ngx_http_server_names(ngx_conf_t * cf,ngx_http_core_main_conf_t * cmcf,ngx_http_conf_addr_t * addr)1425 ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
1426 ngx_http_conf_addr_t *addr)
1427 {
1428 ngx_int_t rc;
1429 ngx_uint_t n, s;
1430 ngx_hash_init_t hash;
1431 ngx_hash_keys_arrays_t ha;
1432 ngx_http_server_name_t *name;
1433 ngx_http_core_srv_conf_t **cscfp;
1434 #if (NGX_PCRE)
1435 ngx_uint_t regex, i;
1436
1437 regex = 0;
1438 #endif
1439
1440 ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
1441
1442 ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
1443 if (ha.temp_pool == NULL) {
1444 return NGX_ERROR;
1445 }
1446
1447 ha.pool = cf->pool;
1448
1449 if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
1450 goto failed;
1451 }
1452
1453 cscfp = addr->servers.elts;
1454
1455 for (s = 0; s < addr->servers.nelts; s++) {
1456
1457 name = cscfp[s]->server_names.elts;
1458
1459 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1460
1461 #if (NGX_PCRE)
1462 if (name[n].regex) {
1463 regex++;
1464 continue;
1465 }
1466 #endif
1467
1468 rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
1469 NGX_HASH_WILDCARD_KEY);
1470
1471 if (rc == NGX_ERROR) {
1472 goto failed;
1473 }
1474
1475 if (rc == NGX_DECLINED) {
1476 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1477 "invalid server name or wildcard \"%V\" on %V",
1478 &name[n].name, &addr->opt.addr_text);
1479 goto failed;
1480 }
1481
1482 if (rc == NGX_BUSY) {
1483 ngx_log_error(NGX_LOG_WARN, cf->log, 0,
1484 "conflicting server name \"%V\" on %V, ignored",
1485 &name[n].name, &addr->opt.addr_text);
1486 }
1487 }
1488 }
1489
1490 hash.key = ngx_hash_key_lc;
1491 hash.max_size = cmcf->server_names_hash_max_size;
1492 hash.bucket_size = cmcf->server_names_hash_bucket_size;
1493 hash.name = "server_names_hash";
1494 hash.pool = cf->pool;
1495
1496 if (ha.keys.nelts) {
1497 hash.hash = &addr->hash;
1498 hash.temp_pool = NULL;
1499
1500 if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
1501 goto failed;
1502 }
1503 }
1504
1505 if (ha.dns_wc_head.nelts) {
1506
1507 ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
1508 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1509
1510 hash.hash = NULL;
1511 hash.temp_pool = ha.temp_pool;
1512
1513 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
1514 ha.dns_wc_head.nelts)
1515 != NGX_OK)
1516 {
1517 goto failed;
1518 }
1519
1520 addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
1521 }
1522
1523 if (ha.dns_wc_tail.nelts) {
1524
1525 ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
1526 sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
1527
1528 hash.hash = NULL;
1529 hash.temp_pool = ha.temp_pool;
1530
1531 if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
1532 ha.dns_wc_tail.nelts)
1533 != NGX_OK)
1534 {
1535 goto failed;
1536 }
1537
1538 addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
1539 }
1540
1541 ngx_destroy_pool(ha.temp_pool);
1542
1543 #if (NGX_PCRE)
1544
1545 if (regex == 0) {
1546 return NGX_OK;
1547 }
1548
1549 addr->nregex = regex;
1550 addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
1551 if (addr->regex == NULL) {
1552 return NGX_ERROR;
1553 }
1554
1555 i = 0;
1556
1557 for (s = 0; s < addr->servers.nelts; s++) {
1558
1559 name = cscfp[s]->server_names.elts;
1560
1561 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
1562 if (name[n].regex) {
1563 addr->regex[i++] = name[n];
1564 }
1565 }
1566 }
1567
1568 #endif
1569
1570 return NGX_OK;
1571
1572 failed:
1573
1574 ngx_destroy_pool(ha.temp_pool);
1575
1576 return NGX_ERROR;
1577 }
1578
1579
1580 static ngx_int_t
ngx_http_cmp_conf_addrs(const void * one,const void * two)1581 ngx_http_cmp_conf_addrs(const void *one, const void *two)
1582 {
1583 ngx_http_conf_addr_t *first, *second;
1584
1585 first = (ngx_http_conf_addr_t *) one;
1586 second = (ngx_http_conf_addr_t *) two;
1587
1588 if (first->opt.wildcard) {
1589 /* a wildcard address must be the last resort, shift it to the end */
1590 return 1;
1591 }
1592
1593 if (second->opt.wildcard) {
1594 /* a wildcard address must be the last resort, shift it to the end */
1595 return -1;
1596 }
1597
1598 if (first->opt.bind && !second->opt.bind) {
1599 /* shift explicit bind()ed addresses to the start */
1600 return -1;
1601 }
1602
1603 if (!first->opt.bind && second->opt.bind) {
1604 /* shift explicit bind()ed addresses to the start */
1605 return 1;
1606 }
1607
1608 /* do not sort by default */
1609
1610 return 0;
1611 }
1612
1613
1614 static int ngx_libc_cdecl
ngx_http_cmp_dns_wildcards(const void * one,const void * two)1615 ngx_http_cmp_dns_wildcards(const void *one, const void *two)
1616 {
1617 ngx_hash_key_t *first, *second;
1618
1619 first = (ngx_hash_key_t *) one;
1620 second = (ngx_hash_key_t *) two;
1621
1622 return ngx_dns_strcmp(first->key.data, second->key.data);
1623 }
1624
1625
1626 static ngx_int_t
ngx_http_init_listening(ngx_conf_t * cf,ngx_http_conf_port_t * port)1627 ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
1628 {
1629 ngx_uint_t i, last, bind_wildcard;
1630 ngx_listening_t *ls;
1631 ngx_http_port_t *hport;
1632 ngx_http_conf_addr_t *addr;
1633
1634 addr = port->addrs.elts;
1635 last = port->addrs.nelts;
1636
1637 /*
1638 * If there is a binding to an "*:port" then we need to bind() to
1639 * the "*:port" only and ignore other implicit bindings. The bindings
1640 * have been already sorted: explicit bindings are on the start, then
1641 * implicit bindings go, and wildcard binding is in the end.
1642 */
1643
1644 if (addr[last - 1].opt.wildcard) {
1645 addr[last - 1].opt.bind = 1;
1646 bind_wildcard = 1;
1647
1648 } else {
1649 bind_wildcard = 0;
1650 }
1651
1652 i = 0;
1653
1654 while (i < last) {
1655
1656 if (bind_wildcard && !addr[i].opt.bind) {
1657 i++;
1658 continue;
1659 }
1660
1661 ls = ngx_http_add_listening(cf, &addr[i]);
1662 if (ls == NULL) {
1663 return NGX_ERROR;
1664 }
1665
1666 hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
1667 if (hport == NULL) {
1668 return NGX_ERROR;
1669 }
1670
1671 ls->servers = hport;
1672
1673 hport->naddrs = i + 1;
1674
1675 switch (ls->sockaddr->sa_family) {
1676
1677 #if (NGX_HAVE_INET6)
1678 case AF_INET6:
1679 if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
1680 return NGX_ERROR;
1681 }
1682 break;
1683 #endif
1684 default: /* AF_INET */
1685 if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
1686 return NGX_ERROR;
1687 }
1688 break;
1689 }
1690
1691 addr++;
1692 last--;
1693 }
1694
1695 return NGX_OK;
1696 }
1697
1698
1699 static ngx_listening_t *
ngx_http_add_listening(ngx_conf_t * cf,ngx_http_conf_addr_t * addr)1700 ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
1701 {
1702 ngx_listening_t *ls;
1703 ngx_http_core_loc_conf_t *clcf;
1704 ngx_http_core_srv_conf_t *cscf;
1705
1706 ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
1707 if (ls == NULL) {
1708 return NULL;
1709 }
1710
1711 ls->addr_ntop = 1;
1712
1713 ls->handler = ngx_http_init_connection;
1714
1715 cscf = addr->default_server;
1716 ls->pool_size = cscf->connection_pool_size;
1717
1718 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
1719
1720 ls->logp = clcf->error_log;
1721 ls->log.data = &ls->addr_text;
1722 ls->log.handler = ngx_accept_log_error;
1723
1724 #if (NGX_WIN32)
1725 {
1726 ngx_iocp_conf_t *iocpcf = NULL;
1727
1728 if (ngx_get_conf(cf->cycle->conf_ctx, ngx_events_module)) {
1729 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
1730 }
1731 if (iocpcf && iocpcf->acceptex_read) {
1732 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
1733 }
1734 }
1735 #endif
1736
1737 ls->backlog = addr->opt.backlog;
1738 ls->rcvbuf = addr->opt.rcvbuf;
1739 ls->sndbuf = addr->opt.sndbuf;
1740
1741 ls->keepalive = addr->opt.so_keepalive;
1742 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
1743 ls->keepidle = addr->opt.tcp_keepidle;
1744 ls->keepintvl = addr->opt.tcp_keepintvl;
1745 ls->keepcnt = addr->opt.tcp_keepcnt;
1746 #endif
1747
1748 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
1749 ls->accept_filter = addr->opt.accept_filter;
1750 #endif
1751
1752 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
1753 ls->deferred_accept = addr->opt.deferred_accept;
1754 #endif
1755
1756 #if (NGX_HAVE_INET6)
1757 ls->ipv6only = addr->opt.ipv6only;
1758 #endif
1759
1760 #if (NGX_HAVE_SETFIB)
1761 ls->setfib = addr->opt.setfib;
1762 #endif
1763
1764 #if (NGX_HAVE_TCP_FASTOPEN)
1765 ls->fastopen = addr->opt.fastopen;
1766 #endif
1767
1768 #if (NGX_HAVE_REUSEPORT)
1769 ls->reuseport = addr->opt.reuseport;
1770 #endif
1771
1772 return ls;
1773 }
1774
1775
1776 static ngx_int_t
ngx_http_add_addrs(ngx_conf_t * cf,ngx_http_port_t * hport,ngx_http_conf_addr_t * addr)1777 ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
1778 ngx_http_conf_addr_t *addr)
1779 {
1780 ngx_uint_t i;
1781 ngx_http_in_addr_t *addrs;
1782 struct sockaddr_in *sin;
1783 ngx_http_virtual_names_t *vn;
1784
1785 hport->addrs = ngx_pcalloc(cf->pool,
1786 hport->naddrs * sizeof(ngx_http_in_addr_t));
1787 if (hport->addrs == NULL) {
1788 return NGX_ERROR;
1789 }
1790
1791 addrs = hport->addrs;
1792
1793 for (i = 0; i < hport->naddrs; i++) {
1794
1795 sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
1796 addrs[i].addr = sin->sin_addr.s_addr;
1797 addrs[i].conf.default_server = addr[i].default_server;
1798 #if (NGX_HTTP_SSL)
1799 addrs[i].conf.ssl = addr[i].opt.ssl;
1800 #endif
1801 #if (NGX_HTTP_V2)
1802 addrs[i].conf.http2 = addr[i].opt.http2;
1803 #endif
1804 addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
1805
1806 if (addr[i].hash.buckets == NULL
1807 && (addr[i].wc_head == NULL
1808 || addr[i].wc_head->hash.buckets == NULL)
1809 && (addr[i].wc_tail == NULL
1810 || addr[i].wc_tail->hash.buckets == NULL)
1811 #if (NGX_PCRE)
1812 && addr[i].nregex == 0
1813 #endif
1814 )
1815 {
1816 continue;
1817 }
1818
1819 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1820 if (vn == NULL) {
1821 return NGX_ERROR;
1822 }
1823
1824 addrs[i].conf.virtual_names = vn;
1825
1826 vn->names.hash = addr[i].hash;
1827 vn->names.wc_head = addr[i].wc_head;
1828 vn->names.wc_tail = addr[i].wc_tail;
1829 #if (NGX_PCRE)
1830 vn->nregex = addr[i].nregex;
1831 vn->regex = addr[i].regex;
1832 #endif
1833 }
1834
1835 return NGX_OK;
1836 }
1837
1838
1839 #if (NGX_HAVE_INET6)
1840
1841 static ngx_int_t
ngx_http_add_addrs6(ngx_conf_t * cf,ngx_http_port_t * hport,ngx_http_conf_addr_t * addr)1842 ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
1843 ngx_http_conf_addr_t *addr)
1844 {
1845 ngx_uint_t i;
1846 ngx_http_in6_addr_t *addrs6;
1847 struct sockaddr_in6 *sin6;
1848 ngx_http_virtual_names_t *vn;
1849
1850 hport->addrs = ngx_pcalloc(cf->pool,
1851 hport->naddrs * sizeof(ngx_http_in6_addr_t));
1852 if (hport->addrs == NULL) {
1853 return NGX_ERROR;
1854 }
1855
1856 addrs6 = hport->addrs;
1857
1858 for (i = 0; i < hport->naddrs; i++) {
1859
1860 sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
1861 addrs6[i].addr6 = sin6->sin6_addr;
1862 addrs6[i].conf.default_server = addr[i].default_server;
1863 #if (NGX_HTTP_SSL)
1864 addrs6[i].conf.ssl = addr[i].opt.ssl;
1865 #endif
1866 #if (NGX_HTTP_V2)
1867 addrs6[i].conf.http2 = addr[i].opt.http2;
1868 #endif
1869 addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
1870
1871 if (addr[i].hash.buckets == NULL
1872 && (addr[i].wc_head == NULL
1873 || addr[i].wc_head->hash.buckets == NULL)
1874 && (addr[i].wc_tail == NULL
1875 || addr[i].wc_tail->hash.buckets == NULL)
1876 #if (NGX_PCRE)
1877 && addr[i].nregex == 0
1878 #endif
1879 )
1880 {
1881 continue;
1882 }
1883
1884 vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
1885 if (vn == NULL) {
1886 return NGX_ERROR;
1887 }
1888
1889 addrs6[i].conf.virtual_names = vn;
1890
1891 vn->names.hash = addr[i].hash;
1892 vn->names.wc_head = addr[i].wc_head;
1893 vn->names.wc_tail = addr[i].wc_tail;
1894 #if (NGX_PCRE)
1895 vn->nregex = addr[i].nregex;
1896 vn->regex = addr[i].regex;
1897 #endif
1898 }
1899
1900 return NGX_OK;
1901 }
1902
1903 #endif
1904
1905
1906 char *
ngx_http_types_slot(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)1907 ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1908 {
1909 char *p = conf;
1910
1911 ngx_array_t **types;
1912 ngx_str_t *value, *default_type;
1913 ngx_uint_t i, n, hash;
1914 ngx_hash_key_t *type;
1915
1916 types = (ngx_array_t **) (p + cmd->offset);
1917
1918 if (*types == (void *) -1) {
1919 return NGX_CONF_OK;
1920 }
1921
1922 default_type = cmd->post;
1923
1924 if (*types == NULL) {
1925 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
1926 if (*types == NULL) {
1927 return NGX_CONF_ERROR;
1928 }
1929
1930 if (default_type) {
1931 type = ngx_array_push(*types);
1932 if (type == NULL) {
1933 return NGX_CONF_ERROR;
1934 }
1935
1936 type->key = *default_type;
1937 type->key_hash = ngx_hash_key(default_type->data,
1938 default_type->len);
1939 type->value = (void *) 4;
1940 }
1941 }
1942
1943 value = cf->args->elts;
1944
1945 for (i = 1; i < cf->args->nelts; i++) {
1946
1947 if (value[i].len == 1 && value[i].data[0] == '*') {
1948 *types = (void *) -1;
1949 return NGX_CONF_OK;
1950 }
1951
1952 hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
1953 value[i].data[value[i].len] = '\0';
1954
1955 type = (*types)->elts;
1956 for (n = 0; n < (*types)->nelts; n++) {
1957
1958 if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
1959 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1960 "duplicate MIME type \"%V\"", &value[i]);
1961 goto next;
1962 }
1963 }
1964
1965 type = ngx_array_push(*types);
1966 if (type == NULL) {
1967 return NGX_CONF_ERROR;
1968 }
1969
1970 type->key = value[i];
1971 type->key_hash = hash;
1972 type->value = (void *) 4;
1973
1974 next:
1975
1976 continue;
1977 }
1978
1979 return NGX_CONF_OK;
1980 }
1981
1982
1983 char *
ngx_http_merge_types(ngx_conf_t * cf,ngx_array_t ** keys,ngx_hash_t * types_hash,ngx_array_t ** prev_keys,ngx_hash_t * prev_types_hash,ngx_str_t * default_types)1984 ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t **keys, ngx_hash_t *types_hash,
1985 ngx_array_t **prev_keys, ngx_hash_t *prev_types_hash,
1986 ngx_str_t *default_types)
1987 {
1988 ngx_hash_init_t hash;
1989
1990 if (*keys) {
1991
1992 if (*keys == (void *) -1) {
1993 return NGX_CONF_OK;
1994 }
1995
1996 hash.hash = types_hash;
1997 hash.key = NULL;
1998 hash.max_size = 2048;
1999 hash.bucket_size = 64;
2000 hash.name = "test_types_hash";
2001 hash.pool = cf->pool;
2002 hash.temp_pool = NULL;
2003
2004 if (ngx_hash_init(&hash, (*keys)->elts, (*keys)->nelts) != NGX_OK) {
2005 return NGX_CONF_ERROR;
2006 }
2007
2008 return NGX_CONF_OK;
2009 }
2010
2011 if (prev_types_hash->buckets == NULL) {
2012
2013 if (*prev_keys == NULL) {
2014
2015 if (ngx_http_set_default_types(cf, prev_keys, default_types)
2016 != NGX_OK)
2017 {
2018 return NGX_CONF_ERROR;
2019 }
2020
2021 } else if (*prev_keys == (void *) -1) {
2022 *keys = *prev_keys;
2023 return NGX_CONF_OK;
2024 }
2025
2026 hash.hash = prev_types_hash;
2027 hash.key = NULL;
2028 hash.max_size = 2048;
2029 hash.bucket_size = 64;
2030 hash.name = "test_types_hash";
2031 hash.pool = cf->pool;
2032 hash.temp_pool = NULL;
2033
2034 if (ngx_hash_init(&hash, (*prev_keys)->elts, (*prev_keys)->nelts)
2035 != NGX_OK)
2036 {
2037 return NGX_CONF_ERROR;
2038 }
2039 }
2040
2041 *types_hash = *prev_types_hash;
2042
2043 return NGX_CONF_OK;
2044
2045 }
2046
2047
2048 ngx_int_t
ngx_http_set_default_types(ngx_conf_t * cf,ngx_array_t ** types,ngx_str_t * default_type)2049 ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
2050 ngx_str_t *default_type)
2051 {
2052 ngx_hash_key_t *type;
2053
2054 *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
2055 if (*types == NULL) {
2056 return NGX_ERROR;
2057 }
2058
2059 while (default_type->len) {
2060
2061 type = ngx_array_push(*types);
2062 if (type == NULL) {
2063 return NGX_ERROR;
2064 }
2065
2066 type->key = *default_type;
2067 type->key_hash = ngx_hash_key(default_type->data,
2068 default_type->len);
2069 type->value = (void *) 4;
2070
2071 default_type++;
2072 }
2073
2074 return NGX_OK;
2075 }
2076