Add more comments describing how to use parse types and how they work.
This commit is contained in:
parent
fa200997c8
commit
63e2ac54d1
@ -47,10 +47,18 @@
|
||||
|
||||
This defines a library of routines for converting between various C
|
||||
language types in binary form and ASCII strings. Types are user
|
||||
definable. Several pre-defined types are supplied, for some
|
||||
common C types: structures, variable and fixed length arrays,
|
||||
integer types, variable and fixed length strings, IP addresses,
|
||||
etc.
|
||||
definable. Several pre-defined types are supplied, for some common
|
||||
C types: structures, variable and fixed length arrays, integer types,
|
||||
variable and fixed length strings, IP addresses, etc.
|
||||
|
||||
A netgraph node type may provide a list of types that correspond to
|
||||
the structures it expects to send and receive in the arguments field
|
||||
of a control message. This allows these messages to be converted
|
||||
between their native binary form and the corresponding ASCII form.
|
||||
|
||||
A future use of the ASCII form may be for inter-machine communication
|
||||
of control messages, because the ASCII form is machine independent
|
||||
whereas the native binary form is not.
|
||||
|
||||
Syntax
|
||||
------
|
||||
@ -77,32 +85,106 @@
|
||||
That is, strings are specified just like C strings. The usual
|
||||
backslash escapes are accepted.
|
||||
|
||||
Other simple types have their obvious ASCII forms.
|
||||
Other simple types (integers, IP addresses) have their obvious forms.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Structure Binary (big endian)
|
||||
--------- -------------------
|
||||
Suppose we have a netgraph command that takes as an argument
|
||||
a 'struct foo' shown below. Here is an example of a possible
|
||||
value for the structure, and the corresponding ASCII encoding
|
||||
of that value:
|
||||
|
||||
struct foo {
|
||||
struct in_addr ip; 03 03 03 03
|
||||
int bar; 00 00 00 00
|
||||
u_char num; 02 00
|
||||
short ary[0]; 00 05 00 00 00 0a
|
||||
};
|
||||
Structure Binary value
|
||||
--------- ------------
|
||||
|
||||
ASCII form: "{ ip=3.3.3.3 num=3 ary=[ 5 2=10 ] }"
|
||||
struct foo {
|
||||
struct in_addr ip; 01 02 03 04
|
||||
int bar; 00 00 00 00
|
||||
char label[8]; 61 62 63 0a 00 00 00 00
|
||||
u_char alen; 03 00
|
||||
short ary[0]; 05 00 00 00 0a 00
|
||||
};
|
||||
|
||||
Note that omitted fields or array elements get their default values
|
||||
("bar" and ary[2]), and that the alignment is handled automatically
|
||||
(the extra 00 byte after "num").
|
||||
ASCII value
|
||||
-----------
|
||||
|
||||
{ ip=1.2.3.4 label="abc\n" alen=3 ary=[ 5 2=10 ] }
|
||||
|
||||
Note that omitted fields and array elements get their default
|
||||
values ("bar" and ary[2]), and that the alignment is handled
|
||||
automatically (the extra 00 byte after "num"). Also, since byte
|
||||
order and alignment are inherently machine dependent, so is this
|
||||
conversion process. The above example shows an x86 (little
|
||||
endian) encoding. Also the above example is tricky because the
|
||||
structure is variable length, depending on 'alen', the number of
|
||||
elements in the array 'ary'.
|
||||
|
||||
Here is how one would define a parse type for the above structure,
|
||||
subclassing the pre-defined types below. We construct the type in
|
||||
a 'bottom up' fashion, defining each field's type first, then the
|
||||
type for the whole structure ('//' comments used to avoid breakage).
|
||||
|
||||
// Super-type info for 'label' field
|
||||
struct ng_parse_fixedsstring_info foo_label_info = { 8 };
|
||||
|
||||
// Parse type for 'label' field
|
||||
struct ng_parse_type foo_label_type = {
|
||||
&ng_parse_fixedstring_type // super-type
|
||||
&foo_label_info // super-type info
|
||||
};
|
||||
|
||||
#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
|
||||
|
||||
// Function to compute the length of the array 'ary', which
|
||||
// is variable length, depending on the previous field 'alen'.
|
||||
// Upon entry 'buf' will be pointing at &ary[0].
|
||||
int
|
||||
foo_ary_getLength(const struct ng_parse_type *type,
|
||||
const u_char *start, const u_char *buf)
|
||||
{
|
||||
const struct foo *f;
|
||||
|
||||
f = (const struct foo *)(buf - OFFSETOF(struct foo, ary));
|
||||
return f->alen;
|
||||
}
|
||||
|
||||
// Super-type info for 'ary' field
|
||||
struct ng_parse_array_info foo_ary_info = {
|
||||
&ng_parse_int16_type, // element type
|
||||
&foo_ary_getLength // func to get array length
|
||||
}
|
||||
|
||||
// Parse type for 'ary' field
|
||||
struct ng_parse_type foo_ary_type = {
|
||||
&ng_parse_array_type, // super-type
|
||||
&foo_ary_info // super-type info
|
||||
};
|
||||
|
||||
// Super-type info for struct foo
|
||||
struct ng_parse_struct_info foo_fields = {
|
||||
{ "ip", &ng_parse_ipaddr_type },
|
||||
{ "bar", &ng_parse_int32_type },
|
||||
{ "label", &foo_label_type },
|
||||
{ "alen", &ng_parse_int8_type },
|
||||
{ "ary", &foo_ary_type },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
// Parse type for struct foo
|
||||
struct ng_parse_type foo_type = {
|
||||
&ng_parse_struct_type, // super-type
|
||||
&foo_fields // super-type info
|
||||
};
|
||||
|
||||
To define a type, you can define it as a sub-type of a predefined
|
||||
type, overriding some of the predefined type's methods and/or its
|
||||
alignment, or define your own syntax, with the restriction that
|
||||
the ASCII representation must not contain any whitespace or these
|
||||
characters: { } [ ] = "
|
||||
type as shown above, possibly overriding some of the predefined
|
||||
type's methods, or define an entirely new syntax, with the restriction
|
||||
that the ASCII representation of your type's value must not contain
|
||||
any whitespace or any of these characters: { } [ ] = "
|
||||
|
||||
See ng_ksocket.c for an example of how to do this for 'struct sockaddr'.
|
||||
See ng_parse.c to see implementations of the pre-defined types below.
|
||||
|
||||
*/
|
||||
|
||||
@ -112,7 +194,8 @@
|
||||
|
||||
/*
|
||||
* Three methods are required for a type. These may be given explicitly
|
||||
* or, if NULL, inherited from the super-type.
|
||||
* or, if NULL, inherited from the super-type. The 'getDefault' method
|
||||
* is always optional; the others are required if there is no super-type.
|
||||
*/
|
||||
|
||||
struct ng_parse_type;
|
||||
@ -182,7 +265,16 @@ typedef int ng_getAlign_t(const struct ng_parse_type *type);
|
||||
|
||||
/*
|
||||
* This structure describes a type, which may be a sub-type of another
|
||||
* type by pointing to it with 'supertype' and omitting one or more methods.
|
||||
* type by pointing to it with 'supertype' and possibly omitting methods.
|
||||
* Typically the super-type requires some type-specific info, which is
|
||||
* supplied by the 'info' field.
|
||||
*
|
||||
* The 'private' field is ignored by all of the pre-defined types.
|
||||
* Sub-types may use it as they see fit.
|
||||
*
|
||||
* The 'getDefault' method may always be omitted (even if there is no
|
||||
* super-type), which means the value for any item of this type must
|
||||
* always be explicitly given.
|
||||
*/
|
||||
struct ng_parse_type {
|
||||
const struct ng_parse_type *supertype; /* super-type, if any */
|
||||
@ -199,7 +291,11 @@ struct ng_parse_type {
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* Structures
|
||||
* STRUCTURE TYPE
|
||||
*
|
||||
* This type supports arbitrary C structures. The normal field alignment
|
||||
* rules for the local machine are applied. Fields are always parsed in
|
||||
* field order, no matter what order they are listed in the ASCII string.
|
||||
*
|
||||
* Default value: Determined on a per-field basis
|
||||
* Additional info: struct ng_parse_struct_info *
|
||||
@ -220,23 +316,26 @@ struct ng_parse_struct_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* Fixed length arrays
|
||||
* FIXED LENGTH ARRAY TYPE
|
||||
*
|
||||
* Default value: See below
|
||||
* This type supports fixed length arrays, having any element type.
|
||||
*
|
||||
* Default value: As returned by getDefault for each index
|
||||
* Additional info: struct ng_parse_fixedarray_info *
|
||||
*/
|
||||
extern const struct ng_parse_type ng_parse_fixedarray_type;
|
||||
|
||||
typedef int ng_parse_array_getLength_t(const struct ng_parse_type *type,
|
||||
const u_char *start, const u_char *buf);
|
||||
/*
|
||||
* Get the default value for the element at index 'index'. This method
|
||||
* may be NULL, in which case the default value is computed from the
|
||||
* element type. Otherwise, it should fill in the default value at *buf
|
||||
* (having size *buflen) and update *buflen to the length of the filled-in
|
||||
* value before return. If there is not enough routine return ERANGE.
|
||||
*/
|
||||
typedef int ng_parse_array_getDefault_t(const struct ng_parse_type *type,
|
||||
int index, const u_char *start,
|
||||
u_char *buf, int *buflen);
|
||||
|
||||
/* The 'getDefault' method may be NULL, in which case the default value
|
||||
is computed from the element type. If not, it should fill in the
|
||||
default value at *buf (having size *buflen) and update *buflen to the
|
||||
length of the filled-in value before return. */
|
||||
struct ng_parse_fixedarray_info {
|
||||
const struct ng_parse_type *elementType;
|
||||
int length;
|
||||
@ -244,13 +343,25 @@ struct ng_parse_fixedarray_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* Variable length arrays
|
||||
* VARIABLE LENGTH ARRAY TYPE
|
||||
*
|
||||
* Same as fixed length arrays, except that the length is determined
|
||||
* by a function instead of a constant value.
|
||||
*
|
||||
* Default value: Same as with fixed length arrays
|
||||
* Additional info: struct ng_parse_array_info *
|
||||
*/
|
||||
extern const struct ng_parse_type ng_parse_array_type;
|
||||
|
||||
/*
|
||||
* Return the length of the array. If the array is a field in a structure,
|
||||
* all prior fields are guaranteed to be filled in already. Upon entry,
|
||||
* 'start' is equal to the first byte parsed in this run, while 'buf' points
|
||||
* to the first element of the array to be filled in.
|
||||
*/
|
||||
typedef int ng_parse_array_getLength_t(const struct ng_parse_type *type,
|
||||
const u_char *start, const u_char *buf);
|
||||
|
||||
struct ng_parse_array_info {
|
||||
const struct ng_parse_type *elementType;
|
||||
ng_parse_array_getLength_t *getLength;
|
||||
@ -258,7 +369,9 @@ struct ng_parse_array_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* Arbitrary length strings
|
||||
* ARBITRARY LENGTH STRING TYPE
|
||||
*
|
||||
* For arbirary length, NUL-terminated strings.
|
||||
*
|
||||
* Default value: Empty string
|
||||
* Additional info: None required
|
||||
@ -266,8 +379,10 @@ struct ng_parse_array_info {
|
||||
extern const struct ng_parse_type ng_parse_string_type;
|
||||
|
||||
/*
|
||||
* Bounded length strings. These are strings that have a fixed-size
|
||||
* buffer, and always include a terminating NUL character.
|
||||
* BOUNDED LENGTH STRING TYPE
|
||||
*
|
||||
* These are strings that have a fixed-size buffer, and always include
|
||||
* a terminating NUL character.
|
||||
*
|
||||
* Default value: Empty string
|
||||
* Additional info: struct ng_parse_fixedsstring_info *
|
||||
@ -279,7 +394,7 @@ struct ng_parse_fixedsstring_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* Some commonly used bounded length string types
|
||||
* COMMONLY USED BOUNDED LENGTH STRING TYPES
|
||||
*/
|
||||
extern const struct ng_parse_type ng_parse_nodebuf_type; /* NG_NODELEN + 1 */
|
||||
extern const struct ng_parse_type ng_parse_hookbuf_type; /* NG_HOOKLEN + 1 */
|
||||
@ -288,7 +403,7 @@ extern const struct ng_parse_type ng_parse_typebuf_type; /* NG_TYPELEN + 1 */
|
||||
extern const struct ng_parse_type ng_parse_cmdbuf_type; /* NG_CMDSTRLEN + 1 */
|
||||
|
||||
/*
|
||||
* Integer types
|
||||
* INTEGER TYPES
|
||||
*
|
||||
* Default value: 0
|
||||
* Additional info: None required
|
||||
@ -299,7 +414,7 @@ extern const struct ng_parse_type ng_parse_int32_type;
|
||||
extern const struct ng_parse_type ng_parse_int64_type;
|
||||
|
||||
/*
|
||||
* IP address type
|
||||
* IP ADDRESS TYPE
|
||||
*
|
||||
* Default value: 0.0.0.0
|
||||
* Additional info: None required
|
||||
@ -307,9 +422,11 @@ extern const struct ng_parse_type ng_parse_int64_type;
|
||||
extern const struct ng_parse_type ng_parse_ipaddr_type;
|
||||
|
||||
/*
|
||||
* Variable length byte array. The bytes are displayed in hex.
|
||||
* ASCII form may be either an array of bytes or a string constant,
|
||||
* in which case the array is zero-filled after the string bytes.
|
||||
* VARIABLE LENGTH BYTE ARRAY TYPE
|
||||
*
|
||||
* The bytes are displayed in hex. The ASCII form may be either an
|
||||
* array of bytes or a string constant, in which case the array is
|
||||
* zero-filled after the string bytes.
|
||||
*
|
||||
* Default value: All bytes are zero
|
||||
* Additional info: ng_parse_array_getLength_t *
|
||||
@ -317,7 +434,9 @@ extern const struct ng_parse_type ng_parse_ipaddr_type;
|
||||
extern const struct ng_parse_type ng_parse_bytearray_type;
|
||||
|
||||
/*
|
||||
* Netgraph control message type
|
||||
* NETGRAPH CONTROL MESSAGE TYPE
|
||||
*
|
||||
* This is the parse type for a struct ng_mesg.
|
||||
*
|
||||
* Default value: All fields zero
|
||||
* Additional info: None required
|
||||
|
Loading…
Reference in New Issue
Block a user