From Harald Welte:
[obnox/wireshark/wip.git] / epan / tvbuff.h
index 8d5b443eb10b62abc0d69ada622c9da65483589d..3f9124e5a3b9c489cb30b4d6f5d26e51663d0bd3 100644 (file)
 #include <epan/guid-utils.h>
 #include "exceptions.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
 /** @file
  * "testy, virtual(-izable) buffer".  They are testy in that they get mad when
  * an attempt is made to access data beyond the bounds of their array. In that
@@ -50,7 +54,6 @@
  * virtual data.
  */
 
-
 /** The different types of tvbuff's */
 typedef enum {
        TVBUFF_REAL_DATA,
@@ -58,71 +61,32 @@ typedef enum {
        TVBUFF_COMPOSITE
 } tvbuff_type;
 
-typedef struct {
-       /** The backing tvbuff_t */
-       struct tvbuff   *tvb;
-
-       /** The offset of 'tvb' to which I'm privy */
-       guint           offset;
-       /** The length of 'tvb' to which I'm privy */
-       guint           length;
-
-} tvb_backing_t;
-
-typedef struct {
-       GSList          *tvbs;
-
-       /* Used for quick testing to see if this
-        * is the tvbuff that a COMPOSITE is
-        * interested in. */
-       guint           *start_offsets;
-       guint           *end_offsets;
-
-} tvb_comp_t;
-
-typedef void (*tvbuff_free_cb_t)(void*);
-
-typedef struct tvbuff {
-       /* Record-keeping */
-       tvbuff_type             type;
-       gboolean                initialized;
-       guint                   usage_count;
-       struct tvbuff           *ds_tvb;  /**< data source top-level tvbuff */
-
-       /** The tvbuffs in which this tvbuff is a member
-        * (that is, a backing tvbuff for a TVBUFF_SUBSET
-        * or a member for a TVB_COMPOSITE) */
-       GSList                  *used_in;
-
-       /** TVBUFF_SUBSET and TVBUFF_COMPOSITE keep track
-        * of the other tvbuff's they use */
-       union {
-               tvb_backing_t   subset;
-               tvb_comp_t      composite;
-       } tvbuffs;
-
-       /** We're either a TVBUFF_REAL_DATA or a
-        * TVBUFF_SUBSET that has a backing buffer that
-        * has real_data != NULL, or a TVBUFF_COMPOSITE
-        * which has flattened its data due to a call
-        * to tvb_get_ptr().
-        */
-       const guint8            *real_data;
-
-       /** Length of virtual buffer (and/or real_data). */
-       guint                   length;
-
-       /** Reported length. */
-       guint                   reported_length;
-
-       /* Offset from beginning of first TVBUFF_REAL. */
-       gint                    raw_offset;
-
-       /** Func to call when actually freed */
-       tvbuff_free_cb_t        free_cb;
-} tvbuff_t;
-
+struct tvbuff;
+typedef struct tvbuff tvbuff_t;
 
+/**
+ * tvbuffs: dissector use and management
+ *
+ *  Consider a collection of tvbs as being a chain or stack of tvbs.
+ *
+ *  The top-level dissector (packet.c) pushes the initial tvb onto the stack
+ *  (starts the chain) and then calls a sub-dissector which in turn calls the next
+ *  sub-dissector and so on. Each sub-dissector may chain additional tvbs to
+ *  the tvb handed to that dissector. After dissection is complete and control has
+ *  returned to the top-level dissector, the chain of tvbs (stack) is free'd
+ *  via a call to tvb_free_chain() (in epan_dissect_cleanup()).
+ *
+ * A dissector:
+ * - Can chain new tvbs (real, subset, composite) to the tvb
+ *    handed to the dissector via tvb_subset(), tvb_new_child_real_data(), etc.
+ *    (Subset and Composite tvbs should reference only tvbs which are
+ *    already part of the chain).
+ * - Must not save a pointer to a tvb handed to the dissector for
+ *    use when dissecting another frame; A higher level function
+ *    may very well free the chain). This also applies to any tvbs chained
+ *    by the dissector to the tvb handed to the dissector.
+ * - Can create its own tvb chain (using tvb_new_real_data() which
+ *    the dissector is free to manage as desired. */
 
 /** TVBUFF_REAL_DATA contains a guint8* that points to real data.
  * The data is allocated and contiguous.
@@ -140,64 +104,44 @@ typedef struct tvbuff {
  * Once a tvbuff is create/initialized/finalized, the tvbuff is read-only.
  * That is, it cannot point to any other data. A new tvbuff must be created if
  * you want a tvbuff that points to other data.
+ *
+ * tvbuff's are normally chained together to allow efficient de-allocation of tvbuff's.
+ *
  */
 
-
-/** "class" initialization. Called once during execution of program
- * so that tvbuff.c can initialize its data. */
-extern void tvbuff_init(void);
-
-/** "class" cleanup. Called once during execution of program
- * so that tvbuff.c can clean up its data. */
-extern void tvbuff_cleanup(void);
-
+typedef void (*tvbuff_free_cb_t)(void*);
 
 /** Returns a pointer to a newly initialized tvbuff. Note that
  * tvbuff's of types TVBUFF_SUBSET and TVBUFF_COMPOSITE
- * require further initialization via the appropriate functions */
+ * require further initialization via the appropriate functions. */
 extern tvbuff_t* tvb_new(tvbuff_type);
 
-/** Marks a tvbuff for freeing. The guint8* data of a TVBUFF_REAL_DATA
- * is *never* freed by the tvbuff routines. The tvbuff itself is actually freed
- * once its usage count drops to 0.
- *
- * Usage counts increment for any time the tvbuff is
- * used as a member of another tvbuff, i.e., as the backing buffer for
- * a TVBUFF_SUBSET or as a member of a TVBUFF_COMPOSITE.
- *
- * Although you may call tvb_free(), the tvbuff may still be in use
- * by other tvbuff's (TVBUFF_SUBSET or TVBUFF_COMPOSITE), so it is not
- * safe, unless you know otherwise, to free your guint8* data. If you
- * cannot be sure that your TVBUFF_REAL_DATA is not in use by another
- * tvbuff, register a callback with tvb_set_free_cb(); when your tvbuff
- * is _really_ freed, then your callback will be called, and at that time
- * you can free your original data.
- *
- * The caller can artificially increment/decrement the usage count
- * with tvbuff_increment_usage_count()/tvbuff_decrement_usage_count().
+/** Extracts 'number of bits' starting at 'bit offset'.
+ * Returns a pointer to a newly initialized ep_alloc'd REAL_DATA
+ * tvbuff with the bits octet aligned.
  */
+extern tvbuff_t* tvb_new_octet_aligned(tvbuff_t *tvb, guint32 bit_offset, gint32 no_of_bits);
+
+/** Free a tvbuff_t and all tvbuffs chained from it
+ * The tvbuff must be 'the 'head' (initial) tvb of a chain or
+ * must not be in a chain.
+ * If specified, a callback to free the tvbuff data will be invoked
+ * for each tvbuff free'd */
 extern void tvb_free(tvbuff_t*);
 
-/** Free the tvbuff_t and all tvbuff's created from it. */
+/** Free the tvbuff_t and all tvbuffs chained from it.
+ * The tvbuff must be 'the 'head' (initial) tvb of a chain or
+ * must not be in a chain.
+ * If specified, a callback to free the tvbuff data will be invoked
+ * for each tvbuff free'd */
 extern void tvb_free_chain(tvbuff_t*);
 
-/** Both return the new usage count, after the increment or decrement */
-extern guint tvb_increment_usage_count(tvbuff_t*, const guint count);
-
-/** If a decrement causes the usage count to drop to 0, a the tvbuff
- * is immediately freed. Be sure you know exactly what you're doing
- * if you decide to use this function, as another tvbuff could
- * still have a pointer to the just-freed tvbuff, causing corrupted data
- * or a segfault in the future */
-extern guint tvb_decrement_usage_count(tvbuff_t*, const guint count);
-
 /** Set a callback function to call when a tvbuff is actually freed
- * (once the usage count drops to 0). One argument is passed to
- * that callback --- a void* that points to the real data.
- * Obviously, this only applies to a TVBUFF_REAL_DATA tvbuff. */
+ * One argument is passed to that callback --- a void* that points
+ * to the real data. Obviously, this only applies to a
+ * TVBUFF_REAL_DATA tvbuff. */
 extern void tvb_set_free_cb(tvbuff_t*, const tvbuff_free_cb_t);
 
-
 /** Attach a TVBUFF_REAL_DATA tvbuff to a parent tvbuff. This connection
  * is used during a tvb_free_chain()... the "child" TVBUFF_REAL_DATA acts
  * as if is part of the chain-of-creation of the parent tvbuff, although it
@@ -205,22 +149,24 @@ extern void tvb_set_free_cb(tvbuff_t*, const tvbuff_free_cb_t);
  * run some operation on it, like decryption or decompression, and make a new
  * tvbuff from it, yet want the new tvbuff to be part of the chain. The reality
  * is that the new tvbuff *is* part of the "chain of creation", but in a way
- * that these tvbuff routines is ignorant of. Use this function to make
+ * that these tvbuff routines are ignorant of. Use this function to make
  * the tvbuff routines knowledgable of this fact. */
 extern void tvb_set_child_real_data_tvbuff(tvbuff_t* parent, tvbuff_t* child);
 
 extern tvbuff_t* tvb_new_child_real_data(tvbuff_t* parent, const guint8* data, const guint length,
     const gint reported_length);
 
-/**Sets parameters for TVBUFF_REAL_DATA. Can throw ReportedBoundsError. */
+/** Sets parameters for TVBUFF_REAL_DATA. Can throw ReportedBoundsError. */
 extern void tvb_set_real_data(tvbuff_t*, const guint8* data, const guint length,
     const gint reported_length);
 
-/** Combination of tvb_new() and tvb_set_real_data(). Can throw ReportedBoundsError. */
+/** Combination of tvb_new() and tvb_set_real_data(). Can throw ReportedBoundsError.
+ * Normally, a callback to free the data should be registered using tvb_set_free_cb();
+ * when this tvbuff is freed, then your callback will be called, and at that time
+ * you can free your original data. */
 extern tvbuff_t* tvb_new_real_data(const guint8* data, const guint length,
     const gint reported_length);
 
-
 /** Define the subset of the backing buffer to use.
  *
  * 'backing_offset' can be negative, to indicate bytes from
@@ -308,8 +254,7 @@ extern void tvb_set_reported_length(tvbuff_t*, const guint);
 extern guint tvb_offset_from_real_beginning(const tvbuff_t *tvb);
 
 /* Returns the offset from the first byte of real data. */
-#define TVB_RAW_OFFSET(tvb)                    \
-       ((tvb->raw_offset==-1)?(tvb->raw_offset = tvb_offset_from_real_beginning(tvb)):tvb->raw_offset)
+extern gint tvb_raw_offset(tvbuff_t *tvb);
 
 /************** START OF ACCESSORS ****************/
 /* All accessors will throw an exception if appropriate */
@@ -319,6 +264,9 @@ extern guint8  tvb_get_guint8(tvbuff_t*, const gint offset);
 extern guint16 tvb_get_ntohs(tvbuff_t*, const gint offset);
 extern guint32 tvb_get_ntoh24(tvbuff_t*, const gint offset);
 extern guint32 tvb_get_ntohl(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_ntoh40(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_ntoh48(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_ntoh56(tvbuff_t*, const gint offset);
 extern guint64 tvb_get_ntoh64(tvbuff_t*, const gint offset);
 extern gfloat tvb_get_ntohieee_float(tvbuff_t*, const gint offset);
 extern gdouble tvb_get_ntohieee_double(tvbuff_t*, const gint offset);
@@ -326,6 +274,9 @@ extern gdouble tvb_get_ntohieee_double(tvbuff_t*, const gint offset);
 extern guint16 tvb_get_letohs(tvbuff_t*, const gint offset);
 extern guint32 tvb_get_letoh24(tvbuff_t*, const gint offset);
 extern guint32 tvb_get_letohl(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_letoh40(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_letoh48(tvbuff_t*, const gint offset);
+extern guint64 tvb_get_letoh56(tvbuff_t*, const gint offset);
 extern guint64 tvb_get_letoh64(tvbuff_t*, const gint offset);
 extern gfloat tvb_get_letohieee_float(tvbuff_t*, const gint offset);
 extern gdouble tvb_get_letohieee_double(tvbuff_t*, const gint offset);
@@ -346,16 +297,20 @@ extern void tvb_get_guid(tvbuff_t *tvb, const gint offset, e_guid_t *guid, const
 
 /* Fetch a specified number of bits from bit offset in a tvb */
 extern guint8 tvb_get_bits8(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits);
-extern guint16 tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian);
-extern guint32 tvb_get_bits32(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian);
-extern guint64 tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const gboolean little_endian);
+extern guint16 tvb_get_bits16(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const guint encoding);
+extern guint32 tvb_get_bits32(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const guint encoding);
+extern guint64 tvb_get_bits64(tvbuff_t *tvb, gint bit_offset, const gint no_of_bits, const guint encoding);
 
-/* Fetch a specified number of bits from bit offset in a tvb, but allow number
+/**
+ * Fetch a specified number of bits from bit offset in a tvb, but allow number
  * of bits to range between 1 and 32. If the requested number of bits is known
  * beforehand, or its range can be handled by a single function of the group
  * above, use one of them instead.
  */
-extern guint32 tvb_get_bits(tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const gboolean little_endian);
+extern guint32 tvb_get_bits(tvbuff_t *tvb, const gint bit_offset, const gint no_of_bits, const guint encoding);
+
+void tvb_get_bits_buf(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, guint8 *buf, gboolean lsb0);
+guint8 *ep_tvb_get_bits(tvbuff_t *tvb, gint bit_offset, gint no_of_bits, gboolean lsb0);
 
 /** Returns target for convenience. Does not suffer from possible
  * expense of tvb_get_ptr(), since this routine is smart enough
@@ -438,6 +393,9 @@ extern gint tvb_strnlen(tvbuff_t*, const gint offset, const guint maxlength);
  * assuming all characters are ASCII  )-:  The len parameter is the number
  * of guint16's to convert from Unicode.
  *
+ * XXX - These functions have been superceded by tvb_get_unicode_string()
+ *       and tvb_get_ephemeral_unicode_string()
+ *
  * tvb_fake_unicode() returns a buffer allocated by g_malloc() and must
  *                    be g_free() by the caller.
  * tvb_get_ephemeral_faked_unicode() returns a buffer that does not need
@@ -486,16 +444,28 @@ extern gchar *tvb_format_stringzpad_wsp(tvbuff_t *tvb, const gint offset, const
  *                   MUST be g_free() by the caller in order not to leak
  *                   memory.
  *
+ * tvb_get_unicode_string() Unicode (UTF-16) version of above
+ *
  * tvb_get_ephemeral_string() returns a string that does not need to be freed,
  *                   instead it will automatically be freed once the next
  *                   packet is dissected.
  *
+ * tvb_get_ephemeral_string_enc() takes a string encoding as well, and
+ *                   converts to UTF-8 from the encoding (only UTF-8 and
+ *                   EBCDIC supported)
+ *
+ * tvb_get_ephemeral_unicode_string() Unicode (UTF-16) version of above
+ *
  * tvb_get_seasonal_string() returns a string that does not need to be freed,
  *                   instead it will automatically be freed when a new capture
  *                   or file is opened.
  */
 extern guint8 *tvb_get_string(tvbuff_t *tvb, const gint offset, const gint length);
+extern gchar  *tvb_get_unicode_string(tvbuff_t *tvb, const gint offset, gint length, const guint encoding);
 extern guint8 *tvb_get_ephemeral_string(tvbuff_t *tvb, const gint offset, const gint length);
+extern guint8 *tvb_get_ephemeral_string_enc(tvbuff_t *tvb, const gint offset,
+    const gint length, const gint encoding);
+extern gchar  *tvb_get_ephemeral_unicode_string(tvbuff_t *tvb, const gint offset, gint length, const guint encoding);
 extern guint8 *tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const gint length);
 
 
@@ -511,16 +481,35 @@ extern guint8 *tvb_get_seasonal_string(tvbuff_t *tvb, const gint offset, const g
  *                   MUST be g_free() by the caller in order not to leak
  *                   memory.
  *
+ * tvb_get_stringz_enc() takes a string encoding as well, and converts to
+ *                   UTF-8 from the encoding (only UTF-8 and EBCDIC supported)
+ *
+ * tvb_get_const_stringz() returns a constant (unmodifiable) string that does
+ *                   not need to be freed, instead it will automatically be
+ *                   freed once the next packet is dissected.  It is slightly
+ *                   more efficient than the other routines.
+ *
  * tvb_get_ephemeral_stringz() returns a string that does not need to be freed,
  *                   instead it will automatically be freed once the next
  *                   packet is dissected.
  *
+ * tvb_get_ephemeral_stringz_enc() takes a string encoding as well, and
+ *                   converts to UTF-8 from the encoding (only UTF-8 and
+ *                   EBCDIC supported)
+ *                   packet is dissected.
+ *
+ * tvb_get_ephemeral_unicode_stringz() Unicode (UTF-16) version of above
+ *
  * tvb_get_seasonal_stringz() returns a string that does not need to be freed,
  *                   instead it will automatically be freed when a new capture
  *                   or file is opened.
  */
 extern guint8 *tvb_get_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp);
+extern guint8 *tvb_get_stringz_enc(tvbuff_t *tvb, const gint offset, gint *lengthp, gint encoding);
+extern const guint8 *tvb_get_const_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp);
 extern guint8 *tvb_get_ephemeral_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp);
+extern guint8 *tvb_get_ephemeral_stringz_enc(tvbuff_t *tvb, const gint offset, gint *lengthp, gint encoding);
+extern gchar  *tvb_get_ephemeral_unicode_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp, const guint encoding);
 extern guint8 *tvb_get_seasonal_stringz(tvbuff_t *tvb, const gint offset, gint *lengthp);
 
 /** Looks for a stringz (NUL-terminated string) in tvbuff and copies
@@ -641,14 +630,30 @@ extern gint tvb_memeql(tvbuff_t *tvb, const gint offset, const guint8 *str,
 extern gchar *tvb_bytes_to_str_punct(tvbuff_t *tvb, const gint offset, const gint len,
     const gchar punct);
 
-/*
+/**
  * Format a bunch of data from a tvbuff as bytes, returning a pointer
  * to the string with the formatted data.
  */
 extern gchar *tvb_bytes_to_str(tvbuff_t *tvb, const gint offset, const gint len);
 
-#define TVB_GET_DS_TVB(tvb)            \
-       (tvb->ds_tvb)
+/**
+ * Given a tvbuff, an offset into the tvbuff, and a length that starts
+ * at that offset (which may be -1 for "all the way to the end of the
+ * tvbuff"), fetch BCD encoded digits from a tvbuff starting from either
+ * the low or high half byte, formating the digits according to an input digit set,
+ * if NUll a default digit set of 0-9 returning "?" for overdecadic digits will be used.
+ * A pointer to the EP allocated string will be returned.
+ * Note a tvbuff content of 0xf is considered a 'filler' and will end the conversion.
+ */
+typedef struct dgt_set_t
+{
+       const unsigned char out[15];
+}
+dgt_set_t;
+
+extern const gchar *tvb_bcd_dig_to_ep_str(tvbuff_t *tvb, const gint offset, const gint len, dgt_set_t *dgt, gboolean skip_first);
+
+struct tvbuff *tvb_get_ds_tvb(tvbuff_t *tvb);
 
 /** Locate a sub-tvbuff within another tvbuff, starting at position
  * 'haystack_offset'. Returns the index of the beginning of 'needle' within
@@ -673,4 +678,8 @@ extern tvbuff_t* tvb_child_uncompress(tvbuff_t *parent, tvbuff_t *tvb, const int
 
 /************** END OF ACCESSORS ****************/
 
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
 #endif /* __TVBUFF_H__ */