"Fossies" - the Fresh Open Source Software Archive

Member "tcpflow-1.6.1/src/tcpdemux.cpp" (19 Feb 2021, 28243 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 "tcpdemux.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  *
    3  * tcpdemux.cpp
    4  * A tcpip demultiplier.
    5  *
    6  * This file is part of tcpflow by Simson Garfinkel,
    7  * originally by Jeremy Elson <jelson@circlemud.org>
    8  *
    9  * This source code is under the GNU Public License (GPL).  See
   10  * LICENSE for details.
   11  *
   12  */
   13 
   14 #include "tcpflow.h"
   15 #include "tcpip.h"
   16 #include "tcpdemux.h"
   17 
   18 #include <iostream>
   19 #include <sstream>
   20 #include <vector>
   21 
   22 #ifdef HAVE_SYS_WAIT_H
   23 #include <sys/wait.h>
   24 #endif
   25 
   26 /* static */ uint32_t tcpdemux::max_saved_flows = 100;
   27 /* static */ uint32_t tcpdemux::tcp_timeout = 0;
   28 /* static */ int tcpdemux::tcp_subproc_max = 10;
   29 /* static */ int tcpdemux::tcp_subproc = 0;
   30 /* static */ int tcpdemux::tcp_alert_fd = -1;
   31 /* static */ std::string tcpdemux::tcp_cmd = "";
   32 
   33 tcpdemux::tcpdemux():
   34 #ifdef HAVE_SQLITE3
   35     db(),insert_flow(),
   36 #endif
   37     flow_sorter(0),tcp_processor(0),
   38     outdir("."),flow_counter(0),packet_counter(0),
   39     xreport(0),pwriter(0),max_open_flows(),max_fds(get_max_fds()-NUM_RESERVED_FDS),
   40     unique_id(0),
   41     flow_map(),open_flows(),saved_flow_map(),flow_fd_cache_map(0),
   42     saved_flows(),start_new_connections(false),opt(),fs()
   43 {
   44     tcp_processor = &tcpdemux::process_tcp;
   45 }
   46 
   47 void tcpdemux::alter_processing_core()
   48 {
   49     DEBUG(1) ("ensuring pcap core");
   50     tcp_processor = &tcpdemux::dissect_tcp;
   51     flow_sorter = new pcap_writer();
   52 }
   53 
   54 void tcpdemux::openDB()
   55 {
   56 #ifdef HAVE_SQLITE3
   57     int rc = sqlite3_open("test.db", &db);
   58     if( rc ){
   59         fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
   60         db = 0;
   61     }
   62     /* Create SQL statement */
   63     const char *sql = "CREATE TABLE connections ("
   64         "starttime TEXT NOT NULL,"
   65         "endtime TEXT NOT NULL,"
   66         "src_ipn TEXT,"
   67         "dst_ipn TEXT,"
   68         "mac_daddr TEXT,"
   69         "mac_saddr TEXT,"
   70         "packets INTEGER,"
   71         "srcport INTEGER,"
   72         "dstport INTEGER,"
   73         "hashdigest_md5 TEXT);";
   74 
   75     /* Execute SQL statement */
   76     rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
   77     if( rc != SQLITE_OK ){
   78         fprintf(stderr, "SQL error: %s\n", zErrMsg);
   79         sqlite3_free(zErrMsg);
   80         sqlite3_close(db);
   81         return 0;
   82     }
   83     const char* zSql = "INSERT INTO connections (starttime,endtime,src_ipn,dst_ipn,mac_daddr,mac_saddr,packets,srcport,dstport,hashdigest_md5) VALUES (?,?,?,?,?,?,?,?,?,?)";
   84     if(sqlite3_prepare_v2(db, zSql, strlen(zSql), &insert_stmt, NULL)!=SQLITE_OK ){
   85         fprintf(stderr, "SQL prepare error");
   86         db = 0;
   87         insert_stmt=0;
   88         return(0);
   89     }
   90 #endif
   91 }
   92 
   93 void  tcpdemux::write_flow_record(const std::string &starttime,const std::string &endtime,
   94                         const std::string &src_ipn,const std::string &dst_ipn,
   95                         const std::string &mac_daddr,const std::string &mac_saddr,
   96                         uint64_t packets,uint16_t srcport,uint16_t dstport,
   97                         const std::string &hashdigest_md5)
   98 {
   99 }
  100 
  101 
  102 
  103 /* static */ tcpdemux *tcpdemux::getInstance()
  104 {
  105     static tcpdemux * theInstance = 0;
  106     if(theInstance==0) theInstance = new tcpdemux();
  107     return theInstance;
  108 }
  109 
  110 /**
  111  * find the flow that has been written to in the furthest past and close it.
  112  */
  113 void tcpdemux::close_oldest_fd()
  114 {
  115     tcpip *oldest_tcp = *open_flows.begin();
  116     if(oldest_tcp) oldest_tcp->close_file();
  117 }
  118 
  119 /* Open a file, closing one of the existing flows f necessary.
  120  */
  121 int tcpdemux::retrying_open(const std::string &filename,int oflag,int mask)
  122 {
  123     while(true){
  124     //Packet index file reduces max_fds by 1/2 as the index files also take a fd
  125     if(open_flows.size() >= (opt.output_packet_index ?  max_fds/2 : max_fds)) close_oldest_fd();
  126     int fd = ::open(filename.c_str(),oflag,mask);
  127     DEBUG(2)("retrying_open ::open(fn=%s,oflag=x%x,mask:x%x)=%d",filename.c_str(),oflag,mask,fd);
  128     if(fd>=0){
  129             /* Open was successful */
  130             return fd;
  131         }
  132     DEBUG(2)("retrying_open ::open failed with errno=%d",errno);
  133     if (errno != ENFILE && errno != EMFILE){
  134         DEBUG(2)("retrying_open ::open failed with errno=%d (%s)",errno,strerror(errno));
  135         return -1;      // wonder what it was
  136     }
  137     DEBUG(5) ("too many open files -- contracting FD ring (size=%d)", (int)open_flows.size());
  138     close_oldest_fd();
  139     }
  140 }
  141 
  142 /* Find previously a previously created flow state in the database.
  143  */
  144 tcpip *tcpdemux::find_tcpip(const flow_addr &flow)
  145 {
  146     flow_map_t::const_iterator it = flow_map.find(flow);
  147     if (it==flow_map.end()){
  148     return NULL; // flow not found
  149     }
  150     return it->second;
  151 }
  152 
  153 /* Create a new flow state structure for a given flow.
  154  * Puts the flow in the map.
  155  * Returns a pointer to the new state.
  156  *
  157  * This is called by tcpdemux::process_tcp(). (Only place it is called)
  158  *
  159  * @param - pi - first packet seen on this connection.
  160  *
  161  * NOTE: We keep pointers to tcp structures in the map, rather than
  162  * the structures themselves. This makes the map slightly more efficient,
  163  * since it doesn't need to shuffle entire structures.
  164  *
  165  *
  166  * TK: Note that the flow() is created on the stack and then used in new tcpip().
  167  * This is resulting in an unnecessary copy.
  168  */
  169 
  170 tcpip *tcpdemux::create_tcpip(const flow_addr &flowa, be13::tcp_seq isn,const be13::packet_info &pi)
  171 {
  172     /* create space for the new state */
  173     flow flow(flowa,flow_counter++,pi);
  174 
  175     tcpip *new_tcpip = new tcpip(*this,flow,isn);
  176     new_tcpip->nsn   = isn+1;       // expected sequence number of the first byte
  177     DEBUG(5) ("new flow %s. path: %s next seq num (nsn):%d",
  178               flowa.str().c_str(),new_tcpip->flow_pathname.c_str(),new_tcpip->nsn);
  179     flow_map[flow] = new_tcpip;
  180     open_flows.reset(new_tcpip);
  181     return new_tcpip;
  182 }
  183 
  184 /**
  185  * Remove a flow from the database.
  186  * Close the flow file.
  187  * Write to the report.xml object.
  188  * Save in the sqlite database.
  189  * This is the ONLY place where a tcpip object is deleted so there is no chance of finding it again.
  190  *
  191  * Flows are post-processed when a FIN is received and all bytes are received.
  192  * If a FIN is received and bytes are outstanding, they are post-processed when the last byte is received.
  193  * When the program shut down, all open flows are post-processed.
  194  *
  195  * Amended to trigger the packet/data location index sort as part of the post-processing.  This sorts
  196  * the (potentially out of order) index to make it simple for external applications.  No processing is
  197  * done if the (-I) index generation feature is turned off.  --GDD
  198  */
  199 
  200 void tcpdemux::post_process(tcpip *tcp)
  201 {
  202     std::stringstream xmladd;       // for this <fileobject>
  203     if(opt.post_processing && tcp->file_created && tcp->last_byte>0){
  204         /**
  205          * After the flow is finished, if more than a byte was
  206          * written, then put it in an SBUF and process it.  if we are
  207          * doing post-processing.  This is called from tcpip::~tcpip()
  208          * in tcpip.cpp.
  209          */
  210 
  211         /* Open the fd if it is not already open */
  212         tcp->open_file();
  213         if(tcp->fd>=0){
  214             sbuf_t *sbuf = sbuf_t::map_file(tcp->flow_pathname,tcp->fd);
  215             if(sbuf){
  216                 be13::plugin::process_sbuf(scanner_params(scanner_params::PHASE_SCAN,*sbuf,*(fs),&xmladd));
  217                 delete sbuf;
  218                 sbuf = 0;
  219             }
  220         }
  221     }
  222     tcp->close_file();
  223     if(xreport) tcp->dump_xml(xreport,xmladd.str());
  224     /**
  225      * Before we delete the tcp structure, save information about the saved flow
  226      */
  227     save_flow(tcp);
  228 
  229     if(opt.store_output && tcp_alert_fd>=0){
  230     std::stringstream ss;
  231     ss << "close\t" << tcp->flow_pathname.c_str() << "\n";
  232     const std::string &sso = ss.str();
  233     if(write(tcp_alert_fd,sso.c_str(),sso.size()) != (int)sso.size()){
  234         perror("write");
  235     }
  236     }
  237 
  238     if(tcp_cmd.size()>0 && tcp->flow_pathname.size()>0){
  239     /* If we are at maximum number of subprocesses, wait for one to exit */
  240     std::string cmd = tcp_cmd + " " + tcp->flow_pathname;
  241 #ifdef HAVE_FORK
  242     int status=0;
  243     pid_t pid = 0;
  244     while(tcp_subproc >= tcp_subproc_max){
  245         pid = wait(&status);
  246         tcp_subproc--;
  247     }
  248     /* Fork off a child */
  249     pid = fork();
  250     if(pid<0) die("Cannot fork child");
  251     if(pid==0){
  252         /* We are the child */
  253         exit(system(cmd.c_str()));
  254     }
  255     tcp_subproc++;
  256 #else
  257     system(cmd.c_str());
  258 #endif
  259     }
  260 
  261     delete tcp;
  262 }
  263 
  264 void tcpdemux::remove_flow(const flow_addr &flow)
  265 {
  266     flow_map_t::iterator it = flow_map.find(flow);
  267     if(it!=flow_map.end()){
  268         post_process(it->second);
  269     flow_map.erase(it);
  270     }
  271 }
  272 
  273 void tcpdemux::remove_all_flows()
  274 {
  275 
  276     DEBUG(10) ("Cleaning up flows");
  277     for(flow_map_t::iterator it=flow_map.begin();it!=flow_map.end();it++){
  278         post_process(it->second);
  279     }
  280     flow_map.clear();
  281 
  282     for(sparse_saved_flow_map_t::iterator it=flow_fd_cache_map.begin();it!=flow_fd_cache_map.end();it++){
  283         delete it->second;
  284     }
  285     flow_fd_cache_map.clear();
  286 }
  287 
  288 /****************************************************************
  289  *** tcpdemultiplexer
  290  ****************************************************************/
  291 
  292 /* Try to find the maximum number of FDs this system can have open */
  293 unsigned int tcpdemux::get_max_fds(void)
  294 {
  295     int max_descs = 0;
  296     const char *method=0;
  297 
  298     /* No longer users OPEN_MAX */
  299 #if defined (HAVE_GETDTABLESIZE)
  300     method = "getdtablesize";
  301     max_descs = getdtablesize();
  302 #elif defined(RLIMIT_NOFILE)
  303     {
  304     struct rlimit limit;
  305     memset(&limit,0,sizeof(limit));
  306 
  307     method = "rlimit";
  308     if (getrlimit(RLIMIT_NOFILE, &limit) < 0) {
  309         perror("getrlimit");
  310         exit(1);
  311     }
  312 
  313     /* set the current to the maximum or specified value */
  314     limit.rlim_cur = limit.rlim_max;
  315 #ifdef OPEN_MAX
  316         if(limit.rlim_cur > OPEN_MAX) limit.rlim_cur = OPEN_MAX;
  317 #endif
  318 
  319     if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {
  320         perror("setrlimit");
  321         exit(1);
  322     }
  323     max_descs = limit.rlim_max;
  324 
  325 #ifdef RLIM_INFINITY
  326     if (limit.rlim_max == RLIM_INFINITY) max_descs = MAX_FD_GUESS * 4;  /* pick a more reasonable max */
  327 #endif
  328     }
  329 #elif defined (_SC_OPEN_MAX)
  330     /* Okay, you don't have getrlimit() and you don't have OPEN_MAX.
  331      * Time to try the POSIX sysconf() function.  (See Stevens'
  332      * _Advanced Programming in the UNIX Environment_).  */
  333     method = "POSIX sysconf";
  334     errno = 0;
  335     if ((max_descs = sysconf(_SC_OPEN_MAX)) < 0) {
  336     if (errno == 0)
  337         max_descs = MAX_FD_GUESS * 4;
  338     else {
  339         perror("calling sysconf");
  340         exit(1);
  341     }
  342     }
  343 
  344     /* if everything has failed, we'll just take a guess */
  345 #else
  346     method = "MAX_FD_GUESS";
  347     max_descs = MAX_FD_GUESS;
  348 #endif
  349     /* this must go here, after rlimit code */
  350     DEBUG(10) ("found max FDs to be %d using %s", max_descs, method);
  351     return max_descs;
  352 }
  353 
  354 
  355 /*
  356  * open the packet save flow
  357  */
  358 void tcpdemux::save_unk_packets(const std::string &ofname,const std::string &ifname)
  359 {
  360     pwriter = pcap_writer::open_copy(ofname,ifname);
  361 }
  362 
  363 /**
  364  * save information on this flow needed to handle strangling packets
  365  */
  366 int c = 0;
  367 void tcpdemux::save_flow(tcpip *tcp)
  368 {
  369     /* First remove the oldest flow if we are in overload */
  370     if(saved_flows.size()>0 && saved_flows.size()>max_saved_flows){
  371         saved_flow *flow0 = saved_flows.at(0);
  372         saved_flow_map.erase(flow0->addr);    // remove from the map
  373         saved_flows.erase(saved_flows.begin()); // remove from the vector
  374         delete flow0;                           // and delete the saved flow
  375     }
  376 
  377     /* Now save the flow */
  378     saved_flow *sf = new saved_flow(tcp);
  379     saved_flow_map[sf->addr] = sf;
  380     saved_flows.push_back(sf);
  381 }
  382 
  383 /**
  384  * dissect_tcp():
  385  *
  386  * Called to process tcp pkts in a way that dissected or isolated pcap flows are
  387  * emerging afterwards. Similar notions go into the direction of "sorting" pcap pkts
  388  * as per flow context.
  389  *
  390  * Returns 0 if packet is processed, 1 if it is not processed, -1 if error
  391  */
  392 
  393 int tcpdemux::dissect_tcp(const ipaddr &src, const ipaddr &dst,sa_family_t family,
  394                           const u_char *ip_data, uint32_t ip_payload_len,
  395                           const be13::packet_info &pi)
  396 {
  397     DEBUG(6) ("dissecting pkt *********************");
  398     struct be13::tcphdr *tcp_header = (struct be13::tcphdr *) ip_data;
  399     flow_addr this_flow(src,dst,ntohs(tcp_header->th_sport),
  400                         ntohs(tcp_header->th_dport),family);
  401 
  402     sparse_saved_flow_map_t::const_iterator it = flow_fd_cache_map.find(this_flow);
  403     if(it!=flow_fd_cache_map.end()){
  404         flow_sorter->update_sink(it->second->fcap);
  405     }
  406     else {
  407         flow fn_gen_vehicle(this_flow, 0, pi); // impromptu flow name generator
  408         std::string fn = fn_gen_vehicle.new_pcap_filename();
  409         flow_sorter->refresh_sink(fn, pi.pcap_dlt);
  410         FILE *sink= flow_sorter->yield_sink();
  411         sparse_saved_flow *ssf = new sparse_saved_flow(this_flow, sink);
  412         flow_fd_cache_map[ssf->addr] = ssf;
  413     }
  414 
  415     flow_sorter->writepkt(pi.pcap_hdr,pi.pcap_data);
  416 
  417     return 0;
  418 }
  419 
  420 /**
  421  * process_tcp():
  422  *
  423  * Called to processes a tcp packet from either process_ip4() or process_ip6().
  424  * The caller breaks out the ip addresses and finds the start of the tcp header.
  425  *
  426  * Skips but otherwise ignores TCP options.
  427  *
  428  * creates a new tcp connection if necessary, then asks the connection to either
  429  * print the packet or store it.
  430  *
  431  * Returns 0 if packet is processed, 1 if it is not processed, -1 if error
  432  */
  433 
  434 #define FLAG_SET(vector, flag) ((vector) & (flag))
  435 
  436 #pragma GCC diagnostic ignored "-Wcast-align"
  437 #include "iptree.h"
  438 
  439 
  440 
  441 int tcpdemux::process_tcp(const ipaddr &src, const ipaddr &dst,sa_family_t family,
  442                           const u_char *ip_data, uint32_t ip_payload_len,
  443                           const be13::packet_info &pi)
  444 {
  445     if (ip_payload_len < sizeof(struct be13::tcphdr)) {
  446     DEBUG(6) ("received truncated TCP segment! (%u<%u)",
  447                   (u_int)ip_payload_len,(u_int)sizeof(struct be13::tcphdr));
  448     return 1;
  449     }
  450 
  451     struct be13::tcphdr *tcp_header = (struct be13::tcphdr *) ip_data;
  452 
  453     /* fill in the flow_addr structure with info that identifies this flow */
  454     flow_addr this_flow(src,dst,ntohs(tcp_header->th_sport),ntohs(tcp_header->th_dport),family);
  455 
  456     be13::tcp_seq seq  = ntohl(tcp_header->th_seq);
  457     bool syn_set = FLAG_SET(tcp_header->th_flags, TH_SYN);
  458     bool ack_set = FLAG_SET(tcp_header->th_flags, TH_ACK);
  459     bool fin_set = FLAG_SET(tcp_header->th_flags, TH_FIN);
  460     bool rst_set = FLAG_SET(tcp_header->th_flags, TH_RST);
  461 
  462     /* calculate the total length of the TCP header including options */
  463     u_int tcp_header_len = tcp_header->th_off * 4;
  464 
  465     /* Find the beginning of the tcp data.
  466      */
  467     const u_char *tcp_data   = ip_data + tcp_header_len;
  468 
  469     /* figure out how much tcp data we have, taking into account tcp options */
  470 
  471     size_t tcp_datalen = (ip_payload_len > tcp_header_len) ? (ip_payload_len - tcp_header_len) : 0;
  472 
  473     /* see if we have state about this flow; if not, create it */
  474     int32_t  delta = 0;         // from current position in tcp connection; must be SIGNED 32 bit!
  475     tcpip   *tcp = find_tcpip(this_flow);
  476 
  477     DEBUG(60)("%s%s%s%s tcp_header_len=%d tcp_datalen=%d seq=%u tcp=%p",
  478               (syn_set?"SYN ":""),(ack_set?"ACK ":""),(fin_set?"FIN ":""),(rst_set?"RST ":""),(int)tcp_header_len,(int)tcp_datalen,(int)seq,tcp);
  479 
  480     /* If this_flow is not in the database and the start_new_connections flag is false, just return */
  481     if(tcp==0 && start_new_connections==false) return 0;
  482 
  483     if(syn_set && tcp && tcp->syn_count>0 && tcp->pos>0){
  484         std::cerr << "SYN TO IGNORE! SYN tcp="<<tcp << " flow="<<this_flow<<"\n";
  485         return 1;
  486     }
  487 
  488     if(tcp==0){
  489         if(tcp_datalen==0){                       // zero length packet
  490             if(fin_set) return 0;              // FIN on a connection that's unknown; safe to ignore
  491             if(rst_set) return 0;              // RST on a connection that's unknown; safe to ignore
  492             if(syn_set==false && ack_set==false) return 0; // neither a SYN nor ACK; return
  493         } else {
  494             /* Data present on a flow that is not actively being demultiplexed.
  495              * See if it is a saved flow. If so, see if the data in the packet
  496              * matches what is on the disk. If so, return.
  497              *
  498              */
  499             saved_flow_map_t::const_iterator it = saved_flow_map.find(this_flow);
  500             if(it!=saved_flow_map.end()){
  501                 uint32_t offset = seq - it->second->isn - 1;
  502                 bool data_match = false;
  503                 int fd = open(it->second->saved_filename.c_str(),O_RDONLY | O_BINARY);
  504                 if(fd>0){
  505                     char *buf = (char *)malloc(tcp_datalen);
  506                     if(buf){
  507                         DEBUG(100)("lseek(fd,%" PRId64 ",SEEK_SET)",(int64_t)(offset));
  508                         lseek(fd,offset,SEEK_SET);
  509                         ssize_t r = read(fd,buf,tcp_datalen);
  510                         data_match = (r==(ssize_t)tcp_datalen) && memcmp(buf,tcp_data,tcp_datalen)==0;
  511                         free(buf);
  512                     }
  513                     close(fd);
  514                 }
  515                 DEBUG(60)("Packet matches saved flow. offset=%u len=%d filename=%s data match=%d\n",
  516                           (u_int)offset,(u_int)tcp_datalen,it->second->saved_filename.c_str(),(u_int)data_match);
  517                 if(data_match) return 0;
  518             }
  519         }
  520     }
  521 
  522     /* flow is in the database; make sure the gap isn't too big.*/
  523     if(tcp){
  524     /* Compute delta based on next expected sequence number.
  525      * If delta will be too much, start a new flow.
  526          *
  527          * NOTE: I hope we don't get a packet from the old flow when
  528          * we are processing the new one. Perhaps we should be able to have
  529          * multiple flows at the same time with the same quad, and they are
  530          * at different window areas...
  531          *
  532      */
  533     delta = seq - tcp->nsn;     // notice that signed offset is calculated
  534 
  535     if(abs(delta) > opt.max_seek){
  536         remove_flow(this_flow);
  537         delta = 0;
  538         tcp = 0;
  539     }
  540     }
  541 
  542     /* At this point, tcp may be NULL because:
  543      * case 1 - It's a new connection and SYN IS SET; normal case
  544      * case 2 - Extra packets on a now-closed connection
  545      * case 3 - Packets for which the initial part of the connection was missed
  546      * case 4 - It's a connecton that had a huge gap and was expired out of the databsae
  547      *
  548      * THIS IS THE ONLY PLACE THAT create_tcpip() is called.
  549      */
  550 
  551     /* q: what if syn is set AND there is data? */
  552     /* q: what if syn is set AND we already know about this connection? */
  553 
  554     if (tcp==NULL){
  555 
  556         /* Don't process if this is not a SYN and there is no data. */
  557         if(syn_set==false && tcp_datalen==0) return 0;
  558 
  559     /* Check if this is the server->client flow related to a client->server flow that is being demultiplexed */
  560     flow_addr reverse_flow(dst,src,ntohs(tcp_header->th_dport),ntohs(tcp_header->th_sport),family);
  561     tcpip   *reverse_tcp = find_tcpip(reverse_flow);
  562     uint64_t uid;
  563     if (reverse_tcp)
  564     {
  565         /* We found a matching client->server flow. Copy its session ID */
  566         uid = reverse_tcp->myflow.session_id;
  567     }
  568     else
  569     {
  570         /* Assign a new unique ID */
  571         uid = unique_id++;
  572     }
  573 
  574     /* Create a new connection.
  575      * delta will be 0, because it's a new connection!
  576      */
  577         be13::tcp_seq isn = syn_set ? seq : seq-1;
  578     tcp = create_tcpip(this_flow, isn, pi);
  579     tcp->myflow.session_id = uid;
  580     }
  581 
  582     /* Now tcp is valid */
  583     tcp->myflow.tlast = pi.ts;      // most recently seen packet
  584     tcp->last_packet_number = packet_counter++;
  585     tcp->myflow.len += pi.pcap_hdr->len;
  586     tcp->myflow.caplen += pi.pcap_hdr->caplen;
  587     tcp->myflow.packet_count++;
  588 
  589     // Does not seem consitent => Print a notice
  590     // See also https://stackoverflow.com/q/1491660
  591     if(pi.pcap_hdr->caplen != pi.pcap_hdr->len){
  592         DEBUG(2)("Captured packet has a length caplen=%d different "
  593                  "from the un-truncated length len=%d provided by PCAP API",
  594                  pi.pcap_hdr->caplen, pi.pcap_hdr->len);
  595     }
  596 
  597     /*
  598      * 2012-10-24 slg - the first byte is sent at SEQ==ISN+1.
  599      * The first byte in POSIX files have an LSEEK of 0.
  600      * The original code overcame this issue by introducing an intentional off-by-one
  601      * error with the statement tcp->isn++.
  602      *
  603      * With the new TCP state-machine we simply follow the spec.
  604      *
  605      * The new state machine works by examining the SYN and ACK packets
  606      * in accordance with the TCP spec.
  607      */
  608     if(syn_set){
  609         /* If the syn is set this is either a SYN or SYN-ACK. We use this information to set the direction
  610          * flag, but that's it. The direction flag is only used for coloring.
  611          */
  612     if(tcp->syn_count>1){
  613         DEBUG(2)("Multiple SYNs (%d) seen on connection %s",tcp->syn_count,tcp->flow_pathname.c_str());
  614     }
  615     tcp->syn_count++;
  616     if( !ack_set ){
  617         DEBUG(50) ("packet is handshake SYN"); /* First packet of three-way handshake */
  618         tcp->dir = tcpip::dir_cs;   // client->server
  619     } else {
  620         DEBUG(50) ("packet is handshake SYN/ACK"); /* second packet of three-way handshake  */
  621         tcp->dir = tcpip::dir_sc;   // server->client
  622     }
  623     if(tcp_datalen>0){
  624         tcp->violations++;
  625         DEBUG(1) ("TCP PROTOCOL VIOLATION: SYN with data! (length=%d)",(int)tcp_datalen);
  626     }
  627     }
  628     if(tcp_datalen==0) DEBUG(50) ("got TCP segment with no data"); // seems pointless to notify
  629 
  630     /* process any data.
  631      * Notice that this typically won't be called for the SYN or SYN/ACK,
  632      * since they both have no data by definition.
  633      */
  634     if (tcp_datalen>0){
  635     if (opt.console_output) {
  636         tcp->print_packet(tcp_data, tcp_datalen);
  637     } else {
  638         if (opt.store_output){
  639         bool new_file = false;
  640         if (tcp->fd < 0) new_file = true;
  641 
  642         tcp->store_packet(tcp_data, tcp_datalen, delta,pi.ts);
  643 
  644         if(new_file && tcp_alert_fd>=0){
  645             std::stringstream ss;
  646             ss << "open\t" << tcp->flow_pathname.c_str() << "\n";
  647             const std::string &sso = ss.str();
  648             if(write(tcp_alert_fd,sso.c_str(),sso.size())!=(int)sso.size()){
  649             perror("write");
  650             }
  651         }
  652         }
  653     }
  654     }
  655 
  656     if (rst_set){
  657         remove_flow(this_flow); // take it out of the map
  658         return 0;
  659     }
  660 
  661     /* Count the FINs.
  662      * If this is a fin, determine the size of the stream
  663      */
  664     if (fin_set){
  665         tcp->fin_count++;
  666         if(tcp->fin_count==1){
  667             tcp->fin_size = (seq+tcp_datalen-tcp->isn)-1;
  668         }
  669     } else {
  670         open_flows.move_to_end(tcp);
  671     }
  672 
  673     /* If a fin was sent and we've seen all of the bytes, close the stream */
  674     DEBUG(50)("%d>0 && %d == %d",tcp->fin_count,tcp->seen_bytes(),tcp->fin_size);
  675 
  676     if (tcp->fin_count>0 && tcp->seen_bytes() == tcp->fin_size){
  677         DEBUG(50)("all bytes have been received; removing flow");
  678         remove_flow(this_flow); // take it out of the map
  679     }
  680 
  681     DEBUG(50)("fin_set=%d  seq=%u fin_count=%d  seq_count=%d len=%d isn=%u",
  682               fin_set,seq,tcp->fin_count,tcp->syn_count,(int)tcp_datalen,tcp->isn);
  683     return 0;                           // successfully processed
  684 }
  685 #pragma GCC diagnostic warning "-Wcast-align"
  686 
  687 
  688 /* This is called when we receive an IPv4 datagram.  We make sure that
  689  * it's valid and contains a TCP segment; if so, we pass it to
  690  * process_tcp() for further processing.
  691  *
  692  * Note: we currently don't know how to handle IP fragments. */
  693 #pragma GCC diagnostic ignored "-Wcast-align"
  694 
  695 
  696 
  697 int tcpdemux::process_ip4(const be13::packet_info &pi)
  698 {
  699     /* make sure that the packet is at least as long as the min IP header */
  700     if (pi.ip_datalen < sizeof(struct be13::ip4)) {
  701     DEBUG(6) ("received truncated IP datagram!");
  702     return -1;                      // couldn't process
  703     }
  704 
  705     const struct be13::ip4 *ip_header = (struct be13::ip4 *) pi.ip_data;
  706 
  707     DEBUG(100)("process_ip4. caplen=%d vlan=%d  ip_p=%d",(int)pi.pcap_hdr->caplen,(int)pi.vlan(),(int)ip_header->ip_p);
  708     if(debug>200){
  709     sbuf_t sbuf(pos0_t(),(const uint8_t *)pi.ip_data,pi.ip_datalen,pi.ip_datalen,0,false, false,false);
  710     sbuf.hex_dump(std::cerr);
  711     }
  712 
  713     /* for now we're only looking for TCP; throw away everything else */
  714     if (ip_header->ip_p != IPPROTO_TCP) {
  715     DEBUG(50) ("got non-TCP frame -- IP proto %d", ip_header->ip_p);
  716     return -1;                      // couldn't process
  717     }
  718 
  719     /* check and see if we got everything.  NOTE: we must use
  720      * ip_total_len after this, because we may have captured bytes
  721      * beyond the end of the packet (e.g. ethernet padding).
  722      */
  723     size_t ip_len = ntohs(ip_header->ip_len);
  724     if (pi.ip_datalen < ip_len) {
  725     DEBUG(6) ("warning: captured only %ld bytes of %ld-byte IP datagram",
  726           (long) pi.ip_datalen, (long) ip_len);
  727     }
  728 
  729     /* XXX - throw away everything but fragment 0; this version doesn't
  730      * know how to do fragment reassembly.
  731      */
  732     if (ntohs(ip_header->ip_off) & 0x1fff) {
  733     DEBUG(2) ("warning: throwing away IP fragment from X to X");
  734     return -1;
  735     }
  736 
  737     /* figure out where the IP header ends */
  738     size_t ip_header_len = ip_header->ip_hl * 4;
  739 
  740     /* make sure there's some data */
  741     if (ip_header_len > ip_len) {
  742     DEBUG(6) ("received truncated IP datagram!");
  743     return -1;
  744     }
  745 
  746     /* do TCP processing, faking an ipv6 address  */
  747     uint16_t ip_payload_len = pi.ip_datalen - ip_header_len;
  748     ipaddr src(ip_header->ip_src.addr);
  749     ipaddr dst(ip_header->ip_dst.addr);
  750     return (this->*tcp_processor)(src, dst ,AF_INET,
  751                                   pi.ip_data + ip_header_len,
  752                                   ip_payload_len,pi);
  753 }
  754 #pragma GCC diagnostic warning "-Wcast-align"
  755 
  756 
  757 /* This is called when we receive an IPv6 datagram.
  758  *
  759  * Note: we don't support IPv6 extended headers
  760  */
  761 
  762 /* These might be defined from an include file, so undef them to be sure */
  763 
  764 int tcpdemux::process_ip6(const be13::packet_info &pi)
  765 {
  766     /* make sure that the packet is at least as long as the IPv6 header */
  767     if (pi.ip_datalen < sizeof(struct be13::ip6_hdr)) {
  768     DEBUG(6) ("received truncated IPv6 datagram!");
  769     return -1;
  770     }
  771 
  772     const struct be13::ip6_hdr *ip_header = (struct be13::ip6_hdr *) pi.ip_data;
  773 
  774     /* for now we're only looking for TCP; throw away everything else */
  775     if (ip_header->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) {
  776     DEBUG(50) ("got non-TCP frame -- IP proto %d", ip_header->ip6_ctlun.ip6_un1.ip6_un1_nxt);
  777     return -1;
  778     }
  779 
  780     /* do TCP processing */
  781     uint16_t ip_payload_len = ntohs(ip_header->ip6_ctlun.ip6_un1.ip6_un1_plen);
  782     ipaddr src(ip_header->ip6_src.addr.addr8);
  783     ipaddr dst(ip_header->ip6_dst.addr.addr8);
  784 
  785     return (this->*tcp_processor)(src, dst ,AF_INET6,
  786                                    pi.ip_data + sizeof(struct be13::ip6_hdr),
  787                                    ip_payload_len,pi);
  788 }
  789 
  790 /* This is called when we receive an IPv4 or IPv6 datagram.
  791  * This function calls process_ip4 or process_ip6
  792  * Returns 0 if packet is processed, 1 if it is not processed, -1 if error.
  793  */
  794 
  795 #pragma GCC diagnostic ignored "-Wcast-align"
  796 int tcpdemux::process_pkt(const be13::packet_info &pi)
  797 {
  798     DEBUG(10)("process_pkt..............................................................................");
  799     int r = 1;                          // not processed yet
  800     switch(pi.ip_version()){
  801     case 4:
  802         r = process_ip4(pi);
  803         break;
  804     case 6:
  805         r = process_ip6(pi);
  806         break;
  807     }
  808     if(r!=0){                           // packet not processed?
  809         /* Write the packet if we didn't process it */
  810         if(pwriter) pwriter->writepkt(pi.pcap_hdr,pi.pcap_data);
  811     }
  812 
  813     /* Process the timeout, if there is any */
  814     if(tcp_timeout){
  815         /* Get a list of the flows that need to be closed.  */
  816         std::vector<flow_addr *> to_close;
  817         for(flow_map_t::iterator it = flow_map.begin(); it!=flow_map.end(); it++){
  818             tcpip &tcp = *(it->second);
  819             uint32_t age = pi.ts.tv_sec - tcp.myflow.tlast.tv_sec;
  820             if (age > tcp_timeout){
  821                 to_close.push_back(&tcp.myflow);
  822             }
  823         }
  824         /* Close them. This removes the flows from the flow_map(), which is why we need
  825          * to create the list first.
  826          */
  827         for(std::vector<flow_addr *>::iterator it = to_close.begin(); it!=to_close.end(); it++){
  828             remove_flow(*(*it));
  829         }
  830     }
  831     return r;
  832 }
  833 #pragma GCC diagnostic warning "-Wcast-align"