Rename "ws_version_info.h", also .c
[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 "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         gchar *opt_str;
733         /* Info to build exported_pdu tags*/
734         exported_pdu_info_t  exported_pdu_info;
735
736         exported_pdu_info.precense_flags = 0;
737         exported_pdu_info.src_ipv4_d1 = 0;
738         exported_pdu_info.src_ipv4_d2 = 0;
739         exported_pdu_info.src_ipv4_d3 = 0;
740         exported_pdu_info.src_ipv4_d4 = 0;
741         exported_pdu_info.ptype = PT_NONE;
742         exported_pdu_info.src_port = 0;
743         exported_pdu_info.dst_ipv4_d1 = 0;
744         exported_pdu_info.dst_ipv4_d2 = 0;
745         exported_pdu_info.dst_ipv4_d3 = 0;
746         exported_pdu_info.dst_ipv4_d4 = 0;
747         exported_pdu_info.dst_port = 0;
748         exported_pdu_info.proto_col_str = NULL;
749
750         import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_", NULL);
751
752         /* Now open a file and dump to it */
753         /* Create data for SHB  */
754         os_info_str = g_string_new("");
755         get_os_version_info(os_info_str);
756
757         shb_hdr = wtap_block_create(WTAP_BLOCK_NG_SECTION);
758         /* options */
759         wtap_block_add_string_option(shb_hdr, OPT_COMMENT, "File converted to Exported PDU format during opening",
760                                                                                                                         strlen("File converted to Exported PDU format during opening"));
761         /*
762         * UTF-8 string containing the name of the operating system used to create
763         * this section.
764         */
765         opt_len = os_info_str->len;
766         opt_str = g_string_free(os_info_str, FALSE);
767         if (opt_str) {
768                 wtap_block_add_string_option(shb_hdr, OPT_SHB_OS, opt_str, opt_len);
769                 g_free(opt_str);
770         }
771
772         /*
773         * UTF-8 string containing the name of the application used to create
774         * this section.
775         */
776         wtap_block_add_string_option_format(shb_hdr, OPT_SHB_USERAPPL, "Wireshark %s", get_ws_vcs_version_info());
777
778         /* Add header to the array */
779         g_array_append_val(shb_hdrs, shb_hdr);
780
781
782         /* Create fake IDB info */
783         idb_inf = g_new(wtapng_iface_descriptions_t, 1);
784         idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtap_block_t));
785
786         /* create the fake interface data */
787         int_data = wtap_block_create(WTAP_BLOCK_IF_DESCR);
788         int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(int_data);
789         int_data_mand->wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
790         int_data_mand->time_units_per_second = 1000000; /* default microsecond resolution */
791         int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD;
792         wtap_block_add_string_option(int_data, OPT_IDB_NAME, "Fake IF", strlen("Fake IF"));
793         int_data_mand->num_stat_entries = 0;          /* Number of ISB:s */
794         int_data_mand->interface_statistics = NULL;
795
796         g_array_append_val(idb_inf->interface_data, int_data);
797
798         wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU,
799                                           WTAP_MAX_PACKET_SIZE_STANDARD, FALSE, shb_hdrs, idb_inf, NULL, &exp_pdu_file_err);
800         if (wdh_exp_pdu == NULL) {
801                 result = WTAP_OPEN_ERROR;
802                 goto end;
803         }
804
805         /* OK we've opend a new pcap-ng file and written the headers, time to do the packets, strt by finding the file size */
806
807         if ((file_size = wtap_file_size(wth, err)) == -1) {
808                 result = WTAP_OPEN_ERROR;
809                 goto end;
810         }
811
812         if (file_size > MAX_FILE_SIZE) {
813                 /*
814                 * Don't blow up trying to allocate space for an
815                 * immensely-large file.
816                 */
817                 *err = WTAP_ERR_BAD_FILE;
818                 *err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
819                         file_size, MAX_FILE_SIZE);
820                 result = WTAP_OPEN_ERROR;
821                 goto end;
822         }
823         packet_size = (int)file_size;
824         /* Allocate the packet buffer
825         * (the whole file + Exported PDU tag "protocol" and
826         * the string "xml" + 1 filler to end on 4 byte boundary for the tag
827         * + End of options 4 bytes
828         */
829         /* XXX add the length of exported bdu tag(s) here */
830         packet_buf = (guint8 *)g_malloc(packet_size + 12 + 1);
831
832         packet_buf[0] = 0;
833         packet_buf[1] = EXP_PDU_TAG_PROTO_NAME;
834         packet_buf[2] = 0;
835         packet_buf[3] = 4;
836         packet_buf[4] = 'x';
837         packet_buf[5] = 'm';
838         packet_buf[6] = 'l';
839         packet_buf[7] = 0;
840         /* End of options */
841         packet_buf[8] = 0;
842         packet_buf[9] = 0;
843         packet_buf[10] = 0;
844         packet_buf[11] = 0;
845
846         if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
847                 result = WTAP_OPEN_ERROR;
848                 goto end;
849         }
850
851         /* Null-terminate buffer; we'll be processing it as a string. */
852         packet_buf[packet_size + 12] = '\0';
853
854         /* Create the packet header */
855         memset(&phdr, 0, sizeof(struct wtap_pkthdr));
856
857         /* Read the file header of the input file, currently we only need the beginTime*/
858
859         /* Advance *packet_buf to point at the raw file data */
860         curr_pos = packet_buf + 12;
861         /* Find the file header */
862         curr_pos = strstr(curr_pos, "<fileHeader");
863         curr_pos = curr_pos + 11;
864
865         /* Find start time */
866         curr_pos = strstr(curr_pos, "<traceCollec beginTime=\"");
867         curr_pos = curr_pos + 24;
868
869         curr_pos = nettrace_parse_begin_time(curr_pos, &phdr);
870
871         start_time = phdr.ts.secs;
872
873         /* set rest of the pkt hdr data */
874         phdr.rec_type = REC_TYPE_PACKET;
875
876         phdr.caplen = packet_size + 12;
877         phdr.len = packet_size + 12;
878
879         /* XXX: report errors! */
880         if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
881                 switch (wrt_err) {
882
883                 case WTAP_ERR_UNWRITABLE_REC_DATA:
884                         g_free(wrt_err_info);
885                         wrt_err_info = NULL;
886                         break;
887
888                 default:
889                         break;
890                 }
891                 result = WTAP_OPEN_ERROR;
892                 goto end;
893         }
894
895         /* Lets add the raw messages as packets after the main "packet" with the whole file */
896         while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
897                 wtap_open_return_val temp_val;
898                 /* Clear for each itteration */
899                 exported_pdu_info.precense_flags = 0;
900                 exported_pdu_info.ptype = PT_NONE;
901
902                 curr_pos = curr_pos + 4;
903                 next_msg_pos = strstr(curr_pos, "</msg>");
904                 if (!next_msg_pos){
905                         /* Somethings wrong, bail out */
906                         break;
907                 }
908                 next_msg_pos = next_msg_pos + 6;
909                 /* Check if we have a time stamp "changeTime"
910                  * expressed in number of seconds and milliseconds (nbsec.ms).
911                  */
912                 prev_pos = curr_pos;
913                 ms = 0;
914                 /* See if we have a "name" */
915                 curr_pos = strstr(curr_pos, "name=");
916                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
917                         /* extract the name */
918                         curr_pos = curr_pos + 6;
919                         next_pos = strstr(curr_pos, "\"");
920                         name_str_len = (int)(next_pos - curr_pos);
921                         if (name_str_len > 63) {
922                                 return WTAP_OPEN_ERROR;
923                         }
924
925                         g_strlcpy(name_str, curr_pos, name_str_len + 1);
926                         ascii_strdown_inplace(name_str);
927
928                 }
929                 else {
930                         curr_pos = prev_pos;
931                 }
932                 curr_pos = strstr(curr_pos, "changeTime");
933                 /* Check if we have the tag or if we pased the end of the current message */
934                 if ((curr_pos)&&(curr_pos < next_msg_pos)){
935                         curr_pos = curr_pos + 12;
936                         scan_found = sscanf(curr_pos, "%u.%u",&second, &ms);
937
938                         if ((scan_found == 2) && (start_time != 0)) {
939                                 start_time = start_time + second;
940                         }
941                 } else {
942                         curr_pos = prev_pos;
943                 }
944                 /* Check if we have "<initiator>"
945                 *  It might contain an address
946                 */
947                 prev_pos = curr_pos;
948                 curr_pos = strstr(curr_pos, "<initiator>");
949                 /* Check if we have the tag or if we pased the end of the current message */
950                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
951                         curr_pos = curr_pos + 11;
952                         next_pos = strstr(curr_pos, "</initiator>");
953                         /* Find address*/
954                         curr_pos = strstr(curr_pos, "address");
955                         if ((curr_pos) && (curr_pos < next_pos)) {
956                                 guint d1, d2, d3, d4, port;
957                                 char transp_str[5];
958
959                                 curr_pos = curr_pos + 7;
960                                 /* Excample from one trace, unsure if it's generic...
961                                  * {address == 192.168.73.1, port == 5062, transport == Udp}
962                                  */
963                                 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
964                                         &d1, &d2, &d3, &d4, &port, transp_str);
965                                 if (scan_found == 6) {
966                                         exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_SRC_BIT + EXP_PDU_TAG_SRC_PORT_BIT;
967                                         exported_pdu_info.src_ipv4_d1 = d1;
968                                         exported_pdu_info.src_ipv4_d2 = d2;
969                                         exported_pdu_info.src_ipv4_d3 = d3;
970                                         exported_pdu_info.src_ipv4_d4 = d4;
971
972                                         /* Only add port_type once */
973                                         if(exported_pdu_info.ptype == PT_NONE){
974                                                 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0)  exported_pdu_info.ptype = PT_UDP;
975                                                 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0)  exported_pdu_info.ptype = PT_TCP;
976                                                 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0)  exported_pdu_info.ptype = PT_SCTP;
977                                         }
978                                         exported_pdu_info.src_port = port;
979                                 } else {
980                                         /* g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str); */
981                                 }
982                         } else {
983                                 /* address not found*/
984                                 curr_pos = next_pos;
985                         }
986                 } else {
987                         /*"<initiator>" not found */
988                         curr_pos = prev_pos;
989                 }
990
991                 /* Check if we have "<target>"
992                 *  It might contain an address
993                 */
994                 prev_pos = curr_pos;
995                 curr_pos = strstr(curr_pos, "<target>");
996                 /* Check if we have the tag or if we pased the end of the current message */
997                 if ((curr_pos) && (curr_pos < next_msg_pos)) {
998                         curr_pos = curr_pos + 8;
999                         next_pos = strstr(curr_pos, "</target>");
1000                         /* Find address*/
1001                         curr_pos = strstr(curr_pos, "address");
1002                         if ((curr_pos) && (curr_pos < next_pos)) {
1003                                 guint d1, d2, d3, d4, port;
1004                                 char transp_str[5];
1005
1006                                 curr_pos = curr_pos + 7;
1007                                 /* Excample from one trace, unsure if it's generic...
1008                                 * {address == 192.168.73.1, port == 5062, transport == Udp}
1009                                 */
1010                                 scan_found = sscanf(curr_pos, "%*s %3u.%3u.%3u.%3u, %*s %*s %5u, %*s %*s %4s",
1011                                         &d1, &d2, &d3, &d4, &port, transp_str);
1012                                 if (scan_found == 6) {
1013                                         exported_pdu_info.precense_flags = exported_pdu_info.precense_flags + EXP_PDU_TAG_IP_DST_BIT + EXP_PDU_TAG_DST_PORT_BIT;
1014                                         exported_pdu_info.dst_ipv4_d1 = d1;
1015                                         exported_pdu_info.dst_ipv4_d2 = d2;
1016                                         exported_pdu_info.dst_ipv4_d3 = d3;
1017                                         exported_pdu_info.dst_ipv4_d4 = d4;
1018                                         /* Only add port_type once */
1019                                         if (exported_pdu_info.ptype == PT_NONE) {
1020                                                 if (g_ascii_strncasecmp(transp_str, "udp", 3) == 0)  exported_pdu_info.ptype = PT_UDP;
1021                                                 else if (g_ascii_strncasecmp(transp_str, "tcp", 3) == 0)  exported_pdu_info.ptype = PT_TCP;
1022                                                 else if (g_ascii_strncasecmp(transp_str, "sctp", 4) == 0)  exported_pdu_info.ptype = PT_SCTP;
1023                                         }
1024                                         exported_pdu_info.dst_port = port;
1025                                 } else {
1026                                         /* g_warning("scan_found:%u, %u.%u.%u.%u Port %u transport %s", scan_found, d1, d2, d3, d4, port, transp_str); */
1027                                 }
1028                         }
1029                         else {
1030                                 /* address not found */
1031                                 curr_pos = next_pos;
1032                         }
1033                 } else {
1034                         /* "<target>" not found */
1035                         curr_pos = prev_pos;
1036                 }
1037
1038                 /* Do we have a raw msg?) */
1039                 curr_pos = strstr(curr_pos, "<rawMsg");
1040                 if (!curr_pos){
1041                         /* No rawMsg, continue */
1042                         curr_pos = next_msg_pos;
1043                         continue;
1044                 }
1045                 curr_pos = curr_pos + 7;
1046                 /* Add the raw msg*/
1047                 temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos, start_time, ms, &exported_pdu_info, name_str);
1048                 if (temp_val != WTAP_OPEN_MINE){
1049                         result = temp_val;
1050                         goto end;
1051                 }
1052                 curr_pos = next_msg_pos;
1053         }
1054
1055         /* Close the written file*/
1056         if (!wtap_dump_close(wdh_exp_pdu, err)){
1057                 result = WTAP_OPEN_ERROR;
1058                 goto end;
1059         }
1060
1061         /* Now open the file for reading */
1062
1063         /* Find out if random read was requested */
1064         if (wth->random_fh){
1065                 do_random = TRUE;
1066         }
1067         file_info->wth_tmp_file =
1068                 wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);
1069
1070         if (!file_info->wth_tmp_file){
1071                 result = WTAP_OPEN_ERROR;
1072                 goto end;
1073         }
1074
1075 end:
1076         g_free(wrt_err_info);
1077         g_free(packet_buf);
1078         wtap_block_array_free(shb_hdrs);
1079         wtap_free_idb_info(idb_inf);
1080
1081         return result;
1082 }
1083
1084 wtap_open_return_val
1085 nettrace_3gpp_32_423_file_open(wtap *wth, int *err, gchar **err_info)
1086 {
1087         char magic_buf[512+1]; /* increase buffer size when needed */
1088         int bytes_read;
1089         char *curr_pos;
1090         nettrace_3gpp_32_423_file_info_t *file_info;
1091         wtap_open_return_val temp_val;
1092
1093
1094         bytes_read = file_read(magic_buf, 512, wth->fh);
1095
1096         if (bytes_read < 0) {
1097                 *err = file_error(wth->fh, err_info);
1098                 return WTAP_OPEN_ERROR;
1099         }
1100         if (bytes_read == 0){
1101                 return WTAP_OPEN_NOT_MINE;
1102         }
1103
1104         if (memcmp(magic_buf, xml_magic, sizeof(xml_magic)) != 0){
1105                 return WTAP_OPEN_NOT_MINE;
1106         }
1107
1108         /* Null-terminate buffer; we'll be processing it as a string. */
1109         magic_buf[512] = '\0';
1110
1111         /* File header should contain something like fileFormatVersion="32.423 V8.1.0" */
1112         curr_pos = strstr(magic_buf, "fileFormatVersion");
1113
1114         if (!curr_pos){
1115                 return WTAP_OPEN_NOT_MINE;
1116         }
1117         curr_pos += 19;
1118         if (memcmp(curr_pos, Threegpp_doc_no, sizeof(Threegpp_doc_no)) != 0){
1119                 return WTAP_OPEN_NOT_MINE;
1120         }
1121
1122         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1123                 return WTAP_OPEN_ERROR;
1124
1125         /* Ok it's our file, open a temp file and do the conversion */
1126         file_info = g_new0(nettrace_3gpp_32_423_file_info_t, 1);
1127         temp_val = create_temp_pcapng_file(wth, err, err_info, file_info);
1128
1129         if (temp_val != WTAP_OPEN_MINE){
1130                 return temp_val;
1131         }
1132
1133         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
1134                 return WTAP_OPEN_ERROR;
1135
1136         /* Copy data from the temp file wth */
1137         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));
1138
1139         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETTRACE_3GPP_32_423;
1140         wth->file_encap = file_info->wth_tmp_file->file_encap;
1141         wth->file_tsprec = file_info->wth_tmp_file->file_tsprec;
1142         wth->subtype_read = nettrace_read;
1143         wth->subtype_seek_read = nettrace_seek_read;
1144         wth->subtype_close = nettrace_close;
1145         wth->snapshot_length = 0;
1146
1147         wth->priv = (void*)file_info;
1148
1149         return WTAP_OPEN_MINE;
1150
1151 }
1152
1153 /*
1154  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1155  *
1156  * Local variables:
1157  * c-basic-offset: 8
1158  * tab-width: 8
1159  * indent-tabs-mode: t
1160  * End:
1161  *
1162  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1163  * :indentSize=8:tabSize=8:noTabs=false:
1164  */