00001 #include <pcap.h>
00002 #include <stdio.h>
00003 #include <unistd.h>
00004 #include <string.h>
00005 #include <stdlib.h>
00006
00007
00008 #include <signal.h>
00009
00010
00011 #include <sys/socket.h>
00012 #include <netinet/in.h>
00013 #include <arpa/inet.h>
00014
00015
00016 #include <net/ethernet.h>
00017
00018
00019 #include <sys/time.h>
00020
00021
00022 #include <stdarg.h>
00023
00024 #include <time.h>
00025
00026
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;
00077 int nbports = 0;
00078 int nburl=0;
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;
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
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
00168
00169
00170
00171
00172
00173
00174
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
00346
00347
00348
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
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
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
00418
00419
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
00441 float time=tvp->tv_sec*1000.0+tvp->tv_usec/1000.0;
00442 print("%.02fms ",time);
00443 }
00444
00445
00446
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
00479 dialog_table=newdialog;
00480 newdialog->prev=NULL;
00481 }
00482 else
00483 {
00484
00485
00486
00487 int i=0;
00488 struct dialog *ptr=dialog_table;
00489 while(ptr && ptr->next!=NULL)
00490 {
00491 if(ptr->request) i++;
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
00569 if(*newurl=='/')
00570 {
00571 has_hostname=0;
00572 }
00573 afterproto=newurl;
00574 ptr=newurl;
00575 }
00576
00577 first_slash=strstr(ptr, "/");
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 if(has_hostname)
00588 {
00589 char *ptr_orig=ptr;
00590
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
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
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
00661 bak=*end;
00662 *end='\0';
00663 last_dot=rindex(ptr,'.');
00664 *end=bak;
00665 if(!last_dot) last_dot=end;
00666
00667
00668 while(ptr<last_dot)
00669 {
00670 *ptr=get_random_char();
00671 ptr++;
00672 }
00673
00674
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
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
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
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
00782
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
00829
00830
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
00865
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
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
00907
00908
00909 strncpy(date, buffer, len);
00910 date[len]='\0';
00911
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
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
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
01037
01038 if(ptr && *ptr=='<')
01039 {
01040 anon_field("",ptr);
01041 }
01042 }
01043 }
01044 if(scan)
01045 {
01046
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
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
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
01086
01087
01088
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
01121
01122
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)
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
01160
01161
01162
01163
01164
01165
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
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
01242
01243
01244
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
01272
01273 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
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
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;
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
01631
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
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
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;
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
01694 if(pct_treshold!=0 && pct<pct_treshold/100.0 && sorted && j<nb-1
01695 && table!=http_response_code_table)
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;
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
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;
01782 else
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
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
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
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
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
01966 for (i = 0; i < nbports; i++)
01967 {
01968
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)
01977 {
01978 newport = htons (nbports + FIRST_ANON_PORT);
01979
01980
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
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
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
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
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
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
02117
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
02320
02321 if(!anonymise && !already_anonymised)
02322 {
02323 timeoffset=gmt2local(0);
02324 timeoffset_usec=0;
02325 }
02326 srand(time(NULL));
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)
02334 {
02335 if (dev == NULL)
02336 {
02337
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
02347 if ((adhandle = pcap_open_live (dev->name,
02348 maxpacketsize,
02349 1,
02350 1000,
02351 errbuf
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
02367 pcap_freealldevs (alldevs);
02368 alldevs=NULL;
02369 }
02370 else
02371 {
02372
02373
02374
02375 input_file_read=24;
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
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
02404 if (pcap_setfilter (adhandle, &fcode) < 0)
02405 {
02406 print("Error setting the filter.\n");
02407 goto end_with_error;
02408 }
02409
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
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
02423 if(alldevs) pcap_freealldevs(alldevs);
02424 exit(EXIT_FAILURE);
02425 }
02426 }
02427
02428 sa.sa_handler = catch_ctrl_c;
02429 sa.sa_flags = 0;
02430 sigaction(SIGINT, &sa, NULL);
02431
02432
02433 time(&start_time);
02434 pcap_loop (adhandle, -1, packet_handler, NULL);
02435
02436
02437 time(&end_time);
02438 pcap_close (adhandle);
02439
02440
02441 if (ofile) pcap_dump_close (dumphandle);
02442
02443
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
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
02522 display_string_table("Content-Type:",content_type_table);
02523 display_string_table("Content-Type (simple):",content_type_simple_table);
02524
02525 if(display_raw_stats)
02526 {
02527 display_string_table("Headers:",header_table);
02528 }
02529
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
02539 free_string_table(header_table);
02540 free_string_table(content_type_table);
02541 free_string_table(content_type_simple_table);
02542
02543
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
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;
02579
02580 struct ether_header *eptr;
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
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
02658 if ((header->caplen) < ETHER_HDRLEN) goto function_end;
02659
02660
02661 if (anonymise && anonymise_mac) memset ((char *) packet, 0, 12);
02662
02663 eptr = (struct ether_header *) data;
02664
02665
02666 if (ntohs (eptr->ether_type) != ETHERTYPE_IP) goto function_end;
02667 if (len < sizeof (struct ip_s)) goto function_end;
02668
02669
02670 data += sizeof (struct ether_header);
02671 len -= sizeof (struct ether_header);
02672
02673 ip = (struct ip_s *) (data);
02674
02675
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
02682 if (IP_V (ip) != 4) goto function_end;
02683
02684 ip_hlen = (ip->ip_vhl & 0x0f) * 4;
02685
02686
02687 data += ip_hlen;
02688 len -= ip_hlen;
02689
02690 if (len < sizeof (struct tcp_s)) goto function_end;
02691
02692
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
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
02717
02718
02719
02720
02721
02722
02723 memset((void*)data+offset,0,8);
02724 }
02725 }
02726 }
02727
02728
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
02742 realdport = ntohs (tcp->th_dport);
02743 realsport = ntohs (tcp->th_sport);
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);
02750 sport = ntohs (tcp->th_sport);
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 (
02766 len >sizeof(struct tcp_s) && (strncmp(data,"HTTP",4) == 0 || strncmp(data,"GET ",4) == 0))
02767 {
02768
02769
02770 eoh= strstr_limited ((char*)data, eop, "\r\n\r\n");
02771 if (eoh)
02772 {
02773
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')
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
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)
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
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 }
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
02866
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
02883
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
02915 if (ofile)
02916 {
02917 if(maxfilesize==0 || output_file_written<maxfilesize)
02918 {
02919 if(truncate_packet)
02920 {
02921 int diff;
02922
02923 if(eoh==NULL) eoh = (char *)data;
02924 diff=eoh-(char*)packet;
02925 if(header->caplen!=diff)
02926 {
02927
02928
02929
02930 ((struct pcap_pkthdr*)header)->caplen=diff;
02931
02932
02933
02934
02935
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 }