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