6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * Enhancements by Mark C. Brown <mbrown@hp.com>
9 * Copyright (C) 2003, 2005 Hewlett-Packard Development Company, L.P.
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.
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.
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.
34 #include "file_wrappers.h"
38 /* HP nettl file header */
40 /* Magic number size */
43 static guchar nettl_magic_hpux9[MAGIC_SIZE] = {
44 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x00
46 static guchar nettl_magic_hpux10[MAGIC_SIZE] = {
47 0x54, 0x52, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
50 #define FILE_HDR_SIZE 128
52 struct nettl_file_hdr {
53 guchar magic[MAGIC_SIZE];
61 guint16 unknown; /* just padding to 128 bytes? */
64 /* HP nettl record header for the SX25L2 subsystem - The FCS is not included in the file. */
65 struct nettlrec_sx25l2_hdr {
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 {
94 /* Full record header for writing out a nettl file */
95 struct nettlrec_dump_hdr {
98 struct nettlrec_ns_ls_ip_hdr hdr;
102 /* header is followed by data and once again the total length (2 bytes) ! */
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.
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>
116 Each entry starts with 0x0044000b
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)
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.
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.
138 The first header seems to be
139 a normal nettlrec_ns_ls_ip_hdr
141 The header for 100baseT seems to be
150 struct nettlrec_ns_ls_drv_eth_hdr {
161 static gboolean nettl_read(wtap *wth, int *err, gchar **err_info,
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);
175 int nettl_open(wtap *wth, int *err, gchar **err_info _U_)
177 char magic[MAGIC_SIZE], os_vers[2];
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);
192 if (memcmp(magic, nettl_magic_hpux9, MAGIC_SIZE) &&
193 memcmp(magic, nettl_magic_hpux10, MAGIC_SIZE)) {
197 if (file_seek(wth->fh, 0x63, SEEK_SET, err) == -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);
208 if (file_seek(wth->fh, FILE_HDR_SIZE, SEEK_SET, err) == -1)
210 wth->data_offset = FILE_HDR_SIZE;
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;
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 */
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) {
229 if (bytes_read != 0) {
230 *err = WTAP_ERR_SHORT_READ;
231 g_free(wth->capture.nettl);
237 subsys = g_ntohs(dummy[1]);
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;
245 case NETTL_SUBSYS_TOKEN :
246 case NETTL_SUBSYS_PCI_TR :
247 wth->file_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
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;
257 /* If this assumption is bad, the read will catch it */
258 wth->file_encap = WTAP_ENCAP_NETTL_ETHERNET;
261 if (file_seek(wth->fh, FILE_HDR_SIZE, SEEK_SET, err) == -1) {
262 g_free(wth->capture.nettl);
265 wth->data_offset = FILE_HDR_SIZE;
266 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
271 /* Read the next packet */
272 static gboolean nettl_read(wtap *wth, int *err, gchar **err_info,
276 gboolean fddihack=FALSE;
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);
283 /* Read error or EOF */
286 wth->data_offset += ret;
289 * If the per-file encapsulation isn't known, set it to this
290 * packet's encapsulation.
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.
296 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
297 wth->file_encap = wth->phdr.pkt_encap;
299 if (wth->file_encap != wth->phdr.pkt_encap)
300 wth->file_encap = WTAP_ENCAP_PER_PACKET;
304 * Read the packet data.
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;
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)
320 struct wtap_pkthdr phdr;
321 gboolean fddihack=FALSE;
323 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
326 /* Read record header. */
327 ret = nettl_read_rec_header(wth, wth->random_fh, &phdr, pseudo_header,
328 err, err_info, &fddihack);
330 /* Read error or EOF */
332 /* EOF means "short read" in random-access mode */
333 *err = WTAP_ERR_SHORT_READ;
339 * Read the packet data.
341 return nettl_read_rec_data(wth->random_fh, pd, length, err, fddihack);
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)
350 struct nettlrec_ns_ls_ip_hdr ip_hdr;
351 struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
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;
372 subsys = g_ntohs(dummy[1]);
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;
421 phdr->pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
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;
434 offset += sizeof ip_hdr;
436 /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
438 if (wth->capture.nettl->is_hpux_11) {
439 if (file_seek(fh, 4, SEEK_CUR, err) == -1) return -1;
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
451 length = pntohl(&ip_hdr.length);
452 if (length <= 0) return 0;
454 phdr->caplen = pntohl(&ip_hdr.caplen);
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;
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;
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;
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;
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;
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;
499 length = pntohl(&ip_hdr.length);
500 if (length <= 0) return 0;
502 phdr->caplen = pntohl(&ip_hdr.caplen);
505 phdr->ts.secs = pntohl(&ip_hdr.sec);
506 phdr->ts.nsecs = pntohl(&ip_hdr.usec) * 1000;
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;
520 offset += sizeof ip_hdr;
522 /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
524 if (wth->capture.nettl->is_hpux_11) {
525 if (file_seek(fh, 4, SEEK_CUR, err) == -1) return -1;
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;
543 offset += sizeof drv_eth_hdr;
545 length = pntohs(&drv_eth_hdr.length);
546 if (length <= 0) return 0;
548 phdr->caplen = pntohs(&drv_eth_hdr.caplen);
550 phdr->ts.secs = pntohl(&ip_hdr.sec);
551 phdr->ts.nsecs = pntohl(&ip_hdr.usec) * 1000;
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;
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)
577 if (file_seek(fh, padlen, SEEK_CUR, err) == -1) return -1;
579 phdr->pkt_encap = WTAP_ENCAP_NETTL_X25;
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;
595 offset += sizeof ip_hdr;
596 length = pntohl(&ip_hdr.length);
597 if (length <= 0) return 0;
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;
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);
618 nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err, gboolean fddihack)
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) {
631 bytes_read = file_read(p, 1, length-18, fh);
639 bytes_read = file_read(p, 1, length-15, fh);
645 bytes_read = file_read(pd, 1, length, fh);
647 if (bytes_read != length) {
648 *err = file_error(fh);
650 *err = WTAP_ERR_SHORT_READ;
656 static void nettl_close(wtap *wth)
658 g_free(wth->capture.nettl);
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.
667 int nettl_dump_can_write_encap(int 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:
681 case WTAP_ENCAP_NETTL_X25:
683 case WTAP_ENCAP_PER_PACKET:
684 case WTAP_ENCAP_UNKNOWN:
685 case WTAP_ENCAP_NETTL_UNKNOWN:
688 return WTAP_ERR_UNSUPPORTED_ENCAP;
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)
697 struct nettl_file_hdr file_hdr;
700 /* This is a nettl file */
701 wdh->subtype_write = nettl_dump;
702 wdh->subtype_close = NULL;
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");
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))
719 *err = WTAP_ERR_SHORT_WRITE;
722 wdh->bytes_dumped += sizeof(file_hdr);
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)
734 struct nettlrec_dump_hdr rec_hdr;
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;
749 switch (phdr->pkt_encap) {
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);
769 case WTAP_ENCAP_RAW_IP:
770 rec_hdr.subsys = g_htons(NETTL_SUBSYS_NS_LS_IP);
773 case WTAP_ENCAP_ETHERNET:
774 rec_hdr.subsys = g_htons(NETTL_SUBSYS_BTLAN);
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);
784 case WTAP_ENCAP_TOKEN_RING:
785 rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_TR);
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);
799 /* found one we don't support */
800 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
804 nwritten = fwrite(&rec_hdr, 1, sizeof(rec_hdr), wdh->fh);
805 if (nwritten != sizeof(rec_hdr)) {
806 if (nwritten == 0 && ferror(wdh->fh))
809 *err = WTAP_ERR_SHORT_WRITE;
812 wdh->bytes_dumped += sizeof(rec_hdr);
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);
819 if (nwritten == 0 && ferror(wdh->fh))
822 *err = WTAP_ERR_SHORT_WRITE;
825 wdh->bytes_dumped += 3;
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))
834 *err = WTAP_ERR_SHORT_WRITE;
837 wdh->bytes_dumped += 24;
841 /* write actual PDU data */
843 nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
844 if (nwritten != phdr->caplen) {
845 if (nwritten == 0 && ferror(wdh->fh))
848 *err = WTAP_ERR_SHORT_WRITE;
851 wdh->bytes_dumped += phdr->caplen;