Coverage Report

Created: 2026-04-12 07:04

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