1 /*
2 ** Copyright (C) 2001-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 **  utils.h
11 **
12 **    A collection of utility routines.
13 **
14 **    Suresh L Konda
15 */
16 #ifndef _UTILS_H
17 #define _UTILS_H
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 #include <silk/silk.h>
23 
24 RCSIDENTVAR(rcsID_UTILS_H, "$SiLK: utils.h ef14e54179be 2020-04-14 21:57:45Z mthomas $");
25 
26 #include <silk/silk_types.h>
27 
28 #ifdef SK_HAVE_GETOPT_LONG_ONLY
29 #include <getopt.h>
30 #else
31 #include <silk/gnu_getopt.h>
32 #endif
33 
34 /**
35  *  @file
36  *
37  *    A collection of utility functions for registring an application,
38  *    registering options, providing common options, parsing option
39  *    strings, printing error messages, opening and closing file, et
40  *    cetera.
41  *
42  *    This file is part of libsilk.
43  */
44 
45 
46 /**
47  *    Where to create temp files by default.  This can be overridden
48  *    by the --temp-dir switch (assuming skOptionsTempDirRegister() is
49  *    in use), or environment variable named in SK_TEMPDIR_ENVAR1 or
50  *    the environment variable named in SK_TEMPDIR_ENVAR2.
51  *
52  *    If this is not defined, no default exists.
53  */
54 #define SK_TEMPDIR_DEFAULT "/tmp"
55 
56 /**
57  *    Name of primary environment variable that holds name of temp
58  *    directory.  This is consulted when the --temp-dir switch is not
59  *    given.
60  */
61 #define SK_TEMPDIR_ENVAR1 "SILK_TMPDIR"
62 
63 /**
64  *    Name of alternate environment variable that holds name of temp
65  *    directory.  Used when the --temp-dir switch is not given and the
66  *    variable named by SK_TMPDIR_ENVAR1 is not set.
67  */
68 #define SK_TEMPDIR_ENVAR2 "TMPDIR"
69 
70 
71 
72 typedef enum {
73     /* Command was successful */
74     SKUTILS_OK = 0,
75 
76     /* Input to function is null or invalid (e.g., 0 length bitmap) */
77     SKUTILS_ERR_INVALID = -1,
78 
79     /* Input to function was empty (or contained only whitespace) */
80     SKUTILS_ERR_EMPTY = -2,
81 
82     /* Unexpected/Bad character or number is unparseable */
83     SKUTILS_ERR_BAD_CHAR = -3,
84 
85     /* Value overflows the parser */
86     SKUTILS_ERR_OVERFLOW = -4,
87 
88     /* Value underflows the parser */
89     SKUTILS_ERR_UNDERFLOW = -5,
90 
91     /* Range is invalid (min > max) */
92     SKUTILS_ERR_BAD_RANGE = -6,
93 
94     /* Unexpected end-of-input */
95     SKUTILS_ERR_SHORT = -7,
96 
97     /* Too many fields provided */
98     SKUTILS_ERR_TOO_MANY_FIELDS = -8,
99 
100     /* Out of memory */
101     SKUTILS_ERR_ALLOC = -9,
102 
103     /* Miscellaneous error */
104     SKUTILS_ERR_OTHER = -10,
105 
106     /* Value is below the minimum */
107     SKUTILS_ERR_MINIMUM = -11,
108 
109     /* Value is above the maximum */
110     SKUTILS_ERR_MAXIMUM = -12,
111 
112     /* Host name or port could not be resolved */
113     SKUTILS_ERR_RESOLVE = -13
114 } silk_utils_errcode_t;
115 
116 
117 
118 /*
119 **
120 **  sku-compat.c
121 **
122 */
123 
124 /* silk.h will #define intmax_t sk_intmax_t if required */
125 typedef int64_t sk_intmax_t;
126 
127 /* silk.h will #define imaxdiv_t sk_imaxdiv_t if required */
128 typedef struct sk_imaxdiv_st {
129     sk_intmax_t quot; /* Quotient  */
130     sk_intmax_t rem;  /* Remainder */
131 } sk_imaxdiv_t;
132 
133 /* silk.h will #define imaxdiv sk_imaxdiv if required */
134 /**
135  *    Do the integer division of 'numer' by 'denom'; return a
136  *    structure that contains the 'quot' (quotient) and the 'rem'
137  *    (remainder).
138  *
139  *    Conforming to C99.
140  */
141 sk_imaxdiv_t
142 sk_imaxdiv(
143     sk_intmax_t         numer,
144     sk_intmax_t         denom);
145 
146 
147 /* silk.h will #define memccpy sk_memccpy if required */
148 /**
149  *    Copy bytes from 'src' to 'dst' stopping after the first
150  *    occurance of 'c' or when 'len' octets have been copied,
151  *    whichever comes first.  If 'c' was not found, NULL is returned;
152  *    else return value pointing to character after 'c' in 'dst'.
153  *
154  *    Conforming to C99.
155  */
156 void *
157 sk_memccpy(
158     void               *dst,
159     const void         *src,
160     int                 c,
161     size_t              len);
162 
163 
164 /* silk.h will #define setenv sk_setenv if required */
165 /**
166  *    Set environment variable 'name' to 'value', unless 'name' already
167  *    exists in the environment and 'overwrite' is 0.
168  *
169  *    Return 0 on success.  Return -1 and set errno on memory
170  *    allocation error or if 'name' contains a '=' character.  Assumes
171  *    'name' and 'value' are not NULL.
172  *
173  *    Conforming to POSIX.1-2001
174  */
175 int
176 sk_setenv(
177     const char         *name,
178     const char         *value,
179     int                 overwrite);
180 
181 
182 /* silk.h will #define strsep sk_strsep if required */
183 /**
184  *    Locate in *stringp first occurrence of any member of 'delim'.
185  *    Change that character to '\0', modify '*stringp' to point to the
186  *    following character, and return the original value of *stringp.
187  *
188  *    Return NULL if *stringp is NULL or when **stringp is '\0'; i.e.,
189  *    when the end of the string is reached.
190  *
191  *    Empty field is determined by testing the returned value to '\0'.
192  *
193  *    Comforming to BSD 4.4
194  */
195 char *
196 sk_strsep(
197     char              **stringp,
198     const char         *delim);
199 
200 
201 /* silk.h will #define timegm sk_timegm if required */
202 /**
203  *    Do the reverse of gmtime(): Take a time structure and return
204  *    seconds since the epoch in the UTC timezone.
205  *
206  *    No standard; common on Open Source systems.
207  */
208 time_t
209 sk_timegm(
210     struct tm          *tm);
211 
212 
213 #if 0
214 /**
215  *    Replacement for snprintf() that always NUL terminates the string.
216  */
217 int
218 sk_snprintf(
219     char               *str,
220     size_t              size,
221     const char         *format,
222     ...);
223 
224 
225 /**
226  *    Replacement for vsnprintf() that always NUL terminates the string.
227  */
228 int
229 sk_vsnprintf(
230     char               *str,
231     size_t              size,
232     const char         *format,
233     va_list             args);
234 #endif
235 
236 
237 
238 /*
239 **
240 **  skbitmap.c
241 **
242 */
243 
244 
245 /* typedef struct sk_bitmap_st sk_bitmap_t; // silk_types.h */
246 struct sk_bitmap_st {
247     uint32_t   *map;
248     uint32_t    num_bits;
249     uint32_t    count;
250 };
251 
252 
253 /**
254  *    Type for iterating over the entries in an sk_bitmap_t.
255  */
256 typedef struct sk_bitmap_iter_st {
257     const sk_bitmap_t  *bitmap;
258     uint32_t            map_idx;
259     uint8_t             pos;
260 } sk_bitmap_iter_t;
261 
262 
263 /* Internal macros.  Not for public use. */
264 #define _BMAP_INDEX(p)      ((p) >> 5)
265 #define _BMAP_OFFSET(p)     (1u << ((p) & 0x1F))
266 #define _BMAP_IS_SET(b, p)  ((b)->map[_BMAP_INDEX(p)] & _BMAP_OFFSET(p))
267 
268 
269 
270 /**
271  *    Create a new empty bitmap capable of holding 'num_bits' bits.
272  *    All bits in the map are set to 0/LOW/OFF.  Return the bitmap in
273  *    the location given by 'bitmap_out'.  Returns 0 if successful; -1
274  *    for a memory allocation error or if 'num_bits' is zero.
275  *
276  *    Bits in an sk_bitmap_t are numbered from 0 to num_bits-1.
277  *
278  *    See also skBitmapBind().
279  */
280 int
281 skBitmapCreate(
282     sk_bitmap_t       **bitmap_out,
283     uint32_t            num_bits);
284 
285 
286 /**
287  *    Bind 'bitmap' to an existing array of uint32_t, 'bitarray', and
288  *    clear the bitmap.  'num_bits' is number of bits you want to the
289  *    bitmap to hold.  'sizeof_bitarray' should be the value of
290  *    sizeof(bitarray).
291  *
292  *    This function can be used to create bitmaps on the stack without
293  *    having to use the allocation code in skBitmapCreate().  These
294  *    bitmaps should NOT be skBitmapDestroy()'ed.
295  */
296 int
297 skBitmapBind(
298     sk_bitmap_t        *bitmap,
299     uint32_t            num_bits,
300     uint32_t           *bitarray,
301     size_t              sizeof_bitarray);
302 
303 
304 /**
305  *    Destroy the bitmap at location given by 'bitmap' that was
306  *    created by skBitmapCreate().  Do not call this function when you
307  *    have used skBitmapBind().
308  *
309  *    The 'bitmap' paramter may be NULL or it may reference a NULL
310  *    value.
311  */
312 void
313 skBitmapDestroy(
314     sk_bitmap_t       **bitmap);
315 
316 
317 /**
318  *    Turn OFF all the bits in 'bitmap' and set the high-bit count to
319  *    zero.
320  */
321 void
322 skBitmapClearAllBits(
323     sk_bitmap_t        *bitmap);
324 
325 
326 /**
327  *    Turn ON all the bits in 'bitmap' and set the high-bit count to
328  *    the number of bits in the bitmap.
329  */
330 void
331 skBitmapSetAllBits(
332     sk_bitmap_t        *bitmap);
333 
334 
335 /**
336  *    Return the number of bits that 'bitmap' can hold.
337  */
338 uint32_t
339 skBitmapGetSizeF(
340     const sk_bitmap_t  *bitmap);
341 #define skBitmapGetSizeFast(bmap_size_fast)     \
342     ((bmap_size_fast)->num_bits)
343 #ifdef SKBITMAP_DEBUG
344 #  define skBitmapGetSize(bitmap) skBitmapGetSizeF(bitmap)
345 #else
346 #  define skBitmapGetSize(bitmap) skBitmapGetSizeFast(bitmap)
347 #endif
348 
349 
350 /**
351  *    Return the number of bits in 'bitmap' that are ON.
352  */
353 uint32_t
354 skBitmapGetHighCountF(
355     const sk_bitmap_t  *bitmap);
356 #define skBitmapGetHighCountFast(bmap_high_fast)        \
357     ((bmap_high_fast)->count)
358 #ifdef SKBITMAP_DEBUG
359 #  define skBitmapGetHighCount(bitmap) skBitmapGetHighCountF(bitmap)
360 #else
361 #  define skBitmapGetHighCount(bitmap) skBitmapGetHighCountFast(bitmap)
362 #endif
363 
364 
365 /**
366  *    Return 1 if the bit at position 'pos' in 'bitmap' is ON; return
367  *    0 if it is OFF.  Valid values for 'pos' are 0 through one less
368  *    than the number of bits in the bitmap.  Return -1 if 'pos' is
369  *    larger than the size of the bitmap.
370  */
371 int
372 skBitmapGetBitF(
373     const sk_bitmap_t  *bitmap,
374     uint32_t            pos);
375 #define skBitmapGetBitFast(bmap_get_fast, pos_get_fast)         \
376     ((((uint32_t)(pos_get_fast)) >= (bmap_get_fast)->num_bits)  \
377      ? -1                                                       \
378      : !!_BMAP_IS_SET((bmap_get_fast), (pos_get_fast)))
379 #ifdef SKBITMAP_DEBUG
380 #  define skBitmapGetBit(bitmap, pos) skBitmapGetBitF(bitmap, pos)
381 #else
382 #  define skBitmapGetBit(bitmap, pos) skBitmapGetBitFast(bitmap, pos)
383 #endif
384 
385 
386 /**
387  *    Turn ON the bit at position 'pos' in 'bitmap'.  Adjust the
388  *    bitmap's high-bit counter.  Valid values for 'pos' are 0 through
389  *    one less than the number of bits in the bitmap.
390  */
391 void
392 skBitmapSetBitF(
393     sk_bitmap_t        *bitmap,
394     uint32_t            pos);
395 #define skBitmapSetBitFast(bmap_set_fast, pos_set_fast)                 \
396     if ((((uint32_t)(pos_set_fast)) >= (bmap_set_fast)->num_bits)       \
397         || _BMAP_IS_SET((bmap_set_fast), (pos_set_fast)))               \
398     { /* no-op */ } else {                                              \
399         (bmap_set_fast)->map[_BMAP_INDEX(pos_set_fast)]                 \
400             |= _BMAP_OFFSET(pos_set_fast);                              \
401         ++(bmap_set_fast)->count;                                       \
402     }
403 #ifdef SKBITMAP_DEBUG
404 #  define skBitmapSetBit(bitmap, pos) skBitmapSetBitF(bitmap, pos)
405 #else
406 #  define skBitmapSetBit(bitmap, pos) skBitmapSetBitFast(bitmap, pos)
407 #endif
408 
409 
410 /**
411  *    Turn OFF the bit at position 'pos' in 'bitmap'.  Adjust the
412  *    bitmap's high-bit counter.  Valid values for 'pos' are 0 through
413  *    one less than the number of bits in the bitmap.
414  */
415 void
416 skBitmapClearBitF(
417     sk_bitmap_t        *bitmap,
418     uint32_t            pos);
419 #define skBitmapClearBitFast(bmap_clear_fast, pos_clear_fast)   \
420     if (((pos_clear_fast) >= (bmap_clear_fast)->num_bits)       \
421         || !_BMAP_IS_SET((bmap_clear_fast),(pos_clear_fast)))   \
422     { /* no-op */ } else {                                      \
423         (bmap_clear_fast)->map[_BMAP_INDEX(pos_clear_fast)]     \
424             &= ~(_BMAP_OFFSET(pos_clear_fast));                 \
425         --(bmap_clear_fast)->count;                             \
426     }
427 #ifdef SKBITMAP_DEBUG
428 #  define skBitmapClearBit(bitmap, pos) skBitmapClearBitF(bitmap, pos)
429 #else
430 #  define skBitmapClearBit(bitmap, pos) skBitmapClearBitFast(bitmap, pos)
431 #endif
432 
433 
434 /**
435  *    Modify 'bitmap' in place to hold its complement.
436  */
437 void
438 skBitmapComplement(
439     sk_bitmap_t        *bitmap);
440 
441 
442 /**
443  *    Compute the intersection of 'dest' and 'src', placing the result
444  *    in 'dest'.  The bitmaps must be of the same size.  If they are
445  *    not of the same size, returns -1, else returns 0.
446  */
447 int
448 skBitmapIntersection(
449     sk_bitmap_t        *dest,
450     const sk_bitmap_t  *src);
451 
452 
453 /**
454  *    Compute the union of 'dest' and 'src', placing the result in
455  *    'dest'.  The bitmaps must be of the same size.  If they are not
456  *    of the same size, returns -1, else returns 0.
457  */
458 int
459 skBitmapUnion(
460     sk_bitmap_t        *dest,
461     const sk_bitmap_t  *src);
462 
463 
464 /**
465  *    Return the number of bits, starting at 'begin_pos', that have
466  *    the value 'state', which should be 0 or 1.  Return UINT32_MAX if
467  *    'begin_pos' is larger than the size of the bitmap.
468  */
469 uint32_t
470 skBitmapCountConsecutive(
471     const sk_bitmap_t  *bitmap,
472     uint32_t            begin_pos,
473     uint32_t            state);
474 
475 
476 /**
477  *    Turn ON all bits in the bitmap from 'begin_pos' to 'end_pos'
478  *    inclusive.  Valid values for 'begin_pos' and 'end_pos' are 0
479  *    through one less than the number of bits in the bitmap.  Return
480  *    -1 if 'end_pos' is less than 'begin_pos' or if either value is
481  *    larger than the size of the bitmap.  Return 0 otherwise.
482  */
483 int
484 skBitmapRangeSet(
485     sk_bitmap_t        *bitmap,
486     uint32_t            begin_pos,
487     uint32_t            end_pos);
488 
489 
490 /**
491  *    Turn OFF all bits in the bitmap from 'begin_pos' to 'end_pos'
492  *    inclusive.  Valid values for 'begin_pos' and 'end_pos' are 0
493  *    through one less than the number of bits in the bitmap.  Return
494  *    -1 if 'end_pos' is less than 'begin_pos' or if either value is
495  *    larger than the size of the bitmap.  Return 0 otherwise.
496  */
497 int
498 skBitmapRangeClear(
499     sk_bitmap_t        *bitmap,
500     uint32_t            begin_pos,
501     uint32_t            end_pos);
502 
503 
504 /**
505  *    Return a count of the number of bits between 'begin_pos' and
506  *    'end_pos' inclusive that are currently ON.  Valid values for
507  *    'begin_pos' and 'end_pos' are 0 through one less than the number
508  *    of bits in the bitmap.  Return UINT32_MAX if 'end_pos' is less
509  *    than 'begin_pos' or if either value is larger than the size of
510  *    the bitmap.
511  */
512 uint32_t
513 skBitmapRangeCountHigh(
514     sk_bitmap_t        *bitmap,
515     uint32_t            begin_pos,
516     uint32_t            end_pos);
517 
518 
519 /**
520  *    Bind the bitmap iterator 'iter' to iterate over the high bits in
521  *    the bitmap 'bitmap'.  It is possible to set/unset bits in the
522  *    bitmap as the iterator moves through it and have the iterator
523  *    visit/skip those bits---as long as the bit position changed is
524  *    greater than the iterator's current position.
525  */
526 void
527 skBitmapIteratorBind(
528     const sk_bitmap_t  *bitmap,
529     sk_bitmap_iter_t   *iter);
530 
531 /**
532  *    Set 'pos' to the next high bit in the bitmap that is bound to
533  *    the iterator 'iter' and return SK_ITERATOR_OK.  If the iterator
534  *    has visited all the high bits in the bitmap, leave the value in
535  *    'pos' unchanged and return SK_ITERATOR_NO_MORE_ENTRIES.
536  */
537 int
538 skBitmapIteratorNext(
539     sk_bitmap_iter_t   *iter,
540     uint32_t           *pos);
541 
542 
543 /**
544  *    Allow the bitmap iterator 'iter' to iterate over the bitmap
545  *    again.
546  */
547 void
548 skBitmapIteratorReset(
549     sk_bitmap_iter_t   *iter);
550 
551 
552 /**
553  *  BITS_IN_WORD32(&countptr, word);
554  *  BITS_IN_WORD64(&countptr, word);
555  *
556  *    Set the value pointed at by 'countptr' to the number of bits
557  *    that are high in the value 'word', where 'word' is either 32 or
558  *    64 bits.
559  *
560  * Fast method of computing the number of bits in a 32-bit word.  From
561  * http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
562  */
563 #define BITS_IN_WORD32(countptr, word)                                  \
564     do {                                                                \
565         uint32_t vv = (word) - (((word) >> 1) & 0x55555555);            \
566         vv = (vv & 0x33333333) + ((vv >> 2) & 0x33333333);              \
567         *(countptr) = (((vv + (vv >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; \
568     } while(0)
569 
570 #define BITS_IN_WORD64(countptr, word)                                  \
571     do {                                                                \
572         uint64_t vv = ((uint64_t)(word)                                 \
573                        - ((uint64_t)((word) >> 1)                       \
574                           & UINT64_C(0x5555555555555555)));             \
575         vv = ((vv & UINT64_C(0x3333333333333333))                       \
576               + ((vv >> 2) & UINT64_C(0x3333333333333333)));            \
577         *(countptr) = (((uint64_t)((vv + (vv >> 4))                     \
578                                    & UINT64_C(0x0f0f0f0f0f0f0f0f))      \
579                         * UINT64_C(0x0101010101010101)) >> 56);         \
580     } while(0)
581 
582 #define BITS_IN_WORD(countptr, word)    BITS_IN_WORD32(countptr, word)
583 
584 
585 /**
586  *  _BITMASK32(s);
587  *  _BITMASK64(s);
588  *
589  *    Private macro used by GET_MASKED_BITS and SET_MASKED_BITS.  This
590  *    returns a 32-bit (or 64-bit) integer with the first `s'
591  *    least-significant bits turned on.
592  */
593 #define _BITMASK32(s)                                   \
594     (((s) >= 32) ? UINT32_MAX : ~(UINT32_MAX << (s)))
595 
596 #define _BITMASK64(s)                                   \
597     (((s) >= 64) ? UINT64_MAX : ~(UINT64_MAX << (s)))
598 
599 #define _BITMASK(s)  _BITMASK32(s)
600 
601 
602 /*
603  *  GET_MASKED_BITS32(x, o, s)
604  *  GET_MASKED_BITS64(x, o, s)
605  *
606  *    Given an integer value 'x', return an integer created by
607  *    shifting 'x' to the right by offset 'o' bits and returning the
608  *    least significant 's' bits.  Works on any size 'x' up to maximum
609  *    specified in the macro's name.
610  *
611  *    GET_MASKED_BITS32(x, 2, 5) would return the value represented by
612  *    the middle 5 bits of a single byte, as shown here:
613  *
614  *    76543210
615  *    .xxxxx..
616  *
617  *    with the value shifted to the right.  The possible values
618  *    returned range from 0---if NONE of the bits are set---through
619  *    31---if ALL of the bits are set.
620  */
621 #define GET_MASKED_BITS32(x, o, s) (((x) >> (o)) & _BITMASK32((s)))
622 
623 #define GET_MASKED_BITS64(x, o, s) (((x) >> (o)) & _BITMASK64((s)))
624 
625 #define GET_MASKED_BITS(x, o, s)   GET_MASKED_BITS32(x, o, s)
626 
627 
628 /**
629  *  SET_MASKED_BITS32(x, v, o, s)
630  *  SET_MASKED_BITS64(x, v, o, s)
631  *
632  *    Modify the integer variable 'x' by clearing the bits from 'o' to
633  *    'o'+'s'-1, and replacing those bits by shifting the value 'v' to
634  *    the left 'o' bits.
635  *
636  *    Bits are numbered with the least significant bit being 0.
637  *
638  *    For example, with x=0 and v<=31, the call
639  *
640  *    SET_MASKED_BITS32(x, v, 1, 5)
641  *
642  *    will result in 'x' being set to 2*'v', with a possible range of
643  *    resulting values for 'x' of 2 to 62.
644  *
645  *    This is the setting equivalent to GET_MASKED_BITS32().
646  */
647 #define SET_MASKED_BITS32(x, v, o, s)                   \
648     do {                                                \
649         (x) = (((x) & (~(_BITMASK32(s) << (o))))        \
650                | (((v) & _BITMASK32(s)) << (o)));       \
651     } while(0)
652 
653 #define SET_MASKED_BITS64(x, v, o, s)                   \
654     do {                                                \
655         (x) = (((x) & (~(_BITMASK64(s) << (o))))        \
656                | (((v) & _BITMASK64(s)) << (o)));       \
657     } while(0)
658 
659 #define SET_MASKED_BITS(x, v, o, s)  SET_MASKED_BITS32(x, v, o, s)
660 
661 
662 /**
663  *  BITMAP_DECLARE(var_name, size);
664  *
665  *    Declares the bitmap 'var_name' that will hold size bits numbered
666  *    from 0 to size-1.
667  */
668 #define BITMAP_DECLARE(name, size)                                      \
669     uint32_t name[((size) >> 5) + ((((size) & 0x1F) == 0) ? 0 : 1)]
670 
671 /**
672  *  BITMAP_INIT(name);
673  *
674  *    Clears all the bits in the bitmap named 'name'.  This macro must
675  *    appear in the same scope as the BITMAP_DECLARE() macro.
676  */
677 #define BITMAP_INIT(name) memset(&name, 0, sizeof(name))
678 
679 /**
680  *  BITMAP_SETBIT(name, pos);
681  *  BITMAP_CLEARBIT(name, pos);
682  *  is_set = BITMAP_GETBIT(name, pos);
683  *
684  *    Set, clear, or get the bit as position 'pos' in bitmap 'name'.
685  */
686 #define BITMAP_SETBIT(name, pos)                        \
687     ((name)[_BMAP_INDEX(pos)] |= _BMAP_OFFSET(pos))
688 #define BITMAP_CLEARBIT(name, pos)                      \
689     ((name)[_BMAP_INDEX(pos)] &= ~_BMAP_OFFSET(pos))
690 #define BITMAP_GETBIT(name, pos)                                \
691     (((name)[_BMAP_INDEX(pos)] & _BMAP_OFFSET(pos)) ? 1 : 0)
692 
693 
694 /*
695 **
696 **    sku-app.c
697 **
698 */
699 
700 /**
701  *    The null message function.  Does nothing and returns zero.
702  */
703 int
704 skMsgNone(
705     const char         *fmt,
706     ...)
707     SK_CHECK_PRINTF(1, 2);
708 
709 /**
710  *    The null message function.  Does nothing and returns zero.
711  */
712 int
713 skMsgNoneV(
714     const char         *fmt,
715     va_list             args)
716     SK_CHECK_PRINTF(1, 0);
717 
718 /**
719  *    Register the application.  Other functions below assume you've
720  *    passed argv[0] as the value of 'name'.
721  */
722 void
723 skAppRegister(
724     const char         *name);
725 
726 /**
727  *    Destroy all data structures and free all memory associated with
728  *    this application.
729  */
730 void
731 skAppUnregister(
732     void);
733 
734 /**
735  *    Return the name that was used to register the application.  This
736  *    is the value that was passed to skAppRegister().  The return
737  *    value should be considered read-only.
738  */
739 const char *
740 skAppRegisteredName(
741     void);
742 
743 /**
744  *    Return a short name for the application.  This is the basename
745  *    of the registered name.  The return value should be considered
746  *    read-only.
747  */
748 const char *
749 skAppName(
750     void);
751 
752 /**
753  *    Return the full path to application.  This will consult the PATH
754  *    envar and cgetcwd() to find the complete path to the
755  *    application.  The return value should be considered read-only.
756  */
757 const char *
758 skAppFullPathname(
759     void);
760 
761 /**
762  *    Return the application's directory's parent directory in 'buf',
763  *    a character array of 'buf_len' bytes. e.g., if the rwfilter
764  *    application lives in "/usr/local/bin/rwfilter", this function
765  *    puts "/usr/local" into buf.  Return value is a pointer to 'buf',
766  *    or NULL on error.
767  */
768 char *
769 skAppDirParentDir(
770     char               *buf,
771     size_t              buf_len);
772 
773 /**
774  *    Print short usage information---telling the user to use the
775  *    ``--help'' option---to stderr and exit the application with a
776  *    FAILURE exit status.
777  */
778 void
779 skAppUsage(
780     void)
781     NORETURN;
782 
783 /**
784  *    Print, to the 'fh' file handle, the current application's name,
785  *    the 'usage_msg', each option in 'app_options' and its 'app_help'
786  *    string.  Returns control to the application.
787  */
788 void
789 skAppStandardUsage(
790     FILE                   *fh,
791     const char             *usage_msg,
792     const struct option    *app_options,
793     const char            **app_help);
794 
795 /**
796  *    Structure used to verify that a SiLK library was compiled with
797  *    the same set of features that were used to build the
798  *    application.
799  */
800 typedef struct silk_features_st {
801     uint64_t struct_version;
802     uint8_t  big_endian;
803     uint8_t  enable_ipv6;
804     uint8_t  enable_gnutls;
805     uint8_t  enable_ipfix;
806     uint8_t  enable_localtime;
807 } silk_features_t;
808 
809 #define SILK_FEATURES_DEFINE_STRUCT(var_name)   \
810     const silk_features_t var_name = {          \
811         2,                                      \
812         SK_BIG_ENDIAN,                          \
813         SK_ENABLE_IPV6,                         \
814         SK_ENABLE_GNUTLS,                       \
815         SK_ENABLE_IPFIX,                        \
816         SK_ENABLE_LOCALTIME                     \
817     }
818 
819 /**
820  *    Verify that the features that were compiled into the application
821  *    agree with those that were compiled into the libsilk library.
822  *
823  *    Currently 'future_use' is unused, but is included for possible
824  *    future expansion.
825  */
826 void
827 skAppVerifyFeatures(
828     const silk_features_t  *features,
829     void                   *future_use);
830 
831 /**
832  *    Sets the error stream to 'f' for any messages printed with
833  *    skAppPrintErrV() or skAppUsage().  When 'f' is NULL, calling
834  *    skAppPrintErr(), skAppPrintErrV(), and skAppUsage() will result
835  *    in no output being generated.
836  *
837  *    Returns the previous value of the error-stream.
838  */
839 FILE *
840 skAppSetErrStream(
841     FILE               *f);
842 
843 /**
844  *    Sets the function that skAppPrintErr() will call to print its
845  *    arguments.  If 'fn' is NULL, resets skAppPrintErr() to use its
846  *    default function, which is skAppPrintErrV().  To disable
847  *    printing of errors, pass 'skMsgNoneV' to this function.
848  */
849 void
850 skAppSetFuncPrintErr(
851     sk_msg_vargs_fn_t   fn);
852 
853 /**
854  *    Sets the function that skAppPrintSyserror() will call to print
855  *    its arguments.  If 'fn' is NULL, resets skAppPrintSyserror() to
856  *    use its default function, which is skAppPrintSyserrorV().  To
857  *    disable printing of errors, pass 'skMsgNoneV' to this function.
858  */
859 void
860 skAppSetFuncPrintSyserror(
861     sk_msg_vargs_fn_t   fn);
862 
863 /**
864  *    Sets the function that skAppPrintAbortMsg(),
865  *    skAppPrintBadCaseMsg(), and skAppPrintOutOfMemoryMsgFunction()
866  *    will call to print their arguments.  If 'fn' is NULL, resets the
867  *    functions to use the default function, which is skAppPrintErr().
868  *    To disable printing of errors, pass 'skMsgNone' to this
869  *    function.
870  */
871 void
872 skAppSetFuncPrintFatalErr(
873     sk_msg_fn_t         fn);
874 
875 /**
876  *    Prints the application name, a colon, the result of formatting
877  *    the arguments using v*printf(), and a newline to the stream set
878  *    by skAppSetErrStream(), which defaults to stderr.
879  *
880  *    This is the default function used by skAppPrintErr() to print
881  *    error messages.
882  */
883 int
884 skAppPrintErrV(
885     const char         *fmt,
886     va_list             args);
887 
888 /**
889  *    Prints the application name, a colon, the result of formatting
890  *    the arguments using v*printf(), the result of calling
891  *    strerror(), and a newline to the stream set by
892  *    skAppSetErrStream(), which defaults to stderr.
893  *
894  *    This is the default function used by skAppPrintSyserror() to
895  *    print system error messages.
896  */
897 int
898 skAppPrintSyserrorV(
899     const char         *fmt,
900     va_list             args);
901 
902 
903 #ifdef TEST_PRINTF_FORMATS
904 #define skAppPrintErr printf
905 #else
906 /**
907  *    Calls the function set by skAppSetFuncPrintErr()---which has the
908  *    default value skAppPrintErrV()---to format and print the
909  *    arguments using the given format 'fmt'.
910  */
911 int
912 skAppPrintErr(
913     const char         *fmt,
914     ...)
915     SK_CHECK_PRINTF(1, 2);
916 #endif
917 
918 
919 #ifdef TEST_PRINTF_FORMATS
920 #define skAppPrintSyserror printf
921 #else
922 /**
923  *    Calls the function set by skAppSetFuncPrintSyserror()---which
924  *    has the default value skAppPrintSyserrorV()---to format and
925  *    print the arguments using the given format 'fmt'.
926  */
927 int
928 skAppPrintSyserror(
929     const char         *fmt,
930     ...)
931     SK_CHECK_PRINTF(1, 2);
932 #endif
933 
934 
935 /**
936  *    Prints a message to the standard error.  This function appends a
937  *    final newline to the output.  This function may used by
938  *    TRACEMSG(), see sktracemsg.h.
939  */
940 int
941 skTraceMsg(
942     const char         *fmt,
943     ...)
944     SK_CHECK_PRINTF(1, 2);
945 
946 
947 /**
948  *    Install the function 'sig_handler' to be called whenever the
949  *    application receives a SIGINT, SIGTERM, SIGQUIT, or SIGPIPE.
950  *
951  *    The parameter passed to 'sig_handler' will be the received
952  *    signal.
953  *
954  *    Return 0 on success, or -1 if the handler cannot be installed.
955  */
956 int
957 skAppSetSignalHandler(
958     void              (*sig_handler)(int signal));
959 
960 
961 /**
962  *    Use skAbort() to call this function.
963  *
964  *    skAbort() is a macro defined in silk.h that calls this function
965  *    with the current function name (if the compiler supports it),
966  *    filename, and line number macros.  Once this function returns,
967  *    the skAbort() macro calls abort().
968  *
969  *    This function will call the function specified by
970  *    skAppSetFuncPrintFatalErr() to print a message containing the
971  *    specified 'func_name', 'file_name' and 'line_number' values.
972  *    This function will return.  It is the caller's responsibility to
973  *    call abort().
974  */
975 void
976 skAppPrintAbortMsg(
977     const char         *func_name,
978     const char         *file_name,
979     int                 line_number);
980 
981 
982 /**
983  *    Use skAbortBadCase(case_expr) to call this function.
984  *
985  *    skAbortBadCase() is a macro defined in silk.h that calls this
986  *    function with the current function name (if the compiler
987  *    supports it), filename, line number macros, the value of
988  *    'case_expr' as an int64_t and the stringification of
989  *    'case_expr'.  Once this function returns, the skAbortBadCase()
990  *    macro calls abort().
991  *
992  *    This function will call the function specified by
993  *    skAppSetFuncPrintFatalErr() to print an appropriate message
994  *    regarding switch(value_expr) getting an unexpected value.  This
995  *    function will return.  It is the caller's responsibility to call
996  *    abort().
997  */
998 void
999 skAppPrintBadCaseMsg(
1000     const char         *func_name,
1001     const char         *file_name,
1002     int                 line_number,
1003     int64_t             value,
1004     const char         *value_expr);
1005 
1006 
1007 #ifdef SK_HAVE_C99___FUNC__
1008 #define skAppPrintOutOfMemory(oom_string)                                  \
1009     skAppPrintOutOfMemoryMsgFunction(__func__, __FILE__, __LINE__, oom_string)
1010 #else
1011 #define skAppPrintOutOfMemory(oom_string)                                  \
1012     skAppPrintOutOfMemoryMsgFunction(NULL, __FILE__, __LINE__, oom_string)
1013 #endif
1014 
1015 
1016 /**
1017  *    Use skAppPrintOutOfMemory("object_name") to call this function.
1018  *
1019  *    skAppPrintOutOfMemory() is a macro defined above that calls this
1020  *    function with the current function name (if the compiler
1021  *    supports it), filename, line number macros, the value for
1022  *    'object_name'.
1023  *
1024  *    This function will call the function specified by
1025  *    skAppSetFuncPrintFatalErr() to print a message about being out
1026  *    of memory and unable to allocate 'object_name'.  'object_name'
1027  *    may be NULL.  This function will return.  It is the caller's
1028  *    responsibility to exit the program.
1029  */
1030 void
1031 skAppPrintOutOfMemoryMsgFunction(
1032     const char         *func_name,
1033     const char         *file_name,
1034     int                 line_number,
1035     const char         *object_name);
1036 
1037 
1038 /*
1039 **
1040 **    sku-options.c
1041 **
1042 */
1043 
1044 /*
1045  *    Values to specify for the 'has_arg' member of struct option when
1046  *    calling skOptionsRegister().
1047  */
1048 #define NO_ARG          0
1049 #define REQUIRED_ARG    1
1050 #define OPTIONAL_ARG    2
1051 
1052 
1053 /**
1054  *    Macro that converts the preceeding values to a string; used when
1055  *    printing usage (--help) information.  The paraemter to the macro
1056  *    is a struct option.
1057  */
1058 #define SK_OPTION_HAS_ARG(struct_option_st)             \
1059     (((struct_option_st).has_arg == REQUIRED_ARG)       \
1060      ? "Req Arg"                                        \
1061      : (((struct_option_st).has_arg == OPTIONAL_ARG)    \
1062         ? "Opt Arg"                                     \
1063         : (((struct_option_st).has_arg == NO_ARG)       \
1064            ? "No Arg"                                   \
1065            : "BAD 'has_arg' VALUE")))
1066 
1067 /**
1068  *    Callback data type for the options handler function.
1069  */
1070 typedef void   *clientData;
1071 
1072 /**
1073  *    Signature of the options handler callback function to pass to
1074  *    skOptionsRegister().  An options handler function is invoked by
1075  *    skOptionsParse() for each command line switch.
1076  *
1077  *    'cData' is user callback data that was supplied to
1078  *    'skOptionsRegister().  The 'optIndex' parameter is set to the
1079  *    value of the 'val' member of the struct option structure for the
1080  *    option.  'optArg' is the user's argument to the command line
1081  *    switch, or NULL if the user provided no switch.
1082  *
1083  *    The options handler should return 0 on success, or non-zero if
1084  *    there was a problem processing the option.  A non-zero return
1085  *    value causes options parsing to stop.
1086  */
1087 typedef int (*optHandler)(
1088     clientData  cData,
1089     int         optIndex,
1090     char       *optArg);
1091 
1092 /**
1093  *    Signature of callback functions invoked when the --help or
1094  *    --version switches are seen.
1095  */
1096 typedef void  (*usage_fn_t)(
1097     void);
1098 
1099 /**
1100  *    Register command line switches (options) with the global options
1101  *    handler.  The paramter 'options' specifies the switches to
1102  *    register as an array of:
1103  *
1104  *        struct option {
1105  *            char   *name;
1106  *            int     has_arg;
1107  *            int    *flag;
1108  *            int     val;
1109  *        };
1110  *
1111  *    where 'name' is the switch name (without the preceeding
1112  *    hyphens), 'has_arg' is one of NO_ARG, REQUIRED_ARG, OPTIONAL_ARG
1113  *    depending on whether the switch requires an argument, 'flag'
1114  *    should always be 0, and 'val' is a user-supplied value that gets
1115  *    passed as the 'optIndex' parameter of the options handler
1116  *    callback.
1117  *
1118  *    Processing of the 'options' array stops once a NULL value for
1119  *    'name' is found or once 'max_options' elements of the 'options'
1120  *    array have been processed, whichever occurs first.  A
1121  *    'max_options' value of 0 is equivalent to no limit.
1122  *
1123  *    The 'handler' function is the callback function to invoke when
1124  *    the option is seen on the command line.
1125  *
1126  *    The 'cData' parameter is a caller maintained pointer will be
1127  *    supplied to the handler function.  skOptionsRegisterCount() does
1128  *    not use this value.  It may be NULL.
1129  */
1130 int
1131 skOptionsRegisterCount(
1132     const struct option    *options,
1133     size_t                  max_options,
1134     optHandler              handler,
1135     clientData              cData);
1136 
1137 /**
1138  *    A wrapper for skOptionsRegisterCount() that calls that function
1139  *    with 0 for the 'max_options' parameter.
1140  */
1141 int
1142 skOptionsRegister(
1143     const struct option    *options,
1144     optHandler              handler,
1145     clientData              cData);
1146 
1147 /**
1148  *    Prepare the application to process options.
1149  *
1150  *    Application writers do not need to call this function as it is
1151  *    called by skAppRegister().
1152  */
1153 void
1154 skOptionsSetup(
1155     void);
1156 
1157 /**
1158  *    Free all memory associated with options processing.
1159  *
1160  *    Application writers do not need to call this function as it is
1161  *    called by skAppUnregister().
1162  */
1163 void
1164 skOptionsTeardown(
1165     void);
1166 
1167 /**
1168  *    Register the function 'help_fn' as the function the appliction
1169  *    will invoke when the user runs the application with the --help
1170  *    option.  If not specified, no output is produced by --help.
1171  *
1172  *    This function should print its results to the stdout.
1173  *
1174  *    It is recommended that this function print a brief summary of
1175  *    the purpose of the application, and then print every switch the
1176  *    function accepts.  The skAppStandardUsage() function can be used
1177  *    to print much of this information.
1178  */
1179 void
1180 skOptionsSetUsageCallback(
1181     usage_fn_t          help_fn);
1182 
1183 /**
1184  *    Register the function 'version_fn' as the function the
1185  *    application will invoke when the user runs the application with
1186  *    the --version option.  If not specified, information about the
1187  *    version of libsilk that the application is using will be
1188  *    printed.
1189  *
1190  *    This function should print its results to the stdout.
1191  *
1192  *    It is recommended that this function print information about how
1193  *    the application was compiled and the license(s) that the
1194  *    application is released under.
1195  */
1196 void
1197 skOptionsSetVersionCallback(
1198     usage_fn_t          version_fn);
1199 
1200 /**
1201  *    Print usage information about the default options that all
1202  *    applications support (namely --help and --version) to the named
1203  *    file handle.
1204  */
1205 void
1206 skOptionsDefaultUsage(
1207     FILE               *fh);
1208 
1209 
1210 #ifndef SK_SUPPORT_CONF_FILE
1211 #  define SK_SUPPORT_CONF_FILE 0
1212 #endif
1213 #if  SK_SUPPORT_CONF_FILE
1214 /**
1215  * optionsHandleConfFile:
1216  *
1217  *     Loads a configuration file.  The configuration file consists of
1218  *     a series of newline-terminated lines.  A line consisting of
1219  *     only whitespace, or whose first non-whitespace character is a
1220  *     `#' character is ignored.  All other lines should consist of a
1221  *     single option name followed by the option's value (if any),
1222  *     separated by whitespace.  Whitespace at the beginning and end
1223  *     of the line is ignored.
1224  *
1225  * BUGS:
1226  *     If you intersperse switches (options) and arguments, arguments
1227  *     before the configuration file is parsed will not be seen.
1228  *
1229  *  Return:
1230  *      0 if ok. -1 else
1231  */
1232 int
1233 optionsHandleConfFile(
1234     char               *filename);
1235 #endif  /* SK_SUPPORT_CONF_FILE */
1236 
1237 
1238 /**
1239  *  skOptionsParse:
1240  *      Adjust the global options array to allow for the help
1241  *      option. If help is selected by the user, call the stashed
1242  *      usageFunction.  Parse input options given a set of
1243  *      pre-registered options and their handlers.  For each
1244  *      legitimate option, call the handler.
1245  *  SideEffects:
1246  *      The individual handlers update whatever datastruture they wish
1247  *      to via the clientData argument to the handler.
1248  *  Return:
1249  *      optind which points at the first non-option argument passed if
1250  *      all is OK.  If not OK, the return -1 for error.
1251  */
1252 int
1253 skOptionsParse(
1254     int                 argc,
1255     char              **argv);
1256 
1257 
1258 /**
1259  *    Verify that the directory in 'dirname' exists, that the length
1260  *    is shorter than PATH_MAX, and that we have a full path to the
1261  *    directory.  If so, return 0; otherwise, print an error that the
1262  *    option named by 'option_name' was bad and return -1.
1263  */
1264 int
1265 skOptionsCheckDirectory(
1266     const char         *dirname,
1267     const char         *option_name);
1268 
1269 
1270 /**
1271  *    Return the length of the shortest unique prefix required to
1272  *    match the option whose complete name is 'option_name'.  Return
1273  *    -1 if option_name is NULL, empty, or if no options have the name
1274  *    'option_name'.
1275  */
1276 int
1277 skOptionsGetShortestPrefix(
1278     const char         *option_name);
1279 
1280 
1281 /**
1282  *    Registers a --temp-directory switch for the application.  Use
1283  *    skOptionsTempDirUsage() to print the usage for this switch.
1284  *
1285  *    The parameter 'var_location' must be specified.  The variable at
1286  *    that location will be set to the location the user provides in
1287  *    the --temp-directory switch.
1288  *
1289  *    The variable at 'var_location' is only modified if the user
1290  *    specifies the --temp-directory switch,
1291  */
1292 int
1293 skOptionsTempDirRegister(
1294     const char        **var_location);
1295 
1296 /**
1297  *    Print the usage information for the --temp-directory switch.
1298  */
1299 void
1300 skOptionsTempDirUsage(
1301     FILE               *fh);
1302 
1303 
1304 /**
1305  *    Registers an --ip-format switch for the application that allows
1306  *    the user to specify how IP addresses will be displayed.
1307  *
1308  *    The parameter 'var_location' must be specified.  The variable at
1309  *    that location will be set to the value the user specifies in the
1310  *    various switches.  This value will be one of the values defined
1311  *    in skipaddr_flags_t (see silk_types.h).
1312  *
1313  *    Use skOptionsIPFormatUsage() to print the usage for these
1314  *    switches.
1315  *
1316  *    The 'settings' parameter registers additional switches.
1317  *
1318  *    When SK_OPTION_IP_FORMAT_INTEGER_IPS is specified, an
1319  *    --integer-ips switch is also registered.
1320  *
1321  *    When SK_OPTION_IP_FORMAT_ZERO_PAD_IPS is specified, a
1322  *    --zero-pad-ips switch is also registered.
1323  *
1324  *    When SK_OPTION_IP_FORMAT_UNMAP_V6 is specified, unmap-v6
1325  *    (SKIPADDR_UNMAP_V6) is automatically added to the default IP
1326  *    format and to the result of parsing the --ip-format switch
1327  *    unless that format specifies map-v4 explicitly or the output
1328  *    format is decimal or hexadecimal.
1329  *
1330  *    The variable at 'var_location' is only modified if the user
1331  *    specifies the --ip-format switch.
1332  *
1333  *    If the SILK_IP_FORMAT environment variable is set, the value in
1334  *    'var_location' is initialized with the result of parsing that
1335  *    variable's value as if it was an argument to the --ip-format
1336  *    switch.
1337  *
1338  *    The 'settings' parameter was added in SiLK 3.15.0.
1339  */
1340 int
1341 skOptionsIPFormatRegister(
1342     uint32_t           *var_location,
1343     uint32_t            settings);
1344 
1345 /**
1346  *    Print the usage information for the switches registered by
1347  *    skOptionsIPFormatRegister() to the stream 'fp'.
1348  */
1349 void
1350 skOptionsIPFormatUsage(
1351     FILE               *fp);
1352 
1353 /**
1354  *    A bit to include in the 'settings' argument to
1355  *    skOptionsIPFormatRegister() that indicates an --integer-ips
1356  *    switch should be included.  Since SiLK 3.15.0.
1357  */
1358 #define SK_OPTION_IP_FORMAT_INTEGER_IPS     (1u << 0)
1359 
1360 /**
1361  *    A bit to include in the 'settings' argument to
1362  *    skOptionsIPFormatRegister() that indicates an --zero-pad-ips
1363  *    switch should be included.  Since SiLK 3.15.0.
1364  */
1365 #define SK_OPTION_IP_FORMAT_ZERO_PAD_IPS    (1u << 1)
1366 
1367 /**
1368  *    A bit to include in the 'settings' argument to
1369  *    skOptionsIPFormatRegister() that causes SKIPADDR_UNMAP_V6
1370  *    (unmap-v6) to be automatically added to the default IP format
1371  *    and to the result of parsing the --ip-format switch unless that
1372  *    format specifies map-v4 explicitly or the output format is
1373  *    decimal or hexadecimal.  Since SiLK 3.17.0.
1374  */
1375 #define SK_OPTION_IP_FORMAT_UNMAP_V6        (1u << 2)
1376 
1377 
1378 /**
1379  *    Registers a --timestamp-format switch for the application that
1380  *    allows the user to specify how timestamps will be displayed.
1381  *
1382  *    The parameter 'var_location' must be specified.  The variable at
1383  *    that location will be set to the value the user specifies in the
1384  *    various switches.  This value includes one or more of the values
1385  *    defined in sktimestamp_flags_t.
1386  *
1387  *    Use skOptionsIPFormatUsage() to print the usage for these
1388  *    switches.
1389  *
1390  *    The 'settings' changes the behavior of the --timestamp-format
1391  *    switch or registers additional switches.
1392  *
1393  *    When SK_OPTION_TIMESTAMP_NEVER_MSEC is specified, the parameter
1394  *    in 'var_location' always has the SKTIMESTAMP_NOMSEC bit set and
1395  *    --timestamp-format does not support 'no-msec'.
1396  *
1397  *    When SK_OPTION_TIMESTAMP_ALWAYS_MSEC is specified, the parameter
1398  *    in 'var_location' never has the SKTIMESTAMP_NOMSEC bit set and
1399  *    --timestamp-format does not support 'no-msec'.
1400  *
1401  *    When SK_OPTION_TIMESTAMP_OPTION_LEGACY is specified, a
1402  *    --legacy-timestamps switch is also registered.
1403  *
1404  *    When SK_OPTION_TIMESTAMP_OPTION_EPOCH is specified, an
1405  *    --epoch-timestamps switch is also registered.
1406  *
1407  *    When SK_OPTION_TIMESTAMP_OPTION_EPOCH_NAME is specified, the
1408  *    first string in the variable options is used as the name of a
1409  *    switch that has the same effect as '--epoch-timestamps'.
1410  *
1411  *    If the SILK_TIMESTAMP_FORMAT environment variable is set, the
1412  *    value in 'var_location' is initialized with the result of
1413  *    parsing that variable's value as if it was an argument to the
1414  *    --timestamp-format switch.
1415  *
1416  *    Since SiLK 3.11.0.
1417  */
1418 int
1419 skOptionsTimestampFormatRegister(
1420     uint32_t           *var_location,
1421     uint32_t            settings,
1422     ...);
1423 
1424 /**
1425  *    Print the usage information for the switches registered by
1426  *    skOptionsTimestampFormatRegister() to the stream 'fp'.
1427  *
1428  *    Since SiLK 3.11.0.
1429  */
1430 void
1431 skOptionsTimestampFormatUsage(
1432     FILE               *fp);
1433 
1434 
1435 /**
1436  *    A bit to include in the 'settings' argument to
1437  *    skOptionsTimestampFormatRegister() that indicates the
1438  *    application does not support fractional seconds.  The
1439  *    SKTIMESTAMP_NOMSEC flag is always set on the result, and
1440  *    "no-msec" is not allowed in --timestamp-format.
1441  */
1442 #define SK_OPTION_TIMESTAMP_NEVER_MSEC          (1u << 0)
1443 
1444 /**
1445  *    A bit to include in the 'settings' argument to
1446  *    skOptionsTimestampFormatRegister() that indicates the
1447  *    application only supports fractional seconds.  The "no-msec"
1448  *    is not allowed in --timestamp-format.
1449  */
1450 #define SK_OPTION_TIMESTAMP_ALWAYS_MSEC         (1u << 1)
1451 
1452 /**
1453  *    A bit to include in the 'settings' argument to
1454  *    skOptionsTimestampFormatRegister() that indicates an
1455  *    --epoch-time switch should be included.
1456  */
1457 #define SK_OPTION_TIMESTAMP_OPTION_EPOCH        (1u << 2)
1458 
1459 /**
1460  *    Similar to SK_OPTION_TIMESTAMP_OPTION_EPOCH except this
1461  *    indicates the name for the switch is included as one of the
1462  *    var-args values.  This takes precedence when
1463  *    SK_OPTION_TIMESTAMP_OPTION_EPOCH is also specified.
1464  */
1465 #define SK_OPTION_TIMESTAMP_OPTION_EPOCH_NAME   (1u << 3)
1466 
1467 /**
1468  *    A bit to include in the 'settings' argument to
1469  *    skOptionsTimestampFormatRegister() that indicates a
1470  *    --legacy-timestamps switch should be included.
1471  */
1472 #define SK_OPTION_TIMESTAMP_OPTION_LEGACY       (1u << 4)
1473 
1474 
1475 
1476 /*
1477 **
1478 **    skoptionsctx.c
1479 **
1480 */
1481 
1482 /**
1483  *    The sk_options_ctx_t structure provides a way to process
1484  *    non-switches command line arguments, such as input file names.
1485  *
1486  *    The sk_options_ctx_t also allows an application to register
1487  *    common options.
1488  *
1489  *    The normal usage pattern is:
1490  *
1491  *        skOptionsCtxCreate()
1492  *        skOptionsCtxOptionsRegister()
1493  *        skOptionsCtxOptionsParse()
1494  *        // use one of these two while() loops
1495  *        while (0==skOptionsCtxNextSilkFile()) {
1496  *            // process file
1497  *        }
1498  *        while (0==skOptionsCtxNextArgument()) {
1499  *            // process argument
1500  *        }
1501  *        skOptionsCtxDestroy()
1502  *
1503  *    TO DO: Should support for --output-path and --pager be added
1504  *    here as well?
1505  */
1506 typedef struct sk_options_ctx_st sk_options_ctx_t;
1507 
1508 /*
1509  *    The following are values to be ORed together to form the 'flags'
1510  *    argument to skOptionsCtxCreate().
1511  */
1512 #define SK_OPTIONS_CTX_PRINT_FILENAMES  (1u <<  0)
1513 #define SK_OPTIONS_CTX_COPY_INPUT       (1u <<  1)
1514 #define SK_OPTIONS_CTX_ALLOW_STDIN      (1u <<  2)
1515 #define SK_OPTIONS_CTX_XARGS            (1u <<  3)
1516 #define SK_OPTIONS_CTX_INPUT_SILK_FLOW  (1u <<  4)
1517 #define SK_OPTIONS_CTX_INPUT_BINARY     (1u <<  5)
1518 #define SK_OPTIONS_CTX_INPUT_PIPE       (1u << 30)
1519 #define SK_OPTIONS_CTX_SWITCHES_ONLY    (1u << 31)
1520 
1521 
1522 /**
1523  *    When the --copy-input switch has been used, this function will
1524  *    close the copy input destination.  Return 0 if the --copy-input
1525  *    switch was not used, or the status of closing the stream.
1526  */
1527 int
1528 skOptionsCtxCopyStreamClose(
1529     sk_options_ctx_t   *arg_ctx,
1530     sk_msg_fn_t         err_fn);
1531 
1532 /**
1533  *    When the --copy-input switch has been used, this function will
1534  *    return 1.  Otherwise, the function will return 0.
1535  */
1536 int
1537 skOptionsCtxCopyStreamIsActive(
1538     const sk_options_ctx_t *arg_ctx);
1539 
1540 /**
1541  *    When the --copy-input switch has been used, this function will
1542  *    return 1 if the stream is bound to the standard output.  Return
1543  *    1 if the --copy-input stream is not used or is not bound to
1544  *    stdout.
1545  */
1546 int
1547 skOptionsCtxCopyStreamIsStdout(
1548     const sk_options_ctx_t *arg_ctx);
1549 
1550 /**
1551  *    Return the number of unprocessed arguments specified on the
1552  *    command line.
1553  */
1554 int
1555 skOptionsCtxCountArgs(
1556     const sk_options_ctx_t *arg_ctx);
1557 
1558 /**
1559  *    Create the options context object.  Return 0 on success or
1560  *    non-zero on allocation error or for inconsistent 'flags' values.
1561  *
1562  *    'flags' is an OR of:
1563  *
1564  *    SK_OPTIONS_CTX_PRINT_FILENAMES -- Cause a --print-filenames
1565  *    switch to be registered and, when the switch is specified, have
1566  *    skOptionsCtxNextSilkFile() print the filenames as the files are
1567  *    opened.
1568  *
1569  *    SK_OPTIONS_CTX_COPY_INPUT -- Cause a --copy-input switch to be
1570  *    registered and, when the switch is specified, have
1571  *    skOptionsCtxNextSilkFile() copy their records to the named file.
1572  *
1573  *    SK_OPTIONS_CTX_ALLOW_STDIN -- Have the application default to
1574  *    reading from the standard input when no other input is
1575  *    specified.
1576  *
1577  *    SK_OPTIONS_CTX_XARGS -- Cause a --xargs switch to be registered
1578  *    and, when the switch is specified, read the names of the input
1579  *    files from the named stream (or from the standard input when no
1580  *    argument is give to the switch).
1581  *
1582  *    SK_OPTIONS_CTX_INPUT_SILK_FLOW -- Whether the input to the
1583  *    application is SiLK Flow records.  When set, prevents the
1584  *    application from reading from standard input when standard input
1585  *    is connected to a terminal.  Implies SK_OPTIONS_CTX_INPUT_BINARY
1586  *
1587  *    SK_OPTIONS_CTX_INPUT_BINARY -- Whether the input to the
1588  *    application is binary.  When set, prevents the application from
1589  *    reading from standard input when standard input is connected to
1590  *    a terminal.
1591  *
1592  *    SK_OPTIONS_CTX_INPUT_PIPE -- Cause an --input-pipe switch to be
1593  *    registered and, when the switch is specified, read input from
1594  *    the file, stream, or pipe.
1595  *
1596  *    SK_OPTIONS_CTX_SWITCHES_ONLY -- Cause the application to
1597  *    complain when any non-switched argument appears on the command
1598  *    line.
1599  */
1600 int
1601 skOptionsCtxCreate(
1602     sk_options_ctx_t  **arg_ctx,
1603     unsigned int        flags);
1604 
1605 /**
1606  *    Destroy the options context object.  If the copy-input stream
1607  *    has not been closed yet, this function closes it.  Returns the
1608  *    status of closing the copy-input stream, or 0.  Does nothing and
1609  *    returns 0 if 'arg_ctx' or the location it points to is NULL.
1610  */
1611 int
1612 skOptionsCtxDestroy(
1613     sk_options_ctx_t  **arg_ctx);
1614 
1615 /**
1616  *    When --print-filenames has been specified, return the file
1617  *    handle to which the file names are being printed.  If
1618  *    --print-filenames has not been specified, this function returns
1619  *    NULL.
1620  */
1621 FILE *
1622 skOptionsCtxGetPrintFilenames(
1623     const sk_options_ctx_t *arg_ctx);
1624 
1625 /**
1626  *    Set the value in 'arg' to point to the next input.  Return 0 if
1627  *    there is more input, 1 if there is no more input, or -1 when
1628  *    getting input from --xargs and there is a read error.  The
1629  *    caller should not modify the value in 'arg'; calling this
1630  *    function may invalidate any previous 'arg' value.
1631  *
1632  *    Depending on the value of 'flags' when the context was created,
1633  *    the next argument may be (1)the value specified to the
1634  *    --input-pipe switch, (2)a name read from --xargs, (3)a file
1635  *    listed on the command line, (4)the value "-" for the standard
1636  *    input.
1637  */
1638 int
1639 skOptionsCtxNextArgument(
1640     sk_options_ctx_t   *arg_ctx,
1641     char              **arg);
1642 
1643 /**
1644  *    A wrapper for skOptionsCtxNextArgument() that treats the string
1645  *    as a file name and attempts to open it as a SiLK Flow file.
1646  *    Return 0 on success, 1 if no more files, or -1 on error.  When
1647  *    'err_fn' is specified, any error opening a file is reported
1648  *    using that function.
1649  *
1650  *    If the skOptionsCtxSetOpenCallback() function was used to set a
1651  *    callback function, that function will be called with the stream
1652  *    as an argument.  If the callback returns 0, the stream is
1653  *    returned to the caller.  If the callback returns 1, the stream
1654  *    is skipped.  If the callback returns -1, the processing of all
1655  *    input stops.
1656  *
1657  *    The function will print the name of the file if
1658  *    --print-filenames was specified.  Will set the SiLK flow records
1659  *    to be copied to the --copy-input stream.
1660  */
1661 int
1662 skOptionsCtxNextSilkFile(
1663     sk_options_ctx_t   *arg_ctx,
1664     skstream_t        **stream,
1665     sk_msg_fn_t         err_fn);
1666 
1667 typedef int (*sk_options_ctx_open_cb_t)(
1668     skstream_t *stream);
1669 
1670 
1671 /**
1672  *    Specify a callback for skOptionsCtxNextSilkFile().
1673  */
1674 void
1675 skOptionsCtxSetOpenCallback(
1676     sk_options_ctx_t           *arg_ctx,
1677     sk_options_ctx_open_cb_t    open_callback_fn);
1678 
1679 /**
1680  *    Call skOptionsParse() and arrange for any non-switched arguments
1681  *    to be handled by the options context.  Return 0 on success, or
1682  *    non-zero on options parsing error or if input files/streams are
1683  *    required and are not available.
1684  */
1685 int
1686 skOptionsCtxOptionsParse(
1687     sk_options_ctx_t   *arg_ctx,
1688     int                 argc,
1689     char              **argv);
1690 
1691 /**
1692  *    Depending on the value of 'flags' specified when the context was
1693  *    created, register options with the global options handler.
1694  */
1695 int
1696 skOptionsCtxOptionsRegister(
1697     const sk_options_ctx_t *arg_ctx);
1698 
1699 /**
1700  *    Print usage information according to flags specified when the
1701  *    context was created.
1702  */
1703 void
1704 skOptionsCtxOptionsUsage(
1705     const sk_options_ctx_t *arg_ctx,
1706     FILE                   *fh);
1707 
1708 /**
1709  *    Open the --copy-input stream and/or --xargs stream as
1710  *    appropriate.  If an error occurs, print the error using the
1711  *    'err_fn' if it in not NULL.
1712  */
1713 int
1714 skOptionsCtxOpenStreams(
1715     sk_options_ctx_t   *arg_ctx,
1716     sk_msg_fn_t         err_fn);
1717 
1718 
1719 /*
1720 **
1721 **    skqsort.c
1722 **
1723 */
1724 
1725 /**
1726  *    Perform a quicksort on the elements in 'buffer', where each
1727  *    element is 'element_size' octets and 'buffer' contains
1728  *    'number_elements' such elements.
1729  *
1730  *    The elements in 'buffer' will be sorted in assending order
1731  *    according to the comparison function 'cmp'.  'cmp' will be
1732  *    handed pointers to two elements in the buffer, and it must
1733  *    return a value less than, equal to, or greater than zero if the
1734  *    first element is less than, equal to, or greater than the
1735  *    second.
1736  */
1737 void
1738 skQSort(
1739     void               *buffer,
1740     size_t              number_elements,
1741     size_t              element_size,
1742     int               (*cmp)(const void *a, const void *b));
1743 
1744 /**
1745  *    Perform the same quicksort operation as skQSort().  This
1746  *    function takes a context object 'thunk' which the function
1747  *    passes as the third argument to the comparison function 'cmp'.
1748  */
1749 void
1750 skQSort_r(
1751     void               *buffer,
1752     size_t              number_elements,
1753     size_t              element_size,
1754     int               (*cmp)(const void *a, const void *b, void *thunk),
1755     void               *thunk);
1756 
1757 
1758 /*
1759 **
1760 **    skoptions-notes.c
1761 **
1762 */
1763 
1764 
1765 int
1766 skOptionsNotesRegister(
1767     int                *note_strip);
1768 
1769 void
1770 skOptionsNotesTeardown(
1771     void);
1772 
1773 void
1774 skOptionsNotesUsage(
1775     FILE               *fh);
1776 
1777 int
1778 skOptionsNotesAddToStream(
1779     skstream_t         *stream);
1780 
1781 
1782 
1783 /*
1784 **
1785 **    sku-times.c
1786 **
1787 */
1788 
1789 
1790 /**
1791  *    Flags that can be use to specify how a timestamp will be
1792  *    printed.
1793  */
1794 typedef enum {
1795     /** Do not include fractional seconds when printing the time */
1796     SKTIMESTAMP_NOMSEC   = (1u << 0),
1797     /** Print as MM/DD/YYYY HH:MM:SS[.sss] */
1798     SKTIMESTAMP_MMDDYYYY = (1u << 1),
1799     /** Print as seconds since the UNIX epoch */
1800     SKTIMESTAMP_EPOCH    = (1u << 2),
1801     /** Print as YYYY-MM-DD HH:MM:SS[.sss] */
1802     SKTIMESTAMP_ISO      = (1u << 3),
1803     /** Print the time as UTC (assuming TZ=0) */
1804     SKTIMESTAMP_UTC      = (1u << 4),
1805     /** Print the time in the local timezone */
1806     SKTIMESTAMP_LOCAL    = (1u << 5)
1807 } sktimestamp_flags_t;
1808 
1809 /**
1810  *    Fill 'outbuf' with an ASCII version of the time 't' and return a
1811  *    pointer to 'output'.  This function assumes that 'outbuf' is at
1812  *    least SKTIMESTAMP_STRLEN characters long.  SKTIMESTAMP_STRLEN is
1813  *    defined in silk_types.h.
1814  *
1815  *    By default, the timestamp will be in the form:
1816  *
1817  *        "YYYY/MM/DDTHH:MM:SS.sss"
1818  *
1819  *    where "sss" == milliseconds, the "T" is a literal 'T'.
1820  *
1821  *    The parameter 'timestamp_flags' can be used to change the
1822  *    printed time, where the flags are a bitwise OR of the
1823  *    sktimestamp_flags_t values.
1824  *
1825  *    The following fields for 'timestamp_flags' are mutually
1826  *    exclusive; if more than one is set, the time is printed in the
1827  *    default form (and the SKTIMESTAMP_NOMSEC bit is ignored):
1828  *
1829  *        SKTIMESTAMP_EPOCH prints the value as the number of seconds
1830  *        since the UNIX epoch.  The timezone bits are ignored.
1831  *
1832  *            "SSSSSSSSSS[.sss]"
1833  *
1834  *        SKTIMESTAMP_MMDDYYYY causes the time to be printed as:
1835  *
1836  *            "MM/DD/YYYY HH:MM:SS[.sss]"
1837  *
1838  *        SKTIMESTAMP_ISO causes the time to be printed as
1839  *
1840  *            "YYYY-MM-DD HH:MM:SS[.sss]"
1841  *
1842  *    The following bit operates independently of any other bits:
1843  *
1844  *        SKTIMESTAMP_NOMSEC suppresses the printing of the
1845  *        milliseconds.  The milliseconds value is dropped and the
1846  *        remaining value is NOT rounded.
1847  *
1848  *    The 'timestamp_flags' value can affect the timezone used when
1849  *    printing the time.  If neither (or both) of the following bits
1850  *    are set, the time is printed in UTC unless SiLK was configured
1851  *    with --enable-local-timezone, in which case the local timezone
1852  *    is used.
1853  *
1854  *        SKTIMESTAMP_UTC causes the value to be printed in UTC,
1855  *        regardless of whether SiLK was configured with the
1856  *        --enable-local-timezone switch.
1857  *
1858  *        SKTIMESTAMP_LOCAL causes the value to be printed in the
1859  *        local timezone, regardless of whether SiLK was configured
1860  *        with the --enable-local-timezone switch.
1861  */
1862 char *
1863 sktimestamp_r(
1864     char               *outbuf,
1865     sktime_t            t,
1866     unsigned int        timestamp_flags);
1867 
1868 
1869 /**
1870  *    Similar to sktimestamp_r(), except returns the value in a static
1871  *    buffer.
1872  */
1873 char *
1874 sktimestamp(
1875     sktime_t            t,
1876     unsigned int        timestamp_flags);
1877 
1878 
1879 /**
1880  *    Return the maximum day in a given month/year
1881  *
1882  *    NOTE:  Months are in the 1..12 range and NOT 0..11
1883  *
1884  */
1885 int
1886 skGetMaxDayInMonth(
1887     int                 yr,
1888     int                 mo);
1889 
1890 
1891 /**
1892  *    Return an sktime set to the current UTC time to millisecond
1893  *    precision.
1894  */
1895 sktime_t
1896 sktimeNow(
1897     void);
1898 
1899 
1900 /**
1901  *    Given a value containing seconds since the UNIX epoch (such as a
1902  *    time_t) and a millisecond count, return an sktime_t.  The second
1903  *    parameter can be any value containing milliseconds.  There is no
1904  *    restriction on the range of its value.
1905  */
1906 #define sktimeCreate(sktc_seconds, sktc_milliseconds)                   \
1907     ((sktime_t)(INT64_C(1000) * (sktc_seconds) + (sktc_milliseconds)))
1908 
1909 
1910 /**
1911  *    Given a pointer to a struct timeval, return an sktime_t
1912  */
1913 #define sktimeCreateFromTimeval(sktc_tv)                                \
1914     sktimeCreate((sktc_tv)->tv_sec, ((sktc_tv)->tv_usec / 1000))
1915 
1916 
1917 /**
1918  *    Given an sktime_t value, fill the locations referenced by
1919  *    'seconds' and 'milliseconds' with the number of seconds and
1920  *    milliseconds that the sktime_t value represents.
1921  */
1922 #define sktimeGetParts(sktgp_time, sktgp_seconds, sktgp_milliseconds)   \
1923     do {                                                                \
1924         imaxdiv_t sktgp_d = imaxdiv((sktgp_time), INT64_C(1000));       \
1925         *(sktgp_seconds) = sktgp_d.quot;                                \
1926         *(sktgp_milliseconds) = sktgp_d.rem;                            \
1927     } while (0)
1928 
1929 
1930 /**
1931  *    Given an sktime_t, return the number of seconds since the UNIX
1932  *    epoch as an integer.
1933  */
1934 #define sktimeGetSeconds(sktgs_time)            \
1935     ((sktgs_time) / INT64_C(1000))
1936 
1937 
1938 /**
1939  *    Given an sktime_t, return fractional seconds as an integer.
1940  */
1941 #define sktimeGetMilliseconds(sktgm_time)       \
1942     ((sktgm_time) % INT64_C(1000))
1943 
1944 
1945 /*
1946 **
1947 **    sku-bigsockbuf.c
1948 **
1949 */
1950 
1951 /**
1952  *    There is no portable way to determine the max send and receive
1953  *    buffers that can be set for a socket, so guess then decrement
1954  *    that guess by 2K until the call succeeds.  If n > 1MB then the
1955  *    decrement by .5MB instead.
1956  *
1957  *    Returns size or -1 for error
1958  */
1959 int
1960 skGrowSocketBuffer(
1961     int                 sock,
1962     int                 direction,
1963     int                 size);
1964 
1965 
1966 /*
1967 **
1968 **    sku-filesys.c
1969 **
1970 */
1971 
1972 /**
1973  *    Strip directory prefix from the file path fp.  Returns a pointer
1974  *    to a static string buffer.
1975  */
1976 char *
1977 skBasename(
1978     const char         *fp);
1979 
1980 
1981 /**
1982  *    Thread safe version of skBasename()
1983  */
1984 char *
1985 skBasename_r(
1986     char               *dest,
1987     const char         *src,
1988     size_t              dest_size);
1989 
1990 
1991 /**
1992  *    Strip file name suffix from the file path fp.  Returns a pointer
1993  *    to a static string buffer.
1994  */
1995 char *
1996 skDirname(
1997     const char         *fp);
1998 
1999 
2000 /**
2001  *    Thread safe version of skDirname()
2002  */
2003 char *
2004 skDirname_r(
2005     char               *dest,
2006     const char         *src,
2007     size_t              dest_size);
2008 
2009 
2010 /**
2011  *    Returns 1 if the FILE* fd is a tty, 0 otherwise
2012  */
2013 #define FILEIsATty(fd)          isatty(fileno(fd))
2014 
2015 
2016 /**
2017  *    Return 1 if 'path_name' exists and is a FIFO.
2018  *
2019  *    Return 0 and set errno if calling stat() on 'path_name' fails.
2020  *
2021  *    Return 0 when stat() succeeds but 'path_name' is not a FIFO.
2022  *
2023  *    See also skFileExists().
2024  */
2025 int
2026 isFIFO(
2027     const char         *path_name);
2028 
2029 
2030 /**
2031  *    Return 1 if 'path_name' exists and is a directory.
2032  *
2033  *    Return 0 and set errno if calling stat() on 'path_name' fails.
2034  *
2035  *    Return 0 when stat() succeeds but 'path_name' is not a
2036  *    directory.
2037  */
2038 int
2039 skDirExists(
2040     const char         *path_name);
2041 
2042 
2043 /**
2044  *    Return 1 if 'path_name' exists and is either a regular file or a
2045  *    FIFO.
2046  *
2047  *    Return 0 and set errno if calling stat() on 'path_name' fails.
2048  *
2049  *    Return 0 when stat() succeeds but 'path_name' is neither a
2050  *    regular file nor a FIFO.
2051  *
2052  *    See also skDirExists() and isFIFO().
2053  */
2054 int
2055 skFileExists(
2056     const char         *path_name);
2057 
2058 
2059 /**
2060  *    Return the size of 'path_name' if it exists.
2061  *
2062  *    Return 0 if 'path_name' exists and is an empty file.
2063  *
2064  *    Return 0 and set errno if calling stat() on 'path_name' fails.
2065  *
2066  *    See also skFileExists().
2067  */
2068 off_t
2069 skFileSize(
2070     const char         *path_name);
2071 
2072 
2073 /**
2074  *    Perform a locking operation on the opened file represented by
2075  *    the file descriptor 'fd'.  'type' is the type of lock, it should
2076  *    be one of F_RDLCK for a read lock, F_WRLCK for a write lock, or
2077  *    F_UNLCK to unlock a previously locked file.  'cmd' should be one
2078  *    of F_SETLKW to wait indefinitely for a lock, or F_SETLK to
2079  *    return immediately.  Return 0 if successful, -1 otherwise.  Use
2080  *    errno to determine the error.
2081  */
2082 int
2083 skFileSetLock(
2084     int                 fd,
2085     short               type,
2086     int                 cmd);
2087 
2088 
2089 /**
2090  *    Find the given file 'base_name' in one of several places:
2091  *
2092  *    -- If 'base_name' begins with a slash (/), copy it to 'buf'.
2093  *    -- See if the environment variable named by the cpp macro
2094  *       ENV_SILK_PATH (normally SILK_PATH) is defined.  If so, check
2095  *       for the file in:
2096  *         * $SILK_PATH/share/silk/file_name
2097  *         * $SILK_PATH/share/file_name
2098  *         * $SILK_PATH/file_name (for historical resaons)
2099  *    -- Take the full path to the application (/yadda/yadda/bin/app),
2100  *       lop off the app's immediate parent directory---which leaves
2101  *       /yadda/yadda---and check for the file in the:
2102  *         * "/share/silk" subdir (/yadda/yadda/share/silk/file_name)
2103  *         * "/share" subdir (/yadda/yadda/share/file_name)
2104  *
2105  *    If found---and if the total path is less than 'bufsize-1'
2106  *    characters---fills 'buf' with a full path to the file and
2107  *    returns a pointer to 'buf'.
2108  *
2109  *    If not found or if 'buf' is too small to hold the full path;
2110  *    returns NULL and leaves 'buf' in an unknown state.
2111  */
2112 char *
2113 skFindFile(
2114     const char         *base_name,
2115     char               *buf,
2116     size_t              bufsize,
2117     int                 verbose);
2118 
2119 
2120 /**
2121  *    Attempt to find the named plug-in, 'dlPath', in one of several
2122  *    places.  If the function searches and finds the plug-in, it
2123  *    copies that location to the character array 'path'--whose
2124  *    caller-allocated size if 'path_len'---and returns 'path';
2125  *    otherwise return NULL.  This routine checks:
2126  *
2127  *    -- If 'dlPath' contains a slash, assume the path to plug-in is
2128  *       correct and return NULL.
2129  *    -- See if the environment variable named by the cpp macro
2130  *       ENV_SILK_PATH (normally SILK_PATH) is defined.  If so, check
2131  *       for the plug-in in the subdirectories of $SILK_PATH specified
2132  *       in the SILK_SUBDIR_PLUGINS macro, namely:
2133  *         * $SILK_PATH/lib/silk/dlPath
2134  *         * $SILK_PATH/share/lib/dlPath
2135  *         * $SILK_PATH/lib/dlPath
2136  *    -- Take the full path to the application "/yadda/yadda/bin/app",
2137  *       lop off the app's immediate parent directory--which leaves
2138  *       "/yadda/yadda", and check the SILK_SUBDIR_PLUGINS
2139  *       subdirectories:
2140  *         * "/lib/silk" subdir (/yadda/yadda/lib/silk/dlPath)
2141  *         * "/share/lib" subdir (/yadda/yadda/share/lib/dlPath)
2142  *         * "/lib" subdir (/yadda/yadda/lib/dlPath)
2143  *
2144  *    If 'verbose_prefix' is not NULL, the function uses
2145  *    skAppPrintErr() to print every pathname it checks, prefixing the
2146  *    pathname with the string in 'verbose_prefix'.
2147  *
2148  *    Return NULL if 'dlPath' was not found of if the search was not
2149  *    performed; otherwise return a char* which is the buffer passed
2150  *    into the subroutine.
2151  */
2152 char *
2153 skFindPluginPath(
2154     const char         *dlPath,
2155     char               *path,
2156     size_t              path_len,
2157     const char         *verbose_prefix);
2158 
2159 
2160 /**
2161  *    Return values for the skFileptrOpen() function.  To get an error
2162  *    message for these values, pass the value to the
2163  *    skFileptrStrerror() function.
2164  */
2165 typedef enum sk_fileptr_status_en {
2166     SK_FILEPTR_OK = 0,
2167     SK_FILEPTR_PAGER_IGNORED = 1,
2168     SK_FILEPTR_ERR_ERRNO = -1,
2169     SK_FILEPTR_ERR_POPEN = -2,
2170     SK_FILEPTR_ERR_WRITE_STDIN = -3,
2171     SK_FILEPTR_ERR_READ_STDOUT = -4,
2172     SK_FILEPTR_ERR_READ_STDERR = -5,
2173     SK_FILEPTR_ERR_TOO_LONG = -6,
2174     SK_FILEPTR_ERR_INVALID = -7
2175 } sk_fileptr_status_t;
2176 
2177 
2178 /**
2179  *    Values for the 'of_file_type' member of the sk_fileptr_t
2180  *    structure.
2181  */
2182 typedef enum sk_fileptr_type_en {
2183     SK_FILEPTR_IS_STDIO, SK_FILEPTR_IS_FILE, SK_FILEPTR_IS_PROCESS
2184 } sk_fileptr_type_t;
2185 
2186 
2187 /**
2188  *    Structure to pass to skFileptrOpen() and skFileptrClose().  For
2189  *    skFileptrOpen(), the 'of_name' member must be non-NULL.  For
2190  *    skFileptrClose(), the 'of_fp' parameter should be non-NULL.
2191  */
2192 typedef struct sk_fileptr_st {
2193     const char         *of_name;
2194     FILE               *of_fp;
2195     sk_fileptr_type_t of_type;
2196 } sk_fileptr_t;
2197 
2198 /**
2199  *    Open a file, process, or stream for reading, writing, or
2200  *    appending.  How the file or stream is opened is determined by
2201  *    the 'io_mode' parameter, which should be one of SK_IO_READ,
2202  *    SK_IO_WRITE, or SK_IO_APPEND.
2203  *
2204  *    The 'of_name' member of the 'file' structure must be non-NULL;
2205  *    if it is NULL, SK_FILEPTR_ERR_INVALID is returned.
2206  *
2207  *    When 'of_name' is '-' or the strings 'stdin', 'stdout', or
2208  *    'stderr', the 'of_fp' member is set to the appropriate standard
2209  *    stream and the 'of_type' value is set to SK_FILEPTR_IS_STDIO.
2210  *
2211  *    When 'of_name' ends in '.gz', skFileptrOpen() attempts to invoke
2212  *    the 'gzip' command to read from or write to the file.  On
2213  *    success, the 'of_fp' member is set the to process file handle
2214  *    and the 'of_type' member is set to SK_FILEPTR_IS_PROCESS.
2215  *
2216  *    Otherwise, the 'of_name' value is opened as a standard file,
2217  *    'of_fp' is set the file handle, and the 'of_type' member is set
2218  *    to SK_FILEPTR_IS_FILE.
2219  *
2220  *    The return status of this function is one of the values in the
2221  *    sk_fileptr_status_t enumeration.
2222  */
2223 int
2224 skFileptrOpen(
2225     sk_fileptr_t       *file,
2226     skstream_mode_t     io_mode);
2227 
2228 /**
2229  *    Close the file, process, or stream specified in the 'of_fp'
2230  *    member of 'file'.  If 'of_fp' in NULL, return 0.  When 'of_fp'
2231  *    represents a standard output or standard error, the stream is
2232  *    flushed but not closed.
2233  *
2234  *    If 'err_fn' is non-NULL, it is used to report any errors in
2235  *    closing the file or process.
2236  */
2237 int
2238 skFileptrClose(
2239     sk_fileptr_t       *file,
2240     sk_msg_fn_t         err_fn);
2241 
2242 /**
2243  *    Return a textual description of the return status from
2244  *    skFileptrOpen().  The parameter 'errnum' should be one of the
2245  *    values in the sk_fileptr_status_t enumeration.
2246  */
2247 const char *
2248 skFileptrStrerror(
2249     int                 errnum);
2250 
2251 /**
2252  *    Set 'file' to the pager process when it is appropriate to do so.
2253  *
2254  *    The function returns SK_FILEPTR_PAGER_IGNORED when the 'of_fp'
2255  *    member of 'file' has a non-NULL value other than stdout, or when
2256  *    the standard output is not a terminal.
2257  *
2258  *    If 'pager' is NULL, the function attempts to find the pager from
2259  *    the environment by checking the environment variables SILK_PAGER
2260  *    and PAGER.  When the function determines that pager is NULL or
2261  *    the empty string, the function returns
2262  *    SK_FILEPTR_PAGER_IGNORED.
2263  *
2264  *    Finally, the function will attempt to open the pager.  If that
2265  *    fails, SK_FILEPTR_ERR_POPEN is returned.
2266  *
2267  *    If opening the pager succeeds, the members of 'file' are updated
2268  *    to hold the name of the pager and the FILE* for the pager
2269  *    process.
2270  *
2271  *    Use skFileptrClose() to close the pager.
2272  */
2273 int
2274 skFileptrOpenPager(
2275     sk_fileptr_t       *file,
2276     const char         *pager);
2277 
2278 
2279 /**
2280  *    DEPRECATED.  Replaced by skFileptrOpen().
2281  *
2282  *    Removed in SiLK 4.0.0.
2283  *
2284  *    Open 'file' as a pipe or as a regular file depending on whether
2285  *    it is a gzipped file or not.  A file is considered gzipped if
2286  *    its name contains the string ".gz\0" or ".gz.".
2287  *
2288  *    The name of the file is given in the C-string 'file'; 'mode'
2289  *    determines whether to open 'file' for reading (mode==0) or
2290  *    writing (mode==1).
2291  *
2292  *    The file pointer to the newly opened file is put into 'fp'.  The
2293  *    value pointed to by 'isPipe' is set to 0 if fopen() was used to
2294  *    open the file, or 1 if popen() was used.  The caller is
2295  *    responsible for calling fclose() or pclose() as appropriate.
2296  *
2297  *    The function returns 0 on success, or 1 on failure.
2298  */
2299 int
2300 skOpenFile(
2301     const char         *FName,
2302     int                 mode,
2303     FILE              **fp,
2304     int                *isPipe)
2305     SK_GCC_DEPRECATED;
2306 
2307 
2308 /**
2309  *    Make the complete directory path to 'directory', including
2310  *    parent(s) if required.  A return status of 0 indicates that
2311  *    'directory' exists---either this function created it or it
2312  *    existed prior to invoking this function.
2313  *
2314  *    A return status of 1 indicates a failure to create 'directory'
2315  *    or its parent(s), or that 'directory' already exists and it is
2316  *    not a directory.  On failure, any parent directories that were
2317  *    created by this function will not be removed.  This function
2318  *    sets errno on failure.
2319  */
2320 int
2321 skMakeDir(
2322     const char         *directory);
2323 
2324 
2325 /**
2326  *    Copy the file 'src_path' to 'dest_path'.  'dest_path' may be a
2327  *    file or a directory.  Overwrite the destination file if it
2328  *    already exists.  Return 0 on success, or errno on failure.
2329  */
2330 int
2331 skCopyFile(
2332     const char         *src_path,
2333     const char         *dest_path);
2334 
2335 
2336 /**
2337  *    Move the file at 'src_path' to 'dest_path'.  'dest_path' may be
2338  *    a file or a directory.  Overwrite the destination file if it
2339  *    already exists.  Return 0 on success, or errno on failure.
2340  */
2341 int
2342 skMoveFile(
2343     const char         *src_path,
2344     const char         *dest_path);
2345 
2346 
2347 /**
2348  *    Return the location of the temporary directory.
2349  *
2350  *    If a temporary directory is not specified or if the specified
2351  *    location does not exist, return NULL.  In addition, if 'err_fn'
2352  *    is specified, print an error message using that function.
2353  *
2354  *    If 'user_temp_dir' is specified, that location is used.
2355  *    Otherwise, locations specified by the SILK_TMPDIR and TMPDIR
2356  *    environment variables are checked, in that order.  Finally, the
2357  *    DEFAULT_TEMP_DIR is used if defined.
2358  */
2359 const char *
2360 skTempDir(
2361     const char         *user_temp_dir,
2362     sk_msg_fn_t         err_fn);
2363 
2364 
2365 /**
2366  *    DEPRECATED.  Replaced by skFileptrOpenPager().
2367  *
2368  *    Removed in SiLK 4.0.0.
2369  *
2370  *    Attempts to redirect the '*output_stream' to the paging program
2371  *    '*pager.'
2372  *
2373  *    If output changed so that it goes to a pager, 1 is returned; if
2374  *    the output is unchanged, 0 is returned.  If an error occurred in
2375  *    invoking the pager, -1 is returned.
2376  *
2377  *    If the '*output_stream' is NULL, it is assumed that the output
2378  *    was being sent to stdout.  If the '*output_stream' is not stdout
2379  *    or not a terminal, no paging is preformed and 0 is returned.
2380  *
2381  *    If '*pager' is NULL, the environment variable SILK_PAGER is
2382  *    checked for the paging program; if that is NULL, the PAGER
2383  *    environment variable is checked.  If that is also NULL, no
2384  *    paging is performed and 0 is returned.
2385  *
2386  *    If there was a problem invoking the pager, an error is printed
2387  *    and -1 is returned.
2388  *
2389  *    If the pager was started, the *output_stream value is set to the
2390  *    pager stream, and *pager is set to the name of the pager (if the
2391  *    user's environment was consulted), and 1 is returned.  To close
2392  *    the pager, use the skClosePager() function, or call pclose() on
2393  *    the *output_stream.
2394  *
2395  *    Due to the race condition of checking the status of the child
2396  *    process, it is possible for 1 to be returned even though the
2397  *    pager has exited.  In this case the tool's output will be lost.
2398  */
2399 int
2400 skOpenPagerWhenStdoutTty(
2401     FILE              **output_stream,
2402     char              **pager)
2403     SK_GCC_DEPRECATED;
2404 
2405 
2406 /**
2407  *    DEPRECATED.
2408  *
2409  *    Removed in SiLK 4.0.0.
2410  *
2411  *    If skOpenPagerWhenStdoutTty() returns a positive value, use this
2412  *    function to close the pager stream.  Prints an error if the
2413  *    close fails.
2414  */
2415 void
2416 skClosePager(
2417     FILE               *output_stream,
2418     const char         *pager)
2419     SK_GCC_DEPRECATED;
2420 
2421 
2422 /**
2423  *    Fill 'out_buffer' with the next non-blank, non-comment line read
2424  *    from 'stream'.  The caller should supply 'out_buffer' and pass
2425  *    its size in the 'buf_size' variable.  The return value is the
2426  *    number of lines that were read to get a valid line.
2427  *
2428  *    The final newline will be removed; if comment_start is provided,
2429  *    it will also be removed from line.
2430  *
2431  *    If a line longer than buf_size is found, out_buffer will be set
2432  *    to the empty string but the return value will be positive.
2433  *
2434  *    At end of file, 0 is returned and out_buffer is the empty
2435  *    string.
2436  */
2437 int
2438 skGetLine(
2439     char               *out_buffer,
2440     size_t              buf_size,
2441     FILE               *stream,
2442     const char         *comment_start);
2443 
2444 
2445 /**
2446  *  Reads 'count' bytes from the file descriptor 'fd' into the buffer
2447  *  'buf'.  The return value is the number of bytes actually read.
2448  *  Will return less than 'count' if an end-of-file situation is
2449  *  reached.  In an error condition, returns -1.  More information
2450  *  about the error can be derived from 'errno'.
2451  */
2452 ssize_t
2453 skreadn(
2454     int                 fd,
2455     void               *buf,
2456     size_t              count);
2457 
2458 /**
2459  *  Writes 'count' bytes from the buffer 'buf' to the file descriptor
2460  *  'fd'.  The return value is the number of bytes actually written.
2461  *  If the underlying `write' call returns zero, this function will
2462  *  return a value less than 'count'.  It is unknown if this actually
2463  *  occurs in any real-life conditions.  In an error condition,
2464  *  returns -1.  More information about the error can be derived from
2465  *  'errno'.
2466  */
2467 ssize_t
2468 skwriten(
2469     int                 fd,
2470     const void         *buf,
2471     size_t              count);
2472 
2473 
2474 /**
2475  *    Verify that the command string specified in 'cmd_string'
2476  *    contains only the conversions specified in 'conversion_chars'.
2477  *
2478  *    Specifically, search 'cmd_string' for the character '%', and
2479  *    verify that the character that follows '%' is either another '%'
2480  *    or one of the characters specified in 'conversion_chars'.  In
2481  *    addition, verify that the command does not contain a single '%'
2482  *    at the end of the string.
2483  *
2484  *    If 'cmd_string' is the empty string or does not contain any
2485  *    invalid conversions, return 0.
2486  *
2487  *    If 'cmd_string' is not valid, return the offset into
2488  *    'cmd_string' of the invalid character that followed '%'.
2489  */
2490 size_t
2491 skSubcommandStringCheck(
2492     const char         *cmd_string,
2493     const char         *conversion_chars);
2494 
2495 /**
2496  *    Allocate and return a new string that contains 'cmd_string' with
2497  *    any %-conversions expanded.
2498  *
2499  *    Specifically, create a new string and copy 'cmd_string' into it,
2500  *    where the string "%%" is replaced with a single '%' and where
2501  *    any other occurence of '%' and a character by is replaced by
2502  *    finding the offset of that character in 'conversion_chars' and
2503  *    using that offset as the index into the variable argument list
2504  *    to get the string to use in place of that conversion.  If the
2505  *    conversion character is not present in 'conversion_chars' or is
2506  *    the '\0' character, return NULL.
2507  *
2508  *    Return the new string.  Return NULL on an allocation error or an
2509  *    invalid conversion.  The caller is responsible for freeing the
2510  *    returned string.
2511  */
2512 char *
2513 skSubcommandStringFill(
2514     const char         *cmd_string,
2515     const char         *conversion_chars,
2516     ...);
2517 
2518 /**
2519  *    Execute 'cmd_array[0]' in a subprocess with the remaining
2520  *    members of 'cmd_array[]' as the arguments to the program.  The
2521  *    final member of cmd_array[] must be NULL.  The value in
2522  *    'cmd_array[0]' should be the full path to the program since this
2523  *    function does not search for the command in PATH.
2524  *
2525  *    See also skSubcommandExecuteShell().
2526  *
2527  *    This function calls fork() twice to ensure that the parent
2528  *    process does not wait for the subprocess to terminate.
2529  *
2530  *    Return the process id of the first child if the parent
2531  *    successfully forks and waits for that child.
2532  *
2533  *    Return -1 if there is an allocate error or if the parent is
2534  *    unable to fork().  Return -2 if the wait() call fails.  In all
2535  *    cases, errno is set.
2536  *
2537  *    The child and grandchild only call a non-reentrant function on
2538  *    error: when either the child process is unable to fork() or
2539  *    grandchild process encounters an error in the execve() call.  In
2540  *    these cases, an error is reported by calling skAppPrintErr().
2541  */
2542 long int
2543 skSubcommandExecute(
2544     char * const        cmd_array[]);
2545 
2546 /**
2547  *    Execute 'cmd_string' in a subprocess.
2548  *
2549  *    This is identical to skSubcommandExecute() execept the command
2550  *    'cmd_string' is invoked as the argument to "/bin/sh -c" in the
2551  *    grandchild process.
2552  */
2553 long int
2554 skSubcommandExecuteShell(
2555     const char         *cmd_string);
2556 
2557 
2558 
2559 /*
2560 **
2561 **    sku-ips.c
2562 **
2563 */
2564 
2565 
2566 /**
2567  *    Return the log2 of 'value' as an integer.  This is the position
2568  *    of the most significant bit in 'value', assuming the MSB is
2569  *    number 63 and the LSB is 0.  Returns -1 if 'value' is 0.
2570  */
2571 int
2572 skIntegerLog2(
2573     uint64_t            value);
2574 
2575 
2576 /**
2577  *    Compute the largest CIDR block that begins at 'start_addr' and
2578  *    contains no IPs larger than 'end_addr', and return the CIDR
2579  *    designation for that block.  For example:
2580  *
2581  *        skCIDRComputePrefix(10.0.0.2, 10.0.0.5, NULL) => 31
2582  *
2583  *    When 'new_start_addr' is not NULL, it's value is set to 0 if the
2584  *    CIDR block completely contains all IPs between 'start_addr' and
2585  *    'end_addr' inclusive.  Otherwise, its value is set to the IP that
2586  *    follows that block covered by the CIDR block.
2587  *
2588  *    Returns -1 if 'end_addr' < 'start_addr'.
2589  *
2590  *    This function allows one to print all CIDR blocks from 'start'
2591  *    to 'end' using:
2592  *
2593  *        do {
2594  *            cidr_prefix = skCIDRComputePrefix(&start, &end, &new_start);
2595  *            printf("%s/%d", skipaddrString(buf, start, 0), cidr_prefix);
2596  *            skipaddrCopy(&start, &new_start);
2597  *        } while (!skipaddrIsZero(&start));
2598  *
2599  *    Continuing the above example:
2600  *
2601  *        skCIDRComputePrefix(10.0.0.2, 10.0.0.5, &new) => 31, new => 10.0.0.4
2602  *        skCIDRComputePrefix(10.0.0.4, 10.0.0.5, &new) => 31, new => 0
2603  *
2604  *    which means that the IP range 10.0.0.2--10.0.0.5 is contained by
2605  *    the two CIDR blocks:
2606  *
2607  *        10.0.0.2/31
2608  *        10.0.0.4/31
2609  */
2610 int
2611 skCIDRComputePrefix(
2612     const skipaddr_t   *start_addr,
2613     const skipaddr_t   *end_addr,
2614     skipaddr_t         *new_start_addr);
2615 
2616 /**
2617  *    Older interface to skCIDRComputePrefix() that uses integers for
2618  *    the IP addresses.
2619  */
2620 int
2621 skComputeCIDR(
2622     uint32_t            start_ip,
2623     uint32_t            end_ip,
2624     uint32_t           *new_start_ip);
2625 
2626 
2627 /**
2628  *    Compute the minimum and maximum IPs that are represented by
2629  *    'ipaddr' when the CIDR mask 'cidr' is applied to it.  Return -1
2630  *    if 'cidr' is too large for the type of IP address.
2631  *
2632  *    Either of the output values, 'min_ip' or 'max_ip', may point to
2633  *    the same memory as 'ipaddr'.
2634  *
2635  *    See also skCIDRComputeEnd().
2636  */
2637 int
2638 skCIDR2IPRange(
2639     const skipaddr_t   *ipaddr,
2640     uint32_t            cidr,
2641     skipaddr_t         *min_ip,
2642     skipaddr_t         *max_ip);
2643 
2644 
2645 /**
2646  *    Compute the minimum IP that is covered by the CIDR block
2647  *    'ipaddr'/'cidr' and fill 'min_ip' with that value.  Return -1 if
2648  *    'cidr' is too marge for the type of IP address.
2649  *
2650  *    'min_ip' may point to the same memory as 'ipaddr'.
2651  *
2652  *    See also skCIDR2IPRange().
2653  */
2654 int
2655 skCIDRComputeStart(
2656     const skipaddr_t   *ipaddr,
2657     uint32_t            cidr,
2658     skipaddr_t         *min_ip);
2659 
2660 
2661 /**
2662  *    Compute the maximum IP that is covered by the CIDR block
2663  *    'ipaddr'/'cidr' and fill 'max_ip' with that value.  Return -1 if
2664  *    'cidr' is too marge for the type of IP address.
2665  *
2666  *    'max_ip' may point to the same memory as 'ipaddr'.
2667  *
2668  *    See also skCIDR2IPRange().
2669  */
2670 int
2671 skCIDRComputeEnd(
2672     const skipaddr_t   *ipaddr,
2673     uint32_t            cidr,
2674     skipaddr_t         *max_ip);
2675 
2676 
2677 /**
2678  *    Parse the string 'policy_name' and set 'ipv6_policy' to the
2679  *    parsed value.  Return 0 on success.
2680  *
2681  *    If 'policy_name' is not a valid policy, return -1.  In addition,
2682  *    if 'option_name' is non-NULL, print an error message that the
2683  *    'policy_name' was invalid.
2684  */
2685 int
2686 skIPv6PolicyParse(
2687     sk_ipv6policy_t    *ipv6_policy,
2688     const char         *policy_name,
2689     const char         *option_name);
2690 
2691 
2692 /**
2693  *    Add an option that will allow the user to determine how IPv6
2694  *    flow records are handled.  This function will also check the
2695  *    environment variabled namd by SILK_IPV6_POLICY_ENVAR for a
2696  *    policy to follow.  After skOptionsParse() sucessfully returns, the
2697  *    variable pointed to by 'ipv6_policy' will contain the IPv6
2698  *    policy to follow.
2699  *
2700  *    Before calling this function, the caller should set the variable
2701  *    that ipv6_policy points at to the application's default IPv6
2702  *    policy.
2703  *
2704  *    If IPv6 support is not enabled, the ipv6_policy is set to ignore
2705  *    IPv6 flows, the environment is not checked, and no option is
2706  *    registered
2707  */
2708 int
2709 skIPv6PolicyOptionsRegister(
2710     sk_ipv6policy_t    *ipv6_policy);
2711 
2712 
2713 /**
2714  *    Print the help text for the --ipv6-policy switch to the named
2715  *    file handle.  Uses the default policy that was set when
2716  *    skIPv6PolicyOptionsRegister() was called.
2717  */
2718 void
2719 skIPv6PolicyUsage(
2720     FILE               *fh);
2721 
2722 
2723 /* typedef struct skIPWildcard_st skIPWildcard_t; // silk_types.h */
2724 struct skIPWildcard_st {
2725     /*
2726      *    m_blocks[] contains a bitmap for each octet of an IPv4
2727      *    address (IPv6:hexadectet).  If the bit is enabled, that
2728      *    value should be returned for that octet/hexadectet.
2729      *
2730      *    m_min[] and m_max[] are the minimum and maximum values in
2731      *    the bitmap for the octet/hexadectet.
2732      *
2733      *    num_blocks is 4 for an IPv4 address, 8 for an IPv6 address.
2734      *
2735      *    m_blocks[0], m_min[0], m_max[0] represent the values for the
2736      *    most significant octet/hexadectet.
2737      */
2738 #if !SK_ENABLE_IPV6
2739     uint32_t            m_blocks[4][256/32];
2740     uint16_t            m_min[4];
2741     uint16_t            m_max[4];
2742 #else
2743     uint32_t            m_blocks[8][65536/32];
2744     uint16_t            m_min[8];
2745     uint16_t            m_max[8];
2746 #endif
2747     uint8_t             num_blocks;
2748 };
2749 
2750 typedef struct skIPWildcardIterator_st {
2751     const skIPWildcard_t   *ipwild;
2752     uint16_t                i_block[8];
2753     unsigned                no_more_entries :1;
2754     unsigned                force_ipv6      :1;
2755     unsigned                force_ipv4      :1;
2756 } skIPWildcardIterator_t;
2757 
2758 
2759 #define _IPWILD_BLOCK_IS_SET(ipwild, block, val)                        \
2760     ((ipwild)->m_blocks[(block)][_BMAP_INDEX(val)] & _BMAP_OFFSET(val))
2761 
2762 #define _IPWILD_IPv4_IS_SET(ipwild, ipaddr)                             \
2763     (_IPWILD_BLOCK_IS_SET((ipwild), 0, 0xFF&(skipaddrGetV4(ipaddr) >> 24))&& \
2764      _IPWILD_BLOCK_IS_SET((ipwild), 1, 0xFF&(skipaddrGetV4(ipaddr) >> 16))&& \
2765      _IPWILD_BLOCK_IS_SET((ipwild), 2, 0xFF&(skipaddrGetV4(ipaddr) >>  8))&& \
2766      _IPWILD_BLOCK_IS_SET((ipwild), 3, 0xFF&(skipaddrGetV4(ipaddr))))
2767 
2768 
2769 /**
2770  *    Zero all values in the skIPWildcard_t 'ipwild'.
2771  */
2772 void
2773 skIPWildcardClear(
2774     skIPWildcard_t     *ipwild);
2775 
2776 
2777 
2778 #if !SK_ENABLE_IPV6
2779 #  define skIPWildcardIsV6(ipwild)   0
2780 #  define skIPWildcardCheckIp(ipwild, ipaddr) \
2781     _IPWILD_IPv4_IS_SET(ipwild, ipaddr)
2782 #else
2783 #  define skIPWildcardIsV6(ipwild) (8 == (ipwild)->num_blocks)
2784 /**
2785  *    Return 1 if 'ip' is represented in by 'ipwild'; 0 otherwise.
2786  */
2787 int
2788 skIPWildcardCheckIp(
2789     const skIPWildcard_t   *ipwild,
2790     const skipaddr_t       *ip);
2791 #endif
2792 
2793 
2794 /**
2795  *    Bind the iterator 'iter' to iterate over the entries in the
2796  *    skIPWildcard_t 'ipwild'.  Use skIPWildcardIteratorNext() or
2797  *    skIPWildcardIteratorNextCidr() to get the entries.
2798  *
2799  *    When iterating over the IPs, the addresses will be returned in
2800  *    the form in which they were specified when 'ipwild' was
2801  *    created---that is, as either IPv4 or as IPv6.  To force an
2802  *    IPWildcard of IPv4 addresses to be returned as IPv6 addresses
2803  *    (in the ::ffff:0:0/96 subnet), use skIPWildcardIteratorBindV6().
2804  *
2805  *    Return 0 unless 'ipwild' is NULL.
2806  */
2807 int
2808 skIPWildcardIteratorBind(
2809     skIPWildcardIterator_t *iter,
2810     const skIPWildcard_t   *ipwild);
2811 
2812 
2813 #if SK_ENABLE_IPV6
2814 /**
2815  *    Bind the iterator 'iter' to iterate over the entries in the
2816  *    skIPWildcard_t 'ipwild'.  Similar to skIPWildcardIteratorBind(),
2817  *    but instructs the iterator to return IPv6 addresses even when
2818  *    the 'ipwild' contains IPv4 addresses.  The IPv4 addresses are
2819  *    mapped into the ::ffff:0:0/96 subnet.
2820  */
2821 int
2822 skIPWildcardIteratorBindV6(
2823     skIPWildcardIterator_t *iter,
2824     const skIPWildcard_t   *ipwild);
2825 
2826 /**
2827  *    Bind the iterator 'iter' to iterate over the entries in the
2828  *    skIPWildcard_t 'ipwild'.  Similar to skIPWildcardIteratorBind(),
2829  *    but instructs the iterator to only visit IPv6 addresses within
2830  *    the ::ffff:0:0/96 subnet and return them as IPv4 addresses.
2831  *
2832  *    Since SiLK 3.9.0.
2833  */
2834 int
2835 skIPWildcardIteratorBindV4(
2836     skIPWildcardIterator_t *out_iter,
2837     const skIPWildcard_t   *ipwild);
2838 #else  /* SK_ENABLE_IPV6 */
2839 #define skIPWildcardIteratorBindV4 skIPWildcardIteratorBind
2840 #endif  /* SK_ENABLE_IPV6 */
2841 
2842 
2843 /**
2844  *    Fill 'out_ip' with the next IP address represented by the
2845  *    IPWildcard that is bound to the iterator 'iter'.  Return
2846  *    SK_ITERATOR_OK if 'out_ip' was filled with an IP address, or
2847  *    SK_ITERATOR_NO_MORE_ENTRIES otherwise.
2848  *
2849  *    This function can be intermingled with calls to
2850  *    skIPWildcardIteratorNextCidr(), which returns the CIDR blocks in
2851  *    the IPWildcard.
2852  */
2853 skIteratorStatus_t
2854 skIPWildcardIteratorNext(
2855     skIPWildcardIterator_t *iter,
2856     skipaddr_t             *out_ip);
2857 
2858 
2859 /**
2860  *    Fill 'out_min_ip' and 'out_prefix' with the next CIDR block
2861  *    (subnet) represented by the IPWildcard that is bound to the
2862  *    iterator 'iter'.  Return SK_ITERATOR_OK if 'out_min_ip' was
2863  *    filled with an IP address, or SK_ITERATOR_NO_MORE_ENTRIES
2864  *    otherwise.
2865  *
2866  *    This function can be intermingled with calls to
2867  *    skIPWildcardIteratorNext(), which returns the individual IPs in
2868  *    the IPWildcard.
2869  */
2870 skIteratorStatus_t
2871 skIPWildcardIteratorNextCidr(
2872     skIPWildcardIterator_t *iter,
2873     skipaddr_t             *out_min_ip,
2874     uint32_t               *out_prefix);
2875 
2876 
2877 /**
2878  *    Allow 'iter' to iterate again over the entries in the IPWildcard
2879  *    that is bound to it.
2880  */
2881 void
2882 skIPWildcardIteratorReset(
2883     skIPWildcardIterator_t *iter);
2884 
2885 
2886 /*
2887 **
2888 **    sku-string.c
2889 **
2890 */
2891 
2892 /**
2893  *    Fill 'outbuf' with a string representation of the IP address in
2894  *    'ip'.  The size of 'outbuf' must be at least SKIPADDR_STRLEN bytes
2895  *    in length.  The function returns a pointer to 'outbuf'.
2896  *
2897  *    The form of the string will depend on the values in 'ip_flags',
2898  *    which should contain values from the skipaddr_flags_t
2899  *    enumeration.  Both skipaddr_flags_t and SKIPADDR_STRLEN are
2900  *    defined in silk_types.h.
2901  *
2902  *    The strlen() of the returned string depends on the values in
2903  *    'ip_flags'.  For help in setting the column width of the output,
2904  *    use skipaddrStringMaxlen() to get the length of the longest
2905  *    possible string.
2906  *
2907  *    Use skipaddrCidrString() for when a CIDR prefix (netblock)
2908  *    length follows the IP address.
2909  */
2910 char *
2911 skipaddrString(
2912     char               *outbuf,
2913     const skipaddr_t   *ip,
2914     uint32_t            ip_flags);
2915 
2916 /**
2917  *    Fill 'outbuf' with a string representation of the CIDR block
2918  *    (netblock) denoted by the IP address in 'ip' and length in
2919  *    'prefix'.  The size of 'outbuf' must be at least
2920  *    SKIPADDR_CIDR_STRLEN bytes in length.  The function returns a
2921  *    pointer to 'outbuf'.
2922  *
2923  *    If the 'ip_flags' changes the displayed IP address between IPv4
2924  *    and IPv6 then the displayed 'prefix' is adjusted as well.
2925  *
2926  *    Note: The function assumes the proper mask has already been
2927  *    applied to the 'ip' (that is, that the bits below the 'prefix'
2928  *    are zero).
2929  *
2930  *    The form of the string will depend on the values in 'ip_flags',
2931  *    which should contain values from the skipaddr_flags_t
2932  *    enumeration.  Both skipaddr_flags_t and SKIPADDR_CIDR_STRLEN are
2933  *    defined in silk_types.h.
2934  *
2935  *    When 'ip_flags' contains SKIPADDR_ZEROPAD, the CIDR prefix value
2936  *    is also zero-padded.  The SKIPADDR_HEXADECIMAL setting does does
2937  *    affect the CIDR prefix, which is always displayed in decimal.
2938  *
2939  *    The strlen() of the returned string depends on the values in
2940  *    'ip_flags'.  For help in setting the column width of the output,
2941  *    use skipaddrCidrStringMaxlen() to get the length of the longest
2942  *    possible string.
2943  *
2944  *    See also skipaddrString().
2945  *
2946  *    Since SiLK 3.18.0.
2947  */
2948 char *
2949 skipaddrCidrString(
2950     char               *outbuf,
2951     const skipaddr_t   *ip,
2952     uint32_t            prefix,
2953     uint32_t            ip_flags);
2954 
2955 
2956 /**
2957  *    Return the length of longest string expected to be returned by
2958  *    skipaddrString() when 'ip_flags' represent the flags value
2959  *    passed to that function and 'allow_ipv6' is 0 when only IPv4
2960  *    addresses are passed to skipaddrString() and non-zero otherwise.
2961  *
2962  *    The return value should only ever be used to set a column width.
2963  *    Always use a buffer having at least SKIPADDR_STRLEN characters
2964  *    as the 'outbuf' parameter.
2965  *
2966  *    This function ignores the SKIPADDR_UNMAP_V6 flag since the
2967  *    function does not know whether all IP addresses in this column
2968  *    fall into the ::ffff:0:0/96 netblock.  If the caller knows this,
2969  *    the caller may safely reduce the returned length by 22.  (The
2970  *    caller may reduce the length by 24 for SKIPADDR_CANONICAL,
2971  *    SKIPADDR_NO_MIXED, and SKIPADDR_HEXADECIMAL, and 22 for
2972  *    SKIPADDR_DECIMAL).
2973  *
2974  *    See also skipaddrCidrStringMaxlen().
2975  */
2976 int
2977 skipaddrStringMaxlen(
2978     unsigned int        allow_ipv6,
2979     uint32_t            ip_flags);
2980 
2981 
2982 /**
2983  *    Return the length of longest string expected to be returned by
2984  *    skipaddrCidrString() when 'ip_flags' represent the flags value
2985  *    passed to that function and 'allow_ipv6' is 0 when only IPv4
2986  *    addresses are passed to skipaddrCidrString() and non-zero
2987  *    otherwise.
2988  *
2989  *    The return value should only ever be used to set a column width.
2990  *    Always use a buffer having at least SKIPADDR_CIDR_STRLEN
2991  *    characters as the 'outbuf' parameter.
2992  *
2993  *    This function treats SKIPADDR_UNMAP_V6 in the same way as
2994  *    skipaddrStringMaxlen(), which see.  When the input is known to
2995  *    contain only IPs in the ::ffff:0:0/96 netblock, the width may be
2996  *    reduced by 23 (or 25).
2997  *
2998  *    See also skipaddrStringMaxlen().
2999  *
3000  *    Since SiLK 3.18.0.
3001  */
3002 int
3003 skipaddrCidrStringMaxlen(
3004     unsigned int        allow_ipv6,
3005     uint32_t            ip_flags);
3006 
3007 
3008 /**
3009  *    DEPRECATED.  Use skipaddrString() instead.
3010  *
3011  *    Converts the integer form of an IPv4 IP address to the dotted-quad
3012  *    version.  ip is taken to be in native byte order; returns a
3013  *    pointer to a static string buffer.
3014  *
3015  *    Returns NULL on error.
3016  *
3017  *    Replace with:
3018  *
3019  *    skipaddr_t ipaddr;
3020  *    char outbuf[SKIPADDR_STRLEN];
3021  *    skipaddrSetV4(&ipaddr, &ip);
3022  *    skipaddrString(outbuf, &ipaddr, 0);
3023  */
3024 char *
3025 num2dot(
3026     uint32_t            ip);
3027 
3028 
3029 /**
3030  *    DEPRECATED.  Use skipaddrString() instead.
3031  *
3032  *    Like num2dot(), but will zero-pad the octects: num2dot0(0) will
3033  *    return "000.000.000.000".
3034  *
3035  *    Replace with:
3036  *
3037  *    skipaddr_t ipaddr;
3038  *    char outbuf[SKIPADDR_STRLEN];
3039  *    skipaddrSetV4(&ipaddr, &ip);
3040  *    skipaddrString(outbuf, &ipaddr, SKIPADDR_ZEROPAD);
3041  */
3042 char *
3043 num2dot0(
3044     uint32_t            ip)
3045     SK_GCC_DEPRECATED;
3046 
3047 
3048 /**
3049  *    DEPRECATED.  Use skipaddrString() instead.
3050  *
3051  *    Thread safe version of num2dot().  The 'outbuf' should be at
3052  *    least SKIPADDR_STRLEN characters long.
3053  *
3054  *    Replace with:
3055  *
3056  *    skipaddr_t ipaddr;
3057  *    char outbuf[SKIPADDR_STRLEN];
3058  *    skipaddrSetV4(&ipaddr, &ip);
3059  *    skipaddrString(outbuf, &ipaddr, 0);
3060  */
3061 char *
3062 num2dot_r(
3063     uint32_t            ip,
3064     char               *outbuf);
3065 
3066 
3067 /**
3068  *    DEPRECATED.  Use skipaddrString() instead.
3069  *
3070  *    Thread safe version of num2dot0().  The 'outbuf' must be at
3071  *    least SKIPADDR_STRLEN characters long.
3072  *
3073  *    Replace with:
3074  *
3075  *    skipaddr_t ipaddr;
3076  *    char outbuf[SKIPADDR_STRLEN];
3077  *    skipaddrSetV4(&ipaddr, &ip);
3078  *    skipaddrString(outbuf, &ipaddr, SKIPADDR_ZEROPAD);
3079  */
3080 char *
3081 num2dot0_r(
3082     uint32_t            ip,
3083     char               *outbuf)
3084     SK_GCC_DEPRECATED;
3085 
3086 
3087 /**
3088  *    A value that may be included in the 'print_flags' value of
3089  *    skTCPFlagsString() and skTCPStateString() that causes the
3090  *    returned string to contain spaces for bits that are not set.
3091  */
3092 #define SK_PADDED_FLAGS (1u << 0)
3093 
3094 
3095 /**
3096  *    The minimum size of the buffer to pass to skTCPFlagsString().
3097  */
3098 #define SK_TCPFLAGS_STRLEN 9
3099 
3100 /**
3101  *    Fill a buffer with a string representation of the TCP flags
3102  *    (tcpControlBits) value 'tcp_flags'.  If all flags are on, the
3103  *    resulting string is "FSRPAUEC".  The 'outbuf' is expected to be
3104  *    at least SK_TCPFLAGS_STRLEN long.
3105  *
3106  *    If 'print_flags' is SK_PADDED_FLAGS, a space ' ' appears in
3107  *    place of the character if the TCP flag is off, and the
3108  *    representation of a particular TCP bit always appears in the
3109  *    same column.
3110  */
3111 char *
3112 skTCPFlagsString(
3113     uint8_t             tcp_flags,
3114     char               *outbuf,
3115     unsigned int        print_flags);
3116 
3117 
3118 /**
3119  *    The minimum size of the buffer to pass to skTCPStateString().
3120  */
3121 #define SK_TCP_STATE_STRLEN 9
3122 
3123 /**
3124  *    Fill a buffer with a string representation of a SiLK atttributes
3125  *    (TCP state) value.  If all state flags are on, the resulting
3126  *    string is "TCFS".  The 'outbuf' is expected to be at least
3127  *    SK_TCP_STATE_STRLEN long.
3128  *
3129  *    If 'print_flags' is SK_PADDED_FLAGS, a space ' ' appears in
3130  *    place of the character if the state flag is off, the
3131  *    representation of a particular attribute bit always appears in
3132  *    the same column, and four space characters are appended to the
3133  *    string to the result is always 8 characters.
3134  */
3135 char *
3136 skTCPStateString(
3137     uint8_t             state,
3138     char               *outbuf,
3139     unsigned int        print_flags);
3140 
3141 
3142 /**
3143  *    DEPRECATED.  Replaced by skTCPFlagsString().
3144  *
3145  *    Removed in SiLK 4.0.0.
3146  *
3147  *    Return an 8 character string denoting which TCP flags are set.
3148  *    If all flags are on, FSRPAUEC is returned.  For any flag that is
3149  *    off, a space (' ') appears in place of the character.  Returns a
3150  *    pointer to a static buffer.
3151  */
3152 char *
3153 tcpflags_string(
3154     uint8_t             flags)
3155     SK_GCC_DEPRECATED;
3156 
3157 
3158 /**
3159  *    DEPRECATED.  Replaced by skTCPFlagsString().
3160  *
3161  *    Removed in SiLK 4.0.0.
3162  *
3163  *    Thread-safe version of tcpflags_string().  The 'outbuf' should
3164  *    be at least SK_TCPFLAGS_STRLEN characters long.
3165  */
3166 char *
3167 tcpflags_string_r(
3168     uint8_t             flags,
3169     char               *outbuf)
3170     SK_GCC_DEPRECATED;
3171 
3172 
3173 /**
3174  *    Strips all leading and trailing whitespace from 'line'.
3175  *    Modifies line in place.
3176  */
3177 int
3178 skStrip(
3179     char               *line);
3180 
3181 
3182 /**
3183  *    Converts uppercase letters in 'cp' to lowercase.  Modifies the
3184  *    string in place.
3185  */
3186 void
3187 skToLower(
3188     char               *cp);
3189 
3190 
3191 /**
3192  *    Converts lowercase letters in 'cp' to uppercase.  Modifies the
3193  *    string in place.
3194  */
3195 void
3196 skToUpper(
3197     char               *cp);
3198 
3199 
3200 /**
3201  *    Return a string describing the last error that occurred when
3202  *    invoking the skStringParse* functions.
3203  *
3204  *    The 'errcode' value is expected to be an silk_utils_errcode_t.
3205  */
3206 const char *
3207 skStringParseStrerror(
3208     int                 errcode);
3209 
3210 
3211 /**
3212  *    Given a C-string containing a list---i.e., comma or hyphen
3213  *    delimited set---of non-negative integers, e.g., "4,3,2-6",
3214  *    allocate and return, via the 'number_list' parameter, an array
3215  *    whose values are the numbers the list contains, breaking ranges
3216  *    into a list of numbers.  If duplicates appear in the input, they
3217  *    will appear in the return value.  Order is maintained.  Thus
3218  *    given the C-string 'input' of "4,3,2-6", the function will set
3219  *    *number_list to a newly allocated array containing
3220  *    {4,3,2,3,4,5,6}.  The number of entries in the array is returned
3221  *    in '*number_count'.  The list of number is limited by the
3222  *    'min_val' and 'max_val' parameters; a 'max_val' of 0 means no
3223  *    maximum.  The maximum size of the array to be returned is given
3224  *    by 'max_number_count'; when this value is 0 and max_value is not
3225  *    zero, it is set to the number of possible values (1+max-min);
3226  *    when max_number_count is 0 and max_value is 0, it is set to a
3227  *    large (2^24) number of entries.  In all cases, the function
3228  *    tries to keep the returned array as small as possible.  On
3229  *    success, 0 is returned.
3230  *
3231  *    INPUT:
3232  *      number_list -- the address in which to return the array
3233  *      number_count -- the address in which to store the
3234  *          number valid elements in the returned array.
3235  *      input -- the string buffer to be parsed
3236  *      min_value -- the minimum allowed value in user input
3237  *      max_value -- the maximum allowed value in user input.  When
3238  *          max_value is 0, there is no maximum.
3239  *      max_number_count -- the maximum number of entries the array
3240  *          returned in 'number_list' is allowed to have.
3241  *
3242  *    The caller should free() the returned array when finished
3243  *    processing.
3244  *
3245  *    On error, a silk_utils_errcode_t value is returned.
3246  */
3247 int
3248 skStringParseNumberList(
3249     uint32_t          **number_list,
3250     uint32_t           *number_count,
3251     const char         *input,
3252     uint32_t            min_val,
3253     uint32_t            max_val,
3254     uint32_t            max_number_count);
3255 
3256 
3257 /**
3258  *    Similar to skStringParseNumberList(), except that instead of
3259  *    returning an array, bits are set in the sk_bitmap_t 'out_bitmap'
3260  *    which the caller must have previously created.
3261  *
3262  *    The input may have values from 0 to skBitmapGetSize(out_bitmap)-1.
3263  *
3264  *    This function does NOT clear the bits in 'out_bitmap' prior to
3265  *    setting the bits based on 'input.  When re-using a bitmap, the
3266  *    caller should first call skBitmapClearAllBits().
3267  *
3268  *    If an error occurs, a silk_utils_errcode_t value is returned and
3269  *    the bitmap will be left in an unknown state.
3270  */
3271 int
3272 skStringParseNumberListToBitmap(
3273     sk_bitmap_t        *out_bitmap,
3274     const char         *input);
3275 
3276 
3277 /**
3278  *    Parses a C-string containing an IPv4 or IPv6 address in the
3279  *    "canonical" presentation form and sets the value pointed to by
3280  *    'out_val' to the result.
3281  *
3282  *    In addition, a single integer value will be parsed as IPv4
3283  *    address.
3284  *
3285  *    Returns 0 and puts the result into 'out_val' if parsing was
3286  *    successful and the 'ip_string' only contained the IP address and
3287  *    optional leading and/or trailing whitespace.
3288  *
3289  *    Returns a positive value and puts the result into 'out_val' if
3290  *    parsing was successful and 'ip_string' contains additional,
3291  *    non-whitespace text.  The return value is the number of
3292  *    characters that were parsed as part of the IP address and any
3293  *    leading whitespace.  That is, the return value is the position
3294  *    in 'ip_string' where the trailing text begins.  Whitespace
3295  *    between the IP address and the trailing text is not parsed.
3296  *
3297  *    Returns one of the silk_utils_errcode_t values on error.
3298  *
3299  *    This routine will not parse IPs in CIDR notation; or rather, it
3300  *    will parse the IP portion, but the return value will be the
3301  *    position of the '/' character.  To correctly parse IPs in CIDR
3302  *    notation, use skStringParseCIDR() or skStringParseIPWildcard().
3303  */
3304 int
3305 skStringParseIP(
3306     skipaddr_t         *out_val,
3307     const char         *ip_string);
3308 
3309 
3310 /**
3311  *    Takes a C-string containing an IPv4 or IPv6 address and fills
3312  *    'ipwild' with the result.
3313  *
3314  *    Returns 0 and puts result into 'ipwild' if parsing was
3315  *    successful and 'ip_string' contained only the IP address and
3316  *    optional leading or trailing whitespace.
3317  *
3318  *    Returns one of the silk_utils_errcode_t values on error.
3319  *
3320  *    The 'ip_string' can be in CIDR notation such as "1.2.3.0/24" or
3321  *    "ff80::/16"; in the canonical form "1.2.3.4" or
3322  *    "::ffff:0102:0304", an integer 16909056, an integer with a CIDR
3323  *    designation 16909056/24, or in SiLK wildcard notation: a IP in
3324  *    the canonical form with an 'x' respresenting an entire octet
3325  *    "1.2.3.x" in IPv4 or entire hexadectet in IPv6
3326  *    "1:2:3:4:5:6:7.x", or a dotted quad with lists or ranges in any
3327  *    or all octets or hexadectets "1.2,3.4,5.6,7", "1.2.3.0-255",
3328  *    "::2-4", "1-2:3-4:5-6:7-8:9-a:b-c:d-e:0-ffff".
3329  *
3330  *    Note that wildcard characters (',','-','x') and CIDR notation
3331  *    cannot be combined in a single address.
3332  *
3333  *    See also skStringParseCIDR().
3334  */
3335 int
3336 skStringParseIPWildcard(
3337     skIPWildcard_t     *ipwild,
3338     const char         *ip_string);
3339 
3340 
3341 /**
3342  *    Parses a C-string containing an IPv4 or IPv6 address in the
3343  *    "canonical" presentation form with an optional CIDR designation.
3344  *    Sets the values pointed to by 'out_val' and 'out_cidr' to the
3345  *    parsed IP address and the CIDR designation.  If no CIDR
3346  *    designation is present in 'ip_string', 'out_cidr' is set to the
3347  *    complete IP length: 32 for IPv4, 128 for IPv6.
3348  *
3349  *    In addition, a single integer value will be parsed as IPv4
3350  *    address, with an optional CIDR designation.
3351  *
3352  *    Returns 0 and puts the result into 'out_val' if parsing was
3353  *    successful and the 'ip_string' only contained the IP address,
3354  *    the CIDR designation, and optional leading and/or trailing
3355  *    whitespace.
3356  *
3357  *    Returns one of the silk_utils_errcode_t values on error.
3358  *
3359  *    If the CIDR mask is too large for the type of IP,
3360  *    SKUTILS_ERR_MAXIMUM is returned.
3361  *
3362  *    It is an error for 'ip_string' to contain any text other than
3363  *    the IP string, CIDR designation, and leading or trailing
3364  *    whitespace.  SKUTILS_ERR_BAD_CHAR will be returned.
3365  *
3366  *    This routine will not parse the SiLK IP Wildcard notation; use
3367  *    skStringParseIPWildcard() for that.
3368  */
3369 int
3370 skStringParseCIDR(
3371     skipaddr_t         *out_val,
3372     uint32_t           *out_cidr,
3373     const char         *ip_string);
3374 
3375 
3376 /* typedef union sk_sockaddr_un sk_sockaddr_t;              // silk_types.h */
3377 /* typedef struct sk_sockaddr_array_st sk_sockaddr_array_t; // silk_types.h */
3378 
3379 /**
3380  *    Constant returned by skSockaddrArrayGetHostname() when the
3381  *    string that created the sk_sockaddr_array_t---that is, the
3382  *    string passed to skStringParseHostPortPair()---did not contain a
3383  *    hostname or host address.
3384  */
3385 extern const char *sk_sockaddr_array_anyhostname;
3386 
3387 /* It seems that solaris does not define SUN_LEN (yet) */
3388 #ifndef SUN_LEN
3389 #define SUN_LEN(su)                                                     \
3390     (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
3391 #endif
3392 
3393 /* AF_UNIX seems to be defined everywhere, but the standard may change
3394  * to AF_LOCAL in the future. */
3395 #ifndef AF_UNIX
3396 #define AF_UNIX AF_LOCAL
3397 #endif
3398 
3399 /**
3400  *    Return the size of sk_sockaddr_t object, suitable for passing
3401  *    as the addrlen in functions such as connect(2) and bind(2).
3402  *
3403  *    Prior to SiLK 3.16.0, this was called skSockaddrLen().
3404  */
3405 #if 0
3406 size_t
3407 skSockaddrGetLen(
3408     const sk_sockaddr_t    *s);
3409 #endif  /* 0 */
3410 #define skSockaddrGetLen(s)                                             \
3411     (((s)->sa.sa_family == AF_INET) ? sizeof((s)->v4) :                 \
3412      (((s)->sa.sa_family == AF_INET6) ? sizeof((s)->v6) :               \
3413       (((s)->sa.sa_family == AF_UNIX) ? SUN_LEN(&(s)->un) : 0)))
3414 
3415 /**
3416  *    DEPRECATED.  Replaced by skSockaddrGetLen().
3417  *
3418  *    Removed in SiLK 4.0.0.
3419  */
3420 size_t
3421 skSockaddrLen(
3422     const sk_sockaddr_t    *s)
3423     SK_GCC_DEPRECATED;
3424 
3425 
3426 /**
3427  *    Return the port portion of a sk_sockaddr_t object, as an integer
3428  *    in host-byte-order.  Return -1 for sockaddr types without
3429  *    ports.
3430  *
3431  *    Prior to SiLK 3.16.0, this was called skSockaddrPort().
3432  */
3433 #if 0
3434 int
3435 skSockaddrGetPort(
3436     const sk_sockaddr_t    *s);
3437 #endif  /* 0 */
3438 #define skSockaddrGetPort(s)                                            \
3439     (((s)->sa.sa_family == AF_INET) ? ntohs((s)->v4.sin_port) :         \
3440      (((s)->sa.sa_family == AF_INET6) ? ntohs((s)->v6.sin6_port) : -1))
3441 
3442 /**
3443  *    DEPRECATED.  Replaced by skSockaddrGetPort().
3444  *
3445  *    Removed in SiLK 4.0.0.
3446  */
3447 int
3448 skSockaddrPort(
3449     const sk_sockaddr_t    *s)
3450     SK_GCC_DEPRECATED;
3451 
3452 
3453 /**
3454  *    Destroy a sk_sockaddr_array_t structure previously created by
3455  *    skStringParseHostPortPair().  Do nothing if the argument is
3456  *    NULL.
3457  */
3458 #if 0
3459 void
3460 skSockaddrArrayDestroy(
3461     sk_sockaddr_array_t    *s);
3462 #endif  /* 0 */
3463 #define skSockaddrArrayDestroy(s)               \
3464     do {                                        \
3465         if (s) {                                \
3466             free((s)->name);                    \
3467             free((s)->host_port_pair);          \
3468             free((s)->addrs);                   \
3469             free(s);                            \
3470         }                                       \
3471     } while (0)
3472 
3473 
3474 /**
3475  *    Return the hostname or host address portion of a
3476  *    sk_sockaddr_array_t structure as a C character array.  That is,
3477  *    return the host or IP address portion of the 'host_port'
3478  *    parameter of skStringParseHostPortPair().
3479  *
3480  *    If no hostname was specified when the sk_sockaddr_array_t was
3481  *    created, return the string specified by the global
3482  *    sk_sockaddr_array_anyhostname constant---the string "*".
3483  *
3484  *    To determine whether a hostname was provided to
3485  *    skStringParseHostPortPair(), the caller may compare the result
3486  *    of this macro with the sk_sockaddr_array_anyhostname constant.
3487  *
3488  *    Prior to SiLK 3.16.0, this was called skSockaddrArrayNameSafe().
3489  */
3490 #if 0
3491 const char *
3492 skSockaddrArrayGetHostname(
3493     const sk_sockaddr_array_t  *s);
3494 #endif  /* 0 */
3495 #define skSockaddrArrayGetHostname(s)                           \
3496     ((s)->name ? (s)->name : sk_sockaddr_array_anyhostname)
3497 
3498 /*
3499  *    DEPRECATED.  Replaced by skSockaddrArrayGetHostname().
3500  *
3501  *    Removed in SiLK 4.0.0.
3502  */
3503 const char *
3504 skSockaddrArrayNameSafe(
3505     const sk_sockaddr_array_t  *s)
3506     SK_GCC_DEPRECATED;
3507 
3508 
3509 /**
3510  *    DEPRECATED.  Replaced by skSockaddrArrayGetHostname().  If need
3511  *    to know whether value is NULL, compare result of
3512  *    skSockaddrArrayGetHostname() to sk_sockaddr_array_anyhostname.
3513  *
3514  *    Removed in SiLK 4.0.0.
3515  *
3516  *    Returns the name of a sk_sockaddr_array_t structure.
3517  *    Specifically, returns the host or IP address portion of the
3518  *    'host_port' parameter of skStringParseHostPortPair().  May
3519  *    return NULL.  See also skSockaddrArrayNameSafe() and
3520  *    skSockaddrString().
3521  */
3522 const char *
3523 skSockaddrArrayName(
3524     const sk_sockaddr_array_t  *s)
3525     SK_GCC_DEPRECATED;
3526 
3527 
3528 /**
3529  *    Return the host-port pair string that created the
3530  *    sk_sockaddr_array_t structure.  The return value is nearly the
3531  *    string that was passed to skStringParseHostPortPair() except the
3532  *    string uses a "*" or "[*]" to represent the host when no
3533  *    host-name/-address was provided to skStringParseHostPortPair()
3534  *    and the HOST_PROHIBITED flag was not set.
3535  *
3536  *    Since SiLK 4.0.0.
3537  */
3538 #if 0
3539 const char *
3540 skSockaddrArrayGetHostPortPair(
3541     const sk_sockaddr_array_t  *s);
3542 #endif  /* 0 */
3543 #define skSockaddrArrayGetHostPortPair(s)   ((s)->host_port_pair)
3544 
3545 
3546 /**
3547  *    Return the number of addresses in a sk_sockaddr_array_t
3548  *    structure.
3549  *
3550  *    Prior to SiLK 3.16.0, this was called skSockaddrArraySize().
3551  */
3552 #if 0
3553 uint32_t
3554 skSockaddrArrayGetSize(
3555     const sk_sockaddr_array_t  *s);
3556 #endif  /* 0 */
3557 #define skSockaddrArrayGetSize(s)           ((s)->num_addrs)
3558 
3559 /*
3560  *    DEPRECATED.  Replaced by skSockaddrArrayGetSize().
3561  *
3562  *    Removed in SiLK 4.0.0.
3563  */
3564 uint32_t
3565 skSockaddrArraySize(
3566     const sk_sockaddr_array_t  *s)
3567     SK_GCC_DEPRECATED;
3568 
3569 
3570 /**
3571  *    Return the address (sk_sockaddr_t *) at position 'n' in the
3572  *    sk_sockaddr_array_t structure 's'.  The first address is at
3573  *    position 0.  The value 'n' must be less than
3574  *    skSockaddrArrayGetSize(s), otherwise the return value is
3575  *    indeterminate.
3576  */
3577 #if 0
3578 const sk_sockaddr_t *
3579 skSockaddrArrayGet(
3580     const sk_sockaddr_array_t  *s,
3581     uint32_t                    n);
3582 #endif  /* 0 */
3583 #define skSockaddrArrayGet(s, n)            (&((s)->addrs[n]))
3584 
3585 
3586 /**
3587  *    Ignore the port value when comparing two sk_sockaddr_t objects
3588  *    with skSockaddrCompare() or skSockaddrArrayMatches().
3589  */
3590 #define SK_SOCKADDRCOMP_NOPORT       (1u << 0)
3591 
3592 /**
3593  *    Ignore the address when comparing two sk_sockaddr_t objects
3594  *    with skSockaddrCompare() or skSockaddrArrayMatches().
3595  */
3596 #define SK_SOCKADDRCOMP_NOADDR       (1u << 1)
3597 
3598 /**
3599  *    Treat IPv4 and IPv6 addresses as different when comparing two
3600  *    sk_sockaddr_t objects with skSockaddrCompare() or
3601  *    skSockaddrArrayMatches().
3602  */
3603 #define SK_SOCKADDRCOMP_NOT_V4_AS_V6 (1u << 2)
3604 
3605 
3606 /**
3607  *    Fill 'outbuf' with a string representing the IP address in
3608  *    'addr' and any non-zero port number.  The IP address and port
3609  *    are separated by a colon, ':'.  If the address in 'addr' is
3610  *    INADDR_ANY, the address is represented by an asterisk '*'.  When
3611  *    the address is IPv6 and the port is non-zero, the address is
3612  *    enclosed in square brackets, '[',']'.  When 'addr' contains a
3613  *    Unix domain socket, write the path to 'outbuf'.
3614  *
3615  *    Return the number of bytes written to 'outbuf', not including
3616  *    the terminating NUL.
3617  *
3618  *    Write no more than 'size' bytes to 'outbuf'.  If 'outbuf' is not
3619  *    large enough to hold the string, return the number of bytes that
3620  *    would have written if 'outbuf' had been large enough to hold the
3621  *    entire string, not including the terminating NUL.
3622  */
3623 ssize_t
3624 skSockaddrString(
3625     char                   *outbuf,
3626     size_t                  size,
3627     const sk_sockaddr_t    *addr);
3628 
3629 /**
3630  *    Compare two sk_sockaddr_t objects.
3631  *
3632  *    Return -1 if a is "less than" b, 1 if a is "greater than" b,
3633  *    and 0 if the two are equal.
3634  *
3635  *    The 'flags' parameter may contain any of the following bits:
3636  *
3637  *    SK_SOCKADDRCOMP_NOPORT -- ignore the port portions when
3638  *    comparing
3639  *
3640  *    SK_SOCKADDRCOMP_NOADDR -- ignore the address potions when
3641  *    comparing
3642  *
3643  *    SK_SOCKADDRCOMP_NOT_V4_AS_V6 -- do not map IPv4 addresses into
3644  *    the ::ffff:0:0/96 IPv6 netblock when comparing an AF_INET and an
3645  *    AF_INET6 sk_sockaddr_t.
3646  */
3647 int
3648 skSockaddrCompare(
3649     const sk_sockaddr_t    *a,
3650     const sk_sockaddr_t    *b,
3651     unsigned int            flags);
3652 
3653 /**
3654  *    Determine whether 'array' contains 'addr', according to
3655  *    'flags'.  Return 1 if true, 0 if false.
3656  *
3657  *    Addresses are compared using the skSockaddrCompare() function.
3658  *    The 'flags' argument will be passed to that function.
3659  *
3660  *    Return value will be 0 if either 'array' or 'addr' are NULL.
3661  */
3662 int
3663 skSockaddrArrayContains(
3664     const sk_sockaddr_array_t  *array,
3665     const sk_sockaddr_t        *addr,
3666     unsigned int                flags);
3667 
3668 /**
3669  *    Determine whether two sk_sockaddr_array_t objects are
3670  *    identical, according to 'flags'.
3671  *
3672  *    Two sk_sockaddr_array_t objects are considered equal if they
3673  *    have the same number of addresses, and each address in 'a' is
3674  *    contained in 'b'.  Two NULL arrays are considered equal.  It is
3675  *    assumed that the two arrays contain no duplicate addresses.
3676  *    Addresses are compared with the skSockaddrCompare() function,
3677  *    which will use the 'flags' argument.
3678  */
3679 int
3680 skSockaddrArrayEqual(
3681     const sk_sockaddr_array_t  *a,
3682     const sk_sockaddr_array_t  *b,
3683     unsigned int                flags);
3684 
3685 
3686 /**
3687  *    Decide whether two sk_sockaddr_array_t objects match.  Return
3688  *    1 if they match, 0 otherwise.
3689  *
3690  *    Two sk_sockaddr_array_t objects are considered to match if any
3691  *    of their sk_sockaddr_t elements match as determined by
3692  *    skSockaddrCompare().  The 'flags' argument will be passed to the
3693  *    skSockaddrCompare() function.
3694  *
3695  *    An empty array matches nothing, not even another empty array.
3696  */
3697 int
3698 skSockaddrArrayMatches(
3699     const sk_sockaddr_array_t  *a,
3700     const sk_sockaddr_array_t  *b,
3701     unsigned int                flags);
3702 
3703 
3704 /* Flags which can be passed to skStringParseHostPortPair() */
3705 #define PORT_REQUIRED    (1u << 0)
3706 #define PORT_PROHIBITED  (1u << 1)
3707 #define HOST_REQUIRED    (1u << 2)
3708 #define HOST_PROHIBITED  (1u << 3)
3709 #define IPV6_REQUIRED    (1u << 4)
3710 #define IPV6_PROHIBITED  (1u << 5)
3711 
3712 
3713 /**
3714  *    Parse a host:port pair, or a host, or a port number.
3715  *
3716  *    Allocate a new sk_sockaddr_array_t object, store the resulting
3717  *    set of addresses and ports as 'sk_sockaddr_t' objects in the
3718  *    sk_sockaddr_array_t object, and store the array in the location
3719  *    referenced by 'sockaddr'.
3720  *
3721  *    The number of sk_sockaddr_t's in the sk_sockaddr_array_t is
3722  *    given by skSockaddrArraySize().  The caller may obtain an
3723  *    individual sk_sockaddr_t by calling skSockaddrArrayGet().  The
3724  *    caller must destroy the array by calling
3725  *    skSockaddrArrayDestroy().
3726  *
3727  *    The host portion of 'host_port' may be a dotted decimal IPv4
3728  *    address, a hex string IPv6 address, or a hostname.  The host may
3729  *    be enclosed in '[' and ']', and it must be so enclosed when an
3730  *    IPv6 hex string includes a port number, for example "[::]:80"
3731  *
3732  *    The flags are a bitwise combination of
3733  *    {PORT,HOST,IPV6}_{REQUIRED,PROHIBITED}.  Four of these flags
3734  *    specify whether the host portion and/or port portion of the
3735  *    host_port string is required or prohibited.  By default there
3736  *    are no requirements/prohibitions on the content of 'host_port'.
3737  *    The other two flags specify whether IPv6 addresses should be
3738  *    resolved, or whether only IPv6 addresses should be resolved.
3739  *    The default is to resolve to both IPv6 and IPv4 addresses.
3740  */
3741 int
3742 skStringParseHostPortPair(
3743     sk_sockaddr_array_t   **sockaddr,
3744     const char             *host_port,
3745     uint8_t                 flags);
3746 
3747 
3748 /**
3749  *    skStringParseDatetime() sets the lower three bits of its
3750  *    'out_flags' parameter to this value when only a year was parsed.
3751  *    The 'out_flags' value should never contain this value.
3752  */
3753 #define SK_PARSED_DATETIME_YEAR             1
3754 
3755 /**
3756  *    skStringParseDatetime() sets the lower three bits of its
3757  *    'out_flags' parameter to this value when a year and month were
3758  *    parsed.  The 'out_flags' value should never contain this value.
3759  */
3760 #define SK_PARSED_DATETIME_MONTH            2
3761 
3762 /**
3763  *    skStringParseDatetime() sets the lower three bits of its
3764  *    'out_flags' parameter to this value when a year, month, and day
3765  *    were parsed or when an epoch time was parsed and the value is a
3766  *    multiple of 86400.
3767  */
3768 #define SK_PARSED_DATETIME_DAY              3
3769 
3770 /**
3771  *    skStringParseDatetime() sets the lower three bits of its
3772  *    'out_flags' parameter to this value when a year, month, day, and
3773  *    hour were parsed or when an epoch time was parsed and the value
3774  *    is a multiple of 3600.
3775  */
3776 #define SK_PARSED_DATETIME_HOUR             4
3777 
3778 /**
3779  *    skStringParseDatetime() sets the lower three bits of its
3780  *    'out_flags' parameter to this value when a year, month, day,
3781  *    hour, and minute were parsed or when an epoch time was parsed
3782  *    and the value is a multiple of 60.
3783  */
3784 #define SK_PARSED_DATETIME_MINUTE           5
3785 
3786 /**
3787  *    skStringParseDatetime() sets the lower three bits of its
3788  *    'out_flags' parameter to this value when a year, month, day,
3789  *    hour, minute, and second were parsed or when an epoch time was
3790  *    parsed and no fractional seconds value was present.
3791  */
3792 #define SK_PARSED_DATETIME_SECOND           6
3793 
3794 /**
3795  *    skStringParseDatetime() sets the lower three bits of its
3796  *    'out_flags' parameter to this value when a year, month, day,
3797  *    hour, minute, second, and fractional second were parsed or when
3798  *    an epoch time was parsed and a fractional seconds value was
3799  *    present.
3800  */
3801 #define SK_PARSED_DATETIME_FRACSEC          7
3802 
3803 /**
3804  *    A mask to apply to the 'out_flags' value set by
3805  *    skStringParseDatetime() to determine the precision.
3806  */
3807 #define SK_PARSED_DATETIME_MASK_PRECISION   0x7
3808 
3809 /**
3810  *    Return the precision portion of the 'out_flags' value that is
3811  *    set by calling skStringParseDatetime().
3812  */
3813 #define SK_PARSED_DATETIME_GET_PRECISION(pdgp_flags)    \
3814     (SK_PARSED_DATETIME_MASK_PRECISION & (pdgp_flags))
3815 
3816 /**
3817  *    skStringParseDatetime() sets this bit in its 'out_flags'
3818  *    parameter when the parsed string contained seconds since the
3819  *    UNIX epoch.
3820  */
3821 #define SK_PARSED_DATETIME_EPOCH            0x8
3822 
3823 /**
3824  *    Attempt to parse the 'time_string' as a date in the form
3825  *    YYYY/MM/DD[:HH[:MM[:SS[.sss]]]] and set *time_val to that time in
3826  *    milliseconds since the UNIX epoch.  Assume the time in UTC
3827  *    unless SiLK was configured with the --enable-local-timezone
3828  *    switch, in which case the time is assumed to be in the local
3829  *    timezone.
3830  *
3831  *    A fractional seconds value with more precision that milliseconds
3832  *    is truncated.  NOTE: Prior to SiLK 3.10.0, fractional seconds
3833  *    were rounded to the nearest millisecond value.
3834  *
3835  *    When the input string contains only digits and decimal points
3836  *    (".") and is at least eight characters in length, parse the
3837  *    value before the decimal point as seconds since the UNIX epoch,
3838  *    and the value after the decimal point as fractional seconds.
3839  *    Return an error if more than one decimal point is present.
3840  *
3841  *    If the 'out_flags' parameter is non-null, set the location it
3842  *    references with SK_PARSED_DATETIME_* values to indicate what was
3843  *    parsed.
3844  *
3845  *    The SK_PARSED_DATEDTIME_EPOCH bit of 'out_flags' is set when the
3846  *    value parsed was in epoch seconds.  The lower three bits are
3847  *    still set to reflect the precision of the value.
3848  *
3849  *    Note that skStringParseDatetime() will return SKUTILS_ERR_SHORT
3850  *    if the time_string is not an epoch time and does not contain at
3851  *    least Day precision.
3852  *
3853  *    Return 0 on success.  Returns a silk_utils_errcode_t value on an
3854  *    error; error conditions include an empty string, malformed date,
3855  *    or extra text after the date.  Returns SKUTILS_ERR_SHORT if the
3856  *    date does not have at least day precision.
3857  */
3858 int
3859 skStringParseDatetime(
3860     sktime_t           *time_val,
3861     const char         *time_string,
3862     unsigned int       *out_flags);
3863 
3864 
3865 /**
3866  *    Attempt to parse 'datetime_range' as a datetime or a range of
3867  *    datetimes.  When two hyphen-separated datetimes are found, store
3868  *    the first in 'start' and the second in 'end'.  When only one
3869  *    datetime is found, store that time in 'start' and set 'end' to
3870  *    INT64_MAX.
3871  *
3872  *    This function uses skStringParseDatetime() internally, and the
3873  *    'start_flags' and 'end_flags' values are set by that function
3874  *    when parsing the starting datetime and ending datetime,
3875  *    respectively.  See skStringParseDatetime() for more information.
3876  *
3877  *    Return 0 when the datetimes are parsed correctly.
3878  *
3879  *    Return an silk_utils_errcode_t value on error, including
3880  *    SKUTILS_ERR_SHORT if the either date does not have at least day
3881  *    precision, and SKUTILS_ERR_BAD_RANGE if the end-date is earlier
3882  *    than the start-date.
3883  */
3884 int
3885 skStringParseDatetimeRange(
3886     sktime_t           *start,
3887     sktime_t           *end,
3888     const char         *datetime_range,
3889     unsigned int       *start_flags,
3890     unsigned int       *end_flags);
3891 
3892 
3893 /**
3894  *    Take a calendar time 't' and a 'precision' and put into
3895  *    'ceiling_time' the latest-possible (largest) calendar time
3896  *    greater than or equal to 't' such that the value specified by
3897  *    'precision' is not modified.  't' and 'ceiling_time' may point
3898  *    to the same memory.  See skStringParseDatetime() for a
3899  *    description the precision.
3900  *
3901  *    skStringParseDatetime() parses a string to the earliest-possible
3902  *    calendar time that meets the constraints parsed.  For example,
3903  *    "1990/12/25:05" is taken to mean "1990/12/25:05:00:00.000".
3904  *    Passing that value and its precision---which would be
3905  *    SK_PARSED_DATETIME_HOUR---to skDatetimeCeiling() would result in
3906  *    the calendar time for "1990/12/25:05:59:59.999".
3907  *
3908  *    skDatetimeCeiling() is commonly used to calculate the endpoint
3909  *    for a range of dates parsed by skStringParseDatetimeRange().
3910  *    For example, "2004/12/25-2004/12/26:3" should represent
3911  *    everything between "2004/12/25:00:00:00.000" and
3912  *    "2004/12/26:03:59:59.999".
3913  *
3914  *    The time is assumed to be in UTC unless SiLK was configured with
3915  *    the --enable-local-timezone switch.  The timezone is only a
3916  *    factor for times that are coarser than hour precision.
3917  *
3918  *    skDatetimeCeiling() ignores whether SK_PARSED_DATETIME_EPOCH is
3919  *    set in the 'precision' parameter.
3920  *
3921  *    Return 0 on success.  Return -1 if the system time conversion
3922  *    functions return an error, if 'precision' is 0, or if
3923  *    'precision' is an unexpected value.
3924  */
3925 int
3926 skDatetimeCeiling(
3927     sktime_t           *ceiling_time,
3928     const sktime_t     *t,
3929     unsigned int        precision);
3930 
3931 
3932 /**
3933  *    Take a calendar time 't' and a 'precision' and put into
3934  *    'floor_time' the earliest-possible (lowest) timestamp less than
3935  *    or equal to 't' such that the value specified by 'precision' is
3936  *    not modified.  't' and 'floor_time' may point to the same
3937  *    memory.  See skStringParseDatetime() for a description the
3938  *    precision.
3939  *
3940  *    One use of skDatetimeFloor() is to clear the minutes and seconds
3941  *    fields from a calendar time.
3942  *
3943  *    The time is assumed to be in UTC unless SiLK was configured with
3944  *    the --enable-local-timezone switch.  The timezone is only a
3945  *    factor for times that are coarser than hour precision.
3946  *
3947  *    skDatetimeFloor() ignores whether SK_PARSED_DATETIME_EPOCH is
3948  *    set in the 'precision' parameter.
3949  *
3950  *    Return 0 on success.  Return -1 if the system time conversion
3951  *    functions return an error, if 'precision' is 0, or if
3952  *    'precision' is an unexpected value.
3953  *
3954  *    Since SiLK 3.11.0.
3955  */
3956 int
3957 skDatetimeFloor(
3958     sktime_t           *floor_time,
3959     const sktime_t     *t,
3960     unsigned int        precision);
3961 
3962 
3963 /**
3964  *    A wrapper over skStringParseUint64() that uses unsiged 32-bit
3965  *    numbers unstead of 64-bit numbers.
3966  */
3967 int
3968 skStringParseUint32(
3969     uint32_t           *result_val,
3970     const char         *int_string,
3971     uint32_t            min_val,
3972     uint32_t            max_val);
3973 
3974 
3975 /**
3976  *    Attempts to parse the C string 'int_string' as an unsigned
3977  *    64-bit decimal integer, and puts the result into the referent of
3978  *    'result_val'.  Ignores any whitespace before and after the
3979  *    number.
3980  *
3981  *    In addition, the function verifies that the value is between
3982  *    'min_val' and 'max_val' inclusive.  A 'max_val' of 0 is
3983  *    equivalent to UINT64_MAX; i.e., the largest value that will fit
3984  *    in a 64bit value.
3985  *
3986  *    Returns 0 and fills 'result_val' when 'int_string' contains only
3987  *    a number and leading or trailing whitespace and the number is
3988  *    parsable and the resulting value is within the limits.
3989  *
3990  *    Returns a positive value and fills 'result_val' when
3991  *    'int_string' contains a value within the limits and contains
3992  *    additional non-whitespace text after a parsed number.  The
3993  *    return value is the number of characters parsed in 'int_string'.
3994  *    For example, an 'int_string' of either "7x" or "7 x" causes the
3995  *    function to set the referent of 'result_val' to 7 and return 1.
3996  *
3997  *    Fills 'result_val' and returns either SKUTILS_ERR_MINIMUM or
3998  *    SKUTILS_ERR_MAXIMUM when the value is successfully parsed but is
3999  *    not within the limits.  When the value falls outside the
4000  *    possible range of the function, 'result_val' is unchanged and
4001  *    SKUTILS_ERR_OVERFLOW is returned.
4002  *
4003  *    Returns a silk_utils_errcode_t value on any other error and
4004  *    leaves 'result_val' unchanged.
4005  */
4006 int
4007 skStringParseUint64(
4008     uint64_t           *result_val,
4009     const char         *int_string,
4010     uint64_t            min_val,
4011     uint64_t            max_val);
4012 
4013 
4014 
4015 /**
4016  *    Options flags to pass to skStringParseHumanUint64()
4017  */
4018 typedef enum {
4019     /** Use 1024 for k, etc.  This is the default unless
4020      * SK_HUMAN_LOWER_SI is specified. */
4021     SK_HUMAN_LOWER_TRADITIONAL = 0,
4022 
4023     /** Use 1000 instead of 1024 for k, etc. */
4024     SK_HUMAN_LOWER_SI = 1,
4025 
4026     /** Use 1024 for K, etc.  This is the default unless
4027      * SK_HUMAN_UPPER_SI is specified. */
4028     SK_HUMAN_UPPER_TRADITIONAL = 0,
4029 
4030     /** Use 1000 instead of 1024 for K, etc. */
4031     SK_HUMAN_UPPER_SI = 2,
4032 
4033     /** Do not allow whitespace between the number and the suffix---the
4034      * position of the suffix will be the function's return value.
4035      * This is the default unless SK_HUMAN_MID_WS is specified. */
4036     SK_HUMAN_MID_NO_WS = 0,
4037 
4038     /** Ignore whitespace between the number and the suffix */
4039     SK_HUMAN_MID_WS = 4,
4040 
4041     /** Parse trailing whitespace.  This is the default unless
4042      * SK_HUMAN_END_NO_WS is specified. */
4043     SK_HUMAN_END_WS = 0,
4044 
4045     /** Do not parse trailing whitespace.  The position of the first
4046      * whitespace chacter is the function's return value. */
4047     SK_HUMAN_END_NO_WS = 8
4048 } skHumanFlags_t;
4049 
4050 /**
4051  *    Default settings from skStringParseHumanUint64()
4052  */
4053 #define SK_HUMAN_NORMAL                                         \
4054     (SK_HUMAN_LOWER_TRADITIONAL | SK_HUMAN_UPPER_TRADITIONAL    \
4055      | SK_HUMAN_MID_NO_WS | SK_HUMAN_END_WS)
4056 
4057 /**
4058  *    Attempts to parse the C string 'int_string' as an unsigned
4059  *    64-bit integer, ignoring leading whitespace.  In addition,
4060  *    handles human suffixes such as k, m, g, and t.  Puts the result
4061  *    into location pointed to by 'result_val'.
4062  *
4063  *    Returns a value >= 0 the string was parsable.  Returns 0 when
4064  *    nothing other than parsed whitespace was present.  A positive
4065  *    return value is the index into 'int_string' of the first
4066  *    non-parsed character following the successfully parsed number;
4067  *    e.g; "1x" would set *result_val to 1 and return 2.
4068  *
4069  *    Returns an silk_utils_errcode_t value on error.  Note that "NaN"
4070  *    returns SKUTILS_ERR_BAD_CHAR.
4071  *
4072  *    The 'parse_flags' value is made by or-ing flags from
4073  *    skHumanFlags_t together.  See their descriptions above.
4074  */
4075 int
4076 skStringParseHumanUint64(
4077     uint64_t           *result_val,
4078     const char         *int_string,
4079     unsigned int        parse_flags);
4080 
4081 
4082 /* Following are used by skStringParseRange64() and
4083  * skStringParseRange32() */
4084 
4085 /**
4086  *    Allow a fully specified range "3-5", a single value "3"
4087  *    (range_upper is set to range_lower), or an open-ended range "3-"
4088  *    (range_upper is set to max_val).
4089  */
4090 #define SKUTILS_RANGE_SINGLE_OPEN   0
4091 
4092 /**
4093  *    Allow a fully specified range "3-5" or an open-ended range "3-";
4094  *    i.e., the argument must contain a hyphen.  A single value is not
4095  *    allowed.
4096  */
4097 #define SKUTILS_RANGE_NO_SINGLE     (1u << 0)
4098 
4099 /**
4100  *    Allow a fully specified range "3-5" or a single value "3"
4101  *    (range_upper is set to range_lower).
4102  */
4103 #define SKUTILS_RANGE_NO_OPEN       (1u << 1)
4104 
4105 /**
4106  *    Only support a fully specified range "3-5"; i.e., the range must
4107  *    have both bounds.
4108  */
4109 #define SKUTILS_RANGE_ONLY_RANGE    (SKUTILS_RANGE_NO_SINGLE \
4110                                      | SKUTILS_RANGE_NO_OPEN)
4111 
4112 /**
4113  *    When a single value "3" is parsed, set range_upper to max_val as
4114  *    if an open-ended range had been specified.
4115  */
4116 #define SKUTILS_RANGE_MAX_SINGLE    (1u << 2)
4117 
4118 /**
4119  *    Attempts to parse the C-string 'range_string' as a range of two
4120  *    32-bit integers; that is, as a 32-bit integer representing the
4121  *    lower bound of the range, a hyphen '-', and the upper bound of
4122  *    the range.  The function sets 'range_lower' to the lower bound,
4123  *    and 'range_upper' to the upper bound.
4124  *
4125  *    The function also verifies that the bounds on the range fall
4126  *    between 'min_val' and 'max_val' inclusive.  A 'max_val' of 0 is
4127  *    equivalent to UINT32_MAX.
4128  *
4129  *    If flags does not contain 'SKUTILS_RANGE_NO_SINGLE', this
4130  *    function will also parse a single value, similar to
4131  *    skStringParseUint32().  When this occurs, both 'range_lower' and
4132  *    'range_upper' are set to the single value.  There is no way for
4133  *    the caller to tell whether the function parsed a single value
4134  *    '4' or a range where the bounds are identical '4-4'.
4135  *    SKUTILS_ERR_SHORT is returned when a single value is present and
4136  *    SKUTILS_RANGE_NO_SINGLE is specified.
4137  *
4138  *    If flags does not contain 'SKUTILS_RANGE_NO_OPEN', the upper
4139  *    bound of the range is optional.  That is, a 'range_string' of
4140  *    '5-' will result in the upper bound being set to 'max_val', or
4141  *    UINT32_MAX if 'max_val' is 0.  SKUTILS_ERR_SHORT is returned
4142  *    when an open-ended range is given and SKUTILS_RANGE_NO_OPEN is
4143  *    specified.
4144  *
4145  *    If flags contains 'SKUTILS_RANGE_MAX_SINGLE', the function sets
4146  *    range_upper to 'max_val' (or to UINT32_MAX if 'max_val' is 0)
4147  *    when a single value is parsed (as for an open-ended range).
4148  *
4149  *    Whitespace around the range will be ignored.  Whitespace within
4150  *    the range will result in SKUTILS_ERR_BAD_CHAR being returned.
4151  *
4152  *    Returns 0 on success, or a silk_utils_errcode_t value on error.
4153  */
4154 int
4155 skStringParseRange32(
4156     uint32_t           *range_lower,
4157     uint32_t           *range_upper,
4158     const char         *range_string,
4159     uint32_t            min_val,
4160     uint32_t            max_val,
4161     unsigned int        flags);
4162 
4163 
4164 /**
4165  *    As skStringParseRange32(), except that it attempts to parse the
4166  *    C-string 'range_string' as two unsigned 64-bit integers and a
4167  *    'max_val' of 0 represents UINT64_MAX.
4168  */
4169 int
4170 skStringParseRange64(
4171     uint64_t           *range_lower,
4172     uint64_t           *range_upper,
4173     const char         *range_string,
4174     uint64_t            min_val,
4175     uint64_t            max_val,
4176     unsigned int        flags);
4177 
4178 
4179 /**
4180  *    Attempts to parse the C string 'dbl_string' as a floating point
4181  *    value (double).  In addition, verifies that the value is between
4182  *    'min_val' and 'max_val' inclusive.  A 'max_val' of 0 is
4183  *    equivalent to HUGE_VAL.  Puts the result into location pointed
4184  *    to by 'result_val'.  Ignores any whitespace around the number.
4185  *
4186  *    Returns 0 and fills 'result_val' when 'dbl_string' contains only
4187  *    a number and whitespace and the number is parsable and the
4188  *    resulting value is within the limits.
4189  *
4190  *    Returns a positive value and fills 'result_val' when
4191  *    'dbl_string' contains a value within the limits and contains
4192  *    additional non-whitespace text.  The return value is the number
4193  *    of characters parsed, not including whitespace between the
4194  *    number and the additional text; e.g; "1.1 x" would set
4195  *    *result_val to 1.1 and return 3.
4196  *
4197  *    Returns an silk_utils_errcode_t value on error.  Note that "NaN"
4198  *    returns SKUTILS_ERR_BAD_CHAR.
4199  */
4200 int
4201 skStringParseDouble(
4202     double             *result_val,
4203     const char         *dbl_string,
4204     double              min_val,
4205     double              max_val);
4206 
4207 
4208 /**
4209  *    As skStringParseRange32(), except that it attempts to parse the
4210  *    C-string 'range_string' as two double values and a 'max_val' of
4211  *    0 represents HUGE_VAL.
4212  */
4213 int
4214 skStringParseDoubleRange(
4215     double             *range_lower,
4216     double             *range_upper,
4217     const char         *range_string,
4218     double              min_val,
4219     double              max_val,
4220     unsigned int        flags);
4221 
4222 
4223 
4224 
4225 /* TCP FLAGS HANDLING */
4226 
4227 /**
4228  *    Sets any high-flags in 'flags' to high in 'var'.  Other high-flags
4229  *    in 'var' are not affected.
4230  */
4231 #define TCP_FLAG_SET_FLAG( var, flags ) ((var) |= (flags))
4232 
4233 /**
4234  *    Returns 1 if the high-flags in 'flags' are also high in 'var';
4235  *    returns 0 otherwise.
4236  */
4237 #define TCP_FLAG_TEST( var, flags ) ( (((flag) & (var)) != 0) ? 1 : 0 )
4238 
4239 /**
4240  *    Returns 1 if, for all high-flags in 'mask', the only high-bits
4241  *    in 'var' are thost that are set in 'high'; return 0 otherwise.
4242  *    See skStringParseTCPFlagsHighMask() for details.
4243  */
4244 #define TCP_FLAG_TEST_HIGH_MASK( var, high, mask ) \
4245     ( (((var) & (mask)) == ((high) & (mask))) ? 1 : 0 )
4246 
4247 
4248 
4249 /**
4250  *    Parses the C-string 'flag_string' as a block of TCP flags and
4251  *    puts the value into the memory pointed at by 'result'.  Flag
4252  *    strings can only contain the following characters:
4253  *
4254  *        F f (FIN)
4255  *        S s (SYN)
4256  *        R r (RESET)
4257  *        P p (PUSH)
4258  *        A a (ACK)
4259  *        U u (URGENT)
4260  *        E e (ECE)
4261  *        C c (CWR)
4262  *
4263  *    Returns 0 when 'flag_string' contains valid TCP flag characters
4264  *    and whitespace.  Returns 0 and sets 'result' to 0 if the string
4265  *    is empty or contains only whitespace.
4266  *
4267  *    Otherwise, a silk_utils_errcode_t value is returned.
4268  */
4269 int
4270 skStringParseTCPFlags(
4271     uint8_t            *result,
4272     const char         *flag_string);
4273 
4274 
4275 /**
4276  *    Parses 'flag_string' as a HIGH/MASK pair of blocks of TCP flags.
4277  *    Both the HIGH and MASK portions of the string are flag strings,
4278  *    and are interpreted by skStringParseTCPFlags().
4279  *
4280  *    In a HIGH/MASK pair, the TCP flags listed in HIGH must be set;
4281  *    flags listed in MASK but not in HIGH must be low; flags not
4282  *    listed in MASK can have any value.  It is an error if a flag is
4283  *    listed in HIGH but not in MASK; that is, HIGH must be a subset
4284  *    of MASK.  For example: "AS/ASFR" means ACK,SYN must be high,
4285  *    FIN,RST must be low, and the other flags--PSH,URG,ECE,CWR--may
4286  *    have any value.
4287  *
4288  *    If successful, returns 0.  Otherwise, an silk_utils_errcode_t
4289  *    value is returned.
4290  *
4291  *    The inputs 'high' and 'mask' are overwritten with the bitmap of
4292  *    the flags set.
4293  *
4294  *    It is an error for any trailing text (other than whitespace) to
4295  *    follow the MASK.  Returns SKUTILS_ERR_SHORT if MASK has no
4296  *    value; returns SKUTILS_ERR_BAD_RANGE if HIGH is not a subset of
4297  *    MASK.
4298  */
4299 int
4300 skStringParseTCPFlagsHighMask(
4301     uint8_t            *high,
4302     uint8_t            *mask,
4303     const char         *flag_string);
4304 
4305 
4306 /*
4307  * flag definitions.
4308  */
4309 #define CWR_FLAG (1u << 7)      /* 128 */
4310 #define ECE_FLAG (1u << 6)      /*  64 */
4311 #define URG_FLAG (1u << 5)      /*  32 */
4312 #define ACK_FLAG (1u << 4)      /*  16 */
4313 #define PSH_FLAG (1u << 3)      /*   8 */
4314 #define RST_FLAG (1u << 2)      /*   4 */
4315 #define SYN_FLAG (1u << 1)      /*   2 */
4316 #define FIN_FLAG (1u << 0)      /*   1 */
4317 
4318 
4319 /**
4320  *    Parses the C-string 'flag_string' as a block of TCP state flags
4321  *    and puts the value into the memory pointed at by 'result'.  Flag
4322  *    strings can only contain the following characters:
4323  *
4324  *        T t (SK_TCPSTATE_TIMEOUT_KILLED)
4325  *        C c (SK_TCPSTATE_TIMEOUT_STARTED)
4326  *        F f (SK_TCPSTATE_FIN_FOLLOWED_NOT_ACK)
4327  *        S s (SK_TCPSTATE_UNIFORM_PACKET_SIZE)
4328  *
4329  *    Returns 0 when 'flag_string' contains valid TCP state flag
4330  *    characters and whitespace.  Returns 0 and sets 'result' to 0 if
4331  *    the string is empty or contains only whitespace.
4332  *
4333  *    Otherwise, a silk_utils_errcode_t value is returned.
4334  */
4335 int
4336 skStringParseTCPState(
4337     uint8_t            *result,
4338     const char         *flag_string);
4339 
4340 
4341 /**
4342  *    Parses 'flag_string' as a HIGH/MASK pair of blocks of TCP state
4343  *    flags.  Both the HIGH and MASK portions of the string are flag
4344  *    strings, and are interpreted by skStringParseTCPState().
4345  *
4346  *    In a HIGH/MASK pair, the TCP state flags listed in HIGH must be
4347  *    set; flags listed in MASK but not in HIGH must be low; flags not
4348  *    listed in MASK can have any value.  It is an error if a flag is
4349  *    listed in HIGH but not in MASK; that is, HIGH must be a subset
4350  *    of MASK.
4351  *
4352  *    If successful, returns 0.  Otherwise, an silk_utils_errcode_t
4353  *    value is returned.
4354  *
4355  *    The inputs 'high' and 'mask' are overwritten with the bitmap of
4356  *    the flags set.
4357  *
4358  *    It is an error for any trailing text (other than whitespace) to
4359  *    follow the MASK.  Returns SKUTILS_ERR_SHORT if MASK has no
4360  *    value; returns SKUTILS_ERR_BAD_RANGE if HIGH is not a subset of
4361  *    MASK.
4362  */
4363 int
4364 skStringParseTCPStateHighMask(
4365     uint8_t            *high,
4366     uint8_t            *mask,
4367     const char         *flag_string);
4368 
4369 
4370 /**
4371  *    Return the name of the signal that has the specified value.  The
4372  *    returned string does not include the "SIG" prefix.  For example,
4373  *    calling this function with the value 9 returns "KILL".
4374  *
4375  *    If 'signal_number' is not recognized as a signal, the return
4376  *    value is "?".
4377  */
4378 const char *
4379 skSignalToName(
4380     int                 signal_num);
4381 
4382 
4383 /**
4384  *    Parse 'signal_name' as either the name of a signal or the number
4385  *    of a signal.  The leading "SIG" on 'signal_name' is optional.
4386  *
4387  *    If the first non-whitespace chacter in 'signal_name' is a digit,
4388  *    the return value is similar to that for skStringParseUint32().
4389  *
4390  *    The function returns 0 if 'signal_name' only contains a signal
4391  *    name and optional leading and/or trailing whitespace.
4392  *
4393  *    A return value greater than 0 indicates that a signal name was
4394  *    parsed, but that additional text appears in the string.  The
4395  *    return value indicates the number of character that were parsed.
4396  *
4397  *    On error, the function returns one of the following values:
4398  *    SKUTILS_ERR_INVALID if an input value is NULL; SKUTILS_ERR_EMPTY
4399  *    if 'signal_name' contains only whitespace, or
4400  *    SKUTILS_ERR_BAD_CHAR if the string does not contain a valid
4401  *    signal name.
4402  */
4403 int
4404 skStringParseSignal(
4405     int                *signal_num,
4406     const char         *signal_name);
4407 
4408 
4409 #ifdef __cplusplus
4410 }
4411 #endif
4412 #endif /* _UTILS_H */
4413 
4414 /*
4415 ** Local Variables:
4416 ** mode:c
4417 ** indent-tabs-mode:nil
4418 ** c-basic-offset:4
4419 ** End:
4420 */
4421