Do a deep copy in wtap_block_add_custom_option().
[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         /* delete the temp file */
217         ws_unlink(file_info->tmpname);
218
219 }
220
221 /* This attribute specification contains a timestamp that refers to the start of the
222 * first trace data that is stored in this file.
223 *
224 * It is a complete timestamp including day, time and delta UTC hour. E.g.
225 * "2001-09-11T09:30:47-05:00".
226 */
227
228 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
229
230 static guint8*
231 nettrace_parse_begin_time(guint8 *curr_pos, struct wtap_pkthdr *phdr)
232 {
233         /* Time vars*/
234         guint year, month, day, hour, minute, second, ms;
235         int UTCdiffh;
236         guint UTCdiffm;
237         int scan_found;
238         static const guint days_in_month[12] = {
239             31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
240         };
241         struct tm tm;
242         guint8 *prev_pos, *next_pos;
243         int length;
244
245         prev_pos = curr_pos;
246         next_pos = strstr(curr_pos, "\"/>");
247         length = (int)(next_pos - prev_pos);
248
249         if (length < 2) {
250                 return next_pos + 3;
251         }
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);
255
256         phdr->ts.nsecs = 0;
257         if (scan_found != 8) {
258                 /* Found this format in a file:
259                 * beginTime="2013-09-11T15:45:00,666+02:00"/>
260                 */
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);
263
264                 if (scan_found == 9) {
265                         phdr->ts.nsecs = ms * 1000;
266                         /* Use the code below to set the time stamp */
267                         scan_found = 8;
268                 } else {
269                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
270                         phdr->ts.secs = 0;
271                         phdr->ts.nsecs = 0;
272                         g_warning("Failed to parse second time format, scan_found %u", scan_found);
273                         return curr_pos;
274                 }
275         }
276         if (scan_found == 8) {
277                 guint UTCdiffsec;
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 */
283                         phdr->ts.secs = 0;
284                         phdr->ts.nsecs = 0;
285                         g_warning("Failed to parse time, month is %u", month);
286                         return curr_pos;
287                 }
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 */
291                         phdr->ts.secs = 0;
292                         phdr->ts.nsecs = 0;
293                         g_warning("Failed to parse time, %u-%02u-%2u is not a valid day",
294                             year, month, day);
295                         return curr_pos;
296                 }
297                 tm.tm_mday = day;
298                 if (hour > 23) {
299                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
300                         phdr->ts.secs = 0;
301                         phdr->ts.nsecs = 0;
302                         g_warning("Failed to parse time, hour is %u", hour);
303                         return curr_pos;
304                 }
305                 tm.tm_hour = hour;
306                 if (minute > 59) {
307                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
308                         phdr->ts.secs = 0;
309                         phdr->ts.nsecs = 0;
310                         g_warning("Failed to parse time, minute is %u", minute);
311                         return curr_pos;
312                 }
313                 tm.tm_min = minute;
314                 if (second > 60) {
315                         /*
316                          * Yes, 60, for leap seconds - POSIX's and Windows'
317                          * refusal to believe in them nonwithstanding.
318                          */
319                         phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
320                         phdr->ts.secs = 0;
321                         phdr->ts.nsecs = 0;
322                         g_warning("Failed to parse time, second is %u", second);
323                         return curr_pos;
324                 }
325                 tm.tm_sec = second;
326                 tm.tm_isdst = -1;    /* daylight saving time info not known */
327
328                                                          /* Get seconds from this time */
329                 phdr->presence_flags = WTAP_HAS_TS;
330                 phdr->ts.secs = mktime(&tm);
331
332                 UTCdiffsec = (abs(UTCdiffh) * 60 * 60) + (UTCdiffm * 60);
333
334                 if (UTCdiffh < 0) {
335                         phdr->ts.secs = phdr->ts.secs - UTCdiffsec;
336                 } else {
337                         phdr->ts.secs = phdr->ts.secs + UTCdiffsec;
338                 }
339         } else {
340                 g_warning("Failed to parse time, only %u fields", scan_found);
341                 phdr->presence_flags = 0; /* yes, we have no bananas^Wtime stamp */
342                 phdr->ts.secs = 0;
343                 phdr->ts.nsecs = 0;
344         }
345
346         return curr_pos;
347 }
348 /* Parsing something like
349  * <rawMsg
350  *   protocol="Diameter"
351  *   version="1">
352  *    [truncated]010001244000012C01000...
353  * </rawMsg>
354  */
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])
357 {
358         char *curr_pos, *next_pos;
359         char proto_name_str[16];
360         char dissector_table_str[32];
361         int dissector_table_val=0;
362         int tag_str_len = 0;
363         int proto_str_len, dissector_table_str_len, raw_data_len, pkt_data_len,  exp_pdu_tags_len, i, j;
364         guint8 *packet_buf;
365         gchar chr;
366         gint val1, val2;
367         gboolean port_type_defined = FALSE;
368         gboolean use_proto_table = FALSE;
369
370         memset(proto_name_str, 0, sizeof(proto_name_str));
371         /* Extract the protocol name */
372         curr_pos = strstr(file_buf, "protocol=\"");
373         if (!curr_pos){
374                 return WTAP_OPEN_ERROR;
375         }
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;
381         }
382
383         g_strlcpy(proto_name_str, curr_pos, proto_str_len+1);
384         ascii_strdown_inplace(proto_name_str);
385
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';
391                 proto_str_len = 5;
392         }
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';
398                 proto_str_len = 13;
399         }
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.
403                  */
404                 exported_pdu_info->proto_col_str = g_strdup("GSM MAP");
405
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;
413                 }
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;
421                 }
422         }
423         /* Find the start of the raw data*/
424         curr_pos = strstr(next_pos, ">") + 1;
425         next_pos = strstr(next_pos, "<");
426
427         raw_data_len = (int)(next_pos - curr_pos);
428
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;
433         } else {
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;
438         }
439
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);
442         }
443
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;
446         }
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;
451                 }
452                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
453         }
454
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;
457         }
458
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;
462                 }
463                 exp_pdu_tags_len += 4 + EXP_PDU_TAG_SRC_PORT_LEN;
464         }
465
466         port_type_defined = FALSE;
467
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);
471
472         /* Fill packet buff */
473         if (use_proto_table == FALSE) {
474                 packet_buf[0] = 0;
475                 packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
476                 packet_buf[2] = 0;
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];
480                 }
481         }else{
482                 packet_buf[0] = 0;
483                 packet_buf[1] = 14; /* EXP_PDU_TAG_DISSECTOR_TABLE_NAME */
484                 packet_buf[2] = 0;
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];
488                 }
489                 packet_buf[i] = 0;
490                 i++;
491                 packet_buf[i] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
492                 i++;
493                 packet_buf[i] = 0;
494                 i++;
495                 packet_buf[i] = 4; /* tag length */;
496                 i++;
497                 packet_buf[i] = 0;
498                 i++;
499                 packet_buf[i] = 0;
500                 i++;
501                 packet_buf[i] = 0;
502                 i++;
503                 packet_buf[i] = dissector_table_val;
504                 i++;
505         }
506
507         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_COL_PROT_BIT) == EXP_PDU_TAG_COL_PROT_BIT) {
508                 packet_buf[i] = 0;
509                 i++;
510                 packet_buf[i] = EXP_PDU_TAG_COL_PROT_TEXT;
511                 i++;
512                 packet_buf[i] = 0;
513                 i++;
514                 packet_buf[i] = (guint8)strlen(exported_pdu_info->proto_col_str);
515                 i++;
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];
518                 }
519                 g_free(exported_pdu_info->proto_col_str);
520         }
521
522
523         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_SRC_BIT) == EXP_PDU_TAG_IP_SRC_BIT) {
524                 packet_buf[i] = 0;
525                 i++;
526                 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC;
527                 i++;
528                 packet_buf[i] = 0;
529                 i++;
530                 packet_buf[i] = EXP_PDU_TAG_IPV4_SRC_LEN; /* tag length */;
531                 i++;
532                 packet_buf[i] = exported_pdu_info->src_ipv4_d1;
533                 i++;
534                 packet_buf[i] = exported_pdu_info->src_ipv4_d2;
535                 i++;
536                 packet_buf[i] = exported_pdu_info->src_ipv4_d3;
537                 i++;
538                 packet_buf[i] = exported_pdu_info->src_ipv4_d4;
539                 i++;
540         }
541
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;
545                         packet_buf[i] = 0;
546                         i++;
547                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
548                         i++;
549                         packet_buf[i] = 0;
550                         i++;
551                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
552                         i++;
553                         packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
554                         i++;
555                         packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
556                         i++;
557                         packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
558                         i++;
559                         packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
560                         i++;
561                 }
562                 packet_buf[i] = 0;
563                 i++;
564                 packet_buf[i] = EXP_PDU_TAG_SRC_PORT;
565                 i++;
566                 packet_buf[i] = 0;
567                 i++;
568                 packet_buf[i] = EXP_PDU_TAG_SRC_PORT_LEN; /* tag length */;
569                 i++;
570                 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
571                 i++;
572                 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
573                 i++;
574                 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
575                 i++;
576                 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
577                 i++;
578         }
579
580         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_IP_DST_BIT) == EXP_PDU_TAG_IP_DST_BIT) {
581                 packet_buf[i] = 0;
582                 i++;
583                 packet_buf[i] = EXP_PDU_TAG_IPV4_DST;
584                 i++;
585                 packet_buf[i] = 0;
586                 i++;
587                 packet_buf[i] = EXP_PDU_TAG_IPV4_DST_LEN; /* tag length */;
588                 i++;
589                 packet_buf[i] = exported_pdu_info->dst_ipv4_d1;
590                 i++;
591                 packet_buf[i] = exported_pdu_info->dst_ipv4_d2;
592                 i++;
593                 packet_buf[i] = exported_pdu_info->dst_ipv4_d3;
594                 i++;
595                 packet_buf[i] = exported_pdu_info->dst_ipv4_d4;
596                 i++;
597         }
598
599         if ((exported_pdu_info->precense_flags & EXP_PDU_TAG_DST_PORT_BIT) == EXP_PDU_TAG_DST_PORT_BIT) {
600                 if (!port_type_defined) {
601                         packet_buf[i] = 0;
602                         i++;
603                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE;
604                         i++;
605                         packet_buf[i] = 0;
606                         i++;
607                         packet_buf[i] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */;
608                         i++;
609                         packet_buf[i] = (exported_pdu_info->ptype & 0xff000000) >> 24;
610                         i++;
611                         packet_buf[i] = (exported_pdu_info->ptype & 0x00ff0000) >> 16;
612                         i++;
613                         packet_buf[i] = (exported_pdu_info->ptype & 0x0000ff00) >> 8;
614                         i++;
615                         packet_buf[i] = (exported_pdu_info->ptype & 0x000000ff);
616                         i++;
617                 }
618                 packet_buf[i] = 0;
619                 i++;
620                 packet_buf[i] = EXP_PDU_TAG_DST_PORT;
621                 i++;
622                 packet_buf[i] = 0;
623                 i++;
624                 packet_buf[i] = EXP_PDU_TAG_DST_PORT_LEN; /* tag length */;
625                 i++;
626                 packet_buf[i] = (exported_pdu_info->src_port & 0xff000000) >> 24;
627                 i++;
628                 packet_buf[i] = (exported_pdu_info->src_port & 0x00ff0000) >> 16;
629                 i++;
630                 packet_buf[i] = (exported_pdu_info->src_port & 0x0000ff00) >> 8;
631                 i++;
632                 packet_buf[i] = (exported_pdu_info->src_port & 0x000000ff);
633                 i++;
634         }
635
636         /* Add end of options */
637         packet_buf[i] = 0;
638         i++;
639         packet_buf[i] = 0;
640         i++;
641         packet_buf[i] = 0;
642         i++;
643         packet_buf[i] = 0;
644         i++;
645         exp_pdu_tags_len = exp_pdu_tags_len + 4;
646
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++){
649                 chr = *curr_pos;
650                 val1 = g_ascii_xdigit_value(chr);
651                 curr_pos++;
652                 chr = *curr_pos;
653                 val2 = g_ascii_xdigit_value(chr);
654                 if ((val1 != -1) && (val2 != -1)){
655                         packet_buf[i] = ((guint8)val1 * 16) + val2;
656                 }
657                 else{
658                         /* Something wrong, bail out */
659                         g_free(packet_buf);
660                         return WTAP_OPEN_ERROR;
661                 }
662                 curr_pos++;
663         }
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 */
669                 phdr->ts.secs = 0;
670                 phdr->ts.nsecs = 0;
671         } else {
672                 phdr->presence_flags = WTAP_HAS_TS;
673                 phdr->ts.secs = start_time;
674                 phdr->ts.nsecs = ms * 1000000;
675         }
676
677         phdr->caplen = pkt_data_len + exp_pdu_tags_len;
678         phdr->len = pkt_data_len + exp_pdu_tags_len;
679
680         if (!wtap_dump(wdh, phdr, packet_buf, err, err_info)) {
681                 switch (*err) {
682
683                 case WTAP_ERR_UNWRITABLE_REC_DATA:
684                         g_free(err_info);
685                         break;
686
687                 default:
688                         break;
689                 }
690                 g_free(packet_buf);
691                 return WTAP_OPEN_ERROR;
692         }
693
694         g_free(packet_buf);
695         return WTAP_OPEN_MINE;
696 }
697
698 /*
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.
702  */
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)
705 {
706         int import_file_fd;
707         wtap_dumper* wdh_exp_pdu;
708         int   exp_pdu_file_err;
709         wtap_open_return_val result = WTAP_OPEN_MINE;
710
711         /* pcapng defs */
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;
718         gint64 file_size;
719         int packet_size;
720         guint8 *packet_buf = NULL;
721         int wrt_err;
722         gchar *wrt_err_info = NULL;
723         struct wtap_pkthdr phdr;
724         time_t start_time;
725         int scan_found;
726         unsigned second, ms;
727         gboolean do_random = FALSE;
728         char *curr_pos, *next_msg_pos, *next_pos, *prev_pos;
729         int name_str_len;
730         char name_str[64];
731         gsize opt_len;
732         /* Info to build exported_pdu tags*/
733         exported_pdu_info_t  exported_pdu_info;
734
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;
748
749         import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_", NULL);
750
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);
755
756         shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
757         /* options */
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"));
760         /*
761         * UTF-8 string containing the name of the operating system used to create
762         * this section.
763         */
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);
766
767         /*
768         * UTF-8 string containing the name of the application used to create
769         * this section.
770         */
771         wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
772
773         /* Add header to the array */
774         g_array_append_val(shb_hdrs, shb_hdr);
775
776
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));
780
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;
791
792         g_array_append_val(idb_inf->interface_data, int_data);
793
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;
798                 goto end;
799         }
800
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 */
802
803         if ((file_size = wtap_file_size(wth, err)) == -1) {
804                 result = WTAP_OPEN_ERROR;
805                 goto end;
806         }
807
808         if (file_size > MAX_FILE_SIZE) {
809                 /*
810                 * Don't blow up trying to allocate space for an
811                 * immensely-large file.
812                 */
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;
817                 goto end;
818         }
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
824         */
825         /* XXX add the length of exported bdu tag(s) here */
826         packet_buf = (guint8 *)g_malloc(packet_size + 12 + 1);
827
828         packet_buf[0] = 0;
829         packet_buf[1] = EXP_PDU_TAG_PROTO_NAME;
830         packet_buf[2] = 0;
831         packet_buf[3] = 4;
832         packet_buf[4] = 'x';
833         packet_buf[5] = 'm';
834         packet_buf[6] = 'l';
835         packet_buf[7] = 0;
836         /* End of options */
837         packet_buf[8] = 0;
838         packet_buf[9] = 0;
839         packet_buf[10] = 0;
840         packet_buf[11] = 0;
841
842         if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
843                 result = WTAP_OPEN_ERROR;
844                 goto end;
845         }
846
847         /* Null-terminate buffer; we'll be processing it as a string. */
848         packet_buf[packet_size + 12] = '\0';
849
850         /* Create the packet header */
851         memset(&phdr, 0, sizeof(struct wtap_pkthdr));
852
853         /* Read the file header of the input file, currently we only need the beginTime*/
854
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;
860
861         /* Find start time */
862         curr_pos = strstr(curr_pos, "<traceCollec beginTime=\"");
863         curr_pos = curr_pos + 24;
864
865         curr_pos = nettrace_parse_begin_time(curr_pos, &phdr);
866
867         start_time = phdr.ts.secs;
868
869         /* set rest of the pkt hdr data */
870         phdr.rec_type = REC_TYPE_PACKET;
871
872         phdr.caplen = packet_size + 12;
873         phdr.len = packet_size + 12;
874
875         /* XXX: report errors! */
876         if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
877                 switch (wrt_err) {
878
879                 case WTAP_ERR_UNWRITABLE_REC_DATA:
880                         g_free(wrt_err_info);
881                         wrt_err_info = NULL;
882                         break;
883
884                 default:
885                         break;
886                 }
887                 result = WTAP_OPEN_ERROR;
888                 goto end;
889         }
890
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;
897
898                 curr_pos = curr_pos + 4;
899                 next_msg_pos = strstr(curr_pos, "</msg>");
900                 if (!next_msg_pos){
901                         /* Somethings wrong, bail out */
902                         break;
903                 }
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).
907                  */
908                 prev_pos = curr_pos;
909                 ms = 0;
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;
919                         }
920
921                         g_strlcpy(name_str, curr_pos, name_str_len + 1);
922                         ascii_strdown_inplace(name_str);
923
924                 }
925                 else {
926                         curr_pos = prev_pos;
927                 }
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);
933
934                         if ((scan_found == 2) && (start_time != 0)) {
935                                 start_time = start_time + second;
936                         }
937                 } else {
938                         curr_pos = prev_pos;
939                 }
940                 /* Check if we have "<initiator>"
941                 *  It might contain an address
942                 */
943                 prev_pos = curr_pos;
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>");
949                         /* Find address*/
950                         curr_pos = strstr(curr_pos, "address");
951                         if ((curr_pos) && (curr_pos < next_pos)) {
952                                 guint d1, d2, d3, d4, port;
953                                 char transp_str[5];
954
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}
958                                  */
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;
967
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;
973                                         }
974                                         exported_pdu_info.src_port = port;
975                                 } else {
976                                         g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
977                                 }
978                         } else {
979                                 /* address not found*/
980                                 curr_pos = next_pos;
981                         }
982                 } else {
983                         /*"<initiator>" not found */
984                         curr_pos = prev_pos;
985                 }
986
987                 /* Check if we have "<target>"
988                 *  It might contain an address
989                 */
990                 prev_pos = curr_pos;
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>");
996                         /* Find address*/
997                         curr_pos = strstr(curr_pos, "address");
998                         if ((curr_pos) && (curr_pos < next_pos)) {
999                                 guint d1, d2, d3, d4, port;
1000                                 char transp_str[5];
1001
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}
1005                                 */
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;
1019                                         }
1020                                         exported_pdu_info.dst_port = port;
1021                                 } else {
1022                                         g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str);
1023                                 }
1024                         }
1025                         else {
1026                                 /* address not found */
1027                                 curr_pos = next_pos;
1028                         }
1029                 } else {
1030                         /* "<target>" not found */
1031                         curr_pos = prev_pos;
1032                 }
1033
1034                 /* Do we have a raw msg?) */
1035                 curr_pos = strstr(curr_pos, "<rawMsg");
1036                 if (!curr_pos){
1037                         /* No rawMsg, continue */
1038                         curr_pos = next_msg_pos;
1039                         continue;
1040                 }
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){
1045                         result = temp_val;
1046                         goto end;
1047                 }
1048                 curr_pos = next_msg_pos;
1049         }
1050
1051         /* Close the written file*/
1052         if (!wtap_dump_close(wdh_exp_pdu, err)){
1053                 result = WTAP_OPEN_ERROR;
1054                 goto end;
1055         }
1056
1057         /* Now open the file for reading */
1058
1059         /* Find out if random read was requested */
1060         if (wth->random_fh){
1061                 do_random = TRUE;
1062         }
1063         file_info->wth_tmp_file =
1064                 wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);
1065
1066         if (!file_info->wth_tmp_file){
1067                 result = WTAP_OPEN_ERROR;
1068                 goto end;
1069         }
1070
1071 end:
1072         g_free(wrt_err_info);
1073         g_free(packet_buf);
1074         wtap_block_array_free(shb_hdrs);
1075         wtap_free_idb_info(idb_inf);
1076
1077         return result;
1078 }
1079
1080 wtap_open_return_val
1081 nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
1082 {
1083         char magic_buf[512+1]; /* increase buffer size when needed */
1084         int bytes_read;
1085         char *curr_pos;
1086         nettrace_3gpp_32_423_file_info_t *file_info;
1087         wtap_open_return_val temp_val;
1088
1089
1090         bytes_read = file_read(magic_buf, 512, wth->fh);
1091
1092         if (bytes_read < 0) {
1093                 *err = file_error(wth->fh, err_info);
1094                 return WTAP_OPEN_ERROR;
1095         }
1096         if (bytes_read == 0){
1097                 return WTAP_OPEN_NOT_MINE;
1098         }
1099
1100         if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
1101                 return WTAP_OPEN_NOT_MINE;
1102         }
1103
1104         /* Null-terminate buffer; we'll be processing it as a string. */
1105         magic_buf[512] = '\0';
1106
1107         /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
1108         curr_pos = strstr(magic_buf, "fileFormatVersion");
1109
1110         if (!curr_pos){
1111                 return WTAP_OPEN_NOT_MINE;
1112         }
1113         curr_pos += 19;
1114         if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
1115                 return WTAP_OPEN_NOT_MINE;
1116         }
1117
1118         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1119                 return WTAP_OPEN_ERROR;
1120
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);
1124
1125         if (temp_val != WTAP_OPEN_MINE){
1126                 return temp_val;
1127         }
1128
1129         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1130                 return WTAP_OPEN_ERROR;
1131
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));
1134
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;
1142
1143         wth->priv = (void*)file_info;
1144
1145         return WTAP_OPEN_MINE;
1146
1147 }
1148
1149 /*
1150  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1151  *
1152  * Local variables:
1153  * c-basic-offset: 8
1154  * tab-width: 8
1155  * indent-tabs-mode: t
1156  * End:
1157  *
1158  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1159  * :indentSize=8:tabSize=8:noTabs=false:
1160  */