2 * Routines for opening CommView file format packet captures
3 * Copyright 2007, Stephen Fisher (see AUTHORS file)
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Based on csids.c and nettl.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
29 /* A brief description of this file format is available at:
30 * http://www.tamos.com/htmlhelp/commview/logformat.htm
44 #include "file_wrappers.h"
47 typedef struct commview_header
{
49 guint16 source_data_len
;
58 guint8 flags
; /* Bit-field positions defined below */
59 guint8 signal_level_percent
;
63 guint8 direction
; /* Or for WiFi, high order byte of
65 guint8 signal_level_dbm
;
66 guint8 noise_level
; /* In dBm (WiFi only) */
69 #define COMMVIEW_HEADER_SIZE 24
71 /* Bit-field positions for various fields in the flags variable of the header */
72 #define FLAGS_MEDIUM 0x0F
73 #define FLAGS_DECRYPTED 0x10
74 #define FLAGS_BROKEN 0x20
75 #define FLAGS_COMPRESSED 0x40
76 #define FLAGS_RESERVED 0x80
78 /* Capture mediums as defined by the commview file format */
79 #define MEDIUM_ETHERNET 0
81 #define MEDIUM_TOKEN_RING 2
83 static gboolean
commview_read(wtap
*wth
, int *err
, gchar
**err_info
,
85 static gboolean
commview_seek_read(wtap
*wth
, gint64 seek_off
,
86 struct wtap_pkthdr
*phdr
,
87 Buffer
*buf
, int length
, int *err
,
89 static gboolean
commview_read_header(commview_header_t
*cv_hdr
, FILE_T fh
,
90 int *err
, gchar
**err_info
);
91 static gboolean
commview_dump(wtap_dumper
*wdh
, const struct wtap_pkthdr
*phdr
,
92 const guint8
*pd
, int *err
);
94 int commview_open(wtap
*wth
, int *err
, gchar
**err_info
)
96 commview_header_t cv_hdr
;
98 if(!commview_read_header(&cv_hdr
, wth
->fh
, err
, err_info
)) {
99 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
104 /* If any of these fields do not match what we expect, bail out. */
105 if(cv_hdr
.version
!= 0 ||
106 cv_hdr
.year
< 1970 || cv_hdr
.year
>= 2038 ||
107 cv_hdr
.month
< 1 || cv_hdr
.month
> 12 ||
108 cv_hdr
.day
< 1 || cv_hdr
.day
> 31 ||
110 cv_hdr
.minutes
> 59 ||
111 cv_hdr
.seconds
> 60 ||
112 cv_hdr
.signal_level_percent
> 100 ||
113 (cv_hdr
.flags
& FLAGS_RESERVED
) != 0 ||
114 ((cv_hdr
.flags
& FLAGS_MEDIUM
) != MEDIUM_ETHERNET
&&
115 (cv_hdr
.flags
& FLAGS_MEDIUM
) != MEDIUM_WIFI
&&
116 (cv_hdr
.flags
& FLAGS_MEDIUM
) != MEDIUM_TOKEN_RING
))
117 return 0; /* Not our kind of file */
119 /* No file header. Reset the fh to 0 so we can read the first packet */
120 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1)
123 /* Set up the pointers to the handlers for this file type */
124 wth
->subtype_read
= commview_read
;
125 wth
->subtype_seek_read
= commview_seek_read
;
127 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_COMMVIEW
;
128 wth
->file_encap
= WTAP_ENCAP_PER_PACKET
;
129 wth
->tsprecision
= WTAP_FILE_TSPREC_USEC
;
131 return 1; /* Our kind of file */
135 commview_read_packet(FILE_T fh
, struct wtap_pkthdr
*phdr
, Buffer
*buf
,
136 int *err
, gchar
**err_info
)
138 commview_header_t cv_hdr
;
141 if(!commview_read_header(&cv_hdr
, fh
, err
, err_info
))
144 switch(cv_hdr
.flags
& FLAGS_MEDIUM
) {
146 case MEDIUM_ETHERNET
:
147 phdr
->pkt_encap
= WTAP_ENCAP_ETHERNET
;
148 phdr
->pseudo_header
.eth
.fcs_len
= -1; /* Unknown */
152 phdr
->pkt_encap
= WTAP_ENCAP_IEEE_802_11_WITH_RADIO
;
153 phdr
->pseudo_header
.ieee_802_11
.fcs_len
= -1; /* Unknown */
154 phdr
->pseudo_header
.ieee_802_11
.channel
= cv_hdr
.channel
;
155 phdr
->pseudo_header
.ieee_802_11
.data_rate
=
156 cv_hdr
.rate
| (cv_hdr
.direction
<< 8);
157 phdr
->pseudo_header
.ieee_802_11
.signal_level
= cv_hdr
.signal_level_percent
;
160 case MEDIUM_TOKEN_RING
:
161 phdr
->pkt_encap
= WTAP_ENCAP_TOKEN_RING
;
165 *err
= WTAP_ERR_BAD_FILE
;
166 *err_info
= g_strdup_printf("commview: unsupported encap: %u",
167 cv_hdr
.flags
& FLAGS_MEDIUM
);
171 tm
.tm_year
= cv_hdr
.year
- 1900;
172 tm
.tm_mon
= cv_hdr
.month
- 1;
173 tm
.tm_mday
= cv_hdr
.day
;
174 tm
.tm_hour
= cv_hdr
.hours
;
175 tm
.tm_min
= cv_hdr
.minutes
;
176 tm
.tm_sec
= cv_hdr
.seconds
;
179 phdr
->presence_flags
= WTAP_HAS_TS
;
181 phdr
->len
= cv_hdr
.data_len
;
182 phdr
->caplen
= cv_hdr
.data_len
;
184 phdr
->ts
.secs
= mktime(&tm
);
185 phdr
->ts
.nsecs
= cv_hdr
.usecs
* 1000;
187 return wtap_read_packet_bytes(fh
, buf
, phdr
->caplen
, err
, err_info
);
191 commview_read(wtap
*wth
, int *err
, gchar
**err_info
, gint64
*data_offset
)
193 *data_offset
= file_tell(wth
->fh
);
195 return commview_read_packet(wth
->fh
, &wth
->phdr
, wth
->frame_buffer
, err
,
200 commview_seek_read(wtap
*wth
, gint64 seek_off
, struct wtap_pkthdr
*phdr
,
201 Buffer
*buf
, int length _U_
, int *err
, gchar
**err_info
)
203 if(file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
206 return commview_read_packet(wth
->random_fh
, phdr
, buf
, err
, err_info
);
210 commview_read_header(commview_header_t
*cv_hdr
, FILE_T fh
, int *err
,
213 wtap_file_read_expected_bytes(&cv_hdr
->data_len
, 2, fh
, err
, err_info
);
214 wtap_file_read_expected_bytes(&cv_hdr
->source_data_len
, 2, fh
, err
, err_info
);
215 wtap_file_read_expected_bytes(&cv_hdr
->version
, 1, fh
, err
, err_info
);
216 wtap_file_read_expected_bytes(&cv_hdr
->year
, 2, fh
, err
, err_info
);
217 wtap_file_read_expected_bytes(&cv_hdr
->month
, 1, fh
, err
, err_info
);
218 wtap_file_read_expected_bytes(&cv_hdr
->day
, 1, fh
, err
, err_info
);
219 wtap_file_read_expected_bytes(&cv_hdr
->hours
, 1, fh
, err
, err_info
);
220 wtap_file_read_expected_bytes(&cv_hdr
->minutes
, 1, fh
, err
, err_info
);
221 wtap_file_read_expected_bytes(&cv_hdr
->seconds
, 1, fh
, err
, err_info
);
222 wtap_file_read_expected_bytes(&cv_hdr
->usecs
, 4, fh
, err
, err_info
);
223 wtap_file_read_expected_bytes(&cv_hdr
->flags
, 1, fh
, err
, err_info
);
224 wtap_file_read_expected_bytes(&cv_hdr
->signal_level_percent
, 1, fh
, err
, err_info
);
225 wtap_file_read_expected_bytes(&cv_hdr
->rate
, 1, fh
, err
, err_info
);
226 wtap_file_read_expected_bytes(&cv_hdr
->band
, 1, fh
, err
, err_info
);
227 wtap_file_read_expected_bytes(&cv_hdr
->channel
, 1, fh
, err
, err_info
);
228 wtap_file_read_expected_bytes(&cv_hdr
->direction
, 1, fh
, err
, err_info
);
229 wtap_file_read_expected_bytes(&cv_hdr
->signal_level_dbm
, 1, fh
, err
, err_info
);
230 wtap_file_read_expected_bytes(&cv_hdr
->noise_level
, 1, fh
, err
, err_info
);
232 /* Convert multi-byte values from little endian to host endian format */
233 cv_hdr
->data_len
= GUINT16_FROM_LE(cv_hdr
->data_len
);
234 cv_hdr
->source_data_len
= GUINT16_FROM_LE(cv_hdr
->source_data_len
);
235 cv_hdr
->year
= GUINT16_FROM_LE(cv_hdr
->year
);
236 cv_hdr
->usecs
= GUINT32_FROM_LE(cv_hdr
->usecs
);
241 /* Returns 0 if we can write out the specified encapsulation type
242 * into a CommView format file. */
243 int commview_dump_can_write_encap(int encap
)
247 case WTAP_ENCAP_ETHERNET
:
248 case WTAP_ENCAP_IEEE_802_11
:
249 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO
:
250 case WTAP_ENCAP_TOKEN_RING
:
251 case WTAP_ENCAP_PER_PACKET
:
255 return WTAP_ERR_UNSUPPORTED_ENCAP
;
259 /* Returns TRUE on success, FALSE on failure;
260 sets "*err" to an error code on failure */
261 gboolean
commview_dump_open(wtap_dumper
*wdh
, int *err _U_
)
263 wdh
->subtype_write
= commview_dump
;
264 wdh
->subtype_close
= NULL
;
266 /* There is no file header to write out */
267 wdh
->bytes_dumped
= 0;
272 /* Write a record for a packet to a dump file.
273 * Returns TRUE on success, FALSE on failure. */
274 static gboolean
commview_dump(wtap_dumper
*wdh
,
275 const struct wtap_pkthdr
*phdr
,
276 const guint8
*pd
, int *err
)
278 commview_header_t cv_hdr
;
281 memset(&cv_hdr
, 0, sizeof(cv_hdr
));
283 cv_hdr
.data_len
= GUINT16_TO_LE((guint16
)phdr
->caplen
);
284 cv_hdr
.source_data_len
= GUINT16_TO_LE((guint16
)phdr
->caplen
);
287 tm
= localtime(&phdr
->ts
.secs
);
288 cv_hdr
.year
= tm
->tm_year
+ 1900;
289 cv_hdr
.month
= tm
->tm_mon
+ 1;
290 cv_hdr
.day
= tm
->tm_mday
;
291 cv_hdr
.hours
= tm
->tm_hour
;
292 cv_hdr
.minutes
= tm
->tm_min
;
293 cv_hdr
.seconds
= tm
->tm_sec
;
294 cv_hdr
.usecs
= GUINT32_TO_LE(phdr
->ts
.nsecs
/ 1000);
296 switch(phdr
->pkt_encap
) {
298 case WTAP_ENCAP_ETHERNET
:
299 cv_hdr
.flags
|= MEDIUM_ETHERNET
;
302 case WTAP_ENCAP_IEEE_802_11
:
303 cv_hdr
.flags
|= MEDIUM_WIFI
;
306 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO
:
307 cv_hdr
.flags
|= MEDIUM_WIFI
;
309 cv_hdr
.channel
= phdr
->pseudo_header
.ieee_802_11
.channel
;
310 cv_hdr
.rate
= (guint8
)(phdr
->pseudo_header
.ieee_802_11
.data_rate
& 0xFF);
311 cv_hdr
.direction
= (guint8
)((phdr
->pseudo_header
.ieee_802_11
.data_rate
>> 8) & 0xFF);
312 cv_hdr
.signal_level_percent
= phdr
->pseudo_header
.ieee_802_11
.signal_level
;
315 case WTAP_ENCAP_TOKEN_RING
:
316 cv_hdr
.flags
|= MEDIUM_TOKEN_RING
;
320 *err
= WTAP_ERR_UNSUPPORTED_ENCAP
;
324 if (!wtap_dump_file_write(wdh
, &cv_hdr
.data_len
, 2, err
))
326 if (!wtap_dump_file_write(wdh
, &cv_hdr
.source_data_len
, 2, err
))
328 if (!wtap_dump_file_write(wdh
, &cv_hdr
.version
, 1, err
))
330 if (!wtap_dump_file_write(wdh
, &cv_hdr
.year
, 2, err
))
332 if (!wtap_dump_file_write(wdh
, &cv_hdr
.month
, 1, err
))
334 if (!wtap_dump_file_write(wdh
, &cv_hdr
.day
, 1, err
))
336 if (!wtap_dump_file_write(wdh
, &cv_hdr
.hours
, 1, err
))
338 if (!wtap_dump_file_write(wdh
, &cv_hdr
.minutes
, 1, err
))
340 if (!wtap_dump_file_write(wdh
, &cv_hdr
.seconds
, 1, err
))
342 if (!wtap_dump_file_write(wdh
, &cv_hdr
.usecs
, 4, err
))
344 if (!wtap_dump_file_write(wdh
, &cv_hdr
.flags
, 1, err
))
346 if (!wtap_dump_file_write(wdh
, &cv_hdr
.signal_level_percent
, 1, err
))
348 if (!wtap_dump_file_write(wdh
, &cv_hdr
.rate
, 1, err
))
350 if (!wtap_dump_file_write(wdh
, &cv_hdr
.band
, 1, err
))
352 if (!wtap_dump_file_write(wdh
, &cv_hdr
.channel
, 1, err
))
354 if (!wtap_dump_file_write(wdh
, &cv_hdr
.direction
, 1, err
))
356 if (!wtap_dump_file_write(wdh
, &cv_hdr
.signal_level_dbm
, 2, err
))
358 if (!wtap_dump_file_write(wdh
, &cv_hdr
.noise_level
, 2, err
))
360 wdh
->bytes_dumped
+= COMMVIEW_HEADER_SIZE
;
362 if (!wtap_dump_file_write(wdh
, pd
, phdr
->caplen
, err
))
364 wdh
->bytes_dumped
+= phdr
->caplen
;