36db056733b440d289ddb3f6765f9027d52f6ffa
[metze/wireshark/wip.git] / epan / ftypes / ftype-tvbuff.c
1 /*
2  * $Id$
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2001 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <ftypes-int.h>
29 #include <string.h>
30
31 #define CMP_MATCHES cmp_matches
32
33 #define tvb_is_private  fvalue_gboolean1
34
35 static void
36 value_new(fvalue_t *fv)
37 {
38         fv->value.tvb = NULL;
39         fv->tvb_is_private = FALSE;
40 }
41
42 static void
43 value_free(fvalue_t *fv)
44 {
45         if (fv->value.tvb && fv->tvb_is_private) {
46                 tvb_free_chain(fv->value.tvb);
47         }
48 }
49
50 static void
51 value_set(fvalue_t *fv, gpointer value, gboolean already_copied)
52 {
53         g_assert(already_copied);
54
55         /* Free up the old value, if we have one */
56         value_free(fv);
57
58         fv->value.tvb = (tvbuff_t *)value;
59 }
60
61 static void
62 free_tvb_data(void *data)
63 {
64         g_free(data);
65 }
66
67 static gboolean
68 val_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
69 {
70         tvbuff_t *new_tvb;
71         guint8 *private_data;
72
73         /* Free up the old value, if we have one */
74         value_free(fv);
75
76         /* Make a tvbuff from the string. We can drop the
77          * terminating NUL. */
78         private_data = (guint8 *)g_memdup(s, (guint)strlen(s));
79         new_tvb = tvb_new_real_data(private_data,
80                         (guint)strlen(s), (gint)strlen(s));
81
82         /* Let the tvbuff know how to delete the data. */
83         tvb_set_free_cb(new_tvb, free_tvb_data);
84
85         /* And let us know that we need to free the tvbuff */
86         fv->tvb_is_private = TRUE;
87         fv->value.tvb = new_tvb;
88         return TRUE;
89 }
90
91 static gboolean
92 val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
93 {
94         fvalue_t *fv_bytes;
95         tvbuff_t *new_tvb;
96         guint8 *private_data;
97
98         /* Free up the old value, if we have one */
99         value_free(fv);
100
101         /* Does this look like a byte string? */
102         fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL);
103         if (fv_bytes) {
104                 /* Make a tvbuff from the bytes */
105                 private_data = (guint8 *)g_memdup(fv_bytes->value.bytes->data,
106                                 fv_bytes->value.bytes->len);
107                 new_tvb = tvb_new_real_data(private_data,
108                                 fv_bytes->value.bytes->len,
109                                 fv_bytes->value.bytes->len);
110
111                 /* Let the tvbuff know how to delete the data. */
112                 tvb_set_free_cb(new_tvb, free_tvb_data);
113
114                 /* And let us know that we need to free the tvbuff */
115                 fv->tvb_is_private = TRUE;
116                 fv->value.tvb = new_tvb;
117                 return TRUE;
118         }
119
120         /* Treat it as a string. */
121         return val_from_string(fv, s, logfunc);
122 }
123
124 static int
125 val_repr_len(fvalue_t *fv, ftrepr_t rtype)
126 {
127         volatile guint length = 0;
128
129         if (rtype != FTREPR_DFILTER) return -1;
130
131         TRY {
132                 /* 3 bytes for each byte of the byte "NN:" minus 1 byte
133                  * as there's no trailing ":". */
134                 length = tvb_length(fv->value.tvb) * 3 - 1;
135         }
136         CATCH_ALL {
137                 /* nothing */
138         }
139         ENDTRY;
140
141         return (int) length;
142 }
143
144 static void
145 val_to_repr(fvalue_t *fv, ftrepr_t rtype, char *buf)
146 {
147         guint length;
148         const guint8 *c;
149         char *write_cursor;
150         unsigned int i;
151
152         g_assert(rtype == FTREPR_DFILTER);
153
154         TRY {
155                 length = tvb_length(fv->value.tvb);
156                 c = tvb_get_ptr(fv->value.tvb, 0, length);
157                 write_cursor = buf;
158
159                 for (i = 0; i < length; i++) {
160                         if (i == 0) {
161                                 sprintf(write_cursor, "%02x", *c++);
162                                 write_cursor += 2;
163                         }
164                         else {
165                                 sprintf(write_cursor, ":%02x", *c++);
166                                 write_cursor += 3;
167                         }
168                 }
169         }
170         CATCH_ALL {
171                 /* nothing */
172         }
173         ENDTRY;
174 }
175
176 static gpointer
177 value_get(fvalue_t *fv)
178 {
179         return fv->value.tvb;
180 }
181
182 static guint
183 len(fvalue_t *fv)
184 {
185         volatile guint length = 0;
186
187         TRY {
188                 if (fv->value.tvb)
189                         length = tvb_length(fv->value.tvb);
190         }
191         CATCH_ALL {
192                 /* nothing */
193         }
194         ENDTRY;
195
196         return length;
197 }
198
199 static void
200 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
201 {
202         const guint8* data;
203
204         if (fv->value.tvb) {
205                 TRY {
206                         data = tvb_get_ptr(fv->value.tvb, offset, length);
207                         g_byte_array_append(bytes, data, length);
208                 }
209                 CATCH_ALL {
210                         /* nothing */
211                 }
212                 ENDTRY;
213
214         }
215 }
216
217 static gboolean
218 cmp_eq(fvalue_t *fv_a, fvalue_t *fv_b)
219 {
220         tvbuff_t        *a = fv_a->value.tvb;
221         tvbuff_t        *b = fv_b->value.tvb;
222         volatile gboolean       eq = FALSE;
223
224         TRY {
225                 guint   a_len = tvb_length(a);
226
227                 if (a_len == tvb_length(b))
228                         eq = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) == 0);
229         }
230         CATCH_ALL {
231                 /* nothing */
232         }
233         ENDTRY;
234
235         return eq;
236 }
237
238 static gboolean
239 cmp_ne(fvalue_t *fv_a, fvalue_t *fv_b)
240 {
241         tvbuff_t        *a = fv_a->value.tvb;
242         tvbuff_t        *b = fv_b->value.tvb;
243         volatile gboolean       ne = TRUE;
244
245         TRY {
246                 guint   a_len = tvb_length(a);
247
248                 if (a_len == tvb_length(b)) {
249                         ne = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) != 0);
250                 }
251         }
252         CATCH_ALL {
253                 /* nothing */
254         }
255         ENDTRY;
256
257         return ne;
258 }
259
260 static gboolean
261 cmp_gt(fvalue_t *fv_a, fvalue_t *fv_b)
262 {
263         tvbuff_t        *a = fv_a->value.tvb;
264         tvbuff_t        *b = fv_b->value.tvb;
265         volatile gboolean       gt = FALSE;
266
267         TRY {
268                 guint   a_len = tvb_length(a);
269                 guint   b_len = tvb_length(b);
270
271                 if (a_len > b_len) {
272                         gt = TRUE;
273                 } else if (a_len == b_len) {
274                         gt = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) > 0);
275                 }
276         }
277         CATCH_ALL {
278                 /* nothing */
279         }
280         ENDTRY;
281
282         return gt;
283 }
284
285 static gboolean
286 cmp_ge(fvalue_t *fv_a, fvalue_t *fv_b)
287 {
288         tvbuff_t        *a = fv_a->value.tvb;
289         tvbuff_t        *b = fv_b->value.tvb;
290         volatile gboolean       ge = FALSE;
291
292         TRY {
293                 guint   a_len = tvb_length(a);
294                 guint   b_len = tvb_length(b);
295
296                 if (a_len > b_len) {
297                         ge = TRUE;
298                 } else if (a_len == b_len) {
299                         ge = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) >= 0);
300                 }
301         }
302         CATCH_ALL {
303                 /* nothing */
304         }
305         ENDTRY;
306
307         return ge;
308 }
309
310 static gboolean
311 cmp_lt(fvalue_t *fv_a, fvalue_t *fv_b)
312 {
313         tvbuff_t        *a = fv_a->value.tvb;
314         tvbuff_t        *b = fv_b->value.tvb;
315         volatile gboolean       lt = FALSE;
316
317         TRY {
318                 guint   a_len = tvb_length(a);
319                 guint   b_len = tvb_length(b);
320
321                 if (a_len < b_len) {
322                         lt = TRUE;
323                 } else if (a_len == b_len) {
324                         lt = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) < 0);
325                 }
326         }
327         CATCH_ALL {
328                 /* nothing */
329         }
330         ENDTRY;
331
332         return lt;
333 }
334
335 static gboolean
336 cmp_le(fvalue_t *fv_a, fvalue_t *fv_b)
337 {
338         tvbuff_t        *a = fv_a->value.tvb;
339         tvbuff_t        *b = fv_b->value.tvb;
340         volatile gboolean       le = FALSE;
341
342         TRY {
343                 guint   a_len = tvb_length(a);
344                 guint   b_len = tvb_length(b);
345
346                 if (a_len < b_len) {
347                         le = TRUE;
348                 } else if (a_len == b_len) {
349                         le = (memcmp(tvb_get_ptr(a, 0, a_len), tvb_get_ptr(b, 0, a_len), a_len) <= 0);
350                 }
351         }
352         CATCH_ALL {
353                 /* nothing */
354         }
355         ENDTRY;
356
357         return le;
358 }
359
360 static gboolean
361 cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
362 {
363         volatile gboolean       contains = FALSE;
364
365         TRY {
366                 if (tvb_find_tvb(fv_a->value.tvb, fv_b->value.tvb, 0) > -1) {
367                         contains = TRUE;
368                 }
369         }
370         CATCH_ALL {
371                 /* nothing */
372         }
373         ENDTRY;
374
375         return contains;
376 }
377
378 static gboolean
379 cmp_matches(fvalue_t *fv_a, fvalue_t *fv_b)
380 {
381         tvbuff_t *tvb = fv_a->value.tvb;
382         GRegex *regex = fv_b->value.re;
383         volatile gboolean rc = FALSE;
384         const char *data = NULL; /* tvb data */
385         guint32 tvb_len; /* tvb length */
386
387         /* fv_b is always a FT_PCRE, otherwise the dfilter semcheck() would have
388          * warned us. For the same reason (and because we're using g_malloc()),
389          * fv_b->value.re is not NULL.
390          */
391         if (strcmp(fv_b->ftype->name, "FT_PCRE") != 0) {
392                 return FALSE;
393         }
394         if (! regex) {
395                 return FALSE;
396         }
397         TRY {
398                 tvb_len = tvb_length(tvb);
399                 data = (const char *)tvb_get_ptr(tvb, 0, tvb_len);
400                 rc = g_regex_match_full(
401                         regex,          /* Compiled PCRE */
402                         data,           /* The data to check for the pattern... */
403                         tvb_len,        /* ... and its length */
404                         0,              /* Start offset within data */
405                         0,              /* GRegexMatchFlags */
406                         NULL,           /* We are not interested in the match information */
407                         NULL            /* We don't want error information */
408                         );
409                 /* NOTE - DO NOT g_free(data) */
410         }
411         CATCH_ALL {
412                 return FALSE;
413         }
414         ENDTRY;
415         return rc;
416 }
417
418 void
419 ftype_register_tvbuff(void)
420 {
421
422         static ftype_t protocol_type = {
423                 FT_PROTOCOL,                    /* ftype */
424                 "FT_PROTOCOL",                  /* name */
425                 "Protocol",                     /* pretty_name */
426                 0,                              /* wire_size */
427                 value_new,                      /* new_value */
428                 value_free,                     /* free_value */
429                 val_from_unparsed,              /* val_from_unparsed */
430                 val_from_string,                /* val_from_string */
431                 val_to_repr,                    /* val_to_string_repr */
432                 val_repr_len,                   /* len_string_repr */
433
434                 value_set,                      /* set_value */
435                 NULL,                           /* set_value_uinteger */
436                 NULL,                           /* set_value_sinteger */
437                 NULL,                           /* set_value_integer64 */
438                 NULL,                           /* set_value_floating */
439
440                 value_get,                      /* get_value */
441                 NULL,                           /* get_value_uinteger */
442                 NULL,                           /* get_value_sinteger */
443                 NULL,                           /* get_value_integer64 */
444                 NULL,                           /* get_value_floating */
445
446                 cmp_eq,
447                 cmp_ne,
448                 cmp_gt,
449                 cmp_ge,
450                 cmp_lt,
451                 cmp_le,
452                 NULL,                           /* cmp_bitwise_and */
453                 cmp_contains,
454                 CMP_MATCHES,
455
456                 len,
457                 slice,
458
459         };
460
461
462         ftype_register(FT_PROTOCOL, &protocol_type);
463 }