1 /***************************************************************************
2 network_instruments.c - description
4 begin : Wed Oct 29 2003
5 copyright : (C) 2003 by root
6 email : scotte[AT}netinst.com
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
24 #include "file_wrappers.h"
25 #include "network_instruments.h"
27 static const char network_instruments_magic[] = {"ObserverPktBufferVersion=15.00"};
28 static const int true_magic_length = 17;
30 static const guint32 observer_packet_magic = 0x88888888;
33 * This structure is used to keep state when writing files. An instance is
34 * allocated for each file, and its address is stored in the wtap_dumper.priv
41 } observer_dump_private_state;
44 * Some time offsets are calculated in advance here, when the first Observer
45 * file is opened for reading or writing, and are then used to adjust frame
46 * timestamps as they are read or written.
48 * The Wiretap API expects timestamps in nanoseconds relative to
49 * January 1, 1970, 00:00:00 GMT (the Wiretap epoch).
51 * Observer versions before 13.10 encode frame timestamps in nanoseconds
52 * relative to January 1, 2000, 00:00:00 local time (the Observer epoch).
53 * Versions 13.10 and later switch over to GMT encoding. Which encoding was used
54 * when saving the file is identified via the time format TLV following
57 * Unfortunately, even though Observer versions before 13.10 saved in local
58 * time, they didn't include the timezone from which the frames were captured,
59 * so converting to GMT correctly from all timezones is impossible. So an
60 * assumption is made that the file is being read from within the same timezone
61 * that it was written.
63 * All code herein is normalized to versions 13.10 and later, special casing for
64 * versions earlier. In other words, timestamps are worked with as if
65 * they are GMT-encoded, and adjustments from local time are made only if
66 * the source file warrants it.
68 * All destination files are saved in GMT format.
70 static const time_t ansi_to_observer_epoch_offset = 946684800;
71 static time_t gmt_to_localtime_offset = (time_t) -1;
73 static void init_gmt_to_localtime_offset(void)
75 if (gmt_to_localtime_offset == (time_t) -1) {
76 time_t ansi_epoch_plus_one_day = 86400;
81 * Compute the local time zone offset as the number of seconds west
82 * of GMT. There's no obvious cross-platform API for querying this
83 * directly. As a workaround, GMT and local tm structures are populated
84 * relative to the ANSI time_t epoch (plus one day to ensure that
85 * local time stays after 1970/1/1 00:00:00). They are then converted
86 * back to time_t as if they were both local times, resulting in the
87 * time zone offset being the difference between them.
89 gmt_tm = *gmtime(&ansi_epoch_plus_one_day);
90 local_tm = *localtime(&ansi_epoch_plus_one_day);
91 local_tm.tm_isdst = 0;
92 gmt_to_localtime_offset = mktime(&gmt_tm) - mktime(&local_tm);
96 static gboolean observer_read(wtap *wth, int *err, gchar **err_info,
98 static gboolean observer_seek_read(wtap *wth, gint64 seek_off,
99 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
100 static int read_packet_header(wtap *wth, FILE_T fh, union wtap_pseudo_header *pseudo_header,
101 packet_entry_header *packet_header, int *err, gchar **err_info);
102 static gboolean process_packet_header(wtap *wth,
103 packet_entry_header *packet_header, struct wtap_pkthdr *phdr, int *err,
105 static int read_packet_data(FILE_T fh, int offset_to_frame, int current_offset_from_packet_header,
106 Buffer *buf, int length, int *err, char **err_info);
107 static gboolean skip_to_next_packet(wtap *wth, int offset_to_next_packet,
108 int current_offset_from_packet_header, int *err, char **err_info);
109 static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
110 const guint8 *pd, int *err, gchar **err_info);
111 static gint observer_to_wtap_encap(int observer_encap);
112 static gint wtap_to_observer_encap(int wtap_encap);
114 wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_info)
117 capture_file_header file_header;
122 packet_entry_header packet_header;
123 observer_dump_private_state * private_state = NULL;
127 /* read in the buffer file header */
128 if (!wtap_read_bytes(wth->fh, &file_header, sizeof file_header,
130 if (*err != WTAP_ERR_SHORT_READ)
131 return WTAP_OPEN_ERROR;
132 return WTAP_OPEN_NOT_MINE;
134 offset += (int)sizeof file_header;
135 CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header);
137 /* check if version info is present */
138 if (memcmp(file_header.observer_version, network_instruments_magic, true_magic_length)!=0) {
139 return WTAP_OPEN_NOT_MINE;
142 /* initialize the private state */
143 private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
144 private_state->time_format = TIME_INFO_LOCAL;
145 wth->priv = (void *) private_state;
147 /* get the location of the first packet */
148 /* v15 and newer uses high byte offset, in previous versions it will be 0 */
149 header_offset = file_header.offset_to_first_packet + ((int)(file_header.offset_to_first_packet_high_byte)<<16);
151 /* process extra information */
152 for (i = 0; i < file_header.number_of_information_elements; i++) {
153 /* for safety break if we've reached the first packet */
154 if (offset >= header_offset)
157 /* read the TLV header */
158 if (!wtap_read_bytes(wth->fh, &tlvh, sizeof tlvh, err, err_info))
159 return WTAP_OPEN_ERROR;
160 offset += (int)sizeof tlvh;
161 TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
163 if (tlvh.length < sizeof tlvh) {
164 *err = WTAP_ERR_BAD_FILE;
165 *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)",
166 tlvh.length, (unsigned long)sizeof tlvh);
167 return WTAP_OPEN_ERROR;
170 /* process (or skip over) the current TLV */
172 case INFORMATION_TYPE_TIME_INFO:
173 if (!wtap_read_bytes(wth->fh, &private_state->time_format,
174 sizeof private_state->time_format,
176 return WTAP_OPEN_ERROR;
177 private_state->time_format = GUINT32_FROM_LE(private_state->time_format);
178 offset += (int)sizeof private_state->time_format;
181 seek_increment = tlvh.length - (int)sizeof tlvh;
182 if (seek_increment > 0) {
183 if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
184 return WTAP_OPEN_ERROR;
186 offset += seek_increment;
190 /* get to the first packet */
191 if (header_offset < offset) {
192 *err = WTAP_ERR_BAD_FILE;
193 *err_info = g_strdup_printf("Observer: bad record (offset to first packet %d < %d)",
194 header_offset, offset);
195 return WTAP_OPEN_ERROR;
197 seek_increment = header_offset - offset;
198 if (seek_increment > 0) {
199 if (file_seek(wth->fh, seek_increment, SEEK_CUR, err) == -1)
200 return WTAP_OPEN_ERROR;
203 /* pull off the packet header */
204 if (!wtap_read_bytes(wth->fh, &packet_header, sizeof packet_header,
206 return WTAP_OPEN_ERROR;
207 PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(packet_header);
209 /* check the packet's magic number */
210 if (packet_header.packet_magic != observer_packet_magic) {
211 *err = WTAP_ERR_UNSUPPORTED;
212 *err_info = g_strdup_printf("Observer: unsupported packet version %ul", packet_header.packet_magic);
213 return WTAP_OPEN_ERROR;
216 /* check the data link type */
217 if (observer_to_wtap_encap(packet_header.network_type) == WTAP_ENCAP_UNKNOWN) {
218 *err = WTAP_ERR_UNSUPPORTED;
219 *err_info = g_strdup_printf("Observer: network type %u unknown or unsupported", packet_header.network_type);
220 return WTAP_OPEN_ERROR;
222 wth->file_encap = observer_to_wtap_encap(packet_header.network_type);
224 /* set up the rest of the capture parameters */
225 private_state->packet_count = 0;
226 private_state->network_type = wtap_to_observer_encap(wth->file_encap);
227 wth->subtype_read = observer_read;
228 wth->subtype_seek_read = observer_seek_read;
229 wth->subtype_close = NULL;
230 wth->subtype_sequential_close = NULL;
231 wth->snapshot_length = 0; /* not available in header */
232 wth->file_tsprec = WTAP_TSPREC_NSEC;
233 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NETWORK_INSTRUMENTS;
235 /* reset the pointer to the first packet */
236 if (file_seek(wth->fh, header_offset, SEEK_SET, err) == -1)
237 return WTAP_OPEN_ERROR;
239 init_gmt_to_localtime_offset();
241 return WTAP_OPEN_MINE;
244 /* Reads the next packet. */
245 static gboolean observer_read(wtap *wth, int *err, gchar **err_info,
248 int header_bytes_consumed;
249 int data_bytes_consumed;
250 packet_entry_header packet_header;
252 /* skip records other than data records */
254 *data_offset = file_tell(wth->fh);
256 /* process the packet header, including TLVs */
257 header_bytes_consumed = read_packet_header(wth, wth->fh, &wth->phdr.pseudo_header, &packet_header, err,
259 if (header_bytes_consumed <= 0)
260 return FALSE; /* EOF or error */
262 if (packet_header.packet_type == PACKET_TYPE_DATA_PACKET)
265 /* skip to next packet */
266 if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
267 header_bytes_consumed, err, err_info)) {
268 return FALSE; /* EOF or error */
272 if (!process_packet_header(wth, &packet_header, &wth->phdr, err, err_info))
275 /* read the frame data */
276 data_bytes_consumed = read_packet_data(wth->fh, packet_header.offset_to_frame,
277 header_bytes_consumed, wth->frame_buffer,
278 wth->phdr.caplen, err, err_info);
279 if (data_bytes_consumed < 0) {
283 /* skip over any extra bytes following the frame data */
284 if (!skip_to_next_packet(wth, packet_header.offset_to_next_packet,
285 header_bytes_consumed + data_bytes_consumed, err, err_info)) {
292 /* Reads a packet at an offset. */
293 static gboolean observer_seek_read(wtap *wth, gint64 seek_off,
294 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
296 union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
297 packet_entry_header packet_header;
299 int data_bytes_consumed;
301 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
304 /* process the packet header, including TLVs */
305 offset = read_packet_header(wth, wth->random_fh, pseudo_header, &packet_header, err,
308 return FALSE; /* EOF or error */
310 if (!process_packet_header(wth, &packet_header, phdr, err, err_info))
313 /* read the frame data */
314 data_bytes_consumed = read_packet_data(wth->random_fh, packet_header.offset_to_frame,
315 offset, buf, phdr->caplen, err, err_info);
316 if (data_bytes_consumed < 0) {
324 read_packet_header(wtap *wth, FILE_T fh, union wtap_pseudo_header *pseudo_header,
325 packet_entry_header *packet_header, int *err, gchar **err_info)
331 tlv_wireless_info wireless_header;
335 /* pull off the packet header */
336 if (!wtap_read_bytes_or_eof(fh, packet_header, sizeof *packet_header,
342 offset += (int)sizeof *packet_header;
343 PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(*packet_header);
345 /* check the packet's magic number */
346 if (packet_header->packet_magic != observer_packet_magic) {
349 * Some files are zero-padded at the end. There is no warning of this
350 * in the previous packet header information, such as setting
351 * offset_to_next_packet to zero. So detect this situation by treating
352 * an all-zero header as a sentinel. Return EOF when it is encountered,
353 * rather than treat it as a bad record.
355 for (i = 0; i < sizeof *packet_header; i++) {
356 if (((guint8*) packet_header)[i] != 0)
359 if (i == sizeof *packet_header) {
364 *err = WTAP_ERR_BAD_FILE;
365 *err_info = g_strdup_printf("Observer: bad record: Invalid magic number 0x%08x",
366 packet_header->packet_magic);
370 /* initialize the pseudo header */
371 switch (wth->file_encap) {
372 case WTAP_ENCAP_ETHERNET:
373 /* There is no FCS in the frame */
374 pseudo_header->eth.fcs_len = 0;
376 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
377 memset(&pseudo_header->ieee_802_11, 0, sizeof(pseudo_header->ieee_802_11));
378 pseudo_header->ieee_802_11.fcs_len = 0;
379 pseudo_header->ieee_802_11.decrypted = FALSE;
380 pseudo_header->ieee_802_11.datapad = FALSE;
381 pseudo_header->ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN;
386 /* process extra information */
387 for (i = 0; i < packet_header->number_of_information_elements; i++) {
388 /* read the TLV header */
389 if (!wtap_read_bytes(fh, &tlvh, sizeof tlvh, err, err_info))
391 offset += (int)sizeof tlvh;
392 TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
394 if (tlvh.length < sizeof tlvh) {
395 *err = WTAP_ERR_BAD_FILE;
396 *err_info = g_strdup_printf("Observer: bad record (TLV length %u < %lu)",
397 tlvh.length, (unsigned long)sizeof tlvh);
401 /* process (or skip over) the current TLV */
403 case INFORMATION_TYPE_WIRELESS:
404 if (!wtap_read_bytes(fh, &wireless_header, sizeof wireless_header,
407 /* set decryption status */
408 /* XXX - what other bits are there in conditions? */
409 pseudo_header->ieee_802_11.decrypted = (wireless_header.conditions & WIRELESS_WEP_SUCCESS) != 0;
410 pseudo_header->ieee_802_11.has_channel = TRUE;
411 pseudo_header->ieee_802_11.channel = wireless_header.frequency;
412 pseudo_header->ieee_802_11.has_data_rate = TRUE;
413 pseudo_header->ieee_802_11.data_rate = wireless_header.rate;
414 pseudo_header->ieee_802_11.has_signal_percent = TRUE;
415 pseudo_header->ieee_802_11.signal_percent = wireless_header.strengthPercent;
416 offset += (int)sizeof wireless_header;
419 /* skip the TLV data */
420 seek_increment = tlvh.length - (int)sizeof tlvh;
421 if (seek_increment > 0) {
422 if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1)
425 offset += seek_increment;
433 process_packet_header(wtap *wth, packet_entry_header *packet_header,
434 struct wtap_pkthdr *phdr, int *err, gchar **err_info)
436 /* set the wiretap packet header fields */
437 phdr->rec_type = REC_TYPE_PACKET;
438 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
439 phdr->pkt_encap = observer_to_wtap_encap(packet_header->network_type);
440 if(wth->file_encap == WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS) {
441 phdr->len = packet_header->network_size;
442 phdr->caplen = packet_header->captured_size;
445 * XXX - what are those 4 bytes?
447 * The comment in the code said "neglect frame markers for wiretap",
448 * but in the captures I've seen, there's no actual data corresponding
449 * to them that might be a "frame marker".
451 * Instead, the packets had a network_size 4 bytes larger than the
452 * captured_size; does the network_size include the CRC, even
453 * though it's not included in a capture? If so, most other
454 * network analyzers that have a "network size" and a "captured
455 * size" don't include the CRC in the "network size" if they
456 * don't include the CRC in a full-length captured packet; the
457 * "captured size" is less than the "network size" only if a
458 * user-specified "snapshot length" caused the packet to be
459 * sliced at a particular point.
461 * That's the model that wiretap and Wireshark/TShark use, so
462 * we implement that model here.
464 if (packet_header->network_size < 4) {
465 *err = WTAP_ERR_BAD_FILE;
466 *err_info = g_strdup_printf("Observer: bad record: Packet length %u < 4",
467 packet_header->network_size);
471 phdr->len = packet_header->network_size - 4;
472 phdr->caplen = MIN(packet_header->captured_size, phdr->len);
475 * The maximum value of packet_header->captured_size is 65535, which
476 * is less than WTAP_MAX_PACKET_SIZE will ever be, so we don't need
480 /* set the wiretap timestamp, assuming for the moment that Observer encoded it in GMT */
481 phdr->ts.secs = (time_t) ((packet_header->nano_seconds_since_2000 / 1000000000) + ansi_to_observer_epoch_offset);
482 phdr->ts.nsecs = (int) (packet_header->nano_seconds_since_2000 % 1000000000);
484 /* adjust to local time, if necessary, also accounting for DST if the frame
485 was captured while it was in effect */
486 if (((observer_dump_private_state*)wth->priv)->time_format == TIME_INFO_LOCAL)
488 struct tm daylight_tm;
489 struct tm standard_tm;
492 /* the Observer timestamp was encoded as local time, so add a
493 correction from local time to GMT */
494 phdr->ts.secs += gmt_to_localtime_offset;
496 /* perform a DST adjustment if necessary */
497 standard_tm = *localtime(&phdr->ts.secs);
498 if (standard_tm.tm_isdst > 0) {
499 daylight_tm = standard_tm;
500 standard_tm.tm_isdst = 0;
501 dst_offset = mktime(&standard_tm) - mktime(&daylight_tm);
502 phdr->ts.secs -= dst_offset;
510 read_packet_data(FILE_T fh, int offset_to_frame, int current_offset_from_packet_header, Buffer *buf,
511 int length, int *err, char **err_info)
514 int bytes_consumed = 0;
516 /* validate offsets */
517 if (offset_to_frame < current_offset_from_packet_header) {
518 *err = WTAP_ERR_BAD_FILE;
519 *err_info = g_strdup_printf("Observer: bad record (offset to packet data %d < %d)",
520 offset_to_frame, current_offset_from_packet_header);
524 /* skip to the packet data */
525 seek_increment = offset_to_frame - current_offset_from_packet_header;
526 if (seek_increment > 0) {
527 if (file_seek(fh, seek_increment, SEEK_CUR, err) == -1) {
530 bytes_consumed += seek_increment;
533 /* set-up the packet buffer */
534 ws_buffer_assure_space(buf, length);
536 /* read in the packet data */
537 if (!wtap_read_packet_bytes(fh, buf, length, 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)
568 /* Returns 0 if we could write the specified encapsulation type,
569 an error indication otherwise. */
570 int network_instruments_dump_can_write_encap(int encap)
572 /* per-packet encapsulations aren't supported */
573 if (encap == WTAP_ENCAP_PER_PACKET)
574 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
576 if (encap < 0 || (wtap_to_observer_encap(encap) == OBSERVER_UNDEFINED))
577 return WTAP_ERR_UNWRITABLE_ENCAP;
582 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
584 gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
586 observer_dump_private_state * private_state = NULL;
587 capture_file_header file_header;
589 tlv_header comment_header;
590 tlv_time_info time_header;
592 size_t comment_length;
593 struct tm * current_time;
596 /* initialize the private state */
597 private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
598 private_state->packet_count = 0;
599 private_state->network_type = wtap_to_observer_encap(wdh->encap);
600 private_state->time_format = TIME_INFO_GMT;
602 /* populate the fields of wdh */
603 wdh->priv = (void *) private_state;
604 wdh->subtype_write = observer_dump;
606 /* initialize the file header */
607 memset(&file_header, 0x00, sizeof(file_header));
608 g_strlcpy(file_header.observer_version, network_instruments_magic, 31);
609 file_header.offset_to_first_packet = (guint16)sizeof(file_header);
610 file_header.offset_to_first_packet_high_byte = 0;
612 /* create the file comment TLV */
615 current_time = localtime(&system_time);
616 memset(&comment, 0x00, sizeof(comment));
617 g_snprintf(comment, 64, "This capture was saved from Wireshark on %s", asctime(current_time));
618 comment_length = strlen(comment);
620 comment_header.type = INFORMATION_TYPE_COMMENT;
621 comment_header.length = (guint16) (sizeof(comment_header) + comment_length);
623 /* update the file header to account for the comment TLV */
624 file_header.number_of_information_elements++;
625 file_header.offset_to_first_packet += comment_header.length;
628 /* create the timestamp encoding TLV */
630 time_header.type = INFORMATION_TYPE_TIME_INFO;
631 time_header.length = (guint16) (sizeof(time_header));
632 time_header.time_format = TIME_INFO_GMT;
634 /* update the file header to account for the timestamp encoding TLV */
635 file_header.number_of_information_elements++;
636 file_header.offset_to_first_packet += time_header.length;
639 /* write the file header, swapping any multibyte fields first */
640 CAPTURE_FILE_HEADER_TO_LE_IN_PLACE(file_header);
641 if (!wtap_dump_file_write(wdh, &file_header, sizeof(file_header), err)) {
644 wdh->bytes_dumped += sizeof(file_header);
646 /* write the comment TLV */
648 TLV_HEADER_TO_LE_IN_PLACE(comment_header);
649 if (!wtap_dump_file_write(wdh, &comment_header, sizeof(comment_header), err)) {
652 wdh->bytes_dumped += sizeof(comment_header);
654 if (!wtap_dump_file_write(wdh, &comment, comment_length, err)) {
657 wdh->bytes_dumped += comment_length;
660 /* write the time info TLV */
662 TLV_TIME_INFO_TO_LE_IN_PLACE(time_header);
663 if (!wtap_dump_file_write(wdh, &time_header, sizeof(time_header), err)) {
666 wdh->bytes_dumped += sizeof(time_header);
669 init_gmt_to_localtime_offset();
674 /* Write a record for a packet to a dump file.
675 Returns TRUE on success, FALSE on failure. */
676 static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
678 int *err, gchar **err_info _U_)
680 observer_dump_private_state * private_state = NULL;
681 packet_entry_header packet_header;
682 guint64 seconds_since_2000;
684 /* We can only write packet records. */
685 if (phdr->rec_type != REC_TYPE_PACKET) {
686 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
690 /* The captured size field is 16 bits, so there's a hard limit of
692 if (phdr->caplen > 65535) {
693 *err = WTAP_ERR_PACKET_TOO_LARGE;
697 /* convert the number of seconds since epoch from ANSI-relative to
699 if (phdr->ts.secs < ansi_to_observer_epoch_offset) {
700 if(phdr->ts.secs > (time_t) 0) {
701 seconds_since_2000 = phdr->ts.secs;
703 seconds_since_2000 = (time_t) 0;
706 seconds_since_2000 = phdr->ts.secs - ansi_to_observer_epoch_offset;
709 /* populate the fields of the packet header */
710 private_state = (observer_dump_private_state *) wdh->priv;
712 memset(&packet_header, 0x00, sizeof(packet_header));
713 packet_header.packet_magic = observer_packet_magic;
714 packet_header.network_speed = 1000000;
715 packet_header.captured_size = (guint16) phdr->caplen;
716 packet_header.network_size = (guint16) (phdr->len + 4);
717 packet_header.offset_to_frame = sizeof(packet_header);
718 /* XXX - what if this doesn't fit in 16 bits? It's not guaranteed to... */
719 packet_header.offset_to_next_packet = (guint16)sizeof(packet_header) + phdr->caplen;
720 packet_header.network_type = private_state->network_type;
721 packet_header.flags = 0x00;
722 packet_header.number_of_information_elements = 0;
723 packet_header.packet_type = PACKET_TYPE_DATA_PACKET;
724 packet_header.packet_number = private_state->packet_count;
725 packet_header.original_packet_number = packet_header.packet_number;
726 packet_header.nano_seconds_since_2000 = seconds_since_2000 * 1000000000 + phdr->ts.nsecs;
728 private_state->packet_count++;
730 /* write the packet header */
731 PACKET_ENTRY_HEADER_TO_LE_IN_PLACE(packet_header);
732 if (!wtap_dump_file_write(wdh, &packet_header, sizeof(packet_header), err)) {
735 wdh->bytes_dumped += sizeof(packet_header);
737 /* write the packet data */
738 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err)) {
741 wdh->bytes_dumped += phdr->caplen;
746 static gint observer_to_wtap_encap(int observer_encap)
748 switch(observer_encap) {
749 case OBSERVER_ETHERNET:
750 return WTAP_ENCAP_ETHERNET;
751 case OBSERVER_TOKENRING:
752 return WTAP_ENCAP_TOKEN_RING;
753 case OBSERVER_FIBRE_CHANNEL:
754 return WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS;
755 case OBSERVER_WIRELESS_802_11:
756 return WTAP_ENCAP_IEEE_802_11_WITH_RADIO;
757 case OBSERVER_UNDEFINED:
758 return WTAP_ENCAP_UNKNOWN;
760 return WTAP_ENCAP_UNKNOWN;
763 static gint wtap_to_observer_encap(int wtap_encap)
766 case WTAP_ENCAP_ETHERNET:
767 return OBSERVER_ETHERNET;
768 case WTAP_ENCAP_TOKEN_RING:
769 return OBSERVER_TOKENRING;
770 case WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS:
771 return OBSERVER_FIBRE_CHANNEL;
772 case WTAP_ENCAP_UNKNOWN:
773 return OBSERVER_UNDEFINED;
775 return OBSERVER_UNDEFINED;
779 * Editor modelines - http://www.wireshark.org/tools/modelines.html
784 * indent-tabs-mode: nil
787 * vi: set shiftwidth=4 tabstop=8 expandtab:
788 * :indentSize=4:tabSize=8:noTabs=true: