1 2 /* 3 * Copyright (C) Valentin V. Bartenev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 #include <nxt_conf.h> 9 #include <nxt_cert.h> 10 #include <nxt_router.h> 11 #include <nxt_http.h> 12 #include <nxt_sockaddr.h> 13 #include <nxt_http_route_addr.h> 14 15 16 typedef enum { 17 NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL, 18 NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN, 19 NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER, 20 NXT_CONF_VLDT_NUMBER = (1 << NXT_CONF_NUMBER) | NXT_CONF_VLDT_INTEGER, 21 NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING, 22 NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY, 23 NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT, 24 } nxt_conf_vldt_type_t; 25 26 #define NXT_CONF_VLDT_ANY_TYPE (NXT_CONF_VLDT_NULL \ 27 |NXT_CONF_VLDT_BOOLEAN \ 28 |NXT_CONF_VLDT_NUMBER \ 29 |NXT_CONF_VLDT_STRING \ 30 |NXT_CONF_VLDT_ARRAY \ 31 |NXT_CONF_VLDT_OBJECT) 32 33 34 typedef nxt_int_t (*nxt_conf_vldt_handler_t)(nxt_conf_validation_t *vldt, 35 nxt_conf_value_t *value, 36 void *data); 37 38 39 typedef struct { 40 nxt_str_t name; 41 nxt_conf_vldt_type_t type; 42 nxt_conf_vldt_handler_t validator; 43 void *data; 44 } nxt_conf_vldt_object_t; 45 46 47 #define NXT_CONF_VLDT_NEXT(f) { nxt_null_string, 0, NULL, (f) } 48 #define NXT_CONF_VLDT_END { nxt_null_string, 0, NULL, NULL } 49 50 51 typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt, 52 nxt_str_t *name, 53 nxt_conf_value_t *value); 54 typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt, 55 nxt_conf_value_t *value); 56 57 static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, 58 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type); 59 static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt, 60 const char *fmt, ...); 61 62 static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, 63 nxt_conf_value_t *value, void *data); 64 static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, 65 nxt_str_t *name, nxt_conf_value_t *value); 66 static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt, 67 nxt_conf_value_t *value); 68 static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, 69 nxt_str_t *name, nxt_conf_value_t *value); 70 #if (NXT_TLS) 71 static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, 72 nxt_conf_value_t *value, void *data); 73 #endif 74 static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt, 75 nxt_conf_value_t *value, void *data); 76 static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, 77 nxt_conf_value_t *value, void *data); 78 static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt, 79 nxt_conf_value_t *value, void *data); 80 static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, 81 nxt_conf_value_t *value, void *data); 82 static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, 83 nxt_conf_value_t *value, void *data); 84 static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, 85 nxt_str_t *name, nxt_conf_value_t *value); 86 static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt, 87 nxt_conf_value_t *value); 88 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets( 89 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); 90 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set( 91 nxt_conf_validation_t *vldt, nxt_conf_value_t *value); 92 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member( 93 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); 94 static nxt_int_t nxt_conf_vldt_match_encoded_patterns( 95 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); 96 static nxt_int_t nxt_conf_vldt_match_encoded_pattern( 97 nxt_conf_validation_t *vldt, nxt_conf_value_t *value); 98 static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt, 99 nxt_conf_value_t *value, void *data); 100 static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, 101 nxt_conf_value_t *value); 102 static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt, 103 nxt_conf_value_t *value, void *data); 104 static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt, 105 nxt_conf_value_t *value); 106 static nxt_int_t nxt_conf_vldt_match_patterns_set_member( 107 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value); 108 static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt, 109 nxt_conf_value_t *value, void *data); 110 static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt, 111 nxt_conf_value_t *value, void *data); 112 static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, 113 nxt_conf_value_t *value); 114 static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, 115 nxt_conf_value_t *value, void *data); 116 static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, 117 nxt_str_t *name, nxt_conf_value_t *value); 118 static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, 119 nxt_conf_value_t *value, void *data); 120 static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, 121 nxt_conf_value_t *value, void *data); 122 static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, 123 nxt_conf_value_t *value, void *data); 124 static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, 125 nxt_conf_value_t *value, void *data); 126 static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, 127 nxt_str_t *name, nxt_conf_value_t *value); 128 static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, 129 nxt_conf_value_t *value); 130 static nxt_int_t nxt_conf_vldt_php(nxt_conf_validation_t *vldt, 131 nxt_conf_value_t *value, void *data); 132 static nxt_int_t nxt_conf_vldt_php_targets_exclusive( 133 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data); 134 static nxt_int_t nxt_conf_vldt_php_targets(nxt_conf_validation_t *vldt, 135 nxt_conf_value_t *value, void *data); 136 static nxt_int_t nxt_conf_vldt_php_target(nxt_conf_validation_t *vldt, 137 nxt_str_t *name, nxt_conf_value_t *value); 138 static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, 139 nxt_str_t *name, nxt_conf_value_t *value); 140 static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, 141 nxt_conf_value_t *value); 142 static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, 143 nxt_conf_value_t *value); 144 static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, 145 nxt_str_t *name, nxt_conf_value_t *value); 146 static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt, 147 nxt_str_t *name, nxt_conf_value_t *value); 148 static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, 149 nxt_conf_value_t *value, void *data); 150 151 static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, 152 nxt_conf_value_t *value, void *data); 153 static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, 154 nxt_conf_value_t *value, void *data); 155 156 #if (NXT_HAVE_CLONE_NEWUSER) 157 static nxt_int_t nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt, 158 const char* mapfile, nxt_conf_value_t *value); 159 static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, 160 nxt_conf_value_t *value); 161 static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, 162 nxt_conf_value_t *value); 163 #endif 164 165 static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = { 166 { nxt_string("read_timeout"), 167 NXT_CONF_VLDT_INTEGER, 168 NULL, 169 NULL }, 170 171 { nxt_string("keepalive_interval"), 172 NXT_CONF_VLDT_INTEGER, 173 NULL, 174 NULL }, 175 176 { nxt_string("max_frame_size"), 177 NXT_CONF_VLDT_INTEGER, 178 NULL, 179 NULL }, 180 181 NXT_CONF_VLDT_END 182 }; 183 184 185 static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = { 186 { nxt_string("mime_types"), 187 NXT_CONF_VLDT_OBJECT, 188 &nxt_conf_vldt_mtypes, 189 NULL }, 190 191 NXT_CONF_VLDT_END 192 }; 193 194 195 static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { 196 { nxt_string("header_read_timeout"), 197 NXT_CONF_VLDT_INTEGER, 198 NULL, 199 NULL }, 200 201 { nxt_string("body_read_timeout"), 202 NXT_CONF_VLDT_INTEGER, 203 NULL, 204 NULL }, 205 206 { nxt_string("send_timeout"), 207 NXT_CONF_VLDT_INTEGER, 208 NULL, 209 NULL }, 210 211 { nxt_string("idle_timeout"), 212 NXT_CONF_VLDT_INTEGER, 213 NULL, 214 NULL }, 215 216 { nxt_string("body_buffer_size"), 217 NXT_CONF_VLDT_INTEGER, 218 NULL, 219 NULL }, 220 221 { nxt_string("max_body_size"), 222 NXT_CONF_VLDT_INTEGER, 223 NULL, 224 NULL }, 225 226 { nxt_string("body_temp_path"), 227 NXT_CONF_VLDT_STRING, 228 NULL, 229 NULL }, 230 231 { nxt_string("websocket"), 232 NXT_CONF_VLDT_OBJECT, 233 &nxt_conf_vldt_object, 234 (void *) &nxt_conf_vldt_websocket_members }, 235 236 { nxt_string("static"), 237 NXT_CONF_VLDT_OBJECT, 238 &nxt_conf_vldt_object, 239 (void *) &nxt_conf_vldt_static_members }, 240 241 NXT_CONF_VLDT_END 242 }; 243 244 245 static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { 246 { nxt_string("http"), 247 NXT_CONF_VLDT_OBJECT, 248 &nxt_conf_vldt_object, 249 (void *) &nxt_conf_vldt_http_members }, 250 251 NXT_CONF_VLDT_END 252 }; 253 254 255 static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { 256 { nxt_string("settings"), 257 NXT_CONF_VLDT_OBJECT, 258 &nxt_conf_vldt_object, 259 (void *) &nxt_conf_vldt_setting_members }, 260 261 { nxt_string("listeners"), 262 NXT_CONF_VLDT_OBJECT, 263 &nxt_conf_vldt_object_iterator, 264 (void *) &nxt_conf_vldt_listener }, 265 266 { nxt_string("routes"), 267 NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT, 268 &nxt_conf_vldt_routes, 269 NULL }, 270 271 { nxt_string("applications"), 272 NXT_CONF_VLDT_OBJECT, 273 &nxt_conf_vldt_object_iterator, 274 (void *) &nxt_conf_vldt_app }, 275 276 { nxt_string("upstreams"), 277 NXT_CONF_VLDT_OBJECT, 278 &nxt_conf_vldt_object_iterator, 279 (void *) &nxt_conf_vldt_upstream }, 280 281 { nxt_string("access_log"), 282 NXT_CONF_VLDT_STRING, 283 NULL, 284 NULL }, 285 286 NXT_CONF_VLDT_END 287 }; 288 289 290 #if (NXT_TLS) 291 292 static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = { 293 { nxt_string("certificate"), 294 NXT_CONF_VLDT_STRING, 295 &nxt_conf_vldt_certificate, 296 NULL }, 297 298 NXT_CONF_VLDT_END 299 }; 300 301 #endif 302 303 304 static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { 305 { nxt_string("pass"), 306 NXT_CONF_VLDT_STRING, 307 &nxt_conf_vldt_pass, 308 NULL }, 309 310 { nxt_string("application"), 311 NXT_CONF_VLDT_STRING, 312 &nxt_conf_vldt_app_name, 313 NULL }, 314 315 #if (NXT_TLS) 316 317 { nxt_string("tls"), 318 NXT_CONF_VLDT_OBJECT, 319 &nxt_conf_vldt_object, 320 (void *) &nxt_conf_vldt_tls_members }, 321 322 #endif 323 324 NXT_CONF_VLDT_END 325 }; 326 327 328 static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = { 329 { nxt_string("method"), 330 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, 331 &nxt_conf_vldt_match_patterns, 332 NULL }, 333 334 { nxt_string("scheme"), 335 NXT_CONF_VLDT_STRING, 336 &nxt_conf_vldt_match_scheme_pattern, 337 NULL }, 338 339 { nxt_string("host"), 340 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, 341 &nxt_conf_vldt_match_patterns, 342 NULL }, 343 344 { nxt_string("source"), 345 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, 346 &nxt_conf_vldt_match_addrs, 347 NULL }, 348 349 { nxt_string("destination"), 350 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, 351 &nxt_conf_vldt_match_addrs, 352 NULL }, 353 354 { nxt_string("uri"), 355 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY, 356 &nxt_conf_vldt_match_encoded_patterns, 357 NULL }, 358 359 { nxt_string("arguments"), 360 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, 361 &nxt_conf_vldt_match_encoded_patterns_sets, 362 NULL }, 363 364 { nxt_string("headers"), 365 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, 366 &nxt_conf_vldt_match_patterns_sets, 367 NULL }, 368 369 { nxt_string("cookies"), 370 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY, 371 &nxt_conf_vldt_match_patterns_sets, 372 NULL }, 373 374 NXT_CONF_VLDT_END 375 }; 376 377 378 static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = { 379 { nxt_string("pass"), 380 NXT_CONF_VLDT_STRING, 381 &nxt_conf_vldt_pass, 382 NULL }, 383 384 NXT_CONF_VLDT_END 385 }; 386 387 388 static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = { 389 { nxt_string("return"), 390 NXT_CONF_VLDT_INTEGER, 391 &nxt_conf_vldt_return, 392 NULL }, 393 394 { nxt_string("location"), 395 NXT_CONF_VLDT_STRING, 396 NULL, 397 NULL }, 398 399 NXT_CONF_VLDT_END 400 }; 401 402 403 static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = { 404 { nxt_string("share"), 405 NXT_CONF_VLDT_STRING, 406 NULL, 407 NULL }, 408 409 { nxt_string("fallback"), 410 NXT_CONF_VLDT_OBJECT, 411 &nxt_conf_vldt_action, 412 NULL }, 413 414 NXT_CONF_VLDT_END 415 }; 416 417 418 static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = { 419 { nxt_string("proxy"), 420 NXT_CONF_VLDT_STRING, 421 &nxt_conf_vldt_proxy, 422 NULL }, 423 424 NXT_CONF_VLDT_END 425 }; 426 427 428 static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = { 429 { nxt_string("match"), 430 NXT_CONF_VLDT_OBJECT, 431 &nxt_conf_vldt_object, 432 (void *) &nxt_conf_vldt_match_members }, 433 434 { nxt_string("action"), 435 NXT_CONF_VLDT_OBJECT, 436 &nxt_conf_vldt_action, 437 NULL }, 438 439 NXT_CONF_VLDT_END 440 }; 441 442 443 static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = { 444 { nxt_string("timeout"), 445 NXT_CONF_VLDT_INTEGER, 446 NULL, 447 NULL }, 448 449 { nxt_string("reschedule_timeout"), 450 NXT_CONF_VLDT_INTEGER, 451 NULL, 452 NULL }, 453 454 { nxt_string("requests"), 455 NXT_CONF_VLDT_INTEGER, 456 NULL, 457 NULL }, 458 459 { nxt_string("shm"), 460 NXT_CONF_VLDT_INTEGER, 461 NULL, 462 NULL }, 463 464 NXT_CONF_VLDT_END 465 }; 466 467 468 static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = { 469 { nxt_string("spare"), 470 NXT_CONF_VLDT_INTEGER, 471 NULL, 472 NULL }, 473 474 { nxt_string("max"), 475 NXT_CONF_VLDT_INTEGER, 476 NULL, 477 NULL }, 478 479 { nxt_string("idle_timeout"), 480 NXT_CONF_VLDT_INTEGER, 481 NULL, 482 NULL }, 483 484 NXT_CONF_VLDT_END 485 }; 486 487 488 static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = { 489 490 #if (NXT_HAVE_CLONE_NEWUSER) 491 { nxt_string("credential"), 492 NXT_CONF_VLDT_BOOLEAN, 493 NULL, 494 NULL }, 495 #endif 496 497 #if (NXT_HAVE_CLONE_NEWPID) 498 { nxt_string("pid"), 499 NXT_CONF_VLDT_BOOLEAN, 500 NULL, 501 NULL }, 502 #endif 503 504 #if (NXT_HAVE_CLONE_NEWNET) 505 { nxt_string("network"), 506 NXT_CONF_VLDT_BOOLEAN, 507 NULL, 508 NULL }, 509 #endif 510 511 #if (NXT_HAVE_CLONE_NEWNS) 512 { nxt_string("mount"), 513 NXT_CONF_VLDT_BOOLEAN, 514 NULL, 515 NULL }, 516 #endif 517 518 #if (NXT_HAVE_CLONE_NEWUTS) 519 { nxt_string("uname"), 520 NXT_CONF_VLDT_BOOLEAN, 521 NULL, 522 NULL }, 523 #endif 524 525 #if (NXT_HAVE_CLONE_NEWCGROUP) 526 { nxt_string("cgroup"), 527 NXT_CONF_VLDT_BOOLEAN, 528 NULL, 529 NULL }, 530 #endif 531 532 NXT_CONF_VLDT_END 533 }; 534 535 536 #if (NXT_HAVE_CLONE_NEWUSER) 537 538 static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = { 539 { nxt_string("container"), 540 NXT_CONF_VLDT_INTEGER, 541 NULL, 542 NULL }, 543 544 { nxt_string("host"), 545 NXT_CONF_VLDT_INTEGER, 546 NULL, 547 NULL }, 548 549 { nxt_string("size"), 550 NXT_CONF_VLDT_INTEGER, 551 NULL, 552 NULL }, 553 }; 554 555 #endif 556 557 558 static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { 559 { nxt_string("namespaces"), 560 NXT_CONF_VLDT_OBJECT, 561 &nxt_conf_vldt_clone_namespaces, 562 (void *) &nxt_conf_vldt_app_namespaces_members }, 563 564 #if (NXT_HAVE_CLONE_NEWUSER) 565 566 { nxt_string("uidmap"), 567 NXT_CONF_VLDT_ARRAY, 568 &nxt_conf_vldt_array_iterator, 569 (void *) &nxt_conf_vldt_clone_uidmap }, 570 571 { nxt_string("gidmap"), 572 NXT_CONF_VLDT_ARRAY, 573 &nxt_conf_vldt_array_iterator, 574 (void *) &nxt_conf_vldt_clone_gidmap }, 575 576 #endif 577 578 #if (NXT_HAVE_ISOLATION_ROOTFS) 579 580 { nxt_string("rootfs"), 581 NXT_CONF_VLDT_STRING, 582 NULL, 583 NULL }, 584 585 #endif 586 587 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 588 589 { nxt_string("new_privs"), 590 NXT_CONF_VLDT_BOOLEAN, 591 NULL, 592 NULL }, 593 594 #endif 595 596 NXT_CONF_VLDT_END 597 }; 598 599 600 static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { 601 { nxt_string("type"), 602 NXT_CONF_VLDT_STRING, 603 NULL, 604 NULL }, 605 606 { nxt_string("limits"), 607 NXT_CONF_VLDT_OBJECT, 608 &nxt_conf_vldt_object, 609 (void *) &nxt_conf_vldt_app_limits_members }, 610 611 { nxt_string("processes"), 612 NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT, 613 &nxt_conf_vldt_processes, 614 (void *) &nxt_conf_vldt_app_processes_members }, 615 616 { nxt_string("user"), 617 NXT_CONF_VLDT_STRING, 618 NULL, 619 NULL }, 620 621 { nxt_string("group"), 622 NXT_CONF_VLDT_STRING, 623 NULL, 624 NULL }, 625 626 { nxt_string("working_directory"), 627 NXT_CONF_VLDT_STRING, 628 NULL, 629 NULL }, 630 631 { nxt_string("environment"), 632 NXT_CONF_VLDT_OBJECT, 633 &nxt_conf_vldt_object_iterator, 634 (void *) &nxt_conf_vldt_environment }, 635 636 { nxt_string("isolation"), 637 NXT_CONF_VLDT_OBJECT, 638 &nxt_conf_vldt_isolation, 639 (void *) &nxt_conf_vldt_app_isolation_members }, 640 641 NXT_CONF_VLDT_END 642 }; 643 644 645 static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = { 646 { nxt_string("executable"), 647 NXT_CONF_VLDT_STRING, 648 NULL, 649 NULL }, 650 651 { nxt_string("arguments"), 652 NXT_CONF_VLDT_ARRAY, 653 &nxt_conf_vldt_array_iterator, 654 (void *) &nxt_conf_vldt_argument }, 655 656 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 657 }; 658 659 660 static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { 661 { nxt_string("home"), 662 NXT_CONF_VLDT_STRING, 663 NULL, 664 NULL }, 665 666 { nxt_string("path"), 667 NXT_CONF_VLDT_STRING, 668 NULL, 669 NULL }, 670 671 { nxt_string("module"), 672 NXT_CONF_VLDT_STRING, 673 NULL, 674 NULL }, 675 676 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 677 }; 678 679 680 static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[] = { 681 { nxt_string("root"), 682 NXT_CONF_VLDT_STRING, 683 NULL, 684 NULL }, 685 686 { nxt_string("script"), 687 NXT_CONF_VLDT_STRING, 688 NULL, 689 NULL }, 690 691 { nxt_string("index"), 692 NXT_CONF_VLDT_STRING, 693 NULL, 694 NULL } 695 }; 696 697 698 static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = { 699 { nxt_string("file"), 700 NXT_CONF_VLDT_STRING, 701 NULL, 702 NULL }, 703 704 { nxt_string("admin"), 705 NXT_CONF_VLDT_OBJECT, 706 &nxt_conf_vldt_object_iterator, 707 (void *) &nxt_conf_vldt_php_option }, 708 709 { nxt_string("user"), 710 NXT_CONF_VLDT_OBJECT, 711 &nxt_conf_vldt_object_iterator, 712 (void *) &nxt_conf_vldt_php_option }, 713 714 NXT_CONF_VLDT_END 715 }; 716 717 718 static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[] = { 719 { nxt_string("options"), 720 NXT_CONF_VLDT_OBJECT, 721 &nxt_conf_vldt_object, 722 (void *) &nxt_conf_vldt_php_options_members }, 723 724 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 725 }; 726 727 728 static nxt_conf_vldt_object_t nxt_conf_vldt_php_notargets_members[] = { 729 { nxt_string("root"), 730 NXT_CONF_VLDT_STRING, 731 NULL, 732 NULL }, 733 734 { nxt_string("script"), 735 NXT_CONF_VLDT_STRING, 736 NULL, 737 NULL }, 738 739 { nxt_string("index"), 740 NXT_CONF_VLDT_STRING, 741 NULL, 742 NULL }, 743 744 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_php_common_members) 745 }; 746 747 748 static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = { 749 { nxt_string("root"), 750 NXT_CONF_VLDT_ANY_TYPE, 751 &nxt_conf_vldt_php_targets_exclusive, 752 (void *) "root" }, 753 754 { nxt_string("script"), 755 NXT_CONF_VLDT_ANY_TYPE, 756 &nxt_conf_vldt_php_targets_exclusive, 757 (void *) "script" }, 758 759 { nxt_string("index"), 760 NXT_CONF_VLDT_ANY_TYPE, 761 &nxt_conf_vldt_php_targets_exclusive, 762 (void *) "index" }, 763 764 { nxt_string("targets"), 765 NXT_CONF_VLDT_OBJECT, 766 &nxt_conf_vldt_php_targets, 767 NULL }, 768 769 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_php_common_members) 770 }; 771 772 773 static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = { 774 { nxt_string("script"), 775 NXT_CONF_VLDT_STRING, 776 NULL, 777 NULL }, 778 779 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 780 }; 781 782 783 static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = { 784 { nxt_string("script"), 785 NXT_CONF_VLDT_STRING, 786 NULL, 787 NULL }, 788 789 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 790 }; 791 792 793 static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = { 794 { nxt_string("classpath"), 795 NXT_CONF_VLDT_ARRAY, 796 &nxt_conf_vldt_array_iterator, 797 (void *) &nxt_conf_vldt_java_classpath }, 798 799 { nxt_string("webapp"), 800 NXT_CONF_VLDT_STRING, 801 NULL, 802 NULL }, 803 804 { nxt_string("options"), 805 NXT_CONF_VLDT_ARRAY, 806 &nxt_conf_vldt_array_iterator, 807 (void *) &nxt_conf_vldt_java_option }, 808 809 { nxt_string("unit_jars"), 810 NXT_CONF_VLDT_STRING, 811 NULL, 812 NULL }, 813 814 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 815 }; 816 817 818 static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = { 819 { nxt_string("servers"), 820 NXT_CONF_VLDT_OBJECT, 821 &nxt_conf_vldt_object_iterator, 822 (void *) &nxt_conf_vldt_server }, 823 824 NXT_CONF_VLDT_END 825 }; 826 827 828 static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = { 829 { nxt_string("weight"), 830 NXT_CONF_VLDT_NUMBER, 831 &nxt_conf_vldt_server_weight, 832 NULL }, 833 834 NXT_CONF_VLDT_END 835 }; 836 837 838 nxt_int_t 839 nxt_conf_validate(nxt_conf_validation_t *vldt) 840 { 841 nxt_int_t ret; 842 843 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); 844 845 if (ret != NXT_OK) { 846 return ret; 847 } 848 849 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); 850 } 851 852 853 #define NXT_CONF_VLDT_ANY_TYPE_STR \ 854 "either a null, a boolean, an integer, " \ 855 "a number, a string, an array, or an object" 856 857 858 static nxt_int_t 859 nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name, 860 nxt_conf_value_t *value, nxt_conf_vldt_type_t type) 861 { 862 u_char *p; 863 nxt_str_t expected; 864 nxt_bool_t serial; 865 nxt_uint_t value_type, n, t; 866 u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE_STR)]; 867 868 static nxt_str_t type_name[] = { 869 nxt_string("a null"), 870 nxt_string("a boolean"), 871 nxt_string("an integer number"), 872 nxt_string("a fractional number"), 873 nxt_string("a string"), 874 nxt_string("an array"), 875 nxt_string("an object"), 876 }; 877 878 value_type = nxt_conf_type(value); 879 880 if ((1 << value_type) & type) { 881 return NXT_OK; 882 } 883 884 p = buf; 885 886 n = nxt_popcount(type); 887 888 if (n > 1) { 889 p = nxt_cpymem(p, "either ", 7); 890 } 891 892 serial = (n > 2); 893 894 for ( ;; ) { 895 t = __builtin_ffs(type) - 1; 896 897 p = nxt_cpymem(p, type_name[t].start, type_name[t].length); 898 899 n--; 900 901 if (n == 0) { 902 break; 903 } 904 905 if (n > 1 || serial) { 906 *p++ = ','; 907 } 908 909 if (n == 1) { 910 p = nxt_cpymem(p, " or", 3); 911 } 912 913 *p++ = ' '; 914 915 type = type & ~(1 << t); 916 } 917 918 expected.length = p - buf; 919 expected.start = buf; 920 921 if (name == NULL) { 922 return nxt_conf_vldt_error(vldt, 923 "The configuration must be %V, but not %V.", 924 &expected, &type_name[value_type]); 925 } 926 927 return nxt_conf_vldt_error(vldt, 928 "The \"%V\" value must be %V, but not %V.", 929 name, &expected, &type_name[value_type]); 930 } 931 932 933 static nxt_int_t 934 nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...) 935 { 936 u_char *p, *end; 937 size_t size; 938 va_list args; 939 u_char error[NXT_MAX_ERROR_STR]; 940 941 va_start(args, fmt); 942 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args); 943 va_end(args); 944 945 size = end - error; 946 947 p = nxt_mp_nget(vldt->pool, size); 948 if (p == NULL) { 949 return NXT_ERROR; 950 } 951 952 nxt_memcpy(p, error, size); 953 954 vldt->error.length = size; 955 vldt->error.start = p; 956 957 return NXT_DECLINED; 958 } 959 960 961 typedef struct { 962 nxt_mp_t *pool; 963 nxt_str_t *type; 964 nxt_lvlhsh_t hash; 965 } nxt_conf_vldt_mtypes_ctx_t; 966 967 968 static nxt_int_t 969 nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 970 void *data) 971 { 972 nxt_int_t ret; 973 nxt_conf_vldt_mtypes_ctx_t ctx; 974 975 ctx.pool = nxt_mp_create(1024, 128, 256, 32); 976 if (nxt_slow_path(ctx.pool == NULL)) { 977 return NXT_ERROR; 978 } 979 980 nxt_lvlhsh_init(&ctx.hash); 981 982 vldt->ctx = &ctx; 983 984 ret = nxt_conf_vldt_object_iterator(vldt, value, 985 &nxt_conf_vldt_mtypes_type); 986 987 vldt->ctx = NULL; 988 989 nxt_mp_destroy(ctx.pool); 990 991 return ret; 992 } 993 994 995 static nxt_int_t 996 nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name, 997 nxt_conf_value_t *value) 998 { 999 nxt_int_t ret; 1000 nxt_conf_vldt_mtypes_ctx_t *ctx; 1001 1002 ret = nxt_conf_vldt_type(vldt, name, value, 1003 NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY); 1004 if (ret != NXT_OK) { 1005 return ret; 1006 } 1007 1008 ctx = vldt->ctx; 1009 1010 ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t)); 1011 if (nxt_slow_path(ctx->type == NULL)) { 1012 return NXT_ERROR; 1013 } 1014 1015 *ctx->type = *name; 1016 1017 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1018 return nxt_conf_vldt_array_iterator(vldt, value, 1019 &nxt_conf_vldt_mtypes_extension); 1020 } 1021 1022 /* NXT_CONF_STRING */ 1023 1024 return nxt_conf_vldt_mtypes_extension(vldt, value); 1025 } 1026 1027 1028 static nxt_int_t 1029 nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt, 1030 nxt_conf_value_t *value) 1031 { 1032 nxt_str_t ext, *dup_type; 1033 nxt_conf_vldt_mtypes_ctx_t *ctx; 1034 1035 ctx = vldt->ctx; 1036 1037 if (nxt_conf_type(value) != NXT_CONF_STRING) { 1038 return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must " 1039 "contain only strings.", ctx->type); 1040 } 1041 1042 nxt_conf_get_string(value, &ext); 1043 1044 if (ext.length == 0) { 1045 return nxt_conf_vldt_error(vldt, "An empty file extension for " 1046 "the \"%V\" MIME type.", ctx->type); 1047 } 1048 1049 dup_type = nxt_http_static_mtypes_hash_find(&ctx->hash, &ext); 1050 1051 if (dup_type != NULL) { 1052 return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been " 1053 "declared for \"%V\" and \"%V\" " 1054 "MIME types at the same time.", 1055 &ext, dup_type, ctx->type); 1056 } 1057 1058 return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash, 1059 &ext, ctx->type); 1060 } 1061 1062 1063 static nxt_int_t 1064 nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name, 1065 nxt_conf_value_t *value) 1066 { 1067 nxt_int_t ret; 1068 1069 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 1070 1071 if (ret != NXT_OK) { 1072 return ret; 1073 } 1074 1075 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members); 1076 } 1077 1078 1079 static nxt_int_t 1080 nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1081 void *data) 1082 { 1083 nxt_uint_t i; 1084 nxt_conf_value_t *action; 1085 nxt_conf_vldt_object_t *members; 1086 1087 static struct { 1088 nxt_str_t name; 1089 nxt_conf_vldt_object_t *members; 1090 1091 } actions[] = { 1092 { nxt_string("pass"), nxt_conf_vldt_pass_action_members }, 1093 { nxt_string("return"), nxt_conf_vldt_return_action_members }, 1094 { nxt_string("share"), nxt_conf_vldt_share_action_members }, 1095 { nxt_string("proxy"), nxt_conf_vldt_proxy_action_members }, 1096 }; 1097 1098 members = NULL; 1099 1100 for (i = 0; i < nxt_nitems(actions); i++) { 1101 action = nxt_conf_get_object_member(value, &actions[i].name, NULL); 1102 1103 if (action == NULL) { 1104 continue; 1105 } 1106 1107 if (members != NULL) { 1108 return nxt_conf_vldt_error(vldt, "The \"action\" object must have " 1109 "just one of \"pass\", \"return\", " 1110 "\"share\", or \"proxy\" options set."); 1111 } 1112 1113 members = actions[i].members; 1114 } 1115 1116 if (members == NULL) { 1117 return nxt_conf_vldt_error(vldt, "The \"action\" object must have " 1118 "either \"pass\", \"return\", \"share\", " 1119 "or \"proxy\" option set."); 1120 } 1121 1122 return nxt_conf_vldt_object(vldt, value, members); 1123 } 1124 1125 1126 static nxt_int_t 1127 nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1128 void *data) 1129 { 1130 nxt_str_t pass; 1131 nxt_int_t ret; 1132 nxt_str_t segments[3]; 1133 1134 static nxt_str_t targets_str = nxt_string("targets"); 1135 1136 nxt_conf_get_string(value, &pass); 1137 1138 ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 3); 1139 1140 if (ret != NXT_OK) { 1141 if (ret == NXT_DECLINED) { 1142 return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" " 1143 "is invalid.", &pass); 1144 } 1145 1146 return NXT_ERROR; 1147 } 1148 1149 if (nxt_str_eq(&segments[0], "applications", 12)) { 1150 1151 if (segments[1].length == 0) { 1152 goto error; 1153 } 1154 1155 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); 1156 1157 if (value == NULL) { 1158 goto error; 1159 } 1160 1161 value = nxt_conf_get_object_member(value, &segments[1], NULL); 1162 1163 if (value == NULL) { 1164 goto error; 1165 } 1166 1167 if (segments[2].length > 0) { 1168 value = nxt_conf_get_object_member(value, &targets_str, NULL); 1169 1170 if (value == NULL) { 1171 goto error; 1172 } 1173 1174 value = nxt_conf_get_object_member(value, &segments[2], NULL); 1175 1176 if (value == NULL) { 1177 goto error; 1178 } 1179 } 1180 1181 return NXT_OK; 1182 } 1183 1184 if (nxt_str_eq(&segments[0], "upstreams", 9)) { 1185 1186 if (segments[1].length == 0 || segments[2].length != 0) { 1187 goto error; 1188 } 1189 1190 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); 1191 1192 if (value == NULL) { 1193 goto error; 1194 } 1195 1196 value = nxt_conf_get_object_member(value, &segments[1], NULL); 1197 1198 if (value == NULL) { 1199 goto error; 1200 } 1201 1202 return NXT_OK; 1203 } 1204 1205 if (nxt_str_eq(&segments[0], "routes", 6)) { 1206 1207 if (segments[2].length != 0) { 1208 goto error; 1209 } 1210 1211 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL); 1212 1213 if (value == NULL) { 1214 goto error; 1215 } 1216 1217 if (segments[1].length == 0) { 1218 if (nxt_conf_type(value) != NXT_CONF_ARRAY) { 1219 goto error; 1220 } 1221 1222 return NXT_OK; 1223 } 1224 1225 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 1226 goto error; 1227 } 1228 1229 value = nxt_conf_get_object_member(value, &segments[1], NULL); 1230 1231 if (value == NULL) { 1232 goto error; 1233 } 1234 1235 return NXT_OK; 1236 } 1237 1238 error: 1239 1240 return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid " 1241 "location \"%V\".", &pass); 1242 } 1243 1244 1245 static nxt_int_t 1246 nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1247 void *data) 1248 { 1249 int64_t status; 1250 1251 status = nxt_conf_get_number(value); 1252 1253 if (status < NXT_HTTP_INVALID || status > NXT_HTTP_STATUS_MAX) { 1254 return nxt_conf_vldt_error(vldt, "The \"return\" value is out of " 1255 "allowed HTTP status code range 0-999."); 1256 } 1257 1258 return NXT_OK; 1259 } 1260 1261 1262 static nxt_int_t 1263 nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1264 void *data) 1265 { 1266 nxt_str_t name; 1267 nxt_sockaddr_t *sa; 1268 1269 nxt_conf_get_string(value, &name); 1270 1271 if (nxt_str_start(&name, "http://", 7)) { 1272 name.length -= 7; 1273 name.start += 7; 1274 1275 sa = nxt_sockaddr_parse(vldt->pool, &name); 1276 if (sa != NULL) { 1277 return NXT_OK; 1278 } 1279 } 1280 1281 return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"", 1282 &name); 1283 } 1284 1285 1286 static nxt_int_t 1287 nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1288 void *data) 1289 { 1290 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1291 return nxt_conf_vldt_array_iterator(vldt, value, 1292 &nxt_conf_vldt_route); 1293 } 1294 1295 /* NXT_CONF_OBJECT */ 1296 1297 return nxt_conf_vldt_object_iterator(vldt, value, 1298 &nxt_conf_vldt_routes_member); 1299 } 1300 1301 1302 static nxt_int_t 1303 nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name, 1304 nxt_conf_value_t *value) 1305 { 1306 nxt_int_t ret; 1307 1308 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY); 1309 1310 if (ret != NXT_OK) { 1311 return ret; 1312 } 1313 1314 return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route); 1315 } 1316 1317 1318 static nxt_int_t 1319 nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 1320 { 1321 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 1322 return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain " 1323 "only object values."); 1324 } 1325 1326 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members); 1327 } 1328 1329 1330 static nxt_int_t 1331 nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt, 1332 nxt_conf_value_t *value, void *data) 1333 { 1334 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1335 return nxt_conf_vldt_array_iterator(vldt, value, 1336 &nxt_conf_vldt_match_pattern); 1337 } 1338 1339 /* NXT_CONF_STRING */ 1340 1341 return nxt_conf_vldt_match_pattern(vldt, value); 1342 } 1343 1344 1345 static nxt_int_t 1346 nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt, 1347 nxt_conf_value_t *value) 1348 { 1349 u_char ch; 1350 nxt_str_t pattern; 1351 nxt_uint_t i, first, last; 1352 1353 enum { 1354 sw_none, 1355 sw_side, 1356 sw_middle 1357 } state; 1358 1359 if (nxt_conf_type(value) != NXT_CONF_STRING) { 1360 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for \"host\", " 1361 "\"uri\", and \"method\" must be strings."); 1362 } 1363 1364 nxt_conf_get_string(value, &pattern); 1365 1366 if (pattern.length == 0) { 1367 return NXT_OK; 1368 } 1369 1370 first = (pattern.start[0] == '!'); 1371 last = pattern.length - 1; 1372 state = sw_none; 1373 1374 for (i = first; i != pattern.length; i++) { 1375 1376 ch = pattern.start[i]; 1377 1378 if (ch != '*') { 1379 continue; 1380 } 1381 1382 switch (state) { 1383 case sw_none: 1384 state = (i == first) ? sw_side : sw_middle; 1385 break; 1386 1387 case sw_side: 1388 if (i == last) { 1389 if (last - first != 1) { 1390 break; 1391 } 1392 1393 return nxt_conf_vldt_error(vldt, "The \"match\" pattern must " 1394 "not contain double \"*\" markers."); 1395 } 1396 1397 /* Fall through. */ 1398 1399 case sw_middle: 1400 return nxt_conf_vldt_error(vldt, "The \"match\" patterns can " 1401 "either contain \"*\" markers at " 1402 "the sides or only one in the middle."); 1403 } 1404 } 1405 1406 return NXT_OK; 1407 } 1408 1409 1410 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets( 1411 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data) 1412 { 1413 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1414 return nxt_conf_vldt_array_iterator(vldt, value, 1415 &nxt_conf_vldt_match_encoded_patterns_set); 1416 } 1417 1418 /* NXT_CONF_STRING */ 1419 1420 return nxt_conf_vldt_match_encoded_patterns_set(vldt, value); 1421 } 1422 1423 1424 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set( 1425 nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 1426 { 1427 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 1428 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " 1429 "\"arguments\" must be an object."); 1430 } 1431 1432 return nxt_conf_vldt_object_iterator(vldt, value, 1433 &nxt_conf_vldt_match_encoded_patterns_set_member); 1434 } 1435 1436 1437 static nxt_int_t 1438 nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t *vldt, 1439 nxt_str_t *name, nxt_conf_value_t *value) 1440 { 1441 u_char *p, *end; 1442 1443 if (nxt_slow_path(name->length == 0)) { 1444 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " 1445 "not contain empty member names."); 1446 } 1447 1448 p = nxt_mp_nget(vldt->pool, name->length); 1449 if (nxt_slow_path(p == NULL)) { 1450 return NXT_ERROR; 1451 } 1452 1453 end = nxt_decode_uri(p, name->start, name->length); 1454 if (nxt_slow_path(end == NULL)) { 1455 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " 1456 "\"arguments\" is encoded but is invalid."); 1457 } 1458 1459 return nxt_conf_vldt_match_encoded_patterns(vldt, value, NULL); 1460 } 1461 1462 1463 static nxt_int_t 1464 nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt, 1465 nxt_conf_value_t *value, void *data) 1466 { 1467 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1468 return nxt_conf_vldt_array_iterator(vldt, value, 1469 &nxt_conf_vldt_match_encoded_pattern); 1470 } 1471 1472 /* NXT_CONF_STRING */ 1473 1474 return nxt_conf_vldt_match_encoded_pattern(vldt, value); 1475 } 1476 1477 1478 static nxt_int_t 1479 nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt, 1480 nxt_conf_value_t *value) 1481 { 1482 u_char *p, *end; 1483 nxt_int_t ret; 1484 nxt_str_t pattern; 1485 1486 if (nxt_conf_type(value) != NXT_CONF_STRING) { 1487 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"uri\" " 1488 "must be a string."); 1489 } 1490 1491 ret = nxt_conf_vldt_match_pattern(vldt, value); 1492 if (nxt_slow_path(ret != NXT_OK)) { 1493 return ret; 1494 } 1495 1496 nxt_conf_get_string(value, &pattern); 1497 1498 p = nxt_mp_nget(vldt->pool, pattern.length); 1499 if (nxt_slow_path(p == NULL)) { 1500 return NXT_ERROR; 1501 } 1502 1503 end = nxt_decode_uri(p, pattern.start, pattern.length); 1504 if (nxt_slow_path(end == NULL)) { 1505 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"uri\" " 1506 "is encoded but is invalid."); 1507 } 1508 1509 return NXT_OK; 1510 } 1511 1512 1513 static nxt_int_t 1514 nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt, 1515 nxt_conf_value_t *value, void *data) 1516 { 1517 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1518 return nxt_conf_vldt_array_iterator(vldt, value, 1519 &nxt_conf_vldt_match_addr); 1520 } 1521 1522 return nxt_conf_vldt_match_addr(vldt, value); 1523 } 1524 1525 1526 static nxt_int_t 1527 nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt, 1528 nxt_conf_value_t *value) 1529 { 1530 nxt_http_route_addr_pattern_t pattern; 1531 1532 switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) { 1533 1534 case NXT_OK: 1535 return NXT_OK; 1536 1537 case NXT_ADDR_PATTERN_PORT_ERROR: 1538 return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid " 1539 "port."); 1540 1541 case NXT_ADDR_PATTERN_CV_TYPE_ERROR: 1542 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for " 1543 "\"address\" must be a string."); 1544 1545 case NXT_ADDR_PATTERN_LENGTH_ERROR: 1546 return nxt_conf_vldt_error(vldt, "The \"address\" is too short."); 1547 1548 case NXT_ADDR_PATTERN_FORMAT_ERROR: 1549 return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid."); 1550 1551 case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR: 1552 return nxt_conf_vldt_error(vldt, "The \"address\" range is " 1553 "overlapping."); 1554 1555 case NXT_ADDR_PATTERN_CIDR_ERROR: 1556 return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR " 1557 "prefix."); 1558 1559 case NXT_ADDR_PATTERN_NO_IPv6_ERROR: 1560 return nxt_conf_vldt_error(vldt, "The \"address\" does not support " 1561 "IPv6 with your configuration."); 1562 1563 default: 1564 return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown " 1565 "format."); 1566 } 1567 } 1568 1569 1570 static nxt_int_t 1571 nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt, 1572 nxt_conf_value_t *value, void *data) 1573 { 1574 nxt_str_t scheme; 1575 1576 static const nxt_str_t http = nxt_string("http"); 1577 static const nxt_str_t https = nxt_string("https"); 1578 1579 nxt_conf_get_string(value, &scheme); 1580 1581 if (nxt_strcasestr_eq(&scheme, &http) 1582 || nxt_strcasestr_eq(&scheme, &https)) 1583 { 1584 return NXT_OK; 1585 } 1586 1587 return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be " 1588 "\"http\" or \"https\"."); 1589 } 1590 1591 1592 static nxt_int_t 1593 nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt, 1594 nxt_conf_value_t *value, void *data) 1595 { 1596 if (nxt_conf_type(value) == NXT_CONF_ARRAY) { 1597 return nxt_conf_vldt_array_iterator(vldt, value, 1598 &nxt_conf_vldt_match_patterns_set); 1599 } 1600 1601 /* NXT_CONF_OBJECT */ 1602 1603 return nxt_conf_vldt_match_patterns_set(vldt, value); 1604 } 1605 1606 1607 static nxt_int_t 1608 nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt, 1609 nxt_conf_value_t *value) 1610 { 1611 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 1612 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for " 1613 "\"arguments\", \"cookies\", and " 1614 "\"headers\" must be objects."); 1615 } 1616 1617 return nxt_conf_vldt_object_iterator(vldt, value, 1618 &nxt_conf_vldt_match_patterns_set_member); 1619 } 1620 1621 1622 static nxt_int_t 1623 nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt, 1624 nxt_str_t *name, nxt_conf_value_t *value) 1625 { 1626 if (name->length == 0) { 1627 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must " 1628 "not contain empty member names."); 1629 } 1630 1631 return nxt_conf_vldt_match_patterns(vldt, value, NULL); 1632 } 1633 1634 1635 #if (NXT_TLS) 1636 1637 static nxt_int_t 1638 nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1639 void *data) 1640 { 1641 nxt_str_t name; 1642 nxt_conf_value_t *cert; 1643 1644 nxt_conf_get_string(value, &name); 1645 1646 cert = nxt_cert_info_get(&name); 1647 1648 if (cert == NULL) { 1649 return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.", 1650 &name); 1651 } 1652 1653 return NXT_OK; 1654 } 1655 1656 #endif 1657 1658 1659 static nxt_int_t 1660 nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1661 void *data) 1662 { 1663 nxt_str_t name; 1664 nxt_conf_value_t *apps, *app; 1665 1666 static nxt_str_t apps_str = nxt_string("applications"); 1667 1668 nxt_conf_get_string(value, &name); 1669 1670 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL); 1671 1672 if (nxt_slow_path(apps == NULL)) { 1673 goto error; 1674 } 1675 1676 app = nxt_conf_get_object_member(apps, &name, NULL); 1677 1678 if (nxt_slow_path(app == NULL)) { 1679 goto error; 1680 } 1681 1682 return NXT_OK; 1683 1684 error: 1685 1686 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for " 1687 "a non existing application \"%V\".", 1688 &name); 1689 } 1690 1691 1692 static nxt_int_t 1693 nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, 1694 nxt_conf_value_t *value) 1695 { 1696 nxt_int_t ret; 1697 nxt_str_t type; 1698 nxt_thread_t *thread; 1699 nxt_conf_value_t *type_value; 1700 nxt_app_lang_module_t *lang; 1701 1702 static nxt_str_t type_str = nxt_string("type"); 1703 1704 static struct { 1705 nxt_conf_vldt_handler_t validator; 1706 nxt_conf_vldt_object_t *members; 1707 1708 } types[] = { 1709 { nxt_conf_vldt_object, nxt_conf_vldt_external_members }, 1710 { nxt_conf_vldt_object, nxt_conf_vldt_python_members }, 1711 { nxt_conf_vldt_php, NULL }, 1712 { nxt_conf_vldt_object, nxt_conf_vldt_perl_members }, 1713 { nxt_conf_vldt_object, nxt_conf_vldt_ruby_members }, 1714 { nxt_conf_vldt_object, nxt_conf_vldt_java_members }, 1715 }; 1716 1717 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 1718 1719 if (ret != NXT_OK) { 1720 return ret; 1721 } 1722 1723 type_value = nxt_conf_get_object_member(value, &type_str, NULL); 1724 1725 if (type_value == NULL) { 1726 return nxt_conf_vldt_error(vldt, 1727 "Application must have the \"type\" property set."); 1728 } 1729 1730 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING); 1731 1732 if (ret != NXT_OK) { 1733 return ret; 1734 } 1735 1736 nxt_conf_get_string(type_value, &type); 1737 1738 thread = nxt_thread(); 1739 1740 lang = nxt_app_lang_module(thread->runtime, &type); 1741 if (lang == NULL) { 1742 return nxt_conf_vldt_error(vldt, 1743 "The module to run \"%V\" is not found " 1744 "among the available application modules.", 1745 &type); 1746 } 1747 1748 return types[lang->type].validator(vldt, value, types[lang->type].members); 1749 } 1750 1751 1752 static nxt_int_t 1753 nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1754 void *data) 1755 { 1756 uint32_t index; 1757 nxt_int_t ret; 1758 nxt_str_t name; 1759 nxt_conf_value_t *member; 1760 nxt_conf_vldt_object_t *vals; 1761 1762 index = 0; 1763 1764 for ( ;; ) { 1765 member = nxt_conf_next_object_member(value, &name, &index); 1766 1767 if (member == NULL) { 1768 return NXT_OK; 1769 } 1770 1771 vals = data; 1772 1773 for ( ;; ) { 1774 if (vals->name.length == 0) { 1775 1776 if (vals->data != NULL) { 1777 vals = vals->data; 1778 continue; 1779 } 1780 1781 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".", 1782 &name); 1783 } 1784 1785 if (!nxt_strstr_eq(&vals->name, &name)) { 1786 vals++; 1787 continue; 1788 } 1789 1790 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type); 1791 1792 if (ret != NXT_OK) { 1793 return ret; 1794 } 1795 1796 if (vals->validator != NULL) { 1797 ret = vals->validator(vldt, member, vals->data); 1798 1799 if (ret != NXT_OK) { 1800 return ret; 1801 } 1802 } 1803 1804 break; 1805 } 1806 } 1807 } 1808 1809 1810 typedef struct { 1811 int64_t spare; 1812 int64_t max; 1813 int64_t idle_timeout; 1814 } nxt_conf_vldt_processes_conf_t; 1815 1816 1817 static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = { 1818 { 1819 nxt_string("spare"), 1820 NXT_CONF_MAP_INT64, 1821 offsetof(nxt_conf_vldt_processes_conf_t, spare), 1822 }, 1823 1824 { 1825 nxt_string("max"), 1826 NXT_CONF_MAP_INT64, 1827 offsetof(nxt_conf_vldt_processes_conf_t, max), 1828 }, 1829 1830 { 1831 nxt_string("idle_timeout"), 1832 NXT_CONF_MAP_INT64, 1833 offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout), 1834 }, 1835 }; 1836 1837 1838 static nxt_int_t 1839 nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 1840 void *data) 1841 { 1842 int64_t int_value; 1843 nxt_int_t ret; 1844 nxt_conf_vldt_processes_conf_t proc; 1845 1846 if (nxt_conf_type(value) == NXT_CONF_NUMBER) { 1847 int_value = nxt_conf_get_number(value); 1848 1849 if (int_value < 1) { 1850 return nxt_conf_vldt_error(vldt, "The \"processes\" number must be " 1851 "equal to or greater than 1."); 1852 } 1853 1854 if (int_value > NXT_INT32_T_MAX) { 1855 return nxt_conf_vldt_error(vldt, "The \"processes\" number must " 1856 "not exceed %d.", NXT_INT32_T_MAX); 1857 } 1858 1859 return NXT_OK; 1860 } 1861 1862 ret = nxt_conf_vldt_object(vldt, value, data); 1863 if (ret != NXT_OK) { 1864 return ret; 1865 } 1866 1867 proc.spare = 0; 1868 proc.max = 1; 1869 proc.idle_timeout = 15; 1870 1871 ret = nxt_conf_map_object(vldt->pool, value, 1872 nxt_conf_vldt_processes_conf_map, 1873 nxt_nitems(nxt_conf_vldt_processes_conf_map), 1874 &proc); 1875 if (ret != NXT_OK) { 1876 return ret; 1877 } 1878 1879 if (proc.spare < 0) { 1880 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be " 1881 "negative."); 1882 } 1883 1884 if (proc.spare > NXT_INT32_T_MAX) { 1885 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not " 1886 "exceed %d.", NXT_INT32_T_MAX); 1887 } 1888 1889 if (proc.max < 1) { 1890 return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal " 1891 "to or greater than 1."); 1892 } 1893 1894 if (proc.max > NXT_INT32_T_MAX) { 1895 return nxt_conf_vldt_error(vldt, "The \"max\" number must not " 1896 "exceed %d.", NXT_INT32_T_MAX); 1897 } 1898 1899 if (proc.max < proc.spare) { 1900 return nxt_conf_vldt_error(vldt, "The \"spare\" number must be " 1901 "less than or equal to \"max\"."); 1902 } 1903 1904 if (proc.idle_timeout < 0) { 1905 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " 1906 "be negative."); 1907 } 1908 1909 if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) { 1910 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " 1911 "exceed %d.", NXT_INT32_T_MAX / 1000); 1912 } 1913 1914 return NXT_OK; 1915 } 1916 1917 1918 static nxt_int_t 1919 nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, 1920 nxt_conf_value_t *value, void *data) 1921 { 1922 uint32_t index; 1923 nxt_int_t ret; 1924 nxt_str_t name; 1925 nxt_conf_value_t *member; 1926 nxt_conf_vldt_member_t validator; 1927 1928 validator = (nxt_conf_vldt_member_t) data; 1929 index = 0; 1930 1931 for ( ;; ) { 1932 member = nxt_conf_next_object_member(value, &name, &index); 1933 1934 if (member == NULL) { 1935 return NXT_OK; 1936 } 1937 1938 ret = validator(vldt, &name, member); 1939 1940 if (ret != NXT_OK) { 1941 return ret; 1942 } 1943 } 1944 } 1945 1946 1947 static nxt_int_t 1948 nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, 1949 nxt_conf_value_t *value, void *data) 1950 { 1951 uint32_t index; 1952 nxt_int_t ret; 1953 nxt_conf_value_t *element; 1954 nxt_conf_vldt_element_t validator; 1955 1956 validator = (nxt_conf_vldt_element_t) data; 1957 1958 for (index = 0; /* void */ ; index++) { 1959 element = nxt_conf_get_array_element(value, index); 1960 1961 if (element == NULL) { 1962 return NXT_OK; 1963 } 1964 1965 ret = validator(vldt, element); 1966 1967 if (ret != NXT_OK) { 1968 return ret; 1969 } 1970 } 1971 } 1972 1973 1974 static nxt_int_t 1975 nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, 1976 nxt_conf_value_t *value) 1977 { 1978 nxt_str_t str; 1979 1980 if (name->length == 0) { 1981 return nxt_conf_vldt_error(vldt, 1982 "The environment name must not be empty."); 1983 } 1984 1985 if (nxt_memchr(name->start, '\0', name->length) != NULL) { 1986 return nxt_conf_vldt_error(vldt, "The environment name must not " 1987 "contain null character."); 1988 } 1989 1990 if (nxt_memchr(name->start, '=', name->length) != NULL) { 1991 return nxt_conf_vldt_error(vldt, "The environment name must not " 1992 "contain '=' character."); 1993 } 1994 1995 if (nxt_conf_type(value) != NXT_CONF_STRING) { 1996 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be " 1997 "a string.", name); 1998 } 1999 2000 nxt_conf_get_string(value, &str); 2001 2002 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 2003 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must " 2004 "not contain null character.", name); 2005 } 2006 2007 return NXT_OK; 2008 } 2009 2010 2011 static nxt_int_t 2012 nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt, 2013 nxt_conf_value_t *value, void *data) 2014 { 2015 return nxt_conf_vldt_object(vldt, value, data); 2016 } 2017 2018 2019 static nxt_int_t 2020 nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 2021 void *data) 2022 { 2023 return nxt_conf_vldt_object(vldt, value, data); 2024 } 2025 2026 2027 #if (NXT_HAVE_CLONE_NEWUSER) 2028 2029 typedef struct { 2030 nxt_int_t container; 2031 nxt_int_t host; 2032 nxt_int_t size; 2033 } nxt_conf_vldt_clone_procmap_conf_t; 2034 2035 2036 static nxt_conf_map_t nxt_conf_vldt_clone_procmap_conf_map[] = { 2037 { 2038 nxt_string("container"), 2039 NXT_CONF_MAP_INT32, 2040 offsetof(nxt_conf_vldt_clone_procmap_conf_t, container), 2041 }, 2042 2043 { 2044 nxt_string("host"), 2045 NXT_CONF_MAP_INT32, 2046 offsetof(nxt_conf_vldt_clone_procmap_conf_t, host), 2047 }, 2048 2049 { 2050 nxt_string("size"), 2051 NXT_CONF_MAP_INT32, 2052 offsetof(nxt_conf_vldt_clone_procmap_conf_t, size), 2053 }, 2054 2055 }; 2056 2057 2058 static nxt_int_t 2059 nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt, const char *mapfile, 2060 nxt_conf_value_t *value) 2061 { 2062 nxt_int_t ret; 2063 nxt_conf_vldt_clone_procmap_conf_t procmap; 2064 2065 procmap.container = -1; 2066 procmap.host = -1; 2067 procmap.size = -1; 2068 2069 ret = nxt_conf_map_object(vldt->pool, value, 2070 nxt_conf_vldt_clone_procmap_conf_map, 2071 nxt_nitems(nxt_conf_vldt_clone_procmap_conf_map), 2072 &procmap); 2073 if (ret != NXT_OK) { 2074 return ret; 2075 } 2076 2077 if (procmap.container == -1) { 2078 return nxt_conf_vldt_error(vldt, "The %s requires the " 2079 "\"container\" field set.", mapfile); 2080 } 2081 2082 if (procmap.host == -1) { 2083 return nxt_conf_vldt_error(vldt, "The %s requires the " 2084 "\"host\" field set.", mapfile); 2085 } 2086 2087 if (procmap.size == -1) { 2088 return nxt_conf_vldt_error(vldt, "The %s requires the " 2089 "\"size\" field set.", mapfile); 2090 } 2091 2092 return NXT_OK; 2093 } 2094 2095 2096 static nxt_int_t 2097 nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 2098 { 2099 nxt_int_t ret; 2100 2101 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 2102 return nxt_conf_vldt_error(vldt, "The \"uidmap\" array " 2103 "must contain only object values."); 2104 } 2105 2106 ret = nxt_conf_vldt_object(vldt, value, 2107 (void *) nxt_conf_vldt_app_procmap_members); 2108 if (nxt_slow_path(ret != NXT_OK)) { 2109 return ret; 2110 } 2111 2112 return nxt_conf_vldt_clone_procmap(vldt, "uid_map", value); 2113 } 2114 2115 2116 static nxt_int_t 2117 nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 2118 { 2119 nxt_int_t ret; 2120 2121 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 2122 return nxt_conf_vldt_error(vldt, "The \"gidmap\" array " 2123 "must contain only object values."); 2124 } 2125 2126 ret = nxt_conf_vldt_object(vldt, value, 2127 (void *) nxt_conf_vldt_app_procmap_members); 2128 if (nxt_slow_path(ret != NXT_OK)) { 2129 return ret; 2130 } 2131 2132 return nxt_conf_vldt_clone_procmap(vldt, "gid_map", value); 2133 } 2134 2135 #endif 2136 2137 2138 static nxt_int_t 2139 nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 2140 { 2141 nxt_str_t str; 2142 2143 if (nxt_conf_type(value) != NXT_CONF_STRING) { 2144 return nxt_conf_vldt_error(vldt, "The \"arguments\" array " 2145 "must contain only string values."); 2146 } 2147 2148 nxt_conf_get_string(value, &str); 2149 2150 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 2151 return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " 2152 "contain strings with null character."); 2153 } 2154 2155 return NXT_OK; 2156 } 2157 2158 2159 static nxt_int_t 2160 nxt_conf_vldt_php(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 2161 void *data) 2162 { 2163 nxt_conf_value_t *targets; 2164 2165 static nxt_str_t targets_str = nxt_string("targets"); 2166 2167 targets = nxt_conf_get_object_member(value, &targets_str, NULL); 2168 2169 if (targets != NULL) { 2170 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_members); 2171 } 2172 2173 return nxt_conf_vldt_object(vldt, value, 2174 nxt_conf_vldt_php_notargets_members); 2175 } 2176 2177 2178 static nxt_int_t 2179 nxt_conf_vldt_php_targets_exclusive(nxt_conf_validation_t *vldt, 2180 nxt_conf_value_t *value, void *data) 2181 { 2182 return nxt_conf_vldt_error(vldt, "The \"%s\" option is mutually exclusive " 2183 "with the \"targets\" object.", data); 2184 } 2185 2186 2187 static nxt_int_t 2188 nxt_conf_vldt_php_targets(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 2189 void *data) 2190 { 2191 nxt_uint_t n; 2192 2193 n = nxt_conf_object_members_count(value); 2194 2195 if (n > 254) { 2196 return nxt_conf_vldt_error(vldt, "The \"targets\" object must not " 2197 "contain more than 254 members."); 2198 } 2199 2200 return nxt_conf_vldt_object_iterator(vldt, value, 2201 &nxt_conf_vldt_php_target); 2202 } 2203 2204 2205 static nxt_int_t 2206 nxt_conf_vldt_php_target(nxt_conf_validation_t *vldt, nxt_str_t *name, 2207 nxt_conf_value_t *value) 2208 { 2209 if (name->length == 0) { 2210 return nxt_conf_vldt_error(vldt, 2211 "The PHP target name must not be empty."); 2212 } 2213 2214 if (nxt_conf_type(value) != NXT_CONF_OBJECT) { 2215 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP target must be " 2216 "an object.", name); 2217 } 2218 2219 return nxt_conf_vldt_object(vldt, value, &nxt_conf_vldt_php_target_members); 2220 } 2221 2222 2223 static nxt_int_t 2224 nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name, 2225 nxt_conf_value_t *value) 2226 { 2227 if (name->length == 0) { 2228 return nxt_conf_vldt_error(vldt, 2229 "The PHP option name must not be empty."); 2230 } 2231 2232 if (nxt_conf_type(value) != NXT_CONF_STRING) { 2233 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be " 2234 "a string.", name); 2235 } 2236 2237 return NXT_OK; 2238 } 2239 2240 2241 static nxt_int_t 2242 nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt, 2243 nxt_conf_value_t *value) 2244 { 2245 nxt_str_t str; 2246 2247 if (nxt_conf_type(value) != NXT_CONF_STRING) { 2248 return nxt_conf_vldt_error(vldt, "The \"classpath\" array " 2249 "must contain only string values."); 2250 } 2251 2252 nxt_conf_get_string(value, &str); 2253 2254 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 2255 return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not " 2256 "contain strings with null character."); 2257 } 2258 2259 return NXT_OK; 2260 } 2261 2262 2263 static nxt_int_t 2264 nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 2265 { 2266 nxt_str_t str; 2267 2268 if (nxt_conf_type(value) != NXT_CONF_STRING) { 2269 return nxt_conf_vldt_error(vldt, "The \"options\" array " 2270 "must contain only string values."); 2271 } 2272 2273 nxt_conf_get_string(value, &str); 2274 2275 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 2276 return nxt_conf_vldt_error(vldt, "The \"options\" array must not " 2277 "contain strings with null character."); 2278 } 2279 2280 return NXT_OK; 2281 } 2282 2283 2284 static nxt_int_t 2285 nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name, 2286 nxt_conf_value_t *value) 2287 { 2288 nxt_int_t ret; 2289 nxt_conf_value_t *conf; 2290 2291 static nxt_str_t servers = nxt_string("servers"); 2292 2293 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 2294 2295 if (ret != NXT_OK) { 2296 return ret; 2297 } 2298 2299 ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members); 2300 2301 if (ret != NXT_OK) { 2302 return ret; 2303 } 2304 2305 conf = nxt_conf_get_object_member(value, &servers, NULL); 2306 if (conf == NULL) { 2307 return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain " 2308 "\"servers\" object value.", name); 2309 } 2310 2311 return NXT_OK; 2312 } 2313 2314 2315 static nxt_int_t 2316 nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name, 2317 nxt_conf_value_t *value) 2318 { 2319 nxt_int_t ret; 2320 nxt_sockaddr_t *sa; 2321 2322 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 2323 2324 if (ret != NXT_OK) { 2325 return ret; 2326 } 2327 2328 sa = nxt_sockaddr_parse(vldt->pool, name); 2329 2330 if (sa == NULL) { 2331 return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid " 2332 "server address.", name); 2333 } 2334 2335 return nxt_conf_vldt_object(vldt, value, 2336 nxt_conf_vldt_upstream_server_members); 2337 } 2338 2339 2340 static nxt_int_t 2341 nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt, 2342 nxt_conf_value_t *value, void *data) 2343 { 2344 double num_value; 2345 2346 num_value = nxt_conf_get_number(value); 2347 2348 if (num_value < 0) { 2349 return nxt_conf_vldt_error(vldt, "The \"weight\" number must be " 2350 "positive."); 2351 } 2352 2353 if (num_value > 1000000) { 2354 return nxt_conf_vldt_error(vldt, "The \"weight\" number must " 2355 "not exceed 1,000,000"); 2356 } 2357 2358 return NXT_OK; 2359 } 2360