Ethereal-dev: [Ethereal-dev] Patch 3 for writing Novell LANalyzer files

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Markus Steinmann <ms@xxxxxx>
Date: Thu, 27 Jun 2002 17:34:25 +0200
Hi,

once again thanks to the suggestions from Guy.
Here comes the result:

Done:
	- good-bye to #pragma pack(2),
		no more writing structures at all
	- "LANalyzer", as Novell like it
	- replace obsolete REC_ defines
	- error EFBIG instead of WTAB_ERR_SHORT_WRITE

and this should now be byte layout independent (htoles, htolel).

Nice regards

		Markus
__________________________________________________________________

Markus Steinmann                                         ms@xxxxxx
Software Development
SEH Computertechnik GmbH Bielefeld               http://www.seh.de
__________________________________________________________________
? wiretap/..lanalyzer.c,,
? wiretap/.file.c,
? wiretap/.kped
? wiretap/.lanalyzer.c,
? wiretap/.lanalyzer.h,
? wiretap/.snoop.c,
? wiretap/.visual.c,
? wiretap/mops.xd
Index: wiretap/file.c
===================================================================
RCS file: /cvsroot/ethereal/wiretap/file.c,v
retrieving revision 1.92
diff -u -r1.92 file.c
--- file.c	2002/06/07 07:47:57	1.92
+++ file.c	2002/06/27 15:20:08
@@ -4,17 +4,17 @@
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxx>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -343,8 +343,8 @@
 	  NULL, NULL },
 
 	/* WTAP_FILE_LANALYZER */
-	{ "Novell LANalyzer", NULL,
-	  NULL, NULL },
+	{ "Novell LANalyzer","lanalyzer",
+	  lanalyzer_dump_can_write_encap, lanalyzer_dump_open },
 
 	/* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
 	{ "Network Associates Sniffer (DOS-based)", "ngsniffer",
Index: wiretap/lanalyzer.c
===================================================================
RCS file: /cvsroot/ethereal/wiretap/lanalyzer.c,v
retrieving revision 1.33
diff -u -r1.33 lanalyzer.c
--- lanalyzer.c	2002/06/07 07:27:35	1.33
+++ lanalyzer.c	2002/06/27 15:20:09
@@ -4,17 +4,17 @@
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxx>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -36,19 +36,90 @@
 	http://secinf.net/info/nw/lan/trace.txt
  */
 
-/* Record types. */
-#define REC_TRACE_HEADER	0x1001
-#define REC_CYCLIC_TRACE_HEADER	0x1007
-#define REC_TRACE_SUMMARY	0x1002
-#define REC_TRACE_PACKET_DATA	0x1005
-
 /* LANalyzer board types (which indicate the type of network on which
    the capture was done). */
-#define BOARD_325		226	/* LANalyzer 325 (Ethernet) */
+#define BOARD_325		      226	/* LANalyzer 325 (Ethernet) */
 #define BOARD_325TR		227	/* LANalyzer 325TR (Token-ring) */
 
