Main Page | Alphabetical List | Class List | File List | Class Members | File Members

anon.c

Go to the documentation of this file.
00001 #include <pcap.h>
00002 #include <stdio.h>
00003 #include <unistd.h>
00004 #include <string.h>
00005 #include <stdlib.h>
00006 
00007 /* For sigaction */
00008 #include <signal.h>
00009 
00010 /* For inet_ntoa() */
00011 #include <sys/socket.h>
00012 #include <netinet/in.h>
00013 #include <arpa/inet.h>
00014 
00015 /* For ETHERTYPE_IP */
00016 #include <net/ethernet.h>
00017 
00018 /* For struct tm */
00019 #include <sys/time.h>
00020 
00021 //For va_list...
00022 #include <stdarg.h>
00023 
00024 #include <time.h>
00025 
00026 /* For pow() */
00027 #include <math.h>
00028 
00029 #define _GNU_SOURCE
00030 #include <getopt.h>
00031 
00032 #include "anon.h"
00033 
00034 int nb_response = 0;
00035 int nb_request = 0;
00036 
00037 char *input_file_size_s=NULL;
00038 int input_file_size=0;
00039 int input_file_read=0;
00040 int input_file_last=0;
00041 int input_file_size_1pct=0;
00042 int output_file_written=0;
00043 time_t start_time;
00044 time_t end_time;
00045 
00046 #define FIRST_ANON_IP "10.0.0.1"
00047 #define FIRST_ANON_PORT 300
00048 
00049 int debug=0;
00050 
00051 int do_stats=1;
00052 int anonymise = 1;
00053 int anonymise_mac = 1;
00054 int anonymise_port = 1;
00055 int anonymise_date = 1;
00056 int anonymise_timestamp = 1;
00057 int anonymise_url = 1;
00058 int anonymise_http = 1;
00059 int anonymise_ip = 1;
00060 int anonymise_content = 1;
00061 int anonymise_checksum = 1;
00062 int anonymise_sequence = 1;
00063 int display=1;
00064 int display_flags=1;
00065 int display_tcp_infos=1;
00066 int display_timestamp=1;
00067 int display_progress=1;
00068 int display_http=1;
00069 int display_http_only=0;
00070 int display_unanswered_requests=0;
00071 int display_raw_stats=0;
00072 
00073 int already_anonymised=0;
00074 int use_sequence_numbers=0;
00075 int truncate_packet=0;
00076 int nbip = 0;                   /* Number of IP that have been anonymised */
00077 int nbports = 0;                /* Number of ports that have been anonymised */
00078 int nburl=0;                    /* Number of URLs that have been anonymised */
00079 char *ip_table = NULL;
00080 char *port_table = NULL;
00081 char *anon_url_table=NULL;
00082 double pct_treshold=0;
00083 
00084 string_and_nb *server_version_table=NULL;
00085 string_and_nb *server_version_simple_table=NULL;
00086 string_and_nb *http_response_code_table=NULL;
00087 string_and_nb *http_version_table=NULL;
00088 string_and_nb *user_agent_table=NULL;
00089 string_and_nb *extension_table=NULL;
00090 string_and_nb *content_type_table=NULL;
00091 string_and_nb *content_type_simple_table=NULL;
00092 string_and_nb *header_table=NULL;
00093 string_and_nb *sequence_number_table=NULL;
00094 string_and_nb *suffix_table=NULL;
00095 nb_table cl_table={0, NULL};
00096 nb_table fresh_table={0, NULL};
00097 nb_table latency_table={0, NULL};
00098 
00099 struct dialog *dialog_table=NULL;
00100 u_int32_t firstanonip = 0;
00101 int32_t timeoffset=0;
00102 int32_t timeoffset_usec=0;
00103 int date_offset=0;
00104 u_int32_t rand_seq_nb=0;
00105 
00106 int maxpacketsize = 65536;
00107 int maxfilesize=0;
00108 int nbpackets = 0;
00109 int nbvalidpackets = 0;
00110 int nbpacketstocapture = -1;    //We capture an infinite number of packets by default
00111 
00112 int max_display_space=0;
00113 
00114 FILE *output_stream;
00115 char *ofile = NULL;
00116 char *ifile = NULL;
00117 pcap_t *adhandle = NULL;
00118 pcap_dumper_t *dumphandle;
00119 pcap_if_t *alldevs = NULL;
00120 
00121 char *fields_to_anonymise[]= { "Host: ", "Client-IP: ", "From: ", 
00122     "Location: ", "Content-Location: ","ETag: ", "If-None-Match: ",
00123     "Referer: ", "Age: ", "Title: ", 
00124     "Expires: ", "Last-Modified: ", "If-Modified-Since: ", "Cookie: ", "Set-Cookie: ", "Date: ", "GET ", "WWW-Authenticate: ", "PPServer: "};
00125 
00126 #define print(format, args...) fprintf(output_stream, format, ##args)
00127 
00128 #define nb_fields_to_anonymise (sizeof(fields_to_anonymise)/sizeof(fields_to_anonymise[0]))
00129 
00130 #define get_string_from_args(s)\
00131 {\
00132  int n, size = 8000;                                                                    \
00133  char *p; va_list ap;                                                                   \
00134  if ((p = malloc (size+1)) == NULL) {va_end(ap);s=NULL;}\
00135  else{                                                                                                  \
00136  while (1) {                                                                                    \
00137         va_start(ap, fmt); n = vsnprintf (p, size, fmt, ap); va_end(ap);                                 \
00138         if (n > -1 && n < size) {va_end(ap);p=realloc(p, n+1);*(p+n)=0;s=p;break;}               \
00139         if (n > -1) size = n+1; else size *= 2;                                                                                  \
00140         if ((p = realloc (p, size+1)) == NULL) {va_end(ap);s=NULL;break;}                                \
00141  }}} 
00142 
00143 #define display_additional_info() { \
00144         int l; char len_space[]="    "; char seq_space[]="          "; \
00145         l=sprintf(len_space, "%i", tcp_len); len_space[l]=' '; len_space[4]='\0'; \
00146         strncpy(seq_space, seq_nb, strlen(seq_nb)); \
00147         if(display_tcp_infos) {print("seq=%s len=%s hlen=%i ",seq_space, len_space, tcp->th_hlen_reserved/4); \
00148         if(display_flags) print("%s ",flags);}; \
00149         }; while(0)
00150 
00151 #define find_anonymised_url(s) find_url(s, 0)
00152 #define look_for_anonymised_url(s) find_url(s, 4)
00153 #define get_extension(s) get_infos(s, 1, 0)
00154 #define get_suffix(s) get_infos(s, 0, 1)
00155 
00156 #define int_to_string(nb) string_append(NULL,"%i",nb)   
00157 
00158 #define display_string_table_with_data_sorted(title, table, data_title) display_string_table_with_data(title, table, data_title, 1)
00159 #define display_string_table_with_data_unsorted(title, table, data_title) display_string_table_with_data(title, table, data_title, 0)   
00160 #define display_string_table(title, table) display_string_table_with_data_sorted(title, table, "")
00161 #define display_string_table_unsorted(title, table) display_string_table_with_data_unsorted(title, table, "")
00162 
00163 //#define add_and_count_string_with_data(table, s, data) add_and_count_a_possible_new_string_with_data(table, s, data)
00164 #define add_and_count_new_string_with_data(table, s, data) add_and_count_string_with_data(table, s, data, 1)
00165 #define add_and_count_string(table, s) add_and_count_string_with_data(table, s, NULL)
00166 
00167 //#ifndef HAVE_PCAP_BREAKLOOP 
00168 //#define HAVE_PCAP_BREAKLOOP 
00169 /*  
00170  * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.  
00171 */
00172 
00173 //#define pcap_breakloop(a) goto aftercapture;
00174 //#endif        
00175         
00176 void free_nb_table(nb_table table)
00177 {
00178         if(table.start) free(table.start);
00179 }
00180 
00181 void add_nb(nb_table *table, int nb)
00182 {
00183         table->len+=1;
00184         table->start=xrealloc(table->start, table->len*sizeof(nb));
00185         table->start[table->len-1]=nb;
00186         if(display_raw_stats)
00187         {
00188                 table->nbpackets=xrealloc(table->nbpackets, table->len*sizeof(nb));
00189                 table->nbpackets[table->len-1]=nbpackets;
00190         }
00191 }
00192 
00193 void stats_add_content_length_nb(int nb)
00194 {
00195         add_nb(&cl_table, nb);
00196 }
00197 
00198 char *find_end(char *ptr)
00199 {
00200         if(ptr==NULL) return NULL;
00201         while(*ptr)
00202         {
00203                 if(*ptr=='?' || *ptr=='&' || *ptr==';' || *ptr=='%' || *ptr=='+' || *ptr=='=' || *ptr=='!' || *ptr=='$' || *ptr=='@' || *ptr=='"' || *ptr==',')
00204                 {
00205                         return ptr;
00206                 }
00207                 ptr++;
00208         }
00209         return NULL;
00210 }
00211 
00212 char *base_name(register char *f)
00213 {
00214   char *file = strrchr(f, '/');
00215   if (file == NULL) return f;
00216   return(file+1);
00217 }
00218 
00219 int is_ip_in_a_string(char *s)
00220 {
00221         int nb,tmp1,tmp2,tmp3,tmp4;
00222         if(!s) return(0);
00223         nb=sscanf(s, "%i.%i.%i.%i",&tmp1,&tmp2,&tmp3,&tmp4);
00224         if(nb==4) return(1);
00225         return(0);
00226 }
00227 
00228 char *string_append(char *s, const char *fmt, ...)
00229 {
00230         char *tmp;
00231         get_string_from_args(tmp);
00232         if(!tmp) return NULL;
00233         if(s==NULL)
00234         {
00235                 s=xmalloc( strlen(tmp)+1);
00236                 strcpy(s, tmp);
00237         }
00238         else
00239         {
00240                 s=xrealloc(s, strlen(s)+strlen(tmp)+1);
00241                 strcat(s, tmp);
00242         }
00243         free(tmp);
00244         if(s==NULL) return NULL;
00245         return s;
00246 }
00247 
00248 inline char *get_pct(double pct)
00249 {
00250         return string_append(NULL,"%.2f%c",(double)pct*100,'%');
00251 }
00252 
00253 char *get_speed(double speed)
00254 {
00255         char *tmp;
00256         if(speed>999999)
00257         {
00258                 speed=(double) speed / 1000000;
00259                 tmp=string_append(NULL, "%.2f MB/s",speed);
00260                 
00261                 if(tmp && strncmp(tmp, "inf", 3)==0) 
00262                 {
00263                         free(tmp);
00264                         return NULL;
00265                 }
00266                 return tmp;
00267         }
00268         else if(speed>999)
00269         {
00270                 speed=(double) speed / 1000;
00271                 return string_append(NULL, "%.2f KB/s",speed);
00272         }
00273         else
00274         {
00275                 return string_append(NULL, "%.2f B/s",speed);
00276         }
00277 }
00278 
00279 char *get_size(int s)
00280 {
00281         double size;
00282         
00283         if(s==-1)
00284         {
00285                 return strdup("???");
00286         }
00287         if(s>999999)
00288         {
00289                 size=(double) s / 1000000;
00290                 if(size==(int)s/1000000) return string_append(NULL, "%i MB",(int)size);
00291                 return string_append(NULL, "%.2f MB",size);
00292         }
00293         else if(s>999)
00294         {
00295                 size=(double) s / 1000;
00296                 if(size==(int)s/1000) return string_append(NULL, "%i KB",(int)size);
00297                 return string_append(NULL, "%.2f KB",size);
00298         }
00299         else
00300         {
00301                 size=(double) s;
00302                 if(size==(int)s) return string_append(NULL, "%i B",(int)size);
00303                 return string_append(NULL, "%.2f B",size);
00304         }
00305         return NULL;
00306 }
00307 
00308 char *get_time(double t)
00309 {
00310                 int years=0;
00311                 int months=0;
00312         int days=0;
00313         int hours=0;
00314         int minutes=0;
00315         int seconds=0;
00316         
00317         char *tmp=NULL;
00318 
00319         seconds=t;
00320         if(seconds>59)
00321         {
00322                 minutes=seconds/60;
00323                 seconds=seconds%60;
00324         }
00325         if(minutes>59)
00326         {
00327                 hours=minutes/60;
00328                 minutes=minutes%60;
00329         }
00330         if(hours>23)
00331         {
00332                 days=hours/24;
00333                 hours=hours%24;
00334         }
00335                 if(days>364)
00336                 {
00337                         years=days/365;
00338                         days=days%365;
00339                 }
00340         if(days>29)
00341         {
00342                 months=days/30;
00343                 days=days%30;
00344         }               
00345 /*        if(months>11)
00346         {
00347                 years+=months/12;
00348                 months=months%12;
00349         }               */
00350         if(years>0)             tmp=string_append(NULL, "%iy%im%id%ih%im%is",years, months, days, hours, minutes, seconds);
00351         else if(months>0)   tmp=string_append(NULL, "%im%id%ih%im%is",months, days, hours, minutes, seconds);
00352         else if(days>0)     tmp=string_append(NULL, "%id%ih%im%is",days, hours, minutes, seconds);
00353         else if(hours>0)    tmp=string_append(NULL, "%ih%im%is",hours, minutes, seconds);
00354         else if(minutes>0)  tmp=string_append(NULL, "%im%is",minutes, seconds);
00355         else                tmp=string_append(NULL, "%is",seconds);
00356         return tmp;
00357 }
00358 
00359         
00360 void catch_ctrl_c(int signum)
00361 {
00362         //We break the loop and restore the initial signal handler
00363         struct sigaction sa;
00364         pcap_breakloop(adhandle);
00365         sa.sa_handler = SIG_DFL;
00366         sa.sa_flags = 0;
00367         sigaction(SIGINT, &sa, NULL);
00368 }
00369 
00370 char *add_flag(char *s, char *flag)
00371 {
00372         int len=0;
00373         if(s) len=strlen(s);
00374         s=xrealloc(s, len+strlen(flag)+2);
00375         if(len==0) sprintf(s+len, "%s", flag);
00376         else sprintf(s+len, ".%s", flag);
00377         return s;
00378 }
00379 char *compute_flags(u_int8_t flags)
00380 {
00381         char *s=NULL;
00382         if(flags & TCP_FIN)  s=add_flag(s, "FIN");
00383         if(flags & TCP_SYN)  s=add_flag(s, "SYN");
00384         if(flags & TCP_RST)  s=add_flag(s, "RST");
00385         if(flags & TCP_PUSH) s=add_flag(s, "PSH");
00386         if(flags & TCP_ACK)  s=add_flag(s, "ACK");
00387         if(flags & TCP_URG)  s=add_flag(s, "URG");
00388         if(s==NULL) s=strdup("");
00389         return s;
00390 }
00391         
00392 void display_packet_infos(int nb, struct timeval *ts, char *ip_src, char *ip_dst, int sport, int dport)
00393 {
00394         //We format the output to be more readable
00395         char display_space[100];
00396         int len=0;
00397         len=sprintf(display_space, "%s:%d",ip_src, sport);
00398         if(len>max_display_space) max_display_space=len;
00399         len=sprintf(display_space, "%s:%d",ip_dst, dport);
00400         if(len>max_display_space) max_display_space=len;
00401                 
00402         memset(display_space,' ',100);
00403         sprintf(display_space, "%s:%d                ",ip_src, sport);
00404         sprintf(display_space+max_display_space, " --> %s:%d                ",ip_dst, dport);
00405         display_space[max_display_space*2+5]='\0';
00406         
00407         if(ts)
00408         {
00409                 print ("[%5i] ", nb);
00410                 if(display && display_timestamp) ts_print(ts);          
00411         }
00412         print("%s ",display_space);
00413 }
00414 
00415 void anon_timestamp(register struct timeval *tvp)
00416 {
00417         //This if the first packet.
00418         //We take the timestamp and substract it from each following timestamp, 
00419         //so the first packet's timestamp will be 0.
00420         if(nbpackets==0) 
00421         {
00422                 timeoffset=tvp->tv_sec;
00423                 timeoffset_usec=tvp->tv_usec;
00424 
00425         }
00426         tvp->tv_sec-=timeoffset;
00427          
00428         if(timeoffset_usec <= tvp->tv_usec) tvp->tv_usec-=timeoffset_usec;
00429         else
00430         {
00431                 tvp->tv_usec-=timeoffset_usec;
00432                 tvp->tv_usec+=1000000;
00433                 tvp->tv_sec--;
00434         }
00435 }
00436 
00437 
00438 void ts_print_diff(struct timeval *tvp)
00439 {
00440         //Print the latency in miliseconds
00441         float time=tvp->tv_sec*1000.0+tvp->tv_usec/1000.0;
00442         print("%.02fms ",time);
00443 }
00444 
00445 
00446 //Borrowed and adapted from TCPDUMP's util.c
00447 void ts_print(struct timeval *tvp_)
00448 {
00449         register int s;
00450         struct timeval tv;
00451         struct timeval *tvp=&tv;
00452         
00453         tv.tv_sec=tvp_->tv_sec;
00454         tv.tv_usec=tvp_->tv_usec;
00455         
00456         if(!anonymise && anonymise_timestamp) s = (tvp->tv_sec+timeoffset) % 86400;
00457         else s = (tvp->tv_sec) % 86400;
00458         (void)print("%02d:%02d:%02d.%06u ",
00459                          s / 3600, (s % 3600) / 60, s % 60,
00460                          (unsigned)tvp->tv_usec);
00461 }
00462 
00463 struct dialog *buffer_request(char *request, int len,int nb,char *ip_src, char *ip_dst, int port_src, int port_dst)
00464 {
00465         struct dialog *newdialog;
00466 
00467         newdialog = xmalloc (sizeof (struct dialog));
00468         strcpy (newdialog->ip_src, ip_src);
00469         strcpy (newdialog->ip_dst, ip_dst);
00470         newdialog->req_nb=nb;
00471         newdialog->request_len=len;
00472         newdialog->port_src = port_src;
00473         newdialog->port_dst = port_dst;
00474         newdialog->request = request;
00475         newdialog->next=NULL;
00476         if(dialog_table==NULL)
00477         {
00478                 //We have no request buffered yet
00479                 dialog_table=newdialog;
00480                 newdialog->prev=NULL;
00481         }
00482         else
00483         {
00484                 
00485                 //We jump at the end of the list, 
00486                 //and we count the requests already buffered
00487                 int i=0;
00488                 struct dialog *ptr=dialog_table;
00489                 while(ptr && ptr->next!=NULL) 
00490                 {
00491                         if(ptr->request) i++; //We don't count the discarded responses
00492                         
00493                         ptr=ptr->next;
00494                 }
00495                 ptr->next=newdialog;
00496                 newdialog->prev=ptr;            
00497                 if(request && display) print("[%d buffered] ",i+1);
00498         }
00499 
00500         return newdialog;
00501 }
00502 
00503 struct dialog *find_request(char *ip_src, char *ip_dst, int port_src, int port_dst)
00504 {
00505         struct dialog *ptr = dialog_table;
00506         while (ptr)
00507         {
00508                 if (strcmp (ptr->ip_src, ip_dst) == 0
00509                     && strcmp (ptr->ip_dst, ip_src) == 0
00510                     && ptr->port_src == port_dst && ptr->port_dst == port_src
00511                         && ptr->request!=NULL)
00512                 {
00513                         return ptr;
00514                 }
00515                 ptr = ptr->next;
00516         }
00517         return NULL;
00518 }
00519 
00520 
00521 char *is_in(char **string_table, char *string)
00522 {
00523         int i;
00524         for(i=0;i<nb_fields_to_anonymise;i++)
00525         {
00526                 if(strncmp(string_table[i], string, strlen(string_table[i]))==0) 
00527                 {
00528                         return string_table[i];
00529                 }
00530         }
00531         return NULL;
00532 }
00533 
00534 void memset_range(char *start, char *end, int c)
00535 {
00536         if(end-start>0) memset(start, c, end-start);
00537 }
00538 
00539 inline char get_random_char()
00540 {
00541         return 'a' + (int)(rand()/(RAND_MAX+1.0)*26);
00542 }
00543 
00544 
00545 char *generate_anonymised_url(char *s)
00546 {
00547         char *newurl=strdup(s);
00548         char *afterproto=strstr(newurl, "://");
00549 
00550         char *first_slash;
00551         char *last_dot;
00552         char *ptr;
00553         int has_hostname=1;
00554         
00555         if(afterproto) 
00556         {
00557                 if(strncasecmp(newurl,"file:///",8)==0)
00558                 {
00559                         ptr=afterproto+4;
00560                 }
00561                 else
00562                 {
00563                         ptr=afterproto+3;
00564                 }
00565         }
00566         else 
00567         {
00568                 //This is an url without a hostname (eg GET [url])
00569                 if(*newurl=='/')
00570                 {
00571                         has_hostname=0;
00572                 }
00573                 afterproto=newurl;
00574                 ptr=newurl;
00575         }
00576         
00577         first_slash=strstr(ptr, "/");
00578 
00579         // http://hostname.com/bla.ext?xxxx
00580         //        ^
00581         //        |
00582         //       ptr
00583         
00584 
00585 
00586         //Anonymising the host name
00587         if(has_hostname)
00588         {
00589                 char *ptr_orig=ptr;
00590                 //char *hostname;
00591                 char *new_hostname;
00592                 char bak;
00593                 int found=0;
00594                 if(first_slash)
00595                 {
00596                         bak=*first_slash;
00597                         *first_slash='\0';
00598                 }
00599                 new_hostname=find_anonymised_url(ptr);
00600                 
00601                         
00602                 if(!new_hostname)
00603                 {
00604                         found=0;
00605                         new_hostname=strdup(ptr);
00606                         last_dot=rindex(new_hostname,'.');
00607                         if(!last_dot) last_dot=new_hostname+strlen(new_hostname);
00608                 
00609                         ptr=new_hostname;
00610                         while(ptr<last_dot)
00611                         {
00612                                 *ptr=get_random_char();
00613                                 ptr++;
00614                         }
00615                 
00616                         //If the url is only a hostname, we won't add it twice! (since full_url=hostname)
00617                         if(strlen(ptr_orig)<strlen(s))
00618                         {
00619                                 add_anonymised_url(ptr_orig,new_hostname);
00620                         }
00621                         
00622                 }
00623                 else found=1;
00624                         
00625                 memcpy(ptr_orig, new_hostname, strlen(new_hostname));
00626                 if(found==0) free(new_hostname);
00627                 
00628                 if(first_slash) *first_slash=bak;
00629         }
00630         else
00631         {
00632                 first_slash=strstr(ptr,"/");
00633         }
00634         if(!first_slash) first_slash=newurl;
00635                 
00636         //Anonymising the part after the hostname, and before the filename
00637         if(first_slash)
00638         {
00639                 char bak;
00640                 char *ptr=first_slash+1;
00641                 char *end;
00642                 char *slash;
00643 
00644                 end=find_end(ptr);
00645                 if(!end) end=newurl+strlen(newurl);
00646                 
00647                 bak=*end;
00648                 *end='\0';
00649                 
00650                 
00651                 
00652                 slash=rindex(ptr,'/');
00653                 if(slash) 
00654                 {
00655                         memset_range(ptr, slash, 'i');
00656                         ptr=slash+1;
00657                 }
00658                 *end=bak;
00659 
00660                 //Anonymising the base file name, keeping the extension
00661                 bak=*end;
00662                 *end='\0';
00663                 last_dot=rindex(ptr,'.');
00664                 *end=bak;
00665                 if(!last_dot) last_dot=end;
00666                 //while(ptr<end)
00667                 
00668                 while(ptr<last_dot)
00669                 {
00670                         *ptr=get_random_char();
00671                         ptr++;
00672                 }
00673 
00674                 //Anonymising optional parameters (e.g. ?cat=5)
00675                 ptr=end;
00676                 
00677                 while(*ptr)
00678                 {
00679                         if(*ptr=='?' || *ptr=='&' || *ptr==';' || *ptr=='%' || *ptr=='+' || *ptr=='=' || *ptr=='!' || *ptr=='$' || *ptr=='@' || *ptr=='"' || *ptr==','){} else *ptr='z';
00680                         ptr++;
00681                 }
00682         }
00683         if(debug) print("anon URL:%s --> %s\n",s,newurl);
00684         return newurl;
00685 }
00686 
00687 
00688 char *get_infos(char *s, int extension, int suffix)
00689 {
00690         char *newurl=strdup(s);
00691         char *afterproto=strstr(newurl, "://");
00692 
00693         char *first_slash;
00694         char *last_dot;
00695 
00696         char *ptr;
00697         char *ext=NULL;
00698         int has_hostname=1;
00699         
00700         if(afterproto) 
00701         {
00702                 if(strncasecmp(newurl,"file:///",8)==0)
00703                 {
00704                         ptr=afterproto+4;
00705                 }
00706                 else
00707                 {
00708                         ptr=afterproto+3;
00709                 }
00710         }
00711         else 
00712         {
00713                 //This is an url without a hostname (eg GET [url])
00714                 if(*newurl=='/')
00715                 {
00716                         has_hostname=0;
00717                 }
00718                 afterproto=newurl;
00719                 ptr=newurl;
00720         }
00721         
00722         first_slash=strstr(ptr, "/");
00723 
00724         if(suffix)
00725         {
00726                 if(has_hostname)
00727                 {
00728                         char *tmp;
00729                         char *ret=NULL;
00730                         if(first_slash) *(first_slash-ptr+newurl)='\0';
00731                         if(is_ip_in_a_string(newurl))
00732                         {
00733                                 if(newurl) free(newurl);                        
00734                                 return NULL;
00735                         }
00736                         if(!ret && (tmp=rindex(newurl, '.'))) ret=strdup(tmp);
00737                         if(ret && (tmp=rindex(ret,':'))) *tmp='\0';
00738                         if(newurl) free(newurl);
00739                         return ret;     
00740                 }
00741                 else 
00742                 {       
00743                         if(newurl) free(newurl);
00744                         return NULL;
00745                 }
00746         }
00747         if(!first_slash) first_slash=newurl;
00748         
00749         //The part after the hostname, and before the filename
00750         if(first_slash)
00751         {
00752                 char bak;
00753                 char *ptr=first_slash+1;
00754                 char *end;
00755                 char *slash;
00756 
00757                 end=find_end(ptr);
00758                 if(!end) end=newurl+strlen(newurl);
00759                 
00760                 bak=*end;
00761                 *end='\0';
00762                 
00763                 slash=rindex(ptr,'/');
00764                 if(slash) 
00765                 {
00766                         ptr=slash+1;    
00767                 }
00768                 *end=bak;
00769 
00770                 //The base file name, keeping the extension
00771                 bak=*end;
00772                 *end='\0';
00773                 last_dot=rindex(ptr,'.');
00774                 *end=bak;
00775                 if(!last_dot) last_dot=end;
00776 
00777                 bak=*end;
00778                 *end='\0';
00779                 ext=strdup(last_dot);
00780                 
00781                 //sometimes, extensions end with spaces, eg ".gif "
00782                 //we strip them.
00783                 while(ext && *ext && *(ext+strlen(ext)-1)==' ') *(ext+strlen(ext)-1)='\0';
00784                 *end=bak;
00785         }
00786         if(newurl) free(newurl);
00787         return ext;
00788 }
00789 
00790 
00791 
00792 void add_anonymised_url(char *url_, char *newurl_)
00793 {
00794         char *url=strdup(url_);
00795         char *newurl=strdup(newurl_);
00796         if(debug) print("ADDING URL:%s \n--> %s\n",url,newurl);
00797         nburl++;
00798         anon_url_table=(char*)xrealloc(anon_url_table, nburl*2*4);
00799         memcpy(anon_url_table+2*(nburl-1)*4,&url,4);
00800         memcpy(anon_url_table+2*(nburl-1)*4+4,&newurl,4);
00801 }
00802 
00803 
00804 void *xmalloc(size_t size)
00805 {
00806         void *tmp=malloc(size);
00807         if(!tmp)
00808         {
00809                 print("Memory allocation error!\n");
00810                 exit(EXIT_FAILURE);
00811         }
00812         return tmp;
00813 }
00814 
00815 void *xrealloc(void *ptr, size_t size)
00816 {
00817         void *tmp=realloc(ptr,size);
00818         if(!tmp)
00819         {
00820                 print("Memory allocation error!\n");
00821                 exit(1);
00822         }
00823         return tmp;
00824 }
00825 
00826 char *find_url(char *s, int offset)
00827 {
00828         //offset=0: finds a non anonymised URL and returns the corresponding anonymised one
00829         //offset=4: finds an anonymised URL and returns it
00830         //print("looking for -%s-\n",s);
00831         int i;
00832         char *ptr=anon_url_table;
00833         char *tmp;
00834         for(i=0;i<nburl;i++)
00835         {
00836                 memcpy(&tmp, ptr+offset, 4);
00837                 if(strcmp(tmp,s)==0)
00838                 {
00839                         memcpy(&tmp, ptr+4, 4);
00840                         return tmp;
00841                 }
00842                 ptr+=8;
00843         }
00844         return NULL;
00845 }
00846 
00847 void anon_url(char *s)
00848 {
00849         char *start=strstr(s, "://");
00850         char *newurl;
00851         int found=0;
00852         
00853         if(!start) start=s;
00854         else start=start+3;
00855         
00856         newurl=find_anonymised_url(s);
00857         if(!newurl) 
00858         {
00859                 int count=0;
00860                 found=0;
00861 generate:
00862                 newurl=generate_anonymised_url(s);
00863                 
00864                 //We make sure our anonymised url is not duplicated
00865                 //After 3 tries, we give up, if the URL is "/" for example
00866                 if(look_for_anonymised_url(newurl) && count<3) 
00867                 {
00868                         count++;
00869                         free(newurl);
00870                         goto generate;
00871                 }
00872                         
00873                 add_anonymised_url(s, newurl);
00874         }
00875         else found=1;
00876         memcpy(s, newurl, strlen(s));
00877         if(found==0) free(newurl);
00878 }
00879 
00880 void anon_sequence(u_int32_t *seq)
00881 {
00882         if(rand_seq_nb==0) rand_seq_nb=(u_int32_t)*seq;
00883         *seq-=(u_int32_t)rand_seq_nb%65536;
00884 }
00885 
00886 void anon_date(char *date)
00887 {
00888         struct tm time;
00889         char *ret;
00890         time_t nb_seconds;
00891         char buffer[100];
00892         int len=strlen(date);
00893         
00894         ret=strptime(date, "%a, %d %b %Y %T GMT", &time);
00895         nb_seconds=mktime(&time);
00896         
00897         
00898         //The first date seen in the capture will be anonymised to: Tue, 01 Jan 1980 00:00:00 GMT
00899         if(date_offset==0) date_offset=nb_seconds-(3600*24)*(365*10+2);
00900         nb_seconds-=date_offset;
00901 
00902         gmtime_r(&nb_seconds, &time);
00903         
00904         strftime(buffer, 99, "%a, %d %b %Y %T GMT", &time);
00905         
00906         //print("DATE NEW:%s\n",asctime(&time));
00907         //print("DDATE:%i\n",ttime);
00908         //strcpy(date, buffer);
00909         strncpy(date, buffer, len);
00910         date[len]='\0';
00911         //print("DATE NEW:%s\n",buffer);
00912 }
00913 
00914 void anon_field(char *field, char *s)
00915 {
00916         if(strcmp(field, "Host: ")==0 || strcmp(field, "Referer: ")==0 
00917                 || strcmp(field, "Location: ")==0 || strcmp(field, "Content-Location: ")==0)
00918         {
00919                 
00920                 if(anonymise && anonymise_url)
00921                 {
00922                         //Some webservers send an IP in the Host field!
00923                         if(strcmp(field, "Host: ")==0 && is_ip_in_a_string(s+strlen(field)))
00924                         {
00925                                 snprintf(s+strlen(field), strlen(s+strlen(field)), "000.000.000.000");
00926                         }
00927                         else
00928                         {
00929                                 anon_url(s+strlen(field));
00930                         }
00931                 }
00932                 return;
00933         }
00934         
00935         if(strcmp(field, "GET ")==0)
00936         {
00937                 if(anonymise && anonymise_url)
00938                 {
00939                         char backup_char;
00940                         char *http_version=strstr(s, " HTTP/");
00941                         if(!http_version)
00942                         {
00943                                 http_version=s+strlen(s);
00944                         }
00945                         backup_char=*http_version;
00946                         *http_version='\0';
00947                         anon_url(s+strlen(field));
00948                         *http_version=backup_char;
00949                 }
00950                 return;
00951         }
00952         
00953         if(strcmp(field, "Date: ")==0 || strcmp(field, "Last-Modified: ")==0 || strcmp(field, "If-Modified-Since: ")==0 || strcmp(field, "Expires: ")==0)
00954         {
00955                 if(anonymise && anonymise_date) anon_date(s+strlen(field));
00956                 return;
00957         }
00958 
00959         memset(s+strlen(field), 'X', strlen(s)-strlen(field));
00960         return;
00961 }
00962 
00963 char *strstr_limited(char *ptr, char *end, char *str)
00964 {
00965         char *first;
00966         if(!str) return NULL;
00967         while(1)
00968         {
00969                 first=memchr(ptr, *str, end-ptr);
00970                 if(first)
00971                 {
00972                         int len=strlen(str);
00973                         if(first+len<=end && strncmp(str, first, len)==0) return first;
00974                 }
00975                 else return NULL;
00976                 ptr=first+1;
00977                 if(ptr>end) return NULL;
00978         }
00979 }
00980 
00981 char *process_http(char *data, int len, int scan, int anon)
00982 {
00983         char *ptr=data;
00984         char *tmp;
00985         char *last_modified=NULL;
00986         char *date=NULL;
00987         char *end=data+len;
00988         char *nextpos=NULL;
00989         char backup_char;
00990         
00991         if(data==NULL) return NULL;
00992         while(1)
00993         {
00994                 tmp=strstr_limited(ptr, end, "\r");
00995                 if(!tmp)
00996                 {
00997                         tmp=strstr_limited(ptr, end, "\n");
00998                 }
00999                 else
01000                 {
01001                         char *tmp2=strstr_limited(ptr, tmp, "\n");
01002                         if(tmp2 && tmp2<tmp) tmp=tmp2;
01003                 }
01004                 if(!tmp) 
01005                 {
01006                         tmp=end;
01007                         nextpos=NULL;
01008                         
01009                         //We skip the headers that have been truncated due to too small snaplen
01010                         if(scan) break; 
01011                 }
01012                 else
01013                 {
01014                         if(*tmp=='\r' && *(tmp+1)=='\n')
01015                         {
01016                                 nextpos=tmp+2;
01017                         }
01018                         else if(*tmp=='\r' || *tmp=='\n')
01019                         {
01020                                 nextpos=tmp+1;
01021                         }
01022         
01023                 }
01024                 backup_char=*tmp;
01025                 *tmp='\0';
01026                 
01027                 if(anon && anonymise && anonymise_http)
01028                 {
01029                         char *field=is_in(fields_to_anonymise, ptr);
01030                         if(field)
01031                         {
01032                                 anon_field(field, ptr);
01033                         }
01034                         else
01035                         {
01036                                 //Handle special Hotmail servers headers, beginning with "<"
01037                                 //Special thanks to Microsoft...
01038                                 if(ptr && *ptr=='<')
01039                                 {
01040                                         anon_field("",ptr);
01041                                 }
01042                         }
01043                 }
01044                 if(scan)
01045                 {
01046                         //Uncomment to get headers stats
01047                         if(display_raw_stats)
01048                         {
01049                                 char *tmp=strstr(ptr, ":");
01050                                 char bak;
01051                                 char *dup;
01052                                 if(!tmp) tmp=strstr(ptr," ");
01053                                 else
01054                                 {
01055                                         char *tmp2=strstr(ptr, " ");
01056                                         if(tmp2 && tmp2<tmp) tmp=tmp2;
01057                                 }
01058                                 if(tmp)
01059                                 {
01060                                         bak=*tmp;
01061                                         *tmp='\0';
01062                                 }
01063                                 
01064                                 dup=strdup(ptr);
01065                                 //convert_to_small(dup);
01066                                 stats_add_header(dup);
01067                                 free(dup);
01068                                 if(tmp) *tmp=bak;
01069                         }
01070                         
01071                         
01072                         if(ptr+5<end && strncmp(ptr, "HTTP/",5)==0)
01073                         {
01074                                 //We only keep the response code
01075                                 char bak;
01076                                 char *tmp=NULL;
01077                                 int tmp_i;
01078                                 bak=ptr[12];
01079                                 if(ptr[12]==' ')
01080                                 {
01081                                         tmp=strdup(ptr+13);
01082                                 }
01083                                 else
01084                                 {
01085                                         //Some webservers are broken:
01086                                         //Normally, they should answer:
01087                                         //response-code [SPACE] reason-code
01088                                         //Unfortunately, that it not always the case
01089                                         tmp=strdup("");
01090                                 }
01091                                 ptr[12]='\0';
01092                                 
01093                                 if(sscanf(ptr+9,"%i ",&tmp_i)==1)
01094                                 {       
01095                                         stats_add_http_response_code_with_data(ptr+9, tmp);
01096                                 
01097                                         ptr[12]=bak;
01098                                         bak=ptr[9];
01099                                         ptr[9]='\0';
01100                                         stats_add_http_version(ptr);
01101                                         ptr[9]=bak;
01102                                 }
01103                                 else
01104                                 {
01106                                         free(tmp);                              
01107                                         ptr[12]=bak;
01108                                         nextpos=NULL;
01109                                 }
01110                         }
01111                         else if(ptr+4<end && strncmp(ptr, "GET ",4)==0)
01112                         {
01113                                 char *tmp;
01114                                 char *page=strdup(ptr+4);
01115                                 *(page+strlen(page)-8)='\0';
01116                                 tmp=get_extension(page);
01117                                 if(tmp) 
01118                                 {
01119                                         char *tmp2=find_end(tmp);
01120                                         //for URLs like:
01121                                         // ._zahi,7,2,15,108,verdenab,8,204,102,0_zahelp
01122                                         // ._zahello,7,3,18,328,verdenab,10,204,102,0_zaplease
01123                                         if(tmp2)
01124                                         {
01125                                                 *tmp2='\0';
01126                                         }
01127                                         convert_to_small(tmp);
01128                                         stats_add_extension(tmp);
01129                                         free(tmp);
01130                                 }
01131                                 free(page);
01132                         }
01133                         else if(strncmp(ptr, "Date: ",6)==0)
01134                         {
01135                                 date=strdup(ptr+6);
01136                         }
01137                         else if(strncmp(ptr, "Server: ",8)==0)
01138                         {
01139                                 char *dup=strdup(ptr+8);
01140                                 char *tmp;
01141                                 if(strncmp(dup, ".V", 2)==0) //Like .V15 Apache/xxx
01142                                 {
01143                                         char *space=index(ptr+8, ' ');
01144                                         if(space) 
01145                                         {
01146                                                 free(dup);
01147                                                 dup=strdup(space+1);
01148                                         }
01149                                 }
01150                                 tmp=index(dup,'/');
01151                                 if(tmp) *tmp='\0';
01152                                 tmp=index(dup,' ');
01153                                 if(tmp) *tmp='\0';
01154                                 tmp=strstr(dup,"Apache");
01155                                 if(tmp) *(tmp+6)='\0';
01156                                 tmp=index(dup,'-');
01157                                 if(tmp) *tmp='\0';
01158                                 stats_add_server(ptr+8);
01159 /*                              if(strncmp(ptr+8, ".V", 2)==0) //Like .V15 Apache/xxx
01160                                 {
01161                                         char *space=index(ptr+8, ' ');
01162                                         if(space) stats_add_server_simple(space+1);
01163                                         else stats_add_server_simple(dup);
01164                                 }
01165                                 else 
01166                                 {*/
01167                                         stats_add_server_simple(dup);
01168                                 //}
01169                                 free(dup);
01170                         }
01171                         else if(strncmp(ptr, "Content-Type: ",14)==0)
01172                         {
01173                                 char *dup=strdup(ptr+14);
01174                                 char *tmp=strstr(dup,";");
01175                                 char *dup2=NULL;
01176                                 if(tmp) *tmp='\0';
01177                                 convert_to_small(dup);
01178                                 dup2=strdup(dup);
01179                                 if((tmp=strstr(dup2,"/"))) *tmp='\0';
01180                                 stats_add_content_type(dup);
01181                                 stats_add_content_type_simple(dup2);
01182                                 free(dup);
01183                                 free(dup2);
01184                         }
01185                         else if(strncmp(ptr, "Host: ",6)==0)
01186                         {
01187                                 char *tmp;
01188                                 tmp=get_suffix(ptr+6);
01189                                 if(tmp) 
01190                                 {
01191                                         convert_to_small(tmp);
01192                                         stats_add_suffix(tmp);
01193                                         free(tmp);
01194                                 }
01195                         }
01196                         else if(strncmp(ptr, "Last-Modified: ",15)==0)
01197                         {
01198                                 last_modified=strdup(ptr+15);
01199                         }
01200                         else if(strncmp(ptr, "Content-Length: ",16)==0)
01201                         {
01202                                 stats_add_content_length_nb(atoi(ptr+16));
01203                         }
01204                         else if(strncmp(ptr, "User-Agent: ",12)==0)
01205                         {
01206                                 stats_add_user_agent(ptr+12);
01207                         }
01208                 }
01209                 
01210                 if(tmp) *tmp=backup_char;
01211         
01212                 if(nextpos==NULL) break;
01213                 ptr=nextpos;
01214         }       
01215         
01216         if(scan)
01217         {
01218                 if(last_modified && date) 
01219                 {
01220                         struct tm time_date;
01221                         struct tm time_lm;
01222                         char *ret_date;
01223                         char *ret_lm;
01224                         
01225                         ret_date=strptime(date, "%a, %d %b %Y %T GMT", &time_date);
01226                         ret_lm=strptime(last_modified, "%a, %d %b %Y %T GMT", &time_lm);
01227 
01228                         if(ret_date==date+strlen(date) && ret_lm==last_modified+strlen(last_modified))
01229                         {
01230                                 //The two dates have been correctly parsed
01231                                 time_t seconds_date=mktime(&time_date);
01232                                 time_t seconds_lm=mktime(&time_lm);
01233                                 double diff=difftime(seconds_date,seconds_lm);
01234                                 free(last_modified);
01235                                 free(date);
01236                                 last_modified=NULL;
01237                                 date=NULL;
01238                                 if(diff>=0) return string_append(NULL, "%i", (int)diff);
01239                         }
01240                 }
01241                 /*else 
01242                 {
01243                         if(date) printf("NOLAST LAST\n");
01244                                 else printf("NOLAST DATE\n");
01245                 }
01246                 */
01247         }
01248         if(date) free(date);
01249         if(last_modified) free(last_modified);
01250         return NULL;
01251 }
01252 
01253 void anon_http(char *data, int len)
01254 {
01255         process_http(data, len, 0, 1);
01256 }
01257 
01258 void convert_to_small(char *ptr)
01259 {
01260         char c;
01261         while((c=*ptr))
01262         {
01263                 if(c>='A' && c<='Z') *ptr=c-'A'+'a';
01264                 ptr++;
01265         }
01266 }
01267 
01268 void scan_http(struct dialog *d)
01269 {
01270         char *freshness=NULL;
01271         //char *tmp=NULL;
01272         
01273         /*tmp=*/process_http(d->request, d->request_len, 1, 0);
01274         freshness=process_http(d->response, d->response_len, 1, 0);
01275 
01276         if(freshness)
01277         {
01278                 stats_add_freshness(atoi(freshness));
01279                 free(freshness);
01280         }
01281         //if(tmp) free(tmp);
01282 }
01283 
01284 void free_string_table(string_and_nb *table)
01285 {
01286         string_and_nb *next=NULL;
01287         while(table)
01288         {
01289                 next=table->next;
01290                 if(table->s) free(table->s);
01291                 if(table->data) free(table->data);
01292                 free(table);
01293                 table=next;
01294         }       
01295 }
01296 
01297 string_and_nb *summarize_stats(nb_table *table, string_and_nb *new_table, int max, char *title)
01298 {
01299         int *ptr=table->start;
01300         string_and_nb *item=NULL;
01301         int nb=0;
01302         int sum=0;
01303         int is_time=0;
01304         int is_size=0;
01305         int is_latency=0;
01306         char *size_s=NULL;
01307         char *size_s2=NULL;
01308         int len=table->len;
01309         if(table==&cl_table ) {is_size=1;}
01310         else if(table==&fresh_table) {is_time=1;}
01311         else if(table==&latency_table) {is_latency=1;}  
01312         
01313         while(len--)
01314         {
01315                 if((*ptr<max || max==-1) && *ptr!=-1)
01316                 {
01317                         nb++;
01318                         sum+=*ptr;
01319                         *ptr=-1;
01320                 }
01321                 ptr++;
01322         }
01323         
01324         if(nb>0)
01325         {
01326                 new_table=add_and_count_string(new_table, "DUMMY");
01327                 item=find_item(new_table, "DUMMY");
01328                 item->nb=nb;
01329                 free(item->s);
01330 
01331                 if(is_size)
01332                 {
01333                         size_s2=get_size(sum);
01334                         if(max==-1)
01335                         {
01336                                 size_s=strdup("above");
01337                         }
01338                         else
01339                         {
01340                                 size_s=get_size(max);
01341                         }
01342                         item->s=string_append(NULL, "< %7s (total: %s)", size_s, size_s2);
01343                 }
01344                 else if(is_time)
01345                 {
01346                         if(title) item->s=strdup(title);
01347                         else item->s=strdup("");
01348                 }
01349                 else if(is_latency)
01350                 {
01351                         if(max==-1)
01352                         {
01353                                 size_s=strdup("above");
01354                         }
01355                         else
01356                         {
01357                                 size_s=string_append(NULL, "%i ms",max/1000);
01358                         }
01359                         item->s=string_append(NULL, "< %7s", size_s);
01360                 }
01361         }
01362         
01363         if(size_s) free(size_s);
01364         if(size_s2) free(size_s2);      
01365         return new_table;
01366 }
01367 
01368 
01369 double compute_mean_value(nb_table table)
01370 {
01371         int *ptr=table.start;
01372         unsigned long int sum=0;
01373         int len=table.len;
01374 
01375         while(len--)
01376         {
01377                 sum+=*ptr;
01378                 ptr++;
01379         }
01380                 
01381         if(table.len==0) return(0);
01382         return((double)sum/(table.len));
01383 }
01384 
01385 double compute_variation(nb_table table)
01386 {
01387         int *ptr=table.start;
01388         int *ptrm=table.start+1;
01389         unsigned long int sum=0;
01390         int len=table.len;
01391         int i;
01392 
01393         for(i=1;i<len-1;i++)
01394         {
01395                 sum+=abs(*ptrm-*ptr);
01396                 ptr++;
01397                 ptrm++;
01398         }
01399         if(len>0) return((double)sum/(len-1));
01400         else return(0);
01401 }
01402 double compute_std_deviation(nb_table table)
01403 {
01404         int *ptr=table.start;
01405         long double sum=0;
01406         int len=table.len;
01407         int i;
01408         double mean=compute_mean_value(table);
01409         if(mean==0) len=0;
01410                 
01411         for(i=0;i<len;i++)
01412         {
01413                 sum+=(double)pow((double)(mean-*ptr),2);
01414                 ptr++;
01415         }
01416         if(len!=0) 
01417         {
01418                 sum=sqrt(sum/len);
01419                 return(sum);
01420         }
01421         else return(0);
01422 }
01423 void freshness_stats()
01424 {
01425         string_and_nb *new_fresh_table=NULL;
01426         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 1*60,            "< 1 min");
01427         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 5*60,            "< 5 min");
01428         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 1*3600,          "< 1 hour");
01429         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 10*3600,         "< 10 hrs");
01430         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 24*3600,         "< 1 day");
01431         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 7*24*3600,       "< 1 week");
01432         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 10*24*3600,      "< 10 days");
01433         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 30*24*3600,      "< 1 month");
01434         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 1+3*30*24*3600,  "< 3 months");
01435         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 3+6*30*24*3600,  "< 6 months");
01436         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 5+9*30*24*3600,  "< 9 months");
01437         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, 365*24*3600, "< 1 year");
01438         new_fresh_table=summarize_stats(&fresh_table, new_fresh_table, -1,              "> 1 year");
01439                 
01440         display_string_table_unsorted("Page freshness: ",new_fresh_table);
01441         free_string_table(new_fresh_table);
01442 }
01443 
01444 nb_table *clone_nb_table(nb_table table)
01445 {
01446         nb_table *new_table=xmalloc(sizeof(nb_table));
01447         new_table->len=table.len;
01448         new_table->start=xmalloc(table.len*sizeof(int));
01449         memcpy(new_table->start, table.start, table.len*sizeof(int));
01450         if(display_raw_stats)
01451         {
01452                 new_table->nbpackets=xmalloc(table.len*sizeof(int));
01453                 memcpy(new_table->nbpackets, table.nbpackets, table.len*sizeof(int));
01454         }
01455         return new_table;
01456 }
01457 
01458 char *display_deviation(nb_table *t, char *title)
01459 {
01460         double mean;
01461         double variation;
01462         double std_deviation;
01463         char *mean_s=NULL;
01464         char *var_s=NULL;
01465         char *stddev_s=NULL;
01466         char *title_s=NULL;
01467 
01468         mean=compute_mean_value(*t);
01469         variation=compute_variation(*t);
01470         std_deviation=compute_std_deviation(*t);
01471         
01472         if(mean>0) mean_s=string_append(NULL, "%f", mean);
01473         else mean_s=strdup("??");
01474         if(variation>0) var_s=string_append(NULL, "%f", variation);
01475         else var_s=strdup("??");
01476         if(std_deviation>0) stddev_s=string_append(NULL, "%f", std_deviation);
01477         else stddev_s=strdup("??");
01478                 
01479         title_s=string_append(NULL,"%s\n|Variation: %s\n|Std Deviation: %s",title,mean_s,var_s,stddev_s);
01480         if(display_raw_stats) title_s=string_append(title_s, "\n|Total count: %i",t->len);
01481         
01482         free(mean_s); free(var_s); free(stddev_s);
01483         return title_s;
01484 }
01485 
01486 void display_nb_table(char *title, nb_table *t)
01487 {
01488         int i;
01489         int *nb;
01490         int *nbp;
01491         
01492         char *title_s=display_deviation(t,title);
01493         print("#%s\n",title_s);
01494         free(title_s);  
01495 
01496         
01499                 
01500         
01501         nb=t->start;
01502         nbp=t->nbpackets;
01503 
01504         for(i=0;i<t->len;i++)
01505         {
01506 
01507                 if(display_raw_stats)
01508                 {
01509                         print("%i:%i\n",*nbp,*nb);
01510                         nbp++;
01511                 }
01512                 else
01513                 {
01514                         print("%i\n",*nb);
01515                 }
01516                 nb++;
01517         }
01518         print("\n");
01519 }
01520 
01521 void latency_stats()
01522 {
01523         string_and_nb *new_latency_table=NULL;
01524         nb_table *cloned_latency_table=clone_nb_table(latency_table);
01525         int i;
01526         int *nb;
01527         int *nb2;
01528         char *title_s=NULL;
01529         char *tmp;
01530 
01531         //We divide each member of the cloned table by 1000, to obtain milliseconds
01532         nb=latency_table.start;
01533         nb2=cloned_latency_table->start;
01534 
01535         for(i=0;i<latency_table.len;i++)
01536         {
01537                 *nb2=(int)*nb/1000.0; //FIXME: rounding error
01538                 nb++;
01539                 nb2++;
01540         }
01541 
01542         title_s=display_deviation(cloned_latency_table, "Latency between requests and responses:");
01543         
01544         new_latency_table=summarize_stats(&latency_table, new_latency_table, 5000,                      "< 5 ms");
01545         new_latency_table=summarize_stats(&latency_table, new_latency_table, 10000,             "< 10 ms");
01546         new_latency_table=summarize_stats(&latency_table, new_latency_table, 15000,             "< 15 ms");
01547         new_latency_table=summarize_stats(&latency_table, new_latency_table, 20000,             "< 20 ms");
01548         new_latency_table=summarize_stats(&latency_table, new_latency_table, 25000,             "< 25 ms");
01549         new_latency_table=summarize_stats(&latency_table, new_latency_table, 50000,             "< 50 ms");
01550         for(i=1;i<10;i++)
01551         {
01552                 tmp=string_append(NULL, "< %i ms");
01553                 new_latency_table=summarize_stats(&latency_table, new_latency_table, i*100*1000, tmp);
01554                 free(tmp);
01555         }
01556         new_latency_table=summarize_stats(&latency_table, new_latency_table, 1000000,           "< 1 s");
01557         new_latency_table=summarize_stats(&latency_table, new_latency_table, 5000000,           "< 5 s");
01558         new_latency_table=summarize_stats(&latency_table, new_latency_table, -1,                        "above");
01559 
01560         free_nb_table(*cloned_latency_table);
01561         free(cloned_latency_table);
01562 
01563         display_string_table_unsorted(title_s,new_latency_table);
01564         free(title_s);
01565         free_string_table(new_latency_table);
01566 }
01567 
01568 void content_length_stats()
01569 {
01570         string_and_nb *new_content_length_table=NULL;
01571         int max;
01572         int i;
01573         char *title_s;
01574         
01575         
01576         nb_table *cloned_cl_table=clone_nb_table(cl_table);
01577         title_s=display_deviation(cloned_cl_table, "Content-Length:");
01578         free_nb_table(*cloned_cl_table);
01579         free(cloned_cl_table);
01580         
01581         
01582         max=1000;
01583         for(i=0;i<7;i++)
01584         {
01585                 new_content_length_table=summarize_stats(&cl_table, new_content_length_table, max, NULL);
01586                 max*=10;
01587         }
01588         
01589         new_content_length_table=summarize_stats(&cl_table, new_content_length_table, -1, NULL);
01590 
01591                 
01592         display_string_table_unsorted(title_s,new_content_length_table);
01593         free(title_s);
01594         
01595         free_string_table(new_content_length_table);
01596 }
01597 
01598 void display_string_table_with_data(char *title,string_and_nb *table, char *data_title, int sorted)
01599 {
01600         string_and_nb *ptr=table;
01601         string_and_nb *ptr_bak2;
01602         int i,j;
01603         int nb=0;
01604         int max=0;
01605         char buffer[100];
01606         int len;
01607         int maxlen;
01608         int total=0;
01609         double pct;
01610         char *pct_s=NULL;
01611         int *sorted_table=NULL;
01612         int max_pos=0;
01613         int pos;
01614         string_and_nb *tmp;
01615         char *d_title=NULL;
01616 
01617         while(ptr)
01618         {
01619                 nb++;
01620                 max=max(ptr->nb , max);
01621                 total+=ptr->nb;
01622                 ptr=ptr->next;
01623         }
01624         print("#%s ",title);
01625         
01626         if(display_raw_stats) sorted=0;
01627         
01628         if(sorted) print("%i different strings ",nb);
01629         print("\n|Total count: %i\n",total);
01630         //if(sorted) print("\n");
01631         //else print("\n");
01632         maxlen=snprintf(buffer,99,"%i",max);
01633         
01634         ptr=table;
01635         
01636         sorted_table=xmalloc(nb*sizeof(nb));
01637 
01638         if(data_title && strcmp(data_title,"")!=0) d_title=strdup(data_title);
01639         else d_title=strdup(" DATA:");
01640 
01641         if(sorted)
01642         {               
01643                 //Sorting the results
01644                 for(j=0;j<nb;j++)
01645                 {
01646                         pos=0;
01647                         max=0;
01648                         ptr=table;
01649                         while(ptr)
01650                         {
01651                                 if(ptr->nb > max)
01652                                 {
01653                                         max=ptr->nb;
01654                                         max_pos=pos;
01655                                         tmp=ptr;
01656                                 }
01657                                 ptr=ptr->next;
01658                                 pos++;
01659                         }
01660                         tmp->nb*=-1;
01661                         sorted_table[j]=max_pos;
01662                         
01663                 }
01664         }
01665         else //not sorted
01666         {
01667                 if(display_raw_stats)
01668                 {
01669                         for(j=0;j<nb;j++) sorted_table[j]=nb-j-1;       
01670                 }
01671                 else
01672                 {
01673                         for(j=0;j<nb;j++) sorted_table[j]=j;
01674                 }
01675         }
01676 
01677         ptr=table;
01678         ptr_bak2=table; //used if not sorted
01679         for(j=0;j<nb;j++)
01680         {
01681                 if(sorted)
01682                 {
01683                         ptr=table;
01684                         for(i=0;i<sorted_table[j];i++) ptr=ptr->next;
01685                         ptr->nb*=-1;
01686                 }
01687                 else
01688                 {
01689                         ptr=ptr_bak2;
01690                 }
01691                 pct=(double)ptr->nb/total;
01692                 
01693                 //We group the values below the specified percentage
01694                 if(pct_treshold!=0 && pct<pct_treshold/100.0 && sorted && j<nb-1
01695                         && table!=http_response_code_table) //We should pass a value to the function instead...
01696                 {
01697                         string_and_nb *ptr_bak=ptr;
01698                         char *new_string=strdup("Various: ");
01699                         int nb_total=0;
01700                         int k;
01701                         char *comma;
01702                         ptr->nb*=-1; //This nb already have been reversed
01703                         for(k=j;k<nb;k++)
01704                         {
01705                                 ptr=table;
01706                                 for(i=0;i<sorted_table[k];i++) ptr=ptr->next;
01707                                 ptr->nb*=-1;
01708                                 nb_total+=ptr->nb;
01709                                 
01710                                 if(k==nb-1) comma="";
01711                                 else comma=",";
01712                                         
01713                                 if(ptr->data==NULL)
01714                                 {
01715                                         new_string=string_append(new_string, "%s%s",ptr->s, comma);
01716                                 }
01717                                 else
01718                                 {
01719                                         new_string=string_append(new_string, "%s%s%s%s",ptr->s,d_title,(char*)ptr->data,comma);
01720                                 }
01721                         }
01722                         ptr=ptr_bak;
01723                         ptr->nb=nb_total;
01724                         free(ptr->s);
01725                         ptr->s=new_string;
01726                         if(ptr->data) {free(ptr->data);ptr->data=NULL;}
01727                         j=nb;
01728                         pct=(double)ptr->nb/total;
01729                         
01730                 }
01731                         
01732                 if(display_raw_stats)
01733                 {
01734                         print("%s\n",ptr->s);
01735                 }
01736                 else
01737                 {
01738                         pct_s=get_pct(pct);
01739                         if(!pct_s) pct_s=strdup("[??]");
01740                         
01741                         len=snprintf(buffer,99, "%i",ptr->nb);
01742                         memset(buffer, ' ', 99);
01743                         snprintf(buffer+maxlen-len,99, "%i",ptr->nb);
01744                         buffer[maxlen+1]='\0';
01745                         if(ptr->data) print("[%7s] %s %s%s%s\n",pct_s,buffer,ptr->s,d_title,(char*)ptr->data);
01746                         else print("[%7s] %s %s\n",pct_s,buffer, ptr->s);
01747                         free(pct_s);
01748                 }
01749                 if(!sorted)
01750                 {
01751                         ptr_bak2=ptr->next;
01752                 }
01753         }
01754         
01755         if(d_title) free(d_title);
01756         if(sorted_table) free(sorted_table);
01757 
01758         print("\n");
01759 }
01760 
01761 string_and_nb *add_and_count_string_with_data(string_and_nb *table, char *s, void *data)
01762 {
01763         string_and_nb *ptr=table;
01764         string_and_nb *tmp;
01765         string_and_nb *prev=NULL;
01766 
01767         int ret;
01768                 
01769         //No need to sort and group results, if displaying raw stats
01770         if(!display_raw_stats)
01771         {
01772                 
01773                 while(ptr)
01774                 {
01775                         ret=strcmp(s, ptr->s);
01776                         
01777                         if(ret<0)
01778                         {
01779                                 prev=ptr;
01780                         }
01781                         else if (ret>0) break; //We have to insert the string here
01782                         else //ret=0, we've found the string
01783                         {
01784                                 if(data) 
01785                                 {
01786                                         if(ptr->data) free(ptr->data);
01787                                         ptr->data=data;
01788                                 }
01789                                 ptr->nb++;
01790                                 return table;
01791                         }
01792                         ptr=ptr->next;
01793                 }
01794         }
01795         
01796         tmp=xmalloc(sizeof(string_and_nb));
01797         
01798         if(display_raw_stats)
01799         {
01801                 tmp->s=string_append(NULL, "%i:%s",nbpackets, s);
01802         }
01803         else
01804         {
01805                 tmp->s=strdup(s);
01806         }
01807         
01808         tmp->nb=1;
01809 
01810         if(data) tmp->data=data;
01811         else tmp->data=NULL;
01812         
01813         //If this is the first string in the list
01814         if(table==NULL)
01815         {
01816                 tmp->next=NULL;
01817                 return tmp;
01818         }
01819         else
01820         {
01821                 if(prev) 
01822                 {
01823                         tmp->next=prev->next;
01824                         prev->next=tmp;
01825                         return table;
01826                 }
01827                 else
01828                 {
01829                         //We insert the new struct at the beginning of the table
01830                         tmp->next=table;
01831                         return tmp;
01832                 }
01833         }
01834 }
01835 
01836 string_and_nb *find_item(string_and_nb *table, char *s)
01837 {
01838         string_and_nb *ptr=table;
01839         int ret;
01840         while(ptr)
01841         {
01842                 ret=strcmp(s, ptr->s);
01843                 if(ret>0) return NULL;
01844                 else if(ret==0) return ptr;
01845                 ptr=ptr->next;
01846         }
01847         return NULL;
01848 }
01849 
01850 void stats_add_sequence_number(char *s)
01851 {
01852         sequence_number_table=add_and_count_string(sequence_number_table, s);
01853 }
01854 void stats_add_sequence_number_with_data(char *s, void *data)
01855 {
01856         sequence_number_table=add_and_count_string_with_data(sequence_number_table, s, data);
01857 }
01858 void stats_add_header(char *s)
01859 {
01860 //      header_table=add_and_count_string(header_table, s);
01861 }
01862 void stats_add_extension(char *s)
01863 {
01864         extension_table=add_and_count_string(extension_table, s);
01865 }
01866 void stats_add_suffix(char *s)
01867 {
01868         suffix_table=add_and_count_string(suffix_table, s);
01869 }
01870 void stats_add_server(char *s)
01871 {
01872         server_version_table=add_and_count_string(server_version_table, s);
01873 }
01874 void stats_add_server_simple(char *s)
01875 {
01876         server_version_simple_table=add_and_count_string(server_version_simple_table, s);
01877 }
01878 void stats_add_user_agent(char *s)
01879 {
01880         user_agent_table=add_and_count_string(user_agent_table, s);
01881 }
01882 
01883 void stats_add_http_response_code_with_data(char *s, char *data)
01884 {
01885         http_response_code_table=add_and_count_string_with_data(http_response_code_table, s, data);
01886 }
01887 
01888 void stats_add_content_type(char *s)
01889 {
01890         content_type_table=add_and_count_string(content_type_table, s);
01891 }
01892 void stats_add_content_type_simple(char *s)
01893 {
01894         content_type_simple_table=add_and_count_string(content_type_simple_table, s);
01895 }
01896 void stats_add_http_version(char *s)
01897 {
01898         http_version_table=add_and_count_string(http_version_table, s);
01899 }
01900 void stats_add_freshness(int nb)
01901 {
01902         add_nb(&fresh_table, nb);
01903 }
01904 void stats_add_latency(int nb)
01905 {
01906         add_nb(&latency_table, nb);
01907 }
01908 
01909 void process_dialog(struct dialog *d)
01910 {
01911         if(do_stats) scan_http(d);
01912 
01913         if(display && display_http) 
01914         {
01915                 if(d->request) print ("%s\n", d->request);
01916                 print ("-----------------\n");
01917                 if(d->response) print ("%s\n", d->response);
01918         }
01919 }
01920 
01921 void free_dialog(struct dialog *d)
01922 {
01923         if(d->request) free(d->request);
01924         if(d->response) free(d->response);
01925                 
01926         if(d==dialog_table)
01927         {
01928                 //If we are freeing the first dialog, we have to update dialog_table
01929                 dialog_table=d->next;
01930         }
01931         if(d->next) d->next->prev=d->prev;
01932         if(d->prev) d->prev->next=d->next;
01933         free(d);
01934 }
01935 
01936 int parse_size(char *string)
01937 {
01938         char *s;
01939         int len;
01940         int mult=1;
01941         if(string==NULL) return 0;
01942         s=strdup(string);
01943         len=strlen(s);
01944         if(*(s+len-1)=='g' || *(s+len-1)=='G') {mult=1000000000;*(s+len-1)='\0';}
01945         else if(*(s+len-1)=='m' || *(s+len-1)=='M') {mult=1000000;*(s+len-1)='\0';}
01946         else if(*(s+len-1)=='k' || *(s+len-1)=='K') {mult=1000;*(s+len-1)='\0';}
01947         return mult*atoi(s);
01948 }
01949 
01950 u_int32_t getip32 (char *ip)
01951 {
01952         int c1, c2, c3, c4;
01953         u_int32_t tmp;
01954         sscanf (ip, "%i.%i.%i.%i", &c1, &c2, &c3, &c4);
01955         tmp = c4 * 16777216 + c3 * 65536 + c2 * 256 + c1;
01956         return tmp;
01957 }
01958 
01959 
01960 void anon_port (u_int16_t * port)
01961 {
01962         int i;
01963         u_int16_t *port2=(u_int16_t*)port_table;
01964         u_int16_t newport = 0;
01965         /* We look for the port in the table, if it has already been anonymised */
01966         for (i = 0; i < nbports; i++)
01967         {
01968                 /* If the IP is found, we get the IP to replace it */
01969                 if(*port==*port2)
01970                 {
01971                         memcpy (&newport, port_table+i*4+ 2, 2);
01972                         break;
01973                 }
01974                 port2+=2;
01975         }
01976         if (newport == 0)       /* We have a new port to anonymise */
01977         {
01978                 newport = htons (nbports + FIRST_ANON_PORT);
01979 
01980                 /* We add the original and anonymised ports to the table */
01981                 port_table = xrealloc (port_table, (nbports + 1) * 4);
01982 
01983                 memcpy (port_table + nbports * 4, port, 2);
01984                 memcpy (port_table + nbports * 4 + 2, &newport, 2);
01985 
01986                 port_table[nbports] = *port;
01987                 port_table[nbports + 1] = newport;
01988                 nbports++;
01989         }
01990         memcpy (port, &newport, 2);
01991 }
01992 
01993 char *find_anonymised_ip(struct in_addr *ip)
01994 {
01995         char *ptr = ip_table;
01996         int i;
01997         for (i = 0; i < nbip; i++)
01998         {
01999                 /* If the IP is found, we get the IP to replace it */
02000                 if (memcmp (ptr, ip, 4) == 0)
02001                 {
02002                         return ptr;
02003                 }
02004                 ptr += 8;
02005         }       
02006         return NULL;
02007 }
02008 
02009 
02010 void anon_ip (struct in_addr *ip)
02011 {
02012         char *ptr = NULL;
02013         struct in_addr newip;
02014 
02015         ptr=find_anonymised_ip(ip);
02016         if(ptr)
02017         {
02018                 memcpy (&newip, ptr + 4, 4);
02019                 
02020         }
02021         else /* We have a new IP to anonymise */
02022         {
02023                 u_int32_t tmp;
02024                 if (firstanonip == 0)
02025                         firstanonip = getip32 (FIRST_ANON_IP);
02026                 tmp = firstanonip += nbip * 16777216;
02027                 memcpy (&newip, &tmp, 4);
02028 
02029                 /* We add the original and anonymised IPs to the table */
02030 
02031                 ip_table = xrealloc (ip_table, (nbip + 1) * 8);
02032 
02033                 memcpy (ip_table + nbip * 8, ip, 4);
02034                 memcpy (ip_table + nbip * 8 + 4, &newip, 4);
02035                 nbip++;
02036         }
02037         memcpy (ip, &newip, 4);
02038 }
02039 
02040 pcap_if_t *get_pcap_interface (char *name)
02041 {
02042         char errbuf[PCAP_ERRBUF_SIZE];
02043         pcap_if_t *d;
02044         int i = 0;
02045         int show = 0;
02046 
02047         /*
02048          * Retrieve the device list 
02049          */
02050         if (pcap_findalldevs (&alldevs, errbuf) == -1)
02051         {
02052                 print("Error in pcap_findalldevs: %s\n", errbuf);
02053                 exit (1);
02054         }
02055 
02056         if (name && strcasecmp (name, "show") == 0)
02057                 show = 1;
02058 
02059         /*
02060          * Print the list 
02061          */
02062         if (show)
02063                 print ("Available interfaces for live capture:\n");
02064         for (d = alldevs; d; d = d->next)
02065         {
02066                 if (name == NULL)
02067                         return d;
02068                 if (show)
02069                 {
02070                         print ("    %s", d->name);
02071                         if (d->description)
02072                                 print (" (%s)\n", d->description);
02073                         else
02074                                 print (" (No description available)\n");
02075                 }
02076                 else
02077                 {
02078                         if (name && strcmp (d->name, name) == 0)
02079                                 return d;
02080                 }
02081                 i++;
02082         }
02083         if(alldevs) 
02084         {
02085                 pcap_freealldevs (alldevs);
02086                 alldevs=NULL;
02087         }
02088 
02089         if (i == 0)
02090         {
02091                 print ("\nNo interfaces found!\n");
02092                 exit (1);
02093         }
02094         return NULL;
02095 }
02096 
02097 int main (int argc, char **argv)
02098 {
02099         pcap_if_t *dev = NULL;
02100         
02101         char *tmp;
02102         bpf_u_int32 net;
02103         struct sigaction sa;
02104                 
02105         u_int netmask;
02106         char *packet_filter = "dst port 80 or src port 80";
02107         struct bpf_program fcode;
02108 
02109         char errbuf[PCAP_ERRBUF_SIZE];
02110         int c;
02111 
02112         struct dialog *ptr;
02113         struct dialog *next;
02114         output_stream=stdout;
02115                 
02116         // Parsing the command line options 
02117         //if(strcasecmp(base_name(argv[0]),"anon")==0) {}
02118         if(strcasecmp(base_name(argv[0]),"stat")==0) 
02119         {
02120                 display=0;
02121                 anonymise=0;
02122                 already_anonymised=1;
02123         }
02124         
02125         while (1)
02126         {
02127                 int option_index = 0;
02128                 static struct option long_options[] = {
02129                         {"filter", 1, 0, 'f'},
02130                         {"interface", 1, 0, 'i'},
02131                         {"live", 0, 0, 'l'},
02132                         {"noanon", 2, 0, 'a'},
02133                         {"nodisplay", 2, 0, 'd'},
02134                         {"httponly", 0, 0, 'H'},
02135                         {"keeptable", 2, 0, 'k'},
02136                         {"size", 1, 0, 's'},
02137                         {"maxsize", 1, 0, 'm'},
02138                         {"treshold", 1, 0, 'p'},
02139                         {"rawstats", 0, 0, 'R'},
02140                         {"nostats", 0, 0, 'S'},
02141                         {"nbpackets", 1, 0, 'n'},
02142                         {"inputfile", 1, 0, 'r'},
02143                         {"outputfile", 1, 0, 'w'},
02144                         {"alreadyanon", 0, 0, 'x'},
02145                         {"useseqnum", 0, 0, 'u'},
02146                         {"truncate", 0, 0, 't'},
02147                         {"help", 0, 0, 'h'},
02148                         {0, 0, 0, 0}
02149                 };
02150                                         
02151                 c = getopt_long (argc, argv, "Rp:txSus:d::f:i:a::lk::m:r:w:n:hH", long_options, &option_index);
02152                 if (c == -1) break;
02153 
02154                 switch (c)
02155                 {
02156                 case 0:
02157                         print ("option %s", long_options[option_index].name);
02158                         if (optarg) print (" with arg %s", optarg);
02159                         print ("\n");
02160                         break;
02161 
02162                 case 'h':
02163                         print ("Usage: %s [options]\n\n", argv[0]);
02164                         print ("Available options:\n");
02165                         print (" -i/--interface dev        : Device name to use to capture the packets.\n");
02166                         print ("                             Defaults to the first interface.\n");
02167                         print ("                             Use 'show' to show available interfaces.\n");
02168                         print (" -S/--nostats              : Do not compute nor print any statistics.\n");      
02169                         print (" -p/--treshold XX          : Group values below XX pct in statistics\n");       
02170                         print (" -aXX/--noanon XX          : Do not anonymise XX, where XX may be: \n");
02171                         print ("                             k (IP&TCP checksums), d (date), p (port), t (timestamp),\n");
02172                         print ("                             m (MAC), c (content), u (url), h (http), i (ip), s (seq nb),\n");
02173                         print ("                             or nothing. In this latter case, everything will be anonymised.\n");
02174                     print (" -f/--filter STRING        : Use STRING as a filter.\n");
02175                         print (" -n/--nbpackets            : Number of packets to read/capture.\n");
02176                         print (" -l/--live                 : If specified, capture is done in live mode.\n");
02177                         print (" -k/--keeptable [filename] : Save infos to de-anonymise in the specified file.\n");
02178                         print ("                             Default filename: key.txt.\n");
02179                         print (" -s/--size                 : Portion to keep from captured packets (for live mode).\n");
02180                         print (" -m/--maxsize              : Maximum size of the output file (eg 1M, 100k, etc...).\n");
02181                         print ("                             No more data will be written if exceeded.\n");
02182                         print (" -t/--truncate             : Truncate the packets. Keep only useful data (the HTTP headers)\n");
02183                         print (" -r/--inputfile filename   : Read input trace from filename.\n");
02184                         print (" -w/--outputfile filename  : Write output trace to filename.\n");
02185                         print (" -H/--httponly             : Only display HTTP packets.\n");
02186                         print (" -dXX/--nodisplay XX       : Do display XX, where XX may be:\n");
02187                         print ("                             h (HTTP), t (timestamp), f (tcp flags),\n");
02188                     print ("                             r (unanswered requests), T (tcp infos),\n");
02189                         print ("                             p (progress, has to be used explicitly), or nothing\n");
02190                         print (" -R/--rawstats                 : Display raw statistics\n");
02191                         print (" -x/--alreadyanon          : Specify this option if the processed trace has already been\n");
02192                         print ("                             anonymised. Only statistics will be done.\n");
02193                         print (" -u/--useseqnum            : Record and use sequence numbers to find continued connections.\n");
02194                         print ("                             (this leads to a big slowdown, so it is disabled by default).\n");
02195                         print (" -h/--help                 : display this help message.\n");
02196                         exit (0);
02197                 case 'i':
02198                         if (!(dev = get_pcap_interface (optarg)))
02199                         {
02200                                 if (strcmp (optarg, "show") != 0)
02201                                 {
02202                                         print ("Device name not valid: %s. use -i show to display valid names\n", optarg);
02203                                         goto end_with_error;
02204                                 }
02205                                 else exit(0);
02206                         }
02207                         break;
02208                 case 'R':
02209                         display_raw_stats=1;
02210                         pct_treshold=0;
02211                         break;
02212                 case 'H':
02213                         display_http_only=1;
02214                         break;
02215                 case 'p':
02216                         pct_treshold=atof(optarg);
02217                         break;
02218                 case 't':
02219                         truncate_packet=1;
02220                         break;
02221                 case 'S':
02222                         do_stats=0;
02223                         break;          
02224                 case 'r':
02225                         ifile = optarg;
02226                         break;
02227                 case 's':
02228                         maxpacketsize = atoi (optarg);
02229                         break;
02230                 case 'a':
02231                         if(optarg==NULL) anonymise=0;
02232                         else
02233                         {
02234                                 while(*optarg)
02235                                 {
02236                                         if(*optarg=='d') anonymise_date=0;
02237                                         else if(*optarg=='p') anonymise_port=0;
02238                                         else if(*optarg=='m') anonymise_mac=0;
02239                                         else if(*optarg=='t') anonymise_timestamp=0;
02240                                         else if(*optarg=='u') anonymise_url=0;
02241                                         else if(*optarg=='h') anonymise_http=0;
02242                                         else if(*optarg=='i') anonymise_ip=0;
02243                                         else if(*optarg=='c') anonymise_content=0;
02244                                         else if(*optarg=='k') anonymise_checksum=0;
02245                                         else if(*optarg=='s') anonymise_sequence=0;
02246                                         else
02247                                         {
02248                                                 print ("Invalid anonymise option specified: %c\n",*optarg);
02249                                                 goto end_with_error;
02250                                         }
02251                                         optarg++;
02252                                 }
02253                         }
02254                         break;
02255                 case 'd':
02256                         if(optarg==NULL) display=0;
02257                         else
02258                         {
02259                                 while(*optarg)
02260                                 {
02261                                         if(*optarg=='t') display_timestamp=0;
02262                                         else if(*optarg=='h') display_http=0;
02263                                         else if(*optarg=='f') display_flags=0;
02264                                         else if(*optarg=='T') display_tcp_infos=0;
02265                                         else if(*optarg=='p') display_progress=0;
02266                                         else if(*optarg=='r') display_unanswered_requests=0;
02267                                         else
02268                                         {
02269                                                 print ("Invalid display option specified: %c\n",*optarg);
02270                                                 goto end_with_error;
02271                                         }
02272                                         optarg++;
02273                                 }
02274                         }
02275                         break;
02276                 case 'w':
02277                         ofile = optarg;
02278                         break;
02279                 case 'n':
02280                         nbpacketstocapture = atoi (optarg);
02281                         break;
02282                 case 'u':
02283                         use_sequence_numbers=1;
02284                         break;
02285                 case 'm':
02286                         maxfilesize=parse_size(optarg);
02287                         break;
02288                 case 'f':
02289                         packet_filter=optarg;
02290                         break;
02291                 case 'x':
02292                         packet_filter="";
02293                         already_anonymised=1;
02294                         anonymise=0;
02295                         break;
02296                 case '?':
02297                         exit (0);
02298                         break;
02299                 default:
02300                         print ("Unknown option used\n");
02301                         break;
02302                 }
02303         }
02304         
02305         if(ofile) output_file_written=24;
02306         if(ofile && strcmp(ofile,"-")==0)
02307         {
02308                 output_stream=stderr;
02309         }
02310         if (optind < argc)
02311         {
02312                 print ("Arguments not expected: ");
02313                 while (optind < argc)
02314                 {
02315                         print ("%s ", argv[optind++]);
02316                 }
02317                 print ("!\n");
02318         }
02319         // End of command line options parsing
02320         
02321         if(!anonymise && !already_anonymised) 
02322         {
02323                 timeoffset=gmt2local(0);
02324                 timeoffset_usec=0;
02325         }
02326         srand(time(NULL)); //Initialise the random numbers generator
02327         
02328         if (ifile && dev)
02329         {
02330                 print ("Please choose between live and file mode. -r and -i options are mutually exclusive.\n");
02331                 goto end_with_error;
02332         }
02333         if (ifile == NULL) // We are in live mode
02334         {                       
02335                 if (dev == NULL) // If no interface was specified 
02336                 {               
02337                         // We try to use the first one 
02338                         dev = get_pcap_interface (NULL);
02339                         if (dev == NULL)
02340                         {
02341                                 print ("Interface name not specified. use -i show to display valid names\n");
02342                                 goto end_with_error;
02343                         }
02344                 }
02345 
02346                 // Open the adapter 
02347                 if ((adhandle = pcap_open_live (dev->name,      // name of the device
02348                                                 maxpacketsize,  // portion of the packet to capture
02349                                                 1,      // promiscuous mode
02350                                                 1000,   // read timeout
02351                                                 errbuf  // error buffer
02352                      )) == NULL)
02353                 {
02354                         print("Unable to open the adapter %s. Please check permissions.\n",dev->name);
02355                         goto end_with_error;
02356                 }
02357 
02358                 if (pcap_lookupnet (dev->name, &net, &netmask, errbuf) == -1)
02359                 {
02360                         print ("Error while getting device properties: %s\n",errbuf);
02361                         goto end_with_error;
02362                 }
02363 
02364                 print ("\nlistening on %s...\n", dev->name);
02365 
02366                 // At this point, we don't need any more the device list. Free it 
02367                 pcap_freealldevs (alldevs);
02368                 alldevs=NULL;
02369         }
02370         else /* if(ifile) */
02371         {
02372                 /* We read the data from a file */
02373                 //We get the input file size to print the progress
02374                 
02375                 input_file_read=24; //TCPDump trace header length
02376                 if(strcmp(ifile, "-")!=0) 
02377                 {
02378                         FILE *f;
02379                         f=fopen(ifile,"rb");
02380                         if(f)
02381                         {
02382                                 fseek(f, 0, SEEK_END);
02383                                 input_file_size=ftell(f);
02384                                 input_file_size_1pct=input_file_size/100;
02385                                 input_file_size_s=get_size(input_file_size);
02386                                 fclose(f);
02387                         }
02388                 }
02389 
02390                 if (!(adhandle = pcap_open_offline (ifile, errbuf)))
02391                 {
02392                         print ("Unable to open %s for reading.\n", ifile);
02393                         goto end_with_error;
02394                 }
02395         }
02396         // compile the filter
02397         if (pcap_compile (adhandle, &fcode, packet_filter, 1, netmask) < 0)
02398         {
02399                 print("Unable to compile the packet filter. Check the syntax.\n");
02400                 goto end_with_error;
02401         }
02402                 
02403         // set the filter
02404         if (pcap_setfilter (adhandle, &fcode) < 0)
02405         {
02406                 print("Error setting the filter.\n");
02407                 goto end_with_error;
02408         }
02409         //Check the link layer. We support only Ethernet
02410         if (pcap_datalink (adhandle) != DLT_EN10MB)
02411         {
02412                 print("This program works only on Ethernet networks.\n");
02413                 goto end_with_error;
02414         }
02415         /* Open the output file, if needed */
02416         if (ofile)
02417         {
02418                 if ((dumphandle = pcap_dump_open (adhandle, ofile)) == NULL)
02419                 {
02420                         print ("Unable to open %s for writing.\n", ofile);
02421 end_with_error:
02422                         //Free the device list 
02423                         if(alldevs) pcap_freealldevs(alldevs);
02424                         exit(EXIT_FAILURE);
02425                 }
02426         }
02427         //Set up the signal handler
02428          sa.sa_handler = catch_ctrl_c;
02429          sa.sa_flags = 0;
02430          sigaction(SIGINT, &sa, NULL);
02431 
02432         //start the capture 
02433         time(&start_time);
02434         pcap_loop (adhandle, -1, packet_handler, NULL);
02435 
02436         //The capture is finished. We close the input trace file
02437         time(&end_time);
02438         pcap_close (adhandle);
02439         
02440         //We close the dump file
02441         if (ofile) pcap_dump_close (dumphandle);
02442 
02443         //Free the compiled filter code
02444         pcap_freecode (&fcode);
02445         
02446         tmp=get_time(difftime(end_time, start_time));
02447         print ("\nProcessing time: %s",tmp);
02448         if(tmp) free(tmp);
02449         tmp=get_speed(input_file_read/difftime(end_time, start_time));
02450         if(tmp)
02451         {
02452                 print (" (at %s).",tmp);
02453                 free(tmp);
02454         }
02455         print ("\n\n");
02456         print ("%i packets captured, of which %i contain HTTP data.\n", nbpackets, nbvalidpackets);
02457         print ("%i requests, %i responses (Total: %i).\n", nb_request, nb_response, nb_request+nb_response);
02458         print ("---\n");
02459         
02460         ptr=dialog_table;
02461         c=0;
02462         while(ptr)
02463         {
02464                 c++;
02465                 ptr=ptr->next;
02466         }
02467         
02468         if(display && display_unanswered_requests==1) print("Unanswered requests: %i\n",c);
02469         
02470         //We print and free the unanswered requests
02471         ptr=dialog_table;
02472         while(ptr)
02473         {
02474                 ptr->response=NULL;
02475                 ptr->response_len=0;
02476                 if(do_stats && display && display_unanswered_requests==1) process_dialog(ptr);
02477                 next=ptr->next;
02478                 free_dialog(ptr);
02479                 ptr=next;
02480         }
02481 
02482         if(do_stats)
02483         {
02484                 print("\n");
02485                 display_string_table("Server versions:",server_version_table);
02486                 display_string_table("Server versions (simple):",server_version_simple_table);
02487                 display_string_table("User agents:",user_agent_table);
02488                 display_string_table("HTTP version:",http_version_table);
02489                 display_string_table_with_data_sorted("HTTP responses:",http_response_code_table," ");  
02490                 display_string_table("Extensions:",extension_table);    
02491                 display_string_table("Websites suffixes:",suffix_table);
02492                 if(display_raw_stats)
02493                 {
02494                         display_nb_table("Latency (in us): ",&latency_table);
02495                 }
02496                 else
02497                 {
02498                         latency_stats();
02499                 }
02500                 
02501                 if(display_raw_stats)
02502                 {
02503                         
02504                         display_nb_table("Content Length: ",&cl_table);
02505                 }
02506                 else
02507                 {
02508                         
02509                         content_length_stats();
02510                 }
02511                 
02512                 if(display_raw_stats)
02513                 {
02514                         display_nb_table("Freshness (in seconds):",&fresh_table);
02515                 }
02516                 else
02517                 {
02518                         freshness_stats();
02519                 }
02520                                 
02521                 //display_string_table_with_data("URLs:",url_table, "DATA:");
02522                 display_string_table("Content-Type:",content_type_table);
02523                 display_string_table("Content-Type (simple):",content_type_simple_table);
02524                 //display_string_table("Content-Length:",content_length_table);
02525                 if(display_raw_stats)
02526                 {
02527                         display_string_table("Headers:",header_table);  
02528                 }
02529                 //display_string_table("Sequence numbers:",sequence_number_table);      
02530         }               
02531         free_string_table(server_version_table);
02532         free_string_table(server_version_simple_table);
02533         free_string_table(user_agent_table);
02534         free_string_table(http_version_table);
02535         free_string_table(http_response_code_table);    
02536         free_string_table(extension_table);     
02537         free_string_table(suffix_table);        
02538         //free_string_table(url_table);
02539         free_string_table(header_table);
02540         free_string_table(content_type_table);
02541         free_string_table(content_type_simple_table);
02542         //free_string_table(content_length_table);
02543         //free_string_table(freshness_table);
02544         free_string_table(sequence_number_table);
02545         free_nb_table(cl_table);
02546         free_nb_table(fresh_table);
02547         free_nb_table(latency_table);
02548         free_anonymised_url_table();
02549         free(ip_table);
02550         free(port_table);
02551         if(input_file_size_s) free(input_file_size_s);
02552         if(alldevs) pcap_freealldevs (alldevs);
02553 
02554         return 0;
02555 }
02556 
02557 void free_anonymised_url_table()
02558 {
02559         char *ptr=anon_url_table;
02560         char *tmp;
02561         
02562         int i;
02563         for(i=0;i<nburl;i++)
02564         {
02565                 memcpy(&tmp, ptr, 4);
02566                 free(tmp);
02567                 memcpy(&tmp, ptr+4, 4);
02568                 free(tmp);
02569                 ptr+=8;
02570         }
02571         free(anon_url_table);
02572 }
02573         
02574 // Callback function invoked by libpcap for every incoming packet 
02575 void packet_handler (u_char * param, const struct pcap_pkthdr *header,const u_char *packet)
02576 {
02577         const u_char *data = packet;
02578         char *eop=(char*)packet+header->caplen; //End of packet (in memory)
02579         
02580         struct ether_header *eptr;      /* net/ethernet.h */
02581         struct ip_s *ip;
02582         u_int tcp_len;
02583         u_int len=header->caplen;
02584         u_int ip_hlen;
02585         
02586         char ip_src[] = "xxx.xxx.xxx.xxx";
02587         char ip_dst[] = "xxx.xxx.xxx.xxx";
02588         char real_ip_src[] = "xxx.xxx.xxx.xxx";
02589         char real_ip_dst[] = "xxx.xxx.xxx.xxx";
02590         u_short dport, sport, realdport, realsport;
02591 
02592         struct dialog *d = NULL;
02593         char *buffer;
02594         struct tcp_s *tcp;
02595         char *flags=NULL;
02596         u_int32_t seq;
02597         char seq_nb[12];
02598         char next_seq_nb[12];
02599         string_and_nb *item=NULL;       
02600         int expected=0;
02601         char *eoh=NULL;
02602         
02603         *eop='\0';
02604         input_file_read+=header->caplen+16;
02605         input_file_last+=header->caplen+16;
02606         if(!display && display_progress)
02607         {
02608                 //stats are displayed every 1Mb (or 1%) for offline mode, or every 50kb for online mode
02609                 if((ifile && input_file_last>=input_file_size_1pct && input_file_last>1000000) || (!ifile && input_file_read-input_file_last>=50000))
02610                 {
02611                         time_t t;
02612                         double diff;
02613                         input_file_last=0;
02614                         
02615                         time(&t);
02616                         diff=input_file_read/difftime(t, start_time);
02617                         
02618                         buffer=get_size(input_file_read);
02619                         if(buffer)
02620                         {
02621                                 if(input_file_size_s)
02622                                 {
02623                                         char *buffer2=get_pct((double)input_file_read/input_file_size);
02624                                         if(buffer2)
02625                                         {
02626                                                 print("[%s] ",buffer2);
02627                                                 free(buffer2);
02628                                         }
02629                                         print("Processed %s/%s",buffer,input_file_size_s);
02630                                 }
02631                                 else print("Processed %s",buffer);
02632                                 
02633                                 free(buffer);
02634                         }
02635                                 
02636                         buffer=get_speed(diff);
02637                         if(buffer)
02638                         {
02639                                 print(" at %s",buffer);
02640                                 free(buffer);
02641                         }
02642                         if(ofile)
02643                         {
02644                                 char *tmp=get_size(output_file_written);
02645                                 if(tmp)
02646                                 {
02647                                         print(" (Written %s)",tmp);
02648                                         free(tmp);
02649                                 }
02650                         }
02651                         print("\n");
02652                         fflush(output_stream);
02653                 }
02654         }
02655         if(anonymise && anonymise_timestamp) anon_timestamp((struct timeval*)&header->ts);
02656         
02657         // Packet is smaller than ethernet header length
02658         if ((header->caplen) < ETHER_HDRLEN) goto function_end;
02659 
02660         // Anoymise source & dest MAC address 
02661         if (anonymise && anonymise_mac) memset ((char *) packet, 0, 12);
02662 
02663         eptr = (struct ether_header *) data;
02664 
02665         // We only process the packet if its type it is an IP packet.
02666         if (ntohs (eptr->ether_type) != ETHERTYPE_IP) goto function_end;
02667         if (len < sizeof (struct ip_s)) goto function_end;
02668 
02669         // We now have an IP packet
02670         data += sizeof (struct ether_header);
02671         len -= sizeof (struct ether_header);
02672                 
02673         ip = (struct ip_s *) (data);
02674 
02675         // If the ip packet hasn't been truncated and it has a correct header length
02676         if (len < sizeof (struct ip_s) || IP_HL (ip) < 5) goto function_end;
02677         if (ip->ip_p != IPPROTO_TCP) goto function_end;
02678                 
02679         if(anonymise && anonymise_checksum) ip->ip_sum=(u_int16_t)0;
02680         
02681         //We check that the used version of IP is 4
02682         if (IP_V (ip) != 4) goto function_end;
02683         
02684         ip_hlen = (ip->ip_vhl & 0x0f) * 4;
02685 
02686         // We have a TCP packet
02687         data += ip_hlen;
02688         len -= ip_hlen;
02689         
02690         if (len < sizeof (struct tcp_s)) goto function_end;
02691 
02692         //The TCP packet is valid
02693         tcp = (struct tcp_s*) data;
02694         if(display && display_tcp_infos && display_flags) flags=compute_flags(tcp->th_flag);    
02695         
02696         if(anonymise && anonymise_checksum) tcp->th_chksum=(u_int16_t)0;
02697         
02698         //Erasing tcp timestamp
02699         if(anonymise && anonymise_timestamp)
02700         {
02701                 if (tcp->th_hlen_reserved > 80)
02702                 {
02703                         int offset=0;
02704                         if (tcp-> th_hlen_reserved == 128)
02705                         {
02706                                 if ((data[20] == 0x01) && (data[21] == 0x01) && (data[22] == 0x08) && (data[23] == 0x0a)) 
02707                                         offset=24;
02708                         }
02709                         else if (tcp->th_hlen_reserved == 160)
02710                         {
02711                                 if ((data[26] == 0x08) && (data[27] == 0x0a)) 
02712                                         offset=28;
02713                         }
02714                         if(offset)
02715                         {
02716                                         //print("TIME ");
02717                                         //ts_print((struct timeval*)data+offset);
02718                                         //print("\n");
02719                                         //anon_timestamp((struct timeval*)data+offset);
02720                                         //print("TIME2 ");
02721                                         //ts_print((struct timeval*)data+offset);
02722                                         //print("\n\n");
02723                                         memset((void*)data+offset,0,8);
02724                         }
02725                 }
02726         }
02727 
02728         /* Anonymising IP src & dest */
02729         strcpy (real_ip_src,inet_ntoa(ip->ip_src));
02730         strcpy (real_ip_dst,inet_ntoa(ip->ip_dst));
02731         
02732         if (anonymise && anonymise_ip)
02733         {
02734                 anon_ip(&(ip->ip_src));
02735                 anon_ip(&(ip->ip_dst));
02736         }
02737 
02738         strcpy (ip_src,inet_ntoa(ip->ip_src));
02739         strcpy (ip_dst,inet_ntoa(ip->ip_dst));
02740 
02741         /* Anonymising source and destination ports */
02742         realdport = ntohs (tcp->th_dport);      // destination port number 
02743         realsport = ntohs (tcp->th_sport);      // source port number
02744         if (anonymise && anonymise_port)
02745         {
02746                 anon_port(&(tcp->th_sport));
02747                 anon_port(&(tcp->th_dport));
02748         }
02749         dport = ntohs (tcp->th_dport);  // destination port number 
02750         sport = ntohs (tcp->th_sport);  // source port number
02751 
02752         nbpackets++;
02753         data += tcp->th_hlen_reserved/4;
02754         len -= tcp->th_hlen_reserved/4;
02755         
02756         tcp_len=header->len-sizeof(struct ether_header)-ip_hlen-tcp->th_hlen_reserved/4;
02757 
02758         if(anonymise && anonymise_sequence) anon_sequence(&(tcp->th_seq));
02759                 
02760         seq=htonl(tcp->th_seq);
02761         sprintf(seq_nb, "%u", seq);
02762 
02763         if(use_sequence_numbers) sprintf(next_seq_nb,"%u",seq+tcp_len);
02764 
02765         if (/*(already_anonymised ||realsport == 80 || realdport ==80)
02766                 &&*/ len >sizeof(struct tcp_s) && (strncmp(data,"HTTP",4) == 0 || strncmp(data,"GET ",4) == 0))
02767         {
02768                 //We look for the end of the headers (CRLF CRLF)
02769                         
02770                 eoh= strstr_limited ((char*)data, eop, "\r\n\r\n");     //End of headers
02771                 if (eoh) 
02772                 {
02773                         //We only keep a final "\r\n"
02774                         eoh+=2;
02775                         len=eoh-(char*)data;
02776                 }
02777                 else eoh = eop;
02778 
02779                 if(anonymise && anonymise_content) memset_range(eoh, eop,0);
02780                 if(anonymise && anonymise_http) anon_http((char*)data,len);
02781                 
02782                 if(display) display_packet_infos(nbpackets, (struct timeval*)&(header->ts), ip_src, ip_dst, sport, dport);
02783                 
02784                 nbvalidpackets++;
02785 
02786                 buffer = xmalloc (len + 1);
02787                 memcpy (buffer, data, len);
02788                 buffer[len] = '\0';
02789 
02790                 if (*data=='G') //This is a request
02791                 {
02792                         if(display)
02793                         {
02794                                 print ("REQ ");
02795                                 display_additional_info();
02796                         }
02797                         nb_request++;
02798                         
02799                         d=buffer_request(buffer,len,nbpackets,ip_src,ip_dst,sport,dport);
02800                         memcpy(&(d->ts_request), (struct timeval*)&(header->ts), sizeof(struct timeval));
02801                 }
02802                 else // This is a response
02803                 {
02804                         if(display)
02805                         {
02806                                 print ("ANS ");
02807                                 display_additional_info();
02808                         }
02809                         nb_response++;
02810 
02811                         d = find_request (ip_src, ip_dst, sport, dport);
02812                         if (d) //We have a buffered request corresponing to this response
02813                         {
02814                                 int lat;
02815                                 struct timeval time_diff;
02816                                 memcpy(&(d->ts_response), (struct timeval*)&(header->ts), sizeof(struct timeval));
02817                                 time_diff.tv_sec=d->ts_response.tv_sec-d->ts_request.tv_sec;
02818                                 
02819                                 if(d->ts_request.tv_usec <= d->ts_response.tv_usec) time_diff.tv_usec=d->ts_response.tv_usec - d->ts_request.tv_usec;
02820                                 else
02821                                 {
02822                                         time_diff.tv_usec=d->ts_response.tv_usec - d->ts_request.tv_usec + 1000000;
02823                                         time_diff.tv_sec--;
02824                                 }
02825                                 
02826                                 lat=time_diff.tv_sec*1000000.0+time_diff.tv_usec;
02827                                 stats_add_latency(lat);
02828                                 
02829                                 if(display)
02830                                 {
02831                                         print("lat=");
02832                                         ts_print_diff(&time_diff);
02833                                         print("[%i]",d->req_nb);
02834                                 }
02835                         }
02836                         else //We have found no corresponding request to this reply
02837                         {
02838                                 d=buffer_request(NULL,0,0,real_ip_src,real_ip_dst,realsport,realdport);
02839                                 memcpy(&(d->ts_response), (struct timeval*)&(header->ts), sizeof(struct timeval));
02840                                 if(display) print ("[??]");
02841                         }
02842                         d->resp_nb=nbpackets;
02843                         d->response = buffer;
02844                         d->response_len=len;
02845                                 
02846                         if(display && display_http) print ("\n-----------------\n");    
02847                         process_dialog(d);
02848                         free_dialog(d);
02849                         
02850                         if(display && display_http) print ("-----------------");
02851                 }
02852                 if(display) print("\n");
02853         } //end if is_valid
02854         else 
02855         {
02856                 if(truncate_packet) eoh=(char*)data;
02857                 if(anonymise && anonymise_content) memset_range((char*)data, eop,'\0');
02858 
02859                 if(tcp_len>0)
02860                 {
02861                         if (use_sequence_numbers)
02862                         {
02863                                 if((item=find_item(sequence_number_table, seq_nb)))
02864                                 {
02865                                         //If were expecting this sequence number
02866                                         //This is a continuation packet, containing HTTP data
02867                                         goto exp;
02868                                 }
02869                         }
02870                         else
02871                         {
02872 exp:
02873                                 nbvalidpackets++;
02874                                 expected=1;     
02875                         }
02876                 }
02877                 if(!display_http_only && display)
02878                 {
02879                         display_packet_infos(nbpackets, (struct timeval*)&(header->ts), ip_src, ip_dst, sport, dport);
02880                         if(expected) 
02881                         {
02882                                 //if(item && item->data) print("CNT %s ",(char*)item->data);
02883                                 //else 
02884                                 print("CNT ");
02885                         }
02886                         else print("    ");
02887                         display_additional_info();
02888                         print("\n");
02889                 }
02890         }
02891         if(use_sequence_numbers)
02892         {
02893                 char tmp[12];
02894                 char *tmp2;
02895                 sprintf(tmp, "%i", nbpackets);
02896                 tmp2=strdup(tmp);
02897 
02898                 if(expected)
02899                 {
02900                         free(item->s);
02901                         item->s=strdup(next_seq_nb);
02902                         if(item->data)
02903                         {
02904                                 free(item->data);
02905                                 item->data=tmp2;
02906                         }
02907                 }
02908                 else stats_add_sequence_number_with_data(next_seq_nb, tmp2);
02909         }
02910         
02911         if(nbpackets>=nbpacketstocapture && nbpacketstocapture>0) pcap_breakloop(adhandle);
02912         
02913 function_end:   
02914         //We dump the (anonymised) packet to the output file, if needed
02915         if (ofile) 
02916         {
02917                 if(maxfilesize==0 || output_file_written<maxfilesize)
02918                 {
02919                         if(truncate_packet)
02920                         {
02921                                 int diff;
02922                                 //if(eoh==NULL) eoh = eop;
02923                                 if(eoh==NULL) eoh = (char *)data;
02924                                 diff=eoh-(char*)packet;
02925                                 if(header->caplen!=diff) 
02926                                 {
02927                                         //new_header=xmalloc(sizeof(struct pcap_pkthdr));
02928                                         //memcpy(new_header, header, sizeof(struct pcap_pkthdr));
02929                                         //new_header->caplen=diff+1;
02930                                         ((struct pcap_pkthdr*)header)->caplen=diff;
02931                                         //*((char*)packet+diff)='\0';
02932                                         //printf("diff:%i\n",diff);
02933                                         //header=new_header;
02934                                         //printf("aaa\n");
02935                                         //printf("%i %i\n",header->caplen,eoh-(char*)packet);
02936                                 }
02937                         }
02938                         pcap_dump ((u_char *) dumphandle, header, packet);
02939                         output_file_written+=header->caplen+16;
02940                 }
02941         }
02942         if(flags) free(flags);  
02943 }

Generated on Sat Sep 10 01:19:13 2005 for Anon by  doxygen 1.4.3-20050530