1 /* nettrace_3gpp_32_423.c
3 * Decoder for 3GPP TS 32.423 file format for the Wiretap library.
4 * The main purpose is to have Wireshark decode raw message content (<rawMsg> tag).
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * Ref: http://www.3gpp.org/DynaReport/32423.htm
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
39 #include "file_wrappers.h"
40 #include "pcap-encap.h"
42 #include <wsutil/buffer.h>
43 #include "wsutil/tempfile.h"
44 #include "wsutil/os_version_info.h"
45 #include "ws_version_info.h"
46 #include "wsutil/str_util.h"
50 #include "nettrace_3gpp_32_423.h"
53 * Impose a not-too-large limit on the maximum file size, to avoid eating
54 * up 99% of the (address space, swap partition, disk space for swap/page
55 * files); if we were to return smaller chunks and let the dissector do
56 * reassembly, it would *still* have to allocate a buffer the size of
57 * the file, so it's not as if we'd never try to allocate a buffer the
58 * size of the file. Laeve space for the exported PDU tag 12 bytes.
60 #define MAX_FILE_SIZE (G_MAXINT-12)
62 static const guint8 xml_magic[] = { '<', '?', 'x', 'm', 'l' };
63 static const guint8 Threegpp_doc_no[] = { '3', '2', '.', '4', '2', '3' };
65 typedef struct nettrace_3gpp_32_423_file_info {
68 } nettrace_3gpp_32_423_file_info_t;
70 /* From epan/address.h Types of port numbers Wireshark knows about. */
72 PT_NONE, /* no port number */
77 PT_IPX, /* IPX sockets */
78 PT_NCP, /* NCP connection */
79 PT_EXCHG, /* Fibre Channel exchange */
80 PT_DDP, /* DDP AppleTalk connection */
82 PT_IDP, /* XNS IDP sockets */
83 PT_TIPC, /* TIPC PORT */
84 PT_USB, /* USB endpoint 0xffff means the host */
86 PT_IBQP, /* Infiniband QP number */
91 typedef struct exported_pdu_info {
92 guint32 precense_flags;
93 /*const char* proto_name;*/
98 port_type ptype; /* epan/address.h port_type valid for both src and dst*/
106 }exported_pdu_info_t ;
108 /* From epan/epxported_pdu.h*/
109 #define EXP_PDU_TAG_END_OF_OPT 0 /**< End-of-options Tag. */
111 #define EXP_PDU_TAG_OPTIONS_LENGTH 10 /**< Total length of the options excluding this TLV */
112 #define EXP_PDU_TAG_PROTO_NAME 12 /**< The value part should be an ASCII non NULL terminated string
113 * of the registered dissector used by Wireshark e.g "sip"
114 * Will be used to call the next dissector.
116 #define EXP_PDU_TAG_DISSECTOR_TABLE_NAME 14 /**< The value part should be an ASCII non NULL terminated string
117 * containing the dissector table name given
118 * during registration, e.g "gsm_map.v3.arg.opcode"
119 * Will be used to call the next dissector.
122 #define EXP_PDU_TAG_IPV4_SRC 20
123 #define EXP_PDU_TAG_IPV4_DST 21
124 #define EXP_PDU_TAG_SRC_PORT 25
125 #define EXP_PDU_TAG_PORT_TYPE 24 /**< value part is port_type enum from epan/address.h */
126 #define EXP_PDU_TAG_DST_PORT 26
127 #define EXP_PDU_TAG_SS7_OPC 28
128 #define EXP_PDU_TAG_SS7_DPC 29
130 #define EXP_PDU_TAG_ORIG_FNO 30
132 #define EXP_PDU_TAG_DVBCI_EVT 31
134 #define EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL 32 /**< value part is the numeric value to be used calling the dissector table
135 * given with tag EXP_PDU_TAG_DISSECTOR_TABLE_NAME, must follow emediatly after the table tag.
138 #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
139 * COL_PROTOCOL might not be filled in.
142 #define EXP_PDU_TAG_IP_SRC_BIT 0x01
143 #define EXP_PDU_TAG_IP_DST_BIT 0x02
144 #define EXP_PDU_TAG_SRC_PORT_BIT 0x04
145 #define EXP_PDU_TAG_DST_PORT_BIT 0x08
146 #define EXP_PDU_TAG_SS7_OPC_BIT 0x20
147 #define EXP_PDU_TAG_SS7_DPC_BIT 0x40
148 #define EXP_PDU_TAG_ORIG_FNO_BIT 0x80
150 /* 2nd byte of optional tags bitmap */
151 #define EXP_PDU_TAG_DVBCI_EVT_BIT 0x0100
152 #define EXP_PDU_TAG_COL_PROT_BIT 0x0200
154 #define EXP_PDU_TAG_IPV4_SRC_LEN 4
155 #define EXP_PDU_TAG_IPV4_DST_LEN 4
156 #define EXP_PDU_TAG_PORT_TYPE_LEN 4
157 #define EXP_PDU_TAG_SRC_PORT_LEN 4
158 #define EXP_PDU_TAG_DST_PORT_LEN 4
162 nettrace_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
164 struct Buffer *frame_buffer_saved;
167 nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
169 frame_buffer_saved = file_info->wth_tmp_file->frame_buffer;
170 file_info->wth_tmp_file->frame_buffer = wth->frame_buffer;
171 /* we read the created pcapng file instead */
172 result = wtap_read(file_info->wth_tmp_file, err, err_info, data_offset);
173 file_info->wth_tmp_file->frame_buffer = frame_buffer_saved;
176 wth->phdr.rec_type = file_info->wth_tmp_file->phdr.rec_type;
177 wth->phdr.presence_flags = file_info->wth_tmp_file->phdr.presence_flags;
178 wth->phdr.ts = file_info->wth_tmp_file->phdr.ts;
179 wth->phdr.caplen = file_info->wth_tmp_file->phdr.caplen;
180 wth->phdr.len = file_info->wth_tmp_file->phdr.len;
181 wth->phdr.pkt_encap = file_info->wth_tmp_file->phdr.pkt_encap;
182 wth->phdr.pkt_tsprec = file_info->wth_tmp_file->phdr.pkt_tsprec;
183 wth->phdr.interface_id = file_info->wth_tmp_file->phdr.interface_id;
184 wth->phdr.opt_comment = file_info->wth_tmp_file->phdr.opt_comment;
185 wth->phdr.drop_count = file_info->wth_tmp_file->phdr.drop_count;
186 wth->phdr.pack_flags = file_info->wth_tmp_file->phdr.pack_flags;
187 wth->phdr.ft_specific_data = file_info->wth_tmp_file->phdr.ft_specific_data;
193 nettrace_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
195 struct Buffer *frame_buffer_saved;
197 nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
199 frame_buffer_saved = file_info->wth_tmp_file->frame_buffer;
200 file_info->wth_tmp_file->frame_buffer = wth->frame_buffer;
202 result = wtap_seek_read(file_info->wth_tmp_file, seek_off, phdr, buf, err, err_info);
203 file_info->wth_tmp_file->frame_buffer = frame_buffer_saved;
208 /* classic wtap: close capture file */
210 nettrace_close(wtap *wth)
212 nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
214 wtap_close(file_info->wth_tmp_file);
216 /* delete the temp file */
217 ws_unlink(file_info->tmpname);
221 /* This attribute specification contains a timestamp that refers to the start of the
222 * first trace data that is stored in this file.
224 * It is a complete timestamp including day, time and delta UTC hour. E.g.
225 * "2001-09-11T09:30:47-05:00".
228 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
231 nettrace_parse_begin_time(guint8 *curr_pos, struct wtap_pkthdr *phdr)
234 guint year, month, day, hour, minute, second, ms;
238 static const guint days_in_month[12] = {
239 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
242 guint8 *prev_pos, *next_pos;
246 next_pos = strstr(curr_pos, "\"/>");
247 length = (int)(next_pos - prev_pos);
252 /* Scan for all fields */
253 scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u%3d:%2u",
254 &year, &month, &day, &hour, &minute, &second, &UTCdiffh, &UTCdiffm);
257 if (scan_found != 8) {
258 /* Found this format in a file:
259 * beginTime="2013-09-11T15:45:00,666+02:00"/>
261 scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u,%3u%3d:%2u",
262 &year, &month, &day, &hour, &minute, &second, &ms, &UTCdiffh, &UTCdiffm);
264 if (scan_found == 9) {
265 phdr->ts.nsecs = ms * 1000;
266 /* Use the code below to set the time stamp */
269 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
272 g_warning("Failed to parse second time format, scan_found %u", scan_found);
276 if (scan_found == 8) {
278 /* Only set time if we managed to parse it*/
279 /* Fill in remaining fields and return it in a time_t */
280 tm.tm_year = year - 1900;
281 if (month < 1 || month > 12) {
282 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
285 g_warning("Failed to parse time, month is %u", month);
288 tm.tm_mon = month - 1; /* Zero count*/
289 if (day > ((month == 2 && isleap(year)) ? 29 : days_in_month[month - 1])) {
290 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
293 g_warning("Failed to parse time, %u-%02u-%2u is not a valid day",
299 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
302 g_warning("Failed to parse time, hour is %u", hour);
307 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
310 g_warning("Failed to parse time, minute is %u", minute);
316 * Yes, 60, for leap seconds - POSIX's and Windows'
317 * refusal to believe in them nonwithstanding.
319 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
322 g_warning("Failed to parse time, second is %u", second);
326 tm.tm_isdst = -1; /* daylight saving time info not known */
328 /* Get seconds from this time */
329 phdr->presence_flags = WTAP_HAS_TS;
330 phdr->ts.secs = mktime(&tm);
332 UTCdiffsec = (abs(UTCdiffh) * 60 * 60) + (UTCdiffm * 60);
335 phdr->ts.secs = phdr->ts.secs - UTCdiffsec;
337 phdr->ts.secs = phdr->ts.secs + UTCdiffsec;
340 g_warning("Failed to parse time, only %u fields", scan_found);
341 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
348 /* Parsing something like
350 * protocol="Diameter"
352 * [truncated]010001244000012C01000...
355 static wtap_open_return_val
356 write_packet_data(wtap_dumper *wdh, struct wtap_pkthdr *phdr, int *err, gchar **err_info, guint8 *file_buf, time_t start_time, int ms, exported_pdu_info_t *exported_pdu_info, char name_str[64])
358 char *curr_pos, *next_pos;
359 char proto_name_str[16];
360 char dissector_table_str[32];
361 int dissector_table_val=0;
363 int proto_str_len, dissector_table_str_len, raw_data_len, pkt_data_len, exp_pdu_tags_len, i, j;
367 gboolean port_type_defined = FALSE;
368 gboolean use_proto_table = FALSE;
370 memset(proto_name_str, 0, sizeof(proto_name_str));
371 /* Extract the protocol name */
372 curr_pos = strstr(file_buf, "protocol=\"");
374 return WTAP_OPEN_ERROR;
376 curr_pos = curr_pos + 10;
377 next_pos = strstr(curr_pos, "\"");
378 proto_str_len = (int)(next_pos - curr_pos);
379 if (proto_str_len > 15){
380 return WTAP_OPEN_ERROR;
383 g_strlcpy(proto_name_str, curr_pos, proto_str_len+1);
384 ascii_strdown_inplace(proto_name_str);
386 /* Do string matching and replace with Wiresharks protocol name */
387 if (strcmp(proto_name_str, "gtpv2-c") == 0){
388 /* Change to gtpv2 */
389 proto_name_str[5] = '\0';
390 proto_name_str[6] = '\0';
393 /* XXX Do we need to check for function="S1" */
394 if (strcmp(proto_name_str, "nas") == 0){
395 /* Change to nas-eps_plain */
396 g_strlcpy(proto_name_str, "nas-eps_plain", 14);
397 proto_name_str[13] = '\0';
400 if (strcmp(proto_name_str, "map") == 0) {
401 /* For /GSM) map, it looks like the message data is stored like SendAuthenticationInfoArg
402 * use the GSM MAP dissector table to dissect the content.
404 exported_pdu_info->proto_col_str = g_strdup("GSM MAP");
406 if (strcmp(name_str, "sai_request") == 0) {
407 use_proto_table = TRUE;
408 g_strlcpy(dissector_table_str, "gsm_map.v3.arg.opcode", 22);
409 dissector_table_str[21] = '\0';
410 dissector_table_str_len = 21;
411 dissector_table_val = 56;
412 exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
414 else if (strcmp(name_str, "sai_response") == 0) {
415 use_proto_table = TRUE;
416 g_strlcpy(dissector_table_str, "gsm_map.v3.res.opcode", 22);
417 dissector_table_str[21] = '\0';
418 dissector_table_str_len = 21;
419 dissector_table_val = 56;
420 exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
423 /* Find the start of the raw data*/
424 curr_pos = strstr(next_pos, ">") + 1;
425 next_pos = strstr(next_pos, "<");
427 raw_data_len = (int)(next_pos - curr_pos);
429 /* Calculate the space needed for exp pdu tags*/
430 if (use_proto_table == FALSE) {
431 tag_str_len = (proto_str_len + 3) & 0xfffffffc;
432 exp_pdu_tags_len = tag_str_len + 4;
434 tag_str_len = (dissector_table_str_len + 3) & 0xfffffffc;
435 exp_pdu_tags_len = tag_str_len + 4;
436 /* Add EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL + length*/
437 exp_pdu_tags_len = exp_pdu_tags_len + 4 + 4;
440 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
441 exp_pdu_tags_len += 4 + (int)strlen(exported_pdu_info->proto_col_str);
444 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
445 exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_SRC_LEN;
447 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
448 if (!port_type_defined) {
449 exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
450 port_type_defined = TRUE;
452 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
455 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
456 exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_DST_LEN;
459 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
460 if (!port_type_defined) {
461 exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
463 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
466 port_type_defined = FALSE;
468 /* Allocate the packet buf */
469 pkt_data_len = raw_data_len / 2;
470 packet_buf = (guint8 *)g_malloc0(pkt_data_len + exp_pdu_tags_len +4);
472 /* Fill packet buff */
473 if (use_proto_table == FALSE) {
475 packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
477 packet_buf[3] = tag_str_len;
478 for (i = 4, j = 0; j < tag_str_len; i++, j++) {
479 packet_buf[i] = proto_name_str[j];
483 packet_buf[1] = 14; /* EXP_PDU_TAG_DISSECTOR_TABLE_NAME */
485 packet_buf[3] = tag_str_len;
486 for (i = 4, j = 0; j < tag_str_len; i++, j++) {
487 packet_buf[i] = dissector_table_str[j];
491 packet_buf[i] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
495 packet_buf[i] = 4; /* tag length */;
503 packet_buf[i] = dissector_table_val;
507 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
510 packet_buf[i] = EXP_PDU_TAG_COL_PROT_TEXT;
514 packet_buf[i] = (guint8)strlen(exported_pdu_info->proto_col_str);
516 for (j = 0; j < (int)strlen(exported_pdu_info->proto_col_str); i++, j++) {
517 packet_buf[i] = exported_pdu_info->proto_col_str[j];
519 g_free(exported_pdu_info->proto_col_str);
523 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
526 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC;
530 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC_LEN; /* tag length */;
532 packet_buf[i] = exported_pdu_info->src_ipv4_d1;
534 packet_buf[i] = exported_pdu_info->src_ipv4_d2;
536 packet_buf[i] = exported_pdu_info->src_ipv4_d3;
538 packet_buf[i] = exported_pdu_info->src_ipv4_d4;
542 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
543 if (!port_type_defined) {
544 port_type_defined = TRUE;
547 packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
551 packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
553 packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
555 packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
557 packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
559 packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
564 packet_buf[i] = EXP_PDU_TAG_SRC_PORT;
568 packet_buf[i] = EXP_PDU_TAG_SRC_PORT_LEN; /* tag length */;
570 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
572 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
574 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
576 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
580 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
583 packet_buf[i] = EXP_PDU_TAG_IPV4_DST;
587 packet_buf[i] = EXP_PDU_TAG_IPV4_DST_LEN; /* tag length */;
589 packet_buf[i] = exported_pdu_info->dst_ipv4_d1;
591 packet_buf[i] = exported_pdu_info->dst_ipv4_d2;
593 packet_buf[i] = exported_pdu_info->dst_ipv4_d3;
595 packet_buf[i] = exported_pdu_info->dst_ipv4_d4;
599 if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
600 if (!port_type_defined) {
603 packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
607 packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
609 packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
611 packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
613 packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
615 packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
620 packet_buf[i] = EXP_PDU_TAG_DST_PORT;
624 packet_buf[i] = EXP_PDU_TAG_DST_PORT_LEN; /* tag length */;
626 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
628 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
630 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
632 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
636 /* Add end of options */
645 exp_pdu_tags_len = exp_pdu_tags_len + 4;
647 /* Convert the hex raw msg data to binary and write to the packet buf*/
648 for (; i < (pkt_data_len + exp_pdu_tags_len); i++){
650 val1 = g_ascii_xdigit_value(chr);
653 val2 = g_ascii_xdigit_value(chr);
654 if ((val1 != -1) && (val2 != -1)){
655 packet_buf[i] = ((guint8)val1 * 16) + val2;
658 /* Something wrong, bail out */
660 return WTAP_OPEN_ERROR;
664 /* Construct the phdr */
665 memset(phdr, 0, sizeof(struct wtap_pkthdr));
666 phdr->rec_type = REC_TYPE_PACKET;
667 if (start_time == 0) {
668 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
672 phdr->presence_flags = WTAP_HAS_TS;
673 phdr->ts.secs = start_time;
674 phdr->ts.nsecs = ms * 1000000;
677 phdr->caplen = pkt_data_len + exp_pdu_tags_len;
678 phdr->len = pkt_data_len + exp_pdu_tags_len;
680 if (!wtap_dump(wdh, phdr, packet_buf, err, err_info)) {
683 case WTAP_ERR_UNWRITABLE_REC_DATA:
691 return WTAP_OPEN_ERROR;
695 return WTAP_OPEN_MINE;
699 * Opens an .xml file with Trace data formated according to 3GPP TS 32.423 and converts it to
700 * an "Exported PDU type file with the entire xml file as the first "packet" appending the
701 * raw messages as subsequent packages to be dissected by wireshark.
703 static wtap_open_return_val
704 create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_423_file_info_t *file_info)
707 wtap_dumper* wdh_exp_pdu;
708 int exp_pdu_file_err;
709 wtap_open_return_val result = WTAP_OPEN_MINE;
712 GArray *shb_hdrs = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
713 wtap_block_t shb_hdr;
714 wtapng_iface_descriptions_t *idb_inf = NULL;
715 wtap_block_t int_data;
716 wtapng_if_descr_mandatory_t *int_data_mand;
717 GString *os_info_str;
720 guint8 *packet_buf = NULL;
722 gchar *wrt_err_info = NULL;
723 struct wtap_pkthdr phdr;
727 gboolean do_random = FALSE;
728 char *curr_pos, *next_msg_pos, *next_pos, *prev_pos;
732 /* Info to build exported_pdu tags*/
733 exported_pdu_info_t exported_pdu_info;
735 exported_pdu_info.precense_flags = 0;
736 exported_pdu_info.src_ipv4_d1 = 0;
737 exported_pdu_info.src_ipv4_d2 = 0;
738 exported_pdu_info.src_ipv4_d3 = 0;
739 exported_pdu_info.src_ipv4_d4 = 0;
740 exported_pdu_info.ptype = PT_NONE;
741 exported_pdu_info.src_port = 0;
742 exported_pdu_info.dst_ipv4_d1 = 0;
743 exported_pdu_info.dst_ipv4_d2 = 0;
744 exported_pdu_info.dst_ipv4_d3 = 0;
745 exported_pdu_info.dst_ipv4_d4 = 0;
746 exported_pdu_info.dst_port = 0;
747 exported_pdu_info.proto_col_str = NULL;
749 import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_", NULL);
751 /* Now open a file and dump to it */
752 /* Create data for SHB */
753 os_info_str = g_string_new("");
754 get_os_version_info(os_info_str);
756 shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
758 wtap_block_add_string_option(shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
759 strlen("File converted to Exported PDU format during opening"));
761 * UTF-8 string containing the name of the operating system used to create
764 opt_len = os_info_str->len;
765 wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
768 * UTF-8 string containing the name of the application used to create
771 wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
773 /* Add header to the array */
774 g_array_append_val(shb_hdrs, shb_hdr);
777 /* Create fake IDB info */
778 idb_inf = g_new(wtapng_iface_descriptions_t, 1);
779 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
781 /* create the fake interface data */
782 int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
783 int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
784 int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
785 int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
786 int_data_mand->link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
787 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE;
788 wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
789 int_data_mand->num_stat_entries = 0; /* Number of ISB:s */
790 int_data_mand->interface_statistics = NULL;
792 g_array_append_val(idb_inf->interface_data, int_data);
794 wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU,
795 WTAP_MAX_PACKET_SIZE, FALSE, shb_hdrs, idb_inf, NULL, &exp_pdu_file_err);
796 if (wdh_exp_pdu == NULL) {
797 result = WTAP_OPEN_ERROR;
801 /* OK we've opend a new pcap-ng file and written the headers, time to do the packets, strt by finding the file size */
803 if ((file_size = wtap_file_size(wth, err)) == -1) {
804 result = WTAP_OPEN_ERROR;
808 if (file_size > MAX_FILE_SIZE) {
810 * Don't blow up trying to allocate space for an
811 * immensely-large file.
813 *err = WTAP_ERR_BAD_FILE;
814 *err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
815 file_size, MAX_FILE_SIZE);
816 result = WTAP_OPEN_ERROR;
819 packet_size = (int)file_size;
820 /* Allocate the packet buffer
821 * (the whole file + Exported PDU tag "protocol" and
822 * the string "xml" + 1 filler to end on 4 byte boundary for the tag
823 * + End of options 4 bytes
825 /* XXX add the length of exported bdu tag(s) here */
826 packet_buf = (guint8 *)g_malloc(packet_size + 12 + 1);
829 packet_buf[1] = EXP_PDU_TAG_PROTO_NAME;
842 if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
843 result = WTAP_OPEN_ERROR;
847 /* Null-terminate buffer; we'll be processing it as a string. */
848 packet_buf[packet_size + 12] = '\0';
850 /* Create the packet header */
851 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
853 /* Read the file header of the input file, currently we only need the beginTime*/
855 /* Advance *packet_buf to point at the raw file data */
856 curr_pos = packet_buf + 12;
857 /* Find the file header */
858 curr_pos = strstr(curr_pos, "<fileHeader");
859 curr_pos = curr_pos + 11;
861 /* Find start time */
862 curr_pos = strstr(curr_pos, "<traceCollec beginTime=\"");
863 curr_pos = curr_pos + 24;
865 curr_pos = nettrace_parse_begin_time(curr_pos, &phdr);
867 start_time = phdr.ts.secs;
869 /* set rest of the pkt hdr data */
870 phdr.rec_type = REC_TYPE_PACKET;
872 phdr.caplen = packet_size + 12;
873 phdr.len = packet_size + 12;
875 /* XXX: report errors! */
876 if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
879 case WTAP_ERR_UNWRITABLE_REC_DATA:
880 g_free(wrt_err_info);
887 result = WTAP_OPEN_ERROR;
891 /* Lets add the raw messages as packets after the main "packet" with the whole file */
892 while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
893 wtap_open_return_val temp_val;
894 /* Clear for each itteration */
895 exported_pdu_info.precense_flags = 0;
896 exported_pdu_info.ptype = PT_NONE;
898 curr_pos = curr_pos + 4;
899 next_msg_pos = strstr(curr_pos, "</msg>");
901 /* Somethings wrong, bail out */
904 next_msg_pos = next_msg_pos + 6;
905 /* Check if we have a time stamp "changeTime"
906 * expressed in number of seconds and milliseconds (nbsec.ms).
910 /* See if we have a "name" */
911 curr_pos = strstr(curr_pos, "name=");
912 if ((curr_pos) && (curr_pos < next_msg_pos)) {
913 /* extract the name */
914 curr_pos = curr_pos + 6;
915 next_pos = strstr(curr_pos, "\"");
916 name_str_len = (int)(next_pos - curr_pos);
917 if (name_str_len > 63) {
918 return WTAP_OPEN_ERROR;
921 g_strlcpy(name_str, curr_pos, name_str_len + 1);
922 ascii_strdown_inplace(name_str);
928 curr_pos = strstr(curr_pos, "changeTime");
929 /* Check if we have the tag or if we pased the end of the current message */
930 if ((curr_pos)&&(curr_pos < next_msg_pos)){
931 curr_pos = curr_pos + 12;
932 scan_found = sscanf(curr_pos, "%u.%u",&second, &ms);
934 if ((scan_found == 2) && (start_time != 0)) {
935 start_time = start_time + second;
940 /* Check if we have "<initiator>"
941 * It might contain an address
944 curr_pos = strstr(curr_pos, "<initiator>");
945 /* Check if we have the tag or if we pased the end of the current message */
946 if ((curr_pos) && (curr_pos < next_msg_pos)) {
947 curr_pos = curr_pos + 11;
948 next_pos = strstr(curr_pos, "</initiator>");
950 curr_pos = strstr(curr_pos, "address");
951 if ((curr_pos) && (curr_pos < next_pos)) {
952 guint d1, d2, d3, d4, port;
955 curr_pos = curr_pos + 7;
956 /* Excample from one trace, unsure if it's generic...
957 * {address == 192.168.73.1, port == 5062, transport == Udp}
959 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
960 &d1, &d2, &d3, &d4, &port, transp_str);
961 if (scan_found == 6) {
962 exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_SRC_BIT + EXP_PDU_TAG_SRC_PORT_BIT;
963 exported_pdu_info.src_ipv4_d1 = d1;
964 exported_pdu_info.src_ipv4_d2 = d2;
965 exported_pdu_info.src_ipv4_d3 = d3;
966 exported_pdu_info.src_ipv4_d4 = d4;
968 /* Only add port_type once */
969 if(exported_pdu_info.ptype == PT_NONE){
970 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0) exported_pdu_info.ptype = PT_UDP;
971 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0) exported_pdu_info.ptype = PT_TCP;
972 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0) exported_pdu_info.ptype = PT_SCTP;
974 exported_pdu_info.src_port = port;
976 g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
979 /* address not found*/
983 /*"<initiator>" not found */
987 /* Check if we have "<target>"
988 * It might contain an address
991 curr_pos = strstr(curr_pos, "<target>");
992 /* Check if we have the tag or if we pased the end of the current message */
993 if ((curr_pos) && (curr_pos < next_msg_pos)) {
994 curr_pos = curr_pos + 8;
995 next_pos = strstr(curr_pos, "</target>");
997 curr_pos = strstr(curr_pos, "address");
998 if ((curr_pos) && (curr_pos < next_pos)) {
999 guint d1, d2, d3, d4, port;
1002 curr_pos = curr_pos + 7;
1003 /* Excample from one trace, unsure if it's generic...
1004 * {address == 192.168.73.1, port == 5062, transport == Udp}
1006 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
1007 &d1, &d2, &d3, &d4, &port, transp_str);
1008 if (scan_found == 6) {
1009 exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_DST_BIT + EXP_PDU_TAG_DST_PORT_BIT;
1010 exported_pdu_info.dst_ipv4_d1 = d1;
1011 exported_pdu_info.dst_ipv4_d2 = d2;
1012 exported_pdu_info.dst_ipv4_d3 = d3;
1013 exported_pdu_info.dst_ipv4_d4 = d4;
1014 /* Only add port_type once */
1015 if (exported_pdu_info.ptype == PT_NONE) {
1016 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0) exported_pdu_info.ptype = PT_UDP;
1017 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0) exported_pdu_info.ptype = PT_TCP;
1018 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0) exported_pdu_info.ptype = PT_SCTP;
1020 exported_pdu_info.dst_port = port;
1022 g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
1026 /* address not found */
1027 curr_pos = next_pos;
1030 /* "<target>" not found */
1031 curr_pos = prev_pos;
1034 /* Do we have a raw msg?) */
1035 curr_pos = strstr(curr_pos, "<rawMsg");
1037 /* No rawMsg, continue */
1038 curr_pos = next_msg_pos;
1041 curr_pos = curr_pos + 7;
1042 /* Add the raw msg*/
1043 temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos, start_time, ms, &exported_pdu_info, name_str);
1044 if (temp_val != WTAP_OPEN_MINE){
1048 curr_pos = next_msg_pos;
1051 /* Close the written file*/
1052 if (!wtap_dump_close(wdh_exp_pdu, err)){
1053 result = WTAP_OPEN_ERROR;
1057 /* Now open the file for reading */
1059 /* Find out if random read was requested */
1060 if (wth->random_fh){
1063 file_info->wth_tmp_file =
1064 wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);
1066 if (!file_info->wth_tmp_file){
1067 result = WTAP_OPEN_ERROR;
1072 g_free(wrt_err_info);
1074 wtap_block_array_free(shb_hdrs);
1075 wtap_free_idb_info(idb_inf);
1080 wtap_open_return_val
1081 nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
1083 char magic_buf[512+1]; /* increase buffer size when needed */
1086 nettrace_3gpp_32_423_file_info_t *file_info;
1087 wtap_open_return_val temp_val;
1090 bytes_read = file_read(magic_buf, 512, wth->fh);
1092 if (bytes_read < 0) {
1093 *err = file_error(wth->fh, err_info);
1094 return WTAP_OPEN_ERROR;
1096 if (bytes_read == 0){
1097 return WTAP_OPEN_NOT_MINE;
1100 if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
1101 return WTAP_OPEN_NOT_MINE;
1104 /* Null-terminate buffer; we'll be processing it as a string. */
1105 magic_buf[512] = '\0';
1107 /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
1108 curr_pos = strstr(magic_buf, "fileFormatVersion");
1111 return WTAP_OPEN_NOT_MINE;
1114 if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
1115 return WTAP_OPEN_NOT_MINE;
1118 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1119 return WTAP_OPEN_ERROR;
1121 /* Ok it's our file, open a temp file and do the conversion */
1122 file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
1123 temp_val = create_temp_pcapng_file(wth, err, err_info, file_info);
1125 if (temp_val != WTAP_OPEN_MINE){
1129 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1130 return WTAP_OPEN_ERROR;
1132 /* Copy data from the temp file wth */
1133 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));
1135 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423;
1136 wth->file_encap = file_info->wth_tmp_file->file_encap;
1137 wth->file_tsprec = file_info->wth_tmp_file->file_tsprec;
1138 wth->subtype_read = nettrace_read;
1139 wth->subtype_seek_read = nettrace_seek_read;
1140 wth->subtype_close = nettrace_close;
1141 wth->snapshot_length = 0;
1143 wth->priv = (void*)file_info;
1145 return WTAP_OPEN_MINE;
1150 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1155 * indent-tabs-mode: t
1158 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1159 * :indentSize=8:tabSize=8:noTabs=false: