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