"Fossies" - the Fresh Open Source Software Archive 
Member "tcpflow-1.6.1/src/flow.cpp" (19 Feb 2021, 6524 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 "flow.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 * flow.cpp:
4 *
5 * The flow class is used to track individual TCP/IP flows (2 per connection).
6 * The class implements the methods that turn a flow into a filename.
7 *
8 * This file is part of tcpflow by Jeremy Elson <jelson@circlemud.org>
9 * Initial Release: 7 April 1999.
10 *
11 * This source code is under the GNU Public License (GPL). See
12 * LICENSE for details.
13 *
14 */
15
16 #include "tcpflow.h"
17 #include "tcpip.h"
18 #include "tcpdemux.h"
19
20 #ifdef HAVE_ARPA_INET_H
21 #include <arpa/inet.h> // inet_ntop
22 #endif
23
24 #include <assert.h>
25 #include <iostream>
26 #include <sstream>
27
28 std::string flow::filename_template("%A.%a-%B.%b%V%v%C%c");
29 std::string flow::outdir(".");
30
31 void flow::usage()
32 {
33 std::cout << "\n"
34 "Filename template format for option -T:\n";
35 std::cout << " %A/%a - source IP address/port; %B/%b - dest IP address/port\n";
36 std::cout << " %E/%e - source/dest Ethernet Mac address\n";
37 std::cout << " %V/%v - VLAN number, '--' if no vlan/'' if no vlan\n";
38 std::cout << " %T/%t - Timestamp in ISO8601 format/unix time_t\n";
39 std::cout << " %c - connection_count for connections>0 / %# for all connections;";
40 std::cout << " %C - 'c' if connection_count >0\n";
41 std::cout << " %N - (connection_number ) % 1000\n";
42 std::cout << " %K - (connection_number / 1000) % 1000\n";
43 std::cout << " %M - (connection_number / 1000000) % 1000\n";
44 std::cout << " %G - (connection_number / 1000000000) % 1000\n";
45 std::cout << " %S - session ID\n";
46 std::cout << " %% - Output a '%'\n";
47 std::cout << "\n";
48 std::cout << "Default value is: '"<< flow::filename_template <<"'\n";
49 std::cout << "\n";
50 std::cout << "Note: Using the option -T will ignore options -Fk, -Fm and -Fg.\n";
51 std::cout << " Filename template format handles '/' to create sub-directories.\n";
52 }
53
54 std::string flow::filename(uint32_t connection_count, bool is_pcap)
55 {
56 std::stringstream ss;
57
58 /* Add the outdir */
59 if(flow::outdir!="." && flow::outdir!=""){
60 ss << flow::outdir;
61 ss << '/';
62 }
63
64 for(unsigned int i=0;i<filename_template.size();i++){
65 switch(filename_template.at(i)){
66 default:
67 ss << filename_template.at(i);
68 break;
69 case '%':
70 if(i==filename_template.size()-1){
71 std::cerr << "Invalid filename_template: " << filename_template << " cannot end with a %\n";
72 exit(1);
73 }
74 /* put the substitute in ss or buf */
75 char buf[1024];
76 buf[0] = 0;
77 switch(filename_template.at(++i)){
78 case 'A': // source IP address
79 switch(family){
80 case AF_INET:
81 snprintf(buf,sizeof(buf),"%03d.%03d.%03d.%03d",
82 src.addr[0], src.addr[1], src.addr[2], src.addr[3]);
83 break;
84 case AF_INET6:
85 inet_ntop(family, src.addr, buf,sizeof(buf));
86 }
87 break;
88 case 'a': // source IP port
89 snprintf(buf,sizeof(buf),"%05d",sport);
90 break;
91 case 'B': // dest IP address
92 switch(family){
93 case AF_INET:
94 snprintf(buf,sizeof(buf),"%03d.%03d.%03d.%03d",
95 dst.addr[0], dst.addr[1], dst.addr[2], dst.addr[3]);
96 break;
97 case AF_INET6:
98 inet_ntop(family, dst.addr, buf,sizeof(buf));
99 }
100 break;
101 case 'b': // dest IP port
102 snprintf(buf,sizeof(buf),"%05d",dport);
103 break;
104 /* binning by connection number */
105 case 'E':
106 snprintf(buf,sizeof(buf),"%02x:%02x:%02x:%02x:%02x:%02x",
107 mac_saddr[0],mac_saddr[1],mac_saddr[2],mac_saddr[3],mac_saddr[4],mac_saddr[5]);
108 break;
109 case 'e':
110 snprintf(buf,sizeof(buf),"%02x:%02x:%02x:%02x:%02x:%02x",
111 mac_daddr[0],mac_daddr[1],mac_daddr[2],mac_daddr[3],mac_daddr[4],mac_daddr[5]);
112 break;
113 case 'N': snprintf(buf,sizeof(buf),"%03d",(int)(id) % 1000);break;
114 case 'K': snprintf(buf,sizeof(buf),"%03d",(int)(id /1000 ) % 1000);break;
115 case 'M': snprintf(buf,sizeof(buf),"%03d",(int)(id /1000000) % 1000);break;
116 case 'G': snprintf(buf,sizeof(buf),"%03d",(int)(id /1000000000) % 1000);break;
117
118 case 'T': // Timestamp in ISO8601 format
119 {
120 time_t t = tstart.tv_sec;
121 strftime(buf,sizeof(buf),"%Y-%m-%dT%H:%M:%SZ",gmtime(&t));
122 break;
123 }
124 case 't': // Unix time_t
125 ss << tstart.tv_sec;
126 break;
127 case 'V': // '--' if VLAN is present
128 if(vlan!=be13::packet_info::NO_VLAN) ss << "--";
129 break;
130 case 'v': // VLAN number if VLAN is present
131 if(vlan!=be13::packet_info::NO_VLAN) ss << vlan;
132 break;
133 case 'C': // 'c' if connection_count >0
134 if(connection_count>0) ss << "c";
135 break;
136 case 'c': // connection_count if connection_count >0
137 if(connection_count>0) ss << connection_count;
138 break;
139 case 'S': // session ID
140 ss << std::setfill('0') << std::setw(20) << session_id;
141 break;
142 case '#': // always output connection count
143 ss << connection_count;
144 break;
145 case '%': // Output a '%'
146 ss << "%";
147 break;
148 default:
149 std::cerr << "Invalid filename_template: " << filename_template << "\n";
150 std::cerr << "unknown character: " << filename_template.at(i+1) << "\n";
151 exit(1);
152 }
153 if(buf[0]) ss << buf;
154 }
155 }
156 if(is_pcap){
157 ss << ".pcap"; // file extension
158 }
159 return ss.str();
160 }
161
162 /**
163 * Find an unused filename for the flow and optionally open it.
164 * This is called from tcpip::open_file().
165 */
166
167 std::string flow::new_filename(int *fd,int flags,int mode)
168 {
169 /* Loop connection count until we find a file that doesn't exist */
170 for(uint32_t connection_count=0;;connection_count++){
171 std::string nfn = filename(connection_count, false);
172 if(nfn.find('/')!=std::string::npos) mkdirs_for_path(nfn.c_str());
173 int nfd = tcpdemux::getInstance()->retrying_open(nfn,flags,mode);
174 if(nfd>=0){
175 *fd = nfd;
176 return nfn;
177 }
178 if(errno!=EEXIST) die("Cannot open: %s",nfn.c_str());
179 }
180 return std::string("<<CANNOT CREATE FILE>>"); // error; no file
181 }
182
183 std::string flow::new_pcap_filename()
184 {
185 /* Loop connection count until we find a file that doesn't exist */
186 for(uint32_t connection_count=0;;connection_count++){
187 std::string nfn = filename(connection_count, true);
188 if(nfn.find('/')!=std::string::npos) mkdirs_for_path(nfn.c_str());
189 return nfn;
190 }
191 return std::string("<<CANNOT CREATE FILE>>"); // error; no file
192 }