Clean up properly if we get an error after allocating the private data
[obnox/wireshark/wip.git] / wiretap / nettl.c
1 /* nettl.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * Enhancements by Mark C. Brown <mbrown@hp.com>
9  * Copyright (C) 2003, 2005 Hewlett-Packard Development Company, L.P.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <string.h>
33 #include "wtap-int.h"
34 #include "file_wrappers.h"
35 #include "buffer.h"
36 #include "nettl.h"
37
38 /* HP nettl file header */
39
40 /* Magic number size */
41 #define MAGIC_SIZE      12
42
43 /* HP-UX 9.x */
44 static const guint8 nettl_magic_hpux9[MAGIC_SIZE] = {
45     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x00
46 };
47 /* HP-UX 10.x and 11.x */
48 static const guint8 nettl_magic_hpux10[MAGIC_SIZE] = {
49     0x54, 0x52, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
50 };
51
52 #define FILE_HDR_SIZE   128
53 #define NETTL_FILENAME_SIZE 56
54
55 struct nettl_file_hdr {
56     guint8      magic[MAGIC_SIZE];
57     gchar       file_name[NETTL_FILENAME_SIZE];
58     gchar       tz[20];
59     gchar       host_name[9];
60     gchar       os_vers[9];
61     guchar      os_v;
62     guint8      xxa[8];
63     gchar       model[11];
64     guint16     unknown;        /* just padding to 128 bytes? */
65 };
66
67 /* HP nettl record header */
68 /* see /usr/include/sys/netdiag1.h for hints */
69 struct nettlrec_hdr {
70     guint16     hdr_len;
71     guint16     subsys;
72     guint32     devid;
73     guint8      xxa[4];
74     guint32     kind;
75     guint8      xxb[16];
76     guint32     caplen;
77     guint32     length;
78     guint32     sec;
79     guint32     usec;
80     guint32     pid;
81     guint8      xxc[10];
82     guint16     uid;
83 };
84
85 /*
86  * This is what we treat as the minimum size of a record header.
87  * It is *not* necessarily the same as sizeof(struct nettlrec_hdr),
88  * because it doesn't include any padding added to the structure.
89  */
90 #define NETTL_REC_HDR_LEN       64
91
92 /* HP nettl record header for the SX25L2 subsystem - The FCS is not included
93    in the file. */
94 struct nettlrec_sx25l2_hdr {
95     guint8      xxa[8];
96     guint8      from_dce;
97     guint8      xxb[55];
98     guint8      caplen[2];
99     guint8      length[2];
100     guint8      xxc[4];
101     guint8      sec[4];
102     guint8      usec[4];
103     guint8      xxd[4];
104 };
105
106 /* NL_LS_DRIVER :
107 The following shows what the header and subheader looks like for NS_LS_DRIVER
108 The capture was taken on HPUX11 and for a 100baseT interface.
109
110 000080 00 44 00 0b 00 00 00 02 00 00 00 00 20 00 00 00
111 000090 00 00 00 00 00 00 04 06 00 00 00 00 00 00 00 00
112 0000a0 00 00 00 74 00 00 00 74 3c e3 76 19 00 06 34 63
113 0000b0 ff ff ff ff 00 00 00 00 00 00 00 00 ff ff ff ff
114 0000c0 00 00 00 00 00 00 01 02 00 5c 00 5c ff ff ff ff
115 0000d0 3c e3 76 19 00 06 34 5a 00 0b 00 14 <here starts the MAC header>
116
117 Each entry starts with 0x0044000b
118
119 The values 0x005c at position 0x0000c8 and 0x0000ca matches the number of
120 bytes in the packet up to the next entry, which starts with 0x00440b again.
121 These are the captured and real and captured length of the packet.
122
123 The values 0x00000074 at positions 0x0000a0 and 0x0000a4 seems to indicate
124 the same number as positions 0x0000c8 and 0x0000ca but added with 24.
125 Perhaps we have here two layers of headers.
126 The first layer is fixed and consists of all the bytes from 0x000084 up to and
127 including 0x0000c3 which is a generic header for all packets captured from any
128 device. This header might be of fixed size 64 bytes (although the first two
129 bytes appear to be the length of that header, in big-endian format) and there
130 might be something in it which indicates the type of the next header which is
131 link type specific. Following this header there is another header for the
132 100baseT interface which in this case is 24 bytes long spanning positions
133 0x0000c4 to 0x0000db.
134
135 In another capture, claimed to be taken on an HP-UX 8 box, but with a
136 file header suggesting it was taken on HP-UX 10.20, the header for
137 NS_LS_DRIVER looks like:
138
139 000080   00 40 00 0b ff ff ff ff 00 00 00 00 00 00 00 00
140 000090   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
141 0000a0   00 00 00 51 00 00 00 51 42 02 5e bf 00 0e ab 7c
142 0000b0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
143 0000c0   00 02 01 00 00 3b 00 3b ff ff ff ff 42 02 5e bf
144 0000d0   00 0e 8e 44 00 0b <here starts the MAC header>
145
146 When someone reports that the loading of the captures breaks, we can
147 compare this header above with what he/she got to learn how to
148 distinguish between different types of link specific headers.
149
150
151 For now, the subheader for 100baseT seems to be
152         4-5     captured length
153         6-7     actual length
154         8-11    unknown
155         12-15   secs
156         16-19   usecs
157         20-21   unknown
158 */
159 struct nettlrec_ns_ls_drv_eth_hdr {
160     guint8      xxa[4];
161     guint8      caplen[2];
162     guint8      length[2];
163     guint8      xxb[4];
164     guint8      sec[4];
165     guint8      usec[4];
166     guint8      xxc[2];
167 };
168
169 /*
170  * This is the size of an NS_LS_DRV_ETH header; it is *not* necessarily
171  * the same as sizeof(struct nettlrec_ns_ls_drv_eth_hdr), because it
172  * doesn't include any padding added to the structure.
173  */
174 #define NS_LS_DRV_ETH_HDR_LEN   22
175
176 /* header is followed by data and once again the total length (2 bytes) ! */
177
178 typedef struct {
179         gboolean is_hpux_11;
180 } nettl_t;
181
182 static gboolean nettl_read(wtap *wth, int *err, gchar **err_info,
183                 gint64 *data_offset);
184 static gboolean nettl_seek_read(wtap *wth, gint64 seek_off,
185                 union wtap_pseudo_header *pseudo_header, guchar *pd,
186                 int length, int *err, gchar **err_info);
187 static int nettl_read_rec_header(wtap *wth, FILE_T fh,
188                 struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
189                 int *err, gchar **err_info, gboolean *fddihack);
190 static gboolean nettl_read_rec_data(FILE_T fh, guchar *pd, int length,
191                 int *err, gboolean fddihack);
192 static gboolean nettl_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
193     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
194
195 int nettl_open(wtap *wth, int *err, gchar **err_info _U_)
196 {
197     struct nettl_file_hdr file_hdr;
198     guint16 dummy[2];
199     int subsys;
200     int bytes_read;
201     nettl_t *nettl;
202
203     /* Read in the string that should be at the start of a HP file */
204     errno = WTAP_ERR_CANT_READ;
205     bytes_read = file_read(file_hdr.magic, 1, MAGIC_SIZE, wth->fh);
206     if (bytes_read != MAGIC_SIZE) {
207         *err = file_error(wth->fh);
208         if (*err != 0)
209             return -1;
210         return 0;
211     }
212
213     if (memcmp(file_hdr.magic, nettl_magic_hpux9, MAGIC_SIZE) &&
214         memcmp(file_hdr.magic, nettl_magic_hpux10, MAGIC_SIZE)) {
215         return 0;
216     }
217
218     /* Read the rest of the file header */
219     bytes_read = file_read(file_hdr.file_name, 1, FILE_HDR_SIZE - MAGIC_SIZE,
220                            wth->fh);
221     if (bytes_read != FILE_HDR_SIZE - MAGIC_SIZE) {
222         *err = file_error(wth->fh);
223         if (*err != 0)
224             return -1;
225         return 0;
226     }
227
228     /* This is an nettl file */
229     wth->file_type = WTAP_FILE_NETTL;
230     nettl = g_malloc(sizeof(nettl_t));
231     wth->priv = (void *)nettl;
232     if (file_hdr.os_vers[2] == '1' && file_hdr.os_vers[3] == '1')
233         nettl->is_hpux_11 = TRUE;
234     else
235         nettl->is_hpux_11 = FALSE;
236     wth->subtype_read = nettl_read;
237     wth->subtype_seek_read = nettl_seek_read;
238     wth->snapshot_length = 0;   /* not available */
239
240     /* read the first header to take a guess at the file encap */
241     bytes_read = file_read(dummy, 1, 4, wth->fh);
242     if (bytes_read != 4) {
243         if (*err != 0) {
244             wth->priv = NULL;
245             g_free(nettl);
246             return -1;
247         }
248         if (bytes_read != 0) {
249             *err = WTAP_ERR_SHORT_READ;
250             wth->priv = NULL;
251             g_free(nettl);
252             return -1;
253         }
254         wth->priv = NULL;
255         g_free(nettl);
256         return 0;
257     }
258
259     subsys = g_ntohs(dummy[1]);
260     switch (subsys) {
261         case NETTL_SUBSYS_HPPB_FDDI :
262         case NETTL_SUBSYS_EISA_FDDI :
263         case NETTL_SUBSYS_PCI_FDDI :
264         case NETTL_SUBSYS_HSC_FDDI :
265                 wth->file_encap = WTAP_ENCAP_NETTL_FDDI;
266                 break;
267         case NETTL_SUBSYS_TOKEN :
268         case NETTL_SUBSYS_PCI_TR :
269                 wth->file_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
270                 break;
271         case NETTL_SUBSYS_NS_LS_IP :
272         case NETTL_SUBSYS_NS_LS_LOOPBACK :
273         case NETTL_SUBSYS_NS_LS_TCP :
274         case NETTL_SUBSYS_NS_LS_UDP :
275         case NETTL_SUBSYS_NS_LS_IPV6 :
276                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_IP;
277                 break;
278         case NETTL_SUBSYS_NS_LS_ICMP :
279                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
280                 break;
281         case NETTL_SUBSYS_NS_LS_ICMPV6 :
282                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
283                 break;
284         case NETTL_SUBSYS_NS_LS_TELNET :
285                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_TELNET;
286                 break;
287         default:
288                 /* If this assumption is bad, the read will catch it */
289                 wth->file_encap = WTAP_ENCAP_NETTL_ETHERNET;
290     }
291
292     if (file_seek(wth->fh, FILE_HDR_SIZE, SEEK_SET, err) == -1) {
293         g_free(nettl);
294         return -1;
295     }
296     wth->data_offset = FILE_HDR_SIZE;
297     wth->tsprecision = WTAP_FILE_TSPREC_USEC;
298
299     return 1;
300 }
301
302 /* Read the next packet */
303 static gboolean nettl_read(wtap *wth, int *err, gchar **err_info,
304     gint64 *data_offset)
305 {
306     int ret;
307     gboolean fddihack=FALSE;
308
309     /* Read record header. */
310     *data_offset = wth->data_offset;
311     ret = nettl_read_rec_header(wth, wth->fh, &wth->phdr, &wth->pseudo_header,
312         err, err_info, &fddihack);
313     if (ret <= 0) {
314         /* Read error or EOF */
315         return FALSE;
316     }
317     wth->data_offset += ret;
318
319     /*
320      * If the per-file encapsulation isn't known, set it to this
321      * packet's encapsulation.
322      *
323      * If it *is* known, and it isn't this packet's encapsulation,
324      * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
325      * have a single encapsulation for all packets in the file.
326      */
327     if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
328         wth->file_encap = wth->phdr.pkt_encap;
329     else {
330         if (wth->file_encap != wth->phdr.pkt_encap)
331             wth->file_encap = WTAP_ENCAP_PER_PACKET;
332     }
333
334     /*
335      * Read the packet data.
336      */
337     buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
338     if (!nettl_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
339                 wth->phdr.caplen, err, fddihack))
340         return FALSE;   /* Read error */
341     wth->data_offset += wth->phdr.caplen;
342     return TRUE;
343 }
344
345 static gboolean
346 nettl_seek_read(wtap *wth, gint64 seek_off,
347                 union wtap_pseudo_header *pseudo_header, guchar *pd,
348                 int length, int *err, gchar **err_info)
349 {
350     int ret;
351     struct wtap_pkthdr phdr;
352     gboolean fddihack=FALSE;
353
354     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
355         return FALSE;
356
357     /* Read record header. */
358     ret = nettl_read_rec_header(wth, wth->random_fh, &phdr, pseudo_header,
359         err, err_info, &fddihack);
360     if (ret <= 0) {
361         /* Read error or EOF */
362         if (ret == 0) {
363             /* EOF means "short read" in random-access mode */
364             *err = WTAP_ERR_SHORT_READ;
365         }
366         return FALSE;
367     }
368
369     /*
370      * Read the packet data.
371      */
372     return nettl_read_rec_data(wth->random_fh, pd, length, err, fddihack);
373 }
374
375 static int
376 nettl_read_rec_header(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
377                 union wtap_pseudo_header *pseudo_header, int *err,
378                 gchar **err_info, gboolean *fddihack)
379 {
380     nettl_t *nettl = (nettl_t *)wth->priv;
381     int bytes_read;
382     struct nettlrec_hdr rec_hdr;
383     guint16 hdr_len;
384     struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
385     guint16 length, caplen;
386     int offset = 0;
387     int subsys;
388     int padlen;
389     guint8 dummyc[16];
390
391     errno = WTAP_ERR_CANT_READ;
392     bytes_read = file_read(&rec_hdr.hdr_len, 1, sizeof rec_hdr.hdr_len, fh);
393     if (bytes_read != sizeof rec_hdr.hdr_len) {
394         *err = file_error(fh);
395         if (*err != 0)
396             return -1;
397         if (bytes_read != 0) {
398             *err = WTAP_ERR_SHORT_READ;
399             return -1;
400         }
401         return 0;
402     }
403     offset += 2;
404     hdr_len = g_ntohs(rec_hdr.hdr_len);
405     if (hdr_len < NETTL_REC_HDR_LEN) {
406         *err = WTAP_ERR_BAD_RECORD;
407         *err_info = g_strdup_printf("nettl: record header length %u too short",
408             hdr_len);
409         return -1;
410     }
411     bytes_read = file_read(&rec_hdr.subsys, 1, NETTL_REC_HDR_LEN - 2, fh);
412     if (bytes_read != NETTL_REC_HDR_LEN - 2) {
413         *err = file_error(fh);
414         if (*err == 0)
415             *err = WTAP_ERR_SHORT_READ;
416         return -1;
417     }
418     offset += NETTL_REC_HDR_LEN - 2;
419     subsys = g_ntohs(rec_hdr.subsys);
420     hdr_len -= NETTL_REC_HDR_LEN;
421     if (file_seek(fh, hdr_len, SEEK_CUR, err) == -1)
422         return -1;
423     offset += hdr_len;
424
425     if ( (pntohl(&rec_hdr.kind) & NETTL_HDR_PDU_MASK) == 0 ) {
426         /* not actually a data packet (PDU) trace record */
427         phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_IP;
428         length = pntohl(&rec_hdr.length);
429         caplen = pntohl(&rec_hdr.caplen);
430         padlen = 0;
431     } else switch (subsys) {
432         case NETTL_SUBSYS_LAN100 :
433         case NETTL_SUBSYS_EISA100BT :
434         case NETTL_SUBSYS_BASE100 :
435         case NETTL_SUBSYS_GSC100BT :
436         case NETTL_SUBSYS_PCI100BT :
437         case NETTL_SUBSYS_SPP100BT :
438         case NETTL_SUBSYS_100VG :
439         case NETTL_SUBSYS_GELAN :
440         case NETTL_SUBSYS_BTLAN :
441         case NETTL_SUBSYS_INTL100 :
442         case NETTL_SUBSYS_IGELAN :
443         case NETTL_SUBSYS_IETHER :
444         case NETTL_SUBSYS_IXGBE :
445         case NETTL_SUBSYS_HSSN :
446         case NETTL_SUBSYS_IGSSN :
447         case NETTL_SUBSYS_ICXGBE :
448         case NETTL_SUBSYS_IEXGBE :
449         case NETTL_SUBSYS_HPPB_FDDI :
450         case NETTL_SUBSYS_EISA_FDDI :
451         case NETTL_SUBSYS_PCI_FDDI :
452         case NETTL_SUBSYS_HSC_FDDI :
453         case NETTL_SUBSYS_TOKEN :
454         case NETTL_SUBSYS_PCI_TR :
455         case NETTL_SUBSYS_NS_LS_IP :
456         case NETTL_SUBSYS_NS_LS_LOOPBACK :
457         case NETTL_SUBSYS_NS_LS_TCP :
458         case NETTL_SUBSYS_NS_LS_UDP :
459         case NETTL_SUBSYS_HP_APAPORT :
460         case NETTL_SUBSYS_HP_APALACP :
461         case NETTL_SUBSYS_NS_LS_IPV6 :
462         case NETTL_SUBSYS_NS_LS_ICMPV6 :
463         case NETTL_SUBSYS_NS_LS_ICMP :
464         case NETTL_SUBSYS_NS_LS_TELNET :
465         case NETTL_SUBSYS_NS_LS_SCTP :
466             if( (subsys == NETTL_SUBSYS_NS_LS_IP)
467              || (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK)
468              || (subsys == NETTL_SUBSYS_NS_LS_UDP)
469              || (subsys == NETTL_SUBSYS_NS_LS_TCP)
470              || (subsys == NETTL_SUBSYS_NS_LS_SCTP)
471              || (subsys == NETTL_SUBSYS_NS_LS_IPV6)) {
472                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_IP;
473             } else if (subsys == NETTL_SUBSYS_NS_LS_ICMP) {
474                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
475             } else if (subsys == NETTL_SUBSYS_NS_LS_ICMPV6) {
476                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
477             } else if (subsys == NETTL_SUBSYS_NS_LS_TELNET) {
478                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_TELNET;
479             } else if( (subsys == NETTL_SUBSYS_HPPB_FDDI)
480                     || (subsys == NETTL_SUBSYS_EISA_FDDI)
481                     || (subsys == NETTL_SUBSYS_PCI_FDDI)
482                     || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
483                 phdr->pkt_encap = WTAP_ENCAP_NETTL_FDDI;
484             } else if( (subsys == NETTL_SUBSYS_PCI_TR)
485                     || (subsys == NETTL_SUBSYS_TOKEN) ) {
486                 phdr->pkt_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
487             } else {
488                 phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
489             }
490
491             length = pntohl(&rec_hdr.length);
492             caplen = pntohl(&rec_hdr.caplen);
493
494             /* HPPB FDDI has different inbound vs outbound trace records */
495             if (subsys == NETTL_SUBSYS_HPPB_FDDI) {
496                 if (pntohl(&rec_hdr.kind) == NETTL_HDR_PDUIN) {
497                     /* inbound is very strange...
498                        there are an extra 3 bytes after the DSAP and SSAP
499                        for SNAP frames ???
500                     */
501                     *fddihack=TRUE;
502                     padlen = 0;
503                 } else {
504                     /* outbound appears to have variable padding */
505                     bytes_read = file_read(dummyc, 1, 9, fh);
506                     if (bytes_read != 9) {
507                         *err = file_error(fh);
508                         if (*err == 0)
509                             *err = WTAP_ERR_SHORT_READ;
510                         return -1;
511                     }
512                     /* padding is usually either a total 11 or 16 bytes??? */
513                     padlen = (int)dummyc[8];
514                     if (file_seek(fh, padlen, SEEK_CUR, err) == -1)
515                         return -1;
516                     padlen += 9;
517                     offset += padlen;
518                 }
519             } else if ( (subsys == NETTL_SUBSYS_PCI_FDDI)
520                      || (subsys == NETTL_SUBSYS_EISA_FDDI)
521                      || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
522                 /* other flavor FDDI cards have an extra 3 bytes of padding */
523                 if (file_seek(fh, 3, SEEK_CUR, err) == -1)
524                     return -1;
525                 padlen = 3;
526                 offset += padlen;
527             } else if (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK) {
528                 /* LOOPBACK has an extra 26 bytes of padding */
529                 if (file_seek(fh, 26, SEEK_CUR, err) == -1)
530                     return -1;
531                 padlen = 26;
532                 offset += padlen;
533             } else if (subsys == NETTL_SUBSYS_NS_LS_SCTP) {
534                 /*
535                  * SCTP 8 byte header that we will ignore...
536                  * 32 bit integer defines format
537                  *   1 = Log
538                  *   2 = ASCII
539                  *   3 = Binary (PDUs should be Binary format)
540                  * 32 bit integer defines type
541                  *   1 = Inbound
542                  *   2 = Outbound
543                  */
544                 if (file_seek(fh, 8, SEEK_CUR, err) == -1)
545                     return -1;
546                 padlen = 8;
547                 offset += padlen;   
548             } else {
549                 padlen = 0;
550             }
551             break;
552
553         case NETTL_SUBSYS_NS_LS_DRIVER :
554             /* XXX we dont know how to identify this as ethernet frames, so
555                we assumes everything is. We will crash and burn for anything else */
556             /* for encapsulated 100baseT we do this */
557             phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
558             bytes_read = file_read(&drv_eth_hdr, 1, NS_LS_DRV_ETH_HDR_LEN, fh);
559             if (bytes_read != NS_LS_DRV_ETH_HDR_LEN) {
560                 *err = file_error(fh);
561                 if (*err == 0)
562                     *err = WTAP_ERR_SHORT_READ;
563                 return -1;
564             }
565             offset += NS_LS_DRV_ETH_HDR_LEN;
566
567             length = pntohs(&drv_eth_hdr.length); 
568             caplen = pntohs(&drv_eth_hdr.caplen);
569             /*
570              * XXX - is there a length field that would give the length
571              * of this header, so that we don't have to check for
572              * nettl files from HP-UX 11?
573              *
574              * And what are the extra two bytes?
575              */
576             if (nettl->is_hpux_11) {
577                 if (file_seek(fh, 2, SEEK_CUR, err) == -1) return -1;
578                 offset += 2;
579             }
580             padlen = 0;
581             break;
582
583         case NETTL_SUBSYS_SX25L2:
584         case NETTL_SUBSYS_SX25L3:
585             /*
586              * XXX - is the 24-byte padding actually a header with
587              * packet lengths, time stamps, etc., just as is the case
588              * for NETTL_SUBSYS_NS_LS_DRIVER?  It might be
589              *
590              *    guint8        caplen[2];
591              *    guint8        length[2];
592              *    guint8        xxc[4];
593              *    guint8        sec[4];
594              *    guint8        usec[4];
595              *    guint8        xxd[4];
596              *
597              * or something such as that - if it has 4 bytes before that
598              * (making it 24 bytes), it'd be like struct
599              * nettlrec_ns_ls_drv_eth_hdr but with 2 more bytes at the end.
600              *
601              * And is "from_dce" at xxa[0] in the nettlrec_hdr structure?
602              */
603             phdr->pkt_encap = WTAP_ENCAP_NETTL_X25;
604             length = pntohl(&rec_hdr.length);
605             caplen = pntohl(&rec_hdr.caplen);
606             padlen = 24;        /* sizeof (struct nettlrec_sx25l2_hdr) - NETTL_REC_HDR_LEN + 4 */
607             if (file_seek(fh, padlen, SEEK_CUR, err) == -1)
608                 return -1;
609             offset += padlen;
610             break;
611
612         default:
613             /* We're going to assume it's ethernet if we don't recognize the
614                subsystem -- We'll probably spew junks and core if it isn't... */
615             wth->file_encap = WTAP_ENCAP_PER_PACKET;
616             phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
617             length = pntohl(&rec_hdr.length);
618             caplen = pntohl(&rec_hdr.caplen);
619             padlen = 0;
620             break;
621     }
622
623     if (length < padlen) {
624         *err = WTAP_ERR_BAD_RECORD;
625         *err_info = g_strdup_printf("nettl: packet length %u in record header too short, less than %u",
626             length, padlen);
627         return -1;
628     }
629     phdr->len = length - padlen;
630     if (caplen < padlen) {
631         *err = WTAP_ERR_BAD_RECORD;
632         *err_info = g_strdup_printf("nettl: captured length %u in record header too short, less than %u",
633             caplen, padlen);
634         return -1;
635     }
636     phdr->caplen = caplen - padlen;
637     phdr->ts.secs = pntohl(&rec_hdr.sec);
638     phdr->ts.nsecs = pntohl(&rec_hdr.usec) * 1000;
639
640     pseudo_header->nettl.subsys   = subsys;
641     pseudo_header->nettl.devid    = pntohl(&rec_hdr.devid);
642     pseudo_header->nettl.kind     = pntohl(&rec_hdr.kind);
643     pseudo_header->nettl.pid      = pntohl(&rec_hdr.pid);
644     pseudo_header->nettl.uid      = pntohs(&rec_hdr.uid);
645
646     return offset;
647 }
648
649 static gboolean
650 nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err, gboolean fddihack)
651 {
652     int bytes_read;
653     guchar *p=NULL;
654     guint8 dummy[3];
655
656     if (fddihack == TRUE) {
657        /* read in FC, dest, src, DSAP and SSAP */
658        if (file_read(pd, 1, 15, fh) == 15) {
659           if (pd[13] == 0xAA) {
660              /* it's SNAP, have to eat 3 bytes??? */
661              if (file_read(dummy, 1, 3, fh) == 3) {
662                 p=pd+15;
663                 bytes_read = file_read(p, 1, length-18, fh);
664                 bytes_read += 18;
665              } else {
666                 bytes_read = -1;
667              }
668           } else {
669              /* not SNAP */
670              p=pd+15;
671              bytes_read = file_read(p, 1, length-15, fh);
672              bytes_read += 15;
673           }
674        } else
675           bytes_read = -1;
676     } else
677        bytes_read = file_read(pd, 1, length, fh);
678
679     if (bytes_read != length) {
680         *err = file_error(fh);
681         if (*err == 0)
682             *err = WTAP_ERR_SHORT_READ;
683         return FALSE;
684     }
685     return TRUE;
686 }
687
688
689 /* Returns 0 if we could write the specified encapsulation type,
690    an error indication otherwise.  nettl files are WTAP_ENCAP_UNKNOWN
691    when they are first opened, so we allow that for tshark read/write.
692  */
693
694 int nettl_dump_can_write_encap(int encap)
695 {
696
697         switch (encap) {
698                 case WTAP_ENCAP_ETHERNET:
699                 case WTAP_ENCAP_FDDI_BITSWAPPED:
700                 case WTAP_ENCAP_TOKEN_RING:
701                 case WTAP_ENCAP_NETTL_ETHERNET:
702                 case WTAP_ENCAP_NETTL_FDDI:
703                 case WTAP_ENCAP_NETTL_TOKEN_RING:
704                 case WTAP_ENCAP_NETTL_RAW_IP:
705                 case WTAP_ENCAP_NETTL_RAW_ICMP:
706                 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
707                 case WTAP_ENCAP_NETTL_RAW_TELNET:
708 /*
709                 case WTAP_ENCAP_NETTL_X25:
710 */
711                 case WTAP_ENCAP_PER_PACKET:
712                 case WTAP_ENCAP_UNKNOWN:
713                 case WTAP_ENCAP_NETTL_UNKNOWN:
714                         return 0;
715                 default:
716                         return WTAP_ERR_UNSUPPORTED_ENCAP;
717         }
718 }
719
720
721 /* Returns TRUE on success, FALSE on failure;
722    sets "*err" to an error code on failure */
723 gboolean nettl_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
724 {
725         struct nettl_file_hdr file_hdr;
726         size_t nwritten;
727
728         /* This is a nettl file */
729         wdh->subtype_write = nettl_dump;
730         wdh->subtype_close = NULL;
731
732         /* Write the file header. */
733         memset(&file_hdr,0,sizeof(file_hdr));
734         memcpy(file_hdr.magic,nettl_magic_hpux10,sizeof(file_hdr.magic));
735         g_strlcpy(file_hdr.file_name,"/tmp/wireshark.TRC000",NETTL_FILENAME_SIZE);
736         g_strlcpy(file_hdr.tz,"UTC",20);
737         g_strlcpy(file_hdr.host_name,"",9);
738         g_strlcpy(file_hdr.os_vers,"B.11.11",9);
739         file_hdr.os_v=0x55;
740         g_strlcpy(file_hdr.model,"9000/800",11);
741         file_hdr.unknown=g_htons(0x406);
742         nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
743         if (nwritten != sizeof(file_hdr)) {
744                 if (nwritten == 0 && ferror(wdh->fh))
745                         *err = errno;
746                 else
747                         *err = WTAP_ERR_SHORT_WRITE;
748                 return FALSE;
749         }
750         wdh->bytes_dumped += sizeof(file_hdr);
751
752         return TRUE;
753 }
754
755 /* Write a record for a packet to a dump file.
756    Returns TRUE on success, FALSE on failure. */
757 static gboolean nettl_dump(wtap_dumper *wdh,
758         const struct wtap_pkthdr *phdr,
759         const union wtap_pseudo_header *pseudo_header _U_,
760         const guchar *pd, int *err)
761 {
762         struct nettlrec_hdr rec_hdr;
763         size_t nwritten;
764         guint8 dummyc[24];
765
766         memset(&rec_hdr,0,sizeof(rec_hdr));
767         /* HP-UX 11.X header should be 68 bytes */
768         rec_hdr.hdr_len = g_htons(sizeof(rec_hdr) + 4);
769         rec_hdr.kind = g_htonl(NETTL_HDR_PDUIN);
770         rec_hdr.sec = g_htonl(phdr->ts.secs);
771         rec_hdr.usec = g_htonl(phdr->ts.nsecs/1000);
772         rec_hdr.caplen = g_htonl(phdr->caplen);
773         rec_hdr.length = g_htonl(phdr->len);
774         rec_hdr.devid = -1;
775         rec_hdr.pid = -1;
776         rec_hdr.uid = -1;
777
778         switch (phdr->pkt_encap) {
779
780                 case WTAP_ENCAP_NETTL_FDDI:
781                         /* account for pad bytes */
782                         rec_hdr.caplen = g_htonl(phdr->caplen + 3);
783                         rec_hdr.length = g_htonl(phdr->len + 3);
784                         /* fall through and fill the rest of the fields */
785                 case WTAP_ENCAP_NETTL_ETHERNET:
786                 case WTAP_ENCAP_NETTL_TOKEN_RING:
787                 case WTAP_ENCAP_NETTL_RAW_IP:
788                 case WTAP_ENCAP_NETTL_RAW_ICMP:
789                 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
790                 case WTAP_ENCAP_NETTL_RAW_TELNET:
791                 case WTAP_ENCAP_NETTL_UNKNOWN:
792                         rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
793                         rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
794                         rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
795                         rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
796                         rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
797                         break;
798
799                 case WTAP_ENCAP_RAW_IP:
800                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_NS_LS_IP);
801                         break;
802
803                 case WTAP_ENCAP_ETHERNET:
804                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_BTLAN);
805                         break;
806
807                 case WTAP_ENCAP_FDDI_BITSWAPPED:
808                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_FDDI);
809                         /* account for pad bytes */
810                         rec_hdr.caplen = g_htonl(phdr->caplen + 3);
811                         rec_hdr.length = g_htonl(phdr->len + 3);
812                         break;
813
814                 case WTAP_ENCAP_TOKEN_RING:
815                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_TR);
816                         break;
817 /*      
818                 case WTAP_ENCAP_NETTL_X25:
819                         rec_hdr.caplen = g_htonl(phdr->caplen + 24);
820                         rec_hdr.length = g_htonl(phdr->len + 24);
821                         rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
822                         rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
823                         rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
824                         rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
825                         rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
826                         break;
827 */
828                 default:
829                         /* found one we don't support */
830                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
831                         return FALSE;
832         }
833
834         nwritten = fwrite(&rec_hdr, 1, sizeof(rec_hdr), wdh->fh);
835         if (nwritten != sizeof(rec_hdr)) {
836                 if (nwritten == 0 && ferror(wdh->fh))
837                         *err = errno;
838                 else
839                         *err = WTAP_ERR_SHORT_WRITE;
840                 return FALSE;
841         }
842         wdh->bytes_dumped += sizeof(rec_hdr);
843
844         /* Write out 4 extra bytes of unknown stuff for HP-UX11
845          * header format.
846          */
847         memset(dummyc, 0, sizeof dummyc);
848         nwritten = fwrite(dummyc, 1, 4, wdh->fh);
849         if (nwritten != 4) {
850                 if (nwritten == 0 && ferror(wdh->fh))
851                         *err = errno;
852                 else
853                         *err = WTAP_ERR_SHORT_WRITE;
854                 return FALSE;
855         }
856         wdh->bytes_dumped += 4;
857
858         if ((phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) ||
859             (phdr->pkt_encap == WTAP_ENCAP_NETTL_FDDI)) {
860                 /* add those weird 3 bytes of padding */
861                 nwritten = fwrite(dummyc, 1, 3, wdh->fh);
862                 if (nwritten != 3) {
863                         if (nwritten == 0 && ferror(wdh->fh))
864                                 *err = errno;
865                         else
866                                 *err = WTAP_ERR_SHORT_WRITE;
867                         return FALSE;
868                 }
869                 wdh->bytes_dumped += 3;
870         }
871 /*
872         } else if (phdr->pkt_encap == WTAP_ENCAP_NETTL_X25) {
873                 nwritten = fwrite(dummyc, 1, 24, wdh->fh);
874                 if (nwritten != 24) {
875                         if (nwritten == 0 && ferror(wdh->fh))
876                                 *err = errno;
877                         else
878                                 *err = WTAP_ERR_SHORT_WRITE;
879                         return FALSE;
880                 }
881                 wdh->bytes_dumped += 24;
882         }
883 */
884
885         /* write actual PDU data */
886
887         nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
888         if (nwritten != phdr->caplen) {
889                 if (nwritten == 0 && ferror(wdh->fh))
890                         *err = errno;
891                 else
892                         *err = WTAP_ERR_SHORT_WRITE;
893                 return FALSE;
894         }
895         wdh->bytes_dumped += phdr->caplen;
896
897         return TRUE;
898 }