aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/nettrace_3gpp_32_423.c
diff options
context:
space:
mode:
authorDavid Perry <boolean263@protonmail.com>2021-01-04 15:20:27 +0000
committerAndersBroman <a.broman58@gmail.com>2021-01-04 15:20:27 +0000
commit718cff5264a514e5c666b6599c4be1b8810a0614 (patch)
treee2eff54c2e82dacb4c93408f6d3a8207d48ff02b /wiretap/nettrace_3gpp_32_423.c
parent84eeeabde98025971c4fd9c0eccbf516856123e3 (diff)
Initial refactor of nettrace reader (#17009)
Old behaviour is to read the entire file into memory at once; provide the XML tree as the first packet; and then individual `<msg>` elements as subsequent packets. It did this by writing to a temporary pcapng file. This change causes the XML file to only be read a chunk at a time (and be read directly, not through an intermediate pcapng). This means much larger files can be loaded, at the cost of no longer showing the raw XML as the first packet. This is not a loss because the file can be loaded in MIME Files Format (or a text editor) to see the XML. Much of the logic from the old functions `create_temp_pcapng_file()` and `write_packet_data()` has been relocated into the new function `nettrace_msg_to_packet()`, and is used to directly generate packet data for wiretap instead of writing it to a temporary file. Also includes some initial "code smell" fixes: - Removed some duplicate `#define`s from epan/exported_pdu.h - Replaces some magic numbers with macros from epan/exported_pdu.h - Replaces other magic numbers with the CLEN() macro to make it easier to see (and debug) where sizes/offsets come from - Use `g_strstr_len()` instead of `strstr()` to remove the need to insert string terminators - Uses direct pointer math instead of indexing into a byte array This compiles and runs, and seems to produce the same results as the old reader (except for the XML packet). Consider it a proof of concept; it needs further revision before being review-ready.
Diffstat (limited to 'wiretap/nettrace_3gpp_32_423.c')
-rw-r--r--wiretap/nettrace_3gpp_32_423.c1638
1 files changed, 692 insertions, 946 deletions
diff --git a/wiretap/nettrace_3gpp_32_423.c b/wiretap/nettrace_3gpp_32_423.c
index 8d3e499a42..825b7c1805 100644
--- a/wiretap/nettrace_3gpp_32_423.c
+++ b/wiretap/nettrace_3gpp_32_423.c
@@ -25,6 +25,7 @@
#include "file_wrappers.h"
#include "pcap-encap.h"
+#include <epan/exported_pdu.h>
#include <wsutil/buffer.h>
#include "wsutil/tempfile.h"
#include "wsutil/os_version_info.h"
@@ -35,607 +36,584 @@
#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)
+/* String constants sought in the XML data.
+ * Written as strings instead of lists of chars for readability.
+ * Use the CLEN() macro to get the length of the constant without counting
+ * the null byte at the end.
+ */
+#define CLEN(x) (sizeof(x)-1)
+static const guchar c_xml_magic[] = "<?xml";
+static const guchar c_file_header[] = "<fileHeader";
+static const guchar c_file_format_version[] = "fileFormatVersion=\"";
+static const guchar c_threegpp_doc_no[] = "32.423";
+static const guchar c_begin_time[] = "<traceCollec beginTime=\"";
+static const guchar c_s_msg[] = "<msg";
+static const guchar c_e_msg[] = "</msg>";
+static const guchar c_s_rawmsg[] = "<rawMsg";
+static const guchar c_change_time[] = "changeTime=\"";
+static const guchar c_proto_name[] = "name=\"";
+static const guchar c_address[] = "ddress"; /* omit the 'a' to cater for "Address" */
+static const guchar c_s_initiator[] = "<initiator";
+static const guchar c_e_initiator[] = "</initiator>";
+static const guchar c_s_target[] = "<target";
+static const guchar c_e_target[] = "</target>";
+static const guchar c_protocol[] = "protocol=\"";
+
+/* These are protocol names we may put in the exported-pdu data based on
+ * what's in the XML. They're defined here as constants so we can use
+ * sizeof()/CLEN() on them and slightly reduce our use of magic constants
+ * for their size. (Modern compilers should make this no slower than that.)
+ */
+static const guchar c_sai_req[] = "gsm_map.v3.arg.opcode";
+static const guchar c_sai_rsp[] = "gsm_map.v3.res.opcode";
+static const guchar c_nas_eps[] = "nas-eps_plain";
+
+#define RINGBUFFER_START_SIZE G_MAXINT
+#define RINGBUFFER_CHUNK_SIZE 1024
-static const guint8 xml_magic[] = { '<', '?', 'x', 'm', 'l' };
-static const guint8 Threegpp_doc_no[] = { '3', '2', '.', '4', '2', '3' };
+#define MAX_NAME_LEN 64
+#define MAX_PROTO_LEN 16
+#define MAX_DTBL_LEN 32
+
+/* We expect to find all the info we need to tell if this file is ours
+ * within this many bytes. Must include the beginTime attribute.
+ */
+#define MAGIC_BUF_SIZE 1024
typedef struct nettrace_3gpp_32_423_file_info {
- char *tmpname;
- wtap *wth_tmp_file;
+ GByteArray *buffer; // holds current chunk of file
+ gint64 start_offset; // where in the file the start of the buffer points
+ nstime_t start_time; // from <traceCollec beginTime=""> attribute
} nettrace_3gpp_32_423_file_info_t;
-/* From epan/exported_pdu.h
- Port types are no longer used for conversation/endpoints so
- many of the enumerated values have been eliminated
- Since export PDU functionality is serializing them,
- keep the old values around for conversion */
-#define OLD_PT_NONE 0
-#define OLD_PT_SCTP 1
-#define OLD_PT_TCP 2
-#define OLD_PT_UDP 3
-#define OLD_PT_DCCP 4
-#define OLD_PT_IPX 5
-#define OLD_PT_NCP 6
-#define OLD_PT_EXCHG 7
-#define OLD_PT_DDP 8
-#define OLD_PT_SBCCS 9
-#define OLD_PT_IDP 10
-#define OLD_PT_TIPC 11
-#define OLD_PT_USB 12
-#define OLD_PT_I2C 13
-#define OLD_PT_IBQP 14
-#define OLD_PT_BLUETOOTH 15
-#define OLD_PT_TDMOP 16
-
typedef struct exported_pdu_info {
- guint32 precense_flags;
- /*const char* proto_name;*/
+ guint32 presence_flags;
guint8 src_ip[16];
guint32 ptype; /* Based on epan/address.h port_type valid for both src and dst*/
guint32 src_port;
guint8 dst_ip[16];
guint32 dst_port;
char* proto_col_str;
-}exported_pdu_info_t ;
-
-/* From epan/epxported_pdu.h*/
-#define EXP_PDU_TAG_END_OF_OPT 0 /**< End-of-options Tag. */
-/* 1 - 9 reserved */
-#define EXP_PDU_TAG_OPTIONS_LENGTH 10 /**< Total length of the options excluding this TLV */
-#define EXP_PDU_TAG_PROTO_NAME 12 /**< The value part should be an ASCII non NULL terminated string
-* of the registered dissector used by Wireshark e.g "sip"
-* Will be used to call the next dissector.
-*/
-#define EXP_PDU_TAG_DISSECTOR_TABLE_NAME 14 /**< The value part should be an ASCII non NULL terminated string
-* containing the dissector table name given
-* during registration, e.g "gsm_map.v3.arg.opcode"
-* Will be used to call the next dissector.
-*/
-
-#define EXP_PDU_TAG_IPV4_SRC 20
-#define EXP_PDU_TAG_IPV4_DST 21
-#define EXP_PDU_TAG_IPV6_SRC 22
-#define EXP_PDU_TAG_IPV6_DST 23
-#define EXP_PDU_TAG_SRC_PORT 25
-#define EXP_PDU_TAG_PORT_TYPE 24 /**< value part is port_type enum from epan/address.h */
-#define EXP_PDU_TAG_DST_PORT 26
-#define EXP_PDU_TAG_SS7_OPC 28
-#define EXP_PDU_TAG_SS7_DPC 29
-
-#define EXP_PDU_TAG_ORIG_FNO 30
-
-#define EXP_PDU_TAG_DVBCI_EVT 31
-
-#define EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL 32 /**< value part is the numeric value to be used calling the dissector table
-* given with tag EXP_PDU_TAG_DISSECTOR_TABLE_NAME, must follow emediatly after the table tag.
-*/
-
-#define EXP_PDU_TAG_COL_PROT_TEXT 33 /**< Text string to put in COL_PROTOCOL, one use case is in conjunction with dissector tables where
-* COL_PROTOCOL might not be filled in.
-*/
+} exported_pdu_info_t;
+
+/* flags for exported_pdu_info.presence_flags */
+#define EXP_PDU_TAG_IP_SRC_BIT 0x001
+#define EXP_PDU_TAG_IP_DST_BIT 0x002
+#define EXP_PDU_TAG_SRC_PORT_BIT 0x004
+#define EXP_PDU_TAG_DST_PORT_BIT 0x008
+#define EXP_PDU_TAG_ORIG_FNO_BIT 0x010
+#define EXP_PDU_TAG_SS7_OPC_BIT 0x020
+#define EXP_PDU_TAG_SS7_DPC_BIT 0x040
+#define EXP_PDU_TAG_IP6_SRC_BIT 0x080
+#define EXP_PDU_TAG_IP6_DST_BIT 0x100
+#define EXP_PDU_TAG_DVBCI_EVT_BIT 0x0100
+#define EXP_PDU_TAG_COL_PROT_BIT 0x0200
+
+
+/* Parse a string IPv4 or IPv6 address into bytes for exported_pdu_info.
+ * Also parses the port pairs and transport layer type.
+ */
+static char*
+nettrace_parse_address(char* curr_pos, char* next_pos, gboolean is_src_addr, exported_pdu_info_t *exported_pdu_info)
+{
+ guint port;
+ char transp_str[5];
+ int scan_found;
+ char str[3];
+ char* end_pos, *skip_pos;
+ char ip_addr_str[WS_INET6_ADDRSTRLEN];
+ int str_len;
+ ws_in6_addr ip6_addr;
+ guint32 ip4_addr;
+ gchar tempchar;
-#define EXP_PDU_TAG_IP_SRC_BIT 0x001
-#define EXP_PDU_TAG_IP_DST_BIT 0x002
-#define EXP_PDU_TAG_SRC_PORT_BIT 0x004
-#define EXP_PDU_TAG_DST_PORT_BIT 0x008
-#define EXP_PDU_TAG_ORIG_FNO_BIT 0x010
-#define EXP_PDU_TAG_SS7_OPC_BIT 0x020
-#define EXP_PDU_TAG_SS7_DPC_BIT 0x040
-#define EXP_PDU_TAG_IP6_SRC_BIT 0x080
-#define EXP_PDU_TAG_IP6_DST_BIT 0x100
+ /* curr_pos pointing to first char after address */
-/* 2nd byte of optional tags bitmap */
-#define EXP_PDU_TAG_DVBCI_EVT_BIT 0x0100
-#define EXP_PDU_TAG_COL_PROT_BIT 0x0200
+ /* Excample from one trace, unsure if it's generic...
+ * {address == 192.168.73.1, port == 5062, transport == Udp}
+ * {address == [2001:1b70:8294:210a::78], port...
+ * {address == 2001:1B70:8294:210A::90, port...
+ * Address=198.142.204.199,Port=2123
+ */
+ /* Skip whitespace and equalsigns) */
+ for (skip_pos = curr_pos; skip_pos < next_pos &&
+ ((tempchar = *skip_pos) == ' ' ||
+ tempchar == '\t' || tempchar == '\r' || tempchar == '\n' || tempchar == '=');
+ skip_pos++);
-#define EXP_PDU_TAG_IPV4_SRC_LEN 4
-#define EXP_PDU_TAG_IPV4_DST_LEN 4
-#define EXP_PDU_TAG_PORT_TYPE_LEN 4
-#define EXP_PDU_TAG_SRC_PORT_LEN 4
-#define EXP_PDU_TAG_DST_PORT_LEN 4
+ curr_pos = skip_pos;
-#define EXP_PDU_TAG_IPV4_LEN 4
-#define EXP_PDU_TAG_IPV6_LEN 16
+ g_strlcpy(str, curr_pos, 3);
+ /* If we find "" here we have no IP address */
+ if (strcmp(str, "\"\"") == 0) {
+ return next_pos;
+ }
+ str[1] = 0;
+ if (strcmp(str, "[") == 0) {
+ /* Should we check for a digit here?*/
+ end_pos = strstr(curr_pos, "]");
+ }else {
+ /* Should we check for a digit here?*/
+ end_pos = strstr(curr_pos, ",");
+ }
+ if (!end_pos) {
+ return next_pos;
+ }
-static gboolean
-nettrace_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset)
-{
- nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+ str_len = (int)(end_pos - curr_pos)+1;
+ if (str_len > WS_INET6_ADDRSTRLEN) {
+ return next_pos;
+ }
+ g_strlcpy(ip_addr_str, curr_pos, str_len);
+ curr_pos = end_pos;
+ if (ws_inet_pton6(ip_addr_str, &ip6_addr)) {
+ if (is_src_addr) {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_IP6_SRC_BIT;
+ memcpy(exported_pdu_info->src_ip, ip6_addr.bytes, EXP_PDU_TAG_IPV6_LEN);
+ }
+ else {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_IP6_DST_BIT;
+ memcpy(exported_pdu_info->dst_ip, ip6_addr.bytes, EXP_PDU_TAG_IPV6_LEN);
+ }
+ }
+ else if (ws_inet_pton4(ip_addr_str, &ip4_addr)) {
+ if (is_src_addr) {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_IP_SRC_BIT;
+ memcpy(exported_pdu_info->src_ip, &ip4_addr, EXP_PDU_TAG_IPV4_LEN);
+ }
+ else {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_IP_DST_BIT;
+ memcpy(exported_pdu_info->dst_ip, &ip4_addr, EXP_PDU_TAG_IPV4_LEN);
+ }
+ }
- /* we read the created pcapng file instead */
- return wtap_read(file_info->wth_tmp_file, rec, buf, err, err_info, data_offset);
+ curr_pos++;
+ scan_found = sscanf(curr_pos, ", %*s %*s %5u, %*s %*s %4s", &port, transp_str);
+ if (scan_found == 2) {
+ /* Only add port_type once */
+ if (exported_pdu_info->ptype == OLD_PT_NONE) {
+ if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0) {
+ exported_pdu_info->ptype = OLD_PT_UDP;
+ }
+ else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0) {
+ exported_pdu_info->ptype = OLD_PT_TCP;
+ }
+ else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0) {
+ exported_pdu_info->ptype = OLD_PT_SCTP;
+ }
+ }
+ if (is_src_addr) {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_SRC_PORT_BIT;
+ exported_pdu_info->src_port = port;
+ }
+ else {
+ exported_pdu_info->presence_flags |= EXP_PDU_TAG_DST_PORT_BIT;
+ exported_pdu_info->dst_port = port;
+ }
+ }
+ return next_pos;
}
-static gboolean
-nettrace_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
-{
- nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
-
- /* we read the created pcapng file instead */
- return wtap_seek_read(file_info->wth_tmp_file, seek_off, rec, buf, err, err_info);
-}
-/* classic wtap: close capture file */
-static void
-nettrace_close(wtap *wth)
+/* Parse a <msg ...><rawMsg ...>XXXX</rawMsg></msg> into packet data. */
+static gboolean
+nettrace_msg_to_packet(nettrace_3gpp_32_423_file_info_t *file_info, wtap_rec *rec, Buffer *buf, guint8 *input, gsize len, int *err, gchar **err_info)
{
- nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+/* Convenience macro. haystack must be >= input! */
+#define STRNSTR(haystack, needle) g_strstr_len(haystack, (len - ((guint8*)(haystack) - (guint8*)input)), needle)
- wtap_close(file_info->wth_tmp_file);
+ gboolean status = TRUE;
+ char *curr_pos, *next_msg_pos, *next_pos, *prev_pos;
+ exported_pdu_info_t exported_pdu_info = {0};
- /* delete the temp file */
- ws_unlink(file_info->tmpname);
- g_free(file_info->tmpname);
-}
+ char* raw_msg_pos;
+ char* start_msg_tag_cont;
+ char name_str[MAX_NAME_LEN+1];
+ char proto_name_str[MAX_PROTO_LEN+1];
+ char dissector_table_str[MAX_DTBL_LEN+1];
+ int dissector_table_val = 0;
-/* This attribute specification contains a timestamp that refers to the start of the
-* first trace data that is stored in this file.
-*
-* It is a complete timestamp including day, time and delta UTC hour. E.g.
-* "2001-09-11T09:30:47-05:00".
-*/
+ int name_str_len = 0;
+ int tag_str_len = 0;
+ int proto_str_len, dissector_table_str_len, raw_data_len, pkt_data_len, exp_pdu_tags_len, i, j;
+ guint8 *packet_buf;
+ gint val1, val2;
+ gboolean port_type_defined = FALSE;
+ gboolean use_proto_table = FALSE;
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+ /* We should always and only be called with a <msg....</msg> payload */
+ if (0 != strncmp(input, c_s_msg, CLEN(c_s_msg))) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Did not start with \"%s\"", c_s_msg);
+ return FALSE;
+ }
+ prev_pos = curr_pos = input + CLEN(c_s_msg);
-static char*
-nettrace_parse_begin_time(char *curr_pos, wtap_rec *rec)
-{
- /* Time vars*/
- guint year, month, day, hour, minute, second, frac;
- int UTCdiffh, UTCdiffm = 0;
- int time_length = 0;
- int scan_found;
- static const guint days_in_month[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
- struct tm tm;
- char *prev_pos, *next_pos;
- int length;
+ rec->rec_type = REC_TYPE_PACKET;
+ rec->presence_flags = 0; /* start out assuming no special features */
+ rec->ts.secs = 0;
+ rec->ts.nsecs = 0;
- prev_pos = curr_pos;
- next_pos = strstr(curr_pos, "\"/>");
- length = (int)(next_pos - prev_pos);
+ /* Clear for each iteration */
+ exported_pdu_info.presence_flags = 0;
+ exported_pdu_info.ptype = OLD_PT_NONE;
- if (length < 2) {
- return next_pos + 3;
+ prev_pos = curr_pos = curr_pos + 4;
+ /* Look for the end of the tag first */
+ next_msg_pos = STRNSTR(curr_pos, ">");
+ if (!next_msg_pos) {
+ /* Something's wrong, bail out */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("Did not find end of tag \">\"");
+ status = FALSE;
+ goto end;
+ }
+ /* Check if its a tag close "/>" */
+ if (*(next_msg_pos - 1) == '/') {
+ /* There is no rawmsg here. Should have been caught before we got called */
+ *err = WTAP_ERR_INTERNAL;
+ *err_info = g_strdup("Had \"<msg />\" with no \"<rawMsg>\"");
+ status = FALSE;
+ goto end;
}
+ start_msg_tag_cont = curr_pos = prev_pos;
+ next_msg_pos = STRNSTR(curr_pos, c_e_msg);
+ if (!next_msg_pos) {
+ /* Something's wrong, bail out */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Did not find \"%s\"", c_e_msg);
+ status = FALSE;
+ goto end;
+ }
+ next_msg_pos += CLEN(c_e_msg);
- rec->presence_flags = 0; /* mark time as invalid, until successful converted */
- rec->ts.secs = 0;
- rec->ts.nsecs = 0;
+ /* Check if we have a time stamp "changeTime"
+ * expressed in number of seconds and milliseconds (nbsec.ms).
+ * Only needed if we have a "beginTime" for this file.
+ */
+ if (!nstime_is_unset(&(file_info->start_time))) {
+ int scan_found;
+ guint second = 0, ms = 0;
- /* Scan for this format: 2001-09-11T09:30:47 Then we will parse any fractions and UTC offset */
- scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u%n",
- &year, &month, &day, &hour, &minute, &second, &time_length);
- if (scan_found == 6 && time_length == 19) {
- /* Fill in the fields and return it in a time_t */
- tm.tm_year = year - 1900;
- if (month < 1 || month > 12) {
- /* g_warning("Failed to parse time, month is %u", month); */
- return curr_pos;
- }
- tm.tm_mon = month - 1; /* Zero count*/
- if (day > ((month == 2 && isleap(year)) ? 29 : days_in_month[month - 1])) {
- /* g_warning("Failed to parse time, %u-%02u-%2u is not a valid day", year, month, day); */
- return curr_pos;
- }
- tm.tm_mday = day;
- if (hour > 23) {
- /* g_warning("Failed to parse time, hour is %u", hour); */
- return curr_pos;
- }
- tm.tm_hour = hour;
- if (minute > 59) {
- /* g_warning("Failed to parse time, minute is %u", minute); */
- return curr_pos;
- }
- tm.tm_min = minute;
- if (second > 60) {
- /*
- * Yes, 60, for leap seconds - POSIX's and Windows'
- * refusal to believe in them nonwithstanding.
- */
- /* g_warning("Failed to parse time, second is %u", second); */
- return curr_pos;
- }
- tm.tm_sec = second;
- tm.tm_isdst = -1; /* daylight saving time info not known */
+ curr_pos = STRNSTR(start_msg_tag_cont, c_change_time);
+ /* Check if we have the tag or if we passed the end of the current message */
+ if (curr_pos != NULL) {
+ curr_pos += CLEN(c_change_time);
+ scan_found = sscanf(curr_pos, "%u.%u", &second, &ms);
- /* Move curr_pos to end of parsed object and get that character 2019-01-10T10:14:56 */
- curr_pos += time_length;
- if (*curr_pos == '.' || *curr_pos == ',') {
- /* We have fractions */
- curr_pos++;
- if (1 == sscanf(curr_pos, "%u%n", &frac, &time_length)) {
- if ((frac >= 1000000000) || (frac == 0)) {
- rec->ts.nsecs = 0;
- } else {
- switch (time_length) { /* including leading zeros */
- case 1: rec->ts.nsecs = frac * 100000000; break;
- case 2: rec->ts.nsecs = frac * 10000000; break;
- case 3: rec->ts.nsecs = frac * 1000000; break;
- case 4: rec->ts.nsecs = frac * 100000; break;
- case 5: rec->ts.nsecs = frac * 10000; break;
- case 6: rec->ts.nsecs = frac * 1000; break;
- case 7: rec->ts.nsecs = frac * 100; break;
- case 8: rec->ts.nsecs = frac * 10; break;
- default: rec->ts.nsecs = frac;
- }
+ if (scan_found == 2) {
+ guint start_ms = file_info->start_time.nsecs / 1000000;
+ guint elapsed_ms = start_ms + ms;
+ if (elapsed_ms > 1000) {
+ elapsed_ms -= 1000;
+ second++;
}
- curr_pos += time_length;
+ rec->presence_flags |= WTAP_HAS_TS;
+ rec->ts.secs = file_info->start_time.secs + second;
+ rec->ts.nsecs = file_info->start_time.nsecs + (elapsed_ms * 1000000);
}
}
+ }
- if (*curr_pos == '-' || *curr_pos == '+' || *curr_pos == 'Z') {
- /* We have UTC offset */
- if (1 <= sscanf(curr_pos, "%3d:%2d", &UTCdiffh, &UTCdiffm)) {
- /* adjust for timezone */
- tm.tm_hour -= UTCdiffh;
- tm.tm_min -= UTCdiffh < 0 ? -UTCdiffm: UTCdiffm;
- } /* else 'Z' for Zero time */
- /* convert to UTC time */
-#ifdef _WIN32
- rec->ts.secs = _mkgmtime(&tm);
-#else
- rec->ts.secs = timegm(&tm);
-#endif
- } else {
- /* no UTC offset means localtime in ISO 8601 */
- rec->ts.secs = mktime(&tm);
+ /* See if we have a "name" */
+ curr_pos = STRNSTR(start_msg_tag_cont, c_proto_name);
+ if (curr_pos != NULL) {
+ /* extract the name */
+ curr_pos += CLEN(c_proto_name);
+ next_pos = STRNSTR(curr_pos, "\"");
+ name_str_len = (int)(next_pos - curr_pos);
+ if (name_str_len > MAX_NAME_LEN) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("name_str_len > %d", MAX_NAME_LEN);
+ goto end;
}
- /* Mark time parsed successfully */
- rec->presence_flags = WTAP_HAS_TS;
- /* } else {
- g_warning("Failed to parse time, only %u fields", scan_found); */
+ g_strlcpy(name_str, curr_pos, (gsize)name_str_len + 1);
+ ascii_strdown_inplace(name_str);
+
+ }
+ /* Check if we have "<initiator>"
+ * It might contain an address
+ */
+ curr_pos = STRNSTR(start_msg_tag_cont, c_s_initiator);
+ /* Check if we have the tag or if we passed the end of the current message */
+ if (curr_pos != NULL) {
+ curr_pos += CLEN(c_s_initiator);
+ next_pos = STRNSTR(curr_pos, c_e_initiator);
+ /* Find address */
+ curr_pos = STRNSTR(curr_pos, c_address);
+ if (curr_pos != NULL) {
+ curr_pos += CLEN(c_address);
+ nettrace_parse_address(curr_pos, next_pos, TRUE/* SRC */, &exported_pdu_info);
+ }
}
- return curr_pos;
-}
-/* Parsing something like
- * <rawMsg
- * protocol="Diameter"
- * version="1">
- * [truncated]010001244000012C01000...
- * </rawMsg>
- */
-static wtap_open_return_val
-write_packet_data(wtap_dumper *wdh, wtap_rec *rec, int *err, gchar **err_info, char *file_buf, nstime_t packet_time, exported_pdu_info_t *exported_pdu_info, char name_str[64])
-{
- char *curr_pos, *next_pos;
- char proto_name_str[16];
- char dissector_table_str[32];
- int dissector_table_val=0;
- int tag_str_len = 0;
- int proto_str_len, dissector_table_str_len, raw_data_len, pkt_data_len, exp_pdu_tags_len, i, j;
- guint8 *packet_buf;
- gint val1, val2;
- gboolean port_type_defined = FALSE;
- gboolean use_proto_table = FALSE;
+ /* Check if we have "<target>"
+ * It might contain an address
+ */
+ curr_pos = STRNSTR(start_msg_tag_cont, c_s_target);
+ /* Check if we have the tag or if we passed the end of the current message */
+ if (curr_pos != NULL) {
+ curr_pos += CLEN(c_s_target);
+ curr_pos = curr_pos + 7;
+ next_pos = STRNSTR(curr_pos, c_e_target);
+ /* Find address */
+ curr_pos = STRNSTR(curr_pos, c_address);
+ if (curr_pos != NULL) {
+ curr_pos += CLEN(c_address);
+ /* curr_pos set below */
+ nettrace_parse_address(curr_pos, next_pos, FALSE/* DST */, &exported_pdu_info);
+ }
+ }
- 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;
+ /* Do we have a raw message in the <msg> </msg> section? */
+ raw_msg_pos = STRNSTR(start_msg_tag_cont, c_s_rawmsg);
+ if (raw_msg_pos == NULL) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Did not find \"%s\"", c_s_rawmsg);
+ status = FALSE;
+ goto end;
}
- curr_pos = curr_pos + 10;
- next_pos = strstr(curr_pos, "\"");
+ curr_pos = STRNSTR(raw_msg_pos, c_protocol);
+ if (curr_pos == NULL) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("Did not find \"%s\"", c_protocol);
+ status = FALSE;
+ goto end;
+ }
+ curr_pos += CLEN(c_protocol);
+ next_pos = STRNSTR(curr_pos, "\"");
proto_str_len = (int)(next_pos - curr_pos);
- if (proto_str_len > 15){
- return WTAP_OPEN_ERROR;
+ if (proto_str_len > MAX_PROTO_LEN){
+ status = FALSE;
+ goto end;
}
-
g_strlcpy(proto_name_str, curr_pos, (gsize)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){
+ if (strcmp(proto_name_str, "gtpv2-c") == 0) {
/* Change to gtpv2 */
proto_name_str[5] = '\0';
proto_str_len = 5;
}
- /* XXX Do we need to check for function="S1" */
- if (strcmp(proto_name_str, "nas") == 0){
+ /* 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_str_len = 13;
+ g_strlcpy(proto_name_str, c_nas_eps, sizeof(c_nas_eps));
+ proto_str_len = CLEN(c_nas_eps);
}
if (strcmp(proto_name_str, "map") == 0) {
- /* For /GSM) map, it looks like the message data is stored like SendAuthenticationInfoArg
+ /* For GSM map, it looks like the message data is stored like SendAuthenticationInfoArg
* use the GSM MAP dissector table to dissect the content.
*/
- exported_pdu_info->proto_col_str = g_strdup("GSM MAP");
+ exported_pdu_info.proto_col_str = g_strdup("GSM MAP");
if (strcmp(name_str, "sai_request") == 0) {
use_proto_table = TRUE;
- g_strlcpy(dissector_table_str, "gsm_map.v3.arg.opcode", 22);
- dissector_table_str_len = 21;
+ g_strlcpy(dissector_table_str, c_sai_req, sizeof(c_sai_req));
+ dissector_table_str_len = CLEN(c_sai_req);
dissector_table_val = 56;
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
+ exported_pdu_info.presence_flags |= EXP_PDU_TAG_COL_PROT_BIT;
}
else if (strcmp(name_str, "sai_response") == 0) {
use_proto_table = TRUE;
- g_strlcpy(dissector_table_str, "gsm_map.v3.res.opcode", 22);
- dissector_table_str_len = 21;
+ g_strlcpy(dissector_table_str, c_sai_rsp, sizeof(c_sai_rsp));
+ dissector_table_str_len = CLEN(c_sai_rsp);
dissector_table_val = 56;
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
+ exported_pdu_info.presence_flags |= EXP_PDU_TAG_COL_PROT_BIT;
} else {
- g_free(exported_pdu_info->proto_col_str);
- exported_pdu_info->proto_col_str = NULL;
+ g_free(exported_pdu_info.proto_col_str);
+ exported_pdu_info.proto_col_str = NULL;
}
}
- /* Find the start of the raw data*/
- curr_pos = strstr(next_pos, ">") + 1;
- next_pos = strstr(curr_pos, "<");
-
+ /* Find the start of the raw data */
+ curr_pos = STRNSTR(next_pos, ">") + 1;
+ next_pos = STRNSTR(curr_pos, "<");
raw_data_len = (int)(next_pos - curr_pos);
- /* Calculate the space needed for exp pdu tags*/
+ /* Calculate the space needed for exp pdu tags */
if (use_proto_table == FALSE) {
tag_str_len = (proto_str_len + 3) & 0xfffffffc;
exp_pdu_tags_len = tag_str_len + 4;
} else {
tag_str_len = (dissector_table_str_len + 3) & 0xfffffffc;
exp_pdu_tags_len = tag_str_len + 4;
- /* Add EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL + length*/
- exp_pdu_tags_len = exp_pdu_tags_len + 4 + 4;
+ /* Add EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL + length */
+ exp_pdu_tags_len += 4 + 4;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_COL_PROT_BIT) {
/* The assert prevents static code analyzers to raise warnings */
- g_assert(exported_pdu_info->proto_col_str);
- exp_pdu_tags_len += 4 + (int)strlen(exported_pdu_info->proto_col_str);
+ g_assert(exported_pdu_info.proto_col_str);
+ exp_pdu_tags_len += 4 + (int)strlen(exported_pdu_info.proto_col_str);
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
- exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_SRC_LEN;
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP_SRC_BIT) {
+ exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_LEN;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP6_SRC_BIT) == EXP_PDU_TAG_IP6_SRC_BIT) {
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP6_SRC_BIT) {
exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV6_LEN;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_SRC_PORT_BIT) {
if (!port_type_defined) {
exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
port_type_defined = TRUE;
}
- exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
+ exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_LEN;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
- exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_DST_LEN;
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP_DST_BIT) {
+ exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_LEN;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP6_DST_BIT) == EXP_PDU_TAG_IP6_DST_BIT) {
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP6_DST_BIT) {
exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV6_LEN;
}
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_DST_PORT_BIT) {
if (!port_type_defined) {
exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
+ port_type_defined = TRUE;
}
- exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
+ exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_LEN;
}
-
- port_type_defined = FALSE;
+ exp_pdu_tags_len += 4; /* account for opt_endofopt */
/* Allocate the packet buf */
pkt_data_len = raw_data_len / 2;
- packet_buf = (guint8 *)g_malloc0((gsize)pkt_data_len + (gsize)exp_pdu_tags_len + (gsize)4);
+ ws_buffer_assure_space(buf, (gsize)pkt_data_len + (gsize)exp_pdu_tags_len);
+ ws_buffer_increase_length(buf, (gsize)pkt_data_len + (gsize)exp_pdu_tags_len);
+ packet_buf = ws_buffer_start_ptr(buf);
/* Fill packet buff */
if (use_proto_table == FALSE) {
- packet_buf[0] = 0;
- packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
- packet_buf[2] = 0;
- packet_buf[3] = tag_str_len;
- memcpy(&packet_buf[4], proto_name_str, proto_str_len);
- i = 4 + tag_str_len;
- }else{
- packet_buf[0] = 0;
- packet_buf[1] = 14; /* EXP_PDU_TAG_DISSECTOR_TABLE_NAME */
- packet_buf[2] = 0;
- packet_buf[3] = tag_str_len;
- memcpy(&packet_buf[4], dissector_table_str, dissector_table_str_len);
- i = 4 + tag_str_len;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = 4; /* tag length */;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = dissector_table_val;
- i++;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_COL_PROT_TEXT;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = (guint8)strlen(exported_pdu_info->proto_col_str);
- i++;
- for (j = 0; j < (int)strlen(exported_pdu_info->proto_col_str); i++, j++) {
- packet_buf[i] = exported_pdu_info->proto_col_str[j];
- }
- g_free(exported_pdu_info->proto_col_str);
- }
-
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV4_SRC;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV4_SRC_LEN; /* tag length */;
- i++;
- memcpy(packet_buf+i, exported_pdu_info->src_ip, EXP_PDU_TAG_IPV4_SRC_LEN);
- i += EXP_PDU_TAG_IPV4_SRC_LEN;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP6_SRC_BIT) == EXP_PDU_TAG_IP6_SRC_BIT) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV6_SRC;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV6_LEN; /* tag length */;
- i++;
- memcpy(packet_buf+i, exported_pdu_info->src_ip, EXP_PDU_TAG_IPV6_LEN);
- i += EXP_PDU_TAG_IPV6_LEN;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
- if (!port_type_defined) {
- port_type_defined = TRUE;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
- i++;
- }
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_SRC_PORT;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_SRC_PORT_LEN; /* tag length */;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
- i++;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV4_DST;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV4_DST_LEN; /* tag length */;
- i++;
- memcpy(packet_buf + i, exported_pdu_info->dst_ip, EXP_PDU_TAG_IPV4_DST_LEN);
- i += EXP_PDU_TAG_IPV4_DST_LEN;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP6_DST_BIT) == EXP_PDU_TAG_IP6_DST_BIT) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV6_DST;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_IPV6_LEN; /* tag length */;
- i++;
- memcpy(packet_buf + i, exported_pdu_info->dst_ip, EXP_PDU_TAG_IPV6_LEN);
- i += EXP_PDU_TAG_IPV6_LEN;
- }
-
- if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
- if (!port_type_defined) {
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
- i++;
- packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
- i++;
- }
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_DST_PORT;
- i++;
- packet_buf[i] = 0;
- i++;
- packet_buf[i] = EXP_PDU_TAG_DST_PORT_LEN; /* tag length */;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
- i++;
- packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
- i++;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_PROTO_NAME;
+ *packet_buf++ = 0;
+ *packet_buf++ = tag_str_len;
+ memset(packet_buf, 0, tag_str_len);
+ memcpy(packet_buf, proto_name_str, proto_str_len);
+ packet_buf += tag_str_len;
+ }
+ else {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_DISSECTOR_TABLE_NAME;
+ *packet_buf++ = 0;
+ *packet_buf++ = tag_str_len;
+ memset(packet_buf, 0, tag_str_len);
+ memcpy(packet_buf, dissector_table_str, dissector_table_str_len);
+ packet_buf += tag_str_len;
+
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
+ *packet_buf++ = 0;
+ *packet_buf++ = 4; /* option length */
+ *packet_buf++ = 0;
+ *packet_buf++ = 0;
+ *packet_buf++ = 0;
+ *packet_buf++ = dissector_table_val;
+ }
+
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_COL_PROT_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_COL_PROT_TEXT;
+ *packet_buf++ = 0;
+ *packet_buf++ = (guint8)strlen(exported_pdu_info.proto_col_str);
+ for (j = 0; j < (int)strlen(exported_pdu_info.proto_col_str); j++) {
+ *packet_buf++ = exported_pdu_info.proto_col_str[j];
+ }
+ g_free(exported_pdu_info.proto_col_str);
+ exported_pdu_info.proto_col_str = NULL;
+ }
+
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP_SRC_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV4_SRC;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV4_LEN;
+ memcpy(packet_buf, exported_pdu_info.src_ip, EXP_PDU_TAG_IPV4_LEN);
+ packet_buf += EXP_PDU_TAG_IPV4_LEN;
+ }
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP_DST_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV4_DST;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV4_LEN;
+ memcpy(packet_buf, exported_pdu_info.dst_ip, EXP_PDU_TAG_IPV4_LEN);
+ packet_buf += EXP_PDU_TAG_IPV4_LEN;
+ }
+
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP6_SRC_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV6_SRC;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV6_LEN;
+ memcpy(packet_buf, exported_pdu_info.src_ip, EXP_PDU_TAG_IPV6_LEN);
+ packet_buf += EXP_PDU_TAG_IPV6_LEN;
+ }
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_IP6_DST_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV6_DST;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_IPV6_LEN;
+ memcpy(packet_buf, exported_pdu_info.dst_ip, EXP_PDU_TAG_IPV6_LEN);
+ packet_buf += EXP_PDU_TAG_IPV6_LEN;
+ }
+
+ if (exported_pdu_info.presence_flags & (EXP_PDU_TAG_SRC_PORT_BIT | EXP_PDU_TAG_DST_PORT_BIT)) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_PORT_TYPE;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_PORT_TYPE_LEN;
+ *packet_buf++ = (exported_pdu_info.ptype & 0xff000000) >> 24;
+ *packet_buf++ = (exported_pdu_info.ptype & 0x00ff0000) >> 16;
+ *packet_buf++ = (exported_pdu_info.ptype & 0x0000ff00) >> 8;
+ *packet_buf++ = (exported_pdu_info.ptype & 0x000000ff);
+ }
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_SRC_PORT_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_SRC_PORT;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_PORT_LEN;
+ *packet_buf++ = (exported_pdu_info.src_port & 0xff000000) >> 24;
+ *packet_buf++ = (exported_pdu_info.src_port & 0x00ff0000) >> 16;
+ *packet_buf++ = (exported_pdu_info.src_port & 0x0000ff00) >> 8;
+ *packet_buf++ = (exported_pdu_info.src_port & 0x000000ff);
+ }
+ if (exported_pdu_info.presence_flags & EXP_PDU_TAG_DST_PORT_BIT) {
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_DST_PORT;
+ *packet_buf++ = 0;
+ *packet_buf++ = EXP_PDU_TAG_PORT_LEN;
+ *packet_buf++ = (exported_pdu_info.dst_port & 0xff000000) >> 24;
+ *packet_buf++ = (exported_pdu_info.dst_port & 0x00ff0000) >> 16;
+ *packet_buf++ = (exported_pdu_info.dst_port & 0x0000ff00) >> 8;
+ *packet_buf++ = (exported_pdu_info.dst_port & 0x000000ff);
}
/* 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;
+ *packet_buf++ = 0;
+ *packet_buf++ = 0;
+ *packet_buf++ = 0;
+ *packet_buf++ = 0;
/* Convert the hex raw msg data to binary and write to the packet buf*/
- for (; i < (pkt_data_len + exp_pdu_tags_len); i++){
+ for (i = 0; i < pkt_data_len; i++) {
gchar chr1, chr2;
- chr1 = *curr_pos;
+ chr1 = *curr_pos++;
+ chr2 = *curr_pos++;
val1 = g_ascii_xdigit_value(chr1);
- curr_pos++;
- chr2 = *curr_pos;
val2 = g_ascii_xdigit_value(chr2);
- if ((val1 != -1) && (val2 != -1)){
- packet_buf[i] = ((guint8)val1 * 16) + val2;
+ if ((val1 != -1) && (val2 != -1)) {
+ *packet_buf++ = ((guint8)val1 * 16) + val2;
}
- else{
+ else {
/* Something wrong, bail out */
*err_info = g_strdup_printf("Could not parse hex data,bufzize %u index %u %c%c",
(pkt_data_len + exp_pdu_tags_len),
@@ -643,505 +621,280 @@ write_packet_data(wtap_dumper *wdh, wtap_rec *rec, int *err, gchar **err_info, c
chr1,
chr2);
*err = WTAP_ERR_BAD_FILE;
- g_free(packet_buf);
- return WTAP_OPEN_ERROR;
+ status = FALSE;
+ goto end;
}
- curr_pos++;
- }
- /* Construct the phdr */
- memset(rec, 0, sizeof *rec);
- rec->rec_type = REC_TYPE_PACKET;
- if (packet_time.secs == 0) {
- rec->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
- rec->ts.secs = 0;
- rec->ts.nsecs = 0;
- } else {
- rec->presence_flags = WTAP_HAS_TS;
- rec->ts.secs = packet_time.secs;
- rec->ts.nsecs = packet_time.nsecs;
}
rec->rec_header.packet_header.caplen = pkt_data_len + exp_pdu_tags_len;
rec->rec_header.packet_header.len = pkt_data_len + exp_pdu_tags_len;
- if (!wtap_dump(wdh, rec, packet_buf, err, err_info)) {
- switch (*err) {
+end:
+ return status;
+#undef STRNSTR
+}
- case WTAP_ERR_UNWRITABLE_REC_DATA:
+/* Read from fh and store into buffer, until buffer contains needle.
+ * Returns location of needle once found, or NULL if it's never found
+ * (due to either EOF or read error).
+ */
+static guint8 *
+read_until(GByteArray *buffer, const guchar *needle, FILE_T fh, int *err, gchar **err_info)
+{
+ guint8 read_buffer[RINGBUFFER_CHUNK_SIZE];
+ guint8 *found_it;
+ gint bytes_read = 0;
+
+ while (NULL == (found_it = g_strstr_len(buffer->data, buffer->len, needle))) {
+ bytes_read = file_read(read_buffer, RINGBUFFER_CHUNK_SIZE, fh);
+ if (bytes_read < 0) {
+ *err = file_error(fh, err_info);
break;
-
- default:
+ }
+ if (bytes_read == 0) {
break;
}
- g_free(packet_buf);
- return WTAP_OPEN_ERROR;
+ g_byte_array_append(buffer, read_buffer, bytes_read);
}
-
- g_free(packet_buf);
- return WTAP_OPEN_MINE;
+ return found_it;
}
-static char*
-nettrace_parse_address(char* curr_pos, char* next_pos, gboolean is_src_addr/*SRC */, exported_pdu_info_t *exported_pdu_info)
+/* Find a complete packet, parse and return it to wiretap.
+ * Set as the subtype_read function in the file_open function below.
+ */
+static gboolean
+nettrace_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset)
{
- guint port;
- char transp_str[5];
- int scan_found;
- char str[3];
- char* end_pos, *skip_pos;
- char ip_addr_str[WS_INET6_ADDRSTRLEN];
- int str_len;
- ws_in6_addr ip6_addr;
- guint32 ip4_addr;
- gchar tempchar;
-
- /* curr_pos pointing to first char after address */
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+ guint8 *buf_start;
+ guint8 *msg_start, *msg_end;
+ guint msg_offset = 0;
+ gsize msg_len = 0;
+ gboolean status = FALSE;
+
+ /* Make sure we have a start and end of message in our buffer -- end first */
+ msg_end = read_until(file_info->buffer, c_e_msg, wth->fh, err, err_info);
+ if (msg_end == NULL) {
+ goto end;
+ }
- /* Excample from one trace, unsure if it's generic...
- * {address == 192.168.73.1, port == 5062, transport == Udp}
- * {address == [2001:1b70:8294:210a::78], port...
- * {address == 2001:1B70:8294:210A::90, port...
- * Address=198.142.204.199,Port=2123
+ buf_start = file_info->buffer->data;
+ /* Now search backwards for the message start
+ * (doing it this way should skip over any empty "<msg ... />" tags we have)
*/
- /* Skip whitespace and equalsigns)*/
- for (skip_pos = curr_pos; skip_pos < next_pos &&
- ((tempchar = *skip_pos) == ' ' ||
- tempchar == '\t' || tempchar == '\r' || tempchar == '\n' || tempchar == '=');
- skip_pos++);
+ msg_start = g_strrstr_len(buf_start, (guint)(msg_end - buf_start), c_s_msg);
+ if (msg_start == NULL || msg_start > msg_end) {
+ *err_info = g_strdup_printf("Found \"%s\" without matching \"%s\"", c_e_msg, c_s_msg);
+ *err = WTAP_ERR_BAD_FILE;
+ goto end;
+ }
- curr_pos = skip_pos;
+ /* We know we have a message, what's its offset from the buffer start? */
+ msg_offset = (guint)(msg_start - buf_start);
+ msg_end += CLEN(c_e_msg);
+ msg_len = (guint)(msg_end - msg_start);
- g_strlcpy(str, curr_pos, 3);
- /* If we find "" here we have no IP address*/
- if (strcmp(str, "\"\"") == 0) {
- return next_pos;
- }
- str[1] = 0;
- if (strcmp(str, "[") == 0) {
- /* Should we check for a digit here?*/
- end_pos = strstr(curr_pos, "]");
+ /* Tell Wireshark to put us at the start of the "<msg" for seek_read later */
+ *data_offset = file_info->start_offset + msg_offset;
- }else {
- /* Should we check for a digit here?*/
- end_pos = strstr(curr_pos, ",");
- }
- if (!end_pos) {
- return next_pos;
- }
+ /* pass all of <msg....</msg> to nettrace_msg_to_packet() */
+ status = nettrace_msg_to_packet(file_info, rec, buf, msg_start, msg_len, err, err_info);
- str_len = (int)(end_pos - curr_pos)+1;
- if (str_len > WS_INET6_ADDRSTRLEN) {
- return next_pos;
- }
- g_strlcpy(ip_addr_str, curr_pos, str_len);
- curr_pos = end_pos;
- if (ws_inet_pton6(ip_addr_str, &ip6_addr)) {
- if (is_src_addr) {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_IP6_SRC_BIT;
- memcpy(exported_pdu_info->src_ip, ip6_addr.bytes, EXP_PDU_TAG_IPV6_LEN);
- }
- else {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_IP6_DST_BIT;
- memcpy(exported_pdu_info->dst_ip, ip6_addr.bytes, EXP_PDU_TAG_IPV6_LEN);
- }
- }
- else if (ws_inet_pton4(ip_addr_str, &ip4_addr)) {
- if (is_src_addr) {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_IP_SRC_BIT;
- memcpy(exported_pdu_info->src_ip, &ip4_addr, EXP_PDU_TAG_IPV4_LEN);
- }
- else {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_IP_DST_BIT;
- memcpy(exported_pdu_info->dst_ip, &ip4_addr, EXP_PDU_TAG_IPV4_LEN);
- }
+ /* Finally, shift our buffer to the end of this message to get ready for the next one.
+ * Re-use msg_len to get the length of the data we're done with.
+ */
+ msg_len = msg_end - file_info->buffer->data;
+ while (G_UNLIKELY(msg_len > G_MAXUINT)) {
+ g_byte_array_remove_range(file_info->buffer, 0, G_MAXUINT);
+ msg_len -= G_MAXUINT;
}
+ g_byte_array_remove_range(file_info->buffer, 0, (guint)msg_len);
+ file_info->start_offset += msg_len;
- curr_pos++;
- scan_found = sscanf(curr_pos, ", %*s %*s %5u, %*s %*s %4s", &port, transp_str);
- if (scan_found == 2) {
- /* Only add port_type once */
- if (exported_pdu_info->ptype == OLD_PT_NONE) {
- if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0) exported_pdu_info->ptype = OLD_PT_UDP;
- else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0) exported_pdu_info->ptype = OLD_PT_TCP;
- else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0) exported_pdu_info->ptype = OLD_PT_SCTP;
- }
- if (is_src_addr) {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_SRC_PORT_BIT;
- exported_pdu_info->src_port = port;
- }
- else {
- exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_DST_PORT_BIT;
- exported_pdu_info->dst_port = port;
- }
+end:
+ if (status == FALSE) {
+ /* There's no more to read. Empty out the buffer */
+ g_byte_array_set_size(file_info->buffer, 0);
}
- return next_pos;
+
+ return status;
}
-/*
- * Opens an .xml file with Trace data formatted 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.
+/* Seek to the complete packet at the offset, parse and return it to wiretap.
+ * Set as the subtype_seek_read function in the file_open function below.
*/
-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)
+static gboolean
+nettrace_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
{
- int import_file_fd;
- wtap_dumper* wdh_exp_pdu;
- wtap_open_return_val result = WTAP_OPEN_MINE;
-
- /* pcapng defs */
- GArray *shb_hdrs;
- wtap_block_t shb_hdr;
- wtapng_iface_descriptions_t *idb_inf = NULL;
- wtap_block_t int_data;
- wtapng_if_descr_mandatory_t *int_data_mand;
- GString *os_info_str;
- gint64 file_size;
- int packet_size;
- char *packet_buf = NULL;
- wtap_rec rec;
- nstime_t start_time, packet_time;
- int scan_found;
- unsigned int second, ms;
- gboolean do_random = FALSE;
- char *curr_pos, *next_msg_pos, *next_pos, *prev_pos;
- int name_str_len;
- char name_str[64];
- gsize opt_len;
- gchar *opt_str;
- /* Info to build exported_pdu tags*/
- exported_pdu_info_t exported_pdu_info = {0};
-
- import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_", NULL, NULL);
- if (import_file_fd < 0)
- return WTAP_OPEN_ERROR;
-
- /* Now open a file and dump to it */
- /* Create data for SHB */
- shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
- os_info_str = g_string_new("");
- get_os_version_info(os_info_str);
-
- shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
- /* options */
- wtap_block_add_string_option(shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
- strlen("File converted to Exported PDU format during opening"));
- /*
- * UTF-8 string containing the name of the operating system used to create
- * this section.
- */
- opt_len = os_info_str->len;
- opt_str = g_string_free(os_info_str, FALSE);
- if (opt_str) {
- wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, opt_str, opt_len);
- g_free(opt_str);
- }
-
- /*
- * UTF-8 string containing the name of the application used to create
- * this section. Avoid the precise version (get_appname_and_version) to
- * avoid wiretap rebuilds when only the version changes.
- */
- wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", VERSION);
-
- /* Add header to the array */
- g_array_append_val(shb_hdrs, shb_hdr);
-
-
- /* Create fake IDB info */
- idb_inf = g_new(wtapng_iface_descriptions_t, 1);
- idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
-
- /* create the fake interface data */
- 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 = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
- int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
- int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
- wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
- int_data_mand->num_stat_entries = 0; /* Number of ISB:s */
- int_data_mand->interface_statistics = NULL;
-
- g_array_append_val(idb_inf->interface_data, int_data);
-
- const wtap_dump_params params = {
- .encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU,
- .snaplen = WTAP_MAX_PACKET_SIZE_STANDARD,
- .shb_hdrs = shb_hdrs,
- .idb_inf = idb_inf,
- };
- wdh_exp_pdu = wtap_dump_fdopen(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG,
- WTAP_UNCOMPRESSED, &params,
- err, err_info);
- if (wdh_exp_pdu == NULL) {
- result = WTAP_OPEN_ERROR;
- goto end;
- }
-
- /* OK we've opend a new pcapng file and written the headers, time to do the packets, strt by finding the file size */
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
+ gboolean status = FALSE;
+ guint8 *msg_end;
+ guint msg_len = 0;
- if ((file_size = wtap_file_size(wth, err)) == -1) {
- result = WTAP_OPEN_ERROR;
- goto end;
- }
+ /* We stored the offset of the "<msg" for this packet */
+ if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+ return FALSE;
- 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);
- result = WTAP_OPEN_ERROR;
- goto end;
- }
- 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 = (char *)g_malloc((gsize)packet_size + (gsize)12 + (gsize)1);
-
- packet_buf[0] = 0;
- packet_buf[1] = EXP_PDU_TAG_PROTO_NAME;
- packet_buf[2] = 0;
- packet_buf[3] = 4;
- packet_buf[4] = 'x';
- packet_buf[5] = 'm';
- packet_buf[6] = '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, err, err_info)){
- result = WTAP_OPEN_ERROR;
- goto end;
+ msg_end = read_until(file_info->buffer, c_e_msg, wth->random_fh, err, err_info);
+ if (msg_end == NULL) {
+ return FALSE;
}
+ msg_end += CLEN(c_e_msg);
+ msg_len = (guint)(msg_end - file_info->buffer->data);
- /* Null-terminate buffer; we'll be processing it as a string. */
- packet_buf[packet_size + 12] = '\0';
-
- /* Create the record header */
- memset(&rec, 0, sizeof rec);
+ status = nettrace_msg_to_packet(file_info, rec, buf, file_info->buffer->data, msg_len, err, err_info);
+ g_byte_array_set_size(file_info->buffer, 0);
+ return status;
+}
- /* Read the file header of the input file, currently we only need the beginTime*/
+/* Clean up any memory we allocated for dealing with this file.
+ * Set as the subtype_close function in the file_open function below.
+ * (wiretap frees wth->priv itself)
+ */
+static void
+nettrace_close(wtap *wth)
+{
+ nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
- /* Advance *packet_buf to point at the raw file data */
- curr_pos = packet_buf + 12;
- /* Find the file header */
- curr_pos = strstr(curr_pos, "<fileHeader");
- if (!curr_pos) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("Could not parse \"<fileHeader\"");
- result = WTAP_OPEN_ERROR;
- goto end;
+ if (file_info != NULL && file_info->buffer != NULL) {
+ g_byte_array_free(file_info->buffer, TRUE);
+ file_info->buffer = NULL;
}
- curr_pos = curr_pos + 11;
+}
- /* Find start time */
- curr_pos = strstr(curr_pos, "<traceCollec beginTime=\"");
- if (!curr_pos) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("Could not parse \"<traceCollec beginTime=\"");
- result = WTAP_OPEN_ERROR;
- goto end;
- }
- curr_pos = curr_pos + 24;
+/* This attribute specification contains a timestamp that refers to the start of the
+* first trace data that is stored in this file.
+*
+* It is a complete timestamp including day, time and delta UTC hour. E.g.
+* "2001-09-11T09:30:47-05:00".
+*/
- curr_pos = nettrace_parse_begin_time(curr_pos, &rec);
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
- start_time.secs = packet_time.secs = rec.ts.secs;
- start_time.nsecs = packet_time.nsecs = rec.ts.nsecs;
+static char*
+nettrace_parse_begin_time(char *curr_pos, size_t n, nstime_t *ts)
+{
+ /* Time vars */
+ guint year, month, day, hour, minute, second, frac;
+ int UTCdiffh, UTCdiffm = 0;
+ int time_length = 0;
+ int scan_found;
+ static const guint days_in_month[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ struct tm tm;
+ char *end_pos;
+ int length;
- /* set rest of the record hdr data */
- rec.rec_type = REC_TYPE_PACKET;
+ nstime_set_unset(ts); /* mark time as invalid, until successful converted */
- rec.rec_header.packet_header.caplen = packet_size + 12;
- rec.rec_header.packet_header.len = packet_size + 12;
+ end_pos = g_strstr_len(curr_pos, n, "\"/>");
+ length = (int)(end_pos - curr_pos);
- /* XXX: report errors! */
- if (!wtap_dump(wdh_exp_pdu, &rec, packet_buf, err, err_info)) {
- result = WTAP_OPEN_ERROR;
- goto end;
+ if (length < 2) {
+ return end_pos + 3;
}
- /* 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;
- char str[3];
- char *raw_msg_pos;
- char* start_msg_tag_cont;
-
- /* Clear for each iteration */
- exported_pdu_info.precense_flags = 0;
- exported_pdu_info.ptype = OLD_PT_NONE;
-
- prev_pos = curr_pos = curr_pos + 4;
- /* Look for the end of the tag first */
- next_msg_pos = strstr(curr_pos, ">");
- if (!next_msg_pos) {
- /* Somethings wrong, bail out */
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("Did not find end of tag \">\"");
- result = WTAP_OPEN_ERROR;
- goto end;
- }
- /* Check if its a tag close "/>" */
- g_strlcpy(str, next_msg_pos - 1 , 3);
- next_msg_pos = next_msg_pos - 1;
- if (strcmp(str, "/>") == 0) {
- /* There is no rawmsg here skip to nex msg */
- curr_pos = next_msg_pos + 2;
- continue;
- }
- start_msg_tag_cont = curr_pos = prev_pos;
- next_msg_pos = strstr(curr_pos, "</msg>");
- if (!next_msg_pos){
- /* Somethings wrong, bail out */
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("Did not find \"</msg>\"");
- result = WTAP_OPEN_ERROR;
- goto end;
+ /* Scan for this format: 2001-09-11T09:30:47 Then we will parse any fractions and UTC offset */
+ scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u%n",
+ &year, &month, &day, &hour, &minute, &second, &time_length);
+ if (scan_found == 6 && time_length == 19) {
+ /* Fill in the fields and return it in a time_t */
+ tm.tm_year = year - 1900;
+ if (month < 1 || month > 12) {
+ /* g_warning("Failed to parse time, month is %u", month); */
+ return curr_pos;
}
- next_msg_pos = next_msg_pos + 6;
-
- /* Do we have a raw message in the <msg> <\msg> section?*/
- raw_msg_pos = strstr(start_msg_tag_cont, "<rawMsg");
- if ((!raw_msg_pos) || (raw_msg_pos > next_msg_pos)) {
- curr_pos = next_msg_pos;
- continue;
+ tm.tm_mon = month - 1; /* Zero count*/
+ if (day > ((month == 2 && isleap(year)) ? 29 : days_in_month[month - 1])) {
+ /* g_warning("Failed to parse time, %u-%02u-%2u is not a valid day", year, month, day); */
+ return curr_pos;
}
-
-
- /* Check if we have a time stamp "changeTime"
- * expressed in number of seconds and milliseconds (nbsec.ms).
- */
- ms = 0;
- curr_pos = strstr(start_msg_tag_cont, "changeTime");
- /* Check if we have the tag or if we passed the end of the current message */
- if ((curr_pos) && (curr_pos < next_msg_pos)) {
- curr_pos = curr_pos + 12;
- scan_found = sscanf(curr_pos, "%u.%u", &second, &ms);
-
- if ((scan_found == 2) && (start_time.secs != 0)) {
- guint start_ms = start_time.nsecs / 1000000;
- guint elapsed_ms = start_ms + ms;
- if (elapsed_ms > 1000) {
- elapsed_ms -= 1000;
- second++;
- }
- packet_time.secs = start_time.secs + second;
- packet_time.nsecs = start_time.nsecs + (elapsed_ms * 1000000);
- }
+ tm.tm_mday = day;
+ if (hour > 23) {
+ /* g_warning("Failed to parse time, hour is %u", hour); */
+ return curr_pos;
}
-
- /* See if we have a "name" */
- curr_pos = strstr(start_msg_tag_cont, "name=");
- if ((curr_pos) && (curr_pos < next_msg_pos)) {
- /* extract the name */
- curr_pos = curr_pos + 6;
- next_pos = strstr(curr_pos, "\"");
- name_str_len = (int)(next_pos - curr_pos);
- if (name_str_len > 63) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("name_str_len > 63");
- return WTAP_OPEN_ERROR;
- }
-
- g_strlcpy(name_str, curr_pos, (gsize)name_str_len + 1);
- ascii_strdown_inplace(name_str);
-
+ tm.tm_hour = hour;
+ if (minute > 59) {
+ /* g_warning("Failed to parse time, minute is %u", minute); */
+ return curr_pos;
}
- /* Check if we have "<initiator>"
- * It might contain an address
- */
- curr_pos = strstr(start_msg_tag_cont, "<initiator");
- /* Check if we have the tag or if we passed the end of the current message */
- if ((curr_pos) && (curr_pos < next_msg_pos)) {
- curr_pos = curr_pos + 10;
- next_pos = strstr(curr_pos, "</initiator>");
- /* Find address (omit the a to cater for A */
- curr_pos = strstr(curr_pos, "ddress");
- if ((curr_pos) && (curr_pos < next_pos)) {
- curr_pos += 6;
- nettrace_parse_address(curr_pos, next_pos, TRUE/*SRC */, &exported_pdu_info);
- }
+ tm.tm_min = minute;
+ if (second > 60) {
+ /*
+ * Yes, 60, for leap seconds - POSIX's and Windows'
+ * refusal to believe in them nonwithstanding.
+ */
+ /* g_warning("Failed to parse time, second is %u", second); */
+ return curr_pos;
}
+ tm.tm_sec = second;
+ tm.tm_isdst = -1; /* daylight saving time info not known */
- /* Check if we have "<target>"
- * It might contain an address
- */
- curr_pos = strstr(start_msg_tag_cont, "<target");
- /* Check if we have the tag or if we passed the end of the current message */
- if ((curr_pos) && (curr_pos < next_msg_pos)) {
- curr_pos = curr_pos + 7;
- next_pos = strstr(curr_pos, "</target>");
- /* Find address(omit the a to cater for A */
- curr_pos = strstr(curr_pos, "ddress");
- if ((curr_pos) && (curr_pos < next_pos)) {
- curr_pos += 7;
- /* curr_pos set below */
- nettrace_parse_address(curr_pos, next_pos, FALSE/*DST */, &exported_pdu_info);
+ /* Move curr_pos to end of parsed object and get that character 2019-01-10T10:14:56 */
+ curr_pos += time_length;
+ if (*curr_pos == '.' || *curr_pos == ',') {
+ /* We have fractions */
+ curr_pos++;
+ if (1 == sscanf(curr_pos, "%u%n", &frac, &time_length)) {
+ if ((frac >= 1000000000) || (frac == 0)) {
+ ts->nsecs = 0;
+ } else {
+ switch (time_length) { /* including leading zeros */
+ case 1: ts->nsecs = frac * 100000000; break;
+ case 2: ts->nsecs = frac * 10000000; break;
+ case 3: ts->nsecs = frac * 1000000; break;
+ case 4: ts->nsecs = frac * 100000; break;
+ case 5: ts->nsecs = frac * 10000; break;
+ case 6: ts->nsecs = frac * 1000; break;
+ case 7: ts->nsecs = frac * 100; break;
+ case 8: ts->nsecs = frac * 10; break;
+ default: ts->nsecs = frac;
+ }
+ }
+ curr_pos += time_length;
}
}
- /* Do we have a raw msg?) */
- curr_pos = raw_msg_pos;
- curr_pos = curr_pos + 7;
- /* Add the raw msg*/
- temp_val = write_packet_data(wdh_exp_pdu, &rec, err, err_info, curr_pos, packet_time, &exported_pdu_info, name_str);
- if (temp_val != WTAP_OPEN_MINE){
- result = temp_val;
- goto end;
+ if (*curr_pos == '-' || *curr_pos == '+' || *curr_pos == 'Z') {
+ /* We have UTC offset */
+ if (1 <= sscanf(curr_pos, "%3d:%2d", &UTCdiffh, &UTCdiffm)) {
+ /* adjust for timezone */
+ tm.tm_hour -= UTCdiffh;
+ tm.tm_min -= UTCdiffh < 0 ? -UTCdiffm: UTCdiffm;
+ } /* else 'Z' for Zero time */
+ /* convert to UTC time */
+#ifdef _WIN32
+ ts->secs = _mkgmtime(&tm);
+#else
+ ts->secs = timegm(&tm);
+#endif
+ } else {
+ /* no UTC offset means localtime in ISO 8601 */
+ ts->secs = mktime(&tm);
}
- curr_pos = next_msg_pos;
- }
-
- /* Close the written file*/
- if (!wtap_dump_close(wdh_exp_pdu, err, err_info)){
- result = WTAP_OPEN_ERROR;
- goto end;
- }
-
- /* Now open the file for reading */
-
- /* Find out if random read was requested */
- if (wth->random_fh){
- do_random = TRUE;
- }
- file_info->wth_tmp_file =
- wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);
-
- if (!file_info->wth_tmp_file){
- result = WTAP_OPEN_ERROR;
- goto end;
+ /* } else {
+ g_warning("Failed to parse time, only %u fields", scan_found); */
}
-end:
- g_free(packet_buf);
- wtap_block_array_free(shb_hdrs);
- wtap_free_idb_info(idb_inf);
-
- return result;
+ return curr_pos;
}
+/* Test the current file to see if it's one we can read.
+ * Set in file_access.c as the function to be called for this file type.
+ */
wtap_open_return_val
nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
{
- char magic_buf[512+1]; /* increase buffer size when needed */
+ char magic_buf[MAGIC_BUF_SIZE+1];
int bytes_read;
char *curr_pos;
nettrace_3gpp_32_423_file_info_t *file_info;
- wtap_open_return_val temp_val;
+ gint64 start_offset;
-
- bytes_read = file_read(magic_buf, 512, wth->fh);
+ start_offset = file_tell(wth->fh); // Most likely 0 but doesn't hurt to check
+ bytes_read = file_read(magic_buf, MAGIC_BUF_SIZE, wth->fh);
if (bytes_read < 0) {
*err = file_error(wth->fh, err_info);
@@ -1151,53 +904,46 @@ nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
return WTAP_OPEN_NOT_MINE;
}
- if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
+ if (memcmp(magic_buf, c_xml_magic, CLEN(c_xml_magic)) != 0){
return WTAP_OPEN_NOT_MINE;
}
- /* Null-terminate buffer; we'll be processing it as a string. */
- magic_buf[512] = '\0';
-
- /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
- curr_pos = strstr(magic_buf, "fileFormatVersion");
-
- if (!curr_pos){
+ curr_pos = g_strstr_len(magic_buf, bytes_read, c_file_header);
+ if (!curr_pos) {
return WTAP_OPEN_NOT_MINE;
}
- curr_pos += 19;
- if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
+ curr_pos = g_strstr_len(curr_pos, bytes_read-(curr_pos-magic_buf), c_file_format_version);
+ if (!curr_pos) {
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;
+ curr_pos += CLEN(c_file_format_version);
+ if (memcmp(curr_pos, c_threegpp_doc_no, CLEN(c_threegpp_doc_no)) != 0){
+ return WTAP_OPEN_NOT_MINE;
}
+ /* Next we expect something like <traceCollec beginTime="..."/> */
+ curr_pos = g_strstr_len(curr_pos, bytes_read-(curr_pos-magic_buf), c_begin_time);
+ if (!curr_pos) {
+ return WTAP_OPEN_NOT_MINE;
+ }
+ curr_pos += CLEN(c_begin_time);
- if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
- return WTAP_OPEN_ERROR;
-
- /* Copy data from the temp file wth */
- wtap_block_copy(g_array_index(wth->shb_hdrs, wtap_block_t, 0), g_array_index(file_info->wth_tmp_file->shb_hdrs, wtap_block_t, 0));
+ /* Ok it's our file. From here we'll need to free memory */
+ file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
+ curr_pos = nettrace_parse_begin_time(curr_pos, (guint)(bytes_read - (curr_pos - magic_buf)), &file_info->start_time);
+ file_info->start_offset = start_offset + (curr_pos - magic_buf);
+ file_info->buffer = g_byte_array_sized_new(RINGBUFFER_START_SIZE);
+ g_byte_array_append(file_info->buffer, curr_pos, (guint)(bytes_read - (curr_pos - magic_buf)));
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->file_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
+ wth->file_tsprec = WTAP_TSPREC_MSEC;
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;
-
}
/*