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