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