Make Content-Length and Max-Forwards fields uints
[obnox/wireshark/wip.git] / editcap.c
index d4598534840fb750f06012c660e78ffafe417274..791689c6cac1679da9cede85e54dba4e59aff6c7 100644 (file)
--- a/editcap.c
+++ b/editcap.c
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <glib.h>
 
 #ifdef HAVE_UNISTD_H
 #include <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>
 #include <process.h>    /* getpid */
 #endif
 
+#ifdef NEED_STRPTIME_H
+# include "strptime.h"
+#endif
+
+#include "epan/crypt-md5.h"
+
 #include "svnversion.h"
 
 /*
@@ -49,6 +63,19 @@ struct select_item {
 
 };
 
+
+/*
+ * Duplicate frame detection
+ */
+typedef struct _fd_hash_t {
+  md5_byte_t digest[16];
+  guint32 len;
+} fd_hash_t;
+
+#define DUP_DEPTH 5
+fd_hash_t fd_hash[DUP_DEPTH];
+int cur_dup = 0;
+
 #define ONE_MILLION 1000000
 
 /* Weights of different errors we can introduce */
@@ -78,6 +105,10 @@ static int out_frame_type = -2;              /* Leave frame type alone */
 static int verbose = 0;                      /* Not so verbose         */
 static struct time_adjustment time_adj = {{0, 0}, 0}; /* no adjustment */
 static double err_prob = 0.0;
+static time_t starttime = 0;
+static time_t stoptime = 0;
+static gboolean check_startstop = FALSE;
+static gboolean dup_detect = FALSE;
 
 /* Add a selection item, a simple parser for now */
 
@@ -141,6 +172,12 @@ static int selected(int recno)
 
 }
 
+/* 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 void
 set_time_adjustment(char *optarg)
 {
@@ -207,6 +244,36 @@ set_time_adjustment(char *optarg)
   time_adj.tv.tv_usec = val;
 }
 
+static gboolean
+is_duplicate(guint8* fd, guint32 len) {
+  int i;
+  md5_state_t ms;
+
+  cur_dup++;
+  if (cur_dup >= DUP_DEPTH)
+    cur_dup = 0;
+
+  /* Calculate our digest */
+  md5_init(&ms);
+  md5_append(&ms, fd, len);
+  md5_finish(&ms, fd_hash[cur_dup].digest);
+
+  fd_hash[cur_dup].len = len;
+
+  /* Look for duplicates */
+  for (i = 0; i < DUP_DEPTH; i++) {
+    if (i == cur_dup)
+      continue;
+
+    if (fd_hash[i].len == fd_hash[cur_dup].len &&
+        memcmp(fd_hash[i].digest, fd_hash[cur_dup].digest, 16) == 0) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 static void usage(void)
 {
   fprintf(stderr, "Editcap %s"
@@ -215,7 +282,7 @@ static void usage(void)
 #endif
          "\n", VERSION);
   fprintf(stderr, "Edit and/or translate the format of capture files.\n");
-  fprintf(stderr, "See http://www.ethereal.com for more information.\n");
+  fprintf(stderr, "See http://www.wireshark.org for more information.\n");
   fprintf(stderr, "\n");
   fprintf(stderr, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
   fprintf(stderr, "\n");
@@ -223,12 +290,17 @@ static void usage(void)
   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, "  -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, "\n");
   fprintf(stderr, "Output File(s):\n");
   fprintf(stderr, "  -c <packets per file>  split the packet output to different files,\n");
@@ -245,33 +317,28 @@ static void usage(void)
   fprintf(stderr, "\n");
 }
 
+static void list_capture_types(void) {
+    int i;
 
-static void bad_option_help(int bad_opt) {
-  int i;
-  const char *string;
-
-
-  switch(bad_opt) {
-  case'F':
-    fprintf(stderr, "The available capture file types for \"F\":\n");
+    fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
     for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
       if (wtap_dump_can_open(i))
         fprintf(stderr, "    %s - %s\n",
           wtap_file_type_short_string(i), wtap_file_type_string(i));
     }
-    break;
-  case'T':
-    fprintf(stderr, "The available encapsulation types for \"T\":\n");
+}
+
+static void list_encap_types(void) {
+    int i;
+    const char *string;
+
+    fprintf(stderr, "editcap: The available encapsulation types for \"T\":\n");
     for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
         string = wtap_encap_short_string(i);
         if (string != NULL)
           fprintf(stderr, "    %s - %s\n",
             string, wtap_encap_string(i));
     }
-    break;
-  default:
-    usage();
-  }
 }
 
 int main(int argc, char *argv[])
@@ -299,7 +366,7 @@ int main(int argc, char *argv[])
 
   /* Process the options first */
 
-  while ((opt = getopt(argc, argv, "c:C:E:F:hrs:t:T:v")) !=-1) {
+  while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:t:T:v")) !=-1) {
 
     switch (opt) {
 
@@ -316,8 +383,9 @@ int main(int argc, char *argv[])
     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",
+       fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
            optarg);
+        list_capture_types();
        exit(1);
       }
       break;
@@ -345,8 +413,25 @@ int main(int argc, char *argv[])
       }
       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;
