aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorAndersBroman <anders.broman@ericsson.com>2015-04-29 09:19:08 +0200
committerAnders Broman <a.broman58@gmail.com>2015-04-30 10:52:01 +0000
commit2d8b4a233e2c089b9736ad7ec2cea90438e6ad0f (patch)
tree06d238e8bf3b09c3449914d90e3621acf68816e1 /wiretap
parent58c890d93f5f3fc88ef99a2ba9ffaca1411b6b3c (diff)
Add the abillity to read 3GPP trace records with format accoding to
TS 32 423(XML) Change-Id: I37895ec35797089a32c7d1695e735046d6aa979e Reviewed-on: https://code.wireshark.org/review/8237 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/CMakeLists.txt1
-rw-r--r--wiretap/Makefile.common2
-rw-r--r--wiretap/file_access.c10
-rw-r--r--wiretap/nettrace_3gpp_32_423.c544
-rw-r--r--wiretap/nettrace_3gpp_32_423.h29
-rw-r--r--wiretap/wtap.h1
6 files changed, 586 insertions, 1 deletions
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt
index fc00413532..63a17c3667 100644
--- a/wiretap/CMakeLists.txt
+++ b/wiretap/CMakeLists.txt
@@ -60,6 +60,7 @@ set(WIRETAP_FILES
netscaler.c
netscreen.c
nettl.c
+ nettrace_3gpp_32_423.c
network_instruments.c
netxray.c
ngsniffer.c
diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common
index d5604adcdc..02c12145b2 100644
--- a/wiretap/Makefile.common
+++ b/wiretap/Makefile.common
@@ -65,6 +65,7 @@ NONGENERATED_C_FILES = \
netscaler.c \
netscreen.c \
nettl.c \
+ nettrace_3gpp_32_423.c \
network_instruments.c \
netxray.c \
ngsniffer.c \
@@ -125,6 +126,7 @@ NONGENERATED_HEADER_FILES = \
netscreen.h \
netscaler.h \
nettl.h \
+ nettrace_3gpp_32_423.h \
network_instruments.h \
netxray.h \
ngsniffer.h \
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 38536ebae2..0dfba98041 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -89,6 +89,7 @@
#include "stanag4607.h"
#include "capsa.h"
#include "pcap-encap.h"
+#include "nettrace_3gpp_32_423.h"
/*
* Add an extension, and all compressed versions thereof, to a GSList
@@ -340,7 +341,7 @@ static struct open_info open_info_base[] = {
{ "InfoVista 5View capture", OPEN_INFO_MAGIC, _5views_open, NULL, NULL, NULL },
{ "Network Instruments Observer", OPEN_INFO_MAGIC, network_instruments_open, NULL, NULL, NULL },
{ "WildPackets tagged", OPEN_INFO_MAGIC, peektagged_open, NULL, NULL, NULL },
- { "Colasoft Capsa", OPEN_INFO_MAGIC, capsa_open, NULL, NULL, NULL },
+ { "Colasoft Capsa", OPEN_INFO_MAGIC, capsa_open, NULL, NULL, NULL },
{ "DBS Etherwatch (VMS)", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL, NULL, NULL },
{ "Tektronix K12xx 32-bit .rf5 format", OPEN_INFO_MAGIC, k12_open, NULL, NULL, NULL },
{ "Catapult DCT2000 trace (.out format)", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL, NULL, NULL },
@@ -348,6 +349,8 @@ static struct open_info open_info_base[] = {
{ "Symbian OS btsnoop", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL, NULL },
{ "EyeSDN USB S0/E1 ISDN trace format", OPEN_INFO_MAGIC, eyesdn_open, NULL, NULL, NULL },
{ "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC, tnef_open, NULL, NULL, NULL },
+ /* 3GPP Nettrace must come before MIME Files as it's XML based*/
+ { "3GPP Nettrace 32 423 Format", OPEN_INFO_MAGIC, nettrace_3gpp_32_423_file_open, NULL, NULL, NULL },
{ "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL, NULL, NULL },
{ "Novell LANalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL, NULL },
/*
@@ -1598,6 +1601,11 @@ static const struct file_type_subtype_info dump_open_table_base[] = {
{ "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
TRUE, FALSE, 0,
nstrace_35_dump_can_write_encap, nstrace_dump_open, NULL },
+
+ /* WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 */
+ { "Nettrace 3GPP 32 423", "nettrace3gpp324423", NULL, NULL,
+ FALSE, FALSE, 0,
+ NULL, NULL, NULL },
};
gint wtap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct file_type_subtype_info);
diff --git a/wiretap/nettrace_3gpp_32_423.c b/wiretap/nettrace_3gpp_32_423.c
new file mode 100644
index 0000000000..0e1168463a
--- /dev/null
+++ b/wiretap/nettrace_3gpp_32_423.c
@@ -0,0 +1,544 @@
+/* nettrace_3gpp_32_423.c
+ *
+ * Decoder for 3GPP 32.423 file format for the Wiretap library.
+ * The main purpose is to have Wireshark decode raw message content (<rawMsg> tag).
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Ref: http://www.3gpp.org/DynaReport/32423.htm
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "wtap-int.h"
+#include "file_wrappers.h"
+#include "pcap-encap.h"
+
+#include <wsutil/buffer.h>
+#include "wsutil/tempfile.h"
+#include "wsutil/os_version_info.h"
+#include "wsutil/ws_version_info.h"
+#include "wsutil/str_util.h"
+
+
+#include "pcapng.h"
+#include "nettrace_3gpp_32_423.h"
+
+/*
+* Impose a not-too-large limit on the maximum file size, to avoid eating
+* up 99% of the (address space, swap partition, disk space for swap/page
+* files); if we were to return smaller chunks and let the dissector do
+* reassembly, it would *still* have to allocate a buffer the size of
+* the file, so it's not as if we'd never try to allocate a buffer the
+* size of the file. Laeve space for the exported PDU tag 12 bytes.
+*/
+#define MAX_FILE_SIZE (G_MAXINT-12)
+
+static const guint8 xml_magic[] = { '<', '?', 'x', 'm', 'l' };
+static const guint8 Threegpp_doc_no[] = { '3', '2', '.', '4', '2', '3' };
+
+typedef struct nettrace_3gpp_32_423_file_info {
+ char *tmpname;
+ wtap *wth_tmp_file;
+} nettrace_3gpp_32_423_file_info_t;
+
+
+static gboolean
+nettrace_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
+{
+ struct Buffer *frame_buffer_saved;
+ gboolean result;
+
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+
+ frame_buffer_saved = file_info->wth_tmp_file->frame_buffer;
+ file_info->wth_tmp_file->frame_buffer = wth->frame_buffer;
+ /* we read the created pcapng file instead */
+ result = wtap_read(file_info->wth_tmp_file, err, err_info, data_offset);
+ file_info->wth_tmp_file->frame_buffer = frame_buffer_saved;
+ if (!result)
+ return result;
+ wth->phdr.rec_type = file_info->wth_tmp_file->phdr.rec_type;
+ wth->phdr.presence_flags = file_info->wth_tmp_file->phdr.presence_flags;
+ wth->phdr.ts = file_info->wth_tmp_file->phdr.ts;
+ wth->phdr.caplen = file_info->wth_tmp_file->phdr.caplen;
+ wth->phdr.len = file_info->wth_tmp_file->phdr.len;
+ wth->phdr.pkt_encap = file_info->wth_tmp_file->phdr.pkt_encap;
+ wth->phdr.pkt_tsprec = file_info->wth_tmp_file->phdr.pkt_tsprec;
+ wth->phdr.interface_id = file_info->wth_tmp_file->phdr.interface_id;
+ wth->phdr.opt_comment = file_info->wth_tmp_file->phdr.opt_comment;
+ wth->phdr.drop_count = file_info->wth_tmp_file->phdr.drop_count;
+ wth->phdr.pack_flags = file_info->wth_tmp_file->phdr.pack_flags;
+ wth->phdr.ft_specific_data = file_info->wth_tmp_file->phdr.ft_specific_data;
+
+ return result;
+}
+
+static gboolean
+nettrace_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
+{
+ struct Buffer *frame_buffer_saved;
+ gboolean result;
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+
+ frame_buffer_saved = file_info->wth_tmp_file->frame_buffer;
+ file_info->wth_tmp_file->frame_buffer = wth->frame_buffer;
+
+ result = wtap_seek_read(file_info->wth_tmp_file, seek_off, phdr, buf, err, err_info);
+ file_info->wth_tmp_file->frame_buffer = frame_buffer_saved;
+
+ return result;
+}
+
+/* classic wtap: close capture file */
+static void
+nettrace_close(wtap *wth)
+{
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+
+ wtap_close(file_info->wth_tmp_file);
+
+ /*Clear the shb info, it's been freed by wtap_close*/
+ wth->shb_hdr.opt_comment = NULL;
+ wth->shb_hdr.shb_hardware = NULL;
+ wth->shb_hdr.shb_os = NULL;
+ wth->shb_hdr.shb_user_appl = NULL;
+
+ /* delete the temp file */
+ ws_unlink(file_info->tmpname);
+
+}
+
+/* Parsing something like
+ * <rawMsg
+ * protocol="Diameter"
+ * version="1">
+ * [truncated]010001244000012C01000...
+ * </rawMsg>
+ */
+static wtap_open_return_val
+write_packet_data(wtap_dumper *wdh, struct wtap_pkthdr *phdr, int *err, gchar **err_info, guint8 *file_buf)
+{
+ char *curr_pos, *next_pos;
+ char proto_name_str[16];
+ int tag_str_len = 0;
+ int proto_str_len, raw_data_len, pkt_data_len, exp_pdu_tags_len, i, j;
+ guint8 *packet_buf;
+ gchar chr;
+ gint val1, val2;
+
+ memset(proto_name_str, 0, sizeof(proto_name_str));
+ /* Extract the protocol name */
+ curr_pos = strstr(file_buf, "protocol=\"");
+ if (!curr_pos){
+ return WTAP_OPEN_ERROR;
+ }
+ curr_pos = curr_pos + 10;
+ next_pos = strstr(curr_pos, "\"");
+ proto_str_len = (int)(next_pos - curr_pos);
+ if (proto_str_len > 15){
+ return WTAP_OPEN_ERROR;
+ }
+
+ g_strlcpy(proto_name_str, curr_pos, proto_str_len+1);
+ ascii_strdown_inplace(proto_name_str);
+
+ /* Do string matching and replace with Wiresharks protocol name */
+ if (strcmp(proto_name_str, "gtpv2-c") == 0){
+ /* Change to gtpv2 */
+ proto_name_str[5] = '\0';
+ proto_name_str[6] = '\0';
+ proto_str_len = 5;
+ }
+ /* XXX Do we need to check for function="S1" */
+ if (strcmp(proto_name_str, "nas") == 0){
+ /* Change to nas-eps_plain */
+ g_strlcpy(proto_name_str, "nas-eps_plain", 14);
+ proto_name_str[13] = '\0';
+ proto_str_len = 13;
+ }
+ /* Find the start of the raw data*/
+ curr_pos = strstr(next_pos, ">") + 1;
+ next_pos = strstr(next_pos, "<");
+
+ raw_data_len = (int)(next_pos - curr_pos);
+
+ /* Calculate the space needed for exp pdu tags*/
+ tag_str_len = (proto_str_len + 3) & 0xfffffffc;
+ exp_pdu_tags_len = tag_str_len + 4;
+
+
+ /* Allocate the packet buf */
+ pkt_data_len = raw_data_len / 2;
+ packet_buf = (guint8 *)g_malloc0(pkt_data_len + exp_pdu_tags_len +4);
+
+ /* Fill packet buff */
+ packet_buf[0] = 0;
+ packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
+ packet_buf[2] = 0;
+ packet_buf[3] = tag_str_len;
+ i = 4;
+ for (i = 4, j = 0; j < tag_str_len; i++, j++){
+ packet_buf[i] = proto_name_str[j];
+ }
+
+ /* Add end of options */
+ packet_buf[i] = 0;
+ i++;
+ packet_buf[i] = 0;
+ i++;
+ packet_buf[i] = 0;
+ i++;
+ packet_buf[i] = 0;
+ i++;
+ exp_pdu_tags_len = exp_pdu_tags_len + 4;
+
+ /* Convert the hex raw msg data to binary and write to the packet buf*/
+ for (; i < (pkt_data_len + exp_pdu_tags_len); i++){
+ chr = *curr_pos;
+ val1 = g_ascii_xdigit_value(chr);
+ curr_pos++;
+ chr = *curr_pos;
+ val2 = g_ascii_xdigit_value(chr);
+ if ((val1 != -1) && (val2 != -1)){
+ packet_buf[i] = ((guint8)val1 * 16) + val2;
+ }
+ else{
+ /* Something wrong, bail out */
+ g_free(packet_buf);
+ return WTAP_OPEN_ERROR;
+ }
+ curr_pos++;
+ }
+ /* Construct the phdr */
+ memset(phdr, 0, sizeof(struct wtap_pkthdr));
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
+
+ phdr->caplen = pkt_data_len + exp_pdu_tags_len;
+ phdr->len = pkt_data_len + exp_pdu_tags_len;
+
+ phdr->ts.secs = 0;
+ phdr->ts.nsecs = 0;
+
+ if (!wtap_dump(wdh, phdr, packet_buf, err, err_info)) {
+ switch (*err) {
+
+ case WTAP_ERR_UNWRITABLE_REC_DATA:
+ g_free(err_info);
+ break;
+
+ default:
+ break;
+ }
+ g_free(packet_buf);
+ return WTAP_OPEN_ERROR;
+ }
+
+ g_free(packet_buf);
+ return WTAP_OPEN_MINE;
+}
+
+/*
+ * Opens an .xml file with Trace data formated according to 3GPP TS 32.423 and converts it to
+ * an "Exported PDU type file with the entire xml file as the first "packet" appending the
+ * raw messages as subsequent packages to be dissected by wireshark.
+ */
+static wtap_open_return_val
+create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_423_file_info_t *file_info)
+{
+ int import_file_fd;
+ wtap_dumper* wdh_exp_pdu;
+ int exp_pdu_file_err;
+
+ /* pcapng defs */
+ wtapng_section_t *shb_hdr;
+ wtapng_iface_descriptions_t *idb_inf;
+ wtapng_if_descr_t int_data;
+ GString *os_info_str;
+ char *appname;
+ gint64 file_size;
+ int packet_size;
+ guint8 *packet_buf;
+ int wrt_err;
+ gchar *wrt_err_info;
+ struct wtap_pkthdr phdr;
+
+ gboolean random = FALSE;
+ char *curr_pos, *next_pos;
+
+ import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_");
+
+ /* Now open a file and dump to it */
+ /* Create data for SHB */
+ os_info_str = g_string_new("");
+ get_os_version_info(os_info_str);
+
+ appname = g_strdup_printf("Wireshark %s", get_ws_vcs_version_info());
+
+ shb_hdr = g_new(wtapng_section_t, 1);
+ shb_hdr->section_length = -1;
+ /* options */
+ shb_hdr->opt_comment = g_strdup_printf("File converted to Exported PDU format during opening");
+ /*
+ * UTF-8 string containing the description of the hardware used to create
+ * this section.
+ */
+ shb_hdr->shb_hardware = NULL;
+ /*
+ * UTF-8 string containing the name of the operating system used to create
+ * this section.
+ */
+ shb_hdr->shb_os = g_string_free(os_info_str, FALSE);
+ /*
+ * UTF-8 string containing the name of the application used to create
+ * this section.
+ */
+ shb_hdr->shb_user_appl = appname;
+
+ /* Create fake IDB info */
+ idb_inf = g_new(wtapng_iface_descriptions_t, 1);
+ idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
+
+ /* create the fake interface data */
+ int_data.wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
+ int_data.time_units_per_second = 1000000; /* default microsecond resolution */
+ int_data.link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
+ int_data.snap_len = WTAP_MAX_PACKET_SIZE;
+ int_data.if_name = g_strdup("Fake IF");
+ int_data.opt_comment = NULL;
+ int_data.if_description = NULL;
+ int_data.if_speed = 0;
+ int_data.if_tsresol = 6;
+ int_data.if_filter_str = NULL;
+ int_data.bpf_filter_len = 0;
+ int_data.if_filter_bpf_bytes = NULL;
+ int_data.if_os = NULL;
+ int_data.if_fcslen = -1;
+ int_data.num_stat_entries = 0; /* Number of ISB:s */
+ int_data.interface_statistics = NULL;
+
+ g_array_append_val(idb_inf->interface_data, int_data);
+
+ wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU, WTAP_MAX_PACKET_SIZE, FALSE, shb_hdr, idb_inf, &exp_pdu_file_err);
+ if (wdh_exp_pdu == NULL) {
+ return WTAP_OPEN_ERROR;
+ }
+
+ g_free(shb_hdr);
+ g_free(appname);
+
+ /* OK we've opend a new pcap-ng file and written the headers, time to do the packets, strt by finding the file size */
+
+ if ((file_size = wtap_file_size(wth, err)) == -1)
+ return WTAP_OPEN_ERROR;
+
+ if (file_size > MAX_FILE_SIZE) {
+ /*
+ * Don't blow up trying to allocate space for an
+ * immensely-large file.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
+ file_size, MAX_FILE_SIZE);
+ return WTAP_OPEN_ERROR;
+ }
+ packet_size = (int)file_size;
+ /* Allocate the packet buffer
+ * (the whole file + Exported PDU tag "protocol" and
+ * the string "xml" + 1 filler to end on 4 byte boundary for the tag
+ * + End of options 4 bytes
+ */
+ /* XXX add the length of exported bdu tag(s) here */
+ packet_buf = (guint8 *)g_malloc(packet_size + 12);
+
+ packet_buf[0] = 0;
+ packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
+ packet_buf[2] = 0;
+ packet_buf[3] = 4;
+ packet_buf[4] = 0x78; /* "x" */
+ packet_buf[5] = 0x6d; /* "m" */
+ packet_buf[6] = 0x6c; /* "l" */
+ packet_buf[7] = 0;
+ /* End of options */
+ packet_buf[8] = 0;
+ packet_buf[9] = 0;
+ packet_buf[10] = 0;
+ packet_buf[11] = 0;
+
+
+ if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
+ return WTAP_OPEN_ERROR;
+ }
+
+ /* Create the packet header */
+ memset(&phdr, 0, sizeof(struct wtap_pkthdr));
+ phdr.rec_type = REC_TYPE_PACKET;
+ phdr.presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
+
+ phdr.caplen = packet_size + 12;
+ phdr.len = packet_size + 12;
+
+ phdr.ts.secs = 0;
+ phdr.ts.nsecs = 0;
+
+ /* XXX: report errors! */
+ if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
+ switch (wrt_err) {
+
+ case WTAP_ERR_UNWRITABLE_REC_DATA:
+ g_free(wrt_err_info);
+ break;
+
+ default:
+ break;
+ }
+ g_free(packet_buf);
+ return WTAP_OPEN_ERROR;
+ }
+
+ /* Advance *packet_buf to point at the raw file data */
+ curr_pos = packet_buf + 12;
+ /* Lets add the raw messages as packets after the main "packet" with the whole file */
+ while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
+ wtap_open_return_val temp_val;
+
+ curr_pos = curr_pos + 4;
+ next_pos = strstr(curr_pos, "</msg>");
+ if (!next_pos){
+ /* Somethings wrong, bail out */
+ break;
+ }
+ next_pos = next_pos + 6;
+ /* Do we have a raw msg?) */
+ curr_pos = strstr(curr_pos, "<rawMsg");
+ if (!curr_pos){
+ /* No rawMsg, continue */
+ curr_pos = next_pos;
+ continue;
+ }
+ curr_pos = curr_pos + 7;
+ /* Add the raw msg*/
+ temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos);
+ if (temp_val != WTAP_OPEN_MINE){
+ g_free(packet_buf);
+ return temp_val;
+ }
+ curr_pos = next_pos;
+ }
+
+ /* Close the written file*/
+ if (!wtap_dump_close(wdh_exp_pdu, err)){
+ g_free(packet_buf);
+ return WTAP_OPEN_ERROR;
+ }
+
+ g_free(packet_buf);
+ /* Now open the file for reading */
+
+ /* Find out if random read was requested */
+ if (wth->random_fh){
+ random = TRUE;
+ }
+ file_info->wth_tmp_file =
+ wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, random);
+
+ if (!file_info->wth_tmp_file){
+ return WTAP_OPEN_ERROR;
+ }
+
+ return WTAP_OPEN_MINE;
+}
+
+wtap_open_return_val
+nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
+{
+ char magic_buf[512]; /* increase buffer size when needed */
+ int bytes_read;
+ char *curr_pos;
+ nettrace_3gpp_32_423_file_info_t *file_info;
+ wtap_open_return_val temp_val;
+
+
+ bytes_read = file_read(magic_buf, 512, wth->fh);
+
+ if (bytes_read < 0) {
+ *err = file_error(wth->fh, err_info);
+ return WTAP_OPEN_ERROR;
+ }
+ if (bytes_read == 0){
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
+ return WTAP_OPEN_NOT_MINE;
+ }
+ /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
+ curr_pos = strstr(magic_buf, "fileFormatVersion");
+
+ if (!curr_pos){
+ return WTAP_OPEN_NOT_MINE;
+ }
+ curr_pos += 19;
+ if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
+ return WTAP_OPEN_NOT_MINE;
+ }
+
+ if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
+ return WTAP_OPEN_ERROR;
+
+ /* Ok it's our file, open a temp file and do the conversion */
+ file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
+ temp_val = create_temp_pcapng_file(wth, err, err_info, file_info);
+
+ if (temp_val != WTAP_OPEN_MINE){
+ return temp_val;
+ }
+
+ if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
+ return WTAP_OPEN_ERROR;
+
+ /* Copy data from the temp file wth */
+ wth->shb_hdr.opt_comment = file_info->wth_tmp_file->shb_hdr.opt_comment;
+ wth->shb_hdr.shb_hardware = file_info->wth_tmp_file->shb_hdr.shb_hardware;
+ wth->shb_hdr.shb_os = file_info->wth_tmp_file->shb_hdr.shb_os;
+ wth->shb_hdr.shb_user_appl = file_info->wth_tmp_file->shb_hdr.shb_user_appl;
+
+ wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423;
+ wth->file_encap = file_info->wth_tmp_file->file_encap;
+ wth->file_tsprec = file_info->wth_tmp_file->file_tsprec;
+ wth->subtype_read = nettrace_read;
+ wth->subtype_seek_read = nettrace_seek_read;
+ wth->subtype_close = nettrace_close;
+ wth->snapshot_length = 0;
+
+ wth->priv = (void*)file_info;
+
+ return WTAP_OPEN_MINE;
+
+}
diff --git a/wiretap/nettrace_3gpp_32_423.h b/wiretap/nettrace_3gpp_32_423.h
new file mode 100644
index 0000000000..2e7d978b2c
--- /dev/null
+++ b/wiretap/nettrace_3gpp_32_423.h
@@ -0,0 +1,29 @@
+/* nettrace_3gpp_32_423.h
+ *
+ * MIME file format decoder for the Wiretap library.
+ *
+ * Wiretap Library
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __NETTRACE_3GPP_32_423__
+#define __NETTRACE_3GPP_32_423__
+
+#include <glib.h>
+#include <wtap.h>
+
+wtap_open_return_val nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info);
+
+#endif
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index 0f257ba275..ece8c7ed23 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -352,6 +352,7 @@ extern "C" {
#define WTAP_FILE_TYPE_SUBTYPE_COLASOFT_PACKET_BUILDER 76
#define WTAP_FILE_TYPE_SUBTYPE_JSON 77
#define WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5 78
+#define WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423 79
#define WTAP_NUM_FILE_TYPES_SUBTYPES wtap_get_num_file_types_subtypes()