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