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