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