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