6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "file_wrappers.h"
31 #include "lanalyzer.h"
33 /* The LANalyzer format is documented (at least in part) in Novell document
34 TID022037, which can be found at, among other places:
36 http://secinf.net/info/nw/lan/trace.txt
39 /* LANalyzer board types (which indicate the type of network on which
40 the capture was done). */
41 #define BOARD_325 226 /* LANalyzer 325 (Ethernet) */
42 #define BOARD_325TR 227 /* LANalyzer 325TR (Token-ring) */
45 static const guint8 LA_HeaderRegularFake[] = {
46 0x01,0x10,0x4c,0x00,0x01,0x05,0x54,0x72,0x61,0x63,0x65,0x20,0x44,0x69,0x73,0x70,
47 0x6c,0x61,0x79,0x20,0x54,0x72,0x61,0x63,0x65,0x20,0x46,0x69,0x6c,0x65,0x00,0x00,
48 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
49 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
50 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
53 static const guint8 LA_RxChannelNameFake[] = {
54 0x06,0x10,0x80,0x00,0x43,0x68,0x61,0x6e ,0x6e,0x65,0x6c,0x31,0x00,0x43,0x68,0x61,
55 0x6e,0x6e,0x65,0x6c,0x32,0x00,0x43,0x68 ,0x61,0x6e,0x6e,0x65,0x6c,0x33,0x00,0x43,
56 0x68,0x61,0x6e,0x6e,0x65,0x6c,0x34,0x00 ,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x35,
57 0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c ,0x36,0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,
58 0x6c,0x37,0x00,0x43,0x68,0x61,0x6e,0x6e ,0x65,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,
59 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
61 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
65 static const guint8 LA_TxChannelNameFake[] = {
66 0x0b,0x10,0x36,0x00 ,0x54,0x72,0x61,0x6e,0x73,0x31,0x00,0x00,
67 0x00,0x54,0x72,0x61,0x6e,0x73,0x32,0x00 ,0x00,0x00,0x54,0x72,0x61,0x6e,0x73,0x33,
68 0x00,0x00,0x00,0x54,0x72,0x61,0x6e,0x73 ,0x34,0x00,0x00,0x00,0x54,0x72,0x61,0x6e,
69 0x73,0x35,0x00,0x00,0x00,0x54,0x72,0x61 ,0x6e,0x73,0x36,0x00,0x00,0x00
72 static const guint8 LA_RxTemplateNameFake[] = {
74 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
75 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
76 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
77 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
78 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
79 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 static const guint8 LA_TxTemplateNameFake[] = {
87 0x36,0x10,0x36,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
88 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
89 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
90 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00
93 static const guint8 LA_DisplayOptionsFake[] = {
95 0x00,0x00,0x01,0x00,0x01,0x02,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
97 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
99 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
100 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
103 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
106 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
109 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
110 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00
114 static const guint8 LA_CyclicInformationFake[] = {
115 0x09,0x10,0x1a,0x00,0x00,0x00,
116 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
120 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
121 gint64 *data_offset);
122 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
123 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
124 int *err, gchar **err_info);
125 static void lanalyzer_close(wtap *wth);
126 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err);
128 int lanalyzer_open(wtap *wth, int *err, gchar **err_info)
131 char LE_record_type[2];
132 char LE_record_length[2];
134 guint16 board_type, mxslc;
135 guint16 record_type, record_length;
136 guint8 cr_day, cr_month;
140 errno = WTAP_ERR_CANT_READ;
141 bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
142 bytes_read += file_read(LE_record_length, 1, 2, wth->fh);
143 if (bytes_read != 4) {
144 *err = file_error(wth->fh);
149 wth->data_offset += 4;
150 record_type = pletohs(LE_record_type);
151 record_length = pletohs(LE_record_length); /* make sure to do this for while() loop */
153 if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) {
157 /* If we made it this far, then the file is a LANAlyzer file.
158 * Let's get some info from it. Note that we get wth->snapshot_length
159 * from a record later in the file. */
160 wth->file_type = WTAP_FILE_LANALYZER;
161 wth->capture.lanalyzer = g_malloc(sizeof(lanalyzer_t));
162 wth->subtype_read = lanalyzer_read;
163 wth->subtype_seek_read = lanalyzer_seek_read;
164 wth->subtype_close = lanalyzer_close;
165 wth->snapshot_length = 0;
166 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
168 /* Read records until we find the start of packets */
170 if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) {
171 g_free(wth->capture.lanalyzer);
174 wth->data_offset += record_length;
175 errno = WTAP_ERR_CANT_READ;
176 bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
177 bytes_read += file_read(LE_record_length, 1, 2, wth->fh);
178 if (bytes_read != 4) {
179 *err = file_error(wth->fh);
181 g_free(wth->capture.lanalyzer);
184 g_free(wth->capture.lanalyzer);
187 wth->data_offset += 4;
189 record_type = pletohs(LE_record_type);
190 record_length = pletohs(LE_record_length);
192 /*g_message("Record 0x%04X Length %d", record_type, record_length);*/
193 switch (record_type) {
194 /* Trace Summary Record */
196 errno = WTAP_ERR_CANT_READ;
197 bytes_read = file_read(summary, 1, sizeof summary,
199 if (bytes_read != sizeof summary) {
200 *err = file_error(wth->fh);
202 g_free(wth->capture.lanalyzer);
205 g_free(wth->capture.lanalyzer);
208 wth->data_offset += sizeof summary;
210 /* Assume that the date of the creation of the trace file
211 * is the same date of the trace. Lanalyzer doesn't
212 * store the creation date/time of the trace, but only of
213 * the file. Unless you traced at 11:55 PM and saved at 00:05
214 * AM, the assumption that trace.date == file.date is true.
217 cr_month = summary[1];
218 cr_year = pletohs(&summary[2]);
219 /*g_message("Day %d Month %d Year %d (%04X)", cr_day, cr_month,
222 /* Get capture start time. I learned how to do
223 * this from Guy's code in ngsniffer.c
225 tm.tm_year = cr_year - 1900;
226 tm.tm_mon = cr_month - 1;
232 wth->capture.lanalyzer->start = mktime(&tm);
233 /*g_message("Day %d Month %d Year %d", tm.tm_mday,
234 tm.tm_mon, tm.tm_year);*/
235 mxslc = pletohs(&summary[30]);
236 wth->snapshot_length = mxslc;
238 record_length = 0; /* to fake the next iteration of while() */
239 board_type = pletohs(&summary[188]);
240 switch (board_type) {
242 wth->file_encap = WTAP_ENCAP_ETHERNET;
245 wth->file_encap = WTAP_ENCAP_TOKEN_RING;
248 g_free(wth->capture.lanalyzer);
249 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
250 *err_info = g_strdup_printf("lanalyzer: board type %u unknown",
256 /* Trace Packet Data Record */
258 /* Go back header number ob ytes so that lanalyzer_read
259 * can read this header */
260 if (file_seek(wth->fh, -bytes_read, SEEK_CUR, err) == -1) {
261 g_free(wth->capture.lanalyzer);
264 wth->data_offset -= bytes_read;
273 #define DESCRIPTOR_LEN 32
275 /* Read the next packet */
276 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
281 char LE_record_type[2];
282 char LE_record_length[2];
283 guint16 record_type, record_length;
284 gchar descriptor[DESCRIPTOR_LEN];
285 guint16 time_low, time_med, time_high, true_size;
289 /* read the record type and length. */
290 errno = WTAP_ERR_CANT_READ;
291 bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
292 if (bytes_read != 2) {
293 *err = file_error(wth->fh);
294 if (*err == 0 && bytes_read != 0) {
295 *err = WTAP_ERR_SHORT_READ;
299 wth->data_offset += 2;
300 bytes_read = file_read(LE_record_length, 1, 2, wth->fh);
301 if (bytes_read != 2) {
302 *err = file_error(wth->fh);
304 *err = WTAP_ERR_SHORT_READ;
307 wth->data_offset += 2;
309 record_type = pletohs(LE_record_type);
310 record_length = pletohs(LE_record_length);
312 /* Only Trace Packet Data Records should occur now that we're in
313 * the middle of reading packets. If any other record type exists
314 * after a Trace Packet Data Record, mark it as an error. */
315 if (record_type != RT_PacketData) {
316 *err = WTAP_ERR_BAD_RECORD;
317 *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record",
322 packet_size = record_length - DESCRIPTOR_LEN;
325 /* Read the descriptor data */
326 errno = WTAP_ERR_CANT_READ;
327 bytes_read = file_read(descriptor, 1, DESCRIPTOR_LEN, wth->fh);
328 if (bytes_read != DESCRIPTOR_LEN) {
329 *err = file_error(wth->fh);
331 *err = WTAP_ERR_SHORT_READ;
334 wth->data_offset += DESCRIPTOR_LEN;
336 /* Read the packet data */
337 buffer_assure_space(wth->frame_buffer, packet_size);
338 *data_offset = wth->data_offset;
339 errno = WTAP_ERR_CANT_READ;
340 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
341 packet_size, wth->fh);
343 if (bytes_read != packet_size) {
344 *err = file_error(wth->fh);
346 *err = WTAP_ERR_SHORT_READ;
349 wth->data_offset += packet_size;
351 true_size = pletohs(&descriptor[4]);
352 packet_size = pletohs(&descriptor[6]);
355 * OK, is the frame data size greater than than what's left of the
358 if (packet_size > record_length - DESCRIPTOR_LEN) {
360 * Yes - treat this as an error.
362 *err = WTAP_ERR_BAD_RECORD;
363 *err_info = g_strdup("lanalyzer: Record length is less than packet size");
367 time_low = pletohs(&descriptor[8]);
368 time_med = pletohs(&descriptor[10]);
369 time_high = pletohs(&descriptor[12]);
370 t = (((guint64)time_low) << 0) + (((guint64)time_med) << 16) +
371 (((guint64)time_high) << 32);
372 tsecs = (time_t) (t/2000000);
373 wth->phdr.ts.secs = tsecs + wth->capture.lanalyzer->start;
374 wth->phdr.ts.nsecs = ((guint32) (t - tsecs*2000000)) * 500;
376 if (true_size - 4 >= packet_size) {
378 * It appears that the "true size" includes the FCS;
379 * make it reflect the non-FCS size (the "packet size"
380 * appears never to include the FCS, even if no slicing
385 wth->phdr.len = true_size;
386 wth->phdr.caplen = packet_size;
388 switch (wth->file_encap) {
390 case WTAP_ENCAP_ETHERNET:
391 /* We assume there's no FCS in this frame. */
392 wth->pseudo_header.eth.fcs_len = 0;
399 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
400 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
401 int *err, gchar **err_info _U_)
405 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
409 * Read the packet data.
411 bytes_read = file_read(pd, sizeof(guint8), length, wth->random_fh);
412 if (bytes_read != length) {
413 *err = file_error(wth->random_fh);
415 *err = WTAP_ERR_SHORT_READ;
419 switch (wth->file_encap) {
421 case WTAP_ENCAP_ETHERNET:
422 /* We assume there's no FCS in this frame. */
423 pseudo_header->eth.fcs_len = 0;
431 lanalyzer_close(wtap *wth)
433 g_free(wth->capture.lanalyzer);
436 /*---------------------------------------------------
438 * Write one block with error control
439 *---------------------------------------------------*/
440 static int swrite(const void* what, guint size, FILE *hd)
444 nwritten = fwrite(what, 1, size, hd);
445 if (nwritten != size) {
446 if (nwritten == 0 && ferror(hd))
449 return WTAP_ERR_SHORT_WRITE;
454 /*---------------------------------------------------
456 * Write one block with error control
457 *---------------------------------------------------*/
458 static int s0write(size_t cnt, FILE *hd)
460 static guint8 z64[64];
465 snack = cnt > 64 ? 64 : cnt;
466 nwritten = fwrite(z64, 1, snack, hd);
467 if (nwritten != snack) {
468 if (nwritten == 0 && ferror(hd))
471 return WTAP_ERR_SHORT_WRITE;
478 /*---------------------------------------------------
480 * Write one block with error control
481 *---------------------------------------------------*/
482 static int s8write(const guint8 s8, FILE *hd)
486 nwritten = fwrite(&s8, 1, 1, hd);
488 if (nwritten == 0 && ferror(hd))
491 return WTAP_ERR_SHORT_WRITE;
495 /*---------------------------------------------------
497 * Write one block with error control
498 *---------------------------------------------------*/
499 static int s16write(const guint16 s16, FILE *hd)
503 nwritten = fwrite(&s16, 1, 2, hd);
505 if (nwritten == 0 && ferror(hd))
508 return WTAP_ERR_SHORT_WRITE;
512 /*---------------------------------------------------
514 * Write one block with error control
515 *---------------------------------------------------*/
516 static int s32write(const guint32 s32, FILE *hd)
520 nwritten = fwrite(&s32, 1, 4, hd);
522 if (nwritten == 0 && ferror(hd))
525 return WTAP_ERR_SHORT_WRITE;
529 /*---------------------------------------------------
531 * calculates C.c = A.a - B.b
532 *---------------------------------------------------*/
533 static void my_timersub(const struct timeval *a,
534 const struct timeval *b,
537 gint32 usec = a->tv_usec;
539 c->tv_sec = a->tv_sec - b->tv_sec;
540 if (b->tv_usec > usec) {
544 c->tv_usec = usec - b->tv_usec;
546 /*---------------------------------------------------
547 * Write a record for a packet to a dump file.
548 * Returns TRUE on success, FALSE on failure.
549 *---------------------------------------------------*/
550 static gboolean lanalyzer_dump(wtap_dumper *wdh,
551 const struct wtap_pkthdr *phdr,
552 const union wtap_pseudo_header *pseudo_header _U_,
553 const guchar *pd, int *err)
560 LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->dump.opaque);
562 int thisSize = phdr->caplen + LA_PacketRecordSize + LA_RecordHeaderSize;
564 if (wdh->bytes_dumped + thisSize > LA_ProFileLimit) {
565 /* printf(" LA_ProFileLimit reached\n"); */
567 return FALSE; /* and don't forget the header */
570 len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0);
572 *err = s16write(htoles(0x1005), wdh->fh);
575 *err = s16write(htoles(len), wdh->fh);
579 tv.tv_sec = (long int) phdr->ts.secs;
580 tv.tv_usec = phdr->ts.nsecs / 1000;
583 /* collect some information for the
584 * finally written header
586 /* XXX - this conversion could probably improved, if the start uses ns */
590 itmp->encap = wdh->encap;
594 my_timersub(&(tv),&(itmp->start),&td);
596 x = (double) td.tv_usec;
597 x += (double) td.tv_sec * 1000000;
600 *err = s16write(htoles(0x0001), wdh->fh); /* pr.rx_channels */
603 *err = s16write(htoles(0x0008), wdh->fh); /* pr.rx_errors */
606 *err = s16write(htoles(phdr->len + 4), wdh->fh); /* pr.rx_frm_len */
609 *err = s16write(htoles(phdr->caplen), wdh->fh); /* pr.rx_frm_sln */
613 for (i = 0; i < 3; i++) {
614 *err = s16write(htoles((guint16) x), wdh->fh);/* pr.rx_time[i] */
620 *err = s32write(htolel(++itmp->pkts), wdh->fh); /* pr.pktno */
623 *err = s16write(htoles(itmp->lastlen), wdh->fh); /* pr.prlen */
628 *err = s0write(12, wdh->fh);
632 *err = swrite(pd , phdr->caplen , wdh->fh);
636 wdh->bytes_dumped += thisSize;
641 /*---------------------------------------------------
642 * Returns 0 if we could write the specified encapsulation type,
643 * an error indication otherwise.
644 *---------------------------------------------------*/
645 int lanalyzer_dump_can_write_encap(int encap)
647 /* Per-packet encapsulations aren't supported. */
648 if (encap == WTAP_ENCAP_PER_PACKET)
649 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
651 if ( encap != WTAP_ENCAP_ETHERNET
652 && encap != WTAP_ENCAP_TOKEN_RING )
653 return WTAP_ERR_UNSUPPORTED_ENCAP;
655 * printf("lanalyzer_dump_can_write_encap(%d)\n",encap);
660 /*---------------------------------------------------
661 * Returns TRUE on success, FALSE on failure; sets "*err" to an
662 * error code on failure
663 *---------------------------------------------------*/
664 gboolean lanalyzer_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
669 /* This is a LANalyzer file. We can't fill in some fields in the
670 header until all the packets have been written, so we can't
673 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
677 tmp = g_malloc(sizeof(LA_TmpInfo));
683 ((LA_TmpInfo*)tmp)->init = FALSE;
684 wdh->dump.opaque = tmp;
685 wdh->subtype_write = lanalyzer_dump;
686 wdh->subtype_close = lanalyzer_dump_close;
688 /* Some of the fields in the file header aren't known yet so
689 just skip over it for now. It will be created after all
690 of the packets have been written. */
692 jump = sizeof (LA_HeaderRegularFake)
693 + sizeof (LA_RxChannelNameFake)
694 + sizeof (LA_TxChannelNameFake)
695 + sizeof (LA_RxTemplateNameFake)
696 + sizeof (LA_TxTemplateNameFake)
697 + sizeof (LA_DisplayOptionsFake)
698 + LA_SummaryRecordSize
699 + LA_SubfileSummaryRecordSize
700 + sizeof (LA_CyclicInformationFake)
701 + LA_IndexRecordSize;
703 if (fseek(wdh->fh, jump, SEEK_SET) == -1) {
707 wdh->bytes_dumped = jump;
711 /*---------------------------------------------------
713 *---------------------------------------------------*/
714 static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err)
716 LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->dump.opaque);
717 struct tm *fT = localtime( (time_t *) &(itmp->start.tv_sec));
718 guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING
719 ? BOARD_325TR /* LANalyzer Board Type */
720 : BOARD_325; /* LANalyzer Board Type */
722 fseek(wdh->fh, 0, SEEK_SET);
724 *err = swrite(&LA_HeaderRegularFake, sizeof LA_HeaderRegularFake, wdh->fh);
727 *err = swrite(&LA_RxChannelNameFake , sizeof LA_RxChannelNameFake , wdh->fh);
730 *err = swrite(&LA_TxChannelNameFake , sizeof LA_TxChannelNameFake , wdh->fh);
733 *err = swrite(&LA_RxTemplateNameFake, sizeof LA_RxTemplateNameFake, wdh->fh);
736 *err = swrite(&LA_TxTemplateNameFake, sizeof LA_TxTemplateNameFake, wdh->fh);
739 *err = swrite(&LA_DisplayOptionsFake, sizeof LA_DisplayOptionsFake, wdh->fh);
742 /*-----------------------------------------------------------------*/
743 *err = s16write(htoles(RT_Summary), wdh->fh); /* rid */
746 *err = s16write(htoles(SummarySize), wdh->fh); /* rlen */
749 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.datcre.day */
752 *err = s8write((guint8) (fT->tm_mon+1), wdh->fh); /* s.datcre.mon */
755 *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datcre.year */
758 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.datclo.day */
761 *err = s8write((guint8) (fT->tm_mon+1), wdh->fh); /* s.datclo.mon */
764 *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datclo.year */
767 *err = s8write((guint8) fT->tm_sec, wdh->fh); /* s.timeopn.second */
770 *err = s8write((guint8) fT->tm_min, wdh->fh); /* s.timeopn.minute */
773 *err = s8write((guint8) fT->tm_hour, wdh->fh); /* s.timeopn.hour */
776 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.timeopn.mday */
779 *err = s0write(2, wdh->fh);
782 *err = s8write((guint8) fT->tm_sec, wdh->fh); /* s.timeclo.second */
785 *err = s8write((guint8) fT->tm_min, wdh->fh); /* s.timeclo.minute */
788 *err = s8write((guint8) fT->tm_hour, wdh->fh); /* s.timeclo.hour */
791 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.timeclo.mday */
794 *err = s0write(2, wdh->fh);
797 *err = s0write(6, wdh->fh); /* EAddr == 0 */
800 *err = s16write(htoles(1), wdh->fh); /* s.mxseqno */
803 *err = s16write(htoles(0), wdh->fh); /* s.slcoffo */
806 *err = s16write(htoles(1514), wdh->fh); /* s.mxslc */
809 *err = s32write(htolel(itmp->pkts), wdh->fh); /* s.totpktt */
812 *err = s0write(12, wdh->fh); /* statrg == 0; ? -1*/
813 if (*err) /* stptrg == 0; ? -1*/
814 return FALSE; /* s.mxpkta[0]=0 */
815 *err = s32write(htolel(itmp->pkts), wdh->fh); /* sr.s.mxpkta[1] */
818 *err = s0write(34*4, wdh->fh); /* s.mxpkta[2-33]=0 */
821 *err = s16write(htoles(board_type), wdh->fh);
824 *err = s0write(20, wdh->fh); /* board_version == 0 */
827 /*-----------------------------------------------------------------*/
828 *err = s16write(htoles(RT_SubfileSummary), wdh->fh); /* ssr.rid */
831 *err = s16write(htoles(LA_SubfileSummaryRecordSize-4), wdh->fh); /* ssr.rlen */
834 *err = s16write(htoles(1), wdh->fh); /* ssr.seqno */
837 *err = s32write(htolel(itmp->pkts), wdh->fh); /* ssr.totpkts */
840 /*-----------------------------------------------------------------*/
841 *err = swrite(&LA_CyclicInformationFake, sizeof LA_CyclicInformationFake, wdh->fh);
844 /*-----------------------------------------------------------------*/
845 *err = s16write(htoles(RT_Index), wdh->fh); /* rid */
848 *err = s16write(htoles(LA_IndexRecordSize -4), wdh->fh);/* rlen */
851 *err = s16write(htoles(LA_IndexSize), wdh->fh); /* idxsp */
854 *err = s0write(LA_IndexRecordSize - 6, wdh->fh);
861 /*---------------------------------------------------
862 * Finish writing to a dump file.
863 * Returns TRUE on success, FALSE on failure.
864 *---------------------------------------------------*/
865 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err)
867 lanalyzer_dump_header(wdh,err);
868 return *err ? FALSE : TRUE;