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