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