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)  

util.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of tcpflow.
3  * Originally by Jeremy Elson <jelson@circlemud.org>
4  * Now maintained by Simson L. Garfinkel <simsong@acm.org>
5  *
6  * This source code is under the GNU Public License (GPL).
7  * See LICENSE for details.
8  *
9  */
10 
11 #include "tcpflow.h"
12 
13 #include <iomanip>
14 
15 static char *debug_prefix = NULL;
16 
17 /*
18  * STD String sprintf wrapper for sane CPP formatting
19  */
20 std::string ssprintf(const char *fmt,...)
21 {
22  char buf[65536];
23  va_list ap;
24  va_start(ap,fmt);
25  vsnprintf(buf,sizeof(buf),fmt,ap);
26  va_end(ap);
27  return std::string(buf);
28 }
29 
30 /*
31  * Insert readability commas into an integer without writing a custom locale facet
32  */
33 std::string comma_number_string(int64_t input)
34 {
35  std::vector<int16_t> tokens;
36  std::stringstream ss;
37  ss << std::setfill('0');
38  int sign = 1;
39 
40  if(input < 0) {
41  sign = -1;
42  input *= -1;
43  }
44 
45  while(input >= 1000) {
46  tokens.push_back(input % 1000);
47  input /= 1000;
48  }
49 
50  ss << (input * sign);
51 
52  for(std::vector<int16_t>::const_reverse_iterator it = tokens.rbegin();
53  it != tokens.rend(); it++) {
54  ss << "," << std::setw(3) << *it;
55  }
56 
57  return ss.str();
58 }
59 
60 
61 std::string macaddr(const uint8_t *addr)
62 {
63  char buf[256];
64  snprintf(buf,sizeof(buf),"%02x:%02x:%02x:%02x:%02x:%02x",
65  addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
66  return std::string(buf);
67 }
68 
69 /*
70  * Remember our program name and process ID so we can use them later
71  * for printing debug messages
72  *
73  */
74 void init_debug(const char *pfx,int include_pid)
75 {
76  if(debug_prefix) free(debug_prefix);
77  size_t debug_prefix_size = strlen(pfx) + 16;
78  debug_prefix = (char *)calloc(sizeof(char), debug_prefix_size);
79  if(debug_prefix==0) die("malloc failed");
80  if(include_pid){
81  snprintf(debug_prefix, debug_prefix_size, "%s[%d]", pfx, (int) getpid());
82  } else {
83  snprintf(debug_prefix, debug_prefix_size, "%s", pfx);
84  }
85 }
86 
87 
88 /****************************************************************/
89 /* C++ string splitting code from http://stackoverflow.com/questions/236129/how-to-split-a-string-in-c */
90 #if 0
91 static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
92 {
93  std::stringstream ss(s);
94  std::string item;
95  while(std::getline(ss, item, delim)) {
96  elems.push_back(item);
97  }
98  return elems;
99 }
100 
101 static std::vector<std::string> split(const std::string &s, char delim)
102 {
103  std::vector<std::string> elems;
104  return split(s, delim, elems);
105 }
106 #endif
107 
108 
109 /* mkdir all of the containing directories in path.
110  * keep track of those made so we don't need to keep remaking them.
111  */
112 void mkdirs_for_path(std::string path)
113 {
114  static std::set<std::string> made_dirs; // track what we made
115 
116  std::string mpath; // the path we are making
117 
118  if(path.at(0)=='/'){
119  mpath = "/";
120  path = path.substr(1);
121  }
122 
123  std::vector<std::string> parts = split(path,'/');
124 
125  /* Notice that this won't mkdir for the last part.
126  * That's okay, because it's a filename.
127  */
128  for(std::vector<std::string>::const_iterator it=parts.begin();it!=parts.end();it++){
129  if(made_dirs.find(mpath)==made_dirs.end()){
130  if(mpath.size()){
131  int r = MKDIR(mpath.c_str(),0777);
132  if(r<0){
133  /* Can't make path; see if we can execute it*/
134  if(access(mpath.c_str(),X_OK)<0){
135  perror(mpath.c_str());
136  exit(1);
137  }
138  }
139  made_dirs.insert(mpath);
140  }
141  }
142  if(mpath.size()>0) mpath += "/";
143  mpath += *it;
144  }
145 }
146 
147 /*
148  * Print a debugging message, given a va_list
149  */
150 void print_debug_message(const char *fmt, va_list ap)
151 {
152  /* print debug prefix */
153  fprintf(stderr, "%s: ", debug_prefix);
154 
155  /* print the var-arg buffer passed to us */
156  vfprintf(stderr, fmt, ap);
157 
158  /* add newline */
159  fprintf(stderr, "\n");
160  (void) fflush(stderr);
161 }
162 
163 /* Print a debugging or informational message */
164 void debug_real(const char *fmt, ...)
165 {
166  va_list ap;
167 
168  va_start(ap, fmt);
169  print_debug_message(fmt, ap);
170  va_end(ap);
171 }
172 
173 
174 /* Print a debugging or informatioal message, then exit */
175 [[noreturn]] void die(const char *fmt, ...)
176 {
177  va_list ap;
178 
179  va_start(ap, fmt);
180  print_debug_message(fmt, ap);
181  exit(1);
182 }
183 
184 /* An attempt at making signal() portable.
185  *
186  * If we detect sigaction, use that;
187  * otherwise if we have setsig, use that;
188  * otherwise, cross our fingers and hope for the best using plain old signal().
189  *
190  * Our first choice is sigaction (sigaction() is POSIX; signal() is
191  * not.) Taken from Stevens' _Advanced Programming in the UNIX Environment_.
192  *
193  * 10/6/08 - slg - removed RETSIGTYPE, since it hasn't been needed to 15 years
194  */
195 void (*portable_signal(int signo, void (*func)(int)))(int)
196 {
197 #if defined(HAVE_SIGACTION)
198  struct sigaction act, oact;
199 
200  memset(&act, 0, sizeof(act));
201  memset(&oact, 0, sizeof(oact));
202  act.sa_handler = func;
203  sigemptyset(&act.sa_mask);
204  act.sa_flags = 0;
205  if (sigaction(signo, &act, &oact) < 0) return (SIG_ERR);
206  return (oact.sa_handler);
207 #elif defined(HAVE_SIGSET)
208  return sigset(signo, func);
209 #else
210  return signal(signo, func);
211 #endif /* HAVE_SIGACTION, HAVE_SIGSET */
212 }
213 
214 
215 /************
216  *** MMAP ***
217  ************/
218 
219 #ifdef HAVE_SYS_MMAN_H
220 #include <sys/mman.h>
221 #endif
222 
223 /**
224  * fake implementation of mmap and munmap if we don't have them
225  */
226 #if !defined(HAVE_MMAP)
227 #define PROT_READ 0
228 #define MAP_FILE 0
229 #define MAP_SHARED 0
230 void *mmap(void *addr,size_t length,int prot, int flags, int fd, off_t offset)
231 {
232  void *buf = (void *)malloc(length);
233  if(!buf) return 0;
234  read(fd,buf,length); // should explore return code
235  return buf;
236 }
237 
238 void munmap(void *buf,size_t size)
239 {
240  free(buf);
241 }
242 
243 #endif
244 
static const char tokens[256]
Definition: http_parser.c:188
flags
Definition: http_parser.h:216
#define MKDIR(a, b)
Definition: tcpflow.h:49
void(*)(int) portable_signal(int signo, void(*func)(int))
Definition: util.cpp:195
void init_debug(const char *pfx, int include_pid)
Definition: util.cpp:74
void die(const char *fmt,...)
Definition: util.cpp:175
std::string macaddr(const uint8_t *addr)
Definition: util.cpp:61
std::string comma_number_string(int64_t input)
Definition: util.cpp:33
void print_debug_message(const char *fmt, va_list ap)
Definition: util.cpp:150
void mkdirs_for_path(std::string path)
Definition: util.cpp:112
static char * debug_prefix
Definition: util.cpp:15
std::string ssprintf(const char *fmt,...)
Definition: util.cpp:20
void debug_real(const char *fmt,...)
Definition: util.cpp:164
void * mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
Definition: util.cpp:230
void munmap(void *buf, size_t size)
Definition: util.cpp:238
unsigned char uint8_t
Definition: util.h:6
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
Definition: utils.cpp:133