+
+static const gint8 LA_HeaderRegularFake[] = {
+0x01,0x10,0x4c,0x00,0x01,0x05,0x54,0x72,0x61,0x63,0x65,0x20,0x44,0x69,0x73,0x70,
+0x6c,0x61,0x79,0x20,0x54,0x72,0x61,0x63,0x65,0x20,0x46,0x69,0x6c,0x65,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+      };
+
+static const gint8 LA_RxChannelNameFake[] = {
+0x06,0x10,0x80,0x00,0x43,0x68,0x61,0x6e ,0x6e,0x65,0x6c,0x31,0x00,0x43,0x68,0x61,
+0x6e,0x6e,0x65,0x6c,0x32,0x00,0x43,0x68 ,0x61,0x6e,0x6e,0x65,0x6c,0x33,0x00,0x43,
+0x68,0x61,0x6e,0x6e,0x65,0x6c,0x34,0x00 ,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x35,
+0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c ,0x36,0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,
+0x6c,0x37,0x00,0x43,0x68,0x61,0x6e,0x6e ,0x65,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00
+      };
+
+static const gint8 LA_TxChannelNameFake[] = {
+                    0x0b,0x10,0x36,0x00 ,0x54,0x72,0x61,0x6e,0x73,0x31,0x00,0x00,
+0x00,0x54,0x72,0x61,0x6e,0x73,0x32,0x00 ,0x00,0x00,0x54,0x72,0x61,0x6e,0x73,0x33,
+0x00,0x00,0x00,0x54,0x72,0x61,0x6e,0x73 ,0x34,0x00,0x00,0x00,0x54,0x72,0x61,0x6e,
+0x73,0x35,0x00,0x00,0x00,0x54,0x72,0x61 ,0x6e,0x73,0x36,0x00,0x00,0x00
+      };
+
+static const gint8 LA_RxTemplateNameFake[] = {
+                                                                       0x35,0x10,
+0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00
+      };
+
+static const gint8 LA_TxTemplateNameFake[] = {
+          0x36,0x10,0x36,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00
+      };
+
+static const gint8 LA_DisplayOptionsFake[] = {
+                                                             0x0a,0x10,0x0a,0x01,
+0x00,0x00,0x01,0x00,0x01,0x02,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00
+      };
+
+static const gint8 LA_CyclicInformationFake[] = {
+                                                   0x09,0x10,0x1a,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+      };
+
 static gboolean lanalyzer_read(wtap *wth, int *err, long *data_offset);
-static void lanalyzer_close(wtap *wth);
+static void     lanalyzer_close(wtap *wth);
+static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err);
 
 int lanalyzer_open(wtap *wth, int *err)
 {
@@ -74,7 +145,7 @@
 	record_type = pletohs(LE_record_type);
 	record_length = pletohs(LE_record_length); /* make sure to do this for while() loop */
 
-	if (record_type != REC_TRACE_HEADER && record_type != REC_CYCLIC_TRACE_HEADER) {  
+	if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) {
 		return 0;
 	}
 
@@ -115,7 +186,7 @@
 		/*g_message("Record 0x%04X Length %d", record_type, record_length);*/
 		switch (record_type) {
 			/* Trace Summary Record */
-			case REC_TRACE_SUMMARY:
+			case RT_Summary:
 				errno = WTAP_ERR_CANT_READ;
 				bytes_read = file_read(summary, 1, sizeof summary,
 				    wth->fh);
@@ -180,7 +251,7 @@
 				break;
 
 			/* Trace Packet Data Record */
-			case REC_TRACE_PACKET_DATA:
+			case RT_PacketData:
 				/* Go back header number ob ytes so that lanalyzer_read
 				 * can read this header */
 				if (file_seek(wth->fh, -bytes_read, SEEK_CUR, err) == -1) {
@@ -193,7 +264,7 @@
 			default:
 				; /* no action */
 		}
-	} 
+	}
 }
 
 #define DESCRIPTOR_LEN	32
@@ -205,10 +276,10 @@
 	int		bytes_read;
 	char		LE_record_type[2];
 	char		LE_record_length[2];
-	guint16		record_type, record_length;
+	guint16	record_type, record_length;
 	gchar		descriptor[DESCRIPTOR_LEN];
-	guint16		time_low, time_med, time_high, true_size;
-	double		t;
+	guint16	time_low, time_med, time_high, true_size;
+	double	t;
 
 	/* read the record type and length. */
 	errno = WTAP_ERR_CANT_READ;
@@ -236,7 +307,7 @@
 	/* Only Trace Packet Data Records should occur now that we're in
 	 * the middle of reading packets.  If any other record type exists
 	 * after a Trace Packet Data Record, mark it as an error. */
