5 /***************************************************************************
6 network_instruments.c - description
8 begin : Wed Oct 29 2003
9 copyright : (C) 2003 by root
10 email : scotte[AT}netinst.com
11 ***************************************************************************/
13 /***************************************************************************
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
20 ***************************************************************************/
30 #include "file_wrappers.h"
32 #include "network_instruments.h"
34 static const char network_instruments_magic[] = {"ObserverPktBufferVersion=15.00"};
35 static const int true_magic_length = 17;
37 static const guint32 observer_packet_magic = 0x88888888;
40 * This structure is used to keep state when writing files. An instance is
41 * allocated for each file, and its address is stored in the wtap_dumper.priv
48 } observer_dump_private_state;
51 * Some time offsets are calculated in advance here, when the first Observer
52 * file is opened for reading or writing, and are then used to adjust frame
53 * timestamps as they are read or written.
55 * The Wiretap API expects timestamps in nanoseconds relative to
56 * January 1, 1970, 00:00:00 GMT (the Wiretap epoch).
58 * Observer versions before 13.10 encode frame timestamps in nanoseconds
59 * relative to January 1, 2000, 00:00:00 local time (the Observer epoch).
60 * Versions 13.10 and later switch over to GMT encoding. Which encoding was used
61 * when saving the file is identified via the time format TLV following
64 * Unfortunately, even though Observer versions before 13.10 saved in local
65 * time, they didn't include the timezone from which the frames were captured,
66 * so converting to GMT correctly from all timezones is impossible. So an
67 * assumption is made that the file is being read from within the same timezone
68 * that it was written.
70 * All code herein is normalized to versions 13.10 and later, special casing for
71 * versions earlier. In other words, timestamps are worked with as if
72 * they are GMT-encoded, and adjustments from local time are made only if
73 * the source file warrants it.
75 * All destination files are saved in GMT format.
77 static const time_t ansi_to_observer_epoch_offset = 946684800;
78 static time_t gmt_to_localtime_offset = (time_t) -1;
80 static void init_gmt_to_localtime_offset(void)
82 if (gmt_to_localtime_offset == (time_t) -1) {
83 time_t ansi_epoch_plus_one_day = 86400;
88 * Compute the local time zone offset as the number of seconds west
89 * of GMT. There's no obvious cross-platform API for querying this
90 * directly. As a workaround, GMT and local tm structures are populated
91 * relative to the ANSI time_t epoch (plus one day to ensure that
92 * local time stays after 1970/1/1 00:00:00). They are then converted
93 * back to time_t as if they were both local times, resulting in the
94 * time zone offset being the difference between them.
96 gmt_tm = *gmtime(&ansi_epoch_plus_one_day);
97 local_tm = *localtime(&ansi_epoch_plus_one_day);
98 local_tm.tm_isdst = 0;
99 gmt_to_localtime_offset = mktime(&gmt_tm) - mktime(&local_tm);
103 static gboolean observer_read(wtap *wth, int *err, gchar **err_info,
104 gint64 *data_offset);
105 static gboolean observer_seek_read(wtap *wth, gint64 seek_off,
106 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
107 int *err, gchar **err_info);
108 static int read_packet_header(FILE_T fh, union wtap_pseudo_header *pseudo_header,
109 packet_entry_header *packet_header, int *err, gchar **err_info);
110 static int read_packet_data(FILE_T fh, int offset_to_frame, int current_offset_from_packet_header,
111 guint8 *pd, int length, int *err, char **err_info);
112 static gboolean skip_to_next_packet(wtap *wth, int offset_to_next_packet,
113 int current_offset_from_packet_header, int *err, char **err_info);
114 static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
115 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err);
116 static gint observer_to_wtap_encap(int observer_encap);
117 static gint wtap_to_observer_encap(int wtap_encap);
119 int network_instruments_open(wtap *wth, int *err, gchar **err_info)
123 capture_file_header file_header;
128 packet_entry_header packet_header;
129 observer_dump_private_state * private_state = NULL;
131 errno = WTAP_ERR_CANT_READ;
134 /* read in the buffer file header */
135 bytes_read = file_read(&file_header, sizeof file_header, wth->fh);
136 if (bytes_read != sizeof file_header) {
137 *err = file_error(wth->fh, err_info);
142 offset += bytes_read;
143 CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header);
145 /* check if version info is present */
146 if (memcmp(file_header.observer_version, network_instruments_magic, true_magic_length)!=0) {
150 /* initialize the private state */
151 private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
152 private_state->time_format = TIME_INFO_LOCAL;
153 wth->priv = (void *) private_state;
155 /* get the location of the first packet */
156 /* v15 and newer uses high byte offset, in previous versions it will be 0 */
157 header_offset = file_header.offset_to_first_packet + ((int)(file_header.offset_to_first_packet_high_byte)<<16);
159 /* process extra information */
160 for (i = 0; i < file_header.number_of_information_elements; i++) {
161 /* for safety break if we've reached the first packet */
162 if (offset >= header_offset)
165 /* read the TLV header */
166 bytes_read = file_read(&tlvh, sizeof tlvh, wth->fh);
167 if (bytes_read != sizeof tlvh) {
168 *err = file_error(wth->fh, err_info);
170 *err = WTAP_ERR_SHORT_READ;
173 offset += bytes_read;
174 TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
176 if (tlvh.length < sizeof tlvh) {
177 *err = WTAP_ERR_BAD_FILE;
178 *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)",
179 tlvh.length, (unsigned long)sizeof tlvh);
183 /* process (or skip over) the current TLV */
185 case INFORMATION_TYPE_TIME_INFO:
186 bytes_read = file_read(&private_state->time_format, sizeof private_state->time_format, wth->fh);
187 if (bytes_read != sizeof private_state->time_format) {
188 *err = file_error(wth->fh, err_info);
190 *err = WTAP_ERR_SHORT_READ;
193 private_state->time_format = GUINT32_FROM_LE(private_state->time_format);
194 offset += bytes_read;
197 seek_increment = tlvh.length - (int)sizeof tlvh;
198 if (seek_increment > 0) {
199 if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
202 offset += seek_increment;
206 /* get to the first packet */
207 if (header_offset < offset) {
208 *err = WTAP_ERR_BAD_FILE;
209 *err_info = g_strdup_printf("Observer: bad record (offset to first packet %d < %d)",
210 header_offset, offset);
213 seek_increment = header_offset - offset;
214 if (seek_increment > 0) {
215 if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
219 /* pull off the packet header */
220 bytes_read = file_read(&packet_header, sizeof packet_header, wth->fh);
221 if (bytes_read != sizeof packet_header) {
222 *err = file_error(wth->fh, err_info);
227 PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(packet_header);
229 /* check the packet's magic number */
230 if (packet_header.packet_magic != observer_packet_magic) {
231 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
232 *err_info = g_strdup_printf("Observer: unsupported packet version %ul", packet_header.packet_magic);
236 /* check the data link type */
237 if (observer_to_wtap_encap(packet_header.network_type) == WTAP_ENCAP_UNKNOWN) {
238 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
239 *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type);
242 wth->file_encap = observer_to_wtap_encap(packet_header.network_type);
244 /* set up the rest of the capture parameters */
245 private_state->packet_count = 0;
246 private_state->network_type = wtap_to_observer_encap(wth->file_encap);
247 wth->subtype_read = observer_read;
248 wth->subtype_seek_read = observer_seek_read;
249 wth->subtype_close = NULL;
250 wth->subtype_sequential_close = NULL;
251 wth->snapshot_length = 0; /* not available in header */
252 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
253 wth->file_type = WTAP_FILE_NETWORK_INSTRUMENTS;
255 /* reset the pointer to the first packet */
256 if (file_seek(wth->fh, header_offset, SEEK_SET,
259 wth->data_offset = header_offset;
261 init_gmt_to_localtime_offset();
266 /* Reads the next packet. */
267 static gboolean observer_read(wtap *wth, int *err, gchar **err_info,
271 int offset_from_packet_header = 0;
272 packet_entry_header packet_header;
274 /* skip records other than data records */
276 *data_offset = wth->data_offset;
278 /* process the packet header, including TLVs */
279 bytes_consumed = read_packet_header(wth->fh, &wth->pseudo_header, &packet_header, err,
281 if (bytes_consumed <= 0)
282 return FALSE; /* EOF or error */
284 wth->data_offset += bytes_consumed;
286 if (packet_header.packet_type == PACKET_TYPE_DATA_PACKET)
289 /* skip to next packet */
290 offset_from_packet_header = (int) (wth->data_offset - *data_offset);
291 if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
292 offset_from_packet_header, err, err_info)) {
293 return FALSE; /* EOF or error */
297 /* neglect frame markers for wiretap */
298 if (packet_header.network_size < 4) {
299 *err = WTAP_ERR_BAD_FILE;
300 *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4",
301 packet_header.network_size);
305 /* set the wiretap packet header fields */
306 wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
307 wth->phdr.pkt_encap = observer_to_wtap_encap(packet_header.network_type);
308 if(wth->file_encap == WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS) {
309 wth->phdr.len = packet_header.network_size;
310 wth->phdr.caplen = packet_header.captured_size;
312 wth->phdr.len = packet_header.network_size - 4;
313 wth->phdr.caplen = MIN(packet_header.captured_size, wth->phdr.len);
316 /* set the wiretap timestamp, assuming for the moment that Observer encoded it in GMT */
317 wth->phdr.ts.secs = (time_t) ((packet_header.nano_seconds_since_2000 / 1000000000) + ansi_to_observer_epoch_offset);
318 wth->phdr.ts.nsecs = (int) (packet_header.nano_seconds_since_2000 % 1000000000);
320 /* adjust to local time, if necessary, also accounting for DST if the frame
321 was captured while it was in effect */
322 if (((observer_dump_private_state*)wth->priv)->time_format == TIME_INFO_LOCAL)
324 struct tm daylight_tm;
325 struct tm standard_tm;
328 /* the Observer timestamp was encoded as local time, so add a
329 correction from local time to GMT */
330 wth->phdr.ts.secs += gmt_to_localtime_offset;
332 /* perform a DST adjustment if necessary */
333 standard_tm = *localtime(&wth->phdr.ts.secs);
334 if (standard_tm.tm_isdst > 0) {
335 daylight_tm = standard_tm;
336 standard_tm.tm_isdst = 0;
337 dst_offset = mktime(&standard_tm) - mktime(&daylight_tm);
338 wth->phdr.ts.secs -= dst_offset;
342 /* update the pseudo header */
343 switch (wth->file_encap) {
344 case WTAP_ENCAP_ETHERNET:
345 /* There is no FCS in the frame */
346 wth->pseudo_header.eth.fcs_len = 0;
348 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
349 /* Updated in read_packet_header */
353 /* set-up the packet buffer */
354 buffer_assure_space(wth->frame_buffer, packet_header.captured_size);
356 /* read the frame data */
357 offset_from_packet_header = (int) (wth->data_offset - *data_offset);
358 bytes_consumed = read_packet_data(wth->fh, packet_header.offset_to_frame,
359 offset_from_packet_header, buffer_start_ptr(wth->frame_buffer),
360 packet_header.captured_size, err, err_info);
361 if (bytes_consumed < 0) {
364 wth->data_offset += bytes_consumed;
366 /* skip over any extra bytes following the frame data */
367 offset_from_packet_header = (int) (wth->data_offset - *data_offset);
368 if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
369 offset_from_packet_header, err, err_info)) {
376 /* Reads a packet at an offset. */
377 static gboolean observer_seek_read(wtap *wth, gint64 seek_off,
378 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
379 int *err, gchar **err_info)
381 packet_entry_header packet_header;
384 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
387 /* process the packet header, including TLVs */
388 offset = read_packet_header(wth->random_fh, pseudo_header, &packet_header, err,
391 return FALSE; /* EOF or error */
393 /* update the pseudo header */
394 switch (wth->file_encap) {
396 case WTAP_ENCAP_ETHERNET:
397 /* There is no FCS in the frame */
398 pseudo_header->eth.fcs_len = 0;
400 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
401 /* Updated in read_packet_header */
405 /* read the frame data */
406 if (!read_packet_data(wth->random_fh, packet_header.offset_to_frame,
407 offset, pd, length, err, err_info))
414 read_packet_header(FILE_T fh, union wtap_pseudo_header *pseudo_header,
415 packet_entry_header *packet_header, int *err, gchar **err_info)
422 tlv_wireless_info wireless_header;
426 /* pull off the packet header */
427 bytes_read = file_read(packet_header, sizeof *packet_header, fh);
428 if (bytes_read != sizeof *packet_header) {
429 *err = file_error(fh, err_info);
434 offset += bytes_read;
435 PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(*packet_header);
437 /* check the packet's magic number */
438 if (packet_header->packet_magic != observer_packet_magic) {
441 * Some files are zero-padded at the end. There is no warning of this
442 * in the previous packet header information, such as setting
443 * offset_to_next_packet to zero. So detect this situation by treating
444 * an all-zero header as a sentinel. Return EOF when it is encountered,
445 * rather than treat it as a bad record.
447 for (i = 0; i < sizeof *packet_header; i++) {
448 if (((guint8*) packet_header)[i] != 0)
451 if (i == sizeof *packet_header) {
456 *err = WTAP_ERR_BAD_FILE;
457 *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x",
458 packet_header->packet_magic);
462 /* process extra information */
463 for (i = 0; i < packet_header->number_of_information_elements; i++) {
464 /* read the TLV header */
465 bytes_read = file_read(&tlvh, sizeof tlvh, fh);
466 if (bytes_read != sizeof tlvh) {
467 *err = file_error(fh, err_info);
469 *err = WTAP_ERR_SHORT_READ;
472 offset += bytes_read;
473 TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
475 if (tlvh.length < sizeof tlvh) {
476 *err = WTAP_ERR_BAD_FILE;
477 *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)",
478 tlvh.length, (unsigned long)sizeof tlvh);
482 /* process (or skip over) the current TLV */
484 case INFORMATION_TYPE_WIRELESS:
485 bytes_read = file_read(&wireless_header, sizeof wireless_header, fh);
486 if (bytes_read != sizeof wireless_header) {
487 *err = file_error(fh, err_info);
489 *err = WTAP_ERR_SHORT_READ;
492 /* update the pseudo header */
493 pseudo_header->ieee_802_11.fcs_len = 0;
494 pseudo_header->ieee_802_11.channel = wireless_header.frequency;
495 pseudo_header->ieee_802_11.data_rate = wireless_header.rate;
496 pseudo_header->ieee_802_11.signal_level = wireless_header.strengthPercent;
497 offset += bytes_read;
500 /* skip the TLV data */
501 seek_increment = tlvh.length - (int)sizeof tlvh;
502 if (seek_increment > 0) {
503 if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1)
506 offset += seek_increment;
514 read_packet_data(FILE_T fh, int offset_to_frame, int current_offset_from_packet_header, guint8 *pd,
515 int length, int *err, char **err_info)
518 int bytes_consumed = 0;
520 /* validate offsets */
521 if (offset_to_frame < current_offset_from_packet_header) {
522 *err = WTAP_ERR_BAD_FILE;
523 *err_info = g_strdup_printf("Observer: bad record (offset to packet data %d < %d)",
524 offset_to_frame, current_offset_from_packet_header);
528 /* skip to the packet data */
529 seek_increment = offset_to_frame - current_offset_from_packet_header;
530 if (seek_increment > 0) {
531 if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) {
534 bytes_consumed += seek_increment;
537 /* read in the packet data */
538 wtap_file_read_expected_bytes(pd, length, fh, err, err_info);
539 bytes_consumed += length;
541 return bytes_consumed;
545 skip_to_next_packet(wtap *wth, int offset_to_next_packet, int current_offset_from_packet_header, int *err,
550 /* validate offsets */
551 if (offset_to_next_packet < current_offset_from_packet_header) {
552 *err = WTAP_ERR_BAD_FILE;
553 *err_info = g_strdup_printf("Observer: bad record (offset to next packet %d < %d)",
554 offset_to_next_packet, current_offset_from_packet_header);
558 /* skip to the next packet header */
559 seek_increment = offset_to_next_packet - current_offset_from_packet_header;
560 if (seek_increment > 0) {
561 if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
563 wth->data_offset += seek_increment;
569 /* Returns 0 if we could write the specified encapsulation type,
570 an error indication otherwise. */
571 int network_instruments_dump_can_write_encap(int encap)
573 /* per-packet encapsulations aren't supported */
574 if (encap == WTAP_ENCAP_PER_PACKET)
575 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
577 if (encap < 0 || (wtap_to_observer_encap(encap) == OBSERVER_UNDEFINED))
578 return WTAP_ERR_UNSUPPORTED_ENCAP;
583 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
585 gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
587 observer_dump_private_state * private_state = NULL;
588 capture_file_header file_header;
590 tlv_header comment_header;
591 tlv_time_info time_header;
593 size_t comment_length;
594 struct tm * current_time;
597 /* initialize the private state */
598 private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
599 private_state->packet_count = 0;
600 private_state->network_type = wtap_to_observer_encap(wdh->encap);
601 private_state->time_format = TIME_INFO_GMT;
603 /* populate the fields of wdh */
604 wdh->priv = (void *) private_state;
605 wdh->subtype_write = observer_dump;
607 /* initialize the file header */
608 memset(&file_header, 0x00, sizeof(file_header));
609 g_strlcpy(file_header.observer_version, network_instruments_magic, 31);
610 file_header.offset_to_first_packet = (guint16)sizeof(file_header);
611 file_header.offset_to_first_packet_high_byte = 0;
613 /* create the file comment TLV */
616 current_time = localtime(&system_time);
617 memset(&comment, 0x00, sizeof(comment));
618 g_snprintf(comment, 64, "This capture was saved from Wireshark on %s", asctime(current_time));
619 comment_length = strlen(comment);
621 comment_header.type = INFORMATION_TYPE_COMMENT;
622 comment_header.length = (guint16) (sizeof(comment_header) + comment_length);
624 /* update the file header to account for the comment TLV */
625 file_header.number_of_information_elements++;
626 file_header.offset_to_first_packet += comment_header.length;
629 /* create the timestamp encoding TLV */
631 time_header.type = INFORMATION_TYPE_TIME_INFO;
632 time_header.length = (guint16) (sizeof(time_header));
633 time_header.time_format = TIME_INFO_GMT;
635 /* update the file header to account for the timestamp encoding TLV */
636 file_header.number_of_information_elements++;
637 file_header.offset_to_first_packet += time_header.length;
640 /* write the file header, swapping any multibyte fields first */
641 CAPTURE_FILE_HEADER_TO_LE_IN_PLACE(file_header);
642 if (!wtap_dump_file_write(wdh, &file_header, sizeof(file_header), err)) {
645 wdh->bytes_dumped += sizeof(file_header);
647 /* write the comment TLV */
649 TLV_HEADER_TO_LE_IN_PLACE(comment_header);
650 if (!wtap_dump_file_write(wdh, &comment_header, sizeof(comment_header), err)) {
653 wdh->bytes_dumped += sizeof(comment_header);
655 if (!wtap_dump_file_write(wdh, &comment, comment_length, err)) {
658 wdh->bytes_dumped += comment_length;
661 /* write the time info TLV */
663 TLV_TIME_INFO_TO_LE_IN_PLACE(time_header);
664 if (!wtap_dump_file_write(wdh, &time_header, sizeof(time_header), err)) {
667 wdh->bytes_dumped += sizeof(time_header);
670 init_gmt_to_localtime_offset();
675 /* Write a record for a packet to a dump file.
676 Returns TRUE on success, FALSE on failure. */
677 static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
678 const union wtap_pseudo_header *pseudo_header _U_, const guint8 *pd,
681 observer_dump_private_state * private_state = NULL;
682 packet_entry_header packet_header;
683 guint64 seconds_since_2000;
685 /* convert the number of seconds since epoch from ANSI-relative to
687 if (phdr->ts.secs < ansi_to_observer_epoch_offset) {
688 if(phdr->ts.secs > (time_t) 0) {
689 seconds_since_2000 = phdr->ts.secs;
691 seconds_since_2000 = (time_t) 0;
694 seconds_since_2000 = phdr->ts.secs - ansi_to_observer_epoch_offset;
697 /* populate the fields of the packet header */
698 private_state = (observer_dump_private_state *) wdh->priv;
700 memset(&packet_header, 0x00, sizeof(packet_header));
701 packet_header.packet_magic = observer_packet_magic;
702 packet_header.network_speed = 1000000;
703 packet_header.captured_size = (guint16) phdr->caplen;
704 packet_header.network_size = (guint16) (phdr->len + 4);
705 packet_header.offset_to_frame = sizeof(packet_header);
706 /* XXX - what if this doesn't fit in 16 bits? It's not guaranteed to... */
707 packet_header.offset_to_next_packet = (guint16)sizeof(packet_header) + phdr->caplen;
708 packet_header.network_type = private_state->network_type;
709 packet_header.flags = 0x00;
710 packet_header.number_of_information_elements = 0;
711 packet_header.packet_type = PACKET_TYPE_DATA_PACKET;
712 packet_header.packet_number = private_state->packet_count;
713 packet_header.original_packet_number = packet_header.packet_number;
714 packet_header.nano_seconds_since_2000 = seconds_since_2000 * 1000000000 + phdr->ts.nsecs;
716 private_state->packet_count++;
718 /* write the packet header */
719 PACKET_ENTRY_HEADER_TO_LE_IN_PLACE(packet_header);
720 if (!wtap_dump_file_write(wdh, &packet_header, sizeof(packet_header), err)) {
723 wdh->bytes_dumped += sizeof(packet_header);
725 /* write the packet data */
726 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err)) {
729 wdh->bytes_dumped += phdr->caplen;
734 static gint observer_to_wtap_encap(int observer_encap)
736 switch(observer_encap) {
737 case OBSERVER_ETHERNET:
738 return WTAP_ENCAP_ETHERNET;
739 case OBSERVER_TOKENRING:
740 return WTAP_ENCAP_TOKEN_RING;
741 case OBSERVER_FIBRE_CHANNEL:
742 return WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS;
743 case OBSERVER_WIRELESS_802_11:
744 return WTAP_ENCAP_IEEE_802_11_WITH_RADIO;
745 case OBSERVER_UNDEFINED:
746 return WTAP_ENCAP_UNKNOWN;
748 return WTAP_ENCAP_UNKNOWN;
751 static gint wtap_to_observer_encap(int wtap_encap)
754 case WTAP_ENCAP_ETHERNET:
755 return OBSERVER_ETHERNET;
756 case WTAP_ENCAP_TOKEN_RING:
757 return OBSERVER_TOKENRING;
758 case WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS:
759 return OBSERVER_FIBRE_CHANNEL;
760 case WTAP_ENCAP_UNKNOWN:
761 return OBSERVER_UNDEFINED;
763 return OBSERVER_UNDEFINED;