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