-	if (record_type != REC_TRACE_PACKET_DATA) {
+	if (record_type != RT_PacketData) {
 		g_message("lanalyzer: record type %u seen after trace summary record",
 		    record_type);
 		*err = WTAP_ERR_BAD_RECORD;
@@ -293,8 +364,442 @@
 	return TRUE;
 }
 
-static void
-lanalyzer_close(wtap *wth)
+/*---------------------------------------------------
+ *
+ *---------------------------------------------------*/
+static void lanalyzer_close(wtap *wth)
 {
 	g_free(wth->capture.lanalyzer);
 }
+
+/*---------------------------------------------------
+ * Returns 0 or error
+ * Write one block with error control
+ *---------------------------------------------------*/
+static int swrite(const void* what, guint size, FILE *hd)
+{
+	size_t nwritten;
+	
+      nwritten = fwrite(what, 1, size, hd);
+	if (nwritten != size) {
+		if (nwritten == 0 && ferror(hd))
+			return errno;
+		else
+			return WTAP_ERR_SHORT_WRITE;
+            }
+      return 0; /* ok */
+}
+
+/*---------------------------------------------------
+ * Returns 0 or error
+ * Write one block with error control
+ *---------------------------------------------------*/
+static int s0write(guint cnt, FILE *hd)
+{
+      static gint8 z64[64];
+	size_t nwritten;
+      size_t snack;
+
+	while (cnt) {
+            snack = cnt > 64 ? 64 : cnt;
+            nwritten = fwrite(z64, 1, snack, hd);
+	      if (nwritten != snack) {
+		      if (nwritten == 0 && ferror(hd))
+			      return errno;
+		      else
+			      return WTAP_ERR_SHORT_WRITE;
+                  }
+            cnt -= snack;
+            }
+      return 0; /* ok */
+}
+
+/*---------------------------------------------------
+ * Returns 0 or error
+ * Write one block with error control
+ *---------------------------------------------------*/
+static int s8write(const guint8 s8, FILE *hd)
+{
+	size_t nwritten;
+	
+      nwritten = fwrite(&s8, 1, 1, hd);
+	if (nwritten != 1) {
+		if (nwritten == 0 && ferror(hd))
+			return errno;
+		else
+			return WTAP_ERR_SHORT_WRITE;
+            }
+      return 0; /* ok */
+}
+/*---------------------------------------------------
+ * Returns 0 or error
+ * Write one block with error control
+ *---------------------------------------------------*/
+static int s16write(const guint16 s16, FILE *hd)
+{
+	size_t nwritten;
+	
+      nwritten = fwrite(&s16, 1, 2, hd);
+	if (nwritten != 2) {
+		if (nwritten == 0 && ferror(hd))
+			return errno;
+		else
+			return WTAP_ERR_SHORT_WRITE;
+            }
+      return 0; /* ok */
+}
+/*---------------------------------------------------
+ * Returns 0 or error
+ * Write one block with error control
+ *---------------------------------------------------*/
+static int s32write(const guint32 s32, FILE *hd)
+{
+	size_t nwritten;
+	
+      nwritten = fwrite(&s32, 1, 4, hd);
+	if (nwritten != 4) {
+		if (nwritten == 0 && ferror(hd))
+			return errno;
+		else
+			return WTAP_ERR_SHORT_WRITE;
+            }
+      return 0; /* ok */
+}
+/*---------------------------------------------------
+ *
+ * calculates C.c = A.a - B.b
+ *---------------------------------------------------*/
+static void my_timersub(const struct timeval *a,
+                        const struct timeval *b,
+                              struct timeval *c)
+{
+      gint32 usec = a->tv_usec;
+
+      c->tv_sec = a->tv_sec - b->tv_sec;
+      if (b->tv_usec > usec) {
+           c->tv_sec--;
+           usec += 1000000;
+           }
+      c->tv_usec = usec - b->tv_usec;
+}
+/*---------------------------------------------------
+ * Write a record for a packet to a dump file.
+ * Returns TRUE on success, FALSE on failure.
+ *---------------------------------------------------*/
+static gboolean lanalyzer_dump(wtap_dumper *wdh,
+	const struct wtap_pkthdr *phdr,
+	const union wtap_pseudo_header *pseudo_header _U_,
+	const u_char *pd, int *err)
+{
+      double x;
+      int    i;
+      int    len;
+
+             LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->dump.opaque);
+      struct timeval td;
+      int    thisSize = phdr->caplen + LA_PacketRecordSize + LA_RecordHeaderSize;
+
+      if (wdh->bytes_dumped + thisSize > LA_ProFileLimit) {
+            /* printf(" LA_ProFileLimit reached\n");     */
+            *err = EFBIG;
+            return FALSE; /* and don't forget the header */
+            }
+
+      len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0);
+
+      *err = s16write(htoles(0x1005), wdh->fh);
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(len), wdh->fh);
+      if (*err)
+            return FALSE;
+
+
+      if (!itmp->init) {
+            /* collect some information for the
+             * finally written header
+             */
+            itmp->start   = phdr->ts;
+            itmp->pkts    = 0;
+            itmp->init    = TRUE;
+            itmp->encap   = wdh->encap;
+            itmp->lastlen = 0;
+            }
+
+      my_timersub(&(phdr->ts),&(itmp->start),&td);
+
+      x   = (double) td.tv_usec;
+      x  += (double) td.tv_sec * 1000000;
+      x  *= 2;
+
+      *err = s16write(htoles(0x0001), wdh->fh);           /* pr.rx_channels */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(0x0008), wdh->fh);           /* pr.rx_errors   */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(phdr->len + 4), wdh->fh);    /* pr.rx_frm_len  */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(phdr->caplen), wdh->fh);     /* pr.rx_frm_sln  */
+      if (*err)
+            return FALSE;
+
+      for (i = 0; i < 3; i++) {
+            *err = s16write(htoles((guint16) x), wdh->fh);/* pr.rx_time[i]  */
+            if (*err)
+                  return FALSE;
+            x /= 0xffff;
+            }
+
+      *err = s32write(htolel(++itmp->pkts), wdh->fh);      /* pr.pktno      */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(itmp->lastlen), wdh->fh);     /* pr.prlen      */
+      if (*err)
+            return FALSE;
+      itmp->lastlen = len;
+
+      *err = s0write(12, wdh->fh);
+      if (*err)
+		return FALSE;
+
+      *err = swrite(pd , phdr->caplen , wdh->fh);
+      if (*err)
+		return FALSE;
+
+      wdh->bytes_dumped += thisSize;
+
+      return TRUE;
+}
+
+/*---------------------------------------------------
+ * Returns 0 if we could write the specified encapsulation type,
+ * an error indication otherwise.
+ *---------------------------------------------------*/
+int lanalyzer_dump_can_write_encap(int encap)
+{
+      /* Per-packet encapsulations aren't supported. */
+      if (encap == WTAP_ENCAP_PER_PACKET)
+                  return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
+
+      if ( encap != WTAP_ENCAP_ETHERNET
+        && encap != WTAP_ENCAP_TOKEN_RING )
+                  return WTAP_ERR_UNSUPPORTED_ENCAP;
+      /*
+       * printf("lanalyzer_dump_can_write_encap(%d)\n",encap);
+       */
+	return 0;
+}
+
+/*---------------------------------------------------
+ * Returns TRUE on success, FALSE on failure; sets "*err" to an
+ * error code on failure
+ *---------------------------------------------------*/
+gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err)
+{
+      int   jump;
+      void  *tmp;
+
+      /* This is a LANalyzer file */
+
+      tmp = g_malloc(sizeof(LA_TmpInfo));
+      if (!tmp) {
+	      *err = errno;
+	      return FALSE;
+            }
+
+      ((LA_TmpInfo*)tmp)->init = FALSE;
+      wdh->dump.opaque         = tmp;
+	wdh->subtype_write       = lanalyzer_dump;
+	wdh->subtype_close       = lanalyzer_dump_close;
+
+      /* Some of the fields in the file header aren't known yet so
+       just skip over it for now.  It will be created after all
+       of the packets have been written. */
+
+      jump = sizeof (LA_HeaderRegularFake)
+           + sizeof (LA_RxChannelNameFake)
+           + sizeof (LA_TxChannelNameFake)
+           + sizeof (LA_RxTemplateNameFake)
+           + sizeof (LA_TxTemplateNameFake)
+           + sizeof (LA_DisplayOptionsFake)
+           + LA_SummaryRecordSize
+           + LA_SubfileSummaryRecordSize
+           + sizeof (LA_CyclicInformationFake)
+           + LA_IndexRecordSize;
+
+      if (fseek(wdh->fh, jump, SEEK_SET) == -1) {
+	      *err = errno;
+	      return FALSE;
+            }
+      wdh->bytes_dumped = jump;
+      return TRUE;
+}
+
+/*---------------------------------------------------
+ *
+ *---------------------------------------------------*/
+static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err)
+{
+      LA_TmpInfo *itmp   = (LA_TmpInfo*)(wdh->dump.opaque);
+      struct tm  *fT     = localtime(&(itmp->start.tv_sec));
+      guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING
+                              ? BOARD_325TR     /* LANalyzer Board Type */
+                              : BOARD_325;      /* LANalyzer Board Type */
+
+      fseek(wdh->fh, 0, SEEK_SET);
+
+      *err = swrite(&LA_HeaderRegularFake,  sizeof LA_HeaderRegularFake, wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = swrite(&LA_RxChannelNameFake , sizeof LA_RxChannelNameFake , wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = swrite(&LA_TxChannelNameFake , sizeof LA_TxChannelNameFake , wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = swrite(&LA_RxTemplateNameFake, sizeof LA_RxTemplateNameFake, wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = swrite(&LA_TxTemplateNameFake, sizeof LA_TxTemplateNameFake, wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = swrite(&LA_DisplayOptionsFake, sizeof LA_DisplayOptionsFake, wdh->fh);
+      if (*err)
+		return FALSE;
+      /*-----------------------------------------------------------------*/
+      *err = s16write(htoles(RT_Summary), wdh->fh);        /* rid */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(SummarySize), wdh->fh);       /* rlen */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mday, wdh->fh);                /* s.datcre.day */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mon+1, wdh->fh);               /* s.datcre.mon */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datcre.year */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mday, wdh->fh);                /* s.datclo.day */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mon+1, wdh->fh);               /* s.datclo.mon */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datclo.year */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_sec, wdh->fh);                 /* s.timeopn.second */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_min, wdh->fh);                 /* s.timeopn.minute */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_hour, wdh->fh);                /* s.timeopn.hour */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mday, wdh->fh);                /* s.timeopn.mday */
+      if (*err)
+            return FALSE;
+      *err = s0write(2, wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = s8write(fT->tm_sec, wdh->fh);                 /* s.timeclo.second */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_min, wdh->fh);                 /* s.timeclo.minute */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_hour, wdh->fh);                /* s.timeclo.hour */
+      if (*err)
+            return FALSE;
+      *err = s8write(fT->tm_mday, wdh->fh);                /* s.timeclo.mday */
+      if (*err)
+            return FALSE;
+      *err = s0write(2, wdh->fh);
+      if (*err)
+		return FALSE;
+      *err = s0write(6, wdh->fh);                          /* EAddr  == 0      */
+      if (*err)
+		return FALSE;
+      *err = s16write(htoles(1), wdh->fh);                 /* s.mxseqno */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(0), wdh->fh);                 /* s.slcoffo */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(1514), wdh->fh);              /* s.mxslc */
+      if (*err)
+            return FALSE;
+      *err = s32write(htolel(itmp->pkts), wdh->fh);        /* s.totpktt */
+      if (*err)
+            return FALSE;
+      *err = s0write(12, wdh->fh);                         /* statrg == 0; ? -1*/
+      if (*err)                                            /* stptrg == 0; ? -1*/
+		return FALSE;                                  /* s.mxpkta[0]=0    */
+      *err = s32write(htolel(itmp->pkts), wdh->fh);        /* sr.s.mxpkta[1]  */
+      if (*err)
+            return FALSE;
+      *err = s0write(34*4, wdh->fh);                       /* s.mxpkta[2-33]=0  */
+      if (*err)
+		return FALSE;
+      *err = s16write(htoles(board_type), wdh->fh);
+      if (*err)
+            return FALSE;
+      *err = s0write(20, wdh->fh);                         /* board_version == 0 */
+      if (*err)
+            return FALSE;
+      /*-----------------------------------------------------------------*/
+      *err = s16write(htoles(RT_SubfileSummary), wdh->fh);    /* ssr.rid */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(LA_SubfileSummaryRecordSize-4), wdh->fh);    /* ssr.rlen */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(1), wdh->fh);                    /* ssr.seqno */
+      if (*err)
+            return FALSE;
+      *err = s32write(htolel(itmp->pkts), wdh->fh);           /* ssr.totpkts */
+      if (*err)
+            return FALSE;
+      /*-----------------------------------------------------------------*/
+      *err = swrite(&LA_CyclicInformationFake, sizeof LA_CyclicInformationFake, wdh->fh);
+      if (*err)
+		return FALSE;
+      /*-----------------------------------------------------------------*/
+      *err = s16write(htoles(RT_Index), wdh->fh);             /* rid */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(LA_IndexRecordSize -4), wdh->fh);/* rlen */
+      if (*err)
+            return FALSE;
+      *err = s16write(htoles(LA_IndexSize), wdh->fh);         /* idxsp */
+      if (*err)
+            return FALSE;
+      *err = s0write(LA_IndexRecordSize - 6, wdh->fh);
+      if (*err)
+		return FALSE;
+
+	return TRUE;
+}
+
+/*---------------------------------------------------
+ * Finish writing to a dump file.
+ * Returns TRUE on success, FALSE on failure.
+ *---------------------------------------------------*/
+static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err)
+{
+      if (wdh->dump.opaque) {
+            lanalyzer_dump_header(wdh,err);
+            g_free(wdh->dump.opaque);
+            wdh->dump.opaque = 0;
+            }
+      return *err ? FALSE : TRUE;
+}
+
+
+
Index: wiretap/lanalyzer.h
===================================================================
RCS file: /cvsroot/ethereal/wiretap/lanalyzer.h,v
retrieving revision 1.5
diff -u -r1.5 lanalyzer.h
--- lanalyzer.h	2001/11/13 23:55:43	1.5
+++ lanalyzer.h	2002/06/27 15:20:09
@@ -4,17 +4,17 @@
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxx>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -23,7 +23,134 @@
 
 #ifndef __LANALYZER_H__
 #define __LANALYZER_H__
