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 200 struct 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 */ 224 typedef 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 */ 239 typedef 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 */ 253 typedef 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 */ 259 typedef 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 */ 278 struct 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 */ 302 extern 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. */ 308 struct 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 */ 322 extern 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 */ 331 typedef 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 335 struct 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 */ 350 extern 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 */ 358 typedef int ng_parse_array_getLength_t(const struct ng_parse_type *type, 359 const u_char *start, const u_char *buf); 360 361 struct 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 */ 375 extern 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 */ 386 extern const struct ng_parse_type ng_parse_fixedstring_type; 387 388 struct 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 */ 401 extern const struct ng_parse_type ng_parse_sizedstring_type; 402 403 /* 404 * COMMONLY USED BOUNDED LENGTH STRING TYPES 405 */ 406 extern const struct ng_parse_type ng_parse_nodebuf_type; /* NG_NODESIZ */ 407 extern const struct ng_parse_type ng_parse_hookbuf_type; /* NG_HOOKSIZ */ 408 extern const struct ng_parse_type ng_parse_pathbuf_type; /* NG_PATHSIZ */ 409 extern const struct ng_parse_type ng_parse_typebuf_type; /* NG_TYPESIZ */ 410 extern 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 */ 418 extern const struct ng_parse_type ng_parse_int8_type; 419 extern const struct ng_parse_type ng_parse_int16_type; 420 extern const struct ng_parse_type ng_parse_int32_type; 421 extern const struct ng_parse_type ng_parse_int64_type; 422 423 /* Same thing but unparse as unsigned quantities */ 424 extern const struct ng_parse_type ng_parse_uint8_type; 425 extern const struct ng_parse_type ng_parse_uint16_type; 426 extern const struct ng_parse_type ng_parse_uint32_type; 427 extern const struct ng_parse_type ng_parse_uint64_type; 428 429 /* Same thing but unparse as hex quantities, e.g., "0xe7" */ 430 extern const struct ng_parse_type ng_parse_hint8_type; 431 extern const struct ng_parse_type ng_parse_hint16_type; 432 extern const struct ng_parse_type ng_parse_hint32_type; 433 extern 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 */ 441 extern 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 */ 449 extern 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 */ 461 extern 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 */ 471 extern 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 */ 478 enum 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 */ 493 extern 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 */ 499 extern 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 */ 505 extern 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 */ 514 extern 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 */ 526 extern 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 */ 535 extern char *ng_encode_string(const char *s, int slen); 536 537 #endif /* _NETGRAPH_NG_PARSE_H_ */ 538