3 * $Id: lanalyzer.c,v 1.48 2004/07/08 07:32:39 guy Exp $
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,
122 static gboolean lanalyzer_seek_read(wtap *wth, long 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;
167 /* Read records until we find the start of packets */
169 if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) {
170 g_free(wth->capture.lanalyzer);
173 wth->data_offset += record_length;
174 errno = WTAP_ERR_CANT_READ;
175 bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
176 bytes_read += file_read(LE_record_length, 1, 2, wth->fh);
177 if (bytes_read != 4) {
178 *err = file_error(wth->fh);
180 g_free(wth->capture.lanalyzer);
183 g_free(wth->capture.lanalyzer);
186 wth->data_offset += 4;
188 record_type = pletohs(LE_record_type);
189 record_length = pletohs(LE_record_length);
191 /*g_message("Record 0x%04X Length %d", record_type, record_length);*/
192 switch (record_type) {
193 /* Trace Summary Record */
195 errno = WTAP_ERR_CANT_READ;
196 bytes_read = file_read(summary, 1, sizeof summary,
198 if (bytes_read != sizeof summary) {
199 *err = file_error(wth->fh);
201 g_free(wth->capture.lanalyzer);
204 g_free(wth->capture.lanalyzer);
207 wth->data_offset += sizeof summary;
209 /* Assume that the date of the creation of the trace file
210 * is the same date of the trace. Lanalyzer doesn't
211 * store the creation date/time of the trace, but only of
212 * the file. Unless you traced at 11:55 PM and saved at 00:05
213 * AM, the assumption that trace.date == file.date is true.
216 cr_month = summary[1];
217 cr_year = pletohs(&summary[2]);
218 /*g_message("Day %d Month %d Year %d (%04X)", cr_day, cr_month,
221 /* Get capture start time. I learned how to do
222 * this from Guy's code in ngsniffer.c
224 tm.tm_year = cr_year - 1900;
225 tm.tm_mon = cr_month - 1;
231 wth->capture.lanalyzer->start = mktime(&tm);
232 /*g_message("Day %d Month %d Year %d", tm.tm_mday,
233 tm.tm_mon, tm.tm_year);*/
234 mxslc = pletohs(&summary[30]);
235 wth->snapshot_length = mxslc;
237 record_length = 0; /* to fake the next iteration of while() */
238 board_type = pletohs(&summary[188]);
239 switch (board_type) {
241 wth->file_encap = WTAP_ENCAP_ETHERNET;
244 wth->file_encap = WTAP_ENCAP_TOKEN_RING;
247 g_free(wth->capture.lanalyzer);
248 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
249 *err_info = g_strdup_printf("lanalyzer: board type %u unknown",
255 /* Trace Packet Data Record */
257 /* Go back header number ob ytes so that lanalyzer_read
258 * can read this header */
259 if (file_seek(wth->fh, -bytes_read, SEEK_CUR, err) == -1) {
260 g_free(wth->capture.lanalyzer);
263 wth->data_offset -= bytes_read;
272 #define DESCRIPTOR_LEN 32
274 /* Read the next packet */
275 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
280 char LE_record_type[2];
281 char LE_record_length[2];
282 guint16 record_type, record_length;
283 gchar descriptor[DESCRIPTOR_LEN];
284 guint16 time_low, time_med, time_high, true_size;
287 /* read the record type and length. */
288 errno = WTAP_ERR_CANT_READ;
289 bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
290 if (bytes_read != 2) {
291 *err = file_error(wth->fh);
292 if (*err == 0 && bytes_read != 0) {
293 *err = WTAP_ERR_SHORT_READ;
297 wth->data_offset += 2;
298 bytes_read = file_read(LE_record_length, 1, 2, wth->fh);
299 if (bytes_read != 2) {
300 *err = file_error(wth->fh);
302 *err = WTAP_ERR_SHORT_READ;
305 wth->data_offset += 2;
307 record_type = pletohs(LE_record_type);
308 record_length = pletohs(LE_record_length);
310 /* Only Trace Packet Data Records should occur now that we're in
311 * the middle of reading packets. If any other record type exists
312 * after a Trace Packet Data Record, mark it as an error. */
313 if (record_type != RT_PacketData) {
314 *err = WTAP_ERR_BAD_RECORD;
315 *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record",
320 packet_size = record_length - DESCRIPTOR_LEN;
323 /* Read the descriptor data */
324 errno = WTAP_ERR_CANT_READ;
325 bytes_read = file_read(descriptor, 1, DESCRIPTOR_LEN, wth->fh);
326 if (bytes_read != DESCRIPTOR_LEN) {
327 *err = file_error(wth->fh);
329 *err = WTAP_ERR_SHORT_READ;
332 wth->data_offset += DESCRIPTOR_LEN;
334 /* Read the packet data */
335 buffer_assure_space(wth->frame_buffer, packet_size);
336 *data_offset = wth->data_offset;
337 errno = WTAP_ERR_CANT_READ;
338 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
339 packet_size, wth->fh);
341 if (bytes_read != packet_size) {
342 *err = file_error(wth->fh);
344 *err = WTAP_ERR_SHORT_READ;
347 wth->data_offset += packet_size;
349 true_size = pletohs(&descriptor[4]);
350 packet_size = pletohs(&descriptor[6]);
351 time_low = pletohs(&descriptor[8]);
352 time_med = pletohs(&descriptor[10]);
353 time_high = pletohs(&descriptor[12]);
356 * OK, is the frame data size greater than than what's left of the
359 if (packet_size > record_length - DESCRIPTOR_LEN) {
361 * Yes - treat this as an error.
363 *err = WTAP_ERR_BAD_RECORD;
364 *err_info = g_strdup("lanalyzer: Record length is less than packet size");
368 t = (double)time_low+(double)(time_med)*65536.0 +
369 (double)time_high*4294967296.0;
370 t = t/1000000.0 * 0.5; /* t = # of secs */
371 t += wth->capture.lanalyzer->start;
373 wth->phdr.ts.tv_sec = (long)t;
374 wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec))
377 if (true_size - 4 >= packet_size) {
379 * It appears that the "true size" includes the FCS;
380 * make it reflect the non-FCS size (the "packet size"
381 * appears never to include the FCS, even if no slicing
386 wth->phdr.len = true_size;
387 wth->phdr.caplen = packet_size;
389 switch (wth->file_encap) {
391 case WTAP_ENCAP_ETHERNET:
392 /* We assume there's no FCS in this frame. */
393 wth->pseudo_header.eth.fcs_len = 0;
400 static gboolean lanalyzer_seek_read(wtap *wth, long seek_off,
401 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
402 int *err, gchar **err_info _U_)
406 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
410 * Read the packet data.
412 bytes_read = file_read(pd, sizeof(guint8), length, wth->random_fh);
413 if (bytes_read != length) {
414 *err = file_error(wth->random_fh);
416 *err = WTAP_ERR_SHORT_READ;
420 switch (wth->file_encap) {
422 case WTAP_ENCAP_ETHERNET:
423 /* We assume there's no FCS in this frame. */
424 pseudo_header->eth.fcs_len = 0;
432 lanalyzer_close(wtap *wth)
434 g_free(wth->capture.lanalyzer);
437 /*---------------------------------------------------
439 * Write one block with error control
440 *---------------------------------------------------*/
441 static int swrite(const void* what, guint size, FILE *hd)
445 nwritten = fwrite(what, 1, size, hd);
446 if (nwritten != size) {
447 if (nwritten == 0 && ferror(hd))
450 return WTAP_ERR_SHORT_WRITE;
455 /*---------------------------------------------------
457 * Write one block with error control
458 *---------------------------------------------------*/
459 static int s0write(guint cnt, FILE *hd)
461 static guint8 z64[64];
466 snack = cnt > 64 ? 64 : cnt;
467 nwritten = fwrite(z64, 1, snack, hd);
468 if (nwritten != snack) {
469 if (nwritten == 0 && ferror(hd))
472 return WTAP_ERR_SHORT_WRITE;
479 /*---------------------------------------------------
481 * Write one block with error control
482 *---------------------------------------------------*/
483 static int s8write(const guint8 s8, FILE *hd)
487 nwritten = fwrite(&s8, 1, 1, hd);
489 if (nwritten == 0 && ferror(hd))
492 return WTAP_ERR_SHORT_WRITE;
496 /*---------------------------------------------------
498 * Write one block with error control
499 *---------------------------------------------------*/
500 static int s16write(const guint16 s16, FILE *hd)
504 nwritten = fwrite(&s16, 1, 2, hd);
506 if (nwritten == 0 && ferror(hd))
509 return WTAP_ERR_SHORT_WRITE;
513 /*---------------------------------------------------
515 * Write one block with error control
516 *---------------------------------------------------*/
517 static int s32write(const guint32 s32, FILE *hd)
521 nwritten = fwrite(&s32, 1, 4, hd);
523 if (nwritten == 0 && ferror(hd))
526 return WTAP_ERR_SHORT_WRITE;
530 /*---------------------------------------------------
532 * calculates C.c = A.a - B.b
533 *---------------------------------------------------*/
534 static void my_timersub(const struct timeval *a,
535 const struct timeval *b,
538 gint32 usec = a->tv_usec;
540 c->tv_sec = a->tv_sec - b->tv_sec;
541 if (b->tv_usec > usec) {
545 c->tv_usec = usec - b->tv_usec;
547 /*---------------------------------------------------
548 * Write a record for a packet to a dump file.
549 * Returns TRUE on success, FALSE on failure.
550 *---------------------------------------------------*/
551 static gboolean lanalyzer_dump(wtap_dumper *wdh,
552 const struct wtap_pkthdr *phdr,
553 const union wtap_pseudo_header *pseudo_header _U_,
554 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);
581 /* collect some information for the
582 * finally written header
584 itmp->start = phdr->ts;
587 itmp->encap = wdh->encap;
591 my_timersub(&(phdr->ts),&(itmp->start),&td);
593 x = (double) td.tv_usec;
594 x += (double) td.tv_sec * 1000000;
597 *err = s16write(htoles(0x0001), wdh->fh); /* pr.rx_channels */
600 *err = s16write(htoles(0x0008), wdh->fh); /* pr.rx_errors */
603 *err = s16write(htoles(phdr->len + 4), wdh->fh); /* pr.rx_frm_len */
606 *err = s16write(htoles(phdr->caplen), wdh->fh); /* pr.rx_frm_sln */
610 for (i = 0; i < 3; i++) {
611 *err = s16write(htoles((guint16) x), wdh->fh);/* pr.rx_time[i] */
617 *err = s32write(htolel(++itmp->pkts), wdh->fh); /* pr.pktno */
620 *err = s16write(htoles(itmp->lastlen), wdh->fh); /* pr.prlen */
625 *err = s0write(12, wdh->fh);
629 *err = swrite(pd , phdr->caplen , wdh->fh);
633 wdh->bytes_dumped += thisSize;
638 /*---------------------------------------------------
639 * Returns 0 if we could write the specified encapsulation type,
640 * an error indication otherwise.
641 *---------------------------------------------------*/
642 int lanalyzer_dump_can_write_encap(int encap)
644 /* Per-packet encapsulations aren't supported. */
645 if (encap == WTAP_ENCAP_PER_PACKET)
646 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
648 if ( encap != WTAP_ENCAP_ETHERNET
649 && encap != WTAP_ENCAP_TOKEN_RING )
650 return WTAP_ERR_UNSUPPORTED_ENCAP;
652 * printf("lanalyzer_dump_can_write_encap(%d)\n",encap);
657 /*---------------------------------------------------
658 * Returns TRUE on success, FALSE on failure; sets "*err" to an
659 * error code on failure
660 *---------------------------------------------------*/
661 gboolean lanalyzer_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
666 /* This is a LANalyzer file. We can't fill in some fields in the
667 header until all the packets have been written, so we can't
670 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
674 tmp = g_malloc(sizeof(LA_TmpInfo));
680 ((LA_TmpInfo*)tmp)->init = FALSE;
681 wdh->dump.opaque = tmp;
682 wdh->subtype_write = lanalyzer_dump;
683 wdh->subtype_close = lanalyzer_dump_close;
685 /* Some of the fields in the file header aren't known yet so
686 just skip over it for now. It will be created after all
687 of the packets have been written. */
689 jump = sizeof (LA_HeaderRegularFake)
690 + sizeof (LA_RxChannelNameFake)
691 + sizeof (LA_TxChannelNameFake)
692 + sizeof (LA_RxTemplateNameFake)
693 + sizeof (LA_TxTemplateNameFake)
694 + sizeof (LA_DisplayOptionsFake)
695 + LA_SummaryRecordSize
696 + LA_SubfileSummaryRecordSize
697 + sizeof (LA_CyclicInformationFake)
698 + LA_IndexRecordSize;
700 if (fseek(wdh->fh, jump, SEEK_SET) == -1) {
704 wdh->bytes_dumped = jump;
708 /*---------------------------------------------------
710 *---------------------------------------------------*/
711 static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err)
713 LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->dump.opaque);
714 struct tm *fT = localtime(&(itmp->start.tv_sec));
715 guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING
716 ? BOARD_325TR /* LANalyzer Board Type */
717 : BOARD_325; /* LANalyzer Board Type */
719 fseek(wdh->fh, 0, SEEK_SET);
721 *err = swrite(&LA_HeaderRegularFake, sizeof LA_HeaderRegularFake, wdh->fh);
724 *err = swrite(&LA_RxChannelNameFake , sizeof LA_RxChannelNameFake , wdh->fh);
727 *err = swrite(&LA_TxChannelNameFake , sizeof LA_TxChannelNameFake , wdh->fh);
730 *err = swrite(&LA_RxTemplateNameFake, sizeof LA_RxTemplateNameFake, wdh->fh);
733 *err = swrite(&LA_TxTemplateNameFake, sizeof LA_TxTemplateNameFake, wdh->fh);
736 *err = swrite(&LA_DisplayOptionsFake, sizeof LA_DisplayOptionsFake, wdh->fh);
739 /*-----------------------------------------------------------------*/
740 *err = s16write(htoles(RT_Summary), wdh->fh); /* rid */
743 *err = s16write(htoles(SummarySize), wdh->fh); /* rlen */
746 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.datcre.day */
749 *err = s8write((guint8) (fT->tm_mon+1), wdh->fh); /* s.datcre.mon */
752 *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datcre.year */
755 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.datclo.day */
758 *err = s8write((guint8) (fT->tm_mon+1), wdh->fh); /* s.datclo.mon */
761 *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datclo.year */
764 *err = s8write((guint8) fT->tm_sec, wdh->fh); /* s.timeopn.second */
767 *err = s8write((guint8) fT->tm_min, wdh->fh); /* s.timeopn.minute */
770 *err = s8write((guint8) fT->tm_hour, wdh->fh); /* s.timeopn.hour */
773 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.timeopn.mday */
776 *err = s0write(2, wdh->fh);
779 *err = s8write((guint8) fT->tm_sec, wdh->fh); /* s.timeclo.second */
782 *err = s8write((guint8) fT->tm_min, wdh->fh); /* s.timeclo.minute */
785 *err = s8write((guint8) fT->tm_hour, wdh->fh); /* s.timeclo.hour */
788 *err = s8write((guint8) fT->tm_mday, wdh->fh); /* s.timeclo.mday */
791 *err = s0write(2, wdh->fh);
794 *err = s0write(6, wdh->fh); /* EAddr == 0 */
797 *err = s16write(htoles(1), wdh->fh); /* s.mxseqno */
800 *err = s16write(htoles(0), wdh->fh); /* s.slcoffo */
803 *err = s16write(htoles(1514), wdh->fh); /* s.mxslc */
806 *err = s32write(htolel(itmp->pkts), wdh->fh); /* s.totpktt */
809 *err = s0write(12, wdh->fh); /* statrg == 0; ? -1*/
810 if (*err) /* stptrg == 0; ? -1*/
811 return FALSE; /* s.mxpkta[0]=0 */
812 *err = s32write(htolel(itmp->pkts), wdh->fh); /* sr.s.mxpkta[1] */
815 *err = s0write(34*4, wdh->fh); /* s.mxpkta[2-33]=0 */
818 *err = s16write(htoles(board_type), wdh->fh);
821 *err = s0write(20, wdh->fh); /* board_version == 0 */
824 /*-----------------------------------------------------------------*/
825 *err = s16write(htoles(RT_SubfileSummary), wdh->fh); /* ssr.rid */
828 *err = s16write(htoles(LA_SubfileSummaryRecordSize-4), wdh->fh); /* ssr.rlen */
831 *err = s16write(htoles(1), wdh->fh); /* ssr.seqno */
834 *err = s32write(htolel(itmp->pkts), wdh->fh); /* ssr.totpkts */
837 /*-----------------------------------------------------------------*/
838 *err = swrite(&LA_CyclicInformationFake, sizeof LA_CyclicInformationFake, wdh->fh);
841 /*-----------------------------------------------------------------*/
842 *err = s16write(htoles(RT_Index), wdh->fh); /* rid */
845 *err = s16write(htoles(LA_IndexRecordSize -4), wdh->fh);/* rlen */
848 *err = s16write(htoles(LA_IndexSize), wdh->fh); /* idxsp */
851 *err = s0write(LA_IndexRecordSize - 6, wdh->fh);
858 /*---------------------------------------------------
859 * Finish writing to a dump file.
860 * Returns TRUE on success, FALSE on failure.
861 *---------------------------------------------------*/
862 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err)
864 lanalyzer_dump_header(wdh,err);
865 return *err ? FALSE : TRUE;