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