0911388cec9ae16ebc724431266840f8c3a310c8
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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                 long *data_offset);
179 static gboolean nettl_seek_read(wtap *wth, long 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         case NETTL_SUBSYS_NS_LS_ICMP :
267                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
268         case NETTL_SUBSYS_NS_LS_ICMPV6 :
269                 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
270                 break;
271         default:
272                 /* If this assumption is bad, the read will catch it */
273                 wth->file_encap = WTAP_ENCAP_NETTL_ETHERNET;
274     }
275
276     if (file_seek(wth->fh, FILE_HDR_SIZE, SEEK_SET, err) == -1) {
277         g_free(wth->capture.nettl);
278         return -1;
279     }
280     wth->data_offset = FILE_HDR_SIZE;
281     wth->tsprecision = WTAP_FILE_TSPREC_USEC;
282
283     return 1;
284 }
285
286 /* Read the next packet */
287 static gboolean nettl_read(wtap *wth, int *err, gchar **err_info,
288     long *data_offset)
289 {
290     int ret;
291     gboolean fddihack=FALSE;
292
293     /* Read record header. */
294     *data_offset = wth->data_offset;
295     ret = nettl_read_rec_header(wth, wth->fh, &wth->phdr, &wth->pseudo_header,
296         err, err_info, &fddihack);
297     if (ret <= 0) {
298         /* Read error or EOF */
299         return FALSE;
300     }
301     wth->data_offset += ret;
302
303     /*
304      * If the per-file encapsulation isn't known, set it to this
305      * packet's encapsulation.
306      *
307      * If it *is* known, and it isn't this packet's encapsulation,
308      * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
309      * have a single encapsulation for all packets in the file.
310      */
311     if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
312         wth->file_encap = wth->phdr.pkt_encap;
313     else {
314         if (wth->file_encap != wth->phdr.pkt_encap)
315             wth->file_encap = WTAP_ENCAP_PER_PACKET;
316     }
317
318     /*
319      * Read the packet data.
320      */
321     buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
322     if (!nettl_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
323                 wth->phdr.caplen, err, fddihack))
324         return FALSE;   /* Read error */
325     wth->data_offset += wth->phdr.caplen;
326     return TRUE;
327 }
328
329 static gboolean
330 nettl_seek_read(wtap *wth, long seek_off,
331                 union wtap_pseudo_header *pseudo_header, guchar *pd,
332                 int length, int *err, gchar **err_info)
333 {
334     int ret;
335     struct wtap_pkthdr phdr;
336     gboolean fddihack=FALSE;
337
338     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
339         return FALSE;
340
341     /* Read record header. */
342     ret = nettl_read_rec_header(wth, wth->random_fh, &phdr, pseudo_header,
343         err, err_info, &fddihack);
344     if (ret <= 0) {
345         /* Read error or EOF */
346         if (ret == 0) {
347             /* EOF means "short read" in random-access mode */
348             *err = WTAP_ERR_SHORT_READ;
349         }
350         return FALSE;
351     }
352
353     /*
354      * Read the packet data.
355      */
356     return nettl_read_rec_data(wth->random_fh, pd, length, err, fddihack);
357 }
358
359 static int
360 nettl_read_rec_header(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
361                 union wtap_pseudo_header *pseudo_header, int *err,
362                 gchar **err_info, gboolean *fddihack)
363 {
364     int bytes_read;
365     struct nettlrec_hdr rec_hdr;
366     guint16 hdr_len;
367     struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
368     guint16 length, caplen;
369     int offset = 0;
370     int subsys;
371     int padlen;
372     guint8 dummyc[16];
373
374     errno = WTAP_ERR_CANT_READ;
375     bytes_read = file_read(&rec_hdr.hdr_len, 1, sizeof rec_hdr.hdr_len, fh);
376     if (bytes_read != sizeof rec_hdr.hdr_len) {
377         *err = file_error(fh);
378         if (*err != 0)
379             return -1;
380         if (bytes_read != 0) {
381             *err = WTAP_ERR_SHORT_READ;
382             return -1;
383         }
384         return 0;
385     }
386     offset += 2;
387     hdr_len = g_ntohs(rec_hdr.hdr_len);
388     if (hdr_len < NETTL_REC_HDR_LEN) {
389         *err = WTAP_ERR_BAD_RECORD;
390         *err_info = g_strdup_printf("nettl: record header length %u too short",
391             hdr_len);
392         return -1;
393     }
394     bytes_read = file_read(&rec_hdr.subsys, 1, NETTL_REC_HDR_LEN - 2, fh);
395     if (bytes_read != NETTL_REC_HDR_LEN - 2) {
396         *err = file_error(fh);
397         if (*err == 0)
398             *err = WTAP_ERR_SHORT_READ;
399         return -1;
400     }
401     offset += NETTL_REC_HDR_LEN - 2;
402     subsys = g_ntohs(rec_hdr.subsys);
403     hdr_len -= NETTL_REC_HDR_LEN;
404     if (file_seek(fh, hdr_len, SEEK_CUR, err) == -1)
405         return -1;
406     offset += hdr_len;
407
408     switch (subsys) {
409         case NETTL_SUBSYS_LAN100 :
410         case NETTL_SUBSYS_EISA100BT :
411         case NETTL_SUBSYS_BASE100 :
412         case NETTL_SUBSYS_GSC100BT :
413         case NETTL_SUBSYS_PCI100BT :
414         case NETTL_SUBSYS_SPP100BT :
415         case NETTL_SUBSYS_100VG :
416         case NETTL_SUBSYS_GELAN :
417         case NETTL_SUBSYS_BTLAN :
418         case NETTL_SUBSYS_INTL100 :
419         case NETTL_SUBSYS_IGELAN :
420         case NETTL_SUBSYS_IETHER :
421         case NETTL_SUBSYS_IXGBE :
422         case NETTL_SUBSYS_HPPB_FDDI :
423         case NETTL_SUBSYS_EISA_FDDI :
424         case NETTL_SUBSYS_PCI_FDDI :
425         case NETTL_SUBSYS_HSC_FDDI :
426         case NETTL_SUBSYS_TOKEN :
427         case NETTL_SUBSYS_PCI_TR :
428         case NETTL_SUBSYS_NS_LS_IP :
429         case NETTL_SUBSYS_NS_LS_LOOPBACK :
430         case NETTL_SUBSYS_NS_LS_TCP :
431         case NETTL_SUBSYS_NS_LS_UDP :
432         case NETTL_SUBSYS_HP_APAPORT :
433         case NETTL_SUBSYS_HP_APALACP :
434         case NETTL_SUBSYS_NS_LS_IPV6 :
435         case NETTL_SUBSYS_NS_LS_ICMPV6 :
436         case NETTL_SUBSYS_NS_LS_ICMP :
437             if( (subsys == NETTL_SUBSYS_NS_LS_IP)
438              || (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK)
439              || (subsys == NETTL_SUBSYS_NS_LS_UDP)
440              || (subsys == NETTL_SUBSYS_NS_LS_TCP)
441              || (subsys == NETTL_SUBSYS_NS_LS_IPV6)) {
442                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_IP;
443             } else if (subsys == NETTL_SUBSYS_NS_LS_ICMP) {
444                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
445             } else if (subsys == NETTL_SUBSYS_NS_LS_ICMPV6) {
446                 phdr->pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
447             } else if( (subsys == NETTL_SUBSYS_HPPB_FDDI)
448                     || (subsys == NETTL_SUBSYS_EISA_FDDI)
449                     || (subsys == NETTL_SUBSYS_PCI_FDDI)
450                     || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
451                 phdr->pkt_encap = WTAP_ENCAP_NETTL_FDDI;
452             } else if( (subsys == NETTL_SUBSYS_PCI_TR)
453                     || (subsys == NETTL_SUBSYS_TOKEN) ) {
454                 phdr->pkt_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
455             } else {
456                 phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
457             }
458
459             length = pntohl(&rec_hdr.length);
460             caplen = pntohl(&rec_hdr.caplen);
461
462             /* HPPB FDDI has different inbound vs outbound trace records */
463             if (subsys == NETTL_SUBSYS_HPPB_FDDI) {
464                 if (pntohl(&rec_hdr.kind) == NETTL_HDR_PDUIN) {
465                     /* inbound is very strange...
466                        there are an extra 3 bytes after the DSAP and SSAP
467                        for SNAP frames ???
468                     */
469                     *fddihack=TRUE;
470                     padlen = 0;
471                 } else {
472                     /* outbound appears to have variable padding */
473                     bytes_read = file_read(dummyc, 1, 9, fh);
474                     if (bytes_read != 9) {
475                         *err = file_error(fh);
476                         if (*err == 0)
477                             *err = WTAP_ERR_SHORT_READ;
478                         return -1;
479                     }
480                     /* padding is usually either a total 11 or 16 bytes??? */
481                     padlen = (int)dummyc[8];
482                     if (file_seek(fh, padlen, SEEK_CUR, err) == -1)
483                         return -1;
484                     padlen += 9;
485                     offset += padlen;
486                 }
487             } else if ( (subsys == NETTL_SUBSYS_PCI_FDDI)
488                      || (subsys == NETTL_SUBSYS_EISA_FDDI)
489                      || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
490                 /* other flavor FDDI cards have an extra 3 bytes of padding */
491                 if (file_seek(fh, 3, SEEK_CUR, err) == -1)
492                     return -1;
493                 padlen = 3;
494                 offset += padlen;
495             } else if (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK) {
496                 /* LOOPBACK has an extra 26 bytes of padding */
497                 if (file_seek(fh, 26, SEEK_CUR, err) == -1)
498                     return -1;
499                 padlen = 26;
500                 offset += padlen;
501             } else {
502                 padlen = 0;
503             }
504             break;
505
506         case NETTL_SUBSYS_NS_LS_DRIVER :
507             /* XXX we dont know how to identify this as ethernet frames, so
508                we assumes everything is. We will crash and burn for anything else */
509             /* for encapsulated 100baseT we do this */
510             phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
511             bytes_read = file_read(&drv_eth_hdr, 1, NS_LS_DRV_ETH_HDR_LEN, fh);
512             if (bytes_read != NS_LS_DRV_ETH_HDR_LEN) {
513                 *err = file_error(fh);
514                 if (*err == 0)
515                     *err = WTAP_ERR_SHORT_READ;
516                 return -1;
517             }
518             offset += NS_LS_DRV_ETH_HDR_LEN;
519
520             length = pntohs(&drv_eth_hdr.length); 
521             caplen = pntohs(&drv_eth_hdr.caplen);
522             /*
523              * XXX - is there a length field that would give the length
524              * of this header, so that we don't have to check for
525              * nettl files from HP-UX 11?
526              *
527              * And what are the extra two bytes?
528              */
529             if (wth->capture.nettl->is_hpux_11) {
530                 if (file_seek(fh, 2, SEEK_CUR, err) == -1) return -1;
531                 offset += 2;
532             }
533             padlen = 0;
534             break;
535
536         case NETTL_SUBSYS_SX25L2:
537         case NETTL_SUBSYS_SX25L3:
538             /*
539              * XXX - is the 24-byte padding actually a header with
540              * packet lengths, time stamps, etc., just as is the case
541              * for NETTL_SUBSYS_NS_LS_DRIVER?  It might be
542              *
543              *    guint8        caplen[2];
544              *    guint8        length[2];
545              *    guint8        xxc[4];
546              *    guint8        sec[4];
547              *    guint8        usec[4];
548              *    guint8        xxd[4];
549              *
550              * or something such as that - if it has 4 bytes before that
551              * (making it 24 bytes), it'd be like struct
552              * nettlrec_ns_ls_drv_eth_hdr but with 2 more bytes at the end.
553              *
554              * And is "from_dce" at xxa[0] in the nettlrec_hdr structure?
555              */
556             phdr->pkt_encap = WTAP_ENCAP_NETTL_X25;
557             length = pntohl(&rec_hdr.length);
558             caplen = pntohl(&rec_hdr.caplen);
559             padlen = 24;        /* sizeof (struct nettlrec_sx25l2_hdr) - NETTL_REC_HDR_LEN + 4 */
560             if (file_seek(fh, padlen, SEEK_CUR, err) == -1)
561                 return -1;
562             offset += padlen;
563             break;
564
565         default:
566             wth->file_encap = WTAP_ENCAP_PER_PACKET;
567             phdr->pkt_encap = WTAP_ENCAP_NETTL_UNKNOWN;
568             length = pntohl(&rec_hdr.length);
569             caplen = pntohl(&rec_hdr.caplen);
570             padlen = 0;
571             break;
572     }
573
574     if (length <= padlen) {
575         *err = WTAP_ERR_BAD_RECORD;
576         *err_info = g_strdup_printf("nettl: packet length %u in record header too short, <= %u",
577             length, padlen);
578         return -1;
579     }
580     phdr->len = length - padlen;
581     if (caplen <= padlen) {
582         *err = WTAP_ERR_BAD_RECORD;
583         *err_info = g_strdup_printf("nettl: captured length %u in record header too short, <= %u",
584             caplen, padlen);
585         return -1;
586     }
587     phdr->caplen = caplen - padlen;
588     phdr->ts.secs = pntohl(&rec_hdr.sec);
589     phdr->ts.nsecs = pntohl(&rec_hdr.usec) * 1000;
590
591     pseudo_header->nettl.subsys   = subsys;
592     pseudo_header->nettl.devid    = pntohl(&rec_hdr.devid);
593     pseudo_header->nettl.kind     = pntohl(&rec_hdr.kind);
594     pseudo_header->nettl.pid      = pntohl(&rec_hdr.pid);
595     pseudo_header->nettl.uid      = pntohs(&rec_hdr.uid);
596
597     return offset;
598 }
599
600 static gboolean
601 nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err, gboolean fddihack)
602 {
603     int bytes_read;
604     guchar *p=NULL;
605     guint8 dummy[3];
606
607     if (fddihack == TRUE) {
608        /* read in FC, dest, src, DSAP and SSAP */
609        if (file_read(pd, 1, 15, fh) == 15) {
610           if (pd[13] == 0xAA) {
611              /* it's SNAP, have to eat 3 bytes??? */
612              if (file_read(dummy, 1, 3, fh) == 3) {
613                 p=pd+15;
614                 bytes_read = file_read(p, 1, length-18, fh);
615                 bytes_read += 18;
616              } else {
617                 bytes_read = -1;
618              }
619           } else {
620              /* not SNAP */
621              p=pd+15;
622              bytes_read = file_read(p, 1, length-15, fh);
623              bytes_read += 15;
624           }
625        } else
626           bytes_read = -1;
627     } else
628        bytes_read = file_read(pd, 1, length, fh);
629
630     if (bytes_read != length) {
631         *err = file_error(fh);
632         if (*err == 0)
633             *err = WTAP_ERR_SHORT_READ;
634         return FALSE;
635     }
636     return TRUE;
637 }
638
639 static void nettl_close(wtap *wth)
640 {
641     g_free(wth->capture.nettl);
642 }
643
644
645 /* Returns 0 if we could write the specified encapsulation type,
646    an error indication otherwise.  nettl files are WTAP_ENCAP_UNKNOWN
647    when they are first opened, so we allow that for tshark read/write.
648  */
649
650 int nettl_dump_can_write_encap(int encap)
651 {
652
653         switch (encap) {
654                 case WTAP_ENCAP_ETHERNET:
655                 case WTAP_ENCAP_FDDI_BITSWAPPED:
656                 case WTAP_ENCAP_TOKEN_RING:
657                 case WTAP_ENCAP_NETTL_ETHERNET:
658                 case WTAP_ENCAP_NETTL_FDDI:
659                 case WTAP_ENCAP_NETTL_TOKEN_RING:
660                 case WTAP_ENCAP_NETTL_RAW_IP:
661                 case WTAP_ENCAP_NETTL_RAW_ICMP:
662                 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
663 /*
664                 case WTAP_ENCAP_NETTL_X25:
665 */
666                 case WTAP_ENCAP_PER_PACKET:
667                 case WTAP_ENCAP_UNKNOWN:
668                 case WTAP_ENCAP_NETTL_UNKNOWN:
669                         return 0;
670                 default:
671                         return WTAP_ERR_UNSUPPORTED_ENCAP;
672         }
673 }
674
675
676 /* Returns TRUE on success, FALSE on failure;
677    sets "*err" to an error code on failure */
678 gboolean nettl_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
679 {
680         struct nettl_file_hdr file_hdr;
681         size_t nwritten;
682
683         /* This is a nettl file */
684         wdh->subtype_write = nettl_dump;
685         wdh->subtype_close = NULL;
686
687         /* Write the file header. */
688         memset(&file_hdr,0,sizeof(file_hdr));
689         memcpy(file_hdr.magic,nettl_magic_hpux10,sizeof(file_hdr.magic));
690         strcpy(file_hdr.file_name,"/tmp/wireshark.TRC000");
691         strcpy(file_hdr.tz,"UTC");
692         strcpy(file_hdr.host_name,"");
693         strcpy(file_hdr.os_vers,"B.11.11");
694         file_hdr.os_v=0x55;
695         strcpy(file_hdr.model,"9000/800");
696         file_hdr.unknown=g_htons(0x406);
697         nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
698         if (nwritten != sizeof(file_hdr)) {
699                 if (nwritten == 0 && ferror(wdh->fh))
700                         *err = errno;
701                 else
702                         *err = WTAP_ERR_SHORT_WRITE;
703                 return FALSE;
704         }
705         wdh->bytes_dumped += sizeof(file_hdr);
706
707         return TRUE;
708 }
709
710 /* Write a record for a packet to a dump file.
711    Returns TRUE on success, FALSE on failure. */
712 static gboolean nettl_dump(wtap_dumper *wdh,
713         const struct wtap_pkthdr *phdr,
714         const union wtap_pseudo_header *pseudo_header _U_,
715         const guchar *pd, int *err)
716 {
717         struct nettlrec_hdr rec_hdr;
718         size_t nwritten;
719         guint8 dummyc[24];
720
721         memset(&rec_hdr,0,sizeof(rec_hdr));
722         /* HP-UX 11.X header should be 68 bytes */
723         rec_hdr.hdr_len = g_htons(sizeof(rec_hdr) + 4);
724         rec_hdr.kind = g_htonl(NETTL_HDR_PDUIN);
725         rec_hdr.sec = g_htonl(phdr->ts.secs);
726         rec_hdr.usec = g_htonl(phdr->ts.nsecs/1000);
727         rec_hdr.caplen = g_htonl(phdr->caplen);
728         rec_hdr.length = g_htonl(phdr->len);
729         rec_hdr.devid = -1;
730         rec_hdr.pid = -1;
731         rec_hdr.uid = -1;
732
733         switch (phdr->pkt_encap) {
734
735                 case WTAP_ENCAP_NETTL_FDDI:
736                         /* account for pad bytes */
737                         rec_hdr.caplen = g_htonl(phdr->caplen + 3);
738                         rec_hdr.length = g_htonl(phdr->len + 3);
739                         /* fall through and fill the rest of the fields */
740                 case WTAP_ENCAP_NETTL_ETHERNET:
741                 case WTAP_ENCAP_NETTL_TOKEN_RING:
742                 case WTAP_ENCAP_NETTL_RAW_IP:
743                 case WTAP_ENCAP_NETTL_RAW_ICMP:
744                 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
745                 case WTAP_ENCAP_NETTL_UNKNOWN:
746                         rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
747                         rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
748                         rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
749                         rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
750                         rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
751                         break;
752
753                 case WTAP_ENCAP_RAW_IP:
754                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_NS_LS_IP);
755                         break;
756
757                 case WTAP_ENCAP_ETHERNET:
758                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_BTLAN);
759                         break;
760
761                 case WTAP_ENCAP_FDDI_BITSWAPPED:
762                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_FDDI);
763                         /* account for pad bytes */
764                         rec_hdr.caplen = g_htonl(phdr->caplen + 3);
765                         rec_hdr.length = g_htonl(phdr->len + 3);
766                         break;
767
768                 case WTAP_ENCAP_TOKEN_RING:
769                         rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_TR);
770                         break;
771 /*      
772                 case WTAP_ENCAP_NETTL_X25:
773                         rec_hdr.caplen = g_htonl(phdr->caplen + 24);
774                         rec_hdr.length = g_htonl(phdr->len + 24);
775                         rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
776                         rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
777                         rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
778                         rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
779                         rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
780                         break;
781 */
782                 default:
783                         /* found one we don't support */
784                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
785                         return FALSE;
786         }
787
788         nwritten = fwrite(&rec_hdr, 1, sizeof(rec_hdr), wdh->fh);
789         if (nwritten != sizeof(rec_hdr)) {
790                 if (nwritten == 0 && ferror(wdh->fh))
791                         *err = errno;
792                 else
793                         *err = WTAP_ERR_SHORT_WRITE;
794                 return FALSE;
795         }
796         wdh->bytes_dumped += sizeof(rec_hdr);
797
798         /* Write out 4 extra bytes of unknown stuff for HP-UX11
799          * header format.
800          */
801         memset(dummyc, 0, sizeof dummyc);
802         nwritten = fwrite(dummyc, 1, 4, wdh->fh);
803         if (nwritten != 4) {
804                 if (nwritten == 0 && ferror(wdh->fh))
805                         *err = errno;
806                 else
807                         *err = WTAP_ERR_SHORT_WRITE;
808                 return FALSE;
809         }
810         wdh->bytes_dumped += 4;
811
812         if ((phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) ||
813             (phdr->pkt_encap == WTAP_ENCAP_NETTL_FDDI)) {
814                 /* add those weird 3 bytes of padding */
815                 nwritten = fwrite(dummyc, 1, 3, wdh->fh);
816                 if (nwritten != 3) {
817                         if (nwritten == 0 && ferror(wdh->fh))
818                                 *err = errno;
819                         else
820                                 *err = WTAP_ERR_SHORT_WRITE;
821                         return FALSE;
822                 }
823                 wdh->bytes_dumped += 3;
824         }
825 /*
826         } else if (phdr->pkt_encap == WTAP_ENCAP_NETTL_X25) {
827                 nwritten = fwrite(dummyc, 1, 24, wdh->fh);
828                 if (nwritten != 24) {
829                         if (nwritten == 0 && ferror(wdh->fh))
830                                 *err = errno;
831                         else
832                                 *err = WTAP_ERR_SHORT_WRITE;
833                         return FALSE;
834                 }
835                 wdh->bytes_dumped += 24;
836         }
837 */
838
839         /* write actual PDU data */
840
841         nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
842         if (nwritten != phdr->caplen) {
843                 if (nwritten == 0 && ferror(wdh->fh))
844                         *err = errno;
845                 else
846                         *err = WTAP_ERR_SHORT_WRITE;
847                 return FALSE;
848         }
849         wdh->bytes_dumped += phdr->caplen;
850
851         return TRUE;
852 }