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