xref: /freebsd/sys/netgraph/ng_parse.h (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 
2 /*
3  * ng_parse.h
4  *
5  * Copyright (c) 1999 Whistle Communications, Inc.
6  * All rights reserved.
7  *
8  * Subject to the following obligations and disclaimer of warranty, use and
9  * redistribution of this software, in source or object code forms, with or
10  * without modifications are expressly permitted by Whistle Communications;
11  * provided, however, that:
12  * 1. Any and all reproductions of the source or object code must include the
13  *    copyright notice above and the following disclaimer of warranties; and
14  * 2. No rights are granted, in any manner or form, to use Whistle
15  *    Communications, Inc. trademarks, including the mark "WHISTLE
16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17  *    such appears in the above copyright notice or in the software.
18  *
19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * Author: Archie Cobbs <archie@freebsd.org>
38  *
39  * $Whistle: ng_parse.h,v 1.2 1999/11/29 01:43:48 archie Exp $
40  * $FreeBSD$
41  */
42 
43 #ifndef _NETGRAPH_PARSE_H_
44 #define _NETGRAPH_PARSE_H_
45 
46 /*
47 
48   This defines a library of routines for converting between various C
49   language types in binary form and ASCII strings.  Types are user
50   definable.  Several pre-defined types are supplied, for some common
51   C types: structures, variable and fixed length arrays, integer types,
52   variable and fixed length strings, IP addresses, etc.
53 
54   A netgraph node type may provide a list of types that correspond to
55   the structures it expects to send and receive in the arguments field
56   of a control message.  This allows these messages to be converted
57   between their native binary form and the corresponding ASCII form.
58 
59   A future use of the ASCII form may be for inter-machine communication
60   of control messages, because the ASCII form is machine independent
61   whereas the native binary form is not.
62 
63   Syntax
64   ------
65 
66     Structures:
67 
68       '{' [ <name>=<value> ... ] '}'
69 
70       Omitted fields have their default values by implication.
71       The order in which the fields are specified does not matter.
72 
73     Arrays:
74 
75       '[' [ [index=]<value> ... ] ']'
76 
77       Element value may be specified with or without the "<index>=" prefix;
78       If omitted, the index after the previous element is used.
79       Omitted fields have their default values by implication.
80 
81     Strings:
82 
83       "foo bar blah\r\n"
84 
85       That is, strings are specified just like C strings. The usual
86       backslash escapes are accepted.
87 
88     Other simple types (integers, IP addresses) have their obvious forms.
89 
90   Example
91   -------
92 
93     Suppose we have a netgraph command that takes as an argument
94     a 'struct foo' shown below.  Here is an example of a possible
95     value for the structure, and the corresponding ASCII encoding
96     of that value:
97 
98 	Structure			Binary value
99 	---------			------------
100 
101 	struct foo {
102 	    struct in_addr ip;  	01 02 03 04
103 	    int bar;			00 00 00 00
104 	    char label[8];		61 62 63 0a 00 00 00 00
105 	    u_char alen;		03 00
106 	    short ary[0];	  	05 00 00 00 0a 00
107 	};
108 
109 	ASCII value
110 	-----------
111 
112 	{ ip=1.2.3.4 label="abc\n" alen=3 ary=[ 5 2=10 ] }
113 
114     Note that omitted fields and array elements get their default
115     values ("bar" and ary[2]), and that the alignment is handled
116     automatically (the extra 00 byte after "num").  Also, since byte
117     order and alignment are inherently machine dependent, so is this
118     conversion process.  The above example shows an x86 (little
119     endian) encoding.  Also the above example is tricky because the
120     structure is variable length, depending on 'alen', the number of
121     elements in the array 'ary'.
122 
123     Here is how one would define a parse type for the above structure,
124     subclassing the pre-defined types below.  We construct the type in
125     a 'bottom up' fashion, defining each field's type first, then the
126     type for the whole structure ('//' comments used to avoid breakage).
127 
128     // Super-type info for 'label' field
129     struct ng_parse_fixedstring_info foo_label_info = { 8 };
130 
131     // Parse type for 'label' field
132     struct ng_parse_type foo_label_type = {
133 	    &ng_parse_fixedstring_type		// super-type
134 	    &foo_label_info			// super-type info
135     };
136 
137     #define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
138 
139     // Function to compute the length of the array 'ary', which
140     // is variable length, depending on the previous field 'alen'.
141     // Upon entry 'buf' will be pointing at &ary[0].
142     int
143     foo_ary_getLength(const struct ng_parse_type *type,
144 	    const u_char *start, const u_char *buf)
145     {
146 	    const struct foo *f;
147 
148 	    f = (const struct foo *)(buf - OFFSETOF(struct foo, ary));
149 	    return f->alen;
150     }
151 
152     // Super-type info for 'ary' field
153     struct ng_parse_array_info foo_ary_info = {
154 	    &ng_parse_int16_type,		// element type
155 	    &foo_ary_getLength			// func to get array length
156     }
157 
158     // Parse type for 'ary' field
159     struct ng_parse_type foo_ary_type = {
160 	    &ng_parse_array_type,		// super-type
161 	    &foo_ary_info			// super-type info
162     };
163 
164     // Super-type info for struct foo
165     struct ng_parse_struct_info foo_fields = {
166 	{
167 	    { "ip",	&ng_parse_ipaddr_type	},
168 	    { "bar",	&ng_parse_int32_type	},
169 	    { "label",	&foo_label_type		},
170 	    { "alen",	&ng_parse_uint8_type	},
171 	    { "ary",	&foo_ary_type		},
172 	    { NULL }
173 	}
174     };
175 
176     // Parse type for struct foo
177     struct ng_parse_type foo_type = {
178 	    &ng_parse_struct_type,		// super-type
179 	    &foo_fields				// super-type info
180     };
181 
182   To define a type, you can define it as a sub-type of a predefined
183   type as shown above, possibly overriding some of the predefined
184   type's methods, or define an entirely new syntax, with the restriction
185   that the ASCII representation of your type's value must not contain
186   any whitespace or any of these characters: { } [ ] = "
187 
188   See ng_ksocket.c for an example of how to do this for 'struct sockaddr'.
189   See ng_parse.c to see implementations of the pre-defined types below.
190 
191 */
192 
193 /************************************************************************
194 			METHODS REQUIRED BY A TYPE
195  ************************************************************************/
196 
197 /*
198  * Three methods are required for a type. These may be given explicitly
199  * or, if NULL, inherited from the super-type.  The 'getDefault' method
200  * is always optional; the others are required if there is no super-type.
201  */
202 
203 struct ng_parse_type;
204 
205 /*
206  * Convert ASCII to binary according to the supplied type.
207  *
208  * The ASCII characters begin at offset *off in 'string'.  The binary
209  * representation is put into 'buf', which has at least *buflen bytes.
210  * 'start' points to the first byte output by ng_parse() (ie, start <= buf).
211  *
212  * Upon return, *buflen contains the length of the new binary data, and
213  * *off is updated to point just past the end of the parsed range of
214  * characters, or, in the case of an error, to the offending character(s).
215  *
216  * Return values:
217  *	0		Success; *buflen holds the length of the data
218  *			and *off points just past the last char parsed.
219  *	EALREADY	Field specified twice
220  *	ENOENT		Unknown field
221  *	E2BIG		Array or character string overflow
222  *	ERANGE		Output was longer than *buflen bytes
223  *	EINVAL		Parse failure or other invalid content
224  *	ENOMEM		Out of memory
225  *	EOPNOTSUPP	Mandatory array/structure element missing
226  */
227 typedef	int	ng_parse_t(const struct ng_parse_type *type, const char *string,
228 			int *off, const u_char *start,
229 			u_char *buf, int *buflen);
230 
231 /*
232  * Convert binary to ASCII according to the supplied type.
233  *
234  * The results are put into 'buf', which is at least buflen bytes long.
235  * *off points to the current byte in 'data' and should be updated
236  * before return to point just past the last byte unparsed.
237  *
238  * Returns:
239  *	0		Success
240  *	ERANGE		Output was longer than buflen bytes
241  */
242 typedef	int	ng_unparse_t(const struct ng_parse_type *type,
243 			const u_char *data, int *off, char *buf, int buflen);
244 
245 /*
246  * Compute the default value according to the supplied type.
247  *
248  * Store the result in 'buf', which is at least *buflen bytes long.
249  * Upon return *buflen contains the length of the output.
250  *
251  * Returns:
252  *	0		Success
253  *	ERANGE		Output was longer than *buflen bytes
254  *	EOPNOTSUPP	Default value is not specified for this type
255  */
256 typedef	int	ng_getDefault_t(const struct ng_parse_type *type,
257 			const u_char *start, u_char *buf, int *buflen);
258 
259 /*
260  * Return the alignment requirement of this type.  Zero is same as one.
261  */
262 typedef	int	ng_getAlign_t(const struct ng_parse_type *type);
263 
264 /************************************************************************
265 			TYPE DEFINITION
266  ************************************************************************/
267 
268 /*
269  * This structure describes a type, which may be a sub-type of another
270  * type by pointing to it with 'supertype' and possibly omitting methods.
271  * Typically the super-type requires some type-specific info, which is
272  * supplied by the 'info' field.
273  *
274  * The 'private' field is ignored by all of the pre-defined types.
275  * Sub-types may use it as they see fit.
276  *
277  * The 'getDefault' method may always be omitted (even if there is no
278  * super-type), which means the value for any item of this type must
279  * always be explicitly given.
280  */
281 struct ng_parse_type {
282 	const struct ng_parse_type *supertype;	/* super-type, if any */
283 	const void		*info;		/* type-specific info */
284 	void			*private;	/* client private info */
285 	ng_parse_t		*parse;		/* parse method */
286 	ng_unparse_t		*unparse;	/* unparse method */
287 	ng_getDefault_t		*getDefault;	/* get default value method */
288 	ng_getAlign_t		*getAlign;	/* get alignment */
289 };
290 
291 /************************************************************************
292 			PRE-DEFINED TYPES
293  ************************************************************************/
294 
295 /*
296  * STRUCTURE TYPE
297  *
298  * This type supports arbitrary C structures.  The normal field alignment
299  * rules for the local machine are applied.  Fields are always parsed in
300  * field order, no matter what order they are listed in the ASCII string.
301  *
302  *   Default value:		Determined on a per-field basis
303  *   Additional info:		struct ng_parse_struct_info *
304  */
305 extern const struct ng_parse_type ng_parse_struct_type;
306 
307 /* Each field has a name, type, and optional alignment override. If the
308    override is non-zero, the alignment is determined from the field type.
309    Note: add an extra struct ng_parse_struct_field with name == NULL
310    to indicate the end of the list. */
311 struct ng_parse_struct_info {
312 	struct ng_parse_struct_field {
313 		const char	*name;		/* field name */
314 		const struct ng_parse_type
315 				*type;		/* field type */
316 		int		alignment;	/* override alignment */
317 	} fields[0];
318 };
319 
320 /*
321  * FIXED LENGTH ARRAY TYPE
322  *
323  * This type supports fixed length arrays, having any element type.
324  *
325  *   Default value:		As returned by getDefault for each index
326  *   Additional info:		struct ng_parse_fixedarray_info *
327  */
328 extern const struct ng_parse_type ng_parse_fixedarray_type;
329 
330 /*
331  * Get the default value for the element at index 'index'.  This method
332  * may be NULL, in which case the default value is computed from the
333  * element type.  Otherwise, it should fill in the default value at *buf
334  * (having size *buflen) and update *buflen to the length of the filled-in
335  * value before return.  If there is not enough routine return ERANGE.
336  */
337 typedef	int	ng_parse_array_getDefault_t(const struct ng_parse_type *type,
338 				int index, const u_char *start,
339 				u_char *buf, int *buflen);
340 
341 struct ng_parse_fixedarray_info {
342 	const struct ng_parse_type	*elementType;
343 	int				length;
344 	ng_parse_array_getDefault_t	*getDefault;
345 };
346 
347 /*
348  * VARIABLE LENGTH ARRAY TYPE
349  *
350  * Same as fixed length arrays, except that the length is determined
351  * by a function instead of a constant value.
352  *
353  *   Default value:		Same as with fixed length arrays
354  *   Additional info:		struct ng_parse_array_info *
355  */
356 extern const struct ng_parse_type ng_parse_array_type;
357 
358 /*
359  * Return the length of the array.  If the array is a field in a structure,
360  * all prior fields are guaranteed to be filled in already.  Upon entry,
361  * 'start' is equal to the first byte parsed in this run, while 'buf' points
362  * to the first element of the array to be filled in.
363  */
364 typedef int	ng_parse_array_getLength_t(const struct ng_parse_type *type,
365 				const u_char *start, const u_char *buf);
366 
367 struct ng_parse_array_info {
368 	const struct ng_parse_type	*elementType;
369 	ng_parse_array_getLength_t	*getLength;
370 	ng_parse_array_getDefault_t	*getDefault;
371 };
372 
373 /*
374  * ARBITRARY LENGTH STRING TYPE
375  *
376  * For arbirary length, NUL-terminated strings.
377  *
378  *   Default value:		Empty string
379  *   Additional info:		None required
380  */
381 extern const struct ng_parse_type ng_parse_string_type;
382 
383 /*
384  * BOUNDED LENGTH STRING TYPE
385  *
386  * These are strings that have a fixed-size buffer, and always include
387  * a terminating NUL character.
388  *
389  *   Default value:		Empty string
390  *   Additional info:		struct ng_parse_fixedstring_info *
391  */
392 extern const struct ng_parse_type ng_parse_fixedstring_type;
393 
394 struct ng_parse_fixedstring_info {
395 	int	bufSize;	/* size of buffer (including NUL) */
396 };
397 
398 /*
399  * EXPLICITLY SIZED STRING TYPE
400  *
401  * These are strings that have a two byte length field preceding them.
402  * Parsed strings are NOT NUL-terminated.
403  *
404  *   Default value:		Empty string
405  *   Additional info:		None
406  */
407 extern const struct ng_parse_type ng_parse_sizedstring_type;
408 
409 /*
410  * COMMONLY USED BOUNDED LENGTH STRING TYPES
411  */
412 extern const struct ng_parse_type ng_parse_nodebuf_type;  /* NG_NODELEN + 1 */
413 extern const struct ng_parse_type ng_parse_hookbuf_type;  /* NG_HOOKLEN + 1 */
414 extern const struct ng_parse_type ng_parse_pathbuf_type;  /* NG_PATHLEN + 1 */
415 extern const struct ng_parse_type ng_parse_typebuf_type;  /* NG_TYPELEN + 1 */
416 extern const struct ng_parse_type ng_parse_cmdbuf_type;   /* NG_CMDSTRLEN + 1 */
417 
418 /*
419  * INTEGER TYPES
420  *
421  *   Default value:		0
422  *   Additional info:		None required
423  */
424 extern const struct ng_parse_type ng_parse_int8_type;
425 extern const struct ng_parse_type ng_parse_int16_type;
426 extern const struct ng_parse_type ng_parse_int32_type;
427 extern const struct ng_parse_type ng_parse_int64_type;
428 
429 /* Same thing but unparse as unsigned quantities */
430 extern const struct ng_parse_type ng_parse_uint8_type;
431 extern const struct ng_parse_type ng_parse_uint16_type;
432 extern const struct ng_parse_type ng_parse_uint32_type;
433 extern const struct ng_parse_type ng_parse_uint64_type;
434 
435 /* Same thing but unparse as hex quantities, e.g., "0xe7" */
436 extern const struct ng_parse_type ng_parse_hint8_type;
437 extern const struct ng_parse_type ng_parse_hint16_type;
438 extern const struct ng_parse_type ng_parse_hint32_type;
439 extern const struct ng_parse_type ng_parse_hint64_type;
440 
441 /*
442  * IP ADDRESS TYPE
443  *
444  *   Default value:		0.0.0.0
445  *   Additional info:		None required
446  */
447 extern const struct ng_parse_type ng_parse_ipaddr_type;
448 
449 /*
450  * VARIABLE LENGTH BYTE ARRAY TYPE
451  *
452  * The bytes are displayed in hex.  The ASCII form may be either an
453  * array of bytes or a string constant, in which case the array is
454  * zero-filled after the string bytes.
455  *
456  *   Default value:		All bytes are zero
457  *   Additional info:		ng_parse_array_getLength_t *
458  */
459 extern const struct ng_parse_type ng_parse_bytearray_type;
460 
461 /*
462  * NETGRAPH CONTROL MESSAGE TYPE
463  *
464  * This is the parse type for a struct ng_mesg.
465  *
466  *   Default value:		All fields zero
467  *   Additional info:		None required
468  */
469 extern const struct ng_parse_type ng_parse_ng_mesg_type;
470 
471 /************************************************************************
472 		CONVERSTION AND PARSING ROUTINES
473  ************************************************************************/
474 
475 /* Tokens for parsing structs and arrays */
476 enum ng_parse_token {
477 	T_LBRACE,		/* '{' */
478 	T_RBRACE,		/* '}' */
479 	T_LBRACKET,		/* '[' */
480 	T_RBRACKET,		/* ']' */
481 	T_EQUALS,		/* '=' */
482 	T_STRING,		/* string in double quotes */
483 	T_ERROR,		/* error parsing string in double quotes */
484 	T_WORD,			/* anything else containing no whitespace */
485 	T_EOF,			/* end of string reached */
486 };
487 
488 /*
489  * See typedef ng_parse_t for definition
490  */
491 extern int	ng_parse(const struct ng_parse_type *type, const char *string,
492 			int *off, u_char *buf, int *buflen);
493 
494 /*
495  * See typedef ng_unparse_t for definition (*off assumed to be zero).
496  */
497 extern int	ng_unparse(const struct ng_parse_type *type,
498 			const u_char *data, char *buf, int buflen);
499 
500 /*
501  * See typedef ng_getDefault_t for definition
502  */
503 extern int	ng_parse_getDefault(const struct ng_parse_type *type,
504 			u_char *buf, int *buflen);
505 
506 /*
507  * Parse a token: '*startp' is the offset to start looking.  Upon
508  * successful return, '*startp' equals the beginning of the token
509  * and '*lenp' the length.  If error, '*startp' points at the
510  * offending character(s).
511  */
512 extern enum	ng_parse_token ng_parse_get_token(const char *s,
513 			int *startp, int *lenp);
514 
515 /*
516  * Like above, but specifically for getting a string token and returning
517  * the string value.  The string token must be enclosed in double quotes
518  * and the normal C backslash escapes are recognized.  The caller must
519  * eventually free() the returned result.  Returns NULL if token is
520  * not a string token, or parse or other error. Otherwise, *lenp contains
521  * the number of characters parsed, and *slenp (if not NULL) contains
522  * the actual number of characters in the parsed string.
523  */
524 extern char	*ng_get_string_token(const char *s, int *startp,
525 			int *lenp, int *slenp);
526 
527 /*
528  * Convert a raw string into a doubly-quoted string including any
529  * necessary backslash escapes.  Caller must free the result.
530  * Returns NULL if ENOMEM. Normally "slen" should equal strlen(s)
531  * unless you want to encode NUL bytes.
532  */
533 extern char	*ng_encode_string(const char *s, int slen);
534 
535 #endif /* _NETGRAPH_PARSE_H_ */
536 
537