Remove write capabilities from wtap_optionblocks.
[metze/wireshark/wip.git] / wiretap / nettrace_3gpp_32_423.c
1 /* nettrace_3gpp_32_423.c
2  *
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).
5  *
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.
10  *
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.
15  *
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.
19  *
20  * Ref: http://www.3gpp.org/DynaReport/32423.htm
21  */
22
23 #include "config.h"
24
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37
38 #include "wtap-int.h"
39 #include "file_wrappers.h"
40 #include "pcap-encap.h"
41
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"
47
48
49 #include "pcapng.h"
50 #include "nettrace_3gpp_32_423.h"
51
52 /*
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.
59 */
60 #define MAX_FILE_SIZE   (G_MAXINT-12)
61
62 static const guint8 xml_magic[] = { '<', '?', 'x', 'm', 'l' };
63 static const guint8 Threegpp_doc_no[] = { '3', '2', '.', '4', '2', '3' };
64
65 typedef struct nettrace_3gpp_32_423_file_info {
66         char *tmpname;
67         wtap *wth_tmp_file;
68 } nettrace_3gpp_32_423_file_info_t;
69
70 /* From epan/address.h Types of port numbers Wireshark knows about. */
71 typedef enum {
72         PT_NONE,            /* no port number */
73         PT_SCTP,            /* SCTP */
74         PT_TCP,             /* TCP */
75         PT_UDP,             /* UDP */
76         PT_DCCP,            /* DCCP */
77         PT_IPX,             /* IPX sockets */
78         PT_NCP,             /* NCP connection */
79         PT_EXCHG,           /* Fibre Channel exchange */
80         PT_DDP,             /* DDP AppleTalk connection */
81         PT_SBCCS,           /* FICON */
82         PT_IDP,             /* XNS IDP sockets */
83         PT_TIPC,            /* TIPC PORT */
84         PT_USB,             /* USB endpoint 0xffff means the host */
85         PT_I2C,
86         PT_IBQP,            /* Infiniband QP number */
87         PT_BLUETOOTH,
88         PT_TDMOP
89 } port_type;
90
91 typedef struct exported_pdu_info {
92         guint32 precense_flags;
93         /*const char* proto_name;*/
94         guint8 src_ipv4_d1;
95         guint8 src_ipv4_d2;
96         guint8 src_ipv4_d3;
97         guint8 src_ipv4_d4;
98         port_type ptype; /* epan/address.h port_type valid for both src and dst*/
99         guint32 src_port;
100         guint8 dst_ipv4_d1;
101         guint8 dst_ipv4_d2;
102         guint8 dst_ipv4_d3;
103         guint8 dst_ipv4_d4;
104         guint32 dst_port;
105         char* proto_col_str;
106 }exported_pdu_info_t ;
107
108 /* From epan/epxported_pdu.h*/
109 #define EXP_PDU_TAG_END_OF_OPT         0 /**< End-of-options Tag. */
110 /* 1 - 9 reserved */
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.
115 */
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.
120 */
121
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
129
130 #define EXP_PDU_TAG_ORIG_FNO        30
131
132 #define EXP_PDU_TAG_DVBCI_EVT       31
133
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.
136 */
137
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.
140 */
141
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
149
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
153
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
159
160
161 static gboolean
162 nettrace_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
163 {
164         struct Buffer               *frame_buffer_saved;
165         gboolean result;
166
167         nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
168
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;
174         if (!result)
175                 return result;
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;
188
189         return result;
190 }
191
192 static gboolean
193 nettrace_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
194 {
195         struct Buffer               *frame_buffer_saved;
196         gboolean result;
197         nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
198
199         frame_buffer_saved = file_info->wth_tmp_file->frame_buffer;
200         file_info->wth_tmp_file->frame_buffer = wth->frame_buffer;
201
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;
204
205         return result;
206 }
207
208 /* classic wtap: close capture file */
209 static void
210 nettrace_close(wtap *wth)
211 {
212         nettrace_3gpp_32_423_file_info_t *file_info = (nettrace_3gpp_32_423_file_info_t *)wth->priv;
213
214         wtap_close(file_info->wth_tmp_file);
215
216         /*Clear the shb info, it's been freed by wtap_close*/
217         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_COMMENT, NULL, 0);
218         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_SHB_HARDWARE, NULL, 0);
219         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_SHB_OS, NULL, 0);
220         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_SHB_USERAPPL, NULL, 0);
221
222         /* delete the temp file */
223         ws_unlink(file_info->tmpname);
224
225 }
226
227 /* This attribute specification contains a timestamp that refers to the start of the
228 * first trace data that is stored in this file.
229 *
230 * It is a complete timestamp including day, time and delta UTC hour. E.g.
231 * "2001-09-11T09:30:47-05:00".
232 */
233
234 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
235
236 static guint8*
237 nettrace_parse_begin_time(guint8 *curr_pos, struct wtap_pkthdr *phdr)
238 {
239         /* Time vars*/
240         guint year, month, day, hour, minute, second, ms;
241         int UTCdiffh;
242         guint UTCdiffm;
243         int scan_found;
244         static const guint days_in_month[12] = {
245             31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
246         };
247         struct tm tm;
248         guint8 *prev_pos, *next_pos;
249         int length;
250
251         prev_pos = curr_pos;
252         next_pos = strstr(curr_pos, "\"/>");
253         length = (int)(next_pos - prev_pos);
254
255         if (length < 2) {
256                 return next_pos + 3;
257         }
258         /* Scan for all fields                                  */
259         scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u%3d:%2u",
260                 &year, &month, &day, &hour, &minute, &second, &UTCdiffh, &UTCdiffm);
261
262         phdr->ts.nsecs = 0;
263         if (scan_found != 8) {
264                 /* Found this format in a file:
265                 * beginTime="2013-09-11T15:45:00,666+02:00"/>
266                 */
267                 scan_found = sscanf(curr_pos, "%4u-%2u-%2uT%2u:%2u:%2u,%3u%3d:%2u",
268                         &year, &month, &day, &hour, &minute, &second, &ms, &UTCdiffh, &UTCdiffm);
269
270                 if (scan_found == 9) {
271                         phdr->ts.nsecs = ms * 1000;
272                         /* Use the code below to set the time stamp */
273                         scan_found = 8;
274                 } else {
275                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
276                         phdr->ts.secs = 0;
277                         phdr->ts.nsecs = 0;
278                         g_warning("Failed to parse second time format, scan_found %u", scan_found);
279                         return curr_pos;
280                 }
281         }
282         if (scan_found == 8) {
283                 guint UTCdiffsec;
284                 /* Only set time if we managed to parse it*/
285                 /* Fill in remaining fields and return it in a time_t */
286                 tm.tm_year = year - 1900;
287                 if (month < 1 || month > 12) {
288                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
289                         phdr->ts.secs = 0;
290                         phdr->ts.nsecs = 0;
291                         g_warning("Failed to parse time, month is %u", month);
292                         return curr_pos;
293                 }
294                 tm.tm_mon = month - 1; /* Zero count*/
295                 if (day > ((month == 2 && isleap(year)) ? 29 : days_in_month[month - 1])) {
296                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
297                         phdr->ts.secs = 0;
298                         phdr->ts.nsecs = 0;
299                         g_warning("Failed to parse time, %u-%02u-%2u is not a valid day",
300                             year, month, day);
301                         return curr_pos;
302                 }
303                 tm.tm_mday = day;
304                 if (hour > 23) {
305                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
306                         phdr->ts.secs = 0;
307                         phdr->ts.nsecs = 0;
308                         g_warning("Failed to parse time, hour is %u", hour);
309                         return curr_pos;
310                 }
311                 tm.tm_hour = hour;
312                 if (minute > 59) {
313                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
314                         phdr->ts.secs = 0;
315                         phdr->ts.nsecs = 0;
316                         g_warning("Failed to parse time, minute is %u", minute);
317                         return curr_pos;
318                 }
319                 tm.tm_min = minute;
320                 if (second > 60) {
321                         /*
322                          * Yes, 60, for leap seconds - POSIX's and Windows'
323                          * refusal to believe in them nonwithstanding.
324                          */
325                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
326                         phdr->ts.secs = 0;
327                         phdr->ts.nsecs = 0;
328                         g_warning("Failed to parse time, second is %u", second);
329                         return curr_pos;
330                 }
331                 tm.tm_sec = second;
332                 tm.tm_isdst = -1;    /* daylight saving time info not known */
333
334                                                          /* Get seconds from this time */
335                 phdr->presence_flags = WTAP_HAS_TS;
336                 phdr->ts.secs = mktime(&tm);
337
338                 UTCdiffsec = (abs(UTCdiffh) * 60 * 60) + (UTCdiffm * 60);
339
340                 if (UTCdiffh < 0) {
341                         phdr->ts.secs = phdr->ts.secs - UTCdiffsec;
342                 } else {
343                         phdr->ts.secs = phdr->ts.secs + UTCdiffsec;
344                 }
345         } else {
346                 g_warning("Failed to parse time, only %u fields", scan_found);
347                 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
348                 phdr->ts.secs = 0;
349                 phdr->ts.nsecs = 0;
350         }
351
352         return curr_pos;
353 }
354 /* Parsing something like
355  * <rawMsg
356  *   protocol="Diameter"
357  *   version="1">
358  *    [truncated]010001244000012C01000...
359  * </rawMsg>
360  */
361 static wtap_open_return_val
362 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])
363 {
364         char *curr_pos, *next_pos;
365         char proto_name_str[16];
366         char dissector_table_str[32];
367         int dissector_table_val=0;
368         int tag_str_len = 0;
369         int proto_str_len, dissector_table_str_len, raw_data_len, pkt_data_len,  exp_pdu_tags_len, i, j;
370         guint8 *packet_buf;
371         gchar chr;
372         gint val1, val2;
373         gboolean port_type_defined = FALSE;
374         gboolean use_proto_table = FALSE;
375
376         memset(proto_name_str, 0, sizeof(proto_name_str));
377         /* Extract the protocol name */
378         curr_pos = strstr(file_buf, "protocol=\"");
379         if (!curr_pos){
380                 return WTAP_OPEN_ERROR;
381         }
382         curr_pos = curr_pos + 10;
383         next_pos = strstr(curr_pos, "\"");
384         proto_str_len = (int)(next_pos - curr_pos);
385         if (proto_str_len > 15){
386                 return WTAP_OPEN_ERROR;
387         }
388
389         g_strlcpy(proto_name_str, curr_pos, proto_str_len+1);
390         ascii_strdown_inplace(proto_name_str);
391
392         /* Do string matching and replace with Wiresharks protocol name */
393         if (strcmp(proto_name_str, "gtpv2-c") == 0){
394                 /* Change to gtpv2 */
395                 proto_name_str[5] = '\0';
396                 proto_name_str[6] = '\0';
397                 proto_str_len = 5;
398         }
399         /* XXX Do we need to check for function="S1" */
400         if (strcmp(proto_name_str, "nas") == 0){
401                 /* Change to nas-eps_plain */
402                 g_strlcpy(proto_name_str, "nas-eps_plain", 14);
403                 proto_name_str[13] = '\0';
404                 proto_str_len = 13;
405         }
406         if (strcmp(proto_name_str, "map") == 0) {
407                 /* For /GSM) map, it looks like the message data is stored like SendAuthenticationInfoArg
408                  * use the GSM MAP dissector table to dissect the content.
409                  */
410                 exported_pdu_info->proto_col_str = g_strdup("GSM MAP");
411
412                 if (strcmp(name_str, "sai_request") == 0) {
413                         use_proto_table = TRUE;
414                         g_strlcpy(dissector_table_str, "gsm_map.v3.arg.opcode", 22);
415                         dissector_table_str[21] = '\0';
416                         dissector_table_str_len = 21;
417                         dissector_table_val = 56;
418                         exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
419                 }
420                 else if (strcmp(name_str, "sai_response") == 0) {
421                         use_proto_table = TRUE;
422                         g_strlcpy(dissector_table_str, "gsm_map.v3.res.opcode", 22);
423                         dissector_table_str[21] = '\0';
424                         dissector_table_str_len = 21;
425                         dissector_table_val = 56;
426                         exported_pdu_info->precense_flags = exported_pdu_info->precense_flags + EXP_PDU_TAG_COL_PROT_BIT;
427                 }
428         }
429         /* Find the start of the raw data*/
430         curr_pos = strstr(next_pos, ">") + 1;
431         next_pos = strstr(next_pos, "<");
432
433         raw_data_len = (int)(next_pos - curr_pos);
434
435         /* Calculate the space needed for exp pdu tags*/
436         if (use_proto_table == FALSE) {
437                 tag_str_len = (proto_str_len + 3) & 0xfffffffc;
438                 exp_pdu_tags_len = tag_str_len + 4;
439         } else {
440                 tag_str_len = (dissector_table_str_len + 3) & 0xfffffffc;
441                 exp_pdu_tags_len = tag_str_len + 4;
442                 /* Add EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL + length*/
443                 exp_pdu_tags_len = exp_pdu_tags_len + 4 + 4;
444         }
445
446         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
447                 exp_pdu_tags_len += 4 + (int)strlen(exported_pdu_info->proto_col_str);
448         }
449
450         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
451                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_SRC_LEN;
452         }
453         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
454                 if (!port_type_defined) {
455                         exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
456                         port_type_defined = TRUE;
457                 }
458                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
459         }
460
461         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
462                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_IPV4_DST_LEN;
463         }
464
465         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
466                 if (!port_type_defined) {
467                         exp_pdu_tags_len += 4 + EXP_PDU_TAG_PORT_TYPE_LEN;
468                 }
469                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
470         }
471
472         port_type_defined = FALSE;
473
474         /* Allocate the packet buf */
475         pkt_data_len = raw_data_len / 2;
476         packet_buf = (guint8 *)g_malloc0(pkt_data_len + exp_pdu_tags_len +4);
477
478         /* Fill packet buff */
479         if (use_proto_table == FALSE) {
480                 packet_buf[0] = 0;
481                 packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
482                 packet_buf[2] = 0;
483                 packet_buf[3] = tag_str_len;
484                 for (i = 4, j = 0; j < tag_str_len; i++, j++) {
485                         packet_buf[i] = proto_name_str[j];
486                 }
487         }else{
488                 packet_buf[0] = 0;
489                 packet_buf[1] = 14; /* EXP_PDU_TAG_DISSECTOR_TABLE_NAME */
490                 packet_buf[2] = 0;
491                 packet_buf[3] = tag_str_len;
492                 for (i = 4, j = 0; j < tag_str_len; i++, j++) {
493                         packet_buf[i] = dissector_table_str[j];
494                 }
495                 packet_buf[i] = 0;
496                 i++;
497                 packet_buf[i] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
498                 i++;
499                 packet_buf[i] = 0;
500                 i++;
501                 packet_buf[i] = 4; /* tag length */;
502                 i++;
503                 packet_buf[i] = 0;
504                 i++;
505                 packet_buf[i] = 0;
506                 i++;
507                 packet_buf[i] = 0;
508                 i++;
509                 packet_buf[i] = dissector_table_val;
510                 i++;
511         }
512
513         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
514                 packet_buf[i] = 0;
515                 i++;
516                 packet_buf[i] = EXP_PDU_TAG_COL_PROT_TEXT;
517                 i++;
518                 packet_buf[i] = 0;
519                 i++;
520                 packet_buf[i] = (guint8)strlen(exported_pdu_info->proto_col_str);
521                 i++;
522                 for (j = 0; j < (int)strlen(exported_pdu_info->proto_col_str); i++, j++) {
523                         packet_buf[i] = exported_pdu_info->proto_col_str[j];
524                 }
525                 g_free(exported_pdu_info->proto_col_str);
526         }
527
528
529         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
530                 packet_buf[i] = 0;
531                 i++;
532                 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC;
533                 i++;
534                 packet_buf[i] = 0;
535                 i++;
536                 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC_LEN; /* tag length */;
537                 i++;
538                 packet_buf[i] = exported_pdu_info->src_ipv4_d1;
539                 i++;
540                 packet_buf[i] = exported_pdu_info->src_ipv4_d2;
541                 i++;
542                 packet_buf[i] = exported_pdu_info->src_ipv4_d3;
543                 i++;
544                 packet_buf[i] = exported_pdu_info->src_ipv4_d4;
545                 i++;
546         }
547
548         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_SRC_PORT_BIT) == EXP_PDU_TAG_SRC_PORT_BIT) {
549                 if (!port_type_defined) {
550                         port_type_defined = TRUE;
551                         packet_buf[i] = 0;
552                         i++;
553                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
554                         i++;
555                         packet_buf[i] = 0;
556                         i++;
557                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
558                         i++;
559                         packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
560                         i++;
561                         packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
562                         i++;
563                         packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
564                         i++;
565                         packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
566                         i++;
567                 }
568                 packet_buf[i] = 0;
569                 i++;
570                 packet_buf[i] = EXP_PDU_TAG_SRC_PORT;
571                 i++;
572                 packet_buf[i] = 0;
573                 i++;
574                 packet_buf[i] = EXP_PDU_TAG_SRC_PORT_LEN; /* tag length */;
575                 i++;
576                 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
577                 i++;
578                 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
579                 i++;
580                 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
581                 i++;
582                 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
583                 i++;
584         }
585
586         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
587                 packet_buf[i] = 0;
588                 i++;
589                 packet_buf[i] = EXP_PDU_TAG_IPV4_DST;
590                 i++;
591                 packet_buf[i] = 0;
592                 i++;
593                 packet_buf[i] = EXP_PDU_TAG_IPV4_DST_LEN; /* tag length */;
594                 i++;
595                 packet_buf[i] = exported_pdu_info->dst_ipv4_d1;
596                 i++;
597                 packet_buf[i] = exported_pdu_info->dst_ipv4_d2;
598                 i++;
599                 packet_buf[i] = exported_pdu_info->dst_ipv4_d3;
600                 i++;
601                 packet_buf[i] = exported_pdu_info->dst_ipv4_d4;
602                 i++;
603         }
604
605         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
606                 if (!port_type_defined) {
607                         packet_buf[i] = 0;
608                         i++;
609                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
610                         i++;
611                         packet_buf[i] = 0;
612                         i++;
613                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
614                         i++;
615                         packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
616                         i++;
617                         packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
618                         i++;
619                         packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
620                         i++;
621                         packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
622                         i++;
623                 }
624                 packet_buf[i] = 0;
625                 i++;
626                 packet_buf[i] = EXP_PDU_TAG_DST_PORT;
627                 i++;
628                 packet_buf[i] = 0;
629                 i++;
630                 packet_buf[i] = EXP_PDU_TAG_DST_PORT_LEN; /* tag length */;
631                 i++;
632                 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
633                 i++;
634                 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
635                 i++;
636                 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
637                 i++;
638                 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
639                 i++;
640         }
641
642         /* Add end of options */
643         packet_buf[i] = 0;
644         i++;
645         packet_buf[i] = 0;
646         i++;
647         packet_buf[i] = 0;
648         i++;
649         packet_buf[i] = 0;
650         i++;
651         exp_pdu_tags_len = exp_pdu_tags_len + 4;
652
653         /* Convert the hex raw msg data to binary and write to the packet buf*/
654         for (; i < (pkt_data_len + exp_pdu_tags_len); i++){
655                 chr = *curr_pos;
656                 val1 = g_ascii_xdigit_value(chr);
657                 curr_pos++;
658                 chr = *curr_pos;
659                 val2 = g_ascii_xdigit_value(chr);
660                 if ((val1 != -1) && (val2 != -1)){
661                         packet_buf[i] = ((guint8)val1 * 16) + val2;
662                 }
663                 else{
664                         /* Something wrong, bail out */
665                         g_free(packet_buf);
666                         return WTAP_OPEN_ERROR;
667                 }
668                 curr_pos++;
669         }
670         /* Construct the phdr */
671         memset(phdr, 0, sizeof(struct wtap_pkthdr));
672         phdr->rec_type = REC_TYPE_PACKET;
673         if (start_time == 0) {
674                 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
675                 phdr->ts.secs = 0;
676                 phdr->ts.nsecs = 0;
677         } else {
678                 phdr->presence_flags = WTAP_HAS_TS;
679                 phdr->ts.secs = start_time;
680                 phdr->ts.nsecs = ms * 1000000;
681         }
682
683         phdr->caplen = pkt_data_len + exp_pdu_tags_len;
684         phdr->len = pkt_data_len + exp_pdu_tags_len;
685
686         if (!wtap_dump(wdh, phdr, packet_buf, err, err_info)) {
687                 switch (*err) {
688
689                 case WTAP_ERR_UNWRITABLE_REC_DATA:
690                         g_free(err_info);
691                         break;
692
693                 default:
694                         break;
695                 }
696                 g_free(packet_buf);
697                 return WTAP_OPEN_ERROR;
698         }
699
700         g_free(packet_buf);
701         return WTAP_OPEN_MINE;
702 }
703
704 /*
705  * Opens an .xml file with Trace data formated according to 3GPP TS 32.423 and converts it to
706  * an "Exported PDU type file with the entire xml file as the first "packet" appending the
707  * raw messages as subsequent packages to be dissected by wireshark.
708  */
709 static wtap_open_return_val
710 create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_423_file_info_t *file_info)
711 {
712         int import_file_fd;
713         wtap_dumper* wdh_exp_pdu;
714         int   exp_pdu_file_err;
715         wtap_open_return_val result = WTAP_OPEN_MINE;
716
717         /* pcapng defs */
718         wtap_optionblock_t           shb_hdr = NULL;
719         wtapng_iface_descriptions_t *idb_inf = NULL;
720         wtap_optionblock_t           int_data;
721         wtapng_if_descr_mandatory_t *int_data_mand;
722         GString                     *os_info_str;
723         gint64 file_size;
724         int packet_size;
725         guint8 *packet_buf = NULL;
726         int wrt_err;
727         gchar *wrt_err_info = NULL;
728         struct wtap_pkthdr phdr;
729         time_t start_time;
730         int scan_found;
731         unsigned second, ms;
732         gboolean do_random = FALSE;
733         char *curr_pos, *next_msg_pos, *next_pos, *prev_pos;
734         int name_str_len;
735         char name_str[64];
736         gsize opt_len;
737         /* Info to build exported_pdu tags*/
738         exported_pdu_info_t  exported_pdu_info;
739
740         exported_pdu_info.precense_flags = 0;
741         exported_pdu_info.src_ipv4_d1 = 0;
742         exported_pdu_info.src_ipv4_d2 = 0;
743         exported_pdu_info.src_ipv4_d3 = 0;
744         exported_pdu_info.src_ipv4_d4 = 0;
745         exported_pdu_info.ptype = PT_NONE;
746         exported_pdu_info.src_port = 0;
747         exported_pdu_info.dst_ipv4_d1 = 0;
748         exported_pdu_info.dst_ipv4_d2 = 0;
749         exported_pdu_info.dst_ipv4_d3 = 0;
750         exported_pdu_info.dst_ipv4_d4 = 0;
751         exported_pdu_info.dst_port = 0;
752         exported_pdu_info.proto_col_str = NULL;
753
754         import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_");
755
756         /* Now open a file and dump to it */
757         /* Create data for SHB  */
758         os_info_str = g_string_new("");
759         get_os_version_info(os_info_str);
760
761         shb_hdr = wtap_optionblock_create(WTAP_OPTION_BLOCK_NG_SECTION);
762         /* options */
763         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
764                                                                                                                         strlen("File converted to Exported PDU format during opening"));
765         /*
766         * UTF-8 string containing the name of the operating system used to create
767         * this section.
768         */
769         opt_len = os_info_str->len;
770         wtap_optionblock_set_option_string(wth->shb_hdr, OPT_SHB_OS, g_string_free(os_info_str, TRUE), opt_len);
771
772         /*
773         * UTF-8 string containing the name of the application used to create
774         * this section.
775         */
776         wtap_optionblock_set_option_string_format(wth->shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
777
778         /* Create fake IDB info */
779         idb_inf = g_new(wtapng_iface_descriptions_t, 1);
780         idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_optionblock_t));
781
782         /* create the fake interface data */
783         int_data = wtap_optionblock_create(WTAP_OPTION_BLOCK_IF_DESCR);
784         int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_optionblock_get_mandatory_data(int_data);
785         int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
786         int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
787         int_data_mand->link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
788         int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE;
789         wtap_optionblock_set_option_string(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
790         int_data_mand->num_stat_entries = 0;          /* Number of ISB:s */
791         int_data_mand->interface_statistics = NULL;
792
793         g_array_append_val(idb_inf->interface_data, int_data);
794
795         wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU,
796                                           WTAP_MAX_PACKET_SIZE, FALSE, shb_hdr, idb_inf, NULL, &exp_pdu_file_err);
797         if (wdh_exp_pdu == NULL) {
798                 result = WTAP_OPEN_ERROR;
799                 goto end;
800         }
801
802         /* 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
804         if ((file_size = wtap_file_size(wth, err)) == -1) {
805                 result = WTAP_OPEN_ERROR;
806                 goto end;
807         }
808
809         if (file_size > MAX_FILE_SIZE) {
810                 /*
811                 * Don't blow up trying to allocate space for an
812                 * immensely-large file.
813                 */
814                 *err = WTAP_ERR_BAD_FILE;
815                 *err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
816                         file_size, MAX_FILE_SIZE);
817                 result = WTAP_OPEN_ERROR;
818                 goto end;
819         }
820         packet_size = (int)file_size;
821         /* Allocate the packet buffer
822         * (the whole file + Exported PDU tag "protocol" and
823         * the string "xml" + 1 filler to end on 4 byte boundary for the tag
824         * + End of options 4 bytes
825         */
826         /* XXX add the length of exported bdu tag(s) here */
827         packet_buf = (guint8 *)g_malloc(packet_size + 12 + 1);
828
829         packet_buf[0] = 0;
830         packet_buf[1] = EXP_PDU_TAG_PROTO_NAME;
831         packet_buf[2] = 0;
832         packet_buf[3] = 4;
833         packet_buf[4] = 'x';
834         packet_buf[5] = 'm';
835         packet_buf[6] = 'l';
836         packet_buf[7] = 0;
837         /* End of options */
838         packet_buf[8] = 0;
839         packet_buf[9] = 0;
840         packet_buf[10] = 0;
841         packet_buf[11] = 0;
842
843         if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
844                 result = WTAP_OPEN_ERROR;
845                 goto end;
846         }
847
848         /* Null-terminate buffer; we'll be processing it as a string. */
849         packet_buf[packet_size + 12] = '\0';
850
851         /* Create the packet header */
852         memset(&phdr, 0, sizeof(struct wtap_pkthdr));
853
854         /* Read the file header of the input file, currently we only need the beginTime*/
855
856         /* Advance *packet_buf to point at the raw file data */
857         curr_pos = packet_buf + 12;
858         /* Find the file header */
859         curr_pos = strstr(curr_pos, "<fileHeader");
860         curr_pos = curr_pos + 11;
861
862         /* Find start time */
863         curr_pos = strstr(curr_pos, "<traceCollec beginTime=\"");
864         curr_pos = curr_pos + 24;
865
866         curr_pos = nettrace_parse_begin_time(curr_pos, &phdr);
867
868         start_time = phdr.ts.secs;
869
870         /* set rest of the pkt hdr data */
871         phdr.rec_type = REC_TYPE_PACKET;
872
873         phdr.caplen = packet_size + 12;
874         phdr.len = packet_size + 12;
875
876         /* XXX: report errors! */
877         if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
878                 switch (wrt_err) {
879
880                 case WTAP_ERR_UNWRITABLE_REC_DATA:
881                         g_free(wrt_err_info);
882                         wrt_err_info = NULL;
883                         break;
884
885                 default:
886                         break;
887                 }
888                 result = WTAP_OPEN_ERROR;
889                 goto end;
890         }
891
892         /* Lets add the raw messages as packets after the main "packet" with the whole file */
893         while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
894                 wtap_open_return_val temp_val;
895                 /* Clear for each itteration */
896                 exported_pdu_info.precense_flags = 0;
897                 exported_pdu_info.ptype = PT_NONE;
898
899                 curr_pos = curr_pos + 4;
900                 next_msg_pos = strstr(curr_pos, "</msg>");
901                 if (!next_msg_pos){
902                         /* Somethings wrong, bail out */
903                         break;
904                 }
905                 next_msg_pos = next_msg_pos + 6;
906                 /* Check if we have a time stamp "changeTime"
907                  * expressed in number of seconds and milliseconds (nbsec.ms).
908                  */
909                 prev_pos = curr_pos;
910                 ms = 0;
911                 /* See if we have a "name" */
912                 curr_pos = strstr(curr_pos, "name=");
913                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
914                         /* extract the name */
915                         curr_pos = curr_pos + 6;
916                         next_pos = strstr(curr_pos, "\"");
917                         name_str_len = (int)(next_pos - curr_pos);
918                         if (name_str_len > 63) {
919                                 return WTAP_OPEN_ERROR;
920                         }
921
922                         g_strlcpy(name_str, curr_pos, name_str_len + 1);
923                         ascii_strdown_inplace(name_str);
924
925                 }
926                 else {
927                         curr_pos = prev_pos;
928                 }
929                 curr_pos = strstr(curr_pos, "changeTime");
930                 /* Check if we have the tag or if we pased the end of the current message */
931                 if ((curr_pos)&&(curr_pos < next_msg_pos)){
932                         curr_pos = curr_pos + 12;
933                         scan_found = sscanf(curr_pos, "%u.%u",&second, &ms);
934
935                         if ((scan_found == 2) && (start_time != 0)) {
936                                 start_time = start_time + second;
937                         }
938                 } else {
939                         curr_pos = prev_pos;
940                 }
941                 /* Check if we have "<initiator>"
942                 *  It might contain an address
943                 */
944                 prev_pos = curr_pos;
945                 curr_pos = strstr(curr_pos, "<initiator>");
946                 /* Check if we have the tag or if we pased the end of the current message */
947                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
948                         curr_pos = curr_pos + 11;
949                         next_pos = strstr(curr_pos, "</initiator>");
950                         /* Find address*/
951                         curr_pos = strstr(curr_pos, "address");
952                         if ((curr_pos) && (curr_pos < next_pos)) {
953                                 guint d1, d2, d3, d4, port;
954                                 char transp_str[5];
955
956                                 curr_pos = curr_pos + 7;
957                                 /* Excample from one trace, unsure if it's generic...
958                                  * {address == 192.168.73.1, port == 5062, transport == Udp}
959                                  */
960                                 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
961                                         &d1, &d2, &d3, &d4, &port, transp_str);
962                                 if (scan_found == 6) {
963                                         exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_SRC_BIT + EXP_PDU_TAG_SRC_PORT_BIT;
964                                         exported_pdu_info.src_ipv4_d1 = d1;
965                                         exported_pdu_info.src_ipv4_d2 = d2;
966                                         exported_pdu_info.src_ipv4_d3 = d3;
967                                         exported_pdu_info.src_ipv4_d4 = d4;
968
969                                         /* Only add port_type once */
970                                         if(exported_pdu_info.ptype == PT_NONE){
971                                                 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0)  exported_pdu_info.ptype = PT_UDP;
972                                                 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0)  exported_pdu_info.ptype = PT_TCP;
973                                                 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0)  exported_pdu_info.ptype = PT_SCTP;
974                                         }
975                                         exported_pdu_info.src_port = port;
976                                 } else {
977                                         g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
978                                 }
979                         } else {
980                                 /* address not found*/
981                                 curr_pos = next_pos;
982                         }
983                 } else {
984                         /*"<initiator>" not found */
985                         curr_pos = prev_pos;
986                 }
987
988                 /* Check if we have "<target>"
989                 *  It might contain an address
990                 */
991                 prev_pos = curr_pos;
992                 curr_pos = strstr(curr_pos, "<target>");
993                 /* Check if we have the tag or if we pased the end of the current message */
994                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
995                         curr_pos = curr_pos + 8;
996                         next_pos = strstr(curr_pos, "</target>");
997                         /* Find address*/
998                         curr_pos = strstr(curr_pos, "address");
999                         if ((curr_pos) && (curr_pos < next_pos)) {
1000                                 guint d1, d2, d3, d4, port;
1001                                 char transp_str[5];
1002
1003                                 curr_pos = curr_pos + 7;
1004                                 /* Excample from one trace, unsure if it's generic...
1005                                 * {address == 192.168.73.1, port == 5062, transport == Udp}
1006                                 */
1007                                 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
1008                                         &d1, &d2, &d3, &d4, &port, transp_str);
1009                                 if (scan_found == 6) {
1010                                         exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_DST_BIT + EXP_PDU_TAG_DST_PORT_BIT;
1011                                         exported_pdu_info.dst_ipv4_d1 = d1;
1012                                         exported_pdu_info.dst_ipv4_d2 = d2;
1013                                         exported_pdu_info.dst_ipv4_d3 = d3;
1014                                         exported_pdu_info.dst_ipv4_d4 = d4;
1015                                         /* Only add port_type once */
1016                                         if (exported_pdu_info.ptype == PT_NONE) {
1017                                                 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0)  exported_pdu_info.ptype = PT_UDP;
1018                                                 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0)  exported_pdu_info.ptype = PT_TCP;
1019                                                 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0)  exported_pdu_info.ptype = PT_SCTP;
1020                                         }
1021                                         exported_pdu_info.dst_port = port;
1022                                 } else {
1023                                         g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
1024                                 }
1025                         }
1026                         else {
1027                                 /* address not found */
1028                                 curr_pos = next_pos;
1029                         }
1030                 } else {
1031                         /* "<target>" not found */
1032                         curr_pos = prev_pos;
1033                 }
1034
1035                 /* Do we have a raw msg?) */
1036                 curr_pos = strstr(curr_pos, "<rawMsg");
1037                 if (!curr_pos){
1038                         /* No rawMsg, continue */
1039                         curr_pos = next_msg_pos;
1040                         continue;
1041                 }
1042                 curr_pos = curr_pos + 7;
1043                 /* Add the raw msg*/
1044                 temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos, start_time, ms, &exported_pdu_info, name_str);
1045                 if (temp_val != WTAP_OPEN_MINE){
1046                         result = temp_val;
1047                         goto end;
1048                 }
1049                 curr_pos = next_msg_pos;
1050         }
1051
1052         /* Close the written file*/
1053         if (!wtap_dump_close(wdh_exp_pdu, err)){
1054                 result = WTAP_OPEN_ERROR;
1055                 goto end;
1056         }
1057
1058         /* Now open the file for reading */
1059
1060         /* Find out if random read was requested */
1061         if (wth->random_fh){
1062                 do_random = TRUE;
1063         }
1064         file_info->wth_tmp_file =
1065                 wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);
1066
1067         if (!file_info->wth_tmp_file){
1068                 result = WTAP_OPEN_ERROR;
1069                 goto end;
1070         }
1071
1072 end:
1073         g_free(wrt_err_info);
1074         g_free(packet_buf);
1075         wtap_optionblock_free(shb_hdr);
1076         wtap_free_idb_info(idb_inf);
1077
1078         return result;
1079 }
1080
1081 wtap_open_return_val
1082 nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
1083 {
1084         char magic_buf[512+1]; /* increase buffer size when needed */
1085         int bytes_read;
1086         char *curr_pos;
1087         nettrace_3gpp_32_423_file_info_t *file_info;
1088         wtap_open_return_val temp_val;
1089
1090
1091         bytes_read = file_read(magic_buf, 512, wth->fh);
1092
1093         if (bytes_read < 0) {
1094                 *err = file_error(wth->fh, err_info);
1095                 return WTAP_OPEN_ERROR;
1096         }
1097         if (bytes_read == 0){
1098                 return WTAP_OPEN_NOT_MINE;
1099         }
1100
1101         if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
1102                 return WTAP_OPEN_NOT_MINE;
1103         }
1104
1105         /* Null-terminate buffer; we'll be processing it as a string. */
1106         magic_buf[512] = '\0';
1107
1108         /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
1109         curr_pos = strstr(magic_buf, "fileFormatVersion");
1110
1111         if (!curr_pos){
1112                 return WTAP_OPEN_NOT_MINE;
1113         }
1114         curr_pos += 19;
1115         if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
1116                 return WTAP_OPEN_NOT_MINE;
1117         }
1118
1119         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1120                 return WTAP_OPEN_ERROR;
1121
1122         /* Ok it's our file, open a temp file and do the conversion */
1123         file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
1124         temp_val = create_temp_pcapng_file(wth, err, err_info, file_info);
1125
1126         if (temp_val != WTAP_OPEN_MINE){
1127                 return temp_val;
1128         }
1129
1130         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1131                 return WTAP_OPEN_ERROR;
1132
1133         /* Copy data from the temp file wth */
1134         wtap_optionblock_copy_options(wth->shb_hdr, file_info->wth_tmp_file->shb_hdr);
1135
1136         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423;
1137         wth->file_encap = file_info->wth_tmp_file->file_encap;
1138         wth->file_tsprec = file_info->wth_tmp_file->file_tsprec;
1139         wth->subtype_read = nettrace_read;
1140         wth->subtype_seek_read = nettrace_seek_read;
1141         wth->subtype_close = nettrace_close;
1142         wth->snapshot_length = 0;
1143
1144         wth->priv = (void*)file_info;
1145
1146         return WTAP_OPEN_MINE;
1147
1148 }
1149
1150 /*
1151  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1152  *
1153  * Local variables:
1154  * c-basic-offset: 8
1155  * tab-width: 8
1156  * indent-tabs-mode: t
1157  * End:
1158  *
1159  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1160  * :indentSize=8:tabSize=8:noTabs=false:
1161  */