#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
+
+/*
+ * Just make sure we include the prototype for strptime as well
+ * (needed for glibc 2.2) but make sure we do this only if not
+ * yet defined.
+ */
+
+#ifndef __USE_XOPEN
+# define __USE_XOPEN
+#endif
+
+#include <time.h>
#include <glib.h>
#ifdef HAVE_UNISTD_H
#endif
-/*
- * Just make sure we include the prototype for strptime as well
- * (needed for glibc 2.2)
- */
-#define __USE_XOPEN
-#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#include <string.h>
#include "wtap.h"
#ifdef NEED_GETOPT_H
# include "strptime.h"
#endif
-#include "epan/crypt-md5.h"
+#include "epan/crypt/crypt-md5.h"
+#include "epan/plugins.h"
+#include "epan/report_err.h"
+#include "epan/filesystem.h"
+#include <epan/privileges.h>
+#include "epan/nstime.h"
#include "svnversion.h"
int is_negative;
};
-static struct select_item selectfrm[100];
+#define MAX_SELECTIONS 512
+static struct select_item selectfrm[MAX_SELECTIONS];
static int max_selected = -1;
static int keep_em = 0;
static int out_file_type = WTAP_FILE_PCAP; /* default to "libpcap" */
static gboolean check_startstop = FALSE;
static gboolean dup_detect = FALSE;
-/* Add a selection item, a simple parser for now */
+static int find_dct2000_real_data(guint8 *buf);
-static void add_selection(char *sel)
+/* Add a selection item, a simple parser for now */
+static gboolean
+add_selection(char *sel)
{
char *locn;
char *next;
- if (max_selected == (sizeof(selectfrm)/sizeof(struct select_item)) - 1)
- return;
+ if (++max_selected >= MAX_SELECTIONS) {
+ /* Let the user know we stopped selecting */
+ printf("Out of room for packet selections!\n");
+ return(FALSE);
+ }
printf("Add_Selected: %s\n", sel);
printf("Not inclusive ...");
- max_selected++;
selectfrm[max_selected].inclusive = 0;
selectfrm[max_selected].first = atoi(sel);
printf("Inclusive ...");
next = locn + 1;
- max_selected++;
selectfrm[max_selected].inclusive = 1;
selectfrm[max_selected].first = atoi(sel);
selectfrm[max_selected].second = atoi(next);
}
-
+ return(TRUE);
}
/* Was the packet selected? */
-static int selected(int recno)
+static int
+selected(int recno)
{
int i = 0;
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) {
- struct wtap_pkthdr* pkthdr = wtap_phdr(wth);
- 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;
}
}
-int main(int argc, char *argv[])
+/*
+ * 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 _U_, va_list ap _U_)
+{
+ return;
+}
+int
+main(int argc, char *argv[])
{
wtap *wth;
int i, j, err;
unsigned int choplen = 0; /* No chop */
wtap_dumper *pdh;
int count = 1;
- long data_offset;
+ gint64 data_offset;
struct wtap_pkthdr snap_phdr;
const struct wtap_pkthdr *phdr;
int err_type;
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;
+#endif
- /* Process the options first */
+ /*
+ * 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();
+ }
+#endif
- while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:t:T:v")) !=-1) {
+ /* Process the options */
+ 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(time(NULL) + getpid());
+ 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);
- 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);
- 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);
+ 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);
}
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++)
- add_selection(argv[i]);
+ if (add_selection(argv[i]) == FALSE)
+ 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;
+ }
- fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
- wtap_strerror(err));
- exit(1);
- }
+ 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 */
- sprintf(filename, "%s-%05d",argv[optind+1], count / split_packet_count);
+ 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);
+ }
- 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);
- pdh = wtap_dump_open(filename, out_file_type,
- out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
- if (pdh == NULL) {
+ if (pdh == NULL) {
+ fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
+ }
+ }
- 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)) {
- }
+ fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
+
+ g_snprintf(filename, filenamelen, "%s-%05d",argv[optind+1], count / split_packet_count);
+
+ 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);
+ if (pdh == NULL) {
+
+ fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
+ wtap_strerror(err));
+ exit(1);
+ }
}
- if ( ((check_startstop && check_timestamp(wth)) || (!check_startstop && !check_timestamp(wth))) && ((!selected(count) && !keep_em) ||
+ check_ts = check_timestamp(wth);
+
+ if ( ((check_startstop && check_ts) || (!check_startstop && !check_ts)) && ((!selected(count) && !keep_em) ||
(selected(count) && keep_em)) ) {
if (verbose)
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;
+}