1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
|
/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
* \file
*
* \brief Schema layer for Yparser.
*
* \addtogroup yparser
* @{
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "libknot/yparser/yparser.h"
#include "libknot/lookup.h"
struct wire_ctx;
/*! Maximal length of item name. */
#define YP_MAX_ITEM_NAME_LEN 64
/*! Maximal length of binary identifier name (maximal dname length). */
#define YP_MAX_ID_LEN 255
/*! Maximal length of binary data (rough limit). */
#define YP_MAX_DATA_LEN 32768
/*! Integer item nil definition. */
#define YP_NIL INT64_MIN
/*! Maximal number of miscellaneous callbacks/pointers. */
#define YP_MAX_MISC_COUNT 4
/*! Maximal node stack depth. */
#define YP_MAX_NODE_DEPTH 2
#define YP_TXT_BIN_PARAMS struct wire_ctx *in, struct wire_ctx *out, const uint8_t *stop
#define YP_BIN_TXT_PARAMS struct wire_ctx *in, struct wire_ctx *out
/*! Helper macros for item variables definition. */
#define YP_VNONE .var.i = { 0 }
#define YP_VINT .var.i
#define YP_VBOOL .var.b
#define YP_VOPT .var.o
#define YP_VSTR .var.s
#define YP_VADDR .var.a
#define YP_VNET .var.d
#define YP_VDNAME .var.d
#define YP_VHEX .var.d
#define YP_VB64 .var.d
#define YP_VDATA .var.d
#define YP_VREF .var.r
#define YP_VGRP .var.g
/*! Schema item name is a char string with a leading byte (string length). */
typedef char yp_name_t;
/*! Schema item type. */
typedef enum {
YP_TNONE = 0, /*!< Unspecified. */
YP_TINT, /*!< Integer. */
YP_TBOOL, /*!< Boolean. */
YP_TOPT, /*!< Option from the list. */
YP_TSTR, /*!< String. */
YP_THEX, /*!< String or hexadecimal string if "0x" prefix. */
YP_TADDR, /*!< Address (address[\@port] | UNIX path). */
YP_TNET, /*!< Network address range (address[/mask] | abs. UNIX path | address-address). */
YP_TDNAME, /*!< Domain name. */
YP_TB64, /*!< Base64 encoded string. */
YP_TDATA, /*!< Customized data. */
YP_TREF, /*!< Reference to another item. */
YP_TGRP, /*!< Group of sub-items. */
} yp_type_t;
/*! Schema item flags. */
typedef enum {
YP_FNONE = 0, /*!< Unspecified. */
YP_FMULTI = 1 << 0, /*!< Multivalued item. */
YP_FALLOC = 1 << 1, /*!< Allocated item. */
YP_FUSR1 = 1 << 5, /*!< User-defined flag1. */
YP_FUSR2 = 1 << 6, /*!< User-defined flag2. */
YP_FUSR3 = 1 << 7, /*!< User-defined flag3. */
YP_FUSR4 = 1 << 8, /*!< User-defined flag4. */
YP_FUSR5 = 1 << 9, /*!< User-defined flag5. */
YP_FUSR6 = 1 << 10, /*!< User-defined flag6. */
YP_FUSR7 = 1 << 11, /*!< User-defined flag7. */
YP_FUSR8 = 1 << 12, /*!< User-defined flag8. */
YP_FUSR9 = 1 << 13, /*!< User-defined flag9. */
YP_FUSR10 = 1 << 14, /*!< User-defined flag10. */
YP_FUSR11 = 1 << 15, /*!< User-defined flag11. */
YP_FUSR12 = 1 << 16, /*!< User-defined flag12. */
YP_FUSR13 = 1 << 17, /*!< User-defined flag13. */
YP_FUSR14 = 1 << 18, /*!< User-defined flag14. */
YP_FUSR15 = 1 << 19, /*!< User-defined flag15. */
YP_FUSR16 = 1 << 20, /*!< User-defined flag16. */
} yp_flag_t;
/*! Schema item style. */
typedef enum {
YP_SNONE = 0, /*!< Unspecified. */
YP_SSIZE = 1 << 0, /*!< Size unit (B, K, M, G) (in, out). */
YP_STIME = 1 << 1, /*!< Time unit (s, m, h, d) (in, out). */
YP_SUNIT = YP_SSIZE | YP_STIME, /*!< Unit (in, out). */
YP_SNOQUOTE = 1 << 2 /*!< Unquoted value (out). */
} yp_style_t;
typedef struct yp_item yp_item_t;
/*! Schema item variables (type dependent). */
typedef union {
/*! Integer variables. */
struct {
/*! Minimal value. */
int64_t min;
/*! Maximal value. */
int64_t max;
/*! Default value. */
int64_t dflt;
/*! Possible unit type. */
yp_style_t unit;
} i;
/*! Boolean variables. */
struct {
/*! Default value. */
bool dflt;
} b;
/*! Option variables. */
struct {
/*! List of options (maximal value is 255). */
struct knot_lookup const *opts;
/*! Default value. */
unsigned dflt;
} o;
/*! String variables. */
struct {
/*! Default value. */
char const *dflt;
} s;
/*! Address variables. */
struct {
/*! Default port (e.g. UDP). */
uint16_t dflt_port;
/*! Alternative default port (e.g. QUIC). */
uint16_t dflt_port_alt;
/*! Default socket. */
char const *dflt_socket;
} a;
/*! Customized data variables. */
struct {
/*! Length of default data. */
size_t dflt_len;
/*! Default data. */
uint8_t const *dflt;
/*! Text to binary transformation function. */
int (*to_bin)(YP_TXT_BIN_PARAMS);
/*! Binary to text transformation function. */
int (*to_txt)(YP_BIN_TXT_PARAMS);
} d;
/*! Reference variables. */
struct {
/*! Referenced section name. */
yp_name_t const *ref_name;
/*! Referenced group section name (optional). */
yp_name_t const *grp_ref_name;
/*! Referenced section item (dynamic value). */
yp_item_t const *ref;
/*! Referenced group section item (dynamic value). */
yp_item_t const *grp_ref;
} r;
/*! Group variables. */
struct {
/*! List of sub-items. */
yp_item_t const *sub_items;
/*! ID item of sub-items (dynamic value). */
yp_item_t const *id;
} g;
} yp_var_t;
/*! Schema item specification. */
struct yp_item {
/*! Item name. */
const yp_name_t *name;
/*! Item type. */
yp_type_t type;
/*! Item parameters. */
yp_var_t var;
/*! Item flags. */
yp_flag_t flags;
/*! Arbitrary data/callbacks. */
const void *misc[YP_MAX_MISC_COUNT];
/*! Parent item. */
yp_item_t *parent;
/*! Item group subitems (name=NULL terminated array). */
yp_item_t *sub_items;
};
typedef struct yp_node yp_node_t;
struct yp_node {
/*! Parent node. */
yp_node_t *parent;
/*! Node item descriptor. */
const yp_item_t *item;
/*! Current binary id length. */
size_t id_len;
/*! Current binary id. */
uint8_t id[YP_MAX_ID_LEN];
/*! Current item data length. */
size_t data_len;
/*! Current item data. */
uint8_t data[YP_MAX_DATA_LEN];
};
/*! Context parameters for check operations. */
typedef struct {
/*! Used schema. */
yp_item_t **schema;
/*! Index of the current node. */
size_t current;
/*! Node stack. */
yp_node_t nodes[YP_MAX_NODE_DEPTH];
} yp_check_ctx_t;
/*!
* Copies the schema and reinitializes dynamic parameters.
*
* \param[out] dst New copy of the schema.
* \param[in] src Source schema.
*
* \return Error code, KNOT_EOK if success.
*/
int yp_schema_copy(
yp_item_t **dst,
const yp_item_t *src
);
/*!
* Merges two schemas.
*
* \param[out] dst Merged schema.
* \param[in] src1 Source schema1.
* \param[in] src2 Source schema2.
*
* \return Error code, KNOT_EOK if success.
*/
int yp_schema_merge(
yp_item_t **dst,
const yp_item_t *src1,
const yp_item_t *src2
);
/*!
* Purges dynamic items from the schema.
*
* \param[in] schema Schema to purge.
*/
void yp_schema_purge_dynamic(
yp_item_t *schema
);
/*!
* Deallocates the schema.
*
* \param[in] schema A schema returned by #yp_schema_copy().
*/
void yp_schema_free(
yp_item_t *schema
);
/*!
* Tries to find given parent_name/name in the schema.
*
* \param[in] name Name of the item.
* \param[in] parent_name Name of the parent item (NULL if no parent).
* \param[in] schema Schema.
*
* \return Item, NULL if not found or error.
*/
const yp_item_t* yp_schema_find(
const yp_name_t *name,
const yp_name_t *parent_name,
const yp_item_t *schema
);
/*!
* Prepares a context for item check against the schema.
*
* \param[in] schema Schema.
*
* \return Context, NULL if error.
*/
yp_check_ctx_t* yp_schema_check_init(
yp_item_t **schema
);
/*!
* Checks the current parser output against the schema.
*
* If the item is correct, context also contains binary value of the item.
*
* \param[in,out] ctx Check context.
* \param[in] parser Parser context.
*
* \return Error code, KNOT_EOK if success.
*/
int yp_schema_check_parser(
yp_check_ctx_t *ctx,
const yp_parser_t *parser
);
/*!
* Checks the string data against the schema.
*
* Description: key0[id].key1 data
*
* If the item is correct, context also contains binary value of the item.
*
* \param[in,out] ctx Check context.
* \param[in] key0 Key0 item name.
* \param[in] key1 Key1 item name.
* \param[in] id Item identifier.
* \param[in] data Item data (NULL means no data provided).
*
* \return Error code, KNOT_EOK if success.
*/
int yp_schema_check_str(
yp_check_ctx_t *ctx,
const char *key0,
const char *key1,
const char *id,
const char *data
);
/*!
* Deallocates the context.
*
* \param[in,out] ctx Check context.
*/
void yp_schema_check_deinit(
yp_check_ctx_t *ctx
);
/*! @} */
|