#include "epan/plugins.h"
#include "epan/report_err.h"
#include "epan/filesystem.h"
+#include <epan/privileges.h>
+#include "epan/nstime.h"
#include "svnversion.h"
static gboolean check_startstop = FALSE;
static gboolean dup_detect = FALSE;
+static int find_dct2000_real_data(guint8 *buf);
+
/* Add a selection item, a simple parser for now */
static gboolean
add_selection(char *sel)
if (selectfrm[i].inclusive) {
if (selectfrm[i].first <= recno && selectfrm[i].second >= recno)
- return 1;
+ return 1;
}
else {
if (recno == selectfrm[i].first)
- return 1;
+ return 1;
}
}
}
/* is the packet in the selected timeframe */
-static gboolean check_timestamp(wtap *wth) {
- static int i = 0;
- struct wtap_pkthdr* pkthdr = wtap_phdr(wth);
- if (!((i++)%250)) printf("== %d starttime=%lu stoptime=%lu ts=%lu",i,starttime,stoptime,pkthdr->ts.secs);
- return ( (time_t) pkthdr->ts.secs >= starttime ) && ( (time_t) pkthdr->ts.secs <= stoptime );
+static gboolean
+check_timestamp(wtap *wth)
+{
+ struct wtap_pkthdr* pkthdr = wtap_phdr(wth);
+
+ return ( pkthdr->ts.secs >= starttime ) && ( pkthdr->ts.secs <= stoptime );
}
static void
return FALSE;
}
-static void usage(void)
+static void
+usage(void)
{
fprintf(stderr, "Editcap %s"
#ifdef SVNVERSION
fprintf(stderr, "\n");
fprintf(stderr, "A single packet or a range of packets can be selected.\n");
fprintf(stderr, "\n");
- fprintf(stderr, "Packets:\n");
- fprintf(stderr, " -C <choplen> chop each packet at the end by <choplen> bytes\n");
- fprintf(stderr, " -d remove duplicate packets\n");
- fprintf(stderr, " -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
- fprintf(stderr, " that a particular packet byte will be randomly changed\n");
+ fprintf(stderr, "Packet selection:\n");
fprintf(stderr, " -r keep the selected packets, default is to delete them\n");
- fprintf(stderr, " -s <snaplen> truncate packets to max. <snaplen> bytes of data\n");
- fprintf(stderr, " -t <time adjustment> adjust the timestamp of selected packets,\n");
- fprintf(stderr, " <time adjustment> is in relative seconds (e.g. -0.5)\n");
fprintf(stderr, " -A <start time> don't output packets whose timestamp is before the\n");
fprintf(stderr, " given time (format as YYYY-MM-DD hh:mm:ss)\n");
fprintf(stderr, " -B <stop time> don't output packets whose timestamp is after the\n");
fprintf(stderr, " given time (format as YYYY-MM-DD hh:mm:ss)\n");
+ fprintf(stderr, " -d remove duplicate packets\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Packet manipulation:\n");
+ fprintf(stderr, " -s <snaplen> truncate each packet to max. <snaplen> bytes of data\n");
+ fprintf(stderr, " -C <choplen> chop each packet at the end by <choplen> bytes\n");
+ fprintf(stderr, " -t <time adjustment> adjust the timestamp of each packet,\n");
+ fprintf(stderr, " <time adjustment> is in relative seconds (e.g. -0.5)\n");
+ fprintf(stderr, " -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
+ fprintf(stderr, " that a particular packet byte will be randomly changed\n");
fprintf(stderr, "\n");
fprintf(stderr, "Output File(s):\n");
fprintf(stderr, " -c <packets per file> split the packet output to different files,\n");
+ fprintf(stderr, " based on uniform packet counts \n");
fprintf(stderr, " with a maximum of <packets per file> each\n");
+ fprintf(stderr, " -i <seconds per file> split the packet output to different files,\n");
+ fprintf(stderr, " based on uniform time intervals \n");
+ fprintf(stderr, " with a maximum of <seconds per file> each\n");
fprintf(stderr, " -F <capture type> set the output file type, default is libpcap\n");
fprintf(stderr, " an empty \"-F\" option will list the file types\n");
fprintf(stderr, " -T <encap type> set the output file encapsulation type,\n");
fprintf(stderr, "\n");
}
-static void list_capture_types(void) {
+static void
+list_capture_types(void) {
int i;
fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
}
}
-static void list_encap_types(void) {
+static void
+list_encap_types(void) {
int i;
const char *string;
}
}
+/*
+ * Don't report failures to load plugins because most (non-wiretap) plugins
+ * *should* fail to load (because we're not linked against libwireshark and
+ * dissector plugins need libwireshark).
+ */
static void
-failure_message(const char *msg_format, va_list ap)
+failure_message(const char *msg_format _U_, va_list ap _U_)
{
- fprintf(stderr, "editcap: ");
- vfprintf(stderr, msg_format, ap);
- fprintf(stderr, "\n");
+ return;
}
-int main(int argc, char *argv[])
-
+int
+main(int argc, char *argv[])
{
wtap *wth;
int i, j, err;
int split_packet_count = 0;
int written_count = 0;
char *filename;
+ size_t filenamelen = 0;
+ gboolean check_ts;
+ int secs_per_block = 0;
+ int block_cnt = 0;
+ nstime_t block_start;
+
#ifdef HAVE_PLUGINS
char* init_progfile_dir_error;
- gboolean check_ts;
-
+#endif
+
+ /*
+ * Get credential information for later use.
+ */
+ get_credential_info();
+
+#ifdef HAVE_PLUGINS
/* Register wiretap plugins */
if ((init_progfile_dir_error = init_progfile_dir(argv[0]))) {
- g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error);
- g_free(init_progfile_dir_error);
- } else {
- init_report_err(failure_message,NULL,NULL);
- init_plugins();
- register_all_wiretap_modules();
- }
+ g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error);
+ g_free(init_progfile_dir_error);
+ } else {
+ init_report_err(failure_message,NULL,NULL);
+ init_plugins();
+ }
#endif
-
+
/* Process the options */
- while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:t:T:v")) !=-1) {
+ while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:i:t:T:v")) !=-1) {
switch (opt) {
case 'E':
err_prob = strtod(optarg, &p);
if (p == optarg || err_prob < 0.0 || err_prob > 1.0) {
- fprintf(stderr, "editcap: probability \"%s\" must be between 0.0 and 1.0\n",
- optarg);
- exit(1);
+ fprintf(stderr, "editcap: probability \"%s\" must be between 0.0 and 1.0\n",
+ optarg);
+ exit(1);
}
srand( (unsigned int) (time(NULL) + getpid()) );
break;
case 'F':
out_file_type = wtap_short_string_to_file_type(optarg);
if (out_file_type < 0) {
- fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
- optarg);
+ fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
+ optarg);
list_capture_types();
- exit(1);
+ exit(1);
}
break;
case 'c':
split_packet_count = strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
- fprintf(stderr, "editcap: \"%s\" isn't a valid packet count\n",
- optarg);
- exit(1);
+ fprintf(stderr, "editcap: \"%s\" isn't a valid packet count\n",
+ optarg);
+ exit(1);
}
if (split_packet_count <= 0) {
- fprintf(stderr, "editcap: \"%d\" packet count must be larger than zero\n",
- split_packet_count);
- exit(1);
+ fprintf(stderr, "editcap: \"%d\" packet count must be larger than zero\n",
+ split_packet_count);
+ exit(1);
}
break;
case 'C':
choplen = strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
- fprintf(stderr, "editcap: \"%s\" isn't a valid chop length\n",
- optarg);
- exit(1);
+ fprintf(stderr, "editcap: \"%s\" isn't a valid chop length\n",
+ optarg);
+ exit(1);
}
break;
case 'd':
dup_detect = TRUE;
for (i = 0; i < DUP_DEPTH; i++) {
- memset(&fd_hash[i].digest, 0, 16);
- fd_hash[i].len = 0;
+ memset(&fd_hash[i].digest, 0, 16);
+ fd_hash[i].len = 0;
}
break;
case 's':
snaplen = strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
- fprintf(stderr, "editcap: \"%s\" isn't a valid snapshot length\n",
- optarg);
- exit(1);
+ fprintf(stderr, "editcap: \"%s\" isn't a valid snapshot length\n",
+ optarg);
+ exit(1);
}
break;
verbose = !verbose; /* Just invert */
break;
- case 'A':
- {
- struct tm starttm;
-
- memset(&starttm,0,sizeof(struct tm));
-
- if(!strptime(optarg,"%F %T",&starttm)) {
- fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
- optarg);
- exit(1);
- }
-
- check_startstop = TRUE;
- starttm.tm_isdst = -1;
-
- starttime = mktime(&starttm);
- printf("=START=> given='%s' stoptime=%lu\n",optarg,starttime);
- break;
- }
- case 'B':
- {
- struct tm stoptm;
-
- memset(&stoptm,0,sizeof(struct tm));
-
- if(!strptime(optarg,"%F %T",&stoptm)) {
- fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
- optarg);
- exit(1);
- }
- check_startstop = TRUE;
- stoptm.tm_isdst = -1;
- stoptime = mktime(&stoptm);
- printf("=STOP=> given='%s' stoptime=%lu\n",optarg,stoptime);
- break;
- }
+ case 'i': /* break capture file based on time interval */
+ secs_per_block = atoi(optarg);
+ nstime_set_unset(&block_start);
+ if(secs_per_block <= 0) {
+ fprintf(stderr, "editcap: \"%s\" isn't a valid time interval\n\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'A':
+ {
+ struct tm starttm;
+
+ memset(&starttm,0,sizeof(struct tm));
+
+ if(!strptime(optarg,"%Y-%m-%d %T",&starttm)) {
+ fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n", optarg);
+ exit(1);
+ }
+
+ check_startstop = TRUE;
+ starttm.tm_isdst = -1;
+
+ starttime = mktime(&starttm);
+ break;
+ }
+
+ case 'B':
+ {
+ struct tm stoptm;
+
+ memset(&stoptm,0,sizeof(struct tm));
+
+ if(!strptime(optarg,"%Y-%m-%d %T",&stoptm)) {
+ fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n", optarg);
+ exit(1);
+ }
+ check_startstop = TRUE;
+ stoptm.tm_isdst = -1;
+ stoptime = mktime(&stoptm);
+ break;
+ }
}
}
}
if (check_startstop && !stoptime) {
- struct tm stoptm;
- /* XXX: will work until 2035 */
- memset(&stoptm,0,sizeof(struct tm));
- stoptm.tm_year = 135;
- stoptm.tm_mday = 31;
- stoptm.tm_mon = 11;
-
- stoptime = mktime(&stoptm);
- printf("=STOP=NEVER=> stoptime=%lu\n",stoptime);
+ struct tm stoptm;
+ /* XXX: will work until 2035 */
+ memset(&stoptm,0,sizeof(struct tm));
+ stoptm.tm_year = 135;
+ stoptm.tm_mday = 31;
+ stoptm.tm_mon = 11;
+
+ stoptime = mktime(&stoptm);
}
if (starttime > stoptime) {
- fprintf(stderr, "editcap: start time is after the stop time\n");
- exit(1);
+ fprintf(stderr, "editcap: start time is after the stop time\n");
+ exit(1);
+ }
+
+ if (split_packet_count > 0 && secs_per_block > 0) {
+ fprintf(stderr, "editcap: can't split on both packet count and time interval\n");
+ fprintf(stderr, "editcap: at the same time\n");
+ exit(1);
}
- printf("==> stoptime=%lu stoptime=%lu\n",starttime,stoptime);
wth = wtap_open_offline(argv[optind], &err, &err_info, FALSE);
}
if (verbose) {
-
fprintf(stderr, "File %s is a %s capture file.\n", argv[optind],
- wtap_file_type_string(wtap_file_type(wth)));
-
+ wtap_file_type_string(wtap_file_type(wth)));
}
/*
out_frame_type = wtap_file_encap(wth);
if (split_packet_count > 0) {
- filename = (char *) malloc(strlen(argv[optind+1]) + 20);
+ filenamelen = strlen(argv[optind+1]) + 20;
+ filename = (char *) g_malloc(filenamelen);
if (!filename) {
- exit(5);
+ exit(5);
}
- sprintf(filename, "%s-%05d", argv[optind+1], 0);
+ g_snprintf(filename, filenamelen, "%s-%05d", argv[optind+1], 0);
} else {
- filename = argv[optind+1];
- }
+ if (secs_per_block > 0) {
+ filenamelen = strlen(argv[optind+1]) + 7;
+ filename = (char *) g_malloc(filenamelen);
+ if (!filename) {
+ exit(5);
+ }
+ g_snprintf(filename, filenamelen, "%s-%05d", argv[optind+1], block_cnt);
+ }
+ else {
+ filename = argv[optind+1];
+ }
+ }
pdh = wtap_dump_open(filename, out_file_type,
- out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
+ out_frame_type, wtap_snapshot_length(wth),
+ FALSE /* compressed */, &err);
if (pdh == NULL) {
fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
- wtap_strerror(err));
+ wtap_strerror(err));
exit(1);
-
}
for (i = optind + 2; i < argc; i++)
if (add_selection(argv[i]) == FALSE)
- break;
+ break;
while (wtap_read(wth, &err, &err_info, &data_offset)) {
- if (split_packet_count > 0 && (written_count % split_packet_count == 0)) {
- if (!wtap_dump_close(pdh, &err)) {
+ if (secs_per_block > 0) {
+ phdr = wtap_phdr(wth);
+
+ if (nstime_is_unset(&block_start)) { /* should only be the first packet */
+ block_start.secs = phdr->ts.secs;
+ block_start.nsecs = phdr->ts.nsecs;
+ }
+
+ while ((phdr->ts.secs - block_start.secs > secs_per_block) ||
+ (phdr->ts.secs - block_start.secs == secs_per_block &&
+ phdr->ts.nsecs >= block_start.nsecs )) { /* time for the next file */
+
+ if (!wtap_dump_close(pdh, &err)) {
+ fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
+ block_start.secs = block_start.secs + secs_per_block; /* reset for next interval */
+ g_snprintf(filename, filenamelen, "%s-%05d",argv[optind+1], ++block_cnt);
+
+ if (verbose) {
+ fprintf(stderr, "Continuing writing in file %s\n", filename);
+ }
+
+ pdh = wtap_dump_open(filename, out_file_type,
+ out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
- fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
- wtap_strerror(err));
- exit(1);
- }
+ if (pdh == NULL) {
+ fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
+ }
+ }
+
+ if (split_packet_count > 0 && (written_count % split_packet_count == 0)) {
+ if (!wtap_dump_close(pdh, &err)) {
- sprintf(filename, "%s-%05d",argv[optind+1], count / split_packet_count);
+ fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
- if (verbose) {
- fprintf(stderr, "Continuing writing in file %s\n", filename);
- }
+ g_snprintf(filename, filenamelen, "%s-%05d",argv[optind+1], count / split_packet_count);
- pdh = wtap_dump_open(filename, out_file_type,
- out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
- if (pdh == NULL) {
+ if (verbose) {
+ fprintf(stderr, "Continuing writing in file %s\n", filename);
+ }
- fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
- wtap_strerror(err));
- exit(1);
+ pdh = wtap_dump_open(filename, out_file_type,
+ out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
+ if (pdh == NULL) {
- }
+ fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
}
-
+
check_ts = check_timestamp(wth);
-
+
if ( ((check_startstop && check_ts) || (!check_startstop && !check_ts)) && ((!selected(count) && !keep_em) ||
(selected(count) && keep_em)) ) {
phdr = &snap_phdr;
}
- if (dup_detect) {
- buf = wtap_buf_ptr(wth);
- if (is_duplicate(buf, phdr->caplen)) {
+ if (dup_detect) {
+ buf = wtap_buf_ptr(wth);
+ if (is_duplicate(buf, phdr->caplen)) {
if (verbose)
printf("Skipping duplicate: %u\n", count);
count++;
- continue;
+ continue;
}
- }
+ }
+ /* Random error mutation */
if (err_prob > 0.0) {
+ int real_data_start = 0;
buf = wtap_buf_ptr(wth);
- for (i = 0; i < (int) phdr->caplen; i++) {
+ /* Protect non-protocol data */
+ if (wtap_file_type(wth) == WTAP_FILE_CATAPULT_DCT2000) {
+ real_data_start = find_dct2000_real_data(buf);
+ }
+ for (i = real_data_start; i < (int) phdr->caplen; i++) {
if (rand() <= err_prob * RAND_MAX) {
err_type = rand() / (RAND_MAX / ERR_WT_TOTAL + 1);
if (err_type < ERR_WT_FMT) {
if ((unsigned int)i < phdr->caplen - 2)
- strcpy((char*) &buf[i], "%s");
+ strncpy((char*) &buf[i], "%s", 2);
err_type = ERR_WT_TOTAL;
} else {
err_type -= ERR_WT_FMT;
if (!wtap_dump(pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth),
&err)) {
-
fprintf(stderr, "editcap: Error writing to %s: %s\n",
filename, wtap_strerror(err));
exit(1);
-
- }
-
- written_count++;
-
+ }
+ written_count++;
}
-
count++;
-
}
if (err != 0) {
/* Print a message noting that the read failed somewhere along the line. */
fprintf(stderr,
"editcap: An error occurred while reading \"%s\": %s.\n",
- argv[optind], wtap_strerror(err));
+ argv[optind], wtap_strerror(err));
switch (err) {
case WTAP_ERR_UNSUPPORTED:
case WTAP_ERR_UNSUPPORTED_ENCAP:
case WTAP_ERR_BAD_RECORD:
- fprintf(stderr, "(%s)\n", err_info);
- break;
+ fprintf(stderr, "(%s)\n", err_info);
+ g_free(err_info);
+ break;
}
}
if (!wtap_dump_close(pdh, &err)) {
fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
- wtap_strerror(err));
+ wtap_strerror(err));
exit(1);
}
return 0;
}
+/* Skip meta-information read from file to return offset of real
+ protocol data */
+static int find_dct2000_real_data(guint8 *buf)
+{
+ int n=0;
+
+ for (n=0; buf[n] != '\0'; n++); /* Context name */
+ n++;
+ n++; /* Context port number */
+ for (; buf[n] != '\0'; n++); /* Timestamp */
+ n++;
+ for (; buf[n] != '\0'; n++); /* Protocol name */
+ n++;
+ for (; buf[n] != '\0'; n++); /* Variant number (as string) */
+ n++;
+ for (; buf[n] != '\0'; n++); /* Outhdr (as string) */
+ n++;
+ n += 2; /* Direction & encap */
+
+ return n;
+}