Restore another include to try to fix solaris build
[metze/wireshark/wip.git] / wiretap / lanalyzer.c
1 /* lanalyzer.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22 #include <stdlib.h>
23 #include <errno.h>
24 #include "wtap-int.h"
25 #include "file_wrappers.h"
26 #include <wsutil/buffer.h>
27 #include "lanalyzer.h"
28
29 /* The LANalyzer format is documented (at least in part) in Novell document
30    TID022037, which can be found at, among other places:
31
32         http://www.windowsecurity.com/whitepapers/Description_of_the_LANalysers_output_file.html
33  */
34
35 /*    Record header format */
36
37 typedef struct {
38         guint8  record_type[2];
39         guint8  record_length[2];
40 } LA_RecordHeader;
41
42 #define LA_RecordHeaderSize 4
43
44 /*    Record type codes:                */
45
46 #define     RT_HeaderRegular       0x1001
47 #define     RT_HeaderCyclic        0x1007
48 #define     RT_RxChannelName       0x1006
49 #define     RT_TxChannelName       0x100b
50 #define     RT_FilterName          0x1032
51 #define     RT_RxTemplateName      0x1035
52 #define     RT_TxTemplateName      0x1036
53 #define     RT_DisplayOptions      0x100a
54 #define     RT_Summary             0x1002
55 #define     RT_SubfileSummary      0x1003
56 #define     RT_CyclicInformation   0x1009
57 #define     RT_Index               0x1004
58 #define     RT_PacketData          0x1005
59
60 #define     LA_ProFileLimit       (1024 * 1024 * 32)
61
62 typedef guint8  Eadr[6];
63 typedef guint16 TimeStamp[3];  /* 0.5 microseconds since start of trace */
64
65 /*
66  * These records have only 2-byte alignment for 4-byte quantities,
67  * so the structures aren't necessarily valid; they're kept as comments
68  * for reference purposes.
69  */
70
71 /*
72  * typedef struct {
73  *       guint8      day;
74  *       guint8      mon;
75  *       gint16      year;
76  *       } Date;
77  */
78
79 /*
80  * typedef struct {
81  *       guint8      second;
82  *       guint8      minute;
83  *       guint8      hour;
84  *       guint8      day;
85  *       gint16      reserved;
86  *       } Time;
87  */
88
89 /*
90  * RT_Summary:
91  *
92  * typedef struct {
93  *       Date        datcre;
94  *       Date        datclo;
95  *       Time        timeopn;
96  *       Time        timeclo;
97  *       Eadr        statadr;
98  *       gint16      mxseqno;
99  *       gint16      slcoff;
100  *       gint16      mxslc;
101  *       gint32      totpktt;
102  *       gint32      statrg;
103  *       gint32      stptrg;
104  *       gint32      mxpkta[36];
105  *       gint16      board_type;
106  *       gint16      board_version;
107  *       gint8       reserved[18];
108  *       } Summary;
109  */
110
111 #define SummarySize (18+22+(4*36)+6+6+6+4+4)
112
113 /*
114  * typedef struct {
115  *       gint16      rid;
116  *       gint16      rlen;
117  *       Summary     s;
118  *       } LA_SummaryRecord;
119  */
120
121 #define LA_SummaryRecordSize (SummarySize + 4)
122
123 /* LANalyzer board types (which indicate the type of network on which
124    the capture was done). */
125 #define BOARD_325               226     /* LANalyzer 325 (Ethernet) */
126 #define BOARD_325TR             227     /* LANalyzer 325TR (Token-ring) */
127
128
129 /*
130  * typedef struct {
131  *       gint16      rid;
132  *       gint16      rlen;
133  *       gint16      seqno;
134  *       gint32      totpktf;
135  *       } LA_SubfileSummaryRecord;
136  */
137
138 #define LA_SubfileSummaryRecordSize 10
139
140
141 #define LA_IndexSize 500
142
143 /*
144  * typedef struct {
145  *       gint16      rid;
146  *       gint16      rlen;
147  *       gint16      idxsp;                    = LA_IndexSize
148  *       gint16      idxct;
149  *       gint8       idxgranu;
150  *       gint8       idxvd;
151  *       gint32      trcidx[LA_IndexSize + 2]; +2 undocumented but used by La 2.2
152  *       } LA_IndexRecord;
153  */
154
155 #define LA_IndexRecordSize (10 + 4 * (LA_IndexSize + 2))
156
157
158 /*
159  * typedef struct {
160  *       guint16     rx_channels;
161  *       guint16     rx_errors;
162  *       gint16      rx_frm_len;
163  *       gint16      rx_frm_sln;
164  *       TimeStamp   rx_time;
165  *       guint32     pktno;
166  *       gint16      prvlen;
167  *       gint16      offset;
168  *       gint16      tx_errs;
169  *       gint16      rx_filters;
170  *       gint8       unused[2];
171  *       gint16      hwcolls;
172  *       gint16      hwcollschans;
173  *       Packetdata ....;
174  *       } LA_PacketRecord;
175  */
176
177 #define LA_PacketRecordSize 32
178
179 typedef struct {
180       gboolean        init;
181       struct timeval  start;
182       guint32         pkts;
183       int             encap;
184       int             lastlen;
185       } LA_TmpInfo;
186
187 static const guint8 LA_HeaderRegularFake[] = {
188 0x01,0x10,0x4c,0x00,0x01,0x05,0x54,0x72,0x61,0x63,0x65,0x20,0x44,0x69,0x73,0x70,
189 0x6c,0x61,0x79,0x20,0x54,0x72,0x61,0x63,0x65,0x20,0x46,0x69,0x6c,0x65,0x00,0x00,
190 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
191 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
192 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
193       };
194
195 static const guint8 LA_RxChannelNameFake[] = {
196 0x06,0x10,0x80,0x00,0x43,0x68,0x61,0x6e ,0x6e,0x65,0x6c,0x31,0x00,0x43,0x68,0x61,
197 0x6e,0x6e,0x65,0x6c,0x32,0x00,0x43,0x68 ,0x61,0x6e,0x6e,0x65,0x6c,0x33,0x00,0x43,
198 0x68,0x61,0x6e,0x6e,0x65,0x6c,0x34,0x00 ,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x35,
199 0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c ,0x36,0x00,0x43,0x68,0x61,0x6e,0x6e,0x65,
200 0x6c,0x37,0x00,0x43,0x68,0x61,0x6e,0x6e ,0x65,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,
201 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
202 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
203 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
204 0x00,0x00,0x00,0x00
205       };
206
207 static const guint8 LA_TxChannelNameFake[] = {
208                     0x0b,0x10,0x36,0x00 ,0x54,0x72,0x61,0x6e,0x73,0x31,0x00,0x00,
209 0x00,0x54,0x72,0x61,0x6e,0x73,0x32,0x00 ,0x00,0x00,0x54,0x72,0x61,0x6e,0x73,0x33,
210 0x00,0x00,0x00,0x54,0x72,0x61,0x6e,0x73 ,0x34,0x00,0x00,0x00,0x54,0x72,0x61,0x6e,
211 0x73,0x35,0x00,0x00,0x00,0x54,0x72,0x61 ,0x6e,0x73,0x36,0x00,0x00,0x00
212       };
213
214 static const guint8 LA_RxTemplateNameFake[] = {
215                                                                        0x35,0x10,
216 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
217 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
218 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
219 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
220 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
221 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
223 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
225 0x00,0x00
226       };
227
228 static const guint8 LA_TxTemplateNameFake[] = {
229           0x36,0x10,0x36,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
231 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00
233       };
234
235 static const guint8 LA_DisplayOptionsFake[] = {
236                                                              0x0a,0x10,0x0a,0x01,
237 0x00,0x00,0x01,0x00,0x01,0x02,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
238 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
239 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
240 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
241 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
242 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
243 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
244 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
245 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
246 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
247 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
248 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
249 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
253 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00
254       };
255
256 static const guint8 LA_CyclicInformationFake[] = {
257                                                    0x09,0x10,0x1a,0x00,0x00,0x00,
258 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
259 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
260       };
261
262 static const guint8 z64[64] = {
263 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
264 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
265 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
266 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
267       };
268
269 typedef struct {
270         time_t  start;
271 } lanalyzer_t;
272
273 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
274     gint64 *data_offset);
275 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
276     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
277 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err);
278
279 wtap_open_return_val lanalyzer_open(wtap *wth, int *err, gchar **err_info)
280 {
281         LA_RecordHeader rec_header;
282         char header_fixed[2];
283         char *comment;
284         char summary[210];
285         guint16 board_type, mxslc;
286         guint16 record_type, record_length;
287         guint8 cr_day, cr_month;
288         guint16 cr_year;
289         struct tm tm;
290         lanalyzer_t *lanalyzer;
291
292         if (!wtap_read_bytes(wth->fh, &rec_header, LA_RecordHeaderSize,
293             err, err_info)) {
294                 if (*err != WTAP_ERR_SHORT_READ)
295                         return WTAP_OPEN_ERROR;
296                 return WTAP_OPEN_NOT_MINE;
297         }
298         record_type = pletoh16(rec_header.record_type);
299         record_length = pletoh16(rec_header.record_length); /* make sure to do this for while() loop */
300
301         if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) {
302                 return WTAP_OPEN_NOT_MINE;
303         }
304
305         /* Read the major and minor version numbers */
306         if (record_length < 2) {
307                 /*
308                  * Not enough room for the major and minor version numbers.
309                  * Just treat that as a "not a LANalyzer file" indication.
310                  */
311                 return WTAP_OPEN_NOT_MINE;
312         }
313         if (!wtap_read_bytes(wth->fh, &header_fixed, sizeof header_fixed,
314             err, err_info)) {
315                 if (*err != WTAP_ERR_SHORT_READ)
316                         return WTAP_OPEN_ERROR;
317                 return WTAP_OPEN_NOT_MINE;
318         }
319         record_length -= sizeof header_fixed;
320
321         if (record_length != 0) {
322                 /* Read the rest of the record as a comment. */
323                 comment = (char *)g_malloc(record_length + 1);
324                 if (!wtap_read_bytes(wth->fh, comment, record_length,
325                     err, err_info)) {
326                         if (*err != WTAP_ERR_SHORT_READ)
327                                 return WTAP_OPEN_ERROR;
328                         return WTAP_OPEN_NOT_MINE;
329                 }
330                 comment[record_length] = '\0';
331                 wth->shb_hdr.opt_comment = comment;
332         }
333
334         /* If we made it this far, then the file is a LANAlyzer file.
335          * Let's get some info from it. Note that we get wth->snapshot_length
336          * from a record later in the file. */
337         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_LANALYZER;
338         lanalyzer = (lanalyzer_t *)g_malloc(sizeof(lanalyzer_t));
339         wth->priv = (void *)lanalyzer;
340         wth->subtype_read = lanalyzer_read;
341         wth->subtype_seek_read = lanalyzer_seek_read;
342         wth->snapshot_length = 0;
343         wth->file_tsprec = WTAP_TSPREC_NSEC;
344
345         /* Read records until we find the start of packets */
346         while (1) {
347                 if (!wtap_read_bytes_or_eof(wth->fh, &rec_header,
348                     LA_RecordHeaderSize, err, err_info)) {
349                         if (*err == 0) {
350                                 /*
351                                  * End of file and no packets;
352                                  * accept this file.
353                                  */
354                                 return WTAP_OPEN_MINE;
355                         }
356                         return WTAP_OPEN_ERROR;
357                 }
358
359                 record_type = pletoh16(rec_header.record_type);
360                 record_length = pletoh16(rec_header.record_length);
361
362                 /*g_message("Record 0x%04X Length %d", record_type, record_length);*/
363                 switch (record_type) {
364                         /* Trace Summary Record */
365                         case RT_Summary:
366                                 if (!wtap_read_bytes(wth->fh, summary,
367                                     sizeof summary, err, err_info))
368                                         return WTAP_OPEN_ERROR;
369
370                                 /* Assume that the date of the creation of the trace file
371                                  * is the same date of the trace. Lanalyzer doesn't
372                                  * store the creation date/time of the trace, but only of
373                                  * the file. Unless you traced at 11:55 PM and saved at 00:05
374                                  * AM, the assumption that trace.date == file.date is true.
375                                  */
376                                 cr_day = summary[0];
377                                 cr_month = summary[1];
378                                 cr_year = pletoh16(&summary[2]);
379                                 /*g_message("Day %d Month %d Year %d (%04X)", cr_day, cr_month,
380                                                 cr_year, cr_year);*/
381
382                                 /* Get capture start time. I learned how to do
383                                  * this from Guy's code in ngsniffer.c
384                                  */
385                                 tm.tm_year = cr_year - 1900;
386                                 tm.tm_mon = cr_month - 1;
387                                 tm.tm_mday = cr_day;
388                                 tm.tm_hour = 0;
389                                 tm.tm_min = 0;
390                                 tm.tm_sec = 0;
391                                 tm.tm_isdst = -1;
392                                 lanalyzer->start = mktime(&tm);
393                                 /*g_message("Day %d Month %d Year %d", tm.tm_mday,
394                                                 tm.tm_mon, tm.tm_year);*/
395                                 mxslc = pletoh16(&summary[30]);
396                                 wth->snapshot_length = mxslc;
397
398                                 board_type = pletoh16(&summary[188]);
399                                 switch (board_type) {
400                                         case BOARD_325:
401                                                 wth->file_encap = WTAP_ENCAP_ETHERNET;
402                                                 break;
403                                         case BOARD_325TR:
404                                                 wth->file_encap = WTAP_ENCAP_TOKEN_RING;
405                                                 break;
406                                         default:
407                                                 *err = WTAP_ERR_UNSUPPORTED;
408                                                 *err_info = g_strdup_printf("lanalyzer: board type %u unknown",
409                                                     board_type);
410                                                 return WTAP_OPEN_ERROR;
411                                 }
412                                 break;
413
414                         /* Trace Packet Data Record */
415                         case RT_PacketData:
416                                 /* Go back header number of bytes so that lanalyzer_read
417                                  * can read this header */
418                                 if (file_seek(wth->fh, -LA_RecordHeaderSize, SEEK_CUR, err) == -1) {
419                                         return WTAP_OPEN_ERROR;
420                                 }
421                                 return WTAP_OPEN_MINE;
422
423                         default:
424                                 if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) {
425                                         return WTAP_OPEN_ERROR;
426                                 }
427                                 break;
428                 }
429         }
430 }
431
432 #define DESCRIPTOR_LEN  32
433
434 static gboolean lanalyzer_read_trace_record(wtap *wth, FILE_T fh,
435     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
436 {
437         char            LE_record_type[2];
438         char            LE_record_length[2];
439         guint16         record_type, record_length;
440         int             record_data_size;
441         int             packet_size;
442         gchar           descriptor[DESCRIPTOR_LEN];
443         lanalyzer_t     *lanalyzer;
444         guint16         time_low, time_med, time_high, true_size;
445         guint64         t;
446         time_t          tsecs;
447
448         /* read the record type and length. */
449         if (!wtap_read_bytes_or_eof(fh, LE_record_type, 2, err, err_info))
450                 return FALSE;
451         if (!wtap_read_bytes(fh, LE_record_length, 2, err, err_info))
452                 return FALSE;
453
454         record_type = pletoh16(LE_record_type);
455         record_length = pletoh16(LE_record_length);
456
457         /* Only Trace Packet Data Records should occur now that we're in
458          * the middle of reading packets.  If any other record type exists
459          * after a Trace Packet Data Record, mark it as an error. */
460         if (record_type != RT_PacketData) {
461                 *err = WTAP_ERR_BAD_FILE;
462                 *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record",
463                     record_type);
464                 return FALSE;
465         }
466
467         if (record_length < DESCRIPTOR_LEN) {
468                 /*
469                  * Uh-oh, the record isn't big enough to even have a
470                  * descriptor.
471                  */
472                 *err = WTAP_ERR_BAD_FILE;
473                 *err_info = g_strdup_printf("lanalyzer: file has a %u-byte record, too small to have even a packet descriptor",
474                     record_length);
475                 return FALSE;
476         }
477         record_data_size = record_length - DESCRIPTOR_LEN;
478
479         /* Read the descriptor data */
480         if (!wtap_read_bytes(fh, descriptor, DESCRIPTOR_LEN, err, err_info))
481                 return FALSE;
482
483         true_size = pletoh16(&descriptor[4]);
484         packet_size = pletoh16(&descriptor[6]);
485
486         /*
487          * OK, is the frame data size greater than than what's left of the
488          * record?
489          */
490         if (packet_size > record_data_size) {
491                 /*
492                  * Yes - treat this as an error.
493                  */
494                 *err = WTAP_ERR_BAD_FILE;
495                 *err_info = g_strdup("lanalyzer: Record length is less than packet size");
496                 return FALSE;
497         }
498
499         phdr->rec_type = REC_TYPE_PACKET;
500         phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
501
502         time_low = pletoh16(&descriptor[8]);
503         time_med = pletoh16(&descriptor[10]);
504         time_high = pletoh16(&descriptor[12]);
505         t = (((guint64)time_low) << 0) + (((guint64)time_med) << 16) +
506             (((guint64)time_high) << 32);
507         tsecs = (time_t) (t/2000000);
508         lanalyzer = (lanalyzer_t *)wth->priv;
509         phdr->ts.secs = tsecs + lanalyzer->start;
510         phdr->ts.nsecs = ((guint32) (t - tsecs*2000000)) * 500;
511
512         if (true_size - 4 >= packet_size) {
513                 /*
514                  * It appears that the "true size" includes the FCS;
515                  * make it reflect the non-FCS size (the "packet size"
516                  * appears never to include the FCS, even if no slicing
517                  * is done).
518                  */
519                 true_size -= 4;
520         }
521         phdr->len = true_size;
522         phdr->caplen = packet_size;
523
524         switch (wth->file_encap) {
525
526         case WTAP_ENCAP_ETHERNET:
527                 /* We assume there's no FCS in this frame. */
528                 phdr->pseudo_header.eth.fcs_len = 0;
529                 break;
530         }
531
532         /* Read the packet data */
533         return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
534 }
535
536 /* Read the next packet */
537 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
538     gint64 *data_offset)
539 {
540         *data_offset = file_tell(wth->fh);
541
542         /* Read the record  */
543         return lanalyzer_read_trace_record(wth, wth->fh, &wth->phdr,
544             wth->frame_buffer, err, err_info);
545 }
546
547 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
548     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
549 {
550         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
551                 return FALSE;
552
553         /* Read the record  */
554         if (!lanalyzer_read_trace_record(wth, wth->random_fh, phdr, buf,
555             err, err_info)) {
556                 if (*err == 0)
557                         *err = WTAP_ERR_SHORT_READ;
558                 return FALSE;
559         }
560         return TRUE;
561 }
562
563 /*---------------------------------------------------
564  * Returns TRUE on success, FALSE on error
565  * Write "cnt" bytes of zero with error control
566  *---------------------------------------------------*/
567 static gboolean s0write(wtap_dumper *wdh, size_t cnt, int *err)
568 {
569         size_t snack;
570
571         while (cnt) {
572                 snack = cnt > 64 ? 64 : cnt;
573
574                 if (!wtap_dump_file_write(wdh, z64, snack, err))
575                         return FALSE;
576                 cnt -= snack;
577         }
578         return TRUE; /* ok */
579 }
580
581 /*---------------------------------------------------
582  * Returns TRUE on success, FALSE on error
583  * Write an 8-bit value with error control
584  *---------------------------------------------------*/
585 static gboolean s8write(wtap_dumper *wdh, const guint8 s8, int *err)
586 {
587         return wtap_dump_file_write(wdh, &s8, 1, err);
588 }
589 /*---------------------------------------------------
590  * Returns TRUE on success, FALSE on error
591  * Write a 16-bit value with error control
592  *---------------------------------------------------*/
593 static gboolean s16write(wtap_dumper *wdh, const guint16 s16, int *err)
594 {
595         return wtap_dump_file_write(wdh, &s16, 2, err);
596 }
597 /*---------------------------------------------------
598  * Returns TRUE on success, FALSE on error
599  * Write a 32-bit value with error control
600  *---------------------------------------------------*/
601 static gboolean s32write(wtap_dumper *wdh, const guint32 s32, int *err)
602 {
603         return wtap_dump_file_write(wdh, &s32, 4, err);
604 }
605 /*---------------------------------------------------
606  *
607  * calculates C.c = A.a - B.b
608  *---------------------------------------------------*/
609 static void my_timersub(const struct timeval *a,
610                         const struct timeval *b,
611                               struct timeval *c)
612 {
613       gint32 usec = (gint32)a->tv_usec;
614
615       c->tv_sec = a->tv_sec - b->tv_sec;
616       if (b->tv_usec > usec) {
617            c->tv_sec--;
618            usec += 1000000;
619            }
620       c->tv_usec = usec - b->tv_usec;
621 }
622 /*---------------------------------------------------
623  * Write a record for a packet to a dump file.
624  * Returns TRUE on success, FALSE on failure.
625  *---------------------------------------------------*/
626 static gboolean lanalyzer_dump(wtap_dumper *wdh,
627         const struct wtap_pkthdr *phdr,
628         const guint8 *pd, int *err, gchar **err_info _U_)
629 {
630       double x;
631       int    i;
632       int    len;
633       struct timeval tv;
634
635       LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->priv);
636       struct timeval td;
637       int    thisSize = phdr->caplen + LA_PacketRecordSize + LA_RecordHeaderSize;
638
639       /* We can only write packet records. */
640       if (phdr->rec_type != REC_TYPE_PACKET) {
641             *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
642             return FALSE;
643             }
644
645       if (wdh->bytes_dumped + thisSize > LA_ProFileLimit) {
646             /* printf(" LA_ProFileLimit reached\n");     */
647             *err = EFBIG;
648             return FALSE; /* and don't forget the header */
649             }
650
651       len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0);
652
653       /* len goes into a 16-bit field, so there's a hard limit of 65535. */
654       if (len > 65535) {
655             *err = WTAP_ERR_PACKET_TOO_LARGE;
656             return FALSE;
657             }
658
659       if (!s16write(wdh, GUINT16_TO_LE(0x1005), err))
660             return FALSE;
661       if (!s16write(wdh, GUINT16_TO_LE(len), err))
662             return FALSE;
663
664       tv.tv_sec  = (long int) phdr->ts.secs;
665       tv.tv_usec = phdr->ts.nsecs / 1000;
666
667       if (!itmp->init) {
668             /* collect some information for the
669              * finally written header
670              */
671                     /* XXX - this conversion could probably improved, if the start uses ns */
672             itmp->start   = tv;
673             itmp->pkts    = 0;
674             itmp->init    = TRUE;
675             itmp->encap   = wdh->encap;
676             itmp->lastlen = 0;
677             }
678
679       my_timersub(&(tv),&(itmp->start),&td);
680
681       x   = (double) td.tv_usec;
682       x  += (double) td.tv_sec * 1000000;
683       x  *= 2;
684
685       if (!s16write(wdh, GUINT16_TO_LE(0x0001), err))             /* pr.rx_channels */
686             return FALSE;
687       if (!s16write(wdh, GUINT16_TO_LE(0x0008), err))             /* pr.rx_errors   */
688             return FALSE;
689       if (!s16write(wdh, GUINT16_TO_LE(phdr->len + 4), err))      /* pr.rx_frm_len  */
690             return FALSE;
691       if (!s16write(wdh, GUINT16_TO_LE(phdr->caplen), err))       /* pr.rx_frm_sln  */
692             return FALSE;
693
694       for (i = 0; i < 3; i++) {
695             if (!s16write(wdh, GUINT16_TO_LE((guint16) x), err))  /* pr.rx_time[i]  */
696                   return FALSE;
697             x /= 0xffff;
698       }
699
700       if (!s32write(wdh, GUINT32_TO_LE(++itmp->pkts), err))       /* pr.pktno      */
701             return FALSE;
702       if (!s16write(wdh, GUINT16_TO_LE(itmp->lastlen), err))      /* pr.prlen      */
703             return FALSE;
704       itmp->lastlen = len;
705
706       if (!s0write(wdh, 12, err))
707             return FALSE;
708
709       if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
710             return FALSE;
711
712       wdh->bytes_dumped += thisSize;
713
714       return TRUE;
715 }
716
717 /*---------------------------------------------------
718  * Returns 0 if we could write the specified encapsulation type,
719  * an error indication otherwise.
720  *---------------------------------------------------*/
721 int lanalyzer_dump_can_write_encap(int encap)
722 {
723       /* Per-packet encapsulations aren't supported. */
724       if (encap == WTAP_ENCAP_PER_PACKET)
725                   return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
726
727       if ( encap != WTAP_ENCAP_ETHERNET
728         && encap != WTAP_ENCAP_TOKEN_RING )
729                   return WTAP_ERR_UNWRITABLE_ENCAP;
730       /*
731        * printf("lanalyzer_dump_can_write_encap(%d)\n",encap);
732        */
733       return 0;
734 }
735
736 /*---------------------------------------------------
737  * Returns TRUE on success, FALSE on failure; sets "*err" to an
738  * error code on failure
739  *---------------------------------------------------*/
740 gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err)
741 {
742       int   jump;
743       void  *tmp;
744
745       tmp = g_malloc(sizeof(LA_TmpInfo));
746       if (!tmp) {
747               *err = errno;
748               return FALSE;
749             }
750
751       ((LA_TmpInfo*)tmp)->init = FALSE;
752       wdh->priv          = tmp;
753       wdh->subtype_write = lanalyzer_dump;
754       wdh->subtype_close = lanalyzer_dump_close;
755
756       /* Some of the fields in the file header aren't known yet so
757        just skip over it for now.  It will be created after all
758        of the packets have been written. */
759
760       jump = sizeof (LA_HeaderRegularFake)
761            + sizeof (LA_RxChannelNameFake)
762            + sizeof (LA_TxChannelNameFake)
763            + sizeof (LA_RxTemplateNameFake)
764            + sizeof (LA_TxTemplateNameFake)
765            + sizeof (LA_DisplayOptionsFake)
766            + LA_SummaryRecordSize
767            + LA_SubfileSummaryRecordSize
768            + sizeof (LA_CyclicInformationFake)
769            + LA_IndexRecordSize;
770
771       if (wtap_dump_file_seek(wdh, jump, SEEK_SET, err) == -1)
772               return FALSE;
773
774       wdh->bytes_dumped = jump;
775       return TRUE;
776 }
777
778 /*---------------------------------------------------
779  *
780  *---------------------------------------------------*/
781 static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err)
782 {
783       LA_TmpInfo *itmp   = (LA_TmpInfo*)(wdh->priv);
784       guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING
785                               ? BOARD_325TR     /* LANalyzer Board Type */
786                               : BOARD_325;      /* LANalyzer Board Type */
787       time_t secs;
788       struct tm *fT;
789
790       /* The secs variable is needed to work around 32/64-bit time_t issues.
791          itmp->start is a timeval struct, which declares its tv_sec field
792          (itmp->start.tv_sec) as a long (typically 32 bits). time_t can be 32
793          or 64 bits, depending on the platform. Invoking as follows could
794          pass a pointer to a 32-bit long where a pointer to a 64-bit time_t
795          is expected: localtime((time_t*) &(itmp->start.tv_sec)) */
796       secs = itmp->start.tv_sec;
797       fT = localtime(&secs);
798       if (fT == NULL)
799             return FALSE;
800
801       if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
802             return FALSE;
803
804       if (!wtap_dump_file_write(wdh, &LA_HeaderRegularFake,
805                                 sizeof LA_HeaderRegularFake, err))
806                 return FALSE;
807       if (!wtap_dump_file_write(wdh, &LA_RxChannelNameFake,
808                                 sizeof LA_RxChannelNameFake, err))
809                 return FALSE;
810       if (!wtap_dump_file_write(wdh, &LA_TxChannelNameFake,
811                                 sizeof LA_TxChannelNameFake, err))
812                 return FALSE;
813       if (!wtap_dump_file_write(wdh, &LA_RxTemplateNameFake,
814                                 sizeof LA_RxTemplateNameFake, err))
815                 return FALSE;
816       if (!wtap_dump_file_write(wdh, &LA_TxTemplateNameFake,
817                                 sizeof LA_TxTemplateNameFake, err))
818                 return FALSE;
819       if (!wtap_dump_file_write(wdh, &LA_DisplayOptionsFake,
820                                 sizeof LA_DisplayOptionsFake, err))
821                 return FALSE;
822       /*-----------------------------------------------------------------*/
823       if (!s16write(wdh, GUINT16_TO_LE(RT_Summary), err))         /* rid */
824             return FALSE;
825       if (!s16write(wdh, GUINT16_TO_LE(SummarySize), err))        /* rlen */
826             return FALSE;
827       if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.datcre.day */
828             return FALSE;
829       if (!s8write(wdh, (guint8) (fT->tm_mon+1), err))     /* s.datcre.mon */
830             return FALSE;
831       if (!s16write(wdh, GUINT16_TO_LE(fT->tm_year + 1900), err)) /* s.datcre.year */
832             return FALSE;
833       if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.datclo.day */
834             return FALSE;
835       if (!s8write(wdh, (guint8) (fT->tm_mon+1), err))     /* s.datclo.mon */
836             return FALSE;
837       if (!s16write(wdh, GUINT16_TO_LE(fT->tm_year + 1900), err)) /* s.datclo.year */
838             return FALSE;
839       if (!s8write(wdh, (guint8) fT->tm_sec, err))         /* s.timeopn.second */
840             return FALSE;
841       if (!s8write(wdh, (guint8) fT->tm_min, err))         /* s.timeopn.minute */
842             return FALSE;
843       if (!s8write(wdh, (guint8) fT->tm_hour, err))        /* s.timeopn.hour */
844             return FALSE;
845       if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.timeopn.mday */
846             return FALSE;
847       if (!s0write(wdh, 2, err))
848             return FALSE;
849       if (!s8write(wdh, (guint8) fT->tm_sec, err))         /* s.timeclo.second */
850             return FALSE;
851       if (!s8write(wdh, (guint8) fT->tm_min, err))         /* s.timeclo.minute */
852             return FALSE;
853       if (!s8write(wdh, (guint8) fT->tm_hour, err))        /* s.timeclo.hour */
854             return FALSE;
855       if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.timeclo.mday */
856             return FALSE;
857       if (!s0write(wdh, 2, err))
858             return FALSE;
859       if (!s0write(wdh, 6, err))                           /* EAddr  == 0      */
860             return FALSE;
861       if (!s16write(wdh, GUINT16_TO_LE(1), err))                  /* s.mxseqno */
862             return FALSE;
863       if (!s16write(wdh, GUINT16_TO_LE(0), err))                  /* s.slcoffo */
864             return FALSE;
865       if (!s16write(wdh, GUINT16_TO_LE(1514), err))               /* s.mxslc */
866             return FALSE;
867       if (!s32write(wdh, GUINT32_TO_LE(itmp->pkts), err))         /* s.totpktt */
868             return FALSE;
869       /*
870        * statrg == 0; ? -1
871        * stptrg == 0; ? -1
872        * s.mxpkta[0]=0
873        */
874       if (!s0write(wdh, 12, err))
875             return FALSE;
876       if (!s32write(wdh, GUINT32_TO_LE(itmp->pkts), err))         /* sr.s.mxpkta[1]  */
877             return FALSE;
878       if (!s0write(wdh, 34*4, err))                        /* s.mxpkta[2-33]=0  */
879             return FALSE;
880       if (!s16write(wdh, GUINT16_TO_LE(board_type), err))
881             return FALSE;
882       if (!s0write(wdh, 20, err))                             /* board_version == 0 */
883             return FALSE;
884       /*-----------------------------------------------------------------*/
885       if (!s16write(wdh, GUINT16_TO_LE(RT_SubfileSummary), err))     /* ssr.rid */
886             return FALSE;
887       if (!s16write(wdh, GUINT16_TO_LE(LA_SubfileSummaryRecordSize-4), err)) /* ssr.rlen */
888             return FALSE;
889       if (!s16write(wdh, GUINT16_TO_LE(1), err))                     /* ssr.seqno */
890             return FALSE;
891       if (!s32write(wdh, GUINT32_TO_LE(itmp->pkts), err))            /* ssr.totpkts */
892             return FALSE;
893       /*-----------------------------------------------------------------*/
894       if (!wtap_dump_file_write(wdh, &LA_CyclicInformationFake,
895                                 sizeof LA_CyclicInformationFake, err))
896             return FALSE;
897       /*-----------------------------------------------------------------*/
898       if (!s16write(wdh, GUINT16_TO_LE(RT_Index), err))              /* rid */
899             return FALSE;
900       if (!s16write(wdh, GUINT16_TO_LE(LA_IndexRecordSize -4), err)) /* rlen */
901             return FALSE;
902       if (!s16write(wdh, GUINT16_TO_LE(LA_IndexSize), err))          /* idxsp */
903             return FALSE;
904       if (!s0write(wdh, LA_IndexRecordSize - 6, err))
905             return FALSE;
906
907       return TRUE;
908 }
909
910 /*---------------------------------------------------
911  * Finish writing to a dump file.
912  * Returns TRUE on success, FALSE on failure.
913  *---------------------------------------------------*/
914 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err)
915 {
916       lanalyzer_dump_header(wdh,err);
917       return *err ? FALSE : TRUE;
918 }