"Fossies" - the Fresh Open Source Software Archive 
Member "tcpflow-1.6.1/src/tcpip.cpp" (19 Feb 2021, 22544 Bytes) of package /linux/misc/tcpflow-1.6.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "tcpip.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.5.0_vs_1.6.1.
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
47 uint32_t tcpip::seen_bytes()
48 {
49 if(seen) return seen->size();
50 return 0;
51 }
52
53 void tcpip::dump_seen()
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 */
103 tcpip::~tcpip()
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 */
128 void tcpip::close_file()
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
177 int tcpip::open_file()
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);
205 if(demux.open_flows.size() > demux.max_open_flows) demux.max_open_flows = demux.open_flows.size();
206 //std::cerr << "open_file1 " << *this << "\n";
207 }
208 if(demux.opt.output_packet_index){
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
248 if(demux.opt.max_bytes_per_flow>=0){
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;
533 out_of_order_count++;
534 DEBUG(25)("%s: insert(0,%d); lseek(%d,0,SEEK_SET) out_of_order_count=%" PRId64,
535 flow_pathname.c_str(), insert_bytes,
536 fd,out_of_order_count);
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
635 if (demux.opt.output_packet_index) {
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 */
663 void tcpip::sort_index(){
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++"