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