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.h
Go to the documentation of this file.
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
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;
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  }
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
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 
197  return mac_daddr[0] || mac_daddr[1] || mac_daddr[2] || mac_daddr[3] || mac_daddr[4] || mac_daddr[5];
198  }
199 
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
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"
228  this->tcp_header = that.tcp_header;
229  return *this;
230  }
231 
232  virtual ~tcp_header_t(){}
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 */
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);
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 
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
378  {
379  if(fcap) fclose(fcap);
380  }
381  /* these are not implemented */
382 private:
385 };
386 
387 
388 #endif
std::string str() const
Definition: tcpip.h:138
flow_addr(const ipaddr &s, const ipaddr &d, uint16_t sp, uint16_t dp, sa_family_t f)
Definition: tcpip.h:90
ipaddr dst
Definition: tcpip.h:98
flow_addr()
Definition: tcpip.h:89
bool operator==(const flow_addr &b) const
Definition: tcpip.h:116
ipaddr src
Definition: tcpip.h:96
sa_family_t family
Definition: tcpip.h:101
flow_addr(const flow_addr &f)
Definition: tcpip.h:93
bool operator<(const flow_addr &b) const
Definition: tcpip.h:124
uint64_t hash() const
Definition: tcpip.h:103
virtual ~flow_addr()
Definition: tcpip.h:96
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
int32_t vlan
Definition: tcpip.h:178
uint64_t packet_count
Definition: tcpip.h:185
uint8_t mac_saddr[6]
Definition: tcpip.h:180
std::string new_pcap_filename()
Definition: flow.cpp:183
bool has_mac_daddr()
Definition: tcpip.h:196
std::string new_filename(int *fd, int flags, int mode)
Definition: flow.cpp:167
flow()
Definition: tcpip.h:161
flow(const flow_addr &flow_addr_, uint64_t id_, const be13::packet_info &pi)
Definition: tcpip.h:162
static std::string outdir
Definition: tcpip.h:160
uint64_t id
Definition: tcpip.h:176
uint64_t session_id
Definition: tcpip.h:186
static void usage()
Definition: flow.cpp:31
struct timeval tstart
Definition: tcpip.h:181
uint8_t mac_daddr[6]
Definition: tcpip.h:179
uint64_t caplen
Definition: tcpip.h:184
static std::string filename_template
Definition: tcpip.h:159
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
virtual ~flow()
Definition: tcpip.h:176
const ipaddr & ia
Definition: tcpip.h:61
ipaddr_prn(const ipaddr &ia_, sa_family_t family_)
Definition: tcpip.h:63
const sa_family_t family
Definition: tcpip.h:62
Definition: tcpip.h:25
ipaddr(const uint8_t a[16])
Definition: tcpip.h:37
bool bit(int i) const
Definition: tcpip.h:42
uint8_t addr[16]
Definition: tcpip.h:41
ipaddr(const in_addr_t &a)
Definition: tcpip.h:30
uint64_t dquad(int i) const
Definition: tcpip.h:48
bool operator>=(const ipaddr &b) const
Definition: tcpip.h:55
ipaddr()
Definition: tcpip.h:27
bool operator<=(const ipaddr &b) const
Definition: tcpip.h:53
bool operator>(const ipaddr &b) const
Definition: tcpip.h:54
bool operator==(const ipaddr &b) const
Definition: tcpip.h:52
bool operator<(const ipaddr &b) const
Definition: tcpip.h:56
uint32_t quad(int i) const
Definition: tcpip.h:45
be13::tcp_seq isn
Definition: tcpip.h:367
saved_flow(tcpip *tcp)
Definition: tcpip.h:361
flow_addr addr
Definition: tcpip.h:365
std::string saved_filename
Definition: tcpip.h:366
virtual ~saved_flow()
Definition: tcpip.h:368
FILE * fcap
Definition: tcpip.h:376
virtual ~sparse_saved_flow()
Definition: tcpip.h:377
flow_addr addr
Definition: tcpip.h:375
sparse_saved_flow(const flow_addr &idx, FILE *_fcap)
Definition: tcpip.h:373
sparse_saved_flow & operator=(const sparse_saved_flow &that)
sparse_saved_flow(const sparse_saved_flow &t)
be13::tcp_seq seq()
Definition: tcpip.h:237
tcp_header_t(const tcp_header_t &b)
Definition: tcpip.h:225
virtual ~tcp_header_t()
Definition: tcpip.h:232
bool th_fin()
Definition: tcpip.h:238
bool th_ack()
Definition: tcpip.h:239
size_t tcp_header_len()
Definition: tcpip.h:234
tcp_header_t & operator=(const tcp_header_t &that)
Definition: tcpip.h:227
bool th_syn()
Definition: tcpip.h:240
tcp_header_t(const u_char *data)
Definition: tcpip.h:222
uint16_t dport()
Definition: tcpip.h:236
struct be13::tcphdr * tcp_header
Definition: tcpip.h:233
uint16_t sport()
Definition: tcpip.h:235
Definition: tcpip.h:274
recon_set * seen
Definition: tcpip.h:317
uint64_t last_packet_number
Definition: tcpip.h:319
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 process_packet(const struct timeval &ts, const int32_t delta, const u_char *data, const uint32_t length)
void dump_seen()
Definition: tcpip.cpp:53
uint64_t last_byte
Definition: tcpip.h:318
uint64_t violations
Definition: tcpip.h:321
uint32_t fin_size
Definition: tcpip.h:304
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_t
Definition: tcpip.h:277
@ dir_sc
Definition: tcpip.h:279
@ dir_cs
Definition: tcpip.h:280
@ unknown
Definition: tcpip.h:278
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
uint32_t fin_count
Definition: tcpip.h:303
static bool compare(std::string a, std::string b)
Definition: tcpip.cpp:613
tcpip & operator=(const tcpip &that)
const uint8_t * get_ether_shost() const
#define TH_FIN
#define TH_ACK
const struct pcap_pkthdr * pcap_hdr
#define TH_SYN
uint32_t tcp_seq
const uint8_t * get_ether_dhost() const
flags
Definition: http_parser.h:216
const char * inet_ntop(int af, const void *addr, char *buf, socklen_t len)
Definition: inet_ntop.c:41
unsigned int uint32_t
Definition: core.h:40
Definition: tcp.h:45
bool operator==(const struct timeval &a, const struct timeval &b)
Definition: tcpip.h:75
std::ostream & operator<<(std::ostream &os, const ipaddr_prn &b)
Definition: tcpip.h:68
unsigned short int sa_family_t
Definition: tcpip.h:16
uint32_t in_addr_t
Definition: tcpip.h:12
bool operator<(const struct timeval &a, const struct timeval &b)
Definition: tcpip.h:79
unsigned short uint16_t
Definition: util.h:7
unsigned char uint8_t
Definition: util.h:6