Add more comments describing how to use parse types and how they work.

This commit is contained in:
Archie Cobbs 1999-12-01 19:41:15 +00:00
parent fa200997c8
commit 63e2ac54d1

View File

@ -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