1 /*
2 ** Copyright (C) 2016-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 #ifndef _SKAGGBAG_H
9 #define _SKAGGBAG_H
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #include <silk/silk.h>
15 
16 RCSIDENTVAR(rcsID_SKAGGBAG_H, "$SiLK: skaggbag.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
17 
18 #include <silk/silk_types.h>
19 #include <silk/skstream.h>
20 
21 
22 /*
23  *  skaggbag.h
24  *
25  *    The API to AggBag, a container and associated file format that
26  *    contains a Bag-like data structure (see skbag.h) where the key
27  *    and counter are aggregates of multiple fields.
28  *
29  *    Since SiLK 3.15.0.
30  *
31  *
32  *    To create an AggBag, use skAggBagCreate().  Specify the type of
33  *    the fields that comprise the key and counter by calling
34  *    skAggBagSetKeyFields() and skAggBagSetCounterFields(),
35  *    respectively.
36  *
37  *    To insert data into the AggBag, first call
38  *    skAggBagInitializeKey() and skAggBagInitializeCounter().  These
39  *    functions initialize an sk_aggbag_aggregate_t and an
40  *    sk_aggbag_field_t.  sk_aggbag_aggregate_t is is an object holds
41  *    the values prior to inserting them into the AggBag.
42  *    sk_aggbag_field_t is an iterator over the fields that comprise a
43  *    key or a counter.  For each field, call
44  *    skAggBagAggregateSetDatetime(), skAggBagAggregateSetIPAddress(),
45  *    or skAggBagAggregateSetUnsigned() to set its value, then call
46  *    skAggBagFieldIterNext() to move the iterator to the next field.
47  *    Once all key fields and counter fields have been specified, call
48  *    skAggBagKeyCounterSet() to insert the key and counter.
49  *
50  *    skAggBagKeyCounterAdd(), skAggBagKeyCounterRemove(), and
51  *    skAggBagKeyCounterSubtract() may be used to manipulate the
52  *    counter values for a key.  Use skAggBagKeyCounterGet() to get a
53  *    counter for a specified key.
54  *
55  *    Once processing is compete, use skAggBagSave() or
56  *    skAggBagWrite() to store the AggBag to disk, and
57  *    skAggBagDestroy() to free the memory used by the AggBag.
58  *
59  *
60  *    For processing an existing AggBag, first use skAggBagLoad() or
61  *    skAggBagRead() to read the AggBag from disk.  Use
62  *    skAggBagIteratorBind() to bind an iterator to the contents of
63  *    the AggBag, and skAggBagIteratorNext() to copy the key and
64  *    counter from the AggBag into the iterator.  Use
65  *    skAggBagFieldIterGetType() to get the type of the field, and
66  *    then the one of the functions skAggBagAggregateGetDatetime(),
67  *    skAggBagAggregateGetIPAddress(), or
68  *    skAggBagAggregateGetUnsigned() to retrieve the value for each
69  *    field in the key or counter.  Use skAggBagFieldIterNext() to
70  *    visit each field in the key and counter.  Once all keys and
71  *    counters have been visited, call skAggBagIteratorFree() to free
72  *    the iterator and skAggBagDestroy() to destroy the AggBag.
73  *
74  *
75  *  Mark Thomas
76  *  December 2016
77  *
78  */
79 
80 /**
81  *    sk_aggbag_t is the AggBag data structure.
82  */
83 typedef struct sk_aggbag_st sk_aggbag_t;
84 
85 /**
86  *    sk_aggbag_aggregate_t is a structure to hold the key or counter
87  *    prior to inserting them into the AggBag or when reading from an
88  *    AggBag.  An sk_aggbag_field_t is usually paired with the
89  *    sk_aggbag_aggregate_t to visit each of the individual fields in
90  *    the key or the counter.
91  */
92 typedef struct sk_aggbag_aggregate_st sk_aggbag_aggregate_t;
93 
94 /**
95  *    sk_aggbag_field_t is an iterator over the individual fields that
96  *    comprise a key or a counter.  It is usually paired with an
97  *    sk_aggbag_aggregate_t that holds the values.
98  */
99 typedef struct sk_aggbag_field_st sk_aggbag_field_t;
100 
101 
102 
103 /**
104  *    sk_aggbag_options_t is used for specifying features of the
105  *    output stream when writing an Aggregate Bag to a file.
106  */
107 struct sk_aggbag_options_st {
108     /**
109      *  type of input to the application, where a non-zero value
110      *  indicates application uses existing SiLK files (either AggBags
111      *  or Flow files).  A non-zero value provides the --notes-strip
112      *  option to the application. */
113     unsigned int        existing_silk_files;
114     /**
115      *  when 0, do not strip invocations from the AggBag; when 1,
116      *  strip invocations from output */
117     unsigned int        invocation_strip;
118     /**
119      *  when 0, do not strip annoations (notes) from the AggBag; when
120      *  1, strip annotations from output */
121     int                 note_strip;
122     /**
123      *  the command line: number of arguments */
124     unsigned int        argc;
125     /**
126      *  the command line: the arguments */
127     char              **argv;
128     /**
129      *  the version of records to write */
130     uint16_t            record_version;
131     /**
132      *  the type of compression to use */
133     sk_compmethod_t     comp_method;
134 };
135 typedef struct sk_aggbag_options_st sk_aggbag_options_t;
136 
137 
138 /**
139  *    sk_aggbag_iter_t is used for iterating over the keys and
140  *    counters that an AggBag contains.  The caller is expected to use
141  *    the SK_AGGBAG_ITER_INITIALIZER macro when initializing an
142  *    sk_aggbag_iter_t on the stack.
143  *
144  *    Use skAggBagIteratorBind() to bind the iterator to an AggBag,
145  *    skAggBagIteratorNext() to visit each key and counter, and
146  *    skAggBagIteratorFree() when done.
147  */
148 typedef struct sk_aggbag_iter_st sk_aggbag_iter_t;
149 
150 /**
151  *    sk_aggbag_type_iter_t is a structure used when iterating over
152  *    the types of fields that the AggBag code supports.
153  *
154  *    Use skAggBagFieldTypeIteratorBind() to initialize it and
155  *    skAggBagFieldTypeIteratorNext() to visit each type.
156  */
157 typedef struct sk_aggbag_type_iter_st sk_aggbag_type_iter_t;
158 
159 /**
160  *    sk_aggbag_type_t specifies the field types that the AggBag code
161  *    supports.
162  */
163 typedef enum sk_aggbag_type_en {
164     SKAGGBAG_FIELD_SIPv4 = 0,
165     SKAGGBAG_FIELD_DIPv4,
166     SKAGGBAG_FIELD_SPORT,
167     SKAGGBAG_FIELD_DPORT,
168     SKAGGBAG_FIELD_PROTO = 4,
169     SKAGGBAG_FIELD_PACKETS,
170     SKAGGBAG_FIELD_BYTES,
171     SKAGGBAG_FIELD_FLAGS,
172     SKAGGBAG_FIELD_STARTTIME = 8,
173     SKAGGBAG_FIELD_ELAPSED,
174     SKAGGBAG_FIELD_ENDTIME,
175     SKAGGBAG_FIELD_SID,
176     SKAGGBAG_FIELD_INPUT = 12,
177     SKAGGBAG_FIELD_OUTPUT,
178     SKAGGBAG_FIELD_NHIPv4,
179     SKAGGBAG_FIELD_INIT_FLAGS,
180     SKAGGBAG_FIELD_REST_FLAGS = 16,
181     SKAGGBAG_FIELD_TCP_STATE,
182     SKAGGBAG_FIELD_APPLICATION,
183     SKAGGBAG_FIELD_FTYPE_CLASS,
184     SKAGGBAG_FIELD_FTYPE_TYPE = 20,
185     /*
186      *  SKAGGBAG_FIELD_STARTTIME_MSEC = 21,
187      *  SKAGGBAG_FIELD_ENDTIME_MSEC,
188      *  SKAGGBAG_FIELD_ELAPSED_MSEC,
189      */
190     SKAGGBAG_FIELD_ICMP_TYPE = 24,
191     SKAGGBAG_FIELD_ICMP_CODE = 25,
192     /* the above correspond to values in rwascii.h */
193 
194     SKAGGBAG_FIELD_SIPv6,
195     SKAGGBAG_FIELD_DIPv6,
196     SKAGGBAG_FIELD_NHIPv6 = 28,
197 
198     SKAGGBAG_FIELD_ANY_IPv4,
199     SKAGGBAG_FIELD_ANY_IPv6,
200     SKAGGBAG_FIELD_ANY_PORT,
201     SKAGGBAG_FIELD_ANY_SNMP = 32,
202     SKAGGBAG_FIELD_ANY_TIME,
203 
204     SKAGGBAG_FIELD_CUSTOM_KEY,
205 
206     SKAGGBAG_FIELD_SIP_COUNTRY,
207     SKAGGBAG_FIELD_DIP_COUNTRY = 36,
208     SKAGGBAG_FIELD_ANY_COUNTRY,
209 
210     SKAGGBAG_FIELD_SIP_PMAP,
211     SKAGGBAG_FIELD_DIP_PMAP,
212     SKAGGBAG_FIELD_ANY_IP_PMAP = 40,
213 
214     SKAGGBAG_FIELD_SPORT_PMAP,
215     SKAGGBAG_FIELD_DPORT_PMAP,
216     SKAGGBAG_FIELD_ANY_PORT_PMAP = 43,
217 
218     SKAGGBAG_FIELD_RECORDS = 0xc000, /* 49152 */
219     SKAGGBAG_FIELD_SUM_PACKETS,
220     SKAGGBAG_FIELD_SUM_BYTES,
221     SKAGGBAG_FIELD_SUM_ELAPSED,
222     SKAGGBAG_FIELD_CUSTOM_COUNTER = 0xc004, /* 49156 */
223 
224     SKAGGBAG_FIELD_INVALID = 65534
225 } sk_aggbag_type_t;
226 
227 
228 /**
229  *    An initializer to use when creating an sk_aggbag_iter_t on the
230  *    stack.
231  */
232 #define SK_AGGBAG_ITER_INITIALIZER                              \
233     { NULL, {NULL, {0}}, {NULL, {0}}, {NULL, 0}, {NULL, 0}}
234 
235 /**
236  *    Specify SK_AGGBAG_KEY as the value of the 'key_counter_flag'
237  *    parameter to skAggBagFieldTypeIteratorBind() to visit the field
238  *    types that represent keys.
239  */
240 #define SK_AGGBAG_KEY       1
241 
242 /**
243  *    Specify SK_AGGBAG_KEY as the value of the 'key_counter_flag'
244  *    parameter to skAggBagFieldTypeIteratorBind() to visit the field
245  *    types that represent counters.
246  */
247 #define SK_AGGBAG_COUNTER   2
248 
249 /**
250  *    The maximum number of octets an aggregate key or counter value
251  *    may occupy.
252  */
253 #define SKAGGBAG_AGGREGATE_MAXLEN  UINT16_MAX
254 
255 
256 /**
257  *    Add the AggBag 'ab_addend' to the AggBag 'ab_augend'.
258  *
259  *    For each key in 'ab_addend', add the value for the key's counter
260  *    to its value in 'ab_augend', creating new entries for keys that
261  *    are not present.
262  */
263 int
264 skAggBagAddAggBag(
265     sk_aggbag_t        *ab_augend,
266     const sk_aggbag_t  *ab_addend);
267 
268 
269 /**
270  *    Get the value of the field at position 'field' in the key
271  *    specified by 'agg' and set the referent of 'time_value' to that
272  *    value.
273  *
274  *    Return SKAGGBAG_OK on success.  Return
275  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
276  *    is not a Time.
277  *
278  *    To set the value, use skAggBagAggregateSetDatetime().  See also
279  *    skAggBagAggregateGetIPAddress() and
280  *    skAggBagAggregateGetUnsigned().
281  */
282 int
283 skAggBagAggregateGetDatetime(
284     const sk_aggbag_aggregate_t    *agg,
285     const sk_aggbag_field_t        *field,
286     sktime_t                       *time_value);
287 
288 
289 /**
290  *    Get the value of the field at position 'field' in the key
291  *    specified by 'agg' and set the referent of 'ip_value' to that
292  *    value.
293  *
294  *    Return SKAGGBAG_OK on success.  Return
295  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
296  *    is not an IP address.
297  *
298  *    To set the value, use skAggBagAggregateSetIPAddress().  See also
299  *    skAggBagAggregateGetDatetime() and
300  *    skAggBagAggregateGetUnsigned().
301  */
302 int
303 skAggBagAggregateGetIPAddress(
304     const sk_aggbag_aggregate_t    *agg,
305     const sk_aggbag_field_t        *field,
306     skipaddr_t                     *ip_value);
307 
308 
309 /**
310  *    Get the value of the field at position 'field' in the key or
311  *    counter specified by 'agg' and set the referent of
312  *    'unsigned_value' to that value.
313  *
314  *    Return SKAGGBAG_OK on success.  Return
315  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
316  *    is an IP address or a Time.
317  *
318  *    To set the value, use skAggBagAggregateSetUnsigned().  See also
319  *    skAggBagAggregateGetDatetime() and
320  *    skAggBagAggregateGetIPAddress().
321  */
322 int
323 skAggBagAggregateGetUnsigned(
324     const sk_aggbag_aggregate_t    *agg,
325     const sk_aggbag_field_t        *field,
326     uint64_t                       *unsigned_value);
327 
328 
329 /**
330  *    Set the value of the field at position 'field' in the key
331  *    specified by 'agg' to the value in 'time_value'.
332  *
333  *    Return SKAGGBAG_OK on success.  Return
334  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
335  *    is not a Time.
336  *
337  *    To get the value, use skAggBagAggregateGetDatetime().  See also
338  *    skAggBagAggregateSetIPAddress() and
339  *    skAggBagAggregateSetUnsigned().
340  */
341 int
342 skAggBagAggregateSetDatetime(
343     sk_aggbag_aggregate_t      *agg,
344     const sk_aggbag_field_t    *field,
345     sktime_t                    time_value);
346 
347 /**
348  *    Set the value of the field at position 'field' in the key
349  *    specified by 'agg' to the value in 'ip_value'.
350  *
351  *    Return SKAGGBAG_OK on success.  Return
352  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
353  *    is not an IP address.
354  *
355  *    To get the value, use skAggBagAggregateGetIPAddress().  See also
356  *    skAggBagAggregateSetDatetime() and
357  *    skAggBagAggregateSetUnsigned().
358  */
359 int
360 skAggBagAggregateSetIPAddress(
361     sk_aggbag_aggregate_t      *agg,
362     const sk_aggbag_field_t    *field,
363     const skipaddr_t           *ip_value);
364 
365 /**
366  *    Set the value of the field at position 'field' in the key or
367  *    counter specified by 'agg' to the value in 'unsigned_value'.
368  *
369  *    Return SKAGGBAG_OK on success.  Return
370  *    SKAGGBAG_E_FIELD_TYPE_MISMATCH if the value at position 'field'
371  *    is an IP address or a Time.
372  *
373  *    To get the value, use skAggBagAggregateGetUnsigned().  See also
374  *    skAggBagAggregateSetDatetime() and
375  *    skAggBagAggregateSetIPAddress().
376  */
377 int
378 skAggBagAggregateSetUnsigned(
379     sk_aggbag_aggregate_t      *agg,
380     const sk_aggbag_field_t    *field,
381     uint64_t                    unsigned_value);
382 
383 
384 /**
385  *    Create a new AggBag data structure and store it in the referent
386  *    of 'ab'.  Before the AggBag can be used, the caller must call
387  *    skAggBagSetKeyFields() and skAggBagSetCounterFields() to set the
388  *    key fields and counter fields of the AggBag.
389  *
390  *    The caller must use skAggBagDestroy() to destroy the AggBag once
391  *    processing is complete.
392  */
393 int
394 skAggBagCreate(
395     sk_aggbag_t       **ab);
396 
397 
398 /**
399  *    Free all memory associated with an AggBag data structure in the
400  *    referent of 'ab' that was allocated via skAggBagCreate(),
401  *    skAggBagRead(), or skAggBagLoad().  Do nothing if 'ab' or its
402  *    referent is NULL.
403  */
404 void
405 skAggBagDestroy(
406     sk_aggbag_t       **ab);
407 
408 
409 /**
410  *    Return the type of the current field at position 'field_iter'.
411  *    Return SKAGGBAG_FIELD_INVALID if 'field_iter' is NULL or if it
412  *    is not positioned on a valid key field or counter field.
413  */
414 sk_aggbag_type_t
415 skAggBagFieldIterGetType(
416     const sk_aggbag_field_t    *field_iter);
417 
418 
419 /**
420  *    Set 'field_iter' to the next field that comprises the key or the
421  *    counter and return SK_ITERATOR_OK if a field exists or return
422  *    SK_ITERATOR_NO_MORE_ENTRIES if all fields have been visited.
423  */
424 int
425 skAggBagFieldIterNext(
426     sk_aggbag_field_t  *field_iter);
427 
428 
429 /**
430  *    Reset the iterator 'field_iter' that supports iterating over the
431  *    fields that comprise the key or counter.  This function sets the
432  *    iterator to point at the first field in the key or counter.
433  *
434  *    Since SiLK 3.17.0.
435  */
436 void
437 skAggBagFieldIterReset(
438     sk_aggbag_field_t  *field_iter);
439 
440 
441 /**
442  *    Return the name associated with the field type 'field_type'.
443  *    Return NULL if the field type is not known.
444  */
445 const char *
446 skAggBagFieldTypeGetName(
447     sk_aggbag_type_t    field_type);
448 
449 /**
450  *    Bind the iterator 'type_iter' to visit each type of key field or
451  *    counter field that the AggBag code supports.  The
452  *    'key_counter_flag' parameter must be either SK_AGGBAG_KEY or
453  *    SK_AGGBAG_COUNTER to specify which field types to visit.
454  *
455  *    The caller should create the iterator on the stack and pass its
456  *    address to this function.
457  *
458  *    Do nothing if 'type_iter' is NULL or 'key_counter_flag' is an
459  *    invalid value.
460  */
461 void
462 skAggBagFieldTypeIteratorBind(
463     sk_aggbag_type_iter_t  *type_iter,
464     unsigned int            key_counter_flag);
465 
466 /**
467  *    Move the type iterator 'type_iter' to the first/next type, set
468  *    the referent of 'field_type' to that type and return the name of
469  *    the type.  Set the referent of 'field_type' to
470  *    SKAGGBAG_FIELD_INVALID and return NULL when all types have been
471  *    visitied.
472  *
473  *    To use this function, the iterator must first be bound via
474  *    skAggBagFieldTypeIteratorBind().
475  */
476 const char *
477 skAggBagFieldTypeIteratorNext(
478     sk_aggbag_type_iter_t  *type_iter,
479     sk_aggbag_type_t       *field_type);
480 
481 /**
482  *    Move the field type iterator 'type_iter' to the beginning of the
483  *    AggBag so that skAggBagIteratorNext() returns the first key and
484  *    counter pair in the AggBag.  Do nothing if 'iter' is NULL.
485  */
486 void
487 skAggBagFieldTypeIteratorReset(
488     sk_aggbag_type_iter_t  *type_iter);
489 
490 
491 /**
492  *    Set all values in 'counter' to 0 and initialize
493  *    'counter_field_iter' to iterate over the fields that comprise
494  *    the aggregate counter in 'ab'.  The parameters 'counter' or
495  *    'counter_field_iter' may be NULL.
496  *
497  *    After calling this function, the iterator is pointed at the
498  *    first field in the counter, and one may set the value of that
499  *    field using one of the skAggBagAggregateSetFOO() functions.
500  *    Calling skAggBagFieldIterNext() moves the iterator to the second
501  *    field in the counter and returns SK_ITERATOR_OK or returns
502  *    SK_ITERATOR_NO_MORE_ENTRIES if the counter contains a single
503  *    field.
504  *
505  *    This function does not modify 'counter' and 'counter_field_iter'
506  *    if 'ab' is NULL.
507  *
508  *    Use skAggBagInitializeKey() to initialize the key.
509  */
510 void
511 skAggBagInitializeCounter(
512     const sk_aggbag_t      *ab,
513     sk_aggbag_aggregate_t  *counter,
514     sk_aggbag_field_t      *counter_field_iter);
515 
516 
517 /**
518  *    Set all values in 'key' to 0 and initialize 'key_field_iter' to
519  *    iterate over the fields that comprise the aggregate key in 'ab'.
520  *    The parameters 'key' or 'key_field_iter' may be NULL.
521  *
522  *    After calling this function, the iterator is pointed at the
523  *    first field in the key, and one may set the value of that field
524  *    using one of the skAggBagAggregateSetFOO() functions.  Calling
525  *    skAggBagFieldIterNext() moves the iterator to the second field in
526  *    the key and returns SK_ITERATOR_OK or returns
527  *    SK_ITERATOR_NO_MORE_ENTRIES if the key contains a single field.
528  *
529  *    This function does not modify 'key' and 'key_field_iter' if 'ab'
530  *    is NULL.
531  *
532  *    Use skAggBagInitializeCounter() to initialize the counter.
533  */
534 void
535 skAggBagInitializeKey(
536     const sk_aggbag_t      *ab,
537     sk_aggbag_aggregate_t  *key,
538     sk_aggbag_field_t      *key_field_iter);
539 
540 
541 /**
542  *    Bind the iterator 'iter' to visit the contents of the AggBag
543  *    data structure 'ab'.  The caller should create the iterator on
544  *    the stack, initialize it with the SK_AGGBAG_ITER_INITIALIZER,
545  *    and pass its address to this function.
546  *
547  *    The caller may use skAggBagIteratorNext() to move the first/next
548  *    key and counter pair in the AggBag.
549  *
550  *    Once the contents have been visited or the caller has finished
551  *    with the iterator, the caller must use skAggBagIteratorFree() to
552  *    free the memory allocated by this function.
553  *
554  *    Do nothing if 'iter' or 'ab' are NULL.
555  */
556 void
557 skAggBagIteratorBind(
558     sk_aggbag_iter_t       *iter,
559     const sk_aggbag_t      *ab);
560 
561 /**
562  *    Free the memory used by the AggBag contents iterator 'iter' that
563  *    was allocated by skAggBagIteratorBind().  For this function to
564  *    work correctly on an iterator that was not bound, the 'iter'
565  *    should be allocated on the stack and initialized with
566  *    SK_AGGBAG_ITER_INITIALIZER.  Do nothing if 'iter' is NULL.
567  */
568 void
569 skAggBagIteratorFree(
570     sk_aggbag_iter_t   *iter);
571 
572 /**
573  *    Move the AggBag contents iterator 'iter' to the first or next
574  *    key and counter pair in the AggBag.  Return SK_ITERATOR_OK if
575  *    the move was successful or SK_ITERATOR_NO_MORE_ENTRIES if all
576  *    key/counter pairs have been visited.  Do nothing if 'iter' is
577  *    NULL.
578  *
579  *    To use this function, the iterator must first be bound to an
580  *    AggBag via skAggBagIteratorBind().
581  */
582 int
583 skAggBagIteratorNext(
584     sk_aggbag_iter_t   *iter);
585 
586 /**
587  *    Move the AggBag contents iterator 'iter' to the beginning of the
588  *    AggBag so that skAggBagIteratorNext() returns the first key and
589  *    counter pair in the AggBag.  Do nothing if 'iter' is NULL.
590  */
591 void
592 skAggBagIteratorReset(
593     sk_aggbag_iter_t   *iter);
594 
595 
596 /**
597  *    In the AggBag 'ab', add to the counter associated with 'key' the
598  *    value in 'counter'.  If 'key' does not exist in 'ab', insert it
599  *    into 'ab' and set its value to 'counter'.
600  *
601  *    If 'new_counter' is not NULL, the new value of the counter is
602  *    copied into that location.  'new_counter' is unchanged when this
603  *    function turns a value other than SKAGGBAG_OK.
604  *
605  */
606 int
607 skAggBagKeyCounterAdd(
608     sk_aggbag_t                    *ab,
609     const sk_aggbag_aggregate_t    *key,
610     const sk_aggbag_aggregate_t    *counter,
611     sk_aggbag_aggregate_t          *new_counter);
612 
613 /**
614  *    Fill 'counter' with the value that 'key' has in the AggBag 'ab'.
615  *
616  *    If 'key' is not in 'ab', set fields in 'counter' to 0 and return
617  *    not found.  Otherwise, return SKAGGBAG_OK.
618  */
619 int
620 skAggBagKeyCounterGet(
621     const sk_aggbag_t              *ab,
622     const sk_aggbag_aggregate_t    *key,
623     sk_aggbag_aggregate_t          *counter);
624 
625 /**
626  *    Remove the counter associated with 'key' from the AggBag 'ab'.
627  */
628 int
629 skAggBagKeyCounterRemove(
630     sk_aggbag_t                    *ab,
631     const sk_aggbag_aggregate_t    *key);
632 
633 /**
634  *    In the AggBag 'ab', set the counter associated with 'key' to the
635  *    value 'counter', overwriting the current counter value, if any.
636  *    If 'counter' is non-zero, create 'key' if it does not already
637  *    exist in 'bag'.  If 'counter' is 0, remove 'key' if it exists in
638  *    'bag'; otherwise, do nothing.
639  */
640 int
641 skAggBagKeyCounterSet(
642     sk_aggbag_t                    *ab,
643     const sk_aggbag_aggregate_t    *key,
644     const sk_aggbag_aggregate_t    *counter);
645 
646 /**
647  *    In the AggBag 'ab', subtract from the counter associated with
648  *    'key' the value 'counter'.  If 'counter' is 0, return
649  *    SKAGGBAG_OK regardless of whether 'key' is in 'bag', but set
650  *    'new_counter' to the counter if 'key' is in 'ab' and if
651  *    'new_counter' is supplied.  When 'counter' is non-zero,
652  *    'key' must exist in 'bag'; if it does not, SKBAG_ERR_OP_BOUNDS
653  *    is returned.  SKBAG_ERR_OP_BOUNDS is also returned when 'key' is
654  *    outside the range of keys supported by 'ab'.
655  *
656  *    If 'new_counter' is not NULL, the new value of the counter is
657  *    copied into that location.  'new_counter' is unchanged when this
658  *    function turns a value other than SKAGGBAG_OK.
659  */
660 int
661 skAggBagKeyCounterSubtract(
662     sk_aggbag_t                    *ab,
663     const sk_aggbag_aggregate_t    *key,
664     const sk_aggbag_aggregate_t    *counter,
665     sk_aggbag_aggregate_t          *new_counter);
666 
667 
668 /**
669  *    Read a serialized AggBag from the file specified by 'filename'
670  *    into a newly created AggBag structure and set the referent of
671  *    'ab' to its location.  This function is a wrapper around
672  *    skBagRead().
673  *
674  *    The caller must use skAggBagDestroy() to free the AggBag once it
675  *    is no longer needed.
676  */
677 int
678 skAggBagLoad(
679     sk_aggbag_t           **ab,
680     const char             *filename);
681 
682 /**
683  *    Bind 'ab_opts' to the AggBag 'ab'.  'ab_opts' specify how the
684  *    AggBag will be written to disk.  If no options are bound to an
685  *    AggBag, the AggBag uses default values when writing the AggBag.
686  *
687  *    The AggBag 'ab' does not copy the 'ab_options'; it simply
688  *    maintains a pointer to them, and it references the options when
689  *    a call to skAggBagSave() or skAggBagWrite() is made.
690  */
691 void
692 skAggBagOptionsBind(
693     sk_aggbag_t                *ab,
694     const sk_aggbag_options_t  *ab_opts);
695 
696 /**
697  *    Register options that affect how binary AggBags are written.
698  *    The 'ab_opts' parameter is required; it is initialized to the
699  *    default values.
700  *
701  *    Prior to calling this function, the caller should set the
702  *    'existing_silk_files' member of the structure to either 0 or 1.
703  *    The value 1 indicates the application works with existing
704  *    AggBags (e.g., rwaggbagtool) or existing SiLK Flow files
705  *    (rwaggbag); the value 0 indicates the application creates new
706  *    AggBags (e.g., rwaggbagbuild).  If the value is non-zero, the
707  *    --notes-strip option is provided.
708  */
709 int
710 skAggBagOptionsRegister(
711     sk_aggbag_options_t    *ab_opts);
712 
713 /**
714  *    Free any memory or internal state used by the AggBag options.
715  */
716 void
717 skAggBagOptionsTeardown(
718     void);
719 
720 /**
721  *    Print usage information for the command line switches registered
722  *    by skAggBagOptionsRegister() to the specified file handle.
723  */
724 void
725 skAggBagOptionsUsage(
726     FILE               *fh);
727 
728 /**
729  *    Read a serialized AggBag from the input stream 'stream' into a
730  *    newly created AggBag structure and set the referent of 'ab' to
731  *    its location.
732  *
733  *    The caller must use skAggBagDestroy() to free the AggBag once it
734  *    is no longer needed.
735  *
736  *
737  *    See also skBagLoad().
738  */
739 int
740 skAggBagRead(
741     sk_aggbag_t           **ab,
742     skstream_t             *stream);
743 
744 /**
745  *    Serialize the AggBag structure 'ab' to the file specified by
746  *    'filename'.  This function is a wrapper around skBagWrite().
747  */
748 int
749 skAggBagSave(
750     const sk_aggbag_t      *ab,
751     const char             *filename);
752 
753 
754 /**
755  *    Set the key fields of the AggBag 'ab' to the list of
756  *    'field_count' values in in 'fields'.
757  */
758 int
759 skAggBagSetKeyFields(
760     sk_aggbag_t            *ab,
761     unsigned int            field_count,
762     const sk_aggbag_type_t  fields[]);
763 
764 /**
765  *    Set the counter fields of the AggBag 'ab' to the list of
766  *    'field_count' values in in 'fields'.
767  */
768 int
769 skAggBagSetCounterFields(
770     sk_aggbag_t            *ab,
771     unsigned int            field_count,
772     const sk_aggbag_type_t  fields[]);
773 
774 
775 /**
776  *    Return a static string that describes the error associated with
777  *    the error code 'err_code.
778  */
779 const char *
780 skAggBagStrerror(
781     int                 err_code);
782 
783 
784 /**
785  *    Subtract the AggBag 'ab_subtrahend' from the AggBag 'ab_minuend'.
786  *
787  *    For each key common to 'ab_subtrahend' and 'ab_minuend',
788  *    subtract the value of the key's counter in 'ab_subtrahend' from
789  *    the value of the key's counter in 'ab_minuend'.  Remove a key
790  *    from 'ab_minuend' if that key's counter is less than or equal to
791  *    the key's counter in 'ab_subtrahend'.
792  */
793 int
794 skAggBagSubtractAggBag(
795     sk_aggbag_t        *ab_minuend,
796     const sk_aggbag_t  *ab_subtrahend);
797 
798 
799 /**
800  *    Serialize the AggBag structure 'ab' to the output stream
801  *    'stream'.  The caller may set the compression method of 'stream'
802  *    before calling this function.
803  *
804  *
805  *    See also skBagSave().
806  */
807 int
808 skAggBagWrite(
809     const sk_aggbag_t      *ab,
810     skstream_t             *stream);
811 
812 
813 /*
814  *    Definifition of the type for sk_aggbag_aggregate_t so that the
815  *    aggregate may be created on the stack.  The caller must treat
816  *    the internals of this type as opaque.
817  */
818 struct sk_aggbag_aggregate_st {
819     const void         *opaque;
820     uint8_t             data[SKAGGBAG_AGGREGATE_MAXLEN];
821 };
822 
823 /*
824  *    Definifition of the type for sk_aggbag_field_t so that the field
825  *    iterator may be created on the stack.  The caller must treat the
826  *    internals of this type as opaque.
827  */
828 struct sk_aggbag_field_st {
829     const void         *opaque;
830     size_t              pos;
831 };
832 
833 /*
834  *    Definifition of the type for sk_aggbag_iter_t so that the AggBag
835  *    content iterator may be created on the stack.  The caller must
836  *    treat the internals of this type as opaque.
837  *
838  *    When creating an sk_aggbag_iter_t on the stack, the caller is
839  *    expected to initialize it to SK_AGGBAG_ITER_INITIALIZER.
840  */
841 struct sk_aggbag_iter_st {
842     const void              *opaque;
843     sk_aggbag_aggregate_t    key;
844     sk_aggbag_aggregate_t    counter;
845     sk_aggbag_field_t        key_field_iter;
846     sk_aggbag_field_t        counter_field_iter;
847 };
848 
849 
850 /*
851  *    Definifition of the type for sk_aggbag_type_iter_t so that the
852  *    type iterator may be created on the stack.  The caller must
853  *    treat the internals of this type as opaque.
854  */
855 struct sk_aggbag_type_iter_st {
856     sk_aggbag_type_t    pos;
857     unsigned int        key_counter_flag;
858 };
859 
860 
861 typedef enum sk_aggbag_retval_en {
862     SKAGGBAG_OK,
863     SKAGGBAG_E_ALLOC,
864     SKAGGBAG_E_NULL_PARM,
865     SKAGGBAG_E_FIXED_FIELDS,
866     SKAGGBAG_E_UNDEFINED_KEY,
867     SKAGGBAG_E_UNDEFINED_COUNTER,
868     SKAGGBAG_E_FIELD_CLASS,
869     SKAGGBAG_E_FIELDS_DIFFER_KEY,
870     SKAGGBAG_E_FIELDS_DIFFER_COUNTER,
871     SKAGGBAG_E_GET_SET_MISMATCH,
872     SKAGGBAG_E_BAD_INDEX,
873     SKAGGBAG_E_READ,
874     SKAGGBAG_E_WRITE,
875     SKAGGBAG_E_HEADER,
876     SKAGGBAG_E_INSERT,
877     SKAGGBAG_E_UNSUPPORTED_IPV6
878 } sk_aggbag_retval_t;
879 
880 
881 #ifdef __cplusplus
882 }
883 #endif
884 #endif /* _SKAGGBAG_H */
885 
886 /*
887 ** Local Variables:
888 ** mode:c
889 ** indent-tabs-mode:nil
890 ** c-basic-offset:4
891 ** End:
892 */
893