1 /* 2 ** Copyright (C) 2004-2020 by Carnegie Mellon University. 3 ** 4 ** @OPENSOURCE_LICENSE_START@ 5 ** See license information in ../../LICENSE.txt 6 ** @OPENSOURCE_LICENSE_END@ 7 */ 8 9 /* 10 ** skbag.h 11 ** 12 ** The Bag API maps keys to counters. 13 ** 14 ** For keys of 32-bits or less, the data structure is a tree whose 15 ** depth depends on the number of octets in the key. A key's value 16 ** is encoded into the tree's structure. At the leaves, the tree 17 ** contains blocks of counters to hold the counter associated with 18 ** a key. 19 ** 20 ** The API defined in this file is current as of SiLK 3.0. 21 ** 22 ** As of SiLK 3.0, some older functions and types have been 23 ** deprecated. Those functions and types are declared in the 24 ** header file silk/bagtree.h. 25 ** 26 ** Original implementation: 27 ** Christopher Lee 28 ** 2004-11-04 29 ** 30 ** 31 */ 32 #ifndef _SKBAG_H 33 #define _SKBAG_H 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 #include <silk/silk.h> 39 40 RCSIDENTVAR(rcsID_SKBAG_H, "$SiLK: skbag.h ef14e54179be 2020-04-14 21:57:45Z mthomas $"); 41 42 #include <silk/silk_types.h> 43 44 /** 45 * @file 46 * 47 * A mapping from a key to a counter. The key can be a 8, 16, or 48 * 32 bit integer or an IPv4 or IPv6 address. The counter is an 49 * unsigned 64 bit value. 50 * 51 * This file is part of libsilk. 52 */ 53 54 55 /* DEFINES AND TYPEDEFS */ 56 57 /** 58 * The Bag object maps keys to counters 59 */ 60 typedef struct skBag_st skBag_t; 61 62 63 /** 64 * Nearly every Bag function returns one of the following values to 65 * denote the status of invoking the function. 66 */ 67 typedef enum skBagErr_en { 68 /** Success */ 69 SKBAG_OK = 0, 70 /** Memory allocation error */ 71 SKBAG_ERR_MEMORY = 1, 72 /** No more entries in bag */ 73 SKBAG_ERR_KEY_NOT_FOUND = 2, 74 /** Invalid argument to function */ 75 SKBAG_ERR_INPUT = 3, 76 /** Overflow/Underflow in counter */ 77 SKBAG_ERR_OP_BOUNDS = 4, 78 /** Error writing to stream */ 79 SKBAG_ERR_OUTPUT = 5, 80 /** Error reading from stream */ 81 SKBAG_ERR_READ = 6, 82 /** File header values incompatible with this compile of SiLK */ 83 SKBAG_ERR_HEADER = 7, 84 /** Key out of range for bag and auto-conversion disabled */ 85 SKBAG_ERR_KEY_RANGE = 8, 86 /** Bag modified during iteration */ 87 SKBAG_ERR_MODIFIED = 9 88 } skBagErr_t; 89 90 91 /** 92 * The following structure is used to iterate over the key/counter 93 * pairs in a Bag. 94 */ 95 typedef struct skBagIterator_st skBagIterator_t; 96 97 98 /** 99 * The Bag API supports adding keys and counters whose types are 100 * one of an enumerated set of values. When setting or getting a 101 * key or counter, the caller must specify the type of key or 102 * counter the caller is providing or wants to receive. 103 * 104 * When getting a key or counter, the caller may specify the 105 * special ANY type to have the Bag return the "natural" type for 106 * the data structure; the Bag sets the type to the type of 107 * value returned. 108 * 109 * The following enumerations list the types for keys and 110 * counters. 111 */ 112 typedef enum skBagKeyType_en { 113 SKBAG_KEY_ANY = 0, 114 SKBAG_KEY_U8 = 1, 115 SKBAG_KEY_U16 = 2, 116 SKBAG_KEY_U32 = 4, 117 SKBAG_KEY_IPADDR = 16 118 } skBagKeyType_t; 119 120 typedef enum skBagCounterType_en { 121 SKBAG_COUNTER_ANY = 0, 122 SKBAG_COUNTER_U64 = 8 123 } skBagCounterType_t; 124 125 126 /** 127 * The following types specify how keys and counters are to be 128 * provided to and received from the Bag, as of SiLK 3.0. 129 */ 130 typedef struct skBagTypedKey_st { 131 skBagKeyType_t type; 132 union skBagTypedKey_un { 133 uint8_t u8; 134 uint16_t u16; 135 uint32_t u32; 136 uint64_t u64; /* unsupported */ 137 skipaddr_t addr; 138 } val; 139 } skBagTypedKey_t; 140 141 typedef struct skBagTypedCounter_st { 142 skBagCounterType_t type; 143 union skBagTypedCounter_un { 144 uint64_t u64; 145 } val; 146 } skBagTypedCounter_t; 147 148 149 /* 150 * The older SiLK 2.x Bag API (see bagtree.h) used a fixed size for 151 * the key and counter stored in the bag. Those types are defined 152 * here. 153 */ 154 155 typedef uint32_t skBagKey_t; 156 typedef uint64_t skBagCounter_t; 157 158 159 /* 160 * The following specify the numeric range of counters in a Bag. 161 * 162 * Note that the maximum counter in SiLK 3.0 is less than that in 163 * SiLK 2.0. 164 * 165 * Although SKBAG_COUNTER_MIN is 0, setting the counter of a key is 166 * 0 effectively removes the key from the bag. 167 */ 168 169 #define SKBAG_COUNTER_MIN UINT64_C(0) 170 #define SKBAG_COUNTER_MAX (UINT64_MAX - UINT64_C(1)) 171 172 173 /* 174 * The following specify the numeric range of keys in a Bag that 175 * does not hold IPv6 addresses. 176 */ 177 178 #define SKBAG_KEY_MIN UINT32_C(0) 179 #define SKBAG_KEY_MAX UINT32_MAX 180 181 182 /** 183 * The Bag data-structure maintains a key-type and counter-type 184 * that specify what the key and counter represent. For example, a 185 * Bag could map each source-port value to the number of flows seen 186 * for that port. 187 * 188 * The following enumeration lists those types. 189 */ 190 typedef enum skBagFieldType_en { 191 /* the following correspond to values in rwascii.h */ 192 SKBAG_FIELD_SIPv4 = 0, 193 SKBAG_FIELD_DIPv4, 194 SKBAG_FIELD_SPORT, 195 SKBAG_FIELD_DPORT, 196 SKBAG_FIELD_PROTO = 4, 197 SKBAG_FIELD_PACKETS, 198 SKBAG_FIELD_BYTES, 199 SKBAG_FIELD_FLAGS, 200 SKBAG_FIELD_STARTTIME = 8, 201 SKBAG_FIELD_ELAPSED, 202 SKBAG_FIELD_ENDTIME, 203 SKBAG_FIELD_SID, 204 SKBAG_FIELD_INPUT = 12, 205 SKBAG_FIELD_OUTPUT, 206 SKBAG_FIELD_NHIPv4, 207 SKBAG_FIELD_INIT_FLAGS, 208 SKBAG_FIELD_REST_FLAGS = 16, 209 SKBAG_FIELD_TCP_STATE, 210 SKBAG_FIELD_APPLICATION, 211 SKBAG_FIELD_FTYPE_CLASS, 212 SKBAG_FIELD_FTYPE_TYPE = 20, 213 /* 214 * SKBAG_FIELD_STARTTIME_MSEC = 21, 215 * SKBAG_FIELD_ENDTIME_MSEC, 216 * SKBAG_FIELD_ELAPSED_MSEC, 217 */ 218 SKBAG_FIELD_ICMP_TYPE_CODE = 24, 219 /* the above correspond to values in rwascii.h */ 220 221 SKBAG_FIELD_SIPv6, 222 SKBAG_FIELD_DIPv6, 223 SKBAG_FIELD_NHIPv6, 224 SKBAG_FIELD_RECORDS = 28, 225 SKBAG_FIELD_SUM_PACKETS, 226 SKBAG_FIELD_SUM_BYTES, 227 SKBAG_FIELD_SUM_ELAPSED, 228 229 SKBAG_FIELD_ANY_IPv4 = 32, 230 SKBAG_FIELD_ANY_IPv6, 231 SKBAG_FIELD_ANY_PORT, 232 SKBAG_FIELD_ANY_SNMP, 233 SKBAG_FIELD_ANY_TIME = 36, 234 235 SKBAG_FIELD_SIP_COUNTRY, 236 SKBAG_FIELD_DIP_COUNTRY, 237 SKBAG_FIELD_ANY_COUNTRY, 238 239 SKBAG_FIELD_SIP_PMAP = 40, 240 SKBAG_FIELD_DIP_PMAP, 241 SKBAG_FIELD_ANY_IP_PMAP, 242 243 SKBAG_FIELD_SPORT_PMAP, 244 SKBAG_FIELD_DPORT_PMAP = 44, 245 SKBAG_FIELD_ANY_PORT_PMAP = 45, 246 247 SKBAG_FIELD_CUSTOM = 255 248 } skBagFieldType_t; 249 250 251 /** 252 * The following structure is used to iterate over the field types 253 * listed above. 254 * 255 * The structure is defined here so that the iterator may be 256 * created on the stack. However, the structure is subject to 257 * change and the caller should treat the interals of this 258 * structure as opaque. 259 */ 260 typedef struct skBagFieldTypeIterator_st { 261 skBagFieldType_t val; 262 uint8_t no_more_entries; 263 } skBagFieldTypeIterator_t; 264 265 266 /** 267 * In skBagCounterFieldName(), skBagFieldTypeAsString(), and 268 * skBagKeyFieldName(), using a character buffer of at least this 269 * size is guaranteed to hold all the possible field type strings. 270 */ 271 #define SKBAG_MAX_FIELD_BUFLEN 32 272 273 274 /** 275 * Value returned by skBagFieldTypeGetLength() when the field type 276 * is SKBAG_FIELD_CUSTOM. 277 */ 278 #define SKBAG_OCTETS_CUSTOM (SIZE_MAX-1) 279 280 281 /** 282 * Value returned by skBagFieldTypeGetLength() when the field type 283 * is not recognized. 284 */ 285 #define SKBAG_OCTETS_UNKNOWN SIZE_MAX 286 287 288 /** 289 * In skBagCreateTyped() and skBagModify(), the value to use for 290 * 'key_octets' or 'counter_octets' that indicates the size should 291 * be the default size for the 'key_type' or 'counter_type', 292 * respectively. 293 */ 294 #define SKBAG_OCTETS_FIELD_DEFAULT 0 295 296 297 /** 298 * In skBagModify(), the value to use for 'key_octets' or 299 * 'counter_octets' that indicates the size should remain 300 * unchagned. 301 */ 302 #define SKBAG_OCTETS_NO_CHANGE (SIZE_MAX-2) 303 304 305 /** 306 * The signature of a callback used by skBagAddBag() when adding 307 * two counters causes an overflow. 308 * 309 * The value in 'key' is the key where the overflow is occuring, 310 * 'in_out_counter' is the current value of the counter in the 311 * destination bag, 'in_counter' is the current value in the source 312 * bag, and 'cb_data' is the caller-supplied parameter to 313 * skBagAddBag(). 314 * 315 * The callback should modify 'in_out_counter' to the value the 316 * caller wants to insert into the destination bag for 'key'. If 317 * the callback returns any value other than SKBAG_OK, 318 * skBagAddBag() stops processing and returns that value. 319 */ 320 typedef skBagErr_t 321 (*skBagBoundsCallback_t)( 322 const skBagTypedKey_t *key, 323 skBagTypedCounter_t *in_out_counter, 324 const skBagTypedCounter_t *in_counter, 325 void *cb_data); 326 327 328 /** 329 * The signature of a callback used by skBagProcessStreamTyped() 330 * when reading a bag from a stream. This callback is invoked 331 * after the stream's header has been read and before processing 332 * any entries in the bag. 333 * 334 * If this function returns a value other than SKBAG_OK, processing 335 * of the bag stops. 336 * 337 * The 'fake_bag' argument is partially constructed bag that may 338 * be used to query the type and/or size of the key and counter in 339 * the bag that is being read. This parameter must be considered 340 * read-only. 341 * 342 * The 'cb_data' parameter is provided for the caller to use. It 343 * is the parameter specified to skBagProcessStream(). 344 */ 345 typedef skBagErr_t 346 (*skBagStreamInitFunc_t)( 347 const skBag_t *fake_bag, 348 void *cb_data); 349 350 351 /** 352 * The signature of a callback used by skBagProcessStreamTyped() 353 * when reading a bag from a stream. This callback is invoked for 354 * each entry (that is, each key/counter pair) read from the bag. 355 * 356 * The 'fake_bag' argument is partially constructed bag that may be 357 * used to query the type and/or size of the key and counter in the 358 * bag that is being read. This parameter must be considered 359 * read-only. 360 * 361 * The 'key' parameter is a pointer to the current key. If the bag 362 * contains IPv6 addresses, the type of the key is 363 * SKBAG_KEY_IPADDR. Otherwise, the type of the key is 364 * SKBAG_KEY_U32. 365 * 366 * The 'counter' paramter is a pointer to the current counter. 367 * 368 * The 'cb_data' parameter is provided for the caller to use. It 369 * is the parameter specified to skBagProcessStream(). 370 */ 371 typedef skBagErr_t 372 (*skBagStreamEntryFunc_t)( 373 const skBag_t *fake_bag, 374 const skBagTypedKey_t *key, 375 const skBagTypedCounter_t *counter, 376 void *cb_data); 377 378 379 /** 380 * Some features of the Bag are implemented as macros, and those 381 * macros use the following variables. The variables are not 382 * considered part of the supported API, and they are not for 383 * public use. 384 */ 385 extern const skBagTypedCounter_t *skbag_counter_zero; 386 extern const skBagTypedCounter_t *skbag_counter_incr; 387 388 389 /* FUNCTION DECLARATIONS */ 390 391 /** 392 * Add the key/counter pairs of the in-memory bag 'src_bag' to the 393 * in-memory bag 'dest_bag', in effect 'dest_bag' += 'src_bag'. 394 * 395 * The key_type, counter_type, key_octets, and counter_octets of 396 * 'dest_bag' may change as a result of this operation. 397 * 398 * The 'bounds_cb' callback may be NULL. When it is specified, it 399 * is invoked whenever summing two counters causes an overflow 400 * (that is, when skBagCounterAdd() returns SKBAG_ERR_OP_BOUNDS). 401 * The callback is invoked with the key, the counter from 402 * 'dest_bag', the counter from 'src_bag', and the 'cb_data'. The 403 * callback should modify the counter from 'dest_bag' to the value 404 * the caller wants to insert into 'dest_bag' and return SKBAG_OK, 405 * and the function then attempts to set the key in 'dest_bag' 406 * to that value. If the insert succeeds, processing continues; 407 * otherwise the result of the attempt to set the key is 408 * returned. If 'bounds_cb' returns a value other than SKBAG_OK, 409 * that value is returned. 410 * 411 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT if 412 * 'dest_bag' or 'src_bag' is NULL. Return SKBAG_ERR_KEY_RANGE if 413 * the key octet width in 'src' is larger than that in 'dest' and 414 * auto-conversion is disabled in 'dest'. Return SKBAG_ERR_MEMORY 415 * if a key cannot be inserted into 'dest_bag'. Return 416 * SKBAG_ERR_OP_BOUNDS if adding two counters causes an overflow 417 * and the 'bounds_cb' callback parameter is NULL. 418 */ 419 skBagErr_t 420 skBagAddBag( 421 skBag_t *dest, 422 const skBag_t *src, 423 skBagBoundsCallback_t bounds_cb, 424 void *cb_data); 425 426 427 /** 428 * Read a serialized Bag from the input stream 'stream' and add 429 * its key/counter pairs to the existing Bag 'bag'. New keys are 430 * created if required; existing keys have their values 431 * summed. 432 * 433 * Return SKBAG_ERR_INPUT if 'bag' or 'stream_in' is NULL. Return 434 * SKBAG_ERR_OP_BOUNDS if summing counters results in an overflow. 435 * Return SKBAG_ERR_KEY_RANGE if auto-conversion is disabled on 436 * 'bag' (see skBagAutoConvertDisable()) and the key size in 'bag' 437 * is smaller than the key size of the bag in 'stream_in'. 438 */ 439 skBagErr_t 440 skBagAddFromStream( 441 skBag_t *bag, 442 skstream_t *stream_in); 443 444 445 /** 446 * Prevent auto-conversion of keys from happening on 'bag'. 447 * 448 * By default, attempting to insert a key whose octet width is 449 * larger than the Bag current supports promotes the keys in the 450 * Bag to hold the larger key. Such an auto-conversion may occur 451 * when inserting an IPv6 address into a uint32_t Bag, or when 452 * inserting a uint32_t key into an uint8_t Bag. This function 453 * disables this conversion. An attempt to insert an unsupported 454 * key size into such a Bag returns SKBAG_ERR_KEY_RANGE. 455 * 456 * See also skBagAutoConvertEnable() and 457 * skBagAutoConvertIsEnabled(). 458 */ 459 void 460 skBagAutoConvertDisable( 461 skBag_t *bag); 462 463 464 /** 465 * Allow an attempt to insert a key whose octet width is larger 466 * than 'bag' currently support to succeed, promoting the keys in 467 * 'bag' to the wider size. This behavior is the default. 468 * 469 * See also skBagAutoConvertDisable() and 470 * skBagAutoConvertIsEnabled(). 471 */ 472 void 473 skBagAutoConvertEnable( 474 skBag_t *bag); 475 476 477 /** 478 * Return 1 if 'bag' automatically converts its keys' octet width 479 * to a larger size when an attempt is made to insert a larger key. 480 * 481 * See also skBagAutoConvertDisable() and 482 * skBagAutoConvertEnable(). 483 */ 484 int 485 skBagAutoConvertIsEnabled( 486 const skBag_t *bag); 487 488 489 /** 490 * Make a new bag that is a deep copy of src, and set the referent 491 * of 'dest' to it. 492 */ 493 skBagErr_t 494 skBagCopy( 495 skBag_t **dest, 496 const skBag_t *src); 497 498 499 /** 500 * Return the number of unique keys in 'bag'. 501 */ 502 uint64_t 503 skBagCountKeys( 504 const skBag_t *bag); 505 506 507 /** 508 * In 'bag', add to the counter associated with 'key' the value 509 * 'counter_add'. If 'key' does not exist in 'bag', insert it into 510 * 'bag' and set its value to 'counter_add'. 511 * 512 * If 'key' is larger than the maximum key currently supported by 513 * 'bag', 'bag' is converted to a size capable of holding 'key' 514 * unless auto-conversion is disabled for 'bag'; see 515 * skBagAutoConvertEnable(), skBagAutoConvertDisable(), and 516 * skBagAutoConvertIsEnabled(). 517 * 518 * If 'new_counter' is not NULL, the new value of the counter is 519 * copied into that location. 'new_counter' is unchanged when this 520 * function turns a value other than SKBAG_OK. 521 * 522 * Return SKBAG_OK on success. Return SKBAG_ERR_MEMORY if the 523 * attempt to insert the key fails because of an allocation error. 524 * Return SKBAG_ERR_KEY_RANGE if the value in 'key' is larger than 525 * the octet width in 'bag' and auto-conversion is disabled in 526 * 'bag'. If the addition would cause the counter to overflow, the 527 * current value in 'bag' remains unchanged and SKBAG_ERR_OP_BOUNDS 528 * is returned. Return SKBAG_ERR_INPUT if any input parameter 529 * (other than 'new_counter') is NULL, if the type of 'key' is 530 * SKBAG_KEY_ANY, if the type of 'counter' is SKBAG_COUNTER_ANY, or 531 * if 'counter' is larger than SKBAG_COUNTER_MAX. 532 * 533 * See also skBagCounterSet() and skBagCounterSubtract(). The 534 * convenience wrapper skBagCounterIncrement() may be used to add 1 535 * to a key's counter. Use skBagCounterGet() to get a key's 536 * counter. 537 */ 538 skBagErr_t 539 skBagCounterAdd( 540 skBag_t *bag, 541 const skBagTypedKey_t *key, 542 const skBagTypedCounter_t *counter_add, 543 skBagTypedCounter_t *new_counter); 544 545 546 /** 547 * In 'bag', decrement the counter associated with 'key' by one. 548 * This is no-op if 'key' does not exist in 'bag'; that is, unlike 549 * skBagCounterSubtract(), this macro returns SKBAG_OK if 'key' is 550 * not in 'bag'. 551 */ 552 #define skBagCounterDecrement(dec_bag, dec_key) \ 553 ((skBagCounterSubtract((dec_bag), (dec_key), \ 554 skbag_counter_incr, NULL) \ 555 == SKBAG_ERR_INPUT) \ 556 ? SKBAG_ERR_INPUT : SKBAG_OK) 557 558 559 /** 560 * Return the number of octets the counter of 'bag' occupies 561 * for the in-core representation of 'bag'. 562 */ 563 size_t 564 skBagCounterFieldLength( 565 const skBag_t *bag); 566 567 568 /** 569 * Return the type of counter that 'bag' contains, and, if 'buf' is 570 * not NULL, fill 'buf' with a string representation of that type. 571 * The caller must specify the size of 'buf' in 'buflen'. If 'buf' 572 * is too small to hold the string representation, 'buf' is filled 573 * with as much of the name as possible. 574 * 575 * See also skBagCounterFieldType(), skBagKeyFieldName(), and 576 * skBagKeyFieldType(). 577 */ 578 skBagFieldType_t 579 skBagCounterFieldName( 580 const skBag_t *bag, 581 char *buf, 582 size_t buflen); 583 584 585 /** 586 * Return the type of counter that 'bag' contains. 587 * 588 * See also skBagCounterFieldName(), skBagKeyFieldType(), and 589 * skBagKeyFieldName(). 590 */ 591 skBagFieldType_t 592 skBagCounterFieldType( 593 const skBag_t *bag); 594 595 596 /** 597 * Fill 'counter' with the value associated with 'key' in 'bag'. 598 * If 'key' is not in bag, set 'counter' to 0. Return SKBAG_OK and 599 * set 'counter' to 0 when 'key' is outside the range supported by 600 * 'bag'. 601 * 602 * Return SKBAG_OK on success, or SKBAG_ERR_INPUT when any input 603 * parameter is NULL or when the type of 'key' or 'counter' is not 604 * recognized. 605 * 606 * Use skBagCounterSet() to set a key's counter. See also 607 * skBagCounterAdd() and skBagCounterSubtract(). 608 */ 609 skBagErr_t 610 skBagCounterGet( 611 const skBag_t *bag, 612 const skBagTypedKey_t *key, 613 skBagTypedCounter_t *counter); 614 615 616 /** 617 * In 'bag', increment the counter associated with 'key' by one. 618 * Create the key and set its counter to 1 if the key does not 619 * exist in the bag. 620 * 621 * This is a convenience wrapper around skBagCounterAdd(), which 622 * see for additional information. 623 */ 624 #define skBagCounterIncrement(inc_bag, inc_key) \ 625 skBagCounterAdd((inc_bag), (inc_key), skbag_counter_incr, NULL) 626 627 628 /** 629 * In 'bag', set the counter associated with 'key' to the value 630 * 'counter'. If 'counter' is non-zero, create 'key' if it does 631 * not already exist in 'bag'. If 'counter' is 0, remove 'key' if 632 * it exists in 'bag'; otherwise, do nothing. 633 * 634 * If 'key' is larger than the maximum key currently supported by 635 * 'bag', 'bag' is converted to a size capable of holding 'key' 636 * unless auto-conversion in 'bag' is disabled; see 637 * skBagAutoConvertEnable(), skBagAutoConvertDisable(), and 638 * skBagAutoConvertIsEnabled(). 639 * 640 * Return SKBAG_OK on success. Return SKBAG_ERR_MEMORY if there is 641 * an allocation error when inserting the 'key'. Unless 'counter' 642 * is 0, return SKBAG_ERR_KEY_RANGE if the value in 'key' is larger 643 * than the octet width in 'bag' and auto-conversion is disabled in 644 * 'bag'. Return SKBAG_ERR_INPUT if any input parameter is NULL, 645 * if the type of 'key' is SKBAG_KEY_ANY, if the type of 'counter' 646 * is SKBAG_COUNTER_ANY, or if 'counter' is larger than 647 * SKBAG_COUNTER_MAX. 648 * 649 * See also skBagCounterAdd() and skBagCounterSubtract(). Use 650 * skBagCounterGet() to get a key's counter. 651 */ 652 skBagErr_t 653 skBagCounterSet( 654 skBag_t *bag, 655 const skBagTypedKey_t *key, 656 const skBagTypedCounter_t *counter); 657 658 659 /** 660 * In 'bag', subtract from the counter associated with 'key' the 661 * value 'counter_sub'. When 'counter_sub' is non-zero, 'key' must 662 * exist in 'bag'; if it does not, SKBAG_ERR_OP_BOUNDS is returned. 663 * SKBAG_ERR_OP_BOUNDS is also returned when 'key' is outside the 664 * range of keys supported by 'bag'. 665 * 666 * When 'counter_sub' is 0, return SKBAG_OK regardless of whether 667 * 'key' is in 'bag' and, if 'new_counter' is not NULL, set it to 668 * the counter for 'key' if 'key' is in 'bag' or 0 otherwise. 669 * 670 * If 'new_counter' is not NULL, the new value of the counter is 671 * copied into that location. 'new_counter' is unchanged when this 672 * function turns a value other than SKBAG_OK. 673 * 674 * Return SKBAG_OK on success. If the subtraction would cause the 675 * counter to become negative or if 'key' does not exist in 'bag', 676 * the counter in 'bag' is unchanged and SKBAG_ERR_OP_BOUNDS is 677 * returned. Return SKBAG_ERR_INPUT if any input parameter is 678 * NULL, if the type of 'key' is SKBAG_KEY_ANY, if the type of 679 * 'counter' is SKBAG_COUNTER_ANY, or if 'counter' is larger than 680 * SKBAG_COUNTER_MAX. 681 * 682 * See also skBagCounterSet() and skBagCounterAdd(). The 683 * convenience wrapper skBagCounterDecrement() may be used to 684 * subtract 1 from a key's counter. Use skBagCounterGet() to 685 * get a key's counter. 686 */ 687 skBagErr_t 688 skBagCounterSubtract( 689 skBag_t *bag, 690 const skBagTypedKey_t *key, 691 const skBagTypedCounter_t *counter_sub, 692 skBagTypedCounter_t *new_counter); 693 694 695 /** 696 * Allocate memory for a new Bag and set the referent of 'bag' to 697 * it. The type of the key and counter are set to 698 * SKBAG_FIELD_CUSTOM. The bag is created with a 4 octet key and 699 * an 8 octet counter. 700 * 701 * See also skBagCreateTyped(). 702 */ 703 skBagErr_t 704 skBagCreate( 705 skBag_t **bag); 706 707 708 /** 709 * Allocate memory for a new Bag to hold a specific type of key and 710 * counter, each having the specified number of octets. Set the 711 * referent of 'bag' to the newly allocated bag. 712 * 713 * When 'key_type' is SKBAG_FIELD_CUSTOM, the value in 'key_octets' 714 * must be one of the supported key lengths. Currently, the 715 * supported values for 'key_octets' are 1,2,4,16. Note that 716 * 'key_octets' of 8 is not supported. 717 * 718 * When 'key_type' is not SKBAG_FIELD_CUSTOM, the value in 719 * 'key_octets' must be a supported key length or the value may be 720 * SKBAG_OCTETS_FIELD_DEFAULT, indicating the bag should use the 721 * size returned by skBagFieldTypeGetLength('key_type'). If that 722 * function returns a length of 8, the bag uses a length of 4 723 * instead. 724 * 725 * When 'counter_type' is SKBAG_FIELD_CUSTOM, the value in 726 * 'counter_octets' must be specified as 8, as currently that is 727 * the only supported value for 'counter_octets'. 728 * 729 * When 'counter_type' is not SKBAG_FIELD_CUSTOM, 'counter_octets' 730 * value must be either 8 or SKBAG_OCTETS_FIELD_DEFAULT. The bag 731 * will use a 'counter_octets' value of 8. 732 * 733 * The function returns SKBAG_OK on success. It returns 734 * SKBAG_ERR_MEMORY if the bag cannot be allocated. A return value 735 * of SKBAG_ERR_INPUT indicates the 'bag' parameter was NULL, the 736 * 'key_type' or 'counter_type' was not recognized, or the 737 * 'key_octets' or 'counter_octets' are not a supported value. 738 */ 739 skBagErr_t 740 skBagCreateTyped( 741 skBag_t **bag, 742 skBagFieldType_t key_type, 743 skBagFieldType_t counter_type, 744 size_t key_octets, 745 size_t counter_octets); 746 747 748 /** 749 * Free all memory associated with the Bag pointed to by 'bag' and 750 * set '*bag' to NULL. This function does nothing when 'bag' is 751 * NULL or the memory that 'bag' points to is NULL. 752 */ 753 void 754 skBagDestroy( 755 skBag_t **bag); 756 757 758 /** 759 * Fill 'buf' with a string representation of the field-type 760 * 'field'. The caller must specify the size of 'buf' in 'buflen'. 761 * Return the value 'buf' when 'field' is a valid field type and 762 * 'buflen' is large enough to hold the complete type name. 763 * Otherwise leave 'buf' unchanged and return NULL. 764 */ 765 char * 766 skBagFieldTypeAsString( 767 skBagFieldType_t field, 768 char *buf, 769 size_t buflen); 770 771 772 /** 773 * Return the standard number of octets required to hold the 774 * field-type 'field'. Return SKBAG_OCTETS_CUSTOM if the field 775 * type is SKBAG_FIELD_CUSTOM. Return SKBAG_OCTETS_UNKNOWN if 776 * 'field' is not recognized. 777 */ 778 size_t 779 skBagFieldTypeGetLength( 780 skBagFieldType_t field); 781 782 783 /** 784 * Bind the iterator 'ft_iter' to iterate over the skBagFieldType_t 785 * values that this bag library supports. Return SKBAG_OK unless 786 * 'ft_iter' is NULL. 787 */ 788 skBagErr_t 789 skBagFieldTypeIteratorBind( 790 skBagFieldTypeIterator_t *ft_iter); 791 792 793 /** 794 * Move the iterator to the next skBagFieldType_t value. Return 795 * SKBAG_OK on success; return SKBAG_ERR_KEY_NOT_FOUND if there are 796 * no more field types to vist; return SKBAG_ERR_INPUT if 'iter' is 797 * NULL. 798 * 799 * If 'field_id' is not NULL, fill it with the skBagFieldType_t 800 * value. If 'field_octets' is not NULL, fill it with the number 801 * of octets normally used by that field. If 'field_name' is not 802 * NULL and 'field_name_len' is large enough to hold the entire 803 * field name, fill 'field_name' with the string representation of 804 * the type. 805 */ 806 skBagErr_t 807 skBagFieldTypeIteratorNext( 808 skBagFieldTypeIterator_t *iter, 809 skBagFieldType_t *field_id, 810 size_t *field_octets, 811 char *field_name, 812 size_t field_name_len); 813 814 815 /** 816 * Reset 'iter' so it will revisit the skBagFieldType_t values. 817 */ 818 skBagErr_t 819 skBagFieldTypeIteratorReset( 820 skBagFieldTypeIterator_t *iter); 821 822 823 /** 824 * Find the field-type whose name is the string 'type_name'. If 825 * 'type_name' is not a valid field-type name, return 826 * SKBAG_ERR_INPUT; otherwise return SKBAG_OK. 827 * 828 * If the argument 'field_type' is not NULL, fill its referent with 829 * the ID corresponding to 'name'. If the argument 'field_octets' 830 * is not NULL, fill its referent with the number of octets that 831 * field normally occupies---that is, the result of calling 832 * skBagFieldTypeGetLength() on the field. 833 */ 834 skBagErr_t 835 skBagFieldTypeLookup( 836 const char *type_name, 837 skBagFieldType_t *field_type, 838 size_t *field_length); 839 840 841 /** 842 * Return the field type that should be used when two bags are 843 * merged. 844 * 845 * This function assumes the bags are being added or subtracted. 846 */ 847 skBagFieldType_t 848 skBagFieldTypeMerge( 849 skBagFieldType_t field_type1, 850 skBagFieldType_t field_type2); 851 852 853 /** 854 * Create a new iterator to iterate over the bag 'bag' and store 855 * the iterator in the referent of 'iter'. The iterator is 856 * initialized so that the first call to skBagIteratorNextTyped() 857 * returns the counter associated with the first key. 858 * 859 * If the key size of the bag changes during iteration, 860 * SKBAG_ERR_MODIFIED is returned. At that point, the 861 * iterator may be destroyed or reset. 862 * 863 * If keys are added or removed during iteration, the entries may 864 * or may not be visited by the iterator. 865 * 866 * The iterator visits the entries in 'bag' in order from the 867 * smallest key to the largest key. 868 * 869 * Once iteration is complete, the caller must destroy the iterator 870 * by calling skBagIteratorDestroy(). 871 */ 872 skBagErr_t 873 skBagIteratorCreate( 874 const skBag_t *bag, 875 skBagIterator_t **iter); 876 877 878 /** 879 * Similar to skBagIteratorCreate(), but the iterator does not make 880 * any guarantees on the order in which the iterator visits the 881 * entries. 882 */ 883 skBagErr_t 884 skBagIteratorCreateUnsorted( 885 const skBag_t *bag, 886 skBagIterator_t **iter); 887 888 889 /** 890 * Deallocate all memory associated with the bag iterator 'iter'. 891 * The function returns SKBAG_ERR_INPUT if the 'iter' parameter is 892 * NULL. 893 */ 894 skBagErr_t 895 skBagIteratorDestroy( 896 skBagIterator_t *iter); 897 898 899 /** 900 * Get the next key/counter pair associated with the given 901 * iterator, 'iter', store them in the referents of 902 * 'key' and 'counter', respectively, and return SKBAG_OK. 903 * 904 * The 'type' field of 'key' and 'counter' structures determine how 905 * the key and counter are returned. If the key's type is 906 * SKBAG_KEY_ANY, 'key' is filled with an SKBAG_KEY_IPADDR for a 907 * bag containing IPv6 addresses and an SKBAG_KEY_U32 otherwise. 908 * 'counter' is always filled with an SKBAG_COUNTER_U64. 909 * 910 * If the range of keys does not fit into the specified type of 911 * 'key', the iterator returns SKBAG_ERR_KEY_NOT_FOUND once all 912 * values that fit into 'key' have been visited. When 913 * iterating over a Bag that contains IPv6 data and the key type is 914 * an integer, addresses in the ::ffff:0:0/96 block are 915 * converted to IPv4 addresses, and then those addresses are 916 * converted to native integers and returned by this function. All 917 * other IPv6 addresses are ignored. 918 * 919 * If the iterator has visited all entries, the 'key' and 'counter' 920 * values are unchanged and the function returns 921 * SKBAG_ERR_KEY_NOT_FOUND. The function returns SKBAG_ERR_INPUT 922 * if any of the input parameters are NULL or if the type field of 923 * 'key' or 'counter' is not recognized. Return SKBAG_ERR_MODIFIED 924 * if the Bag's key size has changed; when this happens, the 925 * iterator must be reset or destroyed. 926 */ 927 skBagErr_t 928 skBagIteratorNextTyped( 929 skBagIterator_t *iter, 930 skBagTypedKey_t *key, 931 skBagTypedCounter_t *counter); 932 933 934 /** 935 * Reset the iterator at 'iter' so the next call to 936 * skBagIteratorNextTyped() returns the counter associated with 937 * the first key. 938 */ 939 skBagErr_t 940 skBagIteratorReset( 941 skBagIterator_t *iter); 942 943 944 /** 945 * Return the number octets the key of 'bag' occupies for the 946 * in-core representation of 'bag'. 947 */ 948 size_t 949 skBagKeyFieldLength( 950 const skBag_t *bag); 951 952 953 /** 954 * Return the type of key that 'bag' contains, and, if 'buf' is not 955 * NULL, fill 'buf' with a string representation of that type. The 956 * caller must specify the size of 'buf' in 'buflen'. If 'buf' is 957 * too small to hold the string representation, 'buf' is filled 958 * with as much of the name as possible. 959 * 960 * See also skBagKeyFieldType(), skBagCounterFieldName(), and 961 * skBagCounterFieldType(). 962 */ 963 skBagFieldType_t 964 skBagKeyFieldName( 965 const skBag_t *bag, 966 char *buf, 967 size_t buflen); 968 969 970 /** 971 * Return the type of key that 'bag' contains. 972 * 973 * See also skBagKeyFieldName(), skBagCounterFieldType(), and 974 * skBagCounterFieldName(). 975 */ 976 skBagFieldType_t 977 skBagKeyFieldType( 978 const skBag_t *bag); 979 980 981 /** 982 * Remove 'key' from the bag 'bag'. Return SKBAG_OK on success. 983 * Return SKBAG_OK if 'key' is not in 'bag'. 984 */ 985 #define skBagKeyRemove(rm_bag, rm_key) \ 986 skBagCounterSet((rm_bag), (rm_key), skbag_counter_zero) 987 988 989 /** 990 * Read a serialized Bag from the file specified by 'filename' into 991 * a newly created bag and set the referent of 'bag' to its 992 * location. This function is a wrapper around skBagRead(). 993 * 994 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT and do not 995 * create the bag if any input parameter is NULL. Return 996 * SKBAG_ERR_READ, print an error, and do not create the bag if 997 * 'filename' cannot be opened. Otherwise, return the error code 998 * specified by skBagRead(). 999 */ 1000 skBagErr_t 1001 skBagLoad( 1002 skBag_t **bag, 1003 const char *filename); 1004 1005 1006 /** 1007 * Modify the type or length of the key or counter for the existing 1008 * bag 'bag'. 1009 * 1010 * When 'key_octets' and/or 'counter_octets' is 1011 * SKBAG_OCTETS_NO_CHANGE, the size of the key and/or counter is 1012 * not modified. Otherwise, the 'key_octets' and/or 1013 * 'counter_octets' values are handled as they are in 1014 * skBagCreateTyped(). 1015 * 1016 * When 'key_octets' and/or 'counter_octets' specifies a size 1017 * smaller than that bag's current key/counter lengths, 1018 * keys/counters whose value is outside the range of the new 1019 * key/counter are removed from the bag. 1020 * 1021 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT when 'bag' 1022 * is NULL or when the other parameters are not recognized or have 1023 * illegal values. 1024 * 1025 */ 1026 skBagErr_t 1027 skBagModify( 1028 skBag_t *bag, 1029 skBagFieldType_t key_type, 1030 skBagFieldType_t counter_type, 1031 size_t key_octets, 1032 size_t counter_octets); 1033 1034 1035 /** 1036 * Print to the stream 'stream' meta-data on how the bag 'bag' is 1037 * performing. 1038 */ 1039 skBagErr_t 1040 skBagPrintTreeStats( 1041 const skBag_t *bag, 1042 skstream_t *stream_out); 1043 1044 1045 /** 1046 * Read a Bag from the 'stream'. For each key/counter pair in the 1047 * Bag, the function invokes the callback function 'cb_entry_func' 1048 * with the key, the counter, and the 'cb_data'. Processing 1049 * continues until the stream is exhausted or until 'cb_entry_func' 1050 * returns a value other than 'SKBAG_OK'. 1051 * 1052 * The 'cb_init_func' callback may be NULL. If it is not NULL, the 1053 * callback is invoked after the stream's header has been read and 1054 * before processing any entries in the bag. The callback is 1055 * invoked with a partially constructed bag that may be used to 1056 * determine the contents of 'stream'. If the 'cb_init_func' 1057 * callback returns a value other than SKBAG_OK, processing of the 1058 * bag stops. 1059 * 1060 * Return SKBAG_ERR_INPUT if the 'stream' or 'cb_entry_func' input 1061 * parameters are NULL. Return SKBAG_ERR_READ (and print an error) 1062 * if there is an error reading 'bag' from 'stream'. Return 1063 * SKBAG_ERR_HEADER (and print an error) if 'stream' does not 1064 * contain a Bag file, if the Bag file version is unsupported, or 1065 * if the file contains key or counter types or octet lengths that 1066 * are not supported by the library. Otherwise, the return status 1067 * of this function is the return status of 'cb_entry_func'. 1068 */ 1069 skBagErr_t 1070 skBagProcessStreamTyped( 1071 skstream_t *stream_in, 1072 void *cb_data, 1073 skBagStreamInitFunc_t cb_init_func, 1074 skBagStreamEntryFunc_t cb_entry_func); 1075 1076 1077 /** 1078 * Read a serialized Bag from the input stream 'stream' into a 1079 * newly created Bag and set 'bag' to its location. 1080 * 1081 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT and do not 1082 * create the bag if any input parameter is NULL. Return 1083 * SKBAG_ERR_HEADER, print an error, and do not create the bag if 1084 * 'stream' does not contain a Bag file, if the bag file version is 1085 * unsupported, or if the file contains key or counter types or 1086 * octet lengths that are not supported by the library. Return 1087 * SKBAG_ERR_MEMORY if there is an error creating the bag or adding 1088 * entries to it; in the latter case, the bag is returned. Return 1089 * SKBAG_ERR_READ (and print an error) if there is an error reading 1090 * from 'stream'; the bag may or may not be created depending on 1091 * when the error occurred. 1092 * 1093 * See also skBagLoad(). 1094 */ 1095 skBagErr_t 1096 skBagRead( 1097 skBag_t **bag, 1098 skstream_t *stream_in); 1099 1100 1101 /** 1102 * Serialize the Bag 'bag' to the file specified by 'filename'. 1103 * This function is a wrapper around skBagWrite(). 1104 * 1105 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT if any 1106 * parameter is NULL. Return SKBAG_ERR_OUTPUT (and print an error) 1107 * if 'filename' cannot be opened for writing. May also return the 1108 * error codes specified by skBagWrite(). 1109 */ 1110 skBagErr_t 1111 skBagSave( 1112 const skBag_t *bag, 1113 const char *filename); 1114 1115 1116 /** 1117 * Return a static string describing the skBagErr_t value 'code'. 1118 */ 1119 const char * 1120 skBagStrerror( 1121 skBagErr_t err_code); 1122 1123 1124 /** 1125 * Serialize the bag 'bag' to the output stream 'stream'. The 1126 * caller may set the compression method of 'stream' before calling 1127 * this function. 1128 * 1129 * Return SKBAG_OK on success. Return SKBAG_ERR_INPUT if any input 1130 * parameter is NULL. Return SKBAG_ERR_OUTPUT if there is an error 1131 * writing 'bag' to 'stream'. 1132 * 1133 * See also skBagSave(). 1134 */ 1135 skBagErr_t 1136 skBagWrite( 1137 const skBag_t *bag, 1138 skstream_t *stream_out); 1139 1140 #ifdef __cplusplus 1141 } 1142 #endif 1143 #endif /* _SKBAG_H */ 1144 1145 /* 1146 ** Local Variables: 1147 ** mode:c 1148 ** indent-tabs-mode:nil 1149 ** c-basic-offset:4 1150 ** End: 1151 */ 1152