+
+/*    Record type codes:                */
+
+#define     RT_HeaderRegular       0x1001
+#define     RT_HeaderCyclic        0x1007
+#define     RT_RxChannelName       0x1006
+#define     RT_TxChannelName       0x100b
+#define     RT_FilterName          0x1032
+#define     RT_RxTemplateName      0x1035
+#define     RT_TxTemplateName      0x1036
+#define     RT_DisplayOptions      0x100a
+#define     RT_Summary             0x1002
+#define     RT_SubfileSummary      0x1003
+#define     RT_CyclicInformation   0x1009
+#define     RT_Index               0x1004
+#define     RT_PacketData          0x1005
+
+#define     LA_ProFileLimit       (1024 * 1024 * 32)
+
+typedef guint8  Eadr[6];
+typedef guint16 TimeStamp[3];  /* 0.5 microseconds since start of trace */
+
+/* out of order #pragma pack(2) */
+
+typedef struct {
+      guint8      day;
+      guint8      mon;
+      gint16      year;
+      } Date;
+
+typedef struct {
+      guint8      second;
+      guint8      minute;
+      guint8      hour;
+      guint8      day;
+      gint16      reserved;
+      } Time;
+
+typedef struct {
+      guint16     rx_channels;
+      guint16     rx_errors;
+      gint16      rx_frm_len;
+      gint16      rx_frm_sln;
+      TimeStamp   rx_time;
+      guint32     pktno;
+      gint16      prvlen;
+      gint16      offset;
+      gint16      tx_errs;
+      gint16      rx_filters;
+      gint8       unused[2];
+      gint16      hwcolls;
+      gint16      hwcollschans;
+      /*          Packetdata ....; */
+      } LA_PacketRecord;
+
+#define LA_PacketRecordSize 32
+
+typedef struct {
+      Date        datcre;
+      Date        datclo;
+      Time        timeopn;
+      Time        timeclo;
+      Eadr        statadr;
+      gint16      mxseqno;
+      gint16      slcoff;
+      gint16      mxslc;
+      gint32      totpktt;
+      gint32      statrg;
+      gint32      stptrg;
+      gint32      mxpkta[36];
+      gint16      board_type;
+      gint16      board_version;
+      gint8       reserved[18];
+      } Summary;
+
+#define SummarySize (18+22+(4*36)+6+6+6+4+4)
+
+
+typedef struct {
+      gint16      rid;
+      gint16      rlen;
+      Summary     s;
+      } LA_SummaryRecord;
+
+#define LA_SummaryRecordSize (SummarySize + 4)
+
+
+typedef struct {
+      gint16      rid;
+      gint16      rlen;
+      gint16      seqno;
+      gint32      totpktf;
+      } LA_SubfileSummaryRecord;
+
+#define LA_SubfileSummaryRecordSize 10
+
+
+#define LA_IndexSize 500
+
+typedef struct {
+      gint16      rid;
+      gint16      rlen;
+      gint16      idxsp;                    /* = LA_IndexSize */
+      gint16      idxct;
+      gint8       idxgranu;
+      gint8       idxvd;
+      gint32      trcidx[LA_IndexSize + 2]; /* +2 undocumented but used by La 2.2 */
+      } LA_IndexRecord;
+
+#define LA_IndexRecordSize (10 + 4 * (LA_IndexSize + 2))
+
+typedef struct {
+      gint16      rid;
+      gint16      rlen;
+      } LA_RecordHeader;
+
+#define LA_RecordHeaderSize 4
+
+typedef struct {
+      gboolean        init;
+      struct timeval  start;
+      guint32         pkts;
+      int             encap;
+      int             lastlen;
+      } LA_TmpInfo;
 
