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: src/sys/netgraph/ng_parse.h,v 1.2.4.4 2002/07/02 23:44:03 archie Exp $ 41 * $DragonFly: src/sys/netgraph/ng_parse.h,v 1.4 2007/06/03 20:51:10 dillon Exp $ 42 */ 43 44 #ifndef _NETGRAPH_PARSE_H_ 45 #define _NETGRAPH_PARSE_H_ 46 47 #ifndef _SYS_TYPES_H_ 48 #include <sys/types.h> 49 #endif 50 51 /* 52 53 This defines a library of routines for converting between various C 54 language types in binary form and ASCII strings. Types are user 55 definable. Several pre-defined types are supplied, for some common 56 C types: structures, variable and fixed length arrays, integer types, 57 variable and fixed length strings, IP addresses, etc. 58 59 A netgraph node type may provide a list of types that correspond to 60 the structures it expects to send and receive in the arguments field 61 of a control message. This allows these messages to be converted 62 between their native binary form and the corresponding ASCII form. 63 64 A future use of the ASCII form may be for inter-machine communication 65 of control messages, because the ASCII form is machine independent 66 whereas the native binary form is not. 67 68 Syntax 69 ------ 70 71 Structures: 72 73 '{' [ <name>=<value> ... ] '}' 74 75 Omitted fields have their default values by implication. 76 The order in which the fields are specified does not matter. 77 78 Arrays: 79 80 '[' [ [index=]<value> ... ] ']' 81 82 Element value may be specified with or without the "<index>=" prefix; 83 If omitted, the index after the previous element is used. 84 Omitted fields have their default values by implication. 85 86 Strings: 87 88 "foo bar blah\r\n" 89 90 That is, strings are specified just like C strings. The usual 91 backslash escapes are accepted. 92 93 Other simple types (integers, IP addresses) have their obvious forms. 94 95 Example 96 ------- 97 98 Suppose we have a netgraph command that takes as an argument 99 a 'struct foo' shown below. Here is an example of a possible 100 value for the structure, and the corresponding ASCII encoding 101 of that value: 102 103 Structure Binary value 104 --------- ------------ 105 106 struct foo { 107 struct in_addr ip; 01 02 03 04 108 int bar; 00 00 00 00 109 char label[8]; 61 62 63 0a 00 00 00 00 110 u_char alen; 03 00 111 short ary[0]; 05 00 00 00 0a 00 112 }; 113 114 ASCII value 115 ----------- 116 117 { ip=1.2.3.4 label="abc\n" alen=3 ary=[ 5 2=10 ] } 118 119 Note that omitted fields and array elements get their default 120 values ("bar" and ary[2]), and that the alignment is handled 121 automatically (the extra 00 byte after "num"). Also, since byte 122 order and alignment are inherently machine dependent, so is this 123 conversion process. The above example shows an x86 (little 124 endian) encoding. Also the above example is tricky because the 125 structure is variable length, depending on 'alen', the number of 126 elements in the array 'ary'. 127 128 Here is how one would define a parse type for the above structure, 129 subclassing the pre-defined types below. We construct the type in 130 a 'bottom up' fashion, defining each field's type first, then the 131 type for the whole structure ('//' comments used to avoid breakage). 132 133 // Super-type info for 'label' field 134 struct ng_parse_fixedstring_info foo_label_info = { 8 }; 135 136 // Parse type for 'label' field 137 struct ng_parse_type foo_label_type = { 138 &ng_parse_fixedstring_type // super-type 139 &foo_label_info // super-type info 140 }; 141 142 #define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0)) 143 144 // Function to compute the length of the array 'ary', which 145 // is variable length, depending on the previous field 'alen'. 146 // Upon entry 'buf' will be pointing at &ary[0]. 147 int 148 foo_ary_getLength(const struct ng_parse_type *type, 149 const u_char *start, const u_char *buf) 150 { 151 const struct foo *f; 152 153 f = (const struct foo *)(buf - OFFSETOF(struct foo, ary)); 154 return f->alen; 155 } 156 157 // Super-type info for 'ary' field 158 struct ng_parse_array_info foo_ary_info = { 159 &ng_parse_int16_type, // element type 160 &foo_ary_getLength // func to get array length 161 } 162 163 // Parse type for 'ary' field 164 struct ng_parse_type foo_ary_type = { 165 &ng_parse_array_type, // super-type 166 &foo_ary_info // super-type info 167 }; 168 169 // Super-type info for struct foo 170 struct ng_parse_struct_field foo_fields[] = { 171 { "ip", &ng_parse_ipaddr_type }, 172 { "bar", &ng_parse_int32_type }, 173 { "label", &foo_label_type }, 174 { "alen", &ng_parse_uint8_type }, 175 { "ary", &foo_ary_type }, 176 { NULL } 177 }; 178 179 // Parse type for struct foo 180 struct ng_parse_type foo_type = { 181 &ng_parse_struct_type, // super-type 182 &foo_fields // super-type info 183 }; 184 185 To define a type, you can define it as a sub-type of a predefined 186 type as shown above, possibly overriding some of the predefined 187 type's methods, or define an entirely new syntax, with the restriction 188 that the ASCII representation of your type's value must not contain 189 any whitespace or any of these characters: { } [ ] = " 190 191 See ng_ksocket.c for an example of how to do this for 'struct sockaddr'. 192 See ng_parse.c to see implementations of the pre-defined types below. 193 194 */ 195 196 /************************************************************************ 197 METHODS REQUIRED BY A TYPE 198 ************************************************************************/ 199 200 /* 201 * Three methods are required for a type. These may be given explicitly 202 * or, if NULL, inherited from the super-type. The 'getDefault' method 203 * is always optional; the others are required if there is no super-type. 204 */ 205 206 struct ng_parse_type; 207 208 /* 209 * Convert ASCII to binary according to the supplied type. 210 * 211 * The ASCII characters begin at offset *off in 'string'. The binary 212 * representation is put into 'buf', which has at least *buflen bytes. 213 * 'start' points to the first byte output by ng_parse() (ie, start <= buf). 214 * 215 * Upon return, *buflen contains the length of the new binary data, and 216 * *off is updated to point just past the end of the parsed range of 217 * characters, or, in the case of an error, to the offending character(s). 218 * 219 * Return values: 220 * 0 Success; *buflen holds the length of the data 221 * and *off points just past the last char parsed. 222 * EALREADY Field specified twice 223 * ENOENT Unknown field 224 * E2BIG Array or character string overflow 225 * ERANGE Output was longer than *buflen bytes 226 * EINVAL Parse failure or other invalid content 227 * ENOMEM Out of memory 228 * EOPNOTSUPP Mandatory array/structure element missing 229 */ 230 typedef int ng_parse_t(const struct ng_parse_type *type, const char *string, 231 int *off, const u_char *start, 232 u_char *buf, int *buflen); 233 234 /* 235 * Convert binary to ASCII according to the supplied type. 236 * 237 * The results are put into 'buf', which is at least buflen bytes long. 238 * *off points to the current byte in 'data' and should be updated 239 * before return to point just past the last byte unparsed. 240 * 241 * Returns: 242 * 0 Success 243 * ERANGE Output was longer than buflen bytes 244 */ 245 typedef int ng_unparse_t(const struct ng_parse_type *type, 246 const u_char *data, int *off, char *buf, int buflen); 247 248 /* 249 * Compute the default value according to the supplied type. 250 * 251 * Store the result in 'buf', which is at least *buflen bytes long. 252 * Upon return *buflen contains the length of the output. 253 * 254 * Returns: 255 * 0 Success 256 * ERANGE Output was longer than *buflen bytes 257 * EOPNOTSUPP Default value is not specified for this type 258 */ 259 typedef int ng_getDefault_t(const struct ng_parse_type *type, 260 const u_char *start, u_char *buf, int *buflen); 261 262 /* 263 * Return the alignment requirement of this type. Zero is same as one. 264 */ 265 typedef int ng_getAlign_t(const struct ng_parse_type *type); 266 267 /************************************************************************ 268 TYPE DEFINITION 269 ************************************************************************/ 270 271 /* 272 * This structure describes a type, which may be a sub-type of another 273 * type by pointing to it with 'supertype' and possibly omitting methods. 274 * Typically the super-type requires some type-specific info, which is 275 * supplied by the 'info' field. 276 * 277 * The 'private' field is ignored by all of the pre-defined types. 278 * Sub-types may use it as they see fit. 279 * 280 * The 'getDefault' method may always be omitted (even if there is no 281 * super-type), which means the value for any item of this type must 282 * always be explicitly given. 283 */ 284 struct ng_parse_type { 285 const struct ng_parse_type *supertype; /* super-type, if any */ 286 const void *info; /* type-specific info */ 287 void *private; /* client private info */ 288 ng_parse_t *parse; /* parse method */ 289 ng_unparse_t *unparse; /* unparse method */ 290 ng_getDefault_t *getDefault; /* get default value method */ 291 ng_getAlign_t *getAlign; /* get alignment */ 292 }; 293 294 /************************************************************************ 295 PRE-DEFINED TYPES 296 ************************************************************************/ 297 298 /* 299 * STRUCTURE TYPE 300 * 301 * This type supports arbitrary C structures. The normal field alignment 302 * rules for the local machine are applied. Fields are always parsed in 303 * field order, no matter what order they are listed in the ASCII string. 304 * 305 * Default value: Determined on a per-field basis 306 * Additional info: struct ng_parse_struct_field * 307 */ 308 extern const struct ng_parse_type ng_parse_struct_type; 309 310 /* Each field has a name, type, and optional alignment override. If the 311 override is non-zero, the alignment is determined from the field type. 312 Note: add an extra struct ng_parse_struct_field with name == NULL 313 to indicate the end of the list. */ 314 struct ng_parse_struct_field { 315 const char *name; /* field name */ 316 const struct ng_parse_type *type; /* field type */ 317 int alignment; /* override alignment */ 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 * COMMONLY USED BOUNDED LENGTH STRING TYPES 400 */ 401 extern const struct ng_parse_type ng_parse_nodebuf_type; /* NG_NODESIZ */ 402 extern const struct ng_parse_type ng_parse_hookbuf_type; /* NG_HOOKSIZ */ 403 extern const struct ng_parse_type ng_parse_pathbuf_type; /* NG_PATHSIZ */ 404 extern const struct ng_parse_type ng_parse_typebuf_type; /* NG_TYPESIZ */ 405 extern const struct ng_parse_type ng_parse_cmdbuf_type; /* NG_CMDSTRSIZ */ 406 407 /* 408 * INTEGER TYPES 409 * 410 * Default value: 0 411 * Additional info: None required 412 */ 413 extern const struct ng_parse_type ng_parse_int8_type; 414 extern const struct ng_parse_type ng_parse_int16_type; 415 extern const struct ng_parse_type ng_parse_int32_type; 416 extern const struct ng_parse_type ng_parse_int64_type; 417 418 /* Same thing but unparse as unsigned quantities */ 419 extern const struct ng_parse_type ng_parse_uint8_type; 420 extern const struct ng_parse_type ng_parse_uint16_type; 421 extern const struct ng_parse_type ng_parse_uint32_type; 422 extern const struct ng_parse_type ng_parse_uint64_type; 423 424 /* Same thing but unparse as hex quantities, e.g., "0xe7" */ 425 extern const struct ng_parse_type ng_parse_hint8_type; 426 extern const struct ng_parse_type ng_parse_hint16_type; 427 extern const struct ng_parse_type ng_parse_hint32_type; 428 extern const struct ng_parse_type ng_parse_hint64_type; 429 430 /* 431 * IP ADDRESS TYPE 432 * 433 * Default value: 0.0.0.0 434 * Additional info: None required 435 */ 436 extern const struct ng_parse_type ng_parse_ipaddr_type; 437 438 /* 439 * VARIABLE LENGTH BYTE ARRAY TYPE 440 * 441 * The bytes are displayed in hex. The ASCII form may be either an 442 * array of bytes or a string constant, in which case the array is 443 * zero-filled after the string bytes. 444 * 445 * Default value: All bytes are zero 446 * Additional info: ng_parse_array_getLength_t * 447 */ 448 extern const struct ng_parse_type ng_parse_bytearray_type; 449 450 /* 451 * NETGRAPH CONTROL MESSAGE TYPE 452 * 453 * This is the parse type for a struct ng_mesg. 454 * 455 * Default value: All fields zero 456 * Additional info: None required 457 */ 458 extern const struct ng_parse_type ng_parse_ng_mesg_type; 459 460 /************************************************************************ 461 CONVERSTION AND PARSING ROUTINES 462 ************************************************************************/ 463 464 /* Tokens for parsing structs and arrays */ 465 enum ng_parse_token { 466 T_LBRACE, /* '{' */ 467 T_RBRACE, /* '}' */ 468 T_LBRACKET, /* '[' */ 469 T_RBRACKET, /* ']' */ 470 T_EQUALS, /* '=' */ 471 T_STRING, /* string in double quotes */ 472 T_ERROR, /* error parsing string in double quotes */ 473 T_WORD, /* anything else containing no whitespace */ 474 T_EOF, /* end of string reached */ 475 }; 476 477 /* 478 * See typedef ng_parse_t for definition 479 */ 480 extern int ng_parse(const struct ng_parse_type *type, const char *string, 481 int *off, u_char *buf, int *buflen); 482 483 /* 484 * See typedef ng_unparse_t for definition (*off assumed to be zero). 485 */ 486 extern int ng_unparse(const struct ng_parse_type *type, 487 const u_char *data, char *buf, int buflen); 488 489 /* 490 * See typedef ng_getDefault_t for definition 491 */ 492 extern int ng_parse_getDefault(const struct ng_parse_type *type, 493 u_char *buf, int *buflen); 494 495 /* 496 * Parse a token: '*startp' is the offset to start looking. Upon 497 * successful return, '*startp' equals the beginning of the token 498 * and '*lenp' the length. If error, '*startp' points at the 499 * offending character(s). 500 */ 501 extern enum ng_parse_token ng_parse_get_token(const char *s, 502 int *startp, int *lenp); 503 504 /* 505 * Like above, but specifically for getting a string token and returning 506 * the string value. The string token must be enclosed in double quotes 507 * and the normal C backslash escapes are recognized. The caller must 508 * eventually free() the returned result. Returns NULL if token is 509 * not a string token, or parse or other error. 510 */ 511 extern char *ng_get_string_token(const char *s, int *startp, int *lenp); 512 513 /* 514 * Convert a raw string into a doubly-quoted string including any 515 * necessary backslash escapes. Caller must free the result. 516 * Returns NULL if ENOMEM. 517 */ 518 extern char *ng_encode_string(const char *s); 519 520 #endif /* _NETGRAPH_PARSE_H_ */ 521 522