2 * Copyright (c) 2003 Endace Technology Ltd, Hamilton, New Zealand.
5 * This software and documentation has been developed by Endace Technology Ltd.
6 * along with the DAG PCI network capture cards. For further information please
7 * visit http://www.endace.com/.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. The name of Endace Technology Ltd may not be used to endorse or promote
20 * products derived from this software without specific prior written
23 * THIS SOFTWARE IS PROVIDED BY ENDACE TECHNOLOGY LTD ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
26 * EVENT SHALL ENDACE TECHNOLOGY LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
38 * erf - Endace ERF (Extensible Record Format)
42 * http://www.endace.com/support/EndaceRecordFormat.pdf
43 * (mirror: https://bugs.wireshark.org/bugzilla/attachment.cgi?id=4333) (bug #4484)
53 #include <wsutil/crc32.h>
56 #include "file_wrappers.h"
58 #include "pcap-encap.h"
62 static int erf_read_header(FILE_T fh
,
63 struct wtap_pkthdr
*phdr
,
64 erf_header_t
*erf_header
,
68 guint32
*packet_size
);
69 static gboolean
erf_read(wtap
*wth
, int *err
, gchar
**err_info
,
71 static gboolean
erf_seek_read(wtap
*wth
, gint64 seek_off
,
72 struct wtap_pkthdr
*phdr
, Buffer
*buf
,
73 int length
, int *err
, gchar
**err_info
);
78 } erf_to_wtap_map
[] = {
79 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_CHDLC
},
80 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_HHDLC
},
81 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_CHDLC_WITH_PHDR
},
82 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_PPP
},
83 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_FRELAY
},
84 { ERF_TYPE_HDLC_POS
, WTAP_ENCAP_MTP2
},
85 { ERF_TYPE_ETH
, WTAP_ENCAP_ETHERNET
},
86 { 99, WTAP_ENCAP_ERF
}, /*this type added so WTAP_ENCAP_ERF will work and then be treated at ERF->ERF*/
89 #define NUM_ERF_ENCAPS (sizeof erf_to_wtap_map / sizeof erf_to_wtap_map[0])
91 extern int erf_open(wtap
*wth
, int *err
, gchar
**err_info
)
93 int i
, n
, records_for_erf_check
= RECORDS_FOR_ERF_CHECK
;
96 erf_timestamp_t prevts
,ts
;
102 guint64 erf_ext_header
;
107 memset(&prevts
, 0, sizeof(prevts
));
109 /* number of records to scan before deciding if this really is ERF */
110 if ((s
= getenv("ERF_RECORDS_TO_CHECK")) != NULL
) {
111 if ((n
= atoi(s
)) > 0 && n
< 101) {
112 records_for_erf_check
= n
;
117 * ERF is a little hard because there's no magic number; we look at
118 * the first few records and see if they look enough like ERF
122 for (i
= 0; i
< records_for_erf_check
; i
++) { /* records_for_erf_check */
124 r
= file_read(&header
,sizeof(header
),wth
->fh
);
127 if (r
!= sizeof(header
)) {
128 *err
= file_error(wth
->fh
, err_info
);
129 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
) {
132 /* ERF header too short accept the file,
133 only if the very first records have been successfully checked */
134 if (i
< MIN_RECORDS_FOR_ERF_CHECK
) {
137 /* BREAK, the last record is too short, and will be ignored */
143 rlen
=g_ntohs(header
.rlen
);
145 /* fail on invalid record type, invalid rlen, timestamps decreasing, or incrementing too far */
147 /* Test valid rlen >= 16 */
152 packet_size
= rlen
- (guint32
)sizeof(header
);
153 if (packet_size
> WTAP_MAX_PACKET_SIZE
) {
155 * Probably a corrupt capture file or a file that's not an ERF file
156 * but that passed earlier tests; don't blow up trying
157 * to allocate space for an immensely-large packet.
162 /* Skip PAD records, timestamps may not be set */
163 if ((header
.type
& 0x7F) == ERF_TYPE_PAD
) {
164 if (file_seek(wth
->fh
, packet_size
, SEEK_CUR
, err
) == -1) {
170 /* fail on invalid record type, decreasing timestamps or non-zero pad-bits */
171 /* Not all types within this range are decoded, but it is a first filter */
172 if ((header
.type
& 0x7F) == 0 || (header
.type
& 0x7F) > ERF_TYPE_MAX
) {
176 /* The ERF_TYPE_MAX is the PAD record, but the last used type is ERF_TYPE_INFINIBAND_LINK */
177 if ((header
.type
& 0x7F) > ERF_TYPE_INFINIBAND_LINK
) {
181 if ((ts
= pletohll(&header
.ts
)) < prevts
) {
182 /* reassembled AALx records may not be in time order, also records are not in strict time order between physical interfaces, so allow 1 sec fudge */
183 if ( ((prevts
-ts
)>>32) > 1 ) {
188 /* Check to see if timestamp increment is > 1 week */
189 if ( (valid_prev
) && (ts
> prevts
) && (((ts
-prevts
)>>32) > 3600*24*7) ) {
193 memcpy(&prevts
, &ts
, sizeof(prevts
));
195 /* Read over the extension headers */
198 if (file_read(&erf_ext_header
, sizeof(erf_ext_header
),wth
->fh
) != sizeof(erf_ext_header
)) {
199 *err
= file_error(wth
->fh
, err_info
);
201 *err
= WTAP_ERR_SHORT_READ
;
204 packet_size
-= (guint32
)sizeof(erf_ext_header
);
205 memcpy(&type
, &erf_ext_header
, sizeof(type
));
209 /* Read over MC or ETH subheader */
210 switch(header
.type
& 0x7F) {
211 case ERF_TYPE_MC_HDLC
:
212 case ERF_TYPE_MC_RAW
:
213 case ERF_TYPE_MC_ATM
:
214 case ERF_TYPE_MC_RAW_CHANNEL
:
215 case ERF_TYPE_MC_AAL5
:
216 case ERF_TYPE_MC_AAL2
:
217 case ERF_TYPE_COLOR_MC_HDLC_POS
:
218 case ERF_TYPE_AAL2
: /* not an MC type but has a similar 'AAL2 ext' header */
219 if (file_read(&mc_hdr
,sizeof(mc_hdr
),wth
->fh
) != sizeof(mc_hdr
)) {
220 *err
= file_error(wth
->fh
, err_info
);
223 packet_size
-= (guint32
)sizeof(mc_hdr
);
226 case ERF_TYPE_COLOR_ETH
:
227 case ERF_TYPE_DSM_COLOR_ETH
:
228 if (file_read(ð_hdr
,sizeof(eth_hdr
),wth
->fh
) != sizeof(eth_hdr
)) {
229 *err
= file_error(wth
->fh
, err_info
);
232 packet_size
-= (guint32
)sizeof(eth_hdr
);
238 /* The file_seek function do not return an error if the end of file
239 is reached whereas the record is truncated */
240 if (packet_size
> WTAP_MAX_PACKET_SIZE
) {
242 * Probably a corrupt capture file; don't blow up trying
243 * to allocate space for an immensely-large packet.
247 buffer
=(gchar
*)g_malloc(packet_size
);
248 r
= file_read(buffer
, packet_size
, wth
->fh
);
251 if (r
!= packet_size
) {
252 /* ERF record too short, accept the file,
253 only if the very first records have been successfully checked */
254 if (i
< MIN_RECORDS_FOR_ERF_CHECK
) {
261 } /* records_for_erf_check */
263 if (file_seek(wth
->fh
, 0L, SEEK_SET
, err
) == -1) { /* rewind */
267 /* This is an ERF file */
268 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_ERF
;
269 wth
->snapshot_length
= 0; /* not available in header, only in frame */
272 * Use the encapsulation for ERF records.
274 wth
->file_encap
= WTAP_ENCAP_ERF
;
276 wth
->subtype_read
= erf_read
;
277 wth
->subtype_seek_read
= erf_seek_read
;
278 wth
->tsprecision
= WTAP_FILE_TSPREC_NSEC
;
280 erf_populate_interfaces(wth
);
285 /* Read the next packet */
286 static gboolean
erf_read(wtap
*wth
, int *err
, gchar
**err_info
,
289 erf_header_t erf_header
;
290 guint32 packet_size
, bytes_read
;
292 *data_offset
= file_tell(wth
->fh
);
295 if (!erf_read_header(wth
->fh
,
296 &wth
->phdr
, &erf_header
,
297 err
, err_info
, &bytes_read
, &packet_size
)) {
301 if (!wtap_read_packet_bytes(wth
->fh
, wth
->frame_buffer
, packet_size
,
305 } while ( erf_header
.type
== ERF_TYPE_PAD
);
310 static gboolean
erf_seek_read(wtap
*wth
, gint64 seek_off
,
311 struct wtap_pkthdr
*phdr
, Buffer
*buf
,
312 int length _U_
, int *err
, gchar
**err_info
)
314 erf_header_t erf_header
;
317 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
321 if (!erf_read_header(wth
->random_fh
, phdr
, &erf_header
,
322 err
, err_info
, NULL
, &packet_size
))
324 } while ( erf_header
.type
== ERF_TYPE_PAD
);
326 return wtap_read_packet_bytes(wth
->random_fh
, buf
, packet_size
,
330 static int erf_read_header(FILE_T fh
,
331 struct wtap_pkthdr
*phdr
,
332 erf_header_t
*erf_header
,
336 guint32
*packet_size
)
338 union wtap_pseudo_header
*pseudo_header
= &phdr
->pseudo_header
;
341 guint64 erf_exhdr_sw
;
346 int max
= sizeof(pseudo_header
->erf
.ehdr_list
)/sizeof(struct erf_ehdr
);
348 wtap_file_read_expected_bytes(erf_header
, sizeof(*erf_header
), fh
, err
,
350 if (bytes_read
!= NULL
) {
351 *bytes_read
= sizeof(*erf_header
);
354 *packet_size
= g_ntohs(erf_header
->rlen
) - (guint32
)sizeof(*erf_header
);
356 if (*packet_size
> WTAP_MAX_PACKET_SIZE
) {
358 * Probably a corrupt capture file; don't blow up trying
359 * to allocate space for an immensely-large packet.
361 *err
= WTAP_ERR_BAD_FILE
;
362 *err_info
= g_strdup_printf("erf: File has %u-byte packet, bigger than maximum of %u",
363 *packet_size
, WTAP_MAX_PACKET_SIZE
);
367 if (*packet_size
== 0) {
368 /* If this isn't a pad record, it's a corrupt packet; bail out */
369 if ((erf_header
->type
& 0x7F) != ERF_TYPE_PAD
) {
370 *err
= WTAP_ERR_BAD_FILE
;
371 *err_info
= g_strdup_printf("erf: File has 0 byte packet");
378 guint64 ts
= pletohll(&erf_header
->ts
);
380 phdr
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
|WTAP_HAS_INTERFACE_ID
;
381 phdr
->ts
.secs
= (long) (ts
>> 32);
382 ts
= ((ts
& 0xffffffff) * 1000 * 1000 * 1000);
383 ts
+= (ts
& 0x80000000) << 1; /* rounding */
384 phdr
->ts
.nsecs
= ((int) (ts
>> 32));
385 if (phdr
->ts
.nsecs
>= 1000000000) {
386 phdr
->ts
.nsecs
-= 1000000000;
389 phdr
->interface_id
= (erf_header
->flags
& 0x03);
392 /* Copy the ERF pseudo header */
393 memset(&pseudo_header
->erf
, 0, sizeof(pseudo_header
->erf
));
394 pseudo_header
->erf
.phdr
.ts
= pletohll(&erf_header
->ts
);
395 pseudo_header
->erf
.phdr
.type
= erf_header
->type
;
396 pseudo_header
->erf
.phdr
.flags
= erf_header
->flags
;
397 pseudo_header
->erf
.phdr
.rlen
= g_ntohs(erf_header
->rlen
);
398 pseudo_header
->erf
.phdr
.lctr
= g_ntohs(erf_header
->lctr
);
399 pseudo_header
->erf
.phdr
.wlen
= g_ntohs(erf_header
->wlen
);
401 /* Copy the ERF extension header into the pseudo header */
402 type
= erf_header
->type
;
404 wtap_file_read_expected_bytes(&erf_exhdr
, sizeof(erf_exhdr
), fh
, err
,
406 if (bytes_read
!= NULL
)
407 *bytes_read
+= (guint32
)sizeof(erf_exhdr
);
408 *packet_size
-= (guint32
)sizeof(erf_exhdr
);
409 skiplen
+= (guint32
)sizeof(erf_exhdr
);
410 erf_exhdr_sw
= pntohll(erf_exhdr
);
412 memcpy(&pseudo_header
->erf
.ehdr_list
[i
].ehdr
, &erf_exhdr_sw
, sizeof(erf_exhdr_sw
));
417 switch (erf_header
->type
& 0x7F) {
420 case ERF_TYPE_RAW_LINK
:
421 case ERF_TYPE_INFINIBAND
:
422 case ERF_TYPE_INFINIBAND_LINK
:
425 phdr
->len
= g_htons(erf_header
->wlen
);
426 phdr
->caplen
= g_htons(erf_header
->wlen
);
432 case ERF_TYPE_HDLC_POS
:
433 case ERF_TYPE_COLOR_HDLC_POS
:
434 case ERF_TYPE_DSM_COLOR_HDLC_POS
:
440 case ERF_TYPE_COLOR_ETH
:
441 case ERF_TYPE_DSM_COLOR_ETH
:
442 wtap_file_read_expected_bytes(ð_hdr
, sizeof(eth_hdr
), fh
, err
,
444 if (bytes_read
!= NULL
)
445 *bytes_read
+= (guint32
)sizeof(eth_hdr
);
446 *packet_size
-= (guint32
)sizeof(eth_hdr
);
447 skiplen
+= (guint32
)sizeof(eth_hdr
);
448 pseudo_header
->erf
.subhdr
.eth_hdr
= g_htons(eth_hdr
);
451 case ERF_TYPE_MC_HDLC
:
452 case ERF_TYPE_MC_RAW
:
453 case ERF_TYPE_MC_ATM
:
454 case ERF_TYPE_MC_RAW_CHANNEL
:
455 case ERF_TYPE_MC_AAL5
:
456 case ERF_TYPE_MC_AAL2
:
457 case ERF_TYPE_COLOR_MC_HDLC_POS
:
458 case ERF_TYPE_AAL2
: /* not an MC type but has a similar 'AAL2 ext' header */
459 wtap_file_read_expected_bytes(&mc_hdr
, sizeof(mc_hdr
), fh
, err
,
461 if (bytes_read
!= NULL
)
462 *bytes_read
+= (guint32
)sizeof(mc_hdr
);
463 *packet_size
-= (guint32
)sizeof(mc_hdr
);
464 skiplen
+= (guint32
)sizeof(mc_hdr
);
465 pseudo_header
->erf
.subhdr
.mc_hdr
= g_htonl(mc_hdr
);
468 case ERF_TYPE_IP_COUNTER
:
469 case ERF_TYPE_TCP_FLOW_COUNTER
:
470 /* unsupported, continue with default: */
472 *err
= WTAP_ERR_UNSUPPORTED_ENCAP
;
473 *err_info
= g_strdup_printf("erf: unknown record encapsulation %u",
479 phdr
->len
= g_htons(erf_header
->wlen
);
480 phdr
->caplen
= MIN( g_htons(erf_header
->wlen
),
481 g_htons(erf_header
->rlen
) - (guint32
)sizeof(*erf_header
) - skiplen
);
484 if (*packet_size
> WTAP_MAX_PACKET_SIZE
) {
486 * Probably a corrupt capture file; don't blow up trying
487 * to allocate space for an immensely-large packet.
489 *err
= WTAP_ERR_BAD_FILE
;
490 *err_info
= g_strdup_printf("erf: File has %u-byte packet, bigger than maximum of %u",
491 *packet_size
, WTAP_MAX_PACKET_SIZE
);
498 static int wtap_wtap_encap_to_erf_encap(int encap
)
501 for(i
= 0; i
< NUM_ERF_ENCAPS
; i
++){
502 if(erf_to_wtap_map
[i
].wtap_encap_value
== encap
)
503 return erf_to_wtap_map
[i
].erf_encap_value
;
508 static gboolean
erf_write_phdr(wtap_dumper
*wdh
, int encap
, const union wtap_pseudo_header
*pseudo_header
, int * err
)
510 guint8 erf_hdr
[sizeof(struct erf_mc_phdr
)];
511 guint8 erf_subhdr
[((sizeof(struct erf_mc_hdr
) > sizeof(struct erf_eth_hdr
))?
512 sizeof(struct erf_mc_hdr
) : sizeof(struct erf_eth_hdr
))];
513 guint8 ehdr
[8*MAX_ERF_EHDR
];
515 size_t subhdr_size
= 0;
521 memset(&erf_hdr
, 0, sizeof(erf_hdr
));
522 phtolell(&erf_hdr
[0], pseudo_header
->erf
.phdr
.ts
);
523 erf_hdr
[8] = pseudo_header
->erf
.phdr
.type
;
524 erf_hdr
[9] = pseudo_header
->erf
.phdr
.flags
;
525 phtons(&erf_hdr
[10], pseudo_header
->erf
.phdr
.rlen
);
526 phtons(&erf_hdr
[12], pseudo_header
->erf
.phdr
.lctr
);
527 phtons(&erf_hdr
[14], pseudo_header
->erf
.phdr
.wlen
);
528 size
= sizeof(struct erf_phdr
);
530 switch(pseudo_header
->erf
.phdr
.type
& 0x7F) {
531 case ERF_TYPE_MC_HDLC
:
532 case ERF_TYPE_MC_RAW
:
533 case ERF_TYPE_MC_ATM
:
534 case ERF_TYPE_MC_RAW_CHANNEL
:
535 case ERF_TYPE_MC_AAL5
:
536 case ERF_TYPE_MC_AAL2
:
537 case ERF_TYPE_COLOR_MC_HDLC_POS
:
538 phtonl(&erf_subhdr
[0], pseudo_header
->erf
.subhdr
.mc_hdr
);
539 subhdr_size
+= (int)sizeof(struct erf_mc_hdr
);
542 case ERF_TYPE_COLOR_ETH
:
543 case ERF_TYPE_DSM_COLOR_ETH
:
544 phtons(&erf_subhdr
[0], pseudo_header
->erf
.subhdr
.eth_hdr
);
545 subhdr_size
+= (int)sizeof(struct erf_eth_hdr
);
555 if (!wtap_dump_file_write(wdh
, erf_hdr
, size
, err
))
557 wdh
->bytes_dumped
+= size
;
559 /*write out up to MAX_ERF_EHDR extension headers*/
560 has_more
= pseudo_header
->erf
.phdr
.type
& 0x80;
561 if(has_more
){ /*we have extension headers*/
563 phtonll(ehdr
+(i
*8), pseudo_header
->erf
.ehdr_list
[i
].ehdr
);
564 if(i
== MAX_ERF_EHDR
-1) ehdr
[i
*8] = ehdr
[i
*8] & 0x7F;
565 has_more
= ehdr
[i
*8] & 0x80;
567 }while(has_more
&& i
< MAX_ERF_EHDR
);
568 if (!wtap_dump_file_write(wdh
, ehdr
, 8*i
, err
))
570 wdh
->bytes_dumped
+= 8*i
;
573 if(!wtap_dump_file_write(wdh
, erf_subhdr
, subhdr_size
, err
))
575 wdh
->bytes_dumped
+= subhdr_size
;
580 static gboolean
erf_dump(
582 const struct wtap_pkthdr
*phdr
,
586 const union wtap_pseudo_header
*pseudo_header
= &phdr
->pseudo_header
;
587 union wtap_pseudo_header other_phdr
;
589 gint64 alignbytes
= 0;
592 gboolean must_add_crc
= FALSE
;
593 guint32 crc32
= 0x00000000;
595 if(wdh
->encap
== WTAP_ENCAP_PER_PACKET
){
596 encap
= phdr
->pkt_encap
;
601 if(encap
== WTAP_ENCAP_ERF
){
602 /* We've been handed an ERF record, so there's not much to do here. */
603 alignbytes
= wdh
->bytes_dumped
+ pseudo_header
->erf
.phdr
.rlen
;
605 if(!erf_write_phdr(wdh
, encap
, pseudo_header
, err
)) return FALSE
;
607 if(!wtap_dump_file_write(wdh
, pd
, phdr
->caplen
, err
)) return FALSE
;
608 wdh
->bytes_dumped
+= phdr
->caplen
;
610 /*XXX: this pads the record to its original length, which is fine in most
611 * cases. However with >MAX_ERF_EHDR unnecessary padding will be added, and
612 * if the record was truncated this will be incorrectly treated as payload.
613 * More than 8 extension headers is unusual though, only the first 8 are
614 * written out anyway and fixing properly would require major refactor.*/
615 while(wdh
->bytes_dumped
< alignbytes
){
616 if(!wtap_dump_file_write(wdh
, "", 1, err
)) return FALSE
;
622 /*generate a fake header in other_phdr using data that we know*/
623 /*covert time erf timestamp format*/
624 other_phdr
.erf
.phdr
.ts
= ((guint64
) phdr
->ts
.secs
<< 32) + (((guint64
) phdr
->ts
.nsecs
<<32) / 1000 / 1000 / 1000);
625 other_phdr
.erf
.phdr
.type
= wtap_wtap_encap_to_erf_encap(encap
);
626 other_phdr
.erf
.phdr
.flags
= 0x4; /*vlen flag set because we're creating variable length records*/
627 other_phdr
.erf
.phdr
.lctr
= 0;
628 /*now we work out rlen, accounting for all the different headers and missing fcs(eth)*/
629 other_phdr
.erf
.phdr
.rlen
= phdr
->caplen
+16;
630 other_phdr
.erf
.phdr
.wlen
= phdr
->len
;
631 switch(other_phdr
.erf
.phdr
.type
){
633 other_phdr
.erf
.phdr
.rlen
+= 2; /*2 bytes for erf eth_type*/
634 if (pseudo_header
->eth
.fcs_len
!= 4) {
635 /* Either this packet doesn't include the FCS
636 (pseudo_header->eth.fcs_len = 0), or we don't
637 know whether it has an FCS (= -1). We have to
639 if(!(phdr
->caplen
< phdr
->len
)){ /*don't add FCS if packet has been snapped off*/
640 crc32
= crc32_ccitt_seed(pd
, phdr
->caplen
, 0xFFFFFFFF);
641 other_phdr
.erf
.phdr
.rlen
+= 4; /*4 bytes for added checksum*/
642 other_phdr
.erf
.phdr
.wlen
+= 4;
647 case ERF_TYPE_HDLC_POS
:
648 /*we assume that it's missing a FCS checksum, make one up*/
649 if(!(phdr
->caplen
< phdr
->len
)){ /*unless of course, the packet has been snapped off*/
650 crc32
= crc32_ccitt_seed(pd
, phdr
->caplen
, 0xFFFFFFFF);
651 other_phdr
.erf
.phdr
.rlen
+= 4; /*4 bytes for added checksum*/
652 other_phdr
.erf
.phdr
.wlen
+= 4;
653 must_add_crc
= TRUE
; /* XXX - these never have an FCS? */
660 alignbytes
= (8 - (other_phdr
.erf
.phdr
.rlen
% 8)) % 8; /*calculate how much padding will be required */
661 if(phdr
->caplen
< phdr
->len
){ /*if packet has been snapped, we need to round down what we output*/
662 round_down
= (8 - (guint
)alignbytes
) % 8;
663 other_phdr
.erf
.phdr
.rlen
-= round_down
;
665 other_phdr
.erf
.phdr
.rlen
+= (gint16
)alignbytes
;
668 if(!erf_write_phdr(wdh
, WTAP_ENCAP_ERF
, &other_phdr
, err
)) return FALSE
;
669 if(!wtap_dump_file_write(wdh
, pd
, phdr
->caplen
- round_down
, err
)) return FALSE
;
670 wdh
->bytes_dumped
+= phdr
->caplen
- round_down
;
672 /*add the 4 byte CRC if necessary*/
674 if(!wtap_dump_file_write(wdh
, &crc32
, 4, err
)) return FALSE
;
675 wdh
->bytes_dumped
+= 4;
677 /*records should be 8byte aligned, so we add padding*/
679 for(i
= (gint16
)alignbytes
; i
> 0; i
--){
680 if(!wtap_dump_file_write(wdh
, "", 1, err
)) return FALSE
;
688 int erf_dump_can_write_encap(int encap
)
691 if(encap
== WTAP_ENCAP_PER_PACKET
)
694 if (wtap_wtap_encap_to_erf_encap(encap
) == -1)
695 return WTAP_ERR_UNSUPPORTED_ENCAP
;
700 int erf_dump_open(wtap_dumper
*wdh
, int *err
)
702 wdh
->subtype_write
= erf_dump
;
703 wdh
->subtype_close
= NULL
;
705 switch(wdh
->file_type_subtype
){
706 case WTAP_FILE_TYPE_SUBTYPE_ERF
:
707 wdh
->tsprecision
= WTAP_FILE_TSPREC_NSEC
;
710 *err
= WTAP_ERR_UNSUPPORTED_FILE_TYPE
;
718 int erf_populate_interfaces(wtap
*wth
)
720 wtapng_if_descr_t int_data
;
726 if (!wth
->interface_data
) {
727 wth
->interface_data
= g_array_new(FALSE
, FALSE
, sizeof(wtapng_if_descr_t
));
730 memset(&int_data
, 0, sizeof(int_data
)); /* Zero all fields */
732 int_data
.wtap_encap
= WTAP_ENCAP_ERF
;
733 /* int_data.time_units_per_second = (1LL<<32); ERF format resolution is 2^-32, capture resolution is unknown */
734 int_data
.time_units_per_second
= 1000000000; /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
735 int_data
.link_type
= wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_ERF
);
736 int_data
.snap_len
= 65535; /* ERF max length */
737 int_data
.opt_comment
= NULL
;
738 /* XXX: if_IPv4addr opt 4 Interface network address and netmask.*/
739 /* XXX: if_IPv6addr opt 5 Interface network address and prefix length (stored in the last byte).*/
740 /* XXX: if_MACaddr opt 6 Interface Hardware MAC address (48 bits).*/
741 /* XXX: if_EUIaddr opt 7 Interface Hardware EUI address (64 bits)*/
742 int_data
.if_speed
= 0; /* Unknown */
743 /* int_data.if_tsresol = 0xa0; ERF format resolution is 2^-32 = 0xa0, capture resolution is unknown */
744 int_data
.if_tsresol
= 0x09; /* XXX Since Wireshark only supports down to nanosecond resolution we have to dilute to this */
745 /* XXX: if_tzone 10 Time zone for GMT support (TODO: specify better). */
746 int_data
.if_filter_str
= NULL
;
747 int_data
.bpf_filter_len
= 0;
748 int_data
.if_filter_bpf_bytes
= NULL
;
749 int_data
.if_os
= NULL
;
750 int_data
.if_fcslen
= 0; /* unknown! */
751 /* XXX if_tsoffset; opt 14 A 64 bits integer value that specifies an offset (in seconds)...*/
752 /* Interface statistics */
753 int_data
.num_stat_entries
= 0;
754 int_data
.interface_statistics
= NULL
;
756 /* Preemptively create interface entries for 4 interfaces, since this is the max number in ERF */
757 for (i
=0; i
<4; i
++) {
758 int_data
.if_name
= g_strdup_printf("Port %c", 'A'+i
);
759 int_data
.if_description
= g_strdup_printf("ERF Interface Id %d (Port %c)", i
, 'A'+i
);
761 g_array_append_val(wth
->interface_data
, int_data
);
762 wth
->number_of_interfaces
++;