From 63e2ac54d172ba2ee9a986b962534fa40ff35717 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Wed, 1 Dec 1999 19:41:15 +0000 Subject: [PATCH] Add more comments describing how to use parse types and how they work. --- sys/netgraph/ng_parse.h | 205 +++++++++++++++++++++++++++++++--------- 1 file changed, 162 insertions(+), 43 deletions(-) diff --git a/sys/netgraph/ng_parse.h b/sys/netgraph/ng_parse.h index 1efbdbef805c..0dbf7691f0c4 100644 --- a/sys/netgraph/ng_parse.h +++ b/sys/netgraph/ng_parse.h @@ -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