-int lanalyzer_open(wtap *wth, int *err);
+int         lanalyzer_open(wtap *wth, int *err);
+gboolean    lanalyzer_dump_open(wtap_dumper *wdh, int *err);
+int         lanalyzer_dump_can_write_encap(int encap);
 
 #endif
Index: wiretap/snoop.c
===================================================================
RCS file: /cvsroot/ethereal/wiretap/snoop.c,v
retrieving revision 1.52
diff -u -r1.52 snoop.c
--- snoop.c	2002/06/07 07:27:35	1.52
+++ snoop.c	2002/06/27 15:20:09
@@ -4,17 +4,17 @@
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxx>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -78,7 +78,7 @@
 
 /*
  * See
- * 
+ *
  *	http://www.opengroup.org/onlinepubs/9638599/apdxf.htm
  *
  * for the "dlpi.h" header file specified by The Open Group, which lists
Index: wiretap/visual.c
===================================================================
RCS file: /cvsroot/ethereal/wiretap/visual.c,v
retrieving revision 1.8
diff -u -r1.8 visual.c
--- visual.c	2002/06/07 07:27:35	1.8
+++ visual.c	2002/06/27 15:20:09
@@ -6,17 +6,17 @@
  *
  * Wiretap Library
  * Copyright (c) 1998 by Gilbert Ramirez <gram@xxxxxxxxxxxxxxx>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
  * of the License, or (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -228,7 +228,7 @@
     /* Check for the end of the packet data.  Note that a check for file EOF
        will not work because there are index values stored after the last
        packet's data. */
