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