"Fossies" - the Fresh Open Source Software Archive

Member "tcpflow-1.6.1/src/tcpip.h" (19 Feb 2021, 14167 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.h" 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 #ifndef TCPIP_H
    2 #define TCPIP_H
    3 
    4 #include <fstream>
    5 
    6 #include "inet_ntop.h"
    7 
    8 /** On windows, there is no in_addr_t; this is from
    9  * /usr/include/netinet/in.h
   10  */
   11 #ifndef HAVE_NETINET_IN_H
   12 typedef uint32_t in_addr_t;
   13 #endif
   14 
   15 #ifndef HAVE_SA_FAMILY_T
   16 typedef unsigned short int sa_family_t;
   17 #endif
   18 
   19 
   20 /**
   21  * ipaddress class.
   22  * represents IPv4 and IPv6 addresses.
   23  * IPv4 addresses have address in bytes 0..3 and all NULL for bytes 4..11
   24  */
   25 class ipaddr {
   26 public:;
   27     ipaddr(){
   28     memset(addr,0,sizeof(addr));
   29     }
   30     ipaddr(const in_addr_t &a){     // copy operator
   31     addr[0] = ((uint8_t *)&a)[0];   // copy the bottom 4 octets and blank the top 12
   32     addr[1] = ((uint8_t *)&a)[1];
   33     addr[2] = ((uint8_t *)&a)[2];
   34     addr[3] = ((uint8_t *)&a)[3];
   35     memset(addr+4,0,12);
   36     }
   37     ipaddr(const uint8_t a[16]){    // begin wiped
   38     memcpy(addr,a,16);
   39     }
   40 
   41     uint8_t addr[16];           // holds v4 or v16
   42     bool bit(int i) const {             // get the ith bit; 0 is MSB
   43         return (addr[i / 8]) & (1<<(7-i%8));
   44     }
   45     uint32_t quad(int i) const {        // gets the ith quad as a 32-bit value
   46         return (addr[i*4+0]<<24) | (addr[i*4+2]<<16) | (addr[i*4+1]<<8) |  (addr[i*4+3]<<0);
   47     }
   48     uint64_t dquad(int i) const {       // gets the first 64-bit half or the second 64-bit half
   49         return (uint64_t)(quad(i*2+1))<<32 | (uint64_t)(quad(i*2));
   50     }
   51         
   52     inline bool operator ==(const ipaddr &b) const { return memcmp(this->addr,b.addr,sizeof(addr))==0; };
   53     inline bool operator <=(const ipaddr &b) const { return memcmp(this->addr,b.addr,sizeof(addr))<=0; };
   54     inline bool operator > (const ipaddr &b) const { return memcmp(this->addr,b.addr,sizeof(addr))>0; };
   55     inline bool operator >=(const ipaddr &b) const { return memcmp(this->addr,b.addr,sizeof(addr))>=0; };
   56     inline bool operator < (const ipaddr &b) const { return memcmp(this->addr,b.addr,sizeof(this->addr))<0; }
   57 };
   58 
   59 class ipaddr_prn {
   60 public:
   61     const ipaddr& ia;
   62     const sa_family_t family;
   63     ipaddr_prn(const ipaddr& ia_, sa_family_t family_)
   64         : ia(ia_), family(family_)
   65     { }
   66 };
   67 
   68 inline std::ostream & operator <<(std::ostream &os, const ipaddr_prn &b) {
   69     char buf[INET6_ADDRSTRLEN];
   70     inet_ntop(b.family, b.ia.addr, buf, sizeof(buf));
   71     os << buf;
   72     return os;
   73 }
   74 
   75 inline bool operator ==(const struct timeval &a,const struct timeval &b) {
   76     return a.tv_sec==b.tv_sec && a.tv_usec==b.tv_usec;
   77 }
   78 
   79 inline bool operator <(const struct timeval &a,const struct timeval &b) {
   80     return (a.tv_sec<b.tv_sec) || ((a.tv_sec==b.tv_sec) && (a.tv_sec<b.tv_sec));
   81 }
   82 
   83 /*
   84  * describes the TCP flow.
   85  * No timing information; this is used as a map index.
   86  */
   87 class flow_addr {
   88 public:
   89     flow_addr():src(),dst(),sport(0),dport(0),family(0){ }
   90     flow_addr(const ipaddr &s,const ipaddr &d,uint16_t sp,uint16_t dp,sa_family_t f):
   91     src(s),dst(d),sport(sp),dport(dp),family(f){
   92     }
   93     flow_addr(const flow_addr &f):src(f.src),dst(f.dst),sport(f.sport),dport(f.dport),
   94                   family(f.family){
   95     }
   96     virtual ~flow_addr(){};
   97     ipaddr  src;        // Source IP address; holds v4 or v6 
   98     ipaddr  dst;        // Destination IP address; holds v4 or v6 
   99     uint16_t    sport;      // Source port number 
  100     uint16_t    dport;      // Destination port number 
  101     sa_family_t family;     // AF_INET or AF_INET6 */
  102 
  103     uint64_t hash() const {
  104     if(family==AF_INET){
  105         return ((uint64_t)(src.quad(0))<<32 | dst.quad(0))
  106                 ^ ((uint64_t)(dst.quad(0))<<32 | src.quad(0))
  107                 ^ (sport<<16 | dport);
  108     } else {
  109         return (src.dquad(0)<<32 ^ dst.dquad(0))
  110                 ^ (dst.dquad(0)<<32  ^ src.dquad(0))
  111                 ^ (src.dquad(1)      ^ dst.dquad(1))
  112                 ^ (sport<<16 | dport);
  113     }
  114     }
  115 
  116     inline bool operator ==(const flow_addr &b) const {
  117     return this->src==b.src &&
  118         this->dst==b.dst &&
  119         this->sport==b.sport &&
  120         this->dport==b.dport &&
  121         this->family==b.family;
  122     }
  123 
  124     inline bool operator <(const flow_addr &b) const {
  125     if (this->src < b.src) return true;
  126     if (this->src > b.src) return false;
  127     if (this->dst < b.dst) return true;
  128     if (this->dst > b.dst) return false;
  129     if (this->sport < b.sport) return true;
  130     if (this->sport > b.sport) return false;
  131     if (this->dport < b.dport) return true;
  132     if (this->dport > b.dport) return false;
  133     if (this->family < b.family) return true;
  134     if (this->family > b.family) return false;
  135     return false;    /* they are equal! */
  136     }
  137 
  138     std::string str() const {
  139         std::stringstream s;
  140         s << "flow[" << ipaddr_prn(src, family) << ":" << sport << "->" << ipaddr_prn(dst, family) << ":" << dport << "]";
  141         return s.str();
  142     }
  143 };
  144 
  145 inline std::ostream & operator <<(std::ostream &os,const flow_addr &f)  {
  146     os << f.str();
  147     return os;
  148 }
  149 
  150 
  151 /*
  152  * A flow is a flow_addr that has additional information regarding when it was seen
  153  * and how many packets were seen. The address is used to locate the flow in the array.
  154  * Notice that it contains no pointers, so it can be copied with the default operator.
  155  */
  156 class flow : public flow_addr {
  157 public:;
  158     static void usage();            // print information on flow notation
  159     static std::string filename_template;   // 
  160     static std::string outdir;                  // where the output gets written
  161     flow():id(),vlan(),mac_daddr(),mac_saddr(),tstart(),tlast(),len(),caplen(),packet_count(),session_id(){};
  162     flow(const flow_addr &flow_addr_,uint64_t id_,const be13::packet_info &pi):
  163     flow_addr(flow_addr_),id(id_),vlan(pi.vlan()),
  164         mac_daddr(),
  165         mac_saddr(),
  166         tstart(pi.ts),tlast(pi.ts),
  167         len(0),
  168         caplen(0),
  169     packet_count(0),
  170         session_id(0) {
  171         if(pi.pcap_hdr){
  172             memcpy(mac_daddr,pi.get_ether_dhost(),sizeof(mac_daddr));
  173             memcpy(mac_saddr,pi.get_ether_shost(),sizeof(mac_saddr));
  174         }
  175     }
  176     virtual ~flow(){};
  177     uint64_t  id;           // flow_counter when this flow was created
  178     int32_t   vlan;         // vlan interface we first observed; -1 means no vlan 
  179     uint8_t mac_daddr[6];               // dst mac address of first packet
  180     uint8_t mac_saddr[6];               // source mac address of first packet
  181     struct timeval tstart;      // when first seen
  182     struct timeval tlast;       // when last seen
  183     uint64_t len;                   // off-wire length
  184     uint64_t caplen;            // captured length
  185     uint64_t packet_count;      // packet count
  186     uint64_t session_id;      // session unique id (used to match client->server and server->client flows
  187 
  188     // return a filename for a flow based on the template and the connection count
  189     std::string filename(uint32_t connection_count, bool);
  190     // return a new filename for a flow based on the temlate,
  191     // optionally opening the file and returning a fd if &fd is provided
  192     std::string new_filename(int *fd,int flags,int mode);   
  193 
  194     std::string new_pcap_filename();
  195 
  196     bool has_mac_daddr(){
  197         return mac_daddr[0] || mac_daddr[1] || mac_daddr[2] || mac_daddr[3] || mac_daddr[4] || mac_daddr[5];
  198     }
  199 
  200     bool has_mac_saddr(){
  201         return mac_saddr[0] || mac_saddr[1] || mac_saddr[2] || mac_saddr[3] || mac_saddr[4] || mac_saddr[5];
  202     }
  203 };
  204 
  205 /*
  206  * Convenience class for working with TCP headers
  207  */
  208 #define PORT_HTTP 80
  209 #define PORT_HTTP_ALT_0 8080
  210 #define PORT_HTTP_ALT_1 8000
  211 #define PORT_HTTP_ALT_2 8888
  212 #define PORT_HTTP_ALT_3 81
  213 #define PORT_HTTP_ALT_4 82
  214 #define PORT_HTTP_ALT_5 8090
  215 #define PORT_HTTPS 443
  216 #define PORT_SSH 22
  217 #define PORT_FTP_DATA 20
  218 #define PORT_FTP_CONTROL 21
  219 class tcp_header_t {
  220 public:
  221 #pragma GCC diagnostic ignored "-Wcast-align"
  222     tcp_header_t(const u_char *data):
  223     tcp_header((struct be13::tcphdr *)data){};
  224 #pragma GCC diagnostic warning "-Wcast-align"
  225     tcp_header_t(const tcp_header_t &b):
  226     tcp_header(b.tcp_header){}
  227     tcp_header_t &operator=(const tcp_header_t &that) {
  228     this->tcp_header = that.tcp_header;
  229     return *this;
  230     }
  231 
  232     virtual ~tcp_header_t(){}
  233     struct be13::tcphdr *tcp_header;
  234     size_t tcp_header_len(){ return tcp_header->th_off * 4; }
  235     uint16_t sport() {return ntohs(tcp_header->th_sport);}
  236     uint16_t dport() {return ntohs(tcp_header->th_dport);}
  237     be13::tcp_seq  seq()   {return ntohl(tcp_header->th_seq);}
  238     bool th_fin()    {return tcp_header->th_flags & TH_FIN;}
  239     bool th_ack()    {return tcp_header->th_flags & TH_ACK;}
  240     bool th_syn()    {return tcp_header->th_flags & TH_SYN;}
  241 };
  242 
  243 
  244 /*
  245  * The tcpip class is a passive tcp/ip implementation.
  246  * It can reconstruct flows!
  247  *
  248  * It includes:
  249  *   - the flow (as an embedded object)
  250  *   - Information about where the flow is written.
  251  *   - Information about how much of the flow has been captured.
  252  * Currently flows only go in one direction and do not know about their sibling flow
  253  */
  254 
  255 #pragma GCC diagnostic ignored "-Weffc++"
  256 #pragma GCC diagnostic ignored "-Wshadow"
  257 #pragma GCC diagnostic ignored "-Wall"
  258 #pragma GCC diagnostic ignored "-Wmissing-noreturn"
  259 
  260 #if defined(HAVE_BOOST_ICL_INTERVAL_HPP) && defined(HAVE_BOOST_ICL_INTERVAL_MAP_HPP) && defined(HAVE_BOOST_ICL_INTERVAL_SET_HPP)
  261 #include <boost/icl/interval.hpp>
  262 #include <boost/icl/interval_map.hpp>
  263 #include <boost/icl/interval_set.hpp>
  264 typedef boost::icl::interval_set<uint64_t> recon_set; // Boost interval set of bytes that were reconstructed.
  265 #endif
  266 
  267 #include "intrusive_list.h"
  268 
  269 #pragma GCC diagnostic warning "-Weffc++"
  270 #pragma GCC diagnostic warning "-Wshadow"
  271 #pragma GCC diagnostic warning "-Wall"
  272 #pragma GCC diagnostic warning "-Wmissing-noreturn"
  273 
  274 class tcpip {
  275 public:
  276     /** track the direction of the flow; this is largely unused */
  277     typedef enum {
  278     unknown=0,          // unknown direction
  279     dir_sc,             // server-to-client 1 
  280     dir_cs              // client-to-server 2
  281     } dir_t;
  282     
  283 private:
  284     /*** Begin Effective C++ error suppression                ***
  285      *** This class does not implement assignment or copying. ***
  286      ***/
  287     tcpip(const tcpip &t);
  288     tcpip &operator=(const tcpip &that);
  289     /*** End Effective C++ error suppression */
  290 
  291 public:;
  292     tcpip(class tcpdemux &demux_,const flow &flow_,be13::tcp_seq isn_);    /* constructor in tcpip.cpp */
  293     virtual ~tcpip();           // destructor
  294 
  295     class tcpdemux &demux;      // our demultiplexer
  296 
  297     /* State information for the flow being reconstructed */
  298     flow    myflow;         /* Description of this flow */
  299     dir_t   dir;            // direction of flow
  300     be13::tcp_seq isn;          // Flow's initial sequence number
  301     be13::tcp_seq nsn;          // fd - expected next sequence number 
  302     uint32_t    syn_count;      // number of SYNs seen
  303     uint32_t    fin_count;              // number of FINs received
  304     uint32_t    fin_size;               // length of stream as determined when fin is sent
  305     uint64_t    pos;            // fd - current position+1 (next byte in stream to be written)
  306 
  307     /* Archiving information */
  308     std::string flow_pathname;      // path where flow is saved
  309     int     fd;         // file descriptor for file storing this flow's data 
  310     bool    file_created;       // true if file was created
  311 
  312     /* Flow Index information - only used if flow packet/data indexing is requested --GDD */
  313     std::string flow_index_pathname;    // Path for the flow index file
  314     std::fstream        idx_file;               // File descriptor for storing the flow index data
  315 
  316     /* Stats */
  317     recon_set   *seen;                  // what we've seen; it must be * due to boost lossage
  318     uint64_t    last_byte;              // last byte in flow processed
  319     uint64_t    last_packet_number; // for finding most recent packet written
  320     uint64_t    out_of_order_count; // all packets were contigious
  321     uint64_t    violations;     // protocol violation count
  322 
  323     /* File Acess Order */
  324     intrusive_list<tcpip>::iterator it;
  325 
  326     /* Methods */
  327     void close_file();          // close fd
  328     int  open_file();                   // opens save file; return -1 if failure, 0 if success
  329     void print_packet(const u_char *data, uint32_t length);
  330     void store_packet(const u_char *data, uint32_t length, int32_t delta,struct timeval ts);
  331     void process_packet(const struct timeval &ts,const int32_t delta,const u_char *data,const uint32_t length);
  332     uint32_t seen_bytes();
  333     void dump_seen();
  334     void dump_xml(class dfxml_writer *xmlreport,const std::string &xmladd);
  335     static bool compare(std::string a, std::string b);
  336     void sort_index(std::fstream *idx_file);
  337     void sort_index();
  338 };
  339 
  340 /* print a tcpip data structure. Largely for debugging */
  341 inline std::ostream & operator <<(std::ostream &os,const tcpip &f) {
  342     os << "tcpip[" << f.myflow
  343        << " dir:" << int(f.dir) << " isn:" << f.isn << " nsn: " << f.nsn
  344        << " sc:" << f.syn_count << " fc:" << f.fin_count << " fs:" << f.fin_size
  345        << " pos:" << f.pos << " fd: " << f.fd << " cr:" << f.file_created 
  346        << " lb:" << f.last_byte << " lpn:" << f.last_packet_number << " ooc:" << f.out_of_order_count
  347        << "]";
  348     if(f.fd>0) os << " ftell(" << f.fd << ")=" << lseek(f.fd,0L,SEEK_CUR);
  349     return os;
  350 }
  351 
  352 /*
  353  * An saved_flow is a flow for which all of the packets have been received and tcpip state
  354  * has been discarded. The saved_flow allows matches against newly received packets
  355  * that are not SYN or ACK packets but have data. We can see if the data matches data that's
  356  * been written to disk. To do this we need ot know the filename and the ISN...
  357  */
  358 
  359 class saved_flow  {
  360 public:
  361     saved_flow(tcpip *tcp):addr(tcp->myflow),
  362                            saved_filename(tcp->flow_pathname),
  363                            isn(tcp->isn) {}
  364                            
  365     flow_addr         addr;                  // flow address
  366     std::string       saved_filename;        // where the flow was saved
  367     be13::tcp_seq     isn;                    // the flow's ISN
  368     virtual ~saved_flow(){};
  369 };
  370 
  371 class sparse_saved_flow  {
  372 public:
  373     sparse_saved_flow (const flow_addr &idx, FILE *_fcap):addr(idx),fcap(_fcap) {}
  374 
  375     flow_addr         addr;                  // flow address
  376     FILE              *fcap;                // output pcap file
  377     virtual ~sparse_saved_flow()
  378     {
  379         if(fcap) fclose(fcap);
  380     }
  381     /* these are not implemented */
  382 private:
  383     sparse_saved_flow(const sparse_saved_flow &t);
  384     sparse_saved_flow &operator=(const sparse_saved_flow &that);
  385 };
  386 
  387 
  388 #endif