-    if (visual->current_pkt > visual->num_pkts) 
+    if (visual->current_pkt > visual->num_pkts)
     {
         *err = 0;   /* it's just an EOF, not an error */
         return FALSE;
@@ -238,10 +238,10 @@
     /* Read the packet header. */
     errno = WTAP_ERR_CANT_READ;
     bytes_read = file_read(&vpkt_hdr, 1, phdr_size, wth->fh);
-    if (bytes_read != phdr_size) 
+    if (bytes_read != phdr_size)
     {
         *err = file_error(wth->fh);
-        if (*err == 0 && bytes_read != 0) 
+        if (*err == 0 && bytes_read != 0)
         {
             *err = WTAP_ERR_SHORT_READ;
         }
@@ -251,7 +251,7 @@
 
     /* Read the packet data. */
     packet_size = pletohs(&vpkt_hdr.incl_len);
-    if (packet_size > WTAP_MAX_PACKET_SIZE) 
+    if (packet_size > WTAP_MAX_PACKET_SIZE)
     {
         /* Probably a corrupt capture file; don't blow up trying
           to allocate space for an immensely-large packet. */
@@ -266,7 +266,7 @@
     bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
             packet_size, wth->fh);
 
-    if (bytes_read != (int) packet_size) 
+    if (bytes_read != (int) packet_size)
     {
         *err = file_error(wth->fh);
         if (*err == 0)
@@ -329,7 +329,7 @@
 /* Read packet data for random access.
    This gets the packet data and rebuilds the pseudo header so that
    the direction flag works. */
-static gboolean visual_seek_read (wtap *wth, long seek_off, 
+static gboolean visual_seek_read (wtap *wth, long seek_off,
     union wtap_pseudo_header *pseudo_header, guint8 *pd, int len, int *err)
 {
     struct visual_pkt_hdr vpkt_hdr;
@@ -383,7 +383,7 @@
 }
 
 
-/* Check for media types that may be written in Visual file format. 
+/* Check for media types that may be written in Visual file format.
    Returns 0 if the specified encapsulation type is supported,
    an error indication otherwise. */
 int visual_dump_can_write_encap(int encap)
@@ -465,7 +465,7 @@
        file header.  Each packet has a capture time (in msec) relative
        to the file start time.  Use the time of the first packet as the
        file start time. */
-    if (visual->index_table_index == 0) 
+    if (visual->index_table_index == 0)
     {
         /* This is the first packet.  Save its start time as the file time. */
         visual->start_time = phdr->ts.tv_sec;
@@ -474,7 +474,7 @@
         visual->index_table = g_malloc(1024 * sizeof *visual->index_table);
         visual->index_table_size = 1024;
     }
-    
+
     /* Calculate milliseconds since capture start. */
     delta_msec = phdr->ts.tv_usec / 1000;
     delta_msec += (phdr->ts.tv_sec - visual->start_time) * 1000;
@@ -488,20 +488,20 @@
     switch (wdh->encap)
     {
     case WTAP_ENCAP_ETHERNET:   /* Ethernet */
-        vpkt_hdr.encap_hint = 2;    
+        vpkt_hdr.encap_hint = 2;
         break;
     case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
-        vpkt_hdr.encap_hint = 3;    
+        vpkt_hdr.encap_hint = 3;
         break;
     case WTAP_ENCAP_PPP:        /* PPP */
     case WTAP_ENCAP_PPP_WITH_PHDR:
-        vpkt_hdr.encap_hint = 14;   
+        vpkt_hdr.encap_hint = 14;
         break;
     case WTAP_ENCAP_CHDLC:      /* HDLC Router */
-        vpkt_hdr.encap_hint = 13;   
+        vpkt_hdr.encap_hint = 13;
         break;
     case WTAP_ENCAP_FRELAY:     /* Frame Relay Auto-detect */
-        vpkt_hdr.encap_hint = 12;   
+        vpkt_hdr.encap_hint = 12;
         break;
     case WTAP_ENCAP_LAPB:       /* Unknown */
     default:
@@ -530,7 +530,7 @@
 
     /* Write the packet header. */
     nwritten = fwrite(&vpkt_hdr, 1, hdr_size, wdh->fh);
-    if (nwritten != hdr_size) 
+    if (nwritten != hdr_size)
     {
         if (nwritten == 0 && ferror(wdh->fh))
             *err = errno;
@@ -541,7 +541,7 @@
 
     /* Write the packet data */
     nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
-    if (nwritten != phdr->caplen) 
+    if (nwritten != phdr->caplen)
     {
         if (nwritten == 0 && ferror(wdh->fh))
             *err = errno;
@@ -551,7 +551,7 @@
     }
 
     /* Store the frame offset in the index table. */
-    if (visual->index_table_index >= visual->index_table_size) 
+    if (visual->index_table_index >= visual->index_table_size)
     {
         /* End of table reached.  Reallocate with a larger size */
         visual->index_table_size *= 2;
@@ -590,7 +590,7 @@
         /* Write the index table to the file. */
         n_to_write = visual->index_table_index * sizeof *visual->index_table;
         nwritten = fwrite(visual->index_table, 1, n_to_write, wdh->fh);
-        if (nwritten != n_to_write) 
+        if (nwritten != n_to_write)
         {
             if (err != NULL)
             {
@@ -645,7 +645,7 @@
 
     /* Write the file header following the magic bytes. */
     nwritten = fwrite(&vfile_hdr, 1, sizeof vfile_hdr, wdh->fh);
-    if (nwritten != sizeof vfile_hdr) 
+    if (nwritten != sizeof vfile_hdr)
     {
         if (err != NULL)
         {

Attachment: lanalyzer3.patch.zip
Description: Binary data