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