+      }
+      break;
+
     case '?':              /* Bad options if GNU getopt */
-      bad_option_help(optopt);
+      switch(optopt) {
+      case'F':
+        list_capture_types();
+        break;
+      case'T':
+        list_encap_types();
+        break;
+      default:
+        usage();
+      }
       exit(1);
       break;
 
@@ -375,8 +460,9 @@ int main(int argc, char *argv[])
     case 'T':
       out_frame_type = wtap_short_string_to_encap(optarg);
       if (out_frame_type < 0) {
-       fprintf(stderr, "editcap: \"%s\" isn't a valid encapsulation type\n",
+       fprintf(stderr, "editcap: \"%s\" isn't a valid encapsulation type\n\n",
            optarg);
+        list_encap_types();
        exit(1);
       }
       break;
@@ -385,6 +471,37 @@ int main(int argc, char *argv[])
       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;
+               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;
+               stoptime = mktime(&stoptm);
+               break;
+       }
     }
 
   }
@@ -400,6 +517,22 @@ int main(int argc, char *argv[])
 
   }
 
+  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);
+  }
+
+  if (starttime > stoptime) {
+         fprintf(stderr, "editcap: start time is after the stop time\n");
+         exit(1);
+  }
+
   wth = wtap_open_offline(argv[optind], &err, &err_info, FALSE);
 
   if (!wth) {
@@ -444,7 +577,7 @@ int main(int argc, char *argv[])
     } else {
       filename = argv[optind+1];
     }
-  
+
     pdh = wtap_dump_open(filename, out_file_type,
                         out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
     if (pdh == NULL) {
@@ -477,16 +610,16 @@ int main(int argc, char *argv[])
        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 ((!selected(count) && !keep_em) ||
-          (selected(count) && keep_em)) {
+      if ( ((check_startstop && check_timestamp(wth)) || (!check_startstop && !check_timestamp(wth))) && ((!selected(count) && !keep_em) ||
+          (selected(count) && keep_em)) {
 
         if (verbose)
           printf("Packet: %u\n", count);
@@ -541,6 +674,16 @@ int main(int argc, char *argv[])
           phdr = &snap_phdr;
         }
 
+       if (dup_detect) {
+         buf = wtap_buf_ptr(wth);
+         if (is_duplicate(buf, phdr->caplen)) {
+            if (verbose)
+              printf("Skipping duplicate: %u\n", count);
+            count++;
+           continue;
+          }
+       }
+
         if (err_prob > 0.0) {
           buf = wtap_buf_ptr(wth);
           for (i = 0; i < (int) phdr->caplen; i++) {
@@ -570,7 +713,7 @@ int main(int argc, char *argv[])
 
               if (err_type < ERR_WT_FMT) {
                 if ((unsigned int)i < phdr->caplen - 2)
-                  strcpy(&buf[i],  "%s");
+                  strcpy((char*) &buf[i],  "%s");
                 err_type = ERR_WT_TOTAL;
               } else {
                 err_type -= ERR_WT_FMT;