+ if (ts_okay && ((!selected(count) && !keep_em)
+ || (selected(count) && keep_em))) {
+
+ if (verbose && !dup_detect && !dup_detect_by_time)
+ fprintf(stderr, "Packet: %u\n", count);
+
+ /* We simply write it, perhaps after truncating it; we could
+ * do other things, like modify it. */
+
+ rec = wtap_get_rec(wth);
+
+ if (rec->presence_flags & WTAP_HAS_TS) {
+ /* Do we adjust timestamps to ensure strict chronological
+ * order? */
+ if (do_strict_time_adjustment) {
+ if (previous_time.secs || previous_time.nsecs) {
+ if (!strict_time_adj.is_negative) {
+ nstime_t current;
+ nstime_t delta;
+
+ current = rec->ts;
+
+ nstime_delta(&delta, ¤t, &previous_time);
+
+ if (delta.secs < 0 || delta.nsecs < 0) {
+ /*
+ * A negative delta indicates that the current packet
+ * has an absolute timestamp less than the previous packet
+ * that it is being compared to. This is NOT a normal
+ * situation since trace files usually have packets in
+ * chronological order (oldest to newest).
+ * Copy and change rather than modify
+ * returned rec.
+ */
+ /* fprintf(stderr, "++out of order, need to adjust this packet!\n"); */
+ temp_rec = *rec;
+ temp_rec.ts.secs = previous_time.secs + strict_time_adj.tv.secs;
+ temp_rec.ts.nsecs = previous_time.nsecs;
+ if (temp_rec.ts.nsecs + strict_time_adj.tv.nsecs >= ONE_BILLION) {
+ /* carry */
+ temp_rec.ts.secs++;
+ temp_rec.ts.nsecs += strict_time_adj.tv.nsecs - ONE_BILLION;
+ } else {
+ temp_rec.ts.nsecs += strict_time_adj.tv.nsecs;
+ }
+ rec = &temp_rec;
+ }
+ } else {
+ /*
+ * A negative strict time adjustment is requested.
+ * Unconditionally set each timestamp to previous
+ * packet's timestamp plus delta.
+ * Copy and change rather than modify returned
+ * rec.
+ */
+ temp_rec = *rec;
+ temp_rec.ts.secs = previous_time.secs + strict_time_adj.tv.secs;
+ temp_rec.ts.nsecs = previous_time.nsecs;
+ if (temp_rec.ts.nsecs + strict_time_adj.tv.nsecs >= ONE_BILLION) {
+ /* carry */
+ temp_rec.ts.secs++;
+ temp_rec.ts.nsecs += strict_time_adj.tv.nsecs - ONE_BILLION;
+ } else {
+ temp_rec.ts.nsecs += strict_time_adj.tv.nsecs;
+ }
+ rec = &temp_rec;
+ }
+ }
+ previous_time = rec->ts;
+ }
+
+ if (time_adj.tv.secs != 0) {
+ /* Copy and change rather than modify returned rec */
+ temp_rec = *rec;
+ if (time_adj.is_negative)
+ temp_rec.ts.secs -= time_adj.tv.secs;
+ else
+ temp_rec.ts.secs += time_adj.tv.secs;
+ rec = &temp_rec;
+ }
+
+ if (time_adj.tv.nsecs != 0) {
+ /* Copy and change rather than modify returned rec */
+ temp_rec = *rec;
+ if (time_adj.is_negative) { /* subtract */
+ if (temp_rec.ts.nsecs < time_adj.tv.nsecs) { /* borrow */
+ temp_rec.ts.secs--;
+ temp_rec.ts.nsecs += ONE_BILLION;
+ }
+ temp_rec.ts.nsecs -= time_adj.tv.nsecs;
+ } else { /* add */
+ if (temp_rec.ts.nsecs + time_adj.tv.nsecs >= ONE_BILLION) {
+ /* carry */
+ temp_rec.ts.secs++;
+ temp_rec.ts.nsecs += time_adj.tv.nsecs - ONE_BILLION;
+ } else {
+ temp_rec.ts.nsecs += time_adj.tv.nsecs;
+ }
+ }
+ rec = &temp_rec;
+ }
+ } /* time stamp adjustment */
+
+ if (rec->rec_type == REC_TYPE_PACKET) {
+ if (snaplen != 0) {
+ /* Limit capture length to snaplen */
+ if (rec->rec_header.packet_header.caplen > snaplen) {
+ /* Copy and change rather than modify returned wtap_rec */
+ temp_rec = *rec;
+ temp_rec.rec_header.packet_header.caplen = snaplen;
+ rec = &temp_rec;
+ }
+ /* If -L, also set reported length to snaplen */
+ if (adjlen && rec->rec_header.packet_header.len > snaplen) {
+ /* Copy and change rather than modify returned phdr */
+ temp_rec = *rec;
+ temp_rec.rec_header.packet_header.len = snaplen;
+ rec = &temp_rec;
+ }
+ }
+
+ /*
+ * CHOP
+ * Copy and change rather than modify returned phdr.
+ */
+ temp_rec = *rec;
+ handle_chopping(chop, &temp_rec.rec_header.packet_header,
+ &rec->rec_header.packet_header, &buf,
+ adjlen);
+ rec = &temp_rec;
+
+ /* remove vlan info */
+ if (rem_vlan) {
+ /* Copy and change rather than modify returned rec */
+ temp_rec = *rec;
+ remove_vlan_info(&rec->rec_header.packet_header, buf,
+ &temp_rec.rec_header.packet_header.caplen);
+ rec = &temp_rec;
+ }
+
+ /* suppress duplicates by packet window */
+ if (dup_detect) {
+ if (is_duplicate(buf, rec->rec_header.packet_header.caplen)) {
+ if (verbose) {
+ fprintf(stderr, "Skipped: %u, Len: %u, MD5 Hash: ",
+ count,
+ rec->rec_header.packet_header.caplen);
+ for (i = 0; i < 16; i++)
+ fprintf(stderr, "%02x",
+ (unsigned char)fd_hash[cur_dup_entry].digest[i]);
+ fprintf(stderr, "\n");
+ }
+ duplicate_count++;
+ count++;
+ continue;
+ } else {
+ if (verbose) {
+ fprintf(stderr, "Packet: %u, Len: %u, MD5 Hash: ",
+ count,
+ rec->rec_header.packet_header.caplen);
+ for (i = 0; i < 16; i++)
+ fprintf(stderr, "%02x",
+ (unsigned char)fd_hash[cur_dup_entry].digest[i]);
+ fprintf(stderr, "\n");
+ }
+ }
+ } /* suppression of duplicates */
+
+ if (rec->presence_flags & WTAP_HAS_TS) {
+ /* suppress duplicates by time window */
+ if (dup_detect_by_time) {
+ nstime_t current;
+
+ current.secs = rec->ts.secs;
+ current.nsecs = rec->ts.nsecs;
+
+ if (is_duplicate_rel_time(buf,
+ rec->rec_header.packet_header.caplen,
+ ¤t)) {
+ if (verbose) {
+ fprintf(stderr, "Skipped: %u, Len: %u, MD5 Hash: ",
+ count,
+ rec->rec_header.packet_header.caplen);
+ for (i = 0; i < 16; i++)
+ fprintf(stderr, "%02x",
+ (unsigned char)fd_hash[cur_dup_entry].digest[i]);
+ fprintf(stderr, "\n");
+ }
+ duplicate_count++;
+ count++;
+ continue;
+ } else {
+ if (verbose) {
+ fprintf(stderr, "Packet: %u, Len: %u, MD5 Hash: ",
+ count,
+ rec->rec_header.packet_header.caplen);
+ for (i = 0; i < 16; i++)
+ fprintf(stderr, "%02x",
+ (unsigned char)fd_hash[cur_dup_entry].digest[i]);
+ fprintf(stderr, "\n");
+ }
+ }
+ }
+ } /* suppress duplicates by time window */
+ }
+
+ /* Random error mutation */
+ do_mutation = FALSE;
+ caplen = 0;
+ if (err_prob > 0.0) {
+ switch (rec->rec_type) {
+
+ case REC_TYPE_PACKET:
+ caplen = rec->rec_header.packet_header.caplen;
+ do_mutation = TRUE;
+ break;
+
+ case REC_TYPE_FT_SPECIFIC_EVENT:
+ case REC_TYPE_FT_SPECIFIC_REPORT:
+ caplen = rec->rec_header.ft_specific_header.record_len;
+ do_mutation = TRUE;
+ break;
+
+ case REC_TYPE_SYSCALL:
+ caplen = rec->rec_header.syscall_header.event_filelen;
+ do_mutation = TRUE;
+ break;
+ }
+
+ if (change_offset > caplen) {
+ fprintf(stderr, "change offset %u is longer than caplen %u in packet %u\n",
+ change_offset, caplen, count);
+ do_mutation = FALSE;
+ }
+ }
+
+ if (do_mutation) {
+ int real_data_start = 0;
+
+ /* Protect non-protocol data */
+ switch (rec->rec_type) {
+
+ case REC_TYPE_PACKET:
+ if (wtap_file_type_subtype(wth) == WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000)
+ real_data_start = find_dct2000_real_data(buf);
+ break;
+ }
+
+ real_data_start += change_offset;
+
+ for (i = real_data_start; i < (int) caplen; i++) {
+ if (rand() <= err_prob * RAND_MAX) {
+ err_type = rand() / (RAND_MAX / ERR_WT_TOTAL + 1);
+
+ if (err_type < ERR_WT_BIT) {
+ buf[i] ^= 1 << (rand() / (RAND_MAX / 8 + 1));
+ err_type = ERR_WT_TOTAL;
+ } else {
+ err_type -= ERR_WT_BYTE;
+ }
+
+ if (err_type < ERR_WT_BYTE) {
+ buf[i] = rand() / (RAND_MAX / 255 + 1);
+ err_type = ERR_WT_TOTAL;
+ } else {
+ err_type -= ERR_WT_BYTE;
+ }
+
+ if (err_type < ERR_WT_ALNUM) {
+ buf[i] = ALNUM_CHARS[rand() / (RAND_MAX / ALNUM_LEN + 1)];
+ err_type = ERR_WT_TOTAL;
+ } else {
+ err_type -= ERR_WT_ALNUM;
+ }
+
+ if (err_type < ERR_WT_FMT) {
+ if ((unsigned int)i < caplen - 2)
+ g_strlcpy((char*) &buf[i], "%s", 2);
+ err_type = ERR_WT_TOTAL;
+ } else {
+ err_type -= ERR_WT_FMT;
+ }
+
+ if (err_type < ERR_WT_AA) {
+ for (j = i; j < (int) caplen; j++)
+ buf[j] = 0xAA;
+ i = caplen;
+ }
+ }
+ }
+ } /* random error mutation */
+
+ /* Find a packet comment we may need to write */
+ if (frames_user_comments) {
+ const char *comment =
+ (const char*)g_tree_lookup(frames_user_comments, GUINT_TO_POINTER(read_count));
+ /* XXX: What about comment changed to no comment? */
+ if (comment != NULL) {
+ /* Copy and change rather than modify returned rec */
+ temp_rec = *rec;
+ temp_rec.opt_comment = g_strdup(comment);
+ temp_rec.has_comment_changed = TRUE;
+ rec = &temp_rec;
+ } else {
+ /* Copy and change rather than modify returned rec */
+ temp_rec = *rec;
+ temp_rec.has_comment_changed = FALSE;
+ rec = &temp_rec;
+ }
+ }
+
+ /* Attempt to dump out current frame to the output file */
+ if (!wtap_dump(pdh, rec, buf, &write_err, &write_err_info)) {
+ cfile_write_failure_message("editcap", argv[optind],
+ filename,
+ write_err, write_err_info,
+ read_count,
+ out_file_type_subtype);
+ ret = DUMP_ERROR;
+ goto clean_exit;
+ }
+ written_count++;