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