diff options
author | Guy Harris <gharris@sonic.net> | 2020-07-27 02:32:45 -0700 |
---|---|---|
committer | Guy Harris <gharris@sonic.net> | 2020-07-27 10:10:57 +0000 |
commit | c099892700eb03155548c06a9deb6c4f7b2bb570 (patch) | |
tree | 047685a4bdc1c8ebeb2691d4a916a2423d4f8379 /wiretap/iptrace.c | |
parent | a4ebc98fa4b2327e1ab2fa402c21585083a9a8ab (diff) |
iptrace: generate IDBs.
The packet information for a packet includes an interface name prefix
and an interface unit number (e.g., "en0", with a prefix of "en" and a
unit number of 0). Keep a hash table of prefixes, unit numbers, and
link-layer header types (as an interface must have only one link-layer
header type), and, for each packet, look up that information from the
packet information to get the interface ID; if that fails, construct a
new entry, with a new interface ID, and an IDB for the interface.
Change-Id: I3f2dafcc8926fe96fe4ffd6875f583397b1582b6
Reviewed-on: https://code.wireshark.org/review/37975
Petri-Dish: Guy Harris <gharris@sonic.net>
Tested-by: Petri Dish Buildbot
Reviewed-by: Guy Harris <gharris@sonic.net>
Diffstat (limited to 'wiretap/iptrace.c')
-rw-r--r-- | wiretap/iptrace.c | 213 |
1 files changed, 195 insertions, 18 deletions
diff --git a/wiretap/iptrace.c b/wiretap/iptrace.c index d4013e09a2..85c17ac5f2 100644 --- a/wiretap/iptrace.c +++ b/wiretap/iptrace.c @@ -15,9 +15,19 @@ #include "atm.h" #include "iptrace.h" +/* + * Private per-wtap_t data needed to read a file. + */ +typedef struct { + GHashTable *interface_ids; /* map name/description/link-layer type to interface ID */ + guint num_interface_ids; /* Number of interface IDs assigned */ +} iptrace_t; + #define IPTRACE_IFT_HF 0x3d /* Support for PERCS IP-HFI*/ #define IPTRACE_IFT_IB 0xc7 /* IP over Infiniband. Number by IANA */ +static void iptrace_close(wtap *wth); + static gboolean iptrace_read_1_0(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset); static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off, @@ -39,9 +49,49 @@ static int wtap_encap_ift(unsigned int ift); */ #define VERSION_STRING_SIZE 11 +/* + * Hash table to map interface name and description, and link-layer + * type, to interface ID. + */ +#define PREFIX_SIZE 4 + +typedef struct { + char prefix[PREFIX_SIZE+1]; + guint8 unit; + guint8 if_type; +} if_info; + +static gboolean destroy_if_info(gpointer key, gpointer value _U_, + gpointer user_data _U_) +{ + if_info *info = (if_info *)key; + + g_free(info); + + return TRUE; +} + +static guint if_info_hash(gconstpointer info_arg) +{ + if_info *info = (if_info *)info_arg; + + return g_str_hash(info->prefix) + info->unit + info->if_type; +} + +static gboolean if_info_equal(gconstpointer info1_arg, gconstpointer info2_arg) +{ + if_info *info1 = (if_info *)info1_arg; + if_info *info2 = (if_info *)info2_arg; + + return strcmp(info1->prefix, info2->prefix) == 0 && + info1->unit == info2->unit && + info1->if_type == info2->if_type; +} + wtap_open_return_val iptrace_open(wtap *wth, int *err, gchar **err_info) { char version_string[VERSION_STRING_SIZE+1]; + iptrace_t *iptrace; if (!wtap_read_bytes(wth->fh, version_string, VERSION_STRING_SIZE, err, err_info)) { @@ -67,9 +117,33 @@ wtap_open_return_val iptrace_open(wtap *wth, int *err, gchar **err_info) return WTAP_OPEN_NOT_MINE; } + /* This is an iptrace file */ + wth->subtype_close = iptrace_close; + iptrace = (iptrace_t *)g_malloc(sizeof(iptrace_t)); + iptrace->interface_ids = g_hash_table_new(if_info_hash, if_info_equal); + iptrace->num_interface_ids = 0; + wth->priv = (void *)iptrace; + return WTAP_OPEN_MINE; } +static void iptrace_close(wtap *wth) +{ + iptrace_t *iptrace = (iptrace_t *)wth->priv; + + g_hash_table_foreach_remove(iptrace->interface_ids, destroy_if_info, NULL); + g_hash_table_destroy(iptrace->interface_ids); +} + +static void add_new_if_info(iptrace_t *iptrace, if_info *info, gpointer *result) +{ + if_info *new_info = (if_info *)g_malloc(sizeof (if_info)); + *new_info = *info; + *result = GUINT_TO_POINTER(iptrace->num_interface_ids); + g_hash_table_insert(iptrace->interface_ids, (gpointer)new_info, *result); + iptrace->num_interface_ids++; +} + /*********************************************************** * iptrace 1.0 * ***********************************************************/ @@ -114,14 +188,16 @@ wtap_open_return_val iptrace_open(wtap *wth, int *err, gchar **err_info) #define IPTRACE_1_0_PINFO_SIZE 22 /* packet information */ static gboolean -iptrace_read_rec_1_0(FILE_T fh, wtap_rec *rec, Buffer *buf, +iptrace_read_rec_1_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) { + iptrace_t *iptrace = (iptrace_t *)wth->priv; guint8 header[IPTRACE_1_0_PHDR_SIZE]; guint32 record_length; guint8 pkt_info[IPTRACE_1_0_PINFO_SIZE]; - guint8 if_type; + if_info info; guint32 packet_size; + gpointer result; if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_1_0_PHDR_SIZE, err, err_info)) { @@ -156,12 +232,12 @@ iptrace_read_rec_1_0(FILE_T fh, wtap_rec *rec, Buffer *buf, * ifType value giving the type of the interface. Check out the * <net/if_types.h> header file. */ - if_type = pkt_info[IPTRACE_1_0_IF_TYPE_OFFSET]; - rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(if_type); + info.if_type = pkt_info[IPTRACE_1_0_IF_TYPE_OFFSET]; + rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type); if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported", - if_type); + info.if_type); return FALSE; } @@ -207,7 +283,7 @@ iptrace_read_rec_1_0(FILE_T fh, wtap_rec *rec, Buffer *buf, } rec->rec_type = REC_TYPE_PACKET; - rec->presence_flags = WTAP_HAS_TS; + rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID; rec->rec_header.packet_header.len = packet_size; rec->rec_header.packet_header.caplen = packet_size; rec->ts.secs = pntoh32(&header[IPTRACE_1_0_TV_SEC_OFFSET]); @@ -219,7 +295,55 @@ iptrace_read_rec_1_0(FILE_T fh, wtap_rec *rec, Buffer *buf, (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]); /* Get the packet data */ - return iptrace_read_rec_data(fh, buf, rec, err, err_info); + if (!iptrace_read_rec_data(fh, buf, rec, err, err_info)) + return FALSE; + + /* + * No errors - get the interface ID. + * + * We do *not* trust the name to be null-terminated. + */ + memcpy(info.prefix, &pkt_info[IPTRACE_1_0_PREFIX_OFFSET], + sizeof info.prefix); + info.prefix[PREFIX_SIZE] = '\0'; + info.unit = pkt_info[IPTRACE_1_0_UNIT_OFFSET]; + + /* + * Try to find the entry with that name, description, and + * interface type. + */ + if (!g_hash_table_lookup_extended(iptrace->interface_ids, + (gconstpointer)&info, NULL, &result)) { + wtap_block_t int_data; + wtapng_if_descr_mandatory_t *int_data_mand; + + /* + * Not found; make a new entry. + */ + add_new_if_info(iptrace, &info, &result); + + /* + * Now make a new IDB and add it. + */ + int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR); + int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data); + + int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap; + int_data_mand->tsprecision = WTAP_TSPREC_SEC; + int_data_mand->time_units_per_second = 1; /* No fractional time stamp */ + int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */ + + wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0); /* 1-second resolution */ + /* Interface statistics */ + int_data_mand->num_stat_entries = 0; + int_data_mand->interface_statistics = NULL; + + wtap_block_set_string_option_value_format(int_data, + OPT_IDB_NAME, "%s%u", info.prefix, info.unit); + wtap_add_idb(wth, int_data); + } + rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result); + return TRUE; } /* Read the next packet */ @@ -229,7 +353,7 @@ static gboolean iptrace_read_1_0(wtap *wth, wtap_rec *rec, *data_offset = file_tell(wth->fh); /* Read the packet */ - if (!iptrace_read_rec_1_0(wth->fh, rec, buf, err, err_info)) { + if (!iptrace_read_rec_1_0(wth, wth->fh, rec, buf, err, err_info)) { /* Read error or EOF */ return FALSE; } @@ -257,7 +381,8 @@ static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off, return FALSE; /* Read the packet */ - if (!iptrace_read_rec_1_0(wth->random_fh, rec, buf, err, err_info)) { + if (!iptrace_read_rec_1_0(wth, wth->random_fh, rec, buf, err, + err_info)) { if (*err == 0) *err = WTAP_ERR_SHORT_READ; return FALSE; @@ -287,6 +412,7 @@ static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off, * * the raw packet data. */ + /* * Offsets of fields in the initial header. */ @@ -311,14 +437,16 @@ static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off, #define IPTRACE_2_0_PINFO_SIZE 32 /* packet information */ static gboolean -iptrace_read_rec_2_0(FILE_T fh, wtap_rec *rec, Buffer *buf, +iptrace_read_rec_2_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) { + iptrace_t *iptrace = (iptrace_t *)wth->priv; guint8 header[IPTRACE_2_0_PHDR_SIZE]; guint32 record_length; guint8 pkt_info[IPTRACE_2_0_PINFO_SIZE]; - guint8 if_type; + if_info info; guint32 packet_size; + gpointer result; if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_2_0_PHDR_SIZE, err, err_info)) { @@ -353,8 +481,8 @@ iptrace_read_rec_2_0(FILE_T fh, wtap_rec *rec, Buffer *buf, * ifType value giving the type of the interface. Check out the * <net/if_types.h> header file. */ - if_type = pkt_info[IPTRACE_2_0_IF_TYPE_OFFSET]; - rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(if_type); + info.if_type = pkt_info[IPTRACE_2_0_IF_TYPE_OFFSET]; + rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type); #if 0 /* * We used to error out if the interface type in iptrace was @@ -375,7 +503,7 @@ iptrace_read_rec_2_0(FILE_T fh, wtap_rec *rec, Buffer *buf, if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported", - if_type); + info.if_type); return FALSE; } #endif @@ -422,7 +550,7 @@ iptrace_read_rec_2_0(FILE_T fh, wtap_rec *rec, Buffer *buf, } rec->rec_type = REC_TYPE_PACKET; - rec->presence_flags = WTAP_HAS_TS; + rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID; rec->rec_header.packet_header.len = packet_size; rec->rec_header.packet_header.caplen = packet_size; rec->ts.secs = pntoh32(&pkt_info[IPTRACE_2_0_TV_SEC_OFFSET]); @@ -434,7 +562,55 @@ iptrace_read_rec_2_0(FILE_T fh, wtap_rec *rec, Buffer *buf, (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]); /* Get the packet data */ - return iptrace_read_rec_data(fh, buf, rec, err, err_info); + if (!iptrace_read_rec_data(fh, buf, rec, err, err_info)) + return FALSE; + + /* + * No errors - get the interface ID. + * + * We do *not* trust the name to be null-terminated. + */ + memcpy(info.prefix, &pkt_info[IPTRACE_2_0_PREFIX_OFFSET], + sizeof info.prefix); + info.prefix[PREFIX_SIZE] = '\0'; + info.unit = pkt_info[IPTRACE_2_0_UNIT_OFFSET]; + + /* + * Try to find the entry with that name, description, and + * interface type. + */ + if (!g_hash_table_lookup_extended(iptrace->interface_ids, + (gconstpointer)&info, NULL, &result)) { + wtap_block_t int_data; + wtapng_if_descr_mandatory_t *int_data_mand; + + /* + * Not found; make a new entry. + */ + add_new_if_info(iptrace, &info, &result); + + /* + * Now make a new IDB and add it. + */ + int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR); + int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data); + + int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap; + int_data_mand->tsprecision = WTAP_TSPREC_NSEC; + int_data_mand->time_units_per_second = 1000000000; /* Nanosecond resolution */ + int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */ + + wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0x09); /* nanosecond resolution */ + /* Interface statistics */ + int_data_mand->num_stat_entries = 0; + int_data_mand->interface_statistics = NULL; + + wtap_block_set_string_option_value_format(int_data, + OPT_IDB_NAME, "%s%u", info.prefix, info.unit); + wtap_add_idb(wth, int_data); + } + rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result); + return TRUE; } /* Read the next packet */ @@ -444,7 +620,7 @@ static gboolean iptrace_read_2_0(wtap *wth, wtap_rec *rec, *data_offset = file_tell(wth->fh); /* Read the packet */ - if (!iptrace_read_rec_2_0(wth->fh, rec, buf, err, err_info)) { + if (!iptrace_read_rec_2_0(wth, wth->fh, rec, buf, err, err_info)) { /* Read error or EOF */ return FALSE; } @@ -472,7 +648,8 @@ static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off, return FALSE; /* Read the packet */ - if (!iptrace_read_rec_2_0(wth->random_fh, rec, buf, err, err_info)) { + if (!iptrace_read_rec_2_0(wth, wth->random_fh, rec, buf, err, + err_info)) { if (*err == 0) *err = WTAP_ERR_SHORT_READ; return FALSE; |