nxt_conf_validation.c (1394:20b41ebfff79) nxt_conf_validation.c (1403:1cee885b7f10)
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
15
16typedef enum {
17 NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL,
18 NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN,
19 NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER,
20 NXT_CONF_VLDT_NUMBER = 1 << NXT_CONF_NUMBER,
21 NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING,
22 NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY,
23 NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT,
24} nxt_conf_vldt_type_t;
25
26
27typedef struct {
28 nxt_str_t name;
29 nxt_conf_vldt_type_t type;
30 nxt_int_t (*validator)(nxt_conf_validation_t *vldt,
31 nxt_conf_value_t *value, void *data);
32 void *data;
33} nxt_conf_vldt_object_t;
34
35
36#define NXT_CONF_VLDT_NEXT(f) { nxt_null_string, 0, NULL, (f) }
37#define NXT_CONF_VLDT_END { nxt_null_string, 0, NULL, NULL }
38
39
40typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
41 nxt_str_t *name,
42 nxt_conf_value_t *value);
43typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt,
44 nxt_conf_value_t *value);
45
46static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
47 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type);
48static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
49 const char *fmt, ...);
50
51static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt,
52 nxt_conf_value_t *value, void *data);
53static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt,
54 nxt_str_t *name, nxt_conf_value_t *value);
55static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
56 nxt_conf_value_t *value);
57static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
58 nxt_str_t *name, nxt_conf_value_t *value);
59#if (NXT_TLS)
60static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt,
61 nxt_conf_value_t *value, void *data);
62#endif
63static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt,
64 nxt_conf_value_t *value, void *data);
65static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt,
66 nxt_conf_value_t *value, void *data);
67static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt,
68 nxt_conf_value_t *value, void *data);
69static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt,
70 nxt_conf_value_t *value, void *data);
71static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt,
72 nxt_str_t *name, nxt_conf_value_t *value);
73static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
74 nxt_conf_value_t *value);
75static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
76 nxt_conf_value_t *value, void *data);
77static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
78 nxt_conf_value_t *value);
79static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
80 nxt_conf_value_t *value, void *data);
81static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
82 nxt_conf_value_t *value);
83static nxt_int_t nxt_conf_vldt_match_patterns_set_member(
84 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
85static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
86 nxt_conf_value_t *value, void *data);
87static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
88 nxt_conf_value_t *value, void *data);
89static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
90 nxt_conf_value_t *value);
91static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
92 nxt_conf_value_t *value, void *data);
93static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
94 nxt_str_t *name, nxt_conf_value_t *value);
95static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
96 nxt_conf_value_t *value, void *data);
97static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt,
98 nxt_conf_value_t *value, void *data);
99static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
100 nxt_conf_value_t *value, void *data);
101static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
102 nxt_conf_value_t *value, void *data);
103static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt,
104 nxt_str_t *name, nxt_conf_value_t *value);
105static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt,
106 nxt_conf_value_t *value);
107static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt,
108 nxt_str_t *name, nxt_conf_value_t *value);
109static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
110 nxt_conf_value_t *value);
111static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt,
112 nxt_conf_value_t *value);
113static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt,
114 nxt_str_t *name, nxt_conf_value_t *value);
115static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
116 nxt_str_t *name, nxt_conf_value_t *value);
117static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
118 nxt_conf_value_t *value, void *data);
119
120static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
121 nxt_conf_value_t *value, void *data);
122static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
123 nxt_conf_value_t *value, void *data);
124
125#if (NXT_HAVE_CLONE_NEWUSER)
126static nxt_int_t nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt,
127 const char* mapfile, nxt_conf_value_t *value);
128static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt,
129 nxt_conf_value_t *value);
130static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt,
131 nxt_conf_value_t *value);
132#endif
133
134static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = {
135 { nxt_string("read_timeout"),
136 NXT_CONF_VLDT_INTEGER,
137 NULL,
138 NULL },
139
140 { nxt_string("keepalive_interval"),
141 NXT_CONF_VLDT_INTEGER,
142 NULL,
143 NULL },
144
145 { nxt_string("max_frame_size"),
146 NXT_CONF_VLDT_INTEGER,
147 NULL,
148 NULL },
149
150 NXT_CONF_VLDT_END
151};
152
153
154static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = {
155 { nxt_string("mime_types"),
156 NXT_CONF_VLDT_OBJECT,
157 &nxt_conf_vldt_mtypes,
158 NULL },
159
160 NXT_CONF_VLDT_END
161};
162
163
164static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = {
165 { nxt_string("header_read_timeout"),
166 NXT_CONF_VLDT_INTEGER,
167 NULL,
168 NULL },
169
170 { nxt_string("body_read_timeout"),
171 NXT_CONF_VLDT_INTEGER,
172 NULL,
173 NULL },
174
175 { nxt_string("send_timeout"),
176 NXT_CONF_VLDT_INTEGER,
177 NULL,
178 NULL },
179
180 { nxt_string("idle_timeout"),
181 NXT_CONF_VLDT_INTEGER,
182 NULL,
183 NULL },
184
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
15
16typedef enum {
17 NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL,
18 NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN,
19 NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER,
20 NXT_CONF_VLDT_NUMBER = 1 << NXT_CONF_NUMBER,
21 NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING,
22 NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY,
23 NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT,
24} nxt_conf_vldt_type_t;
25
26
27typedef struct {
28 nxt_str_t name;
29 nxt_conf_vldt_type_t type;
30 nxt_int_t (*validator)(nxt_conf_validation_t *vldt,
31 nxt_conf_value_t *value, void *data);
32 void *data;
33} nxt_conf_vldt_object_t;
34
35
36#define NXT_CONF_VLDT_NEXT(f) { nxt_null_string, 0, NULL, (f) }
37#define NXT_CONF_VLDT_END { nxt_null_string, 0, NULL, NULL }
38
39
40typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
41 nxt_str_t *name,
42 nxt_conf_value_t *value);
43typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt,
44 nxt_conf_value_t *value);
45
46static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
47 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type);
48static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
49 const char *fmt, ...);
50
51static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt,
52 nxt_conf_value_t *value, void *data);
53static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt,
54 nxt_str_t *name, nxt_conf_value_t *value);
55static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
56 nxt_conf_value_t *value);
57static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
58 nxt_str_t *name, nxt_conf_value_t *value);
59#if (NXT_TLS)
60static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt,
61 nxt_conf_value_t *value, void *data);
62#endif
63static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt,
64 nxt_conf_value_t *value, void *data);
65static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt,
66 nxt_conf_value_t *value, void *data);
67static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt,
68 nxt_conf_value_t *value, void *data);
69static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt,
70 nxt_conf_value_t *value, void *data);
71static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt,
72 nxt_str_t *name, nxt_conf_value_t *value);
73static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
74 nxt_conf_value_t *value);
75static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
76 nxt_conf_value_t *value, void *data);
77static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
78 nxt_conf_value_t *value);
79static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
80 nxt_conf_value_t *value, void *data);
81static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
82 nxt_conf_value_t *value);
83static nxt_int_t nxt_conf_vldt_match_patterns_set_member(
84 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
85static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
86 nxt_conf_value_t *value, void *data);
87static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
88 nxt_conf_value_t *value, void *data);
89static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
90 nxt_conf_value_t *value);
91static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
92 nxt_conf_value_t *value, void *data);
93static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
94 nxt_str_t *name, nxt_conf_value_t *value);
95static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
96 nxt_conf_value_t *value, void *data);
97static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt,
98 nxt_conf_value_t *value, void *data);
99static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
100 nxt_conf_value_t *value, void *data);
101static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
102 nxt_conf_value_t *value, void *data);
103static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt,
104 nxt_str_t *name, nxt_conf_value_t *value);
105static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt,
106 nxt_conf_value_t *value);
107static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt,
108 nxt_str_t *name, nxt_conf_value_t *value);
109static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
110 nxt_conf_value_t *value);
111static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt,
112 nxt_conf_value_t *value);
113static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt,
114 nxt_str_t *name, nxt_conf_value_t *value);
115static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
116 nxt_str_t *name, nxt_conf_value_t *value);
117static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
118 nxt_conf_value_t *value, void *data);
119
120static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
121 nxt_conf_value_t *value, void *data);
122static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
123 nxt_conf_value_t *value, void *data);
124
125#if (NXT_HAVE_CLONE_NEWUSER)
126static nxt_int_t nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt,
127 const char* mapfile, nxt_conf_value_t *value);
128static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt,
129 nxt_conf_value_t *value);
130static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt,
131 nxt_conf_value_t *value);
132#endif
133
134static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = {
135 { nxt_string("read_timeout"),
136 NXT_CONF_VLDT_INTEGER,
137 NULL,
138 NULL },
139
140 { nxt_string("keepalive_interval"),
141 NXT_CONF_VLDT_INTEGER,
142 NULL,
143 NULL },
144
145 { nxt_string("max_frame_size"),
146 NXT_CONF_VLDT_INTEGER,
147 NULL,
148 NULL },
149
150 NXT_CONF_VLDT_END
151};
152
153
154static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = {
155 { nxt_string("mime_types"),
156 NXT_CONF_VLDT_OBJECT,
157 &nxt_conf_vldt_mtypes,
158 NULL },
159
160 NXT_CONF_VLDT_END
161};
162
163
164static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = {
165 { nxt_string("header_read_timeout"),
166 NXT_CONF_VLDT_INTEGER,
167 NULL,
168 NULL },
169
170 { nxt_string("body_read_timeout"),
171 NXT_CONF_VLDT_INTEGER,
172 NULL,
173 NULL },
174
175 { nxt_string("send_timeout"),
176 NXT_CONF_VLDT_INTEGER,
177 NULL,
178 NULL },
179
180 { nxt_string("idle_timeout"),
181 NXT_CONF_VLDT_INTEGER,
182 NULL,
183 NULL },
184
185 { nxt_string("body_buffer_size"),
186 NXT_CONF_VLDT_INTEGER,
187 NULL,
188 NULL },
189
185 { nxt_string("max_body_size"),
186 NXT_CONF_VLDT_INTEGER,
187 NULL,
188 NULL },
189
190 { nxt_string("max_body_size"),
191 NXT_CONF_VLDT_INTEGER,
192 NULL,
193 NULL },
194
195 { nxt_string("body_temp_path"),
196 NXT_CONF_VLDT_STRING,
197 NULL,
198 NULL },
199
190 { nxt_string("websocket"),
191 NXT_CONF_VLDT_OBJECT,
192 &nxt_conf_vldt_object,
193 (void *) &nxt_conf_vldt_websocket_members },
194
195 { nxt_string("static"),
196 NXT_CONF_VLDT_OBJECT,
197 &nxt_conf_vldt_object,
198 (void *) &nxt_conf_vldt_static_members },
199
200 NXT_CONF_VLDT_END
201};
202
203
204static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = {
205 { nxt_string("http"),
206 NXT_CONF_VLDT_OBJECT,
207 &nxt_conf_vldt_object,
208 (void *) &nxt_conf_vldt_http_members },
209
210 NXT_CONF_VLDT_END
211};
212
213
214static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
215 { nxt_string("settings"),
216 NXT_CONF_VLDT_OBJECT,
217 &nxt_conf_vldt_object,
218 (void *) &nxt_conf_vldt_setting_members },
219
220 { nxt_string("listeners"),
221 NXT_CONF_VLDT_OBJECT,
222 &nxt_conf_vldt_object_iterator,
223 (void *) &nxt_conf_vldt_listener },
224
225 { nxt_string("routes"),
226 NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT,
227 &nxt_conf_vldt_routes,
228 NULL },
229
230 { nxt_string("applications"),
231 NXT_CONF_VLDT_OBJECT,
232 &nxt_conf_vldt_object_iterator,
233 (void *) &nxt_conf_vldt_app },
234
235 { nxt_string("upstreams"),
236 NXT_CONF_VLDT_OBJECT,
237 &nxt_conf_vldt_object_iterator,
238 (void *) &nxt_conf_vldt_upstream },
239
240 { nxt_string("access_log"),
241 NXT_CONF_VLDT_STRING,
242 NULL,
243 NULL },
244
245 NXT_CONF_VLDT_END
246};
247
248
249#if (NXT_TLS)
250
251static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = {
252 { nxt_string("certificate"),
253 NXT_CONF_VLDT_STRING,
254 &nxt_conf_vldt_certificate,
255 NULL },
256
257 NXT_CONF_VLDT_END
258};
259
260#endif
261
262
263static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
264 { nxt_string("pass"),
265 NXT_CONF_VLDT_STRING,
266 &nxt_conf_vldt_pass,
267 NULL },
268
269 { nxt_string("application"),
270 NXT_CONF_VLDT_STRING,
271 &nxt_conf_vldt_app_name,
272 NULL },
273
274#if (NXT_TLS)
275
276 { nxt_string("tls"),
277 NXT_CONF_VLDT_OBJECT,
278 &nxt_conf_vldt_object,
279 (void *) &nxt_conf_vldt_tls_members },
280
281#endif
282
283 NXT_CONF_VLDT_END
284};
285
286
287static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
288 { nxt_string("method"),
289 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
290 &nxt_conf_vldt_match_patterns,
291 NULL },
292
293 { nxt_string("scheme"),
294 NXT_CONF_VLDT_STRING,
295 &nxt_conf_vldt_match_scheme_pattern,
296 NULL },
297
298 { nxt_string("host"),
299 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
300 &nxt_conf_vldt_match_patterns,
301 NULL },
302
303 { nxt_string("source"),
304 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
305 &nxt_conf_vldt_match_addrs,
306 NULL },
307
308 { nxt_string("destination"),
309 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
310 &nxt_conf_vldt_match_addrs,
311 NULL },
312
313 { nxt_string("uri"),
314 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
315 &nxt_conf_vldt_match_patterns,
316 NULL },
317
318 { nxt_string("arguments"),
319 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
320 &nxt_conf_vldt_match_patterns_sets,
321 NULL },
322
323 { nxt_string("headers"),
324 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
325 &nxt_conf_vldt_match_patterns_sets,
326 NULL },
327
328 { nxt_string("cookies"),
329 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
330 &nxt_conf_vldt_match_patterns_sets,
331 NULL },
332
333 NXT_CONF_VLDT_END
334};
335
336
337static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
338 { nxt_string("pass"),
339 NXT_CONF_VLDT_STRING,
340 &nxt_conf_vldt_pass,
341 NULL },
342
343 NXT_CONF_VLDT_END
344};
345
346
347static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
348 { nxt_string("share"),
349 NXT_CONF_VLDT_STRING,
350 NULL,
351 NULL },
352
353 { nxt_string("fallback"),
354 NXT_CONF_VLDT_OBJECT,
355 &nxt_conf_vldt_action,
356 NULL },
357
358 NXT_CONF_VLDT_END
359};
360
361
362static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = {
363 { nxt_string("proxy"),
364 NXT_CONF_VLDT_STRING,
365 &nxt_conf_vldt_proxy,
366 NULL },
367
368 NXT_CONF_VLDT_END
369};
370
371
372static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = {
373 { nxt_string("match"),
374 NXT_CONF_VLDT_OBJECT,
375 &nxt_conf_vldt_object,
376 (void *) &nxt_conf_vldt_match_members },
377
378 { nxt_string("action"),
379 NXT_CONF_VLDT_OBJECT,
380 &nxt_conf_vldt_action,
381 NULL },
382
383 NXT_CONF_VLDT_END
384};
385
386
387static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
388 { nxt_string("timeout"),
389 NXT_CONF_VLDT_INTEGER,
390 NULL,
391 NULL },
392
393 { nxt_string("reschedule_timeout"),
394 NXT_CONF_VLDT_INTEGER,
395 NULL,
396 NULL },
397
398 { nxt_string("requests"),
399 NXT_CONF_VLDT_INTEGER,
400 NULL,
401 NULL },
402
403 { nxt_string("shm"),
404 NXT_CONF_VLDT_INTEGER,
405 NULL,
406 NULL },
407
408 NXT_CONF_VLDT_END
409};
410
411
412static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = {
413 { nxt_string("spare"),
414 NXT_CONF_VLDT_INTEGER,
415 NULL,
416 NULL },
417
418 { nxt_string("max"),
419 NXT_CONF_VLDT_INTEGER,
420 NULL,
421 NULL },
422
423 { nxt_string("idle_timeout"),
424 NXT_CONF_VLDT_INTEGER,
425 NULL,
426 NULL },
427
428 NXT_CONF_VLDT_END
429};
430
431
432static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = {
433
434#if (NXT_HAVE_CLONE_NEWUSER)
435 { nxt_string("credential"),
436 NXT_CONF_VLDT_BOOLEAN,
437 NULL,
438 NULL },
439#endif
440
441#if (NXT_HAVE_CLONE_NEWPID)
442 { nxt_string("pid"),
443 NXT_CONF_VLDT_BOOLEAN,
444 NULL,
445 NULL },
446#endif
447
448#if (NXT_HAVE_CLONE_NEWNET)
449 { nxt_string("network"),
450 NXT_CONF_VLDT_BOOLEAN,
451 NULL,
452 NULL },
453#endif
454
455#if (NXT_HAVE_CLONE_NEWNS)
456 { nxt_string("mount"),
457 NXT_CONF_VLDT_BOOLEAN,
458 NULL,
459 NULL },
460#endif
461
462#if (NXT_HAVE_CLONE_NEWUTS)
463 { nxt_string("uname"),
464 NXT_CONF_VLDT_BOOLEAN,
465 NULL,
466 NULL },
467#endif
468
469#if (NXT_HAVE_CLONE_NEWCGROUP)
470 { nxt_string("cgroup"),
471 NXT_CONF_VLDT_BOOLEAN,
472 NULL,
473 NULL },
474#endif
475
476 NXT_CONF_VLDT_END
477};
478
479
480#if (NXT_HAVE_CLONE_NEWUSER)
481
482static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = {
483 { nxt_string("container"),
484 NXT_CONF_VLDT_INTEGER,
485 NULL,
486 NULL },
487
488 { nxt_string("host"),
489 NXT_CONF_VLDT_INTEGER,
490 NULL,
491 NULL },
492
493 { nxt_string("size"),
494 NXT_CONF_VLDT_INTEGER,
495 NULL,
496 NULL },
497};
498
499#endif
500
501
502static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
503 { nxt_string("namespaces"),
504 NXT_CONF_VLDT_OBJECT,
505 &nxt_conf_vldt_clone_namespaces,
506 (void *) &nxt_conf_vldt_app_namespaces_members },
507
508#if (NXT_HAVE_CLONE_NEWUSER)
509
510 { nxt_string("uidmap"),
511 NXT_CONF_VLDT_ARRAY,
512 &nxt_conf_vldt_array_iterator,
513 (void *) &nxt_conf_vldt_clone_uidmap },
514
515 { nxt_string("gidmap"),
516 NXT_CONF_VLDT_ARRAY,
517 &nxt_conf_vldt_array_iterator,
518 (void *) &nxt_conf_vldt_clone_gidmap },
519
520#endif
521
522 NXT_CONF_VLDT_END
523};
524
525
526static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
527 { nxt_string("type"),
528 NXT_CONF_VLDT_STRING,
529 NULL,
530 NULL },
531
532 { nxt_string("limits"),
533 NXT_CONF_VLDT_OBJECT,
534 &nxt_conf_vldt_object,
535 (void *) &nxt_conf_vldt_app_limits_members },
536
537 { nxt_string("processes"),
538 NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT,
539 &nxt_conf_vldt_processes,
540 (void *) &nxt_conf_vldt_app_processes_members },
541
542 { nxt_string("user"),
543 NXT_CONF_VLDT_STRING,
544 NULL,
545 NULL },
546
547 { nxt_string("group"),
548 NXT_CONF_VLDT_STRING,
549 NULL,
550 NULL },
551
552 { nxt_string("working_directory"),
553 NXT_CONF_VLDT_STRING,
554 NULL,
555 NULL },
556
557 { nxt_string("environment"),
558 NXT_CONF_VLDT_OBJECT,
559 &nxt_conf_vldt_object_iterator,
560 (void *) &nxt_conf_vldt_environment },
561
562 { nxt_string("isolation"),
563 NXT_CONF_VLDT_OBJECT,
564 &nxt_conf_vldt_isolation,
565 (void *) &nxt_conf_vldt_app_isolation_members },
566
567 NXT_CONF_VLDT_END
568};
569
570
571static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = {
572 { nxt_string("executable"),
573 NXT_CONF_VLDT_STRING,
574 NULL,
575 NULL },
576
577 { nxt_string("arguments"),
578 NXT_CONF_VLDT_ARRAY,
579 &nxt_conf_vldt_array_iterator,
580 (void *) &nxt_conf_vldt_argument },
581
582 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
583};
584
585
586static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
587 { nxt_string("home"),
588 NXT_CONF_VLDT_STRING,
589 NULL,
590 NULL },
591
592 { nxt_string("path"),
593 NXT_CONF_VLDT_STRING,
594 NULL,
595 NULL },
596
597 { nxt_string("module"),
598 NXT_CONF_VLDT_STRING,
599 NULL,
600 NULL },
601
602 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
603};
604
605
606static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = {
607 { nxt_string("file"),
608 NXT_CONF_VLDT_STRING,
609 NULL,
610 NULL },
611
612 { nxt_string("admin"),
613 NXT_CONF_VLDT_OBJECT,
614 &nxt_conf_vldt_object_iterator,
615 (void *) &nxt_conf_vldt_php_option },
616
617 { nxt_string("user"),
618 NXT_CONF_VLDT_OBJECT,
619 &nxt_conf_vldt_object_iterator,
620 (void *) &nxt_conf_vldt_php_option },
621
622 NXT_CONF_VLDT_END
623};
624
625
626static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
627 { nxt_string("root"),
628 NXT_CONF_VLDT_STRING,
629 NULL,
630 NULL },
631
632 { nxt_string("script"),
633 NXT_CONF_VLDT_STRING,
634 NULL,
635 NULL },
636
637 { nxt_string("index"),
638 NXT_CONF_VLDT_STRING,
639 NULL,
640 NULL },
641
642 { nxt_string("options"),
643 NXT_CONF_VLDT_OBJECT,
644 &nxt_conf_vldt_object,
645 (void *) &nxt_conf_vldt_php_options_members },
646
647 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
648};
649
650
651static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = {
652 { nxt_string("script"),
653 NXT_CONF_VLDT_STRING,
654 NULL,
655 NULL },
656
657 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
658};
659
660
661static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = {
662 { nxt_string("script"),
663 NXT_CONF_VLDT_STRING,
664 NULL,
665 NULL },
666
667 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
668};
669
670
671static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = {
672 { nxt_string("classpath"),
673 NXT_CONF_VLDT_ARRAY,
674 &nxt_conf_vldt_array_iterator,
675 (void *) &nxt_conf_vldt_java_classpath },
676
677 { nxt_string("webapp"),
678 NXT_CONF_VLDT_STRING,
679 NULL,
680 NULL },
681
682 { nxt_string("options"),
683 NXT_CONF_VLDT_ARRAY,
684 &nxt_conf_vldt_array_iterator,
685 (void *) &nxt_conf_vldt_java_option },
686
687 { nxt_string("unit_jars"),
688 NXT_CONF_VLDT_STRING,
689 NULL,
690 NULL },
691
692 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
693};
694
695
696static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = {
697 { nxt_string("servers"),
698 NXT_CONF_VLDT_OBJECT,
699 &nxt_conf_vldt_object_iterator,
700 (void *) &nxt_conf_vldt_server },
701
702 NXT_CONF_VLDT_END
703};
704
705
706static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
707 { nxt_string("weight"),
708 NXT_CONF_VLDT_INTEGER,
709 &nxt_conf_vldt_server_weight,
710 NULL },
711
712 NXT_CONF_VLDT_END
713};
714
715
716nxt_int_t
717nxt_conf_validate(nxt_conf_validation_t *vldt)
718{
719 nxt_int_t ret;
720
721 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
722
723 if (ret != NXT_OK) {
724 return ret;
725 }
726
727 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
728}
729
730
731#define NXT_CONF_VLDT_ANY_TYPE \
732 "either a null, a boolean, an integer, " \
733 "a number, a string, an array, or an object"
734
735
736static nxt_int_t
737nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
738 nxt_conf_value_t *value, nxt_conf_vldt_type_t type)
739{
740 u_char *p;
741 nxt_str_t expected;
742 nxt_bool_t serial;
743 nxt_uint_t value_type, n, t;
744 u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE)];
745
746 static nxt_str_t type_name[] = {
747 nxt_string("a null"),
748 nxt_string("a boolean"),
749 nxt_string("an integer"),
750 nxt_string("a number"),
751 nxt_string("a string"),
752 nxt_string("an array"),
753 nxt_string("an object"),
754 };
755
756 value_type = nxt_conf_type(value);
757
758 if ((1 << value_type) & type) {
759 return NXT_OK;
760 }
761
762 p = buf;
763
764 n = nxt_popcount(type);
765
766 if (n > 1) {
767 p = nxt_cpymem(p, "either ", 7);
768 }
769
770 serial = (n > 2);
771
772 for ( ;; ) {
773 t = __builtin_ffs(type) - 1;
774
775 p = nxt_cpymem(p, type_name[t].start, type_name[t].length);
776
777 n--;
778
779 if (n == 0) {
780 break;
781 }
782
783 if (n > 1 || serial) {
784 *p++ = ',';
785 }
786
787 if (n == 1) {
788 p = nxt_cpymem(p, " or", 3);
789 }
790
791 *p++ = ' ';
792
793 type = type & ~(1 << t);
794 }
795
796 expected.length = p - buf;
797 expected.start = buf;
798
799 if (name == NULL) {
800 return nxt_conf_vldt_error(vldt,
801 "The configuration must be %V, but not %V.",
802 &expected, &type_name[value_type]);
803 }
804
805 return nxt_conf_vldt_error(vldt,
806 "The \"%V\" value must be %V, but not %V.",
807 name, &expected, &type_name[value_type]);
808}
809
810
811static nxt_int_t
812nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
813{
814 u_char *p, *end;
815 size_t size;
816 va_list args;
817 u_char error[NXT_MAX_ERROR_STR];
818
819 va_start(args, fmt);
820 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
821 va_end(args);
822
823 size = end - error;
824
825 p = nxt_mp_nget(vldt->pool, size);
826 if (p == NULL) {
827 return NXT_ERROR;
828 }
829
830 nxt_memcpy(p, error, size);
831
832 vldt->error.length = size;
833 vldt->error.start = p;
834
835 return NXT_DECLINED;
836}
837
838
839typedef struct {
840 nxt_mp_t *pool;
841 nxt_str_t *type;
842 nxt_lvlhsh_t hash;
843} nxt_conf_vldt_mtypes_ctx_t;
844
845
846static nxt_int_t
847nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
848 void *data)
849{
850 nxt_int_t ret;
851 nxt_conf_vldt_mtypes_ctx_t ctx;
852
853 ctx.pool = nxt_mp_create(1024, 128, 256, 32);
854 if (nxt_slow_path(ctx.pool == NULL)) {
855 return NXT_ERROR;
856 }
857
858 nxt_lvlhsh_init(&ctx.hash);
859
860 vldt->ctx = &ctx;
861
862 ret = nxt_conf_vldt_object_iterator(vldt, value,
863 &nxt_conf_vldt_mtypes_type);
864
865 vldt->ctx = NULL;
866
867 nxt_mp_destroy(ctx.pool);
868
869 return ret;
870}
871
872
873static nxt_int_t
874nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
875 nxt_conf_value_t *value)
876{
877 nxt_int_t ret;
878 nxt_conf_vldt_mtypes_ctx_t *ctx;
879
880 ret = nxt_conf_vldt_type(vldt, name, value,
881 NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY);
882 if (ret != NXT_OK) {
883 return ret;
884 }
885
886 ctx = vldt->ctx;
887
888 ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t));
889 if (nxt_slow_path(ctx->type == NULL)) {
890 return NXT_ERROR;
891 }
892
893 *ctx->type = *name;
894
895 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
896 return nxt_conf_vldt_array_iterator(vldt, value,
897 &nxt_conf_vldt_mtypes_extension);
898 }
899
900 /* NXT_CONF_STRING */
901
902 return nxt_conf_vldt_mtypes_extension(vldt, value);
903}
904
905
906static nxt_int_t
907nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
908 nxt_conf_value_t *value)
909{
910 nxt_str_t ext, *dup_type;
911 nxt_conf_vldt_mtypes_ctx_t *ctx;
912
913 ctx = vldt->ctx;
914
915 if (nxt_conf_type(value) != NXT_CONF_STRING) {
916 return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must "
917 "contain only strings.", ctx->type);
918 }
919
920 nxt_conf_get_string(value, &ext);
921
922 if (ext.length == 0) {
923 return nxt_conf_vldt_error(vldt, "An empty file extension for "
924 "the \"%V\" MIME type.", ctx->type);
925 }
926
927 dup_type = nxt_http_static_mtypes_hash_find(&ctx->hash, &ext);
928
929 if (dup_type != NULL) {
930 return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been "
931 "declared for \"%V\" and \"%V\" "
932 "MIME types at the same time.",
933 &ext, dup_type, ctx->type);
934 }
935
936 return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash,
937 &ext, ctx->type);
938}
939
940
941static nxt_int_t
942nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
943 nxt_conf_value_t *value)
944{
945 nxt_int_t ret;
946
947 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
948
949 if (ret != NXT_OK) {
950 return ret;
951 }
952
953 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
954}
955
956
957static nxt_int_t
958nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
959 void *data)
960{
961 nxt_uint_t i;
962 nxt_conf_value_t *action;
963 nxt_conf_vldt_object_t *members;
964
965 static struct {
966 nxt_str_t name;
967 nxt_conf_vldt_object_t *members;
968
969 } actions[] = {
970 { nxt_string("pass"), nxt_conf_vldt_pass_action_members },
971 { nxt_string("share"), nxt_conf_vldt_share_action_members },
972 { nxt_string("proxy"), nxt_conf_vldt_proxy_action_members },
973 };
974
975 members = NULL;
976
977 for (i = 0; i < nxt_nitems(actions); i++) {
978 action = nxt_conf_get_object_member(value, &actions[i].name, NULL);
979
980 if (action == NULL) {
981 continue;
982 }
983
984 if (members != NULL) {
985 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
986 "just one of \"pass\", \"share\" or "
987 "\"proxy\" options set.");
988 }
989
990 members = actions[i].members;
991 }
992
993 if (members == NULL) {
994 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
995 "either \"pass\", \"share\", or "
996 "\"proxy\" option set.");
997 }
998
999 return nxt_conf_vldt_object(vldt, value, members);
1000}
1001
1002
1003static nxt_int_t
1004nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1005 void *data)
1006{
1007 u_char *p;
1008 nxt_str_t pass, first, second;
1009
1010 nxt_conf_get_string(value, &pass);
1011
1012 p = nxt_memchr(pass.start, '/', pass.length);
1013
1014 if (p != NULL) {
1015 first.length = p - pass.start;
1016 first.start = pass.start;
1017
1018 if (pass.length - first.length == 1) {
1019 goto error;
1020 }
1021
1022 second.length = pass.length - first.length - 1;
1023 second.start = p + 1;
1024
1025 } else {
1026 first = pass;
1027 second.length = 0;
1028 }
1029
1030 if (nxt_str_eq(&first, "applications", 12)) {
1031
1032 if (second.length == 0) {
1033 goto error;
1034 }
1035
1036 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1037
1038 if (nxt_slow_path(value == NULL)) {
1039 goto error;
1040 }
1041
1042 value = nxt_conf_get_object_member(value, &second, NULL);
1043
1044 if (nxt_slow_path(value == NULL)) {
1045 goto error;
1046 }
1047
1048 return NXT_OK;
1049 }
1050
1051 if (nxt_str_eq(&first, "upstreams", 9)) {
1052
1053 if (second.length == 0) {
1054 goto error;
1055 }
1056
1057 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1058
1059 if (nxt_slow_path(value == NULL)) {
1060 goto error;
1061 }
1062
1063 value = nxt_conf_get_object_member(value, &second, NULL);
1064
1065 if (nxt_slow_path(value == NULL)) {
1066 goto error;
1067 }
1068
1069 return NXT_OK;
1070 }
1071
1072 if (nxt_str_eq(&first, "routes", 6)) {
1073 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1074
1075 if (nxt_slow_path(value == NULL)) {
1076 goto error;
1077 }
1078
1079 if (second.length == 0) {
1080 if (nxt_conf_type(value) != NXT_CONF_ARRAY) {
1081 goto error;
1082 }
1083
1084 return NXT_OK;
1085 }
1086
1087 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1088 goto error;
1089 }
1090
1091 value = nxt_conf_get_object_member(value, &second, NULL);
1092
1093 if (nxt_slow_path(value == NULL)) {
1094 goto error;
1095 }
1096
1097 return NXT_OK;
1098 }
1099
1100error:
1101
1102 return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid "
1103 "location \"%V\".", &pass);
1104}
1105
1106
1107static nxt_int_t
1108nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1109 void *data)
1110{
1111 nxt_str_t name;
1112 nxt_sockaddr_t *sa;
1113
1114 nxt_conf_get_string(value, &name);
1115
1116 if (nxt_str_start(&name, "http://", 7)) {
1117 name.length -= 7;
1118 name.start += 7;
1119
1120 sa = nxt_sockaddr_parse(vldt->pool, &name);
1121 if (sa != NULL) {
1122 return NXT_OK;
1123 }
1124 }
1125
1126 return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"",
1127 &name);
1128}
1129
1130
1131static nxt_int_t
1132nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1133 void *data)
1134{
1135 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1136 return nxt_conf_vldt_array_iterator(vldt, value,
1137 &nxt_conf_vldt_route);
1138 }
1139
1140 /* NXT_CONF_OBJECT */
1141
1142 return nxt_conf_vldt_object_iterator(vldt, value,
1143 &nxt_conf_vldt_routes_member);
1144}
1145
1146
1147static nxt_int_t
1148nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name,
1149 nxt_conf_value_t *value)
1150{
1151 nxt_int_t ret;
1152
1153 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY);
1154
1155 if (ret != NXT_OK) {
1156 return ret;
1157 }
1158
1159 return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route);
1160}
1161
1162
1163static nxt_int_t
1164nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1165{
1166 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1167 return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain "
1168 "only object values.");
1169 }
1170
1171 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members);
1172}
1173
1174
1175static nxt_int_t
1176nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
1177 nxt_conf_value_t *value, void *data)
1178{
1179 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1180 return nxt_conf_vldt_array_iterator(vldt, value,
1181 &nxt_conf_vldt_match_pattern);
1182 }
1183
1184 /* NXT_CONF_STRING */
1185
1186 return nxt_conf_vldt_match_pattern(vldt, value);
1187}
1188
1189
1190static nxt_int_t
1191nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
1192 nxt_conf_value_t *value)
1193{
1194 u_char ch;
1195 nxt_str_t pattern;
1196 nxt_uint_t i, first, last;
1197
1198 enum {
1199 sw_none,
1200 sw_side,
1201 sw_middle
1202 } state;
1203
1204 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1205 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for \"host\", "
1206 "\"uri\", and \"method\" must be strings.");
1207 }
1208
1209 nxt_conf_get_string(value, &pattern);
1210
1211 if (pattern.length == 0) {
1212 return NXT_OK;
1213 }
1214
1215 first = (pattern.start[0] == '!');
1216 last = pattern.length - 1;
1217 state = sw_none;
1218
1219 for (i = first; i != pattern.length; i++) {
1220
1221 ch = pattern.start[i];
1222
1223 if (ch != '*') {
1224 continue;
1225 }
1226
1227 switch (state) {
1228 case sw_none:
1229 state = (i == first) ? sw_side : sw_middle;
1230 break;
1231
1232 case sw_side:
1233 if (i == last) {
1234 if (last - first != 1) {
1235 break;
1236 }
1237
1238 return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
1239 "not contain double \"*\" markers.");
1240 }
1241
1242 /* Fall through. */
1243
1244 case sw_middle:
1245 return nxt_conf_vldt_error(vldt, "The \"match\" patterns can "
1246 "either contain \"*\" markers at "
1247 "the sides or only one in the middle.");
1248 }
1249 }
1250
1251 return NXT_OK;
1252}
1253
1254
1255static nxt_int_t
1256nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
1257 nxt_conf_value_t *value, void *data)
1258{
1259 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1260 return nxt_conf_vldt_array_iterator(vldt, value,
1261 &nxt_conf_vldt_match_addr);
1262 }
1263
1264 return nxt_conf_vldt_match_addr(vldt, value);
1265}
1266
1267
1268static nxt_int_t
1269nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
1270 nxt_conf_value_t *value)
1271{
1272 nxt_http_route_addr_pattern_t pattern;
1273
1274 switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) {
1275
1276 case NXT_OK:
1277 return NXT_OK;
1278
1279 case NXT_ADDR_PATTERN_PORT_ERROR:
1280 return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid "
1281 "port.");
1282
1283 case NXT_ADDR_PATTERN_CV_TYPE_ERROR:
1284 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
1285 "\"address\" must be a string.");
1286
1287 case NXT_ADDR_PATTERN_LENGTH_ERROR:
1288 return nxt_conf_vldt_error(vldt, "The \"address\" is too short.");
1289
1290 case NXT_ADDR_PATTERN_FORMAT_ERROR:
1291 return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid.");
1292
1293 case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR:
1294 return nxt_conf_vldt_error(vldt, "The \"address\" range is "
1295 "overlapping.");
1296
1297 case NXT_ADDR_PATTERN_CIDR_ERROR:
1298 return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR "
1299 "prefix.");
1300
1301 case NXT_ADDR_PATTERN_NO_IPv6_ERROR:
1302 return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
1303 "IPv6 with your configuration.");
1304
1305 default:
1306 return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
1307 "format.");
1308 }
1309}
1310
1311
1312static nxt_int_t
1313nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
1314 nxt_conf_value_t *value, void *data)
1315{
1316 nxt_str_t scheme;
1317
1318 static const nxt_str_t http = nxt_string("http");
1319 static const nxt_str_t https = nxt_string("https");
1320
1321 nxt_conf_get_string(value, &scheme);
1322
1323 if (nxt_strcasestr_eq(&scheme, &http)
1324 || nxt_strcasestr_eq(&scheme, &https))
1325 {
1326 return NXT_OK;
1327 }
1328
1329 return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be "
1330 "\"http\" or \"https\".");
1331}
1332
1333
1334static nxt_int_t
1335nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
1336 nxt_conf_value_t *value, void *data)
1337{
1338 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1339 return nxt_conf_vldt_array_iterator(vldt, value,
1340 &nxt_conf_vldt_match_patterns_set);
1341 }
1342
1343 /* NXT_CONF_OBJECT */
1344
1345 return nxt_conf_vldt_match_patterns_set(vldt, value);
1346}
1347
1348
1349static nxt_int_t
1350nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
1351 nxt_conf_value_t *value)
1352{
1353 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1354 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for "
1355 "\"arguments\", \"cookies\", and "
1356 "\"headers\" must be objects.");
1357 }
1358
1359 return nxt_conf_vldt_object_iterator(vldt, value,
1360 &nxt_conf_vldt_match_patterns_set_member);
1361}
1362
1363
1364static nxt_int_t
1365nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt,
1366 nxt_str_t *name, nxt_conf_value_t *value)
1367{
1368 if (name->length == 0) {
1369 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
1370 "not contain empty member names.");
1371 }
1372
1373 return nxt_conf_vldt_match_patterns(vldt, value, NULL);
1374}
1375
1376
1377#if (NXT_TLS)
1378
1379static nxt_int_t
1380nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1381 void *data)
1382{
1383 nxt_str_t name;
1384 nxt_conf_value_t *cert;
1385
1386 nxt_conf_get_string(value, &name);
1387
1388 cert = nxt_cert_info_get(&name);
1389
1390 if (cert == NULL) {
1391 return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.",
1392 &name);
1393 }
1394
1395 return NXT_OK;
1396}
1397
1398#endif
1399
1400
1401static nxt_int_t
1402nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1403 void *data)
1404{
1405 nxt_str_t name;
1406 nxt_conf_value_t *apps, *app;
1407
1408 static nxt_str_t apps_str = nxt_string("applications");
1409
1410 nxt_conf_get_string(value, &name);
1411
1412 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
1413
1414 if (nxt_slow_path(apps == NULL)) {
1415 goto error;
1416 }
1417
1418 app = nxt_conf_get_object_member(apps, &name, NULL);
1419
1420 if (nxt_slow_path(app == NULL)) {
1421 goto error;
1422 }
1423
1424 return NXT_OK;
1425
1426error:
1427
1428 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
1429 "a non existing application \"%V\".",
1430 &name);
1431}
1432
1433
1434static nxt_int_t
1435nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
1436 nxt_conf_value_t *value)
1437{
1438 nxt_int_t ret;
1439 nxt_str_t type;
1440 nxt_thread_t *thread;
1441 nxt_conf_value_t *type_value;
1442 nxt_app_lang_module_t *lang;
1443
1444 static nxt_str_t type_str = nxt_string("type");
1445
1446 static void *members[] = {
1447 nxt_conf_vldt_external_members,
1448 nxt_conf_vldt_python_members,
1449 nxt_conf_vldt_php_members,
1450 nxt_conf_vldt_perl_members,
1451 nxt_conf_vldt_ruby_members,
1452 nxt_conf_vldt_java_members,
1453 };
1454
1455 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1456
1457 if (ret != NXT_OK) {
1458 return ret;
1459 }
1460
1461 type_value = nxt_conf_get_object_member(value, &type_str, NULL);
1462
1463 if (type_value == NULL) {
1464 return nxt_conf_vldt_error(vldt,
1465 "Application must have the \"type\" property set.");
1466 }
1467
1468 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING);
1469
1470 if (ret != NXT_OK) {
1471 return ret;
1472 }
1473
1474 nxt_conf_get_string(type_value, &type);
1475
1476 thread = nxt_thread();
1477
1478 lang = nxt_app_lang_module(thread->runtime, &type);
1479 if (lang == NULL) {
1480 return nxt_conf_vldt_error(vldt,
1481 "The module to run \"%V\" is not found "
1482 "among the available application modules.",
1483 &type);
1484 }
1485
1486 return nxt_conf_vldt_object(vldt, value, members[lang->type]);
1487}
1488
1489
1490static nxt_int_t
1491nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1492 void *data)
1493{
1494 uint32_t index;
1495 nxt_int_t ret;
1496 nxt_str_t name;
1497 nxt_conf_value_t *member;
1498 nxt_conf_vldt_object_t *vals;
1499
1500 index = 0;
1501
1502 for ( ;; ) {
1503 member = nxt_conf_next_object_member(value, &name, &index);
1504
1505 if (member == NULL) {
1506 return NXT_OK;
1507 }
1508
1509 vals = data;
1510
1511 for ( ;; ) {
1512 if (vals->name.length == 0) {
1513
1514 if (vals->data != NULL) {
1515 vals = vals->data;
1516 continue;
1517 }
1518
1519 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
1520 &name);
1521 }
1522
1523 if (!nxt_strstr_eq(&vals->name, &name)) {
1524 vals++;
1525 continue;
1526 }
1527
1528 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
1529
1530 if (ret != NXT_OK) {
1531 return ret;
1532 }
1533
1534 if (vals->validator != NULL) {
1535 ret = vals->validator(vldt, member, vals->data);
1536
1537 if (ret != NXT_OK) {
1538 return ret;
1539 }
1540 }
1541
1542 break;
1543 }
1544 }
1545}
1546
1547
1548typedef struct {
1549 int64_t spare;
1550 int64_t max;
1551 int64_t idle_timeout;
1552} nxt_conf_vldt_processes_conf_t;
1553
1554
1555static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = {
1556 {
1557 nxt_string("spare"),
1558 NXT_CONF_MAP_INT64,
1559 offsetof(nxt_conf_vldt_processes_conf_t, spare),
1560 },
1561
1562 {
1563 nxt_string("max"),
1564 NXT_CONF_MAP_INT64,
1565 offsetof(nxt_conf_vldt_processes_conf_t, max),
1566 },
1567
1568 {
1569 nxt_string("idle_timeout"),
1570 NXT_CONF_MAP_INT64,
1571 offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout),
1572 },
1573};
1574
1575
1576static nxt_int_t
1577nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1578 void *data)
1579{
1580 int64_t int_value;
1581 nxt_int_t ret;
1582 nxt_conf_vldt_processes_conf_t proc;
1583
1584 if (nxt_conf_type(value) == NXT_CONF_INTEGER) {
1585 int_value = nxt_conf_get_integer(value);
1586
1587 if (int_value < 1) {
1588 return nxt_conf_vldt_error(vldt, "The \"processes\" number must be "
1589 "equal to or greater than 1.");
1590 }
1591
1592 if (int_value > NXT_INT32_T_MAX) {
1593 return nxt_conf_vldt_error(vldt, "The \"processes\" number must "
1594 "not exceed %d.", NXT_INT32_T_MAX);
1595 }
1596
1597 return NXT_OK;
1598 }
1599
1600 ret = nxt_conf_vldt_object(vldt, value, data);
1601 if (ret != NXT_OK) {
1602 return ret;
1603 }
1604
1605 proc.spare = 0;
1606 proc.max = 1;
1607 proc.idle_timeout = 15;
1608
1609 ret = nxt_conf_map_object(vldt->pool, value,
1610 nxt_conf_vldt_processes_conf_map,
1611 nxt_nitems(nxt_conf_vldt_processes_conf_map),
1612 &proc);
1613 if (ret != NXT_OK) {
1614 return ret;
1615 }
1616
1617 if (proc.spare < 0) {
1618 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be "
1619 "negative.");
1620 }
1621
1622 if (proc.spare > NXT_INT32_T_MAX) {
1623 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not "
1624 "exceed %d.", NXT_INT32_T_MAX);
1625 }
1626
1627 if (proc.max < 1) {
1628 return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal "
1629 "to or greater than 1.");
1630 }
1631
1632 if (proc.max > NXT_INT32_T_MAX) {
1633 return nxt_conf_vldt_error(vldt, "The \"max\" number must not "
1634 "exceed %d.", NXT_INT32_T_MAX);
1635 }
1636
1637 if (proc.max < proc.spare) {
1638 return nxt_conf_vldt_error(vldt, "The \"spare\" number must be "
1639 "less than or equal to \"max\".");
1640 }
1641
1642 if (proc.idle_timeout < 0) {
1643 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
1644 "be negative.");
1645 }
1646
1647 if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) {
1648 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
1649 "exceed %d.", NXT_INT32_T_MAX / 1000);
1650 }
1651
1652 return NXT_OK;
1653}
1654
1655
1656static nxt_int_t
1657nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
1658 nxt_conf_value_t *value, void *data)
1659{
1660 uint32_t index;
1661 nxt_int_t ret;
1662 nxt_str_t name;
1663 nxt_conf_value_t *member;
1664 nxt_conf_vldt_member_t validator;
1665
1666 validator = (nxt_conf_vldt_member_t) data;
1667 index = 0;
1668
1669 for ( ;; ) {
1670 member = nxt_conf_next_object_member(value, &name, &index);
1671
1672 if (member == NULL) {
1673 return NXT_OK;
1674 }
1675
1676 ret = validator(vldt, &name, member);
1677
1678 if (ret != NXT_OK) {
1679 return ret;
1680 }
1681 }
1682}
1683
1684
1685static nxt_int_t
1686nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
1687 nxt_conf_value_t *value, void *data)
1688{
1689 uint32_t index;
1690 nxt_int_t ret;
1691 nxt_conf_value_t *element;
1692 nxt_conf_vldt_element_t validator;
1693
1694 validator = (nxt_conf_vldt_element_t) data;
1695
1696 for (index = 0; /* void */ ; index++) {
1697 element = nxt_conf_get_array_element(value, index);
1698
1699 if (element == NULL) {
1700 return NXT_OK;
1701 }
1702
1703 ret = validator(vldt, element);
1704
1705 if (ret != NXT_OK) {
1706 return ret;
1707 }
1708 }
1709}
1710
1711
1712static nxt_int_t
1713nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name,
1714 nxt_conf_value_t *value)
1715{
1716 nxt_str_t str;
1717
1718 if (name->length == 0) {
1719 return nxt_conf_vldt_error(vldt,
1720 "The environment name must not be empty.");
1721 }
1722
1723 if (nxt_memchr(name->start, '\0', name->length) != NULL) {
1724 return nxt_conf_vldt_error(vldt, "The environment name must not "
1725 "contain null character.");
1726 }
1727
1728 if (nxt_memchr(name->start, '=', name->length) != NULL) {
1729 return nxt_conf_vldt_error(vldt, "The environment name must not "
1730 "contain '=' character.");
1731 }
1732
1733 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1734 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be "
1735 "a string.", name);
1736 }
1737
1738 nxt_conf_get_string(value, &str);
1739
1740 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1741 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must "
1742 "not contain null character.", name);
1743 }
1744
1745 return NXT_OK;
1746}
1747
1748
1749static nxt_int_t
1750nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
1751 nxt_conf_value_t *value, void *data)
1752{
1753 return nxt_conf_vldt_object(vldt, value, data);
1754}
1755
1756
1757static nxt_int_t
1758nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1759 void *data)
1760{
1761 return nxt_conf_vldt_object(vldt, value, data);
1762}
1763
1764
1765#if (NXT_HAVE_CLONE_NEWUSER)
1766
1767typedef struct {
1768 nxt_int_t container;
1769 nxt_int_t host;
1770 nxt_int_t size;
1771} nxt_conf_vldt_clone_procmap_conf_t;
1772
1773
1774static nxt_conf_map_t nxt_conf_vldt_clone_procmap_conf_map[] = {
1775 {
1776 nxt_string("container"),
1777 NXT_CONF_MAP_INT32,
1778 offsetof(nxt_conf_vldt_clone_procmap_conf_t, container),
1779 },
1780
1781 {
1782 nxt_string("host"),
1783 NXT_CONF_MAP_INT32,
1784 offsetof(nxt_conf_vldt_clone_procmap_conf_t, host),
1785 },
1786
1787 {
1788 nxt_string("size"),
1789 NXT_CONF_MAP_INT32,
1790 offsetof(nxt_conf_vldt_clone_procmap_conf_t, size),
1791 },
1792
1793};
1794
1795
1796static nxt_int_t
1797nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt, const char *mapfile,
1798 nxt_conf_value_t *value)
1799{
1800 nxt_int_t ret;
1801 nxt_conf_vldt_clone_procmap_conf_t procmap;
1802
1803 procmap.container = -1;
1804 procmap.host = -1;
1805 procmap.size = -1;
1806
1807 ret = nxt_conf_map_object(vldt->pool, value,
1808 nxt_conf_vldt_clone_procmap_conf_map,
1809 nxt_nitems(nxt_conf_vldt_clone_procmap_conf_map),
1810 &procmap);
1811 if (ret != NXT_OK) {
1812 return ret;
1813 }
1814
1815 if (procmap.container == -1) {
1816 return nxt_conf_vldt_error(vldt, "The %s requires the "
1817 "\"container\" field set.", mapfile);
1818 }
1819
1820 if (procmap.host == -1) {
1821 return nxt_conf_vldt_error(vldt, "The %s requires the "
1822 "\"host\" field set.", mapfile);
1823 }
1824
1825 if (procmap.size == -1) {
1826 return nxt_conf_vldt_error(vldt, "The %s requires the "
1827 "\"size\" field set.", mapfile);
1828 }
1829
1830 return NXT_OK;
1831}
1832
1833
1834static nxt_int_t
1835nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1836{
1837 nxt_int_t ret;
1838
1839 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1840 return nxt_conf_vldt_error(vldt, "The \"uidmap\" array "
1841 "must contain only object values.");
1842 }
1843
1844 ret = nxt_conf_vldt_object(vldt, value,
1845 (void *) nxt_conf_vldt_app_procmap_members);
1846 if (nxt_slow_path(ret != NXT_OK)) {
1847 return ret;
1848 }
1849
1850 return nxt_conf_vldt_clone_procmap(vldt, "uid_map", value);
1851}
1852
1853
1854static nxt_int_t
1855nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1856{
1857 nxt_int_t ret;
1858
1859 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1860 return nxt_conf_vldt_error(vldt, "The \"gidmap\" array "
1861 "must contain only object values.");
1862 }
1863
1864 ret = nxt_conf_vldt_object(vldt, value,
1865 (void *) nxt_conf_vldt_app_procmap_members);
1866 if (nxt_slow_path(ret != NXT_OK)) {
1867 return ret;
1868 }
1869
1870 return nxt_conf_vldt_clone_procmap(vldt, "gid_map", value);
1871}
1872
1873#endif
1874
1875
1876static nxt_int_t
1877nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1878{
1879 nxt_str_t str;
1880
1881 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1882 return nxt_conf_vldt_error(vldt, "The \"arguments\" array "
1883 "must contain only string values.");
1884 }
1885
1886 nxt_conf_get_string(value, &str);
1887
1888 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1889 return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not "
1890 "contain strings with null character.");
1891 }
1892
1893 return NXT_OK;
1894}
1895
1896
1897static nxt_int_t
1898nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name,
1899 nxt_conf_value_t *value)
1900{
1901 if (name->length == 0) {
1902 return nxt_conf_vldt_error(vldt,
1903 "The PHP option name must not be empty.");
1904 }
1905
1906 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1907 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be "
1908 "a string.", name);
1909 }
1910
1911 return NXT_OK;
1912}
1913
1914
1915static nxt_int_t
1916nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
1917 nxt_conf_value_t *value)
1918{
1919 nxt_str_t str;
1920
1921 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1922 return nxt_conf_vldt_error(vldt, "The \"classpath\" array "
1923 "must contain only string values.");
1924 }
1925
1926 nxt_conf_get_string(value, &str);
1927
1928 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1929 return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not "
1930 "contain strings with null character.");
1931 }
1932
1933 return NXT_OK;
1934}
1935
1936
1937static nxt_int_t
1938nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1939{
1940 nxt_str_t str;
1941
1942 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1943 return nxt_conf_vldt_error(vldt, "The \"options\" array "
1944 "must contain only string values.");
1945 }
1946
1947 nxt_conf_get_string(value, &str);
1948
1949 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1950 return nxt_conf_vldt_error(vldt, "The \"options\" array must not "
1951 "contain strings with null character.");
1952 }
1953
1954 return NXT_OK;
1955}
1956
1957
1958static nxt_int_t
1959nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name,
1960 nxt_conf_value_t *value)
1961{
1962 nxt_int_t ret;
1963 nxt_conf_value_t *conf;
1964
1965 static nxt_str_t servers = nxt_string("servers");
1966
1967 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1968
1969 if (ret != NXT_OK) {
1970 return ret;
1971 }
1972
1973 ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members);
1974
1975 if (ret != NXT_OK) {
1976 return ret;
1977 }
1978
1979 conf = nxt_conf_get_object_member(value, &servers, NULL);
1980 if (conf == NULL) {
1981 return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain "
1982 "\"servers\" object value.", name);
1983 }
1984
1985 return NXT_OK;
1986}
1987
1988
1989static nxt_int_t
1990nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name,
1991 nxt_conf_value_t *value)
1992{
1993 nxt_int_t ret;
1994 nxt_sockaddr_t *sa;
1995
1996 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1997
1998 if (ret != NXT_OK) {
1999 return ret;
2000 }
2001
2002 sa = nxt_sockaddr_parse(vldt->pool, name);
2003
2004 if (sa == NULL) {
2005 return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid "
2006 "server address.", name);
2007 }
2008
2009 return nxt_conf_vldt_object(vldt, value,
2010 nxt_conf_vldt_upstream_server_members);
2011}
2012
2013
2014static nxt_int_t
2015nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
2016 nxt_conf_value_t *value, void *data)
2017{
2018 int64_t int_value;
2019
2020 int_value = nxt_conf_get_integer(value);
2021
2022 if (int_value <= 0) {
2023 return nxt_conf_vldt_error(vldt, "The \"weight\" number must be "
2024 "greater than 0.");
2025 }
2026
2027 if (int_value > NXT_INT32_T_MAX) {
2028 return nxt_conf_vldt_error(vldt, "The \"weight\" number must "
2029 "not exceed %d.", NXT_INT32_T_MAX);
2030 }
2031
2032 return NXT_OK;
2033}
200 { nxt_string("websocket"),
201 NXT_CONF_VLDT_OBJECT,
202 &nxt_conf_vldt_object,
203 (void *) &nxt_conf_vldt_websocket_members },
204
205 { nxt_string("static"),
206 NXT_CONF_VLDT_OBJECT,
207 &nxt_conf_vldt_object,
208 (void *) &nxt_conf_vldt_static_members },
209
210 NXT_CONF_VLDT_END
211};
212
213
214static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = {
215 { nxt_string("http"),
216 NXT_CONF_VLDT_OBJECT,
217 &nxt_conf_vldt_object,
218 (void *) &nxt_conf_vldt_http_members },
219
220 NXT_CONF_VLDT_END
221};
222
223
224static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
225 { nxt_string("settings"),
226 NXT_CONF_VLDT_OBJECT,
227 &nxt_conf_vldt_object,
228 (void *) &nxt_conf_vldt_setting_members },
229
230 { nxt_string("listeners"),
231 NXT_CONF_VLDT_OBJECT,
232 &nxt_conf_vldt_object_iterator,
233 (void *) &nxt_conf_vldt_listener },
234
235 { nxt_string("routes"),
236 NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT,
237 &nxt_conf_vldt_routes,
238 NULL },
239
240 { nxt_string("applications"),
241 NXT_CONF_VLDT_OBJECT,
242 &nxt_conf_vldt_object_iterator,
243 (void *) &nxt_conf_vldt_app },
244
245 { nxt_string("upstreams"),
246 NXT_CONF_VLDT_OBJECT,
247 &nxt_conf_vldt_object_iterator,
248 (void *) &nxt_conf_vldt_upstream },
249
250 { nxt_string("access_log"),
251 NXT_CONF_VLDT_STRING,
252 NULL,
253 NULL },
254
255 NXT_CONF_VLDT_END
256};
257
258
259#if (NXT_TLS)
260
261static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = {
262 { nxt_string("certificate"),
263 NXT_CONF_VLDT_STRING,
264 &nxt_conf_vldt_certificate,
265 NULL },
266
267 NXT_CONF_VLDT_END
268};
269
270#endif
271
272
273static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
274 { nxt_string("pass"),
275 NXT_CONF_VLDT_STRING,
276 &nxt_conf_vldt_pass,
277 NULL },
278
279 { nxt_string("application"),
280 NXT_CONF_VLDT_STRING,
281 &nxt_conf_vldt_app_name,
282 NULL },
283
284#if (NXT_TLS)
285
286 { nxt_string("tls"),
287 NXT_CONF_VLDT_OBJECT,
288 &nxt_conf_vldt_object,
289 (void *) &nxt_conf_vldt_tls_members },
290
291#endif
292
293 NXT_CONF_VLDT_END
294};
295
296
297static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
298 { nxt_string("method"),
299 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
300 &nxt_conf_vldt_match_patterns,
301 NULL },
302
303 { nxt_string("scheme"),
304 NXT_CONF_VLDT_STRING,
305 &nxt_conf_vldt_match_scheme_pattern,
306 NULL },
307
308 { nxt_string("host"),
309 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
310 &nxt_conf_vldt_match_patterns,
311 NULL },
312
313 { nxt_string("source"),
314 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
315 &nxt_conf_vldt_match_addrs,
316 NULL },
317
318 { nxt_string("destination"),
319 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
320 &nxt_conf_vldt_match_addrs,
321 NULL },
322
323 { nxt_string("uri"),
324 NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
325 &nxt_conf_vldt_match_patterns,
326 NULL },
327
328 { nxt_string("arguments"),
329 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
330 &nxt_conf_vldt_match_patterns_sets,
331 NULL },
332
333 { nxt_string("headers"),
334 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
335 &nxt_conf_vldt_match_patterns_sets,
336 NULL },
337
338 { nxt_string("cookies"),
339 NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
340 &nxt_conf_vldt_match_patterns_sets,
341 NULL },
342
343 NXT_CONF_VLDT_END
344};
345
346
347static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
348 { nxt_string("pass"),
349 NXT_CONF_VLDT_STRING,
350 &nxt_conf_vldt_pass,
351 NULL },
352
353 NXT_CONF_VLDT_END
354};
355
356
357static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
358 { nxt_string("share"),
359 NXT_CONF_VLDT_STRING,
360 NULL,
361 NULL },
362
363 { nxt_string("fallback"),
364 NXT_CONF_VLDT_OBJECT,
365 &nxt_conf_vldt_action,
366 NULL },
367
368 NXT_CONF_VLDT_END
369};
370
371
372static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = {
373 { nxt_string("proxy"),
374 NXT_CONF_VLDT_STRING,
375 &nxt_conf_vldt_proxy,
376 NULL },
377
378 NXT_CONF_VLDT_END
379};
380
381
382static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = {
383 { nxt_string("match"),
384 NXT_CONF_VLDT_OBJECT,
385 &nxt_conf_vldt_object,
386 (void *) &nxt_conf_vldt_match_members },
387
388 { nxt_string("action"),
389 NXT_CONF_VLDT_OBJECT,
390 &nxt_conf_vldt_action,
391 NULL },
392
393 NXT_CONF_VLDT_END
394};
395
396
397static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
398 { nxt_string("timeout"),
399 NXT_CONF_VLDT_INTEGER,
400 NULL,
401 NULL },
402
403 { nxt_string("reschedule_timeout"),
404 NXT_CONF_VLDT_INTEGER,
405 NULL,
406 NULL },
407
408 { nxt_string("requests"),
409 NXT_CONF_VLDT_INTEGER,
410 NULL,
411 NULL },
412
413 { nxt_string("shm"),
414 NXT_CONF_VLDT_INTEGER,
415 NULL,
416 NULL },
417
418 NXT_CONF_VLDT_END
419};
420
421
422static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = {
423 { nxt_string("spare"),
424 NXT_CONF_VLDT_INTEGER,
425 NULL,
426 NULL },
427
428 { nxt_string("max"),
429 NXT_CONF_VLDT_INTEGER,
430 NULL,
431 NULL },
432
433 { nxt_string("idle_timeout"),
434 NXT_CONF_VLDT_INTEGER,
435 NULL,
436 NULL },
437
438 NXT_CONF_VLDT_END
439};
440
441
442static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = {
443
444#if (NXT_HAVE_CLONE_NEWUSER)
445 { nxt_string("credential"),
446 NXT_CONF_VLDT_BOOLEAN,
447 NULL,
448 NULL },
449#endif
450
451#if (NXT_HAVE_CLONE_NEWPID)
452 { nxt_string("pid"),
453 NXT_CONF_VLDT_BOOLEAN,
454 NULL,
455 NULL },
456#endif
457
458#if (NXT_HAVE_CLONE_NEWNET)
459 { nxt_string("network"),
460 NXT_CONF_VLDT_BOOLEAN,
461 NULL,
462 NULL },
463#endif
464
465#if (NXT_HAVE_CLONE_NEWNS)
466 { nxt_string("mount"),
467 NXT_CONF_VLDT_BOOLEAN,
468 NULL,
469 NULL },
470#endif
471
472#if (NXT_HAVE_CLONE_NEWUTS)
473 { nxt_string("uname"),
474 NXT_CONF_VLDT_BOOLEAN,
475 NULL,
476 NULL },
477#endif
478
479#if (NXT_HAVE_CLONE_NEWCGROUP)
480 { nxt_string("cgroup"),
481 NXT_CONF_VLDT_BOOLEAN,
482 NULL,
483 NULL },
484#endif
485
486 NXT_CONF_VLDT_END
487};
488
489
490#if (NXT_HAVE_CLONE_NEWUSER)
491
492static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = {
493 { nxt_string("container"),
494 NXT_CONF_VLDT_INTEGER,
495 NULL,
496 NULL },
497
498 { nxt_string("host"),
499 NXT_CONF_VLDT_INTEGER,
500 NULL,
501 NULL },
502
503 { nxt_string("size"),
504 NXT_CONF_VLDT_INTEGER,
505 NULL,
506 NULL },
507};
508
509#endif
510
511
512static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
513 { nxt_string("namespaces"),
514 NXT_CONF_VLDT_OBJECT,
515 &nxt_conf_vldt_clone_namespaces,
516 (void *) &nxt_conf_vldt_app_namespaces_members },
517
518#if (NXT_HAVE_CLONE_NEWUSER)
519
520 { nxt_string("uidmap"),
521 NXT_CONF_VLDT_ARRAY,
522 &nxt_conf_vldt_array_iterator,
523 (void *) &nxt_conf_vldt_clone_uidmap },
524
525 { nxt_string("gidmap"),
526 NXT_CONF_VLDT_ARRAY,
527 &nxt_conf_vldt_array_iterator,
528 (void *) &nxt_conf_vldt_clone_gidmap },
529
530#endif
531
532 NXT_CONF_VLDT_END
533};
534
535
536static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
537 { nxt_string("type"),
538 NXT_CONF_VLDT_STRING,
539 NULL,
540 NULL },
541
542 { nxt_string("limits"),
543 NXT_CONF_VLDT_OBJECT,
544 &nxt_conf_vldt_object,
545 (void *) &nxt_conf_vldt_app_limits_members },
546
547 { nxt_string("processes"),
548 NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT,
549 &nxt_conf_vldt_processes,
550 (void *) &nxt_conf_vldt_app_processes_members },
551
552 { nxt_string("user"),
553 NXT_CONF_VLDT_STRING,
554 NULL,
555 NULL },
556
557 { nxt_string("group"),
558 NXT_CONF_VLDT_STRING,
559 NULL,
560 NULL },
561
562 { nxt_string("working_directory"),
563 NXT_CONF_VLDT_STRING,
564 NULL,
565 NULL },
566
567 { nxt_string("environment"),
568 NXT_CONF_VLDT_OBJECT,
569 &nxt_conf_vldt_object_iterator,
570 (void *) &nxt_conf_vldt_environment },
571
572 { nxt_string("isolation"),
573 NXT_CONF_VLDT_OBJECT,
574 &nxt_conf_vldt_isolation,
575 (void *) &nxt_conf_vldt_app_isolation_members },
576
577 NXT_CONF_VLDT_END
578};
579
580
581static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = {
582 { nxt_string("executable"),
583 NXT_CONF_VLDT_STRING,
584 NULL,
585 NULL },
586
587 { nxt_string("arguments"),
588 NXT_CONF_VLDT_ARRAY,
589 &nxt_conf_vldt_array_iterator,
590 (void *) &nxt_conf_vldt_argument },
591
592 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
593};
594
595
596static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
597 { nxt_string("home"),
598 NXT_CONF_VLDT_STRING,
599 NULL,
600 NULL },
601
602 { nxt_string("path"),
603 NXT_CONF_VLDT_STRING,
604 NULL,
605 NULL },
606
607 { nxt_string("module"),
608 NXT_CONF_VLDT_STRING,
609 NULL,
610 NULL },
611
612 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
613};
614
615
616static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = {
617 { nxt_string("file"),
618 NXT_CONF_VLDT_STRING,
619 NULL,
620 NULL },
621
622 { nxt_string("admin"),
623 NXT_CONF_VLDT_OBJECT,
624 &nxt_conf_vldt_object_iterator,
625 (void *) &nxt_conf_vldt_php_option },
626
627 { nxt_string("user"),
628 NXT_CONF_VLDT_OBJECT,
629 &nxt_conf_vldt_object_iterator,
630 (void *) &nxt_conf_vldt_php_option },
631
632 NXT_CONF_VLDT_END
633};
634
635
636static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
637 { nxt_string("root"),
638 NXT_CONF_VLDT_STRING,
639 NULL,
640 NULL },
641
642 { nxt_string("script"),
643 NXT_CONF_VLDT_STRING,
644 NULL,
645 NULL },
646
647 { nxt_string("index"),
648 NXT_CONF_VLDT_STRING,
649 NULL,
650 NULL },
651
652 { nxt_string("options"),
653 NXT_CONF_VLDT_OBJECT,
654 &nxt_conf_vldt_object,
655 (void *) &nxt_conf_vldt_php_options_members },
656
657 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
658};
659
660
661static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = {
662 { nxt_string("script"),
663 NXT_CONF_VLDT_STRING,
664 NULL,
665 NULL },
666
667 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
668};
669
670
671static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = {
672 { nxt_string("script"),
673 NXT_CONF_VLDT_STRING,
674 NULL,
675 NULL },
676
677 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
678};
679
680
681static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = {
682 { nxt_string("classpath"),
683 NXT_CONF_VLDT_ARRAY,
684 &nxt_conf_vldt_array_iterator,
685 (void *) &nxt_conf_vldt_java_classpath },
686
687 { nxt_string("webapp"),
688 NXT_CONF_VLDT_STRING,
689 NULL,
690 NULL },
691
692 { nxt_string("options"),
693 NXT_CONF_VLDT_ARRAY,
694 &nxt_conf_vldt_array_iterator,
695 (void *) &nxt_conf_vldt_java_option },
696
697 { nxt_string("unit_jars"),
698 NXT_CONF_VLDT_STRING,
699 NULL,
700 NULL },
701
702 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members)
703};
704
705
706static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = {
707 { nxt_string("servers"),
708 NXT_CONF_VLDT_OBJECT,
709 &nxt_conf_vldt_object_iterator,
710 (void *) &nxt_conf_vldt_server },
711
712 NXT_CONF_VLDT_END
713};
714
715
716static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
717 { nxt_string("weight"),
718 NXT_CONF_VLDT_INTEGER,
719 &nxt_conf_vldt_server_weight,
720 NULL },
721
722 NXT_CONF_VLDT_END
723};
724
725
726nxt_int_t
727nxt_conf_validate(nxt_conf_validation_t *vldt)
728{
729 nxt_int_t ret;
730
731 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
732
733 if (ret != NXT_OK) {
734 return ret;
735 }
736
737 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
738}
739
740
741#define NXT_CONF_VLDT_ANY_TYPE \
742 "either a null, a boolean, an integer, " \
743 "a number, a string, an array, or an object"
744
745
746static nxt_int_t
747nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
748 nxt_conf_value_t *value, nxt_conf_vldt_type_t type)
749{
750 u_char *p;
751 nxt_str_t expected;
752 nxt_bool_t serial;
753 nxt_uint_t value_type, n, t;
754 u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE)];
755
756 static nxt_str_t type_name[] = {
757 nxt_string("a null"),
758 nxt_string("a boolean"),
759 nxt_string("an integer"),
760 nxt_string("a number"),
761 nxt_string("a string"),
762 nxt_string("an array"),
763 nxt_string("an object"),
764 };
765
766 value_type = nxt_conf_type(value);
767
768 if ((1 << value_type) & type) {
769 return NXT_OK;
770 }
771
772 p = buf;
773
774 n = nxt_popcount(type);
775
776 if (n > 1) {
777 p = nxt_cpymem(p, "either ", 7);
778 }
779
780 serial = (n > 2);
781
782 for ( ;; ) {
783 t = __builtin_ffs(type) - 1;
784
785 p = nxt_cpymem(p, type_name[t].start, type_name[t].length);
786
787 n--;
788
789 if (n == 0) {
790 break;
791 }
792
793 if (n > 1 || serial) {
794 *p++ = ',';
795 }
796
797 if (n == 1) {
798 p = nxt_cpymem(p, " or", 3);
799 }
800
801 *p++ = ' ';
802
803 type = type & ~(1 << t);
804 }
805
806 expected.length = p - buf;
807 expected.start = buf;
808
809 if (name == NULL) {
810 return nxt_conf_vldt_error(vldt,
811 "The configuration must be %V, but not %V.",
812 &expected, &type_name[value_type]);
813 }
814
815 return nxt_conf_vldt_error(vldt,
816 "The \"%V\" value must be %V, but not %V.",
817 name, &expected, &type_name[value_type]);
818}
819
820
821static nxt_int_t
822nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
823{
824 u_char *p, *end;
825 size_t size;
826 va_list args;
827 u_char error[NXT_MAX_ERROR_STR];
828
829 va_start(args, fmt);
830 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
831 va_end(args);
832
833 size = end - error;
834
835 p = nxt_mp_nget(vldt->pool, size);
836 if (p == NULL) {
837 return NXT_ERROR;
838 }
839
840 nxt_memcpy(p, error, size);
841
842 vldt->error.length = size;
843 vldt->error.start = p;
844
845 return NXT_DECLINED;
846}
847
848
849typedef struct {
850 nxt_mp_t *pool;
851 nxt_str_t *type;
852 nxt_lvlhsh_t hash;
853} nxt_conf_vldt_mtypes_ctx_t;
854
855
856static nxt_int_t
857nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
858 void *data)
859{
860 nxt_int_t ret;
861 nxt_conf_vldt_mtypes_ctx_t ctx;
862
863 ctx.pool = nxt_mp_create(1024, 128, 256, 32);
864 if (nxt_slow_path(ctx.pool == NULL)) {
865 return NXT_ERROR;
866 }
867
868 nxt_lvlhsh_init(&ctx.hash);
869
870 vldt->ctx = &ctx;
871
872 ret = nxt_conf_vldt_object_iterator(vldt, value,
873 &nxt_conf_vldt_mtypes_type);
874
875 vldt->ctx = NULL;
876
877 nxt_mp_destroy(ctx.pool);
878
879 return ret;
880}
881
882
883static nxt_int_t
884nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
885 nxt_conf_value_t *value)
886{
887 nxt_int_t ret;
888 nxt_conf_vldt_mtypes_ctx_t *ctx;
889
890 ret = nxt_conf_vldt_type(vldt, name, value,
891 NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY);
892 if (ret != NXT_OK) {
893 return ret;
894 }
895
896 ctx = vldt->ctx;
897
898 ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t));
899 if (nxt_slow_path(ctx->type == NULL)) {
900 return NXT_ERROR;
901 }
902
903 *ctx->type = *name;
904
905 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
906 return nxt_conf_vldt_array_iterator(vldt, value,
907 &nxt_conf_vldt_mtypes_extension);
908 }
909
910 /* NXT_CONF_STRING */
911
912 return nxt_conf_vldt_mtypes_extension(vldt, value);
913}
914
915
916static nxt_int_t
917nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
918 nxt_conf_value_t *value)
919{
920 nxt_str_t ext, *dup_type;
921 nxt_conf_vldt_mtypes_ctx_t *ctx;
922
923 ctx = vldt->ctx;
924
925 if (nxt_conf_type(value) != NXT_CONF_STRING) {
926 return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must "
927 "contain only strings.", ctx->type);
928 }
929
930 nxt_conf_get_string(value, &ext);
931
932 if (ext.length == 0) {
933 return nxt_conf_vldt_error(vldt, "An empty file extension for "
934 "the \"%V\" MIME type.", ctx->type);
935 }
936
937 dup_type = nxt_http_static_mtypes_hash_find(&ctx->hash, &ext);
938
939 if (dup_type != NULL) {
940 return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been "
941 "declared for \"%V\" and \"%V\" "
942 "MIME types at the same time.",
943 &ext, dup_type, ctx->type);
944 }
945
946 return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash,
947 &ext, ctx->type);
948}
949
950
951static nxt_int_t
952nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
953 nxt_conf_value_t *value)
954{
955 nxt_int_t ret;
956
957 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
958
959 if (ret != NXT_OK) {
960 return ret;
961 }
962
963 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
964}
965
966
967static nxt_int_t
968nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
969 void *data)
970{
971 nxt_uint_t i;
972 nxt_conf_value_t *action;
973 nxt_conf_vldt_object_t *members;
974
975 static struct {
976 nxt_str_t name;
977 nxt_conf_vldt_object_t *members;
978
979 } actions[] = {
980 { nxt_string("pass"), nxt_conf_vldt_pass_action_members },
981 { nxt_string("share"), nxt_conf_vldt_share_action_members },
982 { nxt_string("proxy"), nxt_conf_vldt_proxy_action_members },
983 };
984
985 members = NULL;
986
987 for (i = 0; i < nxt_nitems(actions); i++) {
988 action = nxt_conf_get_object_member(value, &actions[i].name, NULL);
989
990 if (action == NULL) {
991 continue;
992 }
993
994 if (members != NULL) {
995 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
996 "just one of \"pass\", \"share\" or "
997 "\"proxy\" options set.");
998 }
999
1000 members = actions[i].members;
1001 }
1002
1003 if (members == NULL) {
1004 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
1005 "either \"pass\", \"share\", or "
1006 "\"proxy\" option set.");
1007 }
1008
1009 return nxt_conf_vldt_object(vldt, value, members);
1010}
1011
1012
1013static nxt_int_t
1014nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1015 void *data)
1016{
1017 u_char *p;
1018 nxt_str_t pass, first, second;
1019
1020 nxt_conf_get_string(value, &pass);
1021
1022 p = nxt_memchr(pass.start, '/', pass.length);
1023
1024 if (p != NULL) {
1025 first.length = p - pass.start;
1026 first.start = pass.start;
1027
1028 if (pass.length - first.length == 1) {
1029 goto error;
1030 }
1031
1032 second.length = pass.length - first.length - 1;
1033 second.start = p + 1;
1034
1035 } else {
1036 first = pass;
1037 second.length = 0;
1038 }
1039
1040 if (nxt_str_eq(&first, "applications", 12)) {
1041
1042 if (second.length == 0) {
1043 goto error;
1044 }
1045
1046 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1047
1048 if (nxt_slow_path(value == NULL)) {
1049 goto error;
1050 }
1051
1052 value = nxt_conf_get_object_member(value, &second, NULL);
1053
1054 if (nxt_slow_path(value == NULL)) {
1055 goto error;
1056 }
1057
1058 return NXT_OK;
1059 }
1060
1061 if (nxt_str_eq(&first, "upstreams", 9)) {
1062
1063 if (second.length == 0) {
1064 goto error;
1065 }
1066
1067 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1068
1069 if (nxt_slow_path(value == NULL)) {
1070 goto error;
1071 }
1072
1073 value = nxt_conf_get_object_member(value, &second, NULL);
1074
1075 if (nxt_slow_path(value == NULL)) {
1076 goto error;
1077 }
1078
1079 return NXT_OK;
1080 }
1081
1082 if (nxt_str_eq(&first, "routes", 6)) {
1083 value = nxt_conf_get_object_member(vldt->conf, &first, NULL);
1084
1085 if (nxt_slow_path(value == NULL)) {
1086 goto error;
1087 }
1088
1089 if (second.length == 0) {
1090 if (nxt_conf_type(value) != NXT_CONF_ARRAY) {
1091 goto error;
1092 }
1093
1094 return NXT_OK;
1095 }
1096
1097 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1098 goto error;
1099 }
1100
1101 value = nxt_conf_get_object_member(value, &second, NULL);
1102
1103 if (nxt_slow_path(value == NULL)) {
1104 goto error;
1105 }
1106
1107 return NXT_OK;
1108 }
1109
1110error:
1111
1112 return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid "
1113 "location \"%V\".", &pass);
1114}
1115
1116
1117static nxt_int_t
1118nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1119 void *data)
1120{
1121 nxt_str_t name;
1122 nxt_sockaddr_t *sa;
1123
1124 nxt_conf_get_string(value, &name);
1125
1126 if (nxt_str_start(&name, "http://", 7)) {
1127 name.length -= 7;
1128 name.start += 7;
1129
1130 sa = nxt_sockaddr_parse(vldt->pool, &name);
1131 if (sa != NULL) {
1132 return NXT_OK;
1133 }
1134 }
1135
1136 return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"",
1137 &name);
1138}
1139
1140
1141static nxt_int_t
1142nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1143 void *data)
1144{
1145 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1146 return nxt_conf_vldt_array_iterator(vldt, value,
1147 &nxt_conf_vldt_route);
1148 }
1149
1150 /* NXT_CONF_OBJECT */
1151
1152 return nxt_conf_vldt_object_iterator(vldt, value,
1153 &nxt_conf_vldt_routes_member);
1154}
1155
1156
1157static nxt_int_t
1158nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name,
1159 nxt_conf_value_t *value)
1160{
1161 nxt_int_t ret;
1162
1163 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY);
1164
1165 if (ret != NXT_OK) {
1166 return ret;
1167 }
1168
1169 return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route);
1170}
1171
1172
1173static nxt_int_t
1174nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1175{
1176 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1177 return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain "
1178 "only object values.");
1179 }
1180
1181 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members);
1182}
1183
1184
1185static nxt_int_t
1186nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
1187 nxt_conf_value_t *value, void *data)
1188{
1189 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1190 return nxt_conf_vldt_array_iterator(vldt, value,
1191 &nxt_conf_vldt_match_pattern);
1192 }
1193
1194 /* NXT_CONF_STRING */
1195
1196 return nxt_conf_vldt_match_pattern(vldt, value);
1197}
1198
1199
1200static nxt_int_t
1201nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
1202 nxt_conf_value_t *value)
1203{
1204 u_char ch;
1205 nxt_str_t pattern;
1206 nxt_uint_t i, first, last;
1207
1208 enum {
1209 sw_none,
1210 sw_side,
1211 sw_middle
1212 } state;
1213
1214 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1215 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for \"host\", "
1216 "\"uri\", and \"method\" must be strings.");
1217 }
1218
1219 nxt_conf_get_string(value, &pattern);
1220
1221 if (pattern.length == 0) {
1222 return NXT_OK;
1223 }
1224
1225 first = (pattern.start[0] == '!');
1226 last = pattern.length - 1;
1227 state = sw_none;
1228
1229 for (i = first; i != pattern.length; i++) {
1230
1231 ch = pattern.start[i];
1232
1233 if (ch != '*') {
1234 continue;
1235 }
1236
1237 switch (state) {
1238 case sw_none:
1239 state = (i == first) ? sw_side : sw_middle;
1240 break;
1241
1242 case sw_side:
1243 if (i == last) {
1244 if (last - first != 1) {
1245 break;
1246 }
1247
1248 return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
1249 "not contain double \"*\" markers.");
1250 }
1251
1252 /* Fall through. */
1253
1254 case sw_middle:
1255 return nxt_conf_vldt_error(vldt, "The \"match\" patterns can "
1256 "either contain \"*\" markers at "
1257 "the sides or only one in the middle.");
1258 }
1259 }
1260
1261 return NXT_OK;
1262}
1263
1264
1265static nxt_int_t
1266nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
1267 nxt_conf_value_t *value, void *data)
1268{
1269 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1270 return nxt_conf_vldt_array_iterator(vldt, value,
1271 &nxt_conf_vldt_match_addr);
1272 }
1273
1274 return nxt_conf_vldt_match_addr(vldt, value);
1275}
1276
1277
1278static nxt_int_t
1279nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
1280 nxt_conf_value_t *value)
1281{
1282 nxt_http_route_addr_pattern_t pattern;
1283
1284 switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) {
1285
1286 case NXT_OK:
1287 return NXT_OK;
1288
1289 case NXT_ADDR_PATTERN_PORT_ERROR:
1290 return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid "
1291 "port.");
1292
1293 case NXT_ADDR_PATTERN_CV_TYPE_ERROR:
1294 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
1295 "\"address\" must be a string.");
1296
1297 case NXT_ADDR_PATTERN_LENGTH_ERROR:
1298 return nxt_conf_vldt_error(vldt, "The \"address\" is too short.");
1299
1300 case NXT_ADDR_PATTERN_FORMAT_ERROR:
1301 return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid.");
1302
1303 case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR:
1304 return nxt_conf_vldt_error(vldt, "The \"address\" range is "
1305 "overlapping.");
1306
1307 case NXT_ADDR_PATTERN_CIDR_ERROR:
1308 return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR "
1309 "prefix.");
1310
1311 case NXT_ADDR_PATTERN_NO_IPv6_ERROR:
1312 return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
1313 "IPv6 with your configuration.");
1314
1315 default:
1316 return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
1317 "format.");
1318 }
1319}
1320
1321
1322static nxt_int_t
1323nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
1324 nxt_conf_value_t *value, void *data)
1325{
1326 nxt_str_t scheme;
1327
1328 static const nxt_str_t http = nxt_string("http");
1329 static const nxt_str_t https = nxt_string("https");
1330
1331 nxt_conf_get_string(value, &scheme);
1332
1333 if (nxt_strcasestr_eq(&scheme, &http)
1334 || nxt_strcasestr_eq(&scheme, &https))
1335 {
1336 return NXT_OK;
1337 }
1338
1339 return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be "
1340 "\"http\" or \"https\".");
1341}
1342
1343
1344static nxt_int_t
1345nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
1346 nxt_conf_value_t *value, void *data)
1347{
1348 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1349 return nxt_conf_vldt_array_iterator(vldt, value,
1350 &nxt_conf_vldt_match_patterns_set);
1351 }
1352
1353 /* NXT_CONF_OBJECT */
1354
1355 return nxt_conf_vldt_match_patterns_set(vldt, value);
1356}
1357
1358
1359static nxt_int_t
1360nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
1361 nxt_conf_value_t *value)
1362{
1363 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1364 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for "
1365 "\"arguments\", \"cookies\", and "
1366 "\"headers\" must be objects.");
1367 }
1368
1369 return nxt_conf_vldt_object_iterator(vldt, value,
1370 &nxt_conf_vldt_match_patterns_set_member);
1371}
1372
1373
1374static nxt_int_t
1375nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt,
1376 nxt_str_t *name, nxt_conf_value_t *value)
1377{
1378 if (name->length == 0) {
1379 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
1380 "not contain empty member names.");
1381 }
1382
1383 return nxt_conf_vldt_match_patterns(vldt, value, NULL);
1384}
1385
1386
1387#if (NXT_TLS)
1388
1389static nxt_int_t
1390nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1391 void *data)
1392{
1393 nxt_str_t name;
1394 nxt_conf_value_t *cert;
1395
1396 nxt_conf_get_string(value, &name);
1397
1398 cert = nxt_cert_info_get(&name);
1399
1400 if (cert == NULL) {
1401 return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.",
1402 &name);
1403 }
1404
1405 return NXT_OK;
1406}
1407
1408#endif
1409
1410
1411static nxt_int_t
1412nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1413 void *data)
1414{
1415 nxt_str_t name;
1416 nxt_conf_value_t *apps, *app;
1417
1418 static nxt_str_t apps_str = nxt_string("applications");
1419
1420 nxt_conf_get_string(value, &name);
1421
1422 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
1423
1424 if (nxt_slow_path(apps == NULL)) {
1425 goto error;
1426 }
1427
1428 app = nxt_conf_get_object_member(apps, &name, NULL);
1429
1430 if (nxt_slow_path(app == NULL)) {
1431 goto error;
1432 }
1433
1434 return NXT_OK;
1435
1436error:
1437
1438 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
1439 "a non existing application \"%V\".",
1440 &name);
1441}
1442
1443
1444static nxt_int_t
1445nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
1446 nxt_conf_value_t *value)
1447{
1448 nxt_int_t ret;
1449 nxt_str_t type;
1450 nxt_thread_t *thread;
1451 nxt_conf_value_t *type_value;
1452 nxt_app_lang_module_t *lang;
1453
1454 static nxt_str_t type_str = nxt_string("type");
1455
1456 static void *members[] = {
1457 nxt_conf_vldt_external_members,
1458 nxt_conf_vldt_python_members,
1459 nxt_conf_vldt_php_members,
1460 nxt_conf_vldt_perl_members,
1461 nxt_conf_vldt_ruby_members,
1462 nxt_conf_vldt_java_members,
1463 };
1464
1465 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1466
1467 if (ret != NXT_OK) {
1468 return ret;
1469 }
1470
1471 type_value = nxt_conf_get_object_member(value, &type_str, NULL);
1472
1473 if (type_value == NULL) {
1474 return nxt_conf_vldt_error(vldt,
1475 "Application must have the \"type\" property set.");
1476 }
1477
1478 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING);
1479
1480 if (ret != NXT_OK) {
1481 return ret;
1482 }
1483
1484 nxt_conf_get_string(type_value, &type);
1485
1486 thread = nxt_thread();
1487
1488 lang = nxt_app_lang_module(thread->runtime, &type);
1489 if (lang == NULL) {
1490 return nxt_conf_vldt_error(vldt,
1491 "The module to run \"%V\" is not found "
1492 "among the available application modules.",
1493 &type);
1494 }
1495
1496 return nxt_conf_vldt_object(vldt, value, members[lang->type]);
1497}
1498
1499
1500static nxt_int_t
1501nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1502 void *data)
1503{
1504 uint32_t index;
1505 nxt_int_t ret;
1506 nxt_str_t name;
1507 nxt_conf_value_t *member;
1508 nxt_conf_vldt_object_t *vals;
1509
1510 index = 0;
1511
1512 for ( ;; ) {
1513 member = nxt_conf_next_object_member(value, &name, &index);
1514
1515 if (member == NULL) {
1516 return NXT_OK;
1517 }
1518
1519 vals = data;
1520
1521 for ( ;; ) {
1522 if (vals->name.length == 0) {
1523
1524 if (vals->data != NULL) {
1525 vals = vals->data;
1526 continue;
1527 }
1528
1529 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
1530 &name);
1531 }
1532
1533 if (!nxt_strstr_eq(&vals->name, &name)) {
1534 vals++;
1535 continue;
1536 }
1537
1538 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
1539
1540 if (ret != NXT_OK) {
1541 return ret;
1542 }
1543
1544 if (vals->validator != NULL) {
1545 ret = vals->validator(vldt, member, vals->data);
1546
1547 if (ret != NXT_OK) {
1548 return ret;
1549 }
1550 }
1551
1552 break;
1553 }
1554 }
1555}
1556
1557
1558typedef struct {
1559 int64_t spare;
1560 int64_t max;
1561 int64_t idle_timeout;
1562} nxt_conf_vldt_processes_conf_t;
1563
1564
1565static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = {
1566 {
1567 nxt_string("spare"),
1568 NXT_CONF_MAP_INT64,
1569 offsetof(nxt_conf_vldt_processes_conf_t, spare),
1570 },
1571
1572 {
1573 nxt_string("max"),
1574 NXT_CONF_MAP_INT64,
1575 offsetof(nxt_conf_vldt_processes_conf_t, max),
1576 },
1577
1578 {
1579 nxt_string("idle_timeout"),
1580 NXT_CONF_MAP_INT64,
1581 offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout),
1582 },
1583};
1584
1585
1586static nxt_int_t
1587nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1588 void *data)
1589{
1590 int64_t int_value;
1591 nxt_int_t ret;
1592 nxt_conf_vldt_processes_conf_t proc;
1593
1594 if (nxt_conf_type(value) == NXT_CONF_INTEGER) {
1595 int_value = nxt_conf_get_integer(value);
1596
1597 if (int_value < 1) {
1598 return nxt_conf_vldt_error(vldt, "The \"processes\" number must be "
1599 "equal to or greater than 1.");
1600 }
1601
1602 if (int_value > NXT_INT32_T_MAX) {
1603 return nxt_conf_vldt_error(vldt, "The \"processes\" number must "
1604 "not exceed %d.", NXT_INT32_T_MAX);
1605 }
1606
1607 return NXT_OK;
1608 }
1609
1610 ret = nxt_conf_vldt_object(vldt, value, data);
1611 if (ret != NXT_OK) {
1612 return ret;
1613 }
1614
1615 proc.spare = 0;
1616 proc.max = 1;
1617 proc.idle_timeout = 15;
1618
1619 ret = nxt_conf_map_object(vldt->pool, value,
1620 nxt_conf_vldt_processes_conf_map,
1621 nxt_nitems(nxt_conf_vldt_processes_conf_map),
1622 &proc);
1623 if (ret != NXT_OK) {
1624 return ret;
1625 }
1626
1627 if (proc.spare < 0) {
1628 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be "
1629 "negative.");
1630 }
1631
1632 if (proc.spare > NXT_INT32_T_MAX) {
1633 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not "
1634 "exceed %d.", NXT_INT32_T_MAX);
1635 }
1636
1637 if (proc.max < 1) {
1638 return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal "
1639 "to or greater than 1.");
1640 }
1641
1642 if (proc.max > NXT_INT32_T_MAX) {
1643 return nxt_conf_vldt_error(vldt, "The \"max\" number must not "
1644 "exceed %d.", NXT_INT32_T_MAX);
1645 }
1646
1647 if (proc.max < proc.spare) {
1648 return nxt_conf_vldt_error(vldt, "The \"spare\" number must be "
1649 "less than or equal to \"max\".");
1650 }
1651
1652 if (proc.idle_timeout < 0) {
1653 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
1654 "be negative.");
1655 }
1656
1657 if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) {
1658 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
1659 "exceed %d.", NXT_INT32_T_MAX / 1000);
1660 }
1661
1662 return NXT_OK;
1663}
1664
1665
1666static nxt_int_t
1667nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
1668 nxt_conf_value_t *value, void *data)
1669{
1670 uint32_t index;
1671 nxt_int_t ret;
1672 nxt_str_t name;
1673 nxt_conf_value_t *member;
1674 nxt_conf_vldt_member_t validator;
1675
1676 validator = (nxt_conf_vldt_member_t) data;
1677 index = 0;
1678
1679 for ( ;; ) {
1680 member = nxt_conf_next_object_member(value, &name, &index);
1681
1682 if (member == NULL) {
1683 return NXT_OK;
1684 }
1685
1686 ret = validator(vldt, &name, member);
1687
1688 if (ret != NXT_OK) {
1689 return ret;
1690 }
1691 }
1692}
1693
1694
1695static nxt_int_t
1696nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
1697 nxt_conf_value_t *value, void *data)
1698{
1699 uint32_t index;
1700 nxt_int_t ret;
1701 nxt_conf_value_t *element;
1702 nxt_conf_vldt_element_t validator;
1703
1704 validator = (nxt_conf_vldt_element_t) data;
1705
1706 for (index = 0; /* void */ ; index++) {
1707 element = nxt_conf_get_array_element(value, index);
1708
1709 if (element == NULL) {
1710 return NXT_OK;
1711 }
1712
1713 ret = validator(vldt, element);
1714
1715 if (ret != NXT_OK) {
1716 return ret;
1717 }
1718 }
1719}
1720
1721
1722static nxt_int_t
1723nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name,
1724 nxt_conf_value_t *value)
1725{
1726 nxt_str_t str;
1727
1728 if (name->length == 0) {
1729 return nxt_conf_vldt_error(vldt,
1730 "The environment name must not be empty.");
1731 }
1732
1733 if (nxt_memchr(name->start, '\0', name->length) != NULL) {
1734 return nxt_conf_vldt_error(vldt, "The environment name must not "
1735 "contain null character.");
1736 }
1737
1738 if (nxt_memchr(name->start, '=', name->length) != NULL) {
1739 return nxt_conf_vldt_error(vldt, "The environment name must not "
1740 "contain '=' character.");
1741 }
1742
1743 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1744 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be "
1745 "a string.", name);
1746 }
1747
1748 nxt_conf_get_string(value, &str);
1749
1750 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1751 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must "
1752 "not contain null character.", name);
1753 }
1754
1755 return NXT_OK;
1756}
1757
1758
1759static nxt_int_t
1760nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
1761 nxt_conf_value_t *value, void *data)
1762{
1763 return nxt_conf_vldt_object(vldt, value, data);
1764}
1765
1766
1767static nxt_int_t
1768nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1769 void *data)
1770{
1771 return nxt_conf_vldt_object(vldt, value, data);
1772}
1773
1774
1775#if (NXT_HAVE_CLONE_NEWUSER)
1776
1777typedef struct {
1778 nxt_int_t container;
1779 nxt_int_t host;
1780 nxt_int_t size;
1781} nxt_conf_vldt_clone_procmap_conf_t;
1782
1783
1784static nxt_conf_map_t nxt_conf_vldt_clone_procmap_conf_map[] = {
1785 {
1786 nxt_string("container"),
1787 NXT_CONF_MAP_INT32,
1788 offsetof(nxt_conf_vldt_clone_procmap_conf_t, container),
1789 },
1790
1791 {
1792 nxt_string("host"),
1793 NXT_CONF_MAP_INT32,
1794 offsetof(nxt_conf_vldt_clone_procmap_conf_t, host),
1795 },
1796
1797 {
1798 nxt_string("size"),
1799 NXT_CONF_MAP_INT32,
1800 offsetof(nxt_conf_vldt_clone_procmap_conf_t, size),
1801 },
1802
1803};
1804
1805
1806static nxt_int_t
1807nxt_conf_vldt_clone_procmap(nxt_conf_validation_t *vldt, const char *mapfile,
1808 nxt_conf_value_t *value)
1809{
1810 nxt_int_t ret;
1811 nxt_conf_vldt_clone_procmap_conf_t procmap;
1812
1813 procmap.container = -1;
1814 procmap.host = -1;
1815 procmap.size = -1;
1816
1817 ret = nxt_conf_map_object(vldt->pool, value,
1818 nxt_conf_vldt_clone_procmap_conf_map,
1819 nxt_nitems(nxt_conf_vldt_clone_procmap_conf_map),
1820 &procmap);
1821 if (ret != NXT_OK) {
1822 return ret;
1823 }
1824
1825 if (procmap.container == -1) {
1826 return nxt_conf_vldt_error(vldt, "The %s requires the "
1827 "\"container\" field set.", mapfile);
1828 }
1829
1830 if (procmap.host == -1) {
1831 return nxt_conf_vldt_error(vldt, "The %s requires the "
1832 "\"host\" field set.", mapfile);
1833 }
1834
1835 if (procmap.size == -1) {
1836 return nxt_conf_vldt_error(vldt, "The %s requires the "
1837 "\"size\" field set.", mapfile);
1838 }
1839
1840 return NXT_OK;
1841}
1842
1843
1844static nxt_int_t
1845nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1846{
1847 nxt_int_t ret;
1848
1849 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1850 return nxt_conf_vldt_error(vldt, "The \"uidmap\" array "
1851 "must contain only object values.");
1852 }
1853
1854 ret = nxt_conf_vldt_object(vldt, value,
1855 (void *) nxt_conf_vldt_app_procmap_members);
1856 if (nxt_slow_path(ret != NXT_OK)) {
1857 return ret;
1858 }
1859
1860 return nxt_conf_vldt_clone_procmap(vldt, "uid_map", value);
1861}
1862
1863
1864static nxt_int_t
1865nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1866{
1867 nxt_int_t ret;
1868
1869 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1870 return nxt_conf_vldt_error(vldt, "The \"gidmap\" array "
1871 "must contain only object values.");
1872 }
1873
1874 ret = nxt_conf_vldt_object(vldt, value,
1875 (void *) nxt_conf_vldt_app_procmap_members);
1876 if (nxt_slow_path(ret != NXT_OK)) {
1877 return ret;
1878 }
1879
1880 return nxt_conf_vldt_clone_procmap(vldt, "gid_map", value);
1881}
1882
1883#endif
1884
1885
1886static nxt_int_t
1887nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1888{
1889 nxt_str_t str;
1890
1891 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1892 return nxt_conf_vldt_error(vldt, "The \"arguments\" array "
1893 "must contain only string values.");
1894 }
1895
1896 nxt_conf_get_string(value, &str);
1897
1898 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1899 return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not "
1900 "contain strings with null character.");
1901 }
1902
1903 return NXT_OK;
1904}
1905
1906
1907static nxt_int_t
1908nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name,
1909 nxt_conf_value_t *value)
1910{
1911 if (name->length == 0) {
1912 return nxt_conf_vldt_error(vldt,
1913 "The PHP option name must not be empty.");
1914 }
1915
1916 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1917 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be "
1918 "a string.", name);
1919 }
1920
1921 return NXT_OK;
1922}
1923
1924
1925static nxt_int_t
1926nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
1927 nxt_conf_value_t *value)
1928{
1929 nxt_str_t str;
1930
1931 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1932 return nxt_conf_vldt_error(vldt, "The \"classpath\" array "
1933 "must contain only string values.");
1934 }
1935
1936 nxt_conf_get_string(value, &str);
1937
1938 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1939 return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not "
1940 "contain strings with null character.");
1941 }
1942
1943 return NXT_OK;
1944}
1945
1946
1947static nxt_int_t
1948nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
1949{
1950 nxt_str_t str;
1951
1952 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1953 return nxt_conf_vldt_error(vldt, "The \"options\" array "
1954 "must contain only string values.");
1955 }
1956
1957 nxt_conf_get_string(value, &str);
1958
1959 if (nxt_memchr(str.start, '\0', str.length) != NULL) {
1960 return nxt_conf_vldt_error(vldt, "The \"options\" array must not "
1961 "contain strings with null character.");
1962 }
1963
1964 return NXT_OK;
1965}
1966
1967
1968static nxt_int_t
1969nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name,
1970 nxt_conf_value_t *value)
1971{
1972 nxt_int_t ret;
1973 nxt_conf_value_t *conf;
1974
1975 static nxt_str_t servers = nxt_string("servers");
1976
1977 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1978
1979 if (ret != NXT_OK) {
1980 return ret;
1981 }
1982
1983 ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members);
1984
1985 if (ret != NXT_OK) {
1986 return ret;
1987 }
1988
1989 conf = nxt_conf_get_object_member(value, &servers, NULL);
1990 if (conf == NULL) {
1991 return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain "
1992 "\"servers\" object value.", name);
1993 }
1994
1995 return NXT_OK;
1996}
1997
1998
1999static nxt_int_t
2000nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name,
2001 nxt_conf_value_t *value)
2002{
2003 nxt_int_t ret;
2004 nxt_sockaddr_t *sa;
2005
2006 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
2007
2008 if (ret != NXT_OK) {
2009 return ret;
2010 }
2011
2012 sa = nxt_sockaddr_parse(vldt->pool, name);
2013
2014 if (sa == NULL) {
2015 return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid "
2016 "server address.", name);
2017 }
2018
2019 return nxt_conf_vldt_object(vldt, value,
2020 nxt_conf_vldt_upstream_server_members);
2021}
2022
2023
2024static nxt_int_t
2025nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
2026 nxt_conf_value_t *value, void *data)
2027{
2028 int64_t int_value;
2029
2030 int_value = nxt_conf_get_integer(value);
2031
2032 if (int_value <= 0) {
2033 return nxt_conf_vldt_error(vldt, "The \"weight\" number must be "
2034 "greater than 0.");
2035 }
2036
2037 if (int_value > NXT_INT32_T_MAX) {
2038 return nxt_conf_vldt_error(vldt, "The \"weight\" number must "
2039 "not exceed %d.", NXT_INT32_T_MAX);
2040 }
2041
2042 return NXT_OK;
2043}