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