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