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