tcpflow  1.6.1
About: tcpflow is a TCP/IP packet demultiplexer that captures data transmitted as part of TCP connections (flows), and stores the data in a way that is convenient for protocol analysis and debugging.
  Fossies Dox: tcpflow-1.6.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

tcpip.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of tcpflow by Simson Garfinkel,
3  * originally by Jeremy Elson <jelson@circlemud.org>
4  *
5  * Modified by Greg Drew to add support for creating a packet time / data index
6  * which allows mapping bytes in the flow back to their relative arrival time.
7  * This is very useful in reassembling inherently bidirectional conversations
8  * such as chat or telnet sessions. --GDD
9  *
10  * This source code is under the GNU Public License (GPL). See
11  * LICENSE for details.
12  *
13  */
14 
15 #include "tcpflow.h"
16 #include "tcpip.h"
17 #include "tcpdemux.h"
18 
19 #include <iostream>
20 #include <sstream>
21 #include <vector>
22 #include <string>
23 
24 #pragma GCC diagnostic ignored "-Weffc++"
25 #pragma GCC diagnostic ignored "-Wshadow"
26 
27 
28 /* Create a new tcp object.
29  *
30  * Creating a new object creates a new passive TCP/IP decoder.
31  * It will *NOT* append to a flow that is already on the disk or in memory.
32  *
33  * called from tcpdemux::create_tcpip()
34  */
35 tcpip::tcpip(tcpdemux &demux_,const flow &flow_,be13::tcp_seq isn_):
36  demux(demux_),myflow(flow_),dir(unknown),isn(isn_),nsn(0),
37  syn_count(0),fin_count(0),fin_size(0),pos(0),
38  flow_pathname(),fd(-1),file_created(false),
39  flow_index_pathname(),idx_file(),
40  seen(new recon_set()),
41  last_byte(),
42  last_packet_number(),out_of_order_count(0),violations(0)
43 {
44 }
45 
46 
48 {
49  if(seen) return seen->size();
50  return 0;
51 }
52 
54 {
55  if(seen){
56  for(recon_set::const_iterator it = seen->begin(); it!=seen->end(); it++){
57  std::cerr << *it << ", ";
58  }
59  std::cerr << std::endl;
60  }
61 }
62 
63 void tcpip::dump_xml(class dfxml_writer *xreport,const std::string &xmladd)
64 {
65  static const std::string fileobject_str("fileobject");
66  static const std::string filesize_str("filesize");
67  static const std::string filename_str("filename");
68  static const std::string tcpflow_str("tcpflow");
69 
70  xreport->push(fileobject_str);
71  if(flow_pathname.size()) xreport->xmlout(filename_str,flow_pathname);
72 
73  xreport->xmlout(filesize_str,last_byte);
74 
75  std::stringstream attrs;
76  attrs << "startime='" << dfxml_writer::to8601(myflow.tstart) << "' ";
77  attrs << "endtime='" << dfxml_writer::to8601(myflow.tlast) << "' ";
78  if(myflow.has_mac_daddr()) attrs << "mac_daddr='" << macaddr(myflow.mac_daddr) << "' ";
79  if(myflow.has_mac_saddr()) attrs << "mac_saddr='" << macaddr(myflow.mac_saddr) << "' ";
80  attrs << "family='" << (int)myflow.family << "' ";
81  attrs << "src_ipn='" << ipaddr_prn(myflow.src, myflow.family) << "' ";
82  attrs << "dst_ipn='" << ipaddr_prn(myflow.dst, myflow.family) << "' ";
83  attrs << "srcport='" << myflow.sport << "' ";
84  attrs << "dstport='" << myflow.dport << "' ";
85  attrs << "packets='" << myflow.packet_count << "' ";
86  if(out_of_order_count) attrs << "out_of_order_count='" << out_of_order_count << "' ";
87  if(violations) attrs << "violations='" << violations << "' ";
88  attrs << "len='" << myflow.len << "' ";
89  if(myflow.len != myflow.caplen) attrs << "caplen='" << myflow.caplen << "' ";
90  xreport->xmlout(tcpflow_str,"",attrs.str(),false);
91  if(xmladd.size()>0) xreport->xmlout("",xmladd,"",false);
92  xreport->pop();
93  xreport->flush();
94 }
95 
96 
97 /**
98  * Destructor is called when flow is closed.
99  * It implements "after" processing.
100  * This should only be called from remove_flow() or remove_all_flows()
101  * when a flow is deleted.
102  */
104 {
105  assert(fd<0); // file must be closed
106  delete seen; // no need to check to see if seen is null or not.
107 }
108 
109 #pragma GCC diagnostic warning "-Weffc++"
110 #pragma GCC diagnostic warning "-Wshadow"
111 
112 
113 /****************************************************************
114  ** SAVE FILE MANAGEMENT
115  ****************************************************************
116  *
117  * Unlike the tcp/ip object, which is created once, the file can be opened, closed, and
118  * re-opened depending on the availability of file handles.
119  *
120  * Closing the file does not delete the tcp/ip object.
121  */
122 
123 
124 /* Closes the file belonging to a flow.
125  * Does not take tcpip out of flow database.
126  * Does not change pos.
127  */
129 {
130  if (fd>=0){
131  struct timeval times[2];
132  times[0] = myflow.tstart;
133  times[1] = myflow.tstart;
134 
135  DEBUG(5) ("%s: closing file in tcpip::close_file", flow_pathname.c_str());
136  /* close the file and remember that it's closed */
137 #if defined(HAVE_FUTIMES)
138  /* fix microseconds if they are invalid */
139  for ( int i=0; i<2; i++){
140  if ( times[i].tv_usec < 0 || times[i].tv_usec >= 1000000 ){
141  times[i].tv_usec = 0;
142  }
143  }
144  if (futimes(fd,times)){
145  fprintf(stderr,"%s: futimes(fd=%d,[%ld:%ld,%ld:%ld])\n",
146  strerror(errno),fd,
147  times[0].tv_sec,times[1].tv_usec,
148  times[1].tv_sec,times[1].tv_usec);
149  }
150 #elif defined(HAVE_FUTIMENS)
151  struct timespec tstimes[2];
152  for(int i=0;i<2;i++){
153  tstimes[i].tv_sec = times[i].tv_sec;
154  tstimes[i].tv_nsec = times[i].tv_usec * 1000;
155  }
156  if(futimens(fd,tstimes)){
157  perror("futimens(fd=%d)",fd);
158  }
159 #endif
160  close(fd);
161  fd = -1;
162  demux.open_flows.erase(this); // we are no longer open
163  }
164  // Also close the flow_index file, if flow indexing is in use --GDD
165  if(demux.opt.output_packet_index && idx_file.is_open()){
166  idx_file.close();
167  }
168  //std::cerr << "close_file1 " << *this << "\n";
169 }
170 
171 /*
172  * Opens the file transcript file (creating file if necessary).
173  * Called by store_packet()
174  * Does not change pos.
175  */
176 
178 {
179  int create_idx_needed = false;
180  if(fd<0){
181  //std::cerr << "open_file0 " << ct << " " << *this << "\n";
182  /* If we don't have a filename, create the flow */
183  if(flow_pathname.size()==0) {
184  flow_pathname = myflow.new_filename(&fd,O_RDWR|O_BINARY|O_CREAT|O_EXCL,0666);
185  file_created = true; // remember we made it
186  create_idx_needed = true; // We created a new stream, so we need to create a new flow file. --GDD
187  DEBUG(5) ("%s: created new file",flow_pathname.c_str());
188  } else {
189  /* open an existing flow */
190  fd = demux.retrying_open(flow_pathname,O_RDWR | O_BINARY | O_CREAT,0666);
191  lseek(fd,pos,SEEK_SET);
192  DEBUG(5) ("%s: opening existing file", flow_pathname.c_str());
193  }
194 
195  /* If the file isn't open at this point, there's a problem */
196  if (fd < 0 ) {
197  /* we had some problem opening the file -- set FINISHED so we
198  * don't keep trying over and over again to reopen it
199  */
200  perror(flow_pathname.c_str());
201  return -1;
202  }
203  /* Remember that we have this open */
204  demux.open_flows.push_back(this);
206  //std::cerr << "open_file1 " << *this << "\n";
207  }
209  //Open the file for the flow index. We don't do this if the flow file could not be
210  // opened. The file must be opened for append, in case this is a reopen. The filename
211  // standard is the flow name followed by ".findx", which google currently says does not
212  // conflict with anything major.
213  flow_index_pathname = flow_pathname + ".findx";
214  DEBUG(10)("opening index file: %s",flow_index_pathname.c_str());
215  if(create_idx_needed){
216  //New flow file, even if there was an old one laying around --GDD
217  idx_file.open(flow_index_pathname.c_str(),std::ios::trunc|std::ios::in|std::ios::out);
218  }else{
219  //Use existing flow file --GDD
220  idx_file.open(flow_index_pathname.c_str(),std::ios::ate|std::ios::in|std::ios::out);
221  }
222  if(idx_file.bad()){
223  perror(flow_index_pathname.c_str());
224  // Be nice and be sure the flow has been closed in the demultiplexer.
225  // demux.close_tcpip_fd(this); Need to fix this. Also, when called, it will
226  // have to differentiate the fact that the open fd cound only needs to be
227  // decremented by one and not by 2.--GDD
228  return -1;
229  }
230 
231  }
232  return 0;
233 }
234 
235 
236 
237 /*************************************************************************/
238 
239 /* print the contents of this packet to the console.
240  * This is nice for immediate satisfaction, but it can't handle
241  * out of order packets, etc.
242  */
243 void tcpip::print_packet(const u_char *data, uint32_t length)
244 {
245  /* green, blue, read */
246  const char *color[3] = { "\033[0;32m", "\033[0;34m", "\033[0;31m" };
247 
249  uint64_t max_bytes_per_flow = (uint64_t)demux.opt.max_bytes_per_flow;
250 
251  if(last_byte > max_bytes_per_flow) return; /* too much has been printed */
252  if(length > max_bytes_per_flow - last_byte){
253  length = max_bytes_per_flow - last_byte; /* can only output this much */
254  if(length==0) return;
255  }
256  }
257 
258 #ifdef HAVE_PTHREAD
259  if(semlock){
260  if(sem_wait(semlock)){
261  fprintf(stderr,"%s: attempt to acquire semaphore failed: %s\n",progname,strerror(errno));
262  exit(1);
263  }
264  }
265 #endif
266 
267  if(flow_pathname.size()==0) flow_pathname = myflow.filename(0, false);
268  if (demux.opt.use_color) fputs(dir==dir_cs ? color[1] : color[2], stdout);
269  if (demux.opt.suppress_header == 0 && demux.opt.output_json == 0){
270  printf("%s: ", flow_pathname.c_str());
271  if(demux.opt.output_hex) putchar('\n');
272  }
273 
274  size_t written = 0;
275  if(demux.opt.output_hex){
276  const size_t bytes_per_line = 32;
277  size_t max_spaces = 0;
278  for(u_int i=0;i<length;i+=bytes_per_line){
279  size_t spaces=0;
280 
281  /* Print the offset */
282  char b[64];
283  size_t count = snprintf(b,sizeof(b),"%04x: ",(int)i);
284  if(fwrite(b,1,count,stdout)!=count){
285  perror("fwrite");
286  }
287  spaces += count;
288 
289  /* Print the hext bytes */
290  for(size_t j=0;j<bytes_per_line && i+j<length ;j++){
291  unsigned char ch = data[i+j];
292  fprintf(stdout,"%02x",ch); spaces += 2;
293  if(j%2==1){
294  fputc(' ',stdout);
295  spaces += 1;
296  }
297  }
298  /* space out to where the ASCII region is */
299  if(spaces>max_spaces) max_spaces=spaces;
300  for(;spaces<max_spaces;spaces++){
301  fputc(' ',stdout);
302  }
303  putchar(' ');
304  /* Print the ascii */
305  for(size_t j=0;j<bytes_per_line && i+j<length;j++){
306  unsigned char ch = data[i+j];
307  if(ch>=' ' && ch<='~') fputc(ch,stdout);
308  else fputc('.',stdout);
309  }
310  fputc('\n',stdout);
311  }
312  written = length; // just fake it.
313  } else if (demux.opt.output_json) {
314  // {
315  // "src_host": "192.168.0.1",
316  // "src_port": 1234,
317  // "dst_host": "1.1.1.1",
318  // "dst_port": 80,
319  // "payload" : [...]
320  // }
321 
322  std::string hoststr = std::string();
323 
324  putchar('{');
325  printf("\"src_host\":\"");
326 
327  size_t src_pos = 0;
328  size_t src_end_pos = 0;
329  size_t src_pos_counter = 0;
330 
331  size_t pathname_len = flow_pathname.length();
332  for(size_t i = 0; i < pathname_len; ++i) {
333  if(flow_pathname[i] == '.') {
334  src_pos_counter++;
335  printf("%d%s", atoi(hoststr.c_str()), (src_pos_counter != 4 ? "." : ""));
336  hoststr.clear();
337  } else {
338  hoststr = hoststr + flow_pathname[i];
339  }
340  if(src_pos_counter == 4) {
341  src_pos = i;
342  break;
343  }
344  }
345  src_end_pos = src_pos;
346  for(;src_end_pos < pathname_len; ++src_end_pos) {
347  if(flow_pathname[src_end_pos] == '-') {
348  break;
349  }
350  }
351  printf("\",\"src_port\":%d,\"dst_host\":\"", atoi(flow_pathname.substr(src_pos + 1, src_end_pos - src_pos).c_str()));
352 
353  size_t dst_pos = src_end_pos + 1;
354  size_t dst_end_pos = dst_pos;
355  size_t dst_pos_counter = 0;
356 
357  for(size_t i = dst_pos; i < pathname_len; ++i) {
358  if(flow_pathname[i] == '.') {
359  dst_pos_counter++;
360  printf("%d%s", atoi(hoststr.c_str()), (dst_pos_counter != 4 ? "." : ""));
361  hoststr.clear();
362  } else {
363  hoststr = hoststr + flow_pathname[i];
364  }
365  if(dst_pos_counter == 4) {
366  dst_pos = i;
367  break;
368  }
369  }
370  dst_end_pos = dst_pos;
371  for(;dst_end_pos < pathname_len; ++dst_end_pos) {
372  if(flow_pathname[dst_end_pos] == '-') {
373  break;
374  }
375  }
376  printf("\",\"dst_port\":%d,\"payload\": [", atoi(flow_pathname.substr(dst_pos + 1, dst_end_pos - dst_pos).c_str()));
377 
378  for(size_t i = 0; i < length; ++i) {
379  printf("%d%s", data[i], (i != length - 1 ? "," : "]}"));
380  }
381  } else if (demux.opt.output_strip_nonprint) {
382  for(const u_char *cc = data;cc<data+length;cc++){
383  if(isprint(*cc) || (*cc=='\n') || (*cc=='\r')){
384  int ret = fputc(*cc,stdout);
385  if(ret==EOF){
386  std::cerr << "EOF on write to stdout\n";
387  exit(1);
388 
389  }
390  }
391  else fputc('.',stdout);
392  written += 1; // treat even unprintable characters as "written". It
393  // really means "processed"
394  }
395  } else {
396  written = fwrite(data,1,length,stdout);
397  if(length != written) std::cerr << "\nwrite error to stdout (" << length << "!=" << written << ") \n";
398  }
399 
400  last_byte += length;
401 
402  if (demux.opt.use_color) printf("\033[0m");
403 
404  if (! demux.opt.console_output_nonewline) putchar('\n');
405  fflush(stdout);
406 
407 #ifdef HAVE_PTHREAD
408  if(semlock){
409  if(sem_post(semlock)){
410  fprintf(stderr,"%s: attempt to post semaphore failed: %s\n",progname,strerror(errno));
411  exit(1);
412  }
413  }
414 #endif
415 }
416 
417 /*
418  * extend_file_and_insert():
419  * A handy function for inserting in the middle or beginning of a file.
420  *
421  * Based on:
422  * http://stackoverflow.com/questions/10467711/c-write-in-the-middle-of-a-binary-file-without-overwriting-any-existing-content
423  */
424 
425 static int shift_file(int fd, size_t inslen)
426 {
427  enum { BUFFERSIZE = 64 * 1024 };
428  char buffer[BUFFERSIZE];
429  struct stat sb;
430 
431  DEBUG(100)("shift_file(%d,%d)",fd,(int)inslen);
432 
433  if (fstat(fd, &sb) != 0) return -1;
434 
435  /* Move data after offset up by inslen bytes */
436  size_t bytes_to_move = sb.st_size;
437  off_t read_end_offset = sb.st_size;
438  while (bytes_to_move != 0) {
439  ssize_t bytes_this_time = bytes_to_move < BUFFERSIZE ? bytes_to_move : BUFFERSIZE ;
440  ssize_t rd_off = read_end_offset - bytes_this_time;
441  ssize_t wr_off = rd_off + inslen;
442  lseek(fd, rd_off, SEEK_SET);
443  if (read(fd, buffer, bytes_this_time) != bytes_this_time)
444  return -1;
445  lseek(fd, wr_off, SEEK_SET);
446  if (write(fd, buffer, bytes_this_time) != bytes_this_time)
447  return -1;
448  bytes_to_move -= bytes_this_time;
449  }
450  return 0;
451 }
452 
453 #pragma GCC diagnostic ignored "-Weffc++"
454 void update_seen(recon_set *seen,uint64_t pos,uint32_t length)
455 {
456  if(seen){
457  (*seen) += boost::icl::discrete_interval<uint64_t>::closed(pos,pos+length-1);
458  }
459 }
460 
461 /* store the contents of this packet to its place in its file
462  * This has to handle out-of-order packets as well as writes
463  * past the 4GiB boundary.
464  *
465  * 2012-10-24 Originally this code simply computed the 32-bit offset
466  * from the beginning of the file using the isn. The new version tracks
467  * nsn (the expected next sequence number for the open file).
468  *
469  * A relative seek before the beginning of the file means that we need
470  * to insert. A relative seek more than max_seek means that we have a
471  * different flow that needs to be separately handled.
472  *
473  * called from tcpdemux::process_tcp_packet()
474  */
475 void tcpip::store_packet(const u_char *data, uint32_t length, int32_t delta,struct timeval ts)
476 {
477  if(length==0) return; // no need to do anything
478 
479  uint32_t insert_bytes=0;
480  uint64_t offset = pos+delta; // where the data will go in absolute byte positions (first byte is pos=0)
481 
482  if((int64_t)offset < 0){
483  /* We got bytes before the beginning of the TCP connection.
484  * Either this is a protocol violation,
485  * or else we never saw a SYN and we got the ISN wrong.
486  */
487  if(syn_count>0){
488  DEBUG(2)("packet received with offset %" PRId64 "; ignoring",offset);
489  violations++;
490  return;
491  }
492  insert_bytes = -offset; // open up this much space
493  offset = 0; // and write the data here
494  }
495 
496  /* reduce length to write if it goes beyond the number of bytes per flow,
497  * but remember to seek out to the actual position after the truncated write...
498  */
499  uint32_t wlength = length; // length to write
500  if (demux.opt.max_bytes_per_flow >= 0){
501  uint64_t max_bytes_per_flow = (uint64_t)demux.opt.max_bytes_per_flow;
502 
503  if(offset >= max_bytes_per_flow){
504  wlength = 0;
505  }
506  if(offset < max_bytes_per_flow && offset+length > max_bytes_per_flow){
507  DEBUG(2) ("packet truncated by max_bytes_per_flow on %s", flow_pathname.c_str());
508  wlength = max_bytes_per_flow - offset;
509  }
510  }
511 
512  /* if we don't have a file open for this flow, try to open it.
513  * return if the open fails. Note that we don't have to explicitly
514  * save the return value because open_tcpfile() puts the file pointer
515  * into the structure for us.
516  */
517  if (fd < 0) {
518  if (open_file()) {
519  DEBUG(1)("unable to open TCP file %s fd=%d wlength=%d",
520  flow_pathname.c_str(),fd,(int)wlength);
521  return;
522  }
523  }
524 
525  /* Shift the file now if we were going shift it */
526 
527  if(insert_bytes>0){
528  if(fd>=0) shift_file(fd,insert_bytes);
529  isn -= insert_bytes; // it's really earlier
530  lseek(fd,(off_t)0,SEEK_SET); // put at the beginning
531  pos = 0;
532  nsn = isn+1;
534  DEBUG(25)("%s: insert(0,%d); lseek(%d,0,SEEK_SET) out_of_order_count=%" PRId64,
535  flow_pathname.c_str(), insert_bytes,
537 
538  /* TK: If we have seen packets, everything in the recon set needs to be shifted as well.*/
539  delete seen;
540  seen = 0;
541  }
542 
543  /* if we're not at the correct point in the file, seek there */
544  if (offset != pos) {
545  /* Check for a keepalive */
546  if(delta == -1 && length == 1) {
547  DEBUG(25)("%s: RFC1122 keepalive detected and ignored",flow_pathname.c_str());
548  return;
549  }
550 
551  if(fd>=0) lseek(fd,(off_t)delta,SEEK_CUR);
552  if(delta<0) out_of_order_count++; // only increment for backwards seeks
553  DEBUG(25)("%s: lseek(%d,%d,SEEK_CUR) offset=%" PRId64 " pos=%" PRId64 " out_of_order_count=%" PRId64,
554  flow_pathname.c_str(), fd,(int)delta,offset,pos,out_of_order_count);
555  pos += delta; // where we are now
556  nsn += delta; // what we expect the nsn to be now
557  }
558 
559  /* write the data into the file */
560  DEBUG(25) ("%s: %s write %ld bytes @%" PRId64,
561  flow_pathname.c_str(),
562  fd>=0 ? "will" : "won't",
563  (long) wlength, offset);
564 
565  if(fd>=0){
566  if ((uint32_t)write(fd,data, wlength) != wlength) {
567  DEBUG(1) ("write to %s failed: ", flow_pathname.c_str());
568  if (debug >= 1) perror("");
569  }
570  // Write to the index file if needed. Note, index file is sorted before close, so no need to jump around --GDD
571  if (demux.opt.output_packet_index && idx_file.is_open()) {
572  idx_file << offset << "|" << ts.tv_sec << "." << std::setw(6) << std::setfill('0') << ts.tv_usec << "|"
573  << wlength << "\n";
574  if (idx_file.bad()){
575  DEBUG(1)("write to index file %s failed: ",flow_index_pathname.c_str());
576  if(debug >= 1){
577  perror("");
578  }
579  }
580  }
581  if(wlength != length){
582  off_t p = lseek(fd,length-wlength,SEEK_CUR); // seek out the space we didn't write
583  DEBUG(100)(" lseek(%" PRId64 ",SEEK_CUR)=%" PRId64,(int64_t)(length-wlength),(int64_t)p);
584  }
585  }
586 
587  /* Update the database of bytes that we've seen */
588  if(seen) update_seen(seen,pos,length);
589 
590  /* Update the position in the file and the next expected sequence number */
591  pos += length;
592  nsn += length; // expected next sequence number
593 
594  if(pos>last_byte) last_byte = pos;
595 
596  if(debug>=100){
597  uint64_t rpos = lseek(fd,(off_t)0,SEEK_CUR);
598  DEBUG(100)(" pos=%" PRId64 " lseek(fd,0,SEEK_CUR)=%" PRId64,pos,rpos);
599  assert(pos==rpos);
600  }
601 
602 #ifdef DEBUG_REOPEN_LOGIC
603  /* For debugging, force this connection closed */
604  demux.close_tcpip_fd(this);
605 #endif
606 }
607 
608 /*
609  * Compare two index strings and return the result. Called by
610  * the vector::sort in sort_index.
611  * --GDD
612  */
613 bool tcpip::compare(std::string a, std::string b){
614  std::stringstream ss_a(a),ss_b(b);
615  long a_l,b_l;
616 
617  ss_a >> a_l;
618  ss_b >> b_l;
619  return a_l < b_l;
620 }
621 
622 /*
623  * Sort an index file (presumably from this object) if file indexing is
624  * turned on and the file exists. Index files may be out of order due
625  * to the arrival of out of order packets. It is cheaper to reorder them
626  * one time at the end of processing than it is to continually keep them
627  * in order.
628  * --GDD
629  */
630 void tcpip::sort_index(std::fstream *ix_file) {
631 
632  std::vector<std::string> idx;
633  std::string line;
634 
636  if (!(idx_file.good() && idx_file.is_open())) {
637  DEBUG(5)("Skipping index file sort. Unusual behavior.\n");
638  return; //Nothing to do
639  }
640  //Make sure we are at the beginning.
641  ix_file->clear();
642  ix_file->seekg(0);
643  do {
644  *ix_file >> line;
645  if (!ix_file->eof()) {
646  idx.push_back(line);
647  }
648  } while (ix_file->good());
649  std::sort(idx.begin(), idx.end(), &tcpip::compare);
650  ix_file->clear();
651  ix_file->seekg(0);
652  for (std::vector<std::string>::iterator s = idx.begin(); s != idx.end();
653  s++) {
654  *ix_file << *s << "\n";
655  }
656  }
657 }
658 
659 /*
660  * Convenience function to cause the local index file to be sorted.
661  * --GDD
662  */
664  tcpip::sort_index(&(this->idx_file));
665 }
666 
667 #pragma GCC diagnostic ignored "-Weffc++"
668 #pragma GCC diagnostic ignored "-Wshadow"
669 
670 /* Note --- Turn off warning so that creating the seen() map doesn't throw an error */
671 //#pragma GCC diagnostic ignored "-Weffc++"
ipaddr dst
Definition: tcpip.h:98
ipaddr src
Definition: tcpip.h:96
sa_family_t family
Definition: tcpip.h:101
uint16_t dport
Definition: tcpip.h:100
uint16_t sport
Definition: tcpip.h:99
Definition: tcpip.h:156
uint64_t len
Definition: tcpip.h:183
uint64_t packet_count
Definition: tcpip.h:185
uint8_t mac_saddr[6]
Definition: tcpip.h:180
bool has_mac_daddr()
Definition: tcpip.h:196
std::string new_filename(int *fd, int flags, int mode)
Definition: flow.cpp:167
struct timeval tstart
Definition: tcpip.h:181
uint8_t mac_daddr[6]
Definition: tcpip.h:179
uint64_t caplen
Definition: tcpip.h:184
std::string filename(uint32_t connection_count, bool)
Definition: flow.cpp:54
bool has_mac_saddr()
Definition: tcpip.h:200
struct timeval tlast
Definition: tcpip.h:182
void push_back(T *node)
void erase(T *node)
bool console_output_nonewline
Definition: tcpdemux.h:109
int64_t max_bytes_per_flow
Definition: tcpdemux.h:114
bool suppress_header
Definition: tcpdemux.h:116
bool output_strip_nonprint
Definition: tcpdemux.h:117
bool output_packet_index
Definition: tcpdemux.h:122
int retrying_open(const std::string &filename, int oflag, int mask)
Definition: tcpdemux.cpp:121
intrusive_list< tcpip > open_flows
Definition: tcpdemux.h:139
options opt
Definition: tcpdemux.h:146
void close_tcpip_fd(tcpip *)
unsigned int max_open_flows
Definition: tcpdemux.h:134
recon_set * seen
Definition: tcpip.h:317
void sort_index()
Definition: tcpip.cpp:663
class tcpdemux & demux
Definition: tcpip.h:295
uint32_t seen_bytes()
Definition: tcpip.cpp:47
uint64_t out_of_order_count
Definition: tcpip.h:320
void dump_seen()
Definition: tcpip.cpp:53
uint64_t last_byte
Definition: tcpip.h:318
uint64_t violations
Definition: tcpip.h:321
dir_t dir
Definition: tcpip.h:299
flow myflow
Definition: tcpip.h:298
int fd
Definition: tcpip.h:309
void dump_xml(class dfxml_writer *xmlreport, const std::string &xmladd)
Definition: tcpip.cpp:63
int open_file()
Definition: tcpip.cpp:177
uint64_t pos
Definition: tcpip.h:305
void store_packet(const u_char *data, uint32_t length, int32_t delta, struct timeval ts)
Definition: tcpip.cpp:475
uint32_t syn_count
Definition: tcpip.h:302
std::string flow_pathname
Definition: tcpip.h:308
tcpip(const tcpip &t)
std::fstream idx_file
Definition: tcpip.h:314
bool file_created
Definition: tcpip.h:310
intrusive_list< tcpip >::iterator it
Definition: tcpip.h:324
@ dir_cs
Definition: tcpip.h:280
void close_file()
Definition: tcpip.cpp:128
be13::tcp_seq isn
Definition: tcpip.h:300
be13::tcp_seq nsn
Definition: tcpip.h:301
virtual ~tcpip()
Definition: tcpip.cpp:103
void print_packet(const u_char *data, uint32_t length)
Definition: tcpip.cpp:243
std::string flow_index_pathname
Definition: tcpip.h:313
static bool compare(std::string a, std::string b)
Definition: tcpip.cpp:613
#define O_BINARY
static int debug
uint32_t tcp_seq
unsigned int uint32_t
Definition: core.h:40
dfxml_writer * xreport
Definition: tcpflow.cpp:242
const char * progname
Definition: tcpflow.cpp:70
#define SEEK_SET
Definition: tcpflow.h:202
std::string macaddr(const uint8_t *addr)
Definition: util.cpp:61
#define DEBUG(message_level)
Definition: tcpflow.h:273
void update_seen(recon_set *seen, uint64_t pos, uint32_t length)
Definition: tcpip.cpp:454
static int shift_file(int fd, size_t inslen)
Definition: tcpip.cpp:425