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