1 /*
2 rate -- statistic traffic analyzer
3 Copyright (C) 2003 Mateusz 'mteg' Golicz
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #ifdef HAVE_REGEX
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #ifdef OPEN_BSD
27 #include <netinet/in_systm.h>
28 #endif
29 #include <netinet/in.h>
30 #include <netinet/ip.h>
31 #include <netinet/tcp.h>
32 #include <sys/timeb.h>
33 #include <signal.h>
34 #include <time.h>
35 #include <pcap.h>
36 #include "lib.h"
37 #ifdef HAVE_REGEX
38 #include <regex.h>
39 #endif
40 #include "iphash.h"
41
42 static regex_t global_regex_c;
43 static char * regex_checking_buffer = NULL;
44 extern int opt_caplen;
45
46
unescape(char * string,int * length,unsigned char terminator)47 char* unescape(char *string, int *length, unsigned char terminator)
48 {
49 char *out;
50 char c, d, e;
51 int i, k;
52
53 out = (char*) malloc(strlen(string)); k=0; /* in the worst case we'll need so much */
54 for(i = 0; string[i] != 0; i++) /* foreach character in string */
55 {
56 if(string[i] == '\\') /* is it '\' ? */
57 {
58 c = string[i + 1]; /* get next character .. */
59 if(!c) continue; /* if it's end of string, forget that */
60 if(c == 'x') /* x - means hexadecimal code of character */
61 {
62 if((d = string[i + 2])) /* get first hex digit */
63 {
64 if((e = string[i + 3])) /* get second hex digit */
65 {
66 if(d >= 'a' && d <= 'f') d = d - 'a' + 10; else d -= '0';
67 if(e >= 'a' && e <= 'f') e = e - 'a' + 10; else e -= '0';
68 out[k++] = d << 4 | e; /* calculate character code and write into final string */
69 i += 3; /* x<hex_digit><hex_digit> */
70 continue;
71 }
72 }
73 }
74 if(c == 'n')
75 {
76 out[k++] = '\n';
77 i += 1;
78 continue;
79 }
80 if(c == 'r')
81 {
82 out[k++] = '\r';
83 i += 1;
84 continue;
85 }
86 if(c == 't')
87 {
88 out[k++] = '\t';
89 i += 1;
90 continue;
91 }
92 if(c == '\\')
93 {
94 out[k++] = c;
95 i += 1;
96 continue;
97 }
98 out[k++] = string[i];
99 out[k++] = c;
100 i += 1;
101 }
102 else
103 {
104 if(string[i] == terminator) break; /* we reached end of string */
105 out[k++] = string[i]; /* add that end marker to final string */
106 }
107 }
108 out[k] = 0;
109 if(length) *length = i;
110 return(out);
111 }
112
113
prepare_buffer(const char * data,int len,char nul_char)114 void prepare_buffer(const char * data, int len, char nul_char)
115 {
116 int safe_len = (len > opt_caplen) ? opt_caplen : len;
117 int i;
118 for(i = 0; i<safe_len; i++)
119 {
120 char c;
121 c = data[i];
122 if(c == 0) c = nul_char;
123 regex_checking_buffer[i] = c;
124 }
125 regex_checking_buffer[i] = 0;
126 }
127
check_regex(const char * data,int len,char nul_char)128 int check_regex(const char * data, int len, char nul_char)
129 {
130 prepare_buffer(data, len, nul_char);
131 if(regexec(&global_regex_c, regex_checking_buffer, 0, NULL, 0) == 0)
132 return(1);
133 else
134 return(0);
135
136 }
prepare_regex(char * regex,int caplen)137 void prepare_regex(char *regex, int caplen)
138 {
139 if(regex)
140 {
141 int rc;
142
143 regex = unescape(regex, NULL, 0);
144 rc = regcomp(&global_regex_c, regex, REG_EXTENDED | REG_NOSUB);
145 if(rc)
146 {
147 char errbuff[100];
148 regerror(rc, &global_regex_c, errbuff, 100);
149 fprintf(stderr, "regcomp('%s'): %s\n", regex, errbuff);
150 exit(1);
151 }
152 regex_checking_buffer = (char*) malloc(caplen + 1);
153 if(!regex_checking_buffer)
154 {
155 fprintf(stderr, "Unable to allocate regex checking buffer, out of memory?\n");
156 exit(1);
157 }
158 }
159 }
160
161
162
163
164 static regex_t *global_extractor_c = NULL;
165 static char ** stringtab = NULL;
166 static int *lentab = NULL;
167 static int ext_count = 0;
168
169 static char ** formattab = NULL;
170 static int * ordertab = NULL;
171 int ordercount = 0;
172
173
prepare_extractor(char * regex,char * order,int caplen)174 void prepare_extractor(char *regex, char * order, int caplen)
175 {
176 int state = '(';
177 char * pos, * nx;
178
179 nx = pos = regex = unescape(regex, NULL, 0);
180
181 for(; nx;)
182 {
183 char * part;
184 int rc;
185
186 for(nx = index(pos, state); nx; nx = index(nx + 1, state))
187 if(nx != regex)
188 {
189 if((nx - 1) != regex)
190 if(*(nx - 2) == '\\') continue;
191
192 if(*(nx - 1) == '\\')
193 break;
194 }
195
196 if(nx)
197 {
198 *(nx - 1) = 0;
199 *(nx++) = 0;
200 }
201
202 if(state == '(')
203 state = ')';
204 else
205 state = '(';
206
207 part = strdup(pos);
208 global_extractor_c = (regex_t*) realloc(global_extractor_c, sizeof(regex_t) * (ext_count + 1));
209 {
210 rc = regcomp(&global_extractor_c[ext_count], part, REG_EXTENDED);
211 if(rc)
212 {
213 char errbuff[100];
214 regerror(rc, &global_extractor_c[ext_count], errbuff, 100);
215 fprintf(stderr, "regcomp('%s'): %s\n", part, errbuff);
216 exit(1);
217 }
218 ext_count++;
219 }
220 pos = nx;
221 }
222
223 if(ext_count % 2 == 0)
224 {
225 fprintf(stderr, "Unmatched '(' or ')' (%d sub-expressions)\n", ext_count);
226 exit(1);
227 }
228 if(!ext_count)
229 {
230 fprintf(stderr, "Empty extractor match regex.\n");
231 exit(1);
232 }
233
234 regex_checking_buffer = (char*) malloc(caplen + 1);
235
236 if(!regex_checking_buffer)
237 {
238 fprintf(stderr, "Unable to allocate regex checking buffer, out of memory?\n");
239 exit(1);
240 }
241 stringtab = (char**) malloc(sizeof(char*) * ext_count);
242 lentab = (int*) malloc(sizeof(int) * ext_count);
243
244 if(order)
245 {
246 nx = pos = order;
247
248 for(; nx;)
249 {
250 char * part;
251
252 nx = index(pos, '\\');
253
254 if(nx)
255 *(nx++) = 0;
256
257 formattab = (char**) realloc(formattab, (ordercount + 1) * sizeof(char*));
258 ordertab = (int*) realloc(ordertab, (ordercount + 1) * sizeof(int));
259
260 formattab[ordercount] = strdup(pos);
261 if(nx)
262 {
263 if(*nx)
264 {
265 ordertab[ordercount] = *(nx) - '1';
266 if(ordertab[ordercount] >= (ext_count / 2))
267 {
268 fprintf(stderr, "Reference %c in format string is invalid.\n", *nx);
269 exit(1);
270 }
271 nx++;
272 ordercount++;
273 }
274 }
275 pos = nx;
276 }
277 }
278 }
279
280 #define MAX_STRSIZE 512
281
extractor(const char * data,int len,char nul_char,int showips)282 int extractor(const char * data, int len, char nul_char, int showips)
283 {
284 regmatch_t match;
285 int lastchar = -1;
286 int i, j = 0;
287 unsigned char strout[MAX_STRSIZE];
288
289
290 prepare_buffer(data, len, nul_char);
291 for(i = 0; i < ext_count; i++)
292 {
293 if(regexec(&global_extractor_c[i], regex_checking_buffer + ((lastchar > 0) ? (lastchar) : 0), 1, &match, 0) != 0) break;
294
295 if(i % 2 == 1)
296 {
297 stringtab[j] = regex_checking_buffer + lastchar + match.rm_so;
298 lentab[j++] = match.rm_eo - match.rm_so + 1;
299 }
300
301 if(lastchar < 0)
302 lastchar = match.rm_eo;
303 else
304 {
305 if(match.rm_so != 0) break;
306 lastchar += match.rm_eo;
307 }
308 }
309
310 if(i == ext_count)
311 {
312 if(showips)
313 {
314 struct in_addr in;
315 if(len >= sizeof(struct ip))
316 {
317 in = ((struct ip*) data)->ip_src;
318 printf("%s => ", inet_ntoa(in));
319 in = ((struct ip*) data)->ip_dst;
320 printf("%s ", inet_ntoa(in));
321 }
322 }
323 if(ordertab)
324 {
325 int oc;
326 for(oc = 0; oc<ordercount; oc++)
327 {
328 int l, o;
329 printf("%s", formattab[oc]);
330 o = ordertab[oc];
331
332 l = lentab[o];
333 if(l > (MAX_STRSIZE - 1)) l = MAX_STRSIZE - 1;
334 snprintf(strout, l, "%s", stringtab[o]);
335 printf("%s", strout);
336 }
337 printf("%s\n", formattab[oc]);
338 }
339 else
340 {
341 for(i = 0; i < j; i++)
342 {
343 int l = lentab[i];
344 if(l > (MAX_STRSIZE - 1)) l = MAX_STRSIZE - 1;
345 snprintf(strout, l, "%s", stringtab[i]);
346 printf("%s ", strout);
347 }
348 printf("\n");
349 }
350 }
351 }
352
353 #endif
354