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