Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / epan / ftypes / ftype-tvbuff.c
1 /*
2  * $Id$
3  *
4  * Ethereal - Network traffic analyzer
5  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <ftypes-int.h>
28 #include <string.h>
29 #include <epan/gdebug.h>
30
31 #ifdef HAVE_LIBPCRE
32 #include <pcre.h>
33 #define CMP_MATCHES cmp_matches
34 #else
35 #define CMP_MATCHES NULL
36 #endif
37
38 #define tvb_is_private  fvalue_gboolean1
39
40 static void
41 value_new(fvalue_t *fv)
42 {
43         fv->value.tvb = NULL;
44         fv->tvb_is_private = FALSE;
45 }
46
47 static void
48 value_free(fvalue_t *fv)
49 {
50         if (fv->value.tvb && fv->tvb_is_private) {
51                 tvb_free_chain(fv->value.tvb);
52         }
53 }
54
55 static void
56 value_set(fvalue_t *fv, gpointer value, gboolean already_copied)
57 {
58         g_assert(already_copied);
59
60         /* Free up the old value, if we have one */
61         value_free(fv);
62
63         fv->value.tvb = value;
64 }
65
66 static void
67 free_tvb_data(void *data)
68 {
69         g_free(data);
70 }
71
72 static gboolean
73 val_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
74 {
75         tvbuff_t *new_tvb;
76         guint8 *private_data;
77
78         /* Free up the old value, if we have one */
79         value_free(fv);
80
81         /* Make a tvbuff from the string. We can drop the
82          * terminating NUL. */
83         private_data = g_memdup(s, strlen(s)); 
84         new_tvb = tvb_new_real_data(private_data, 
85                         strlen(s), strlen(s));
86
87         /* Let the tvbuff know how to delete the data. */
88         tvb_set_free_cb(new_tvb, free_tvb_data);
89
90         /* And let us know that we need to free the tvbuff */
91         fv->tvb_is_private = TRUE;
92         fv->value.tvb = new_tvb;
93         return TRUE;
94 }
95
96 static gboolean
97 val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
98 {
99         fvalue_t *fv_bytes;
100         tvbuff_t *new_tvb;
101         guint8 *private_data;
102
103         /* Free up the old value, if we have one */
104         value_free(fv);
105
106         /* Does this look like a byte string? */
107         fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL);
108         if (fv_bytes) {
109                 /* Make a tvbuff from the bytes */
110                 private_data = g_memdup(fv_bytes->value.bytes->data,
111                                 fv_bytes->value.bytes->len);
112                 new_tvb = tvb_new_real_data(private_data, 
113                                 fv_bytes->value.bytes->len,
114                                 fv_bytes->value.bytes->len);
115
116                 /* Let the tvbuff know how to delete the data. */
117                 tvb_set_free_cb(new_tvb, free_tvb_data);
118
119                 /* And let us know that we need to free the tvbuff */
120                 fv->tvb_is_private = TRUE;
121                 fv->value.tvb = new_tvb;
122                 return TRUE;
123         }
124         else {
125                 /* Treat it as a string. */
126                 return val_from_string(fv, s, logfunc);
127         }
128         g_assert_not_reached();
129 }
130
131 static gpointer
132 value_get(fvalue_t *fv)
133 {
134         return fv->value.tvb;
135 }
136
137 static guint
138 len(fvalue_t *fv)
139 {
140         if (fv->value.tvb)
141                 return tvb_length(fv->value.tvb);
142         else
143                 return 0;
144 }
145
146 static void
147 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
148 {
149         const guint8* data;
150
151         if (fv->value.tvb) {
152                 TRY {
153                         data = tvb_get_ptr(fv->value.tvb, offset, length);
154                         g_byte_array_append(bytes, data, length);
155                 }
156                 CATCH_ALL {
157                         /* nothing */
158                 }
159                 ENDTRY;
160
161         }
162 }
163
164 static gboolean
165 cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
166 {
167         if (tvb_find_tvb(fv_a->value.tvb, fv_b->value.tvb, 0) > -1) {
168                 return TRUE;
169         }
170         else {
171                 return FALSE;
172         }
173 }
174
175 #ifdef HAVE_LIBPCRE
176 static gboolean
177 cmp_matches(fvalue_t *fv_a, fvalue_t *fv_b)
178 {
179         tvbuff_t *tvb = fv_a->value.tvb;
180         pcre_tuple_t *pcre = fv_b->value.re;
181         int options = 0;
182         int rc;
183         const char *data = NULL; /* tvb data */
184         guint32 tvb_len; /* tvb length */
185
186         /* fv_b is always a FT_PCRE, otherwise the dfilter semcheck() would have
187          * warned us. For the same reason (and because we're using g_malloc()),
188          * fv_b->value.re is not NULL.
189          */
190         if (strcmp(fv_b->ftype->name, "FT_PCRE") != 0) {
191                 return FALSE;
192         }
193         if (! pcre) {
194                 return FALSE;
195         }
196         TRY {
197                 tvb_len = tvb_length(tvb);
198                 data = (const char *)tvb_get_ptr(tvb, 0, tvb_len);
199                 rc = pcre_exec(
200                         pcre->re,       /* Compiled PCRE */
201                         pcre->ex,       /* PCRE extra from pcre_study() */
202                         data,           /* The data to check for the pattern... */
203                         tvb_len,        /* ... and its length */
204                         0,                      /* Start offset within data */
205                         options,        /* PCRE options */
206                         NULL,           /* We are not interested in the matched string */
207                         0                       /* of the pattern; only in success or failure. */
208                         );
209                 /* NOTE - DO NOT g_free(data) */
210         }
211         CATCH_ALL {
212                 return FALSE;
213         }
214         ENDTRY;
215         if (rc == 0) {
216                 return TRUE;
217         }
218         return FALSE;
219 }
220 #endif
221
222 void
223 ftype_register_tvbuff(void)
224 {
225
226         static ftype_t protocol_type = {
227                 "FT_PROTOCOL",                  /* name */
228                 "protocol",                     /* pretty_name */
229                 0,                              /* wire_size */
230                 value_new,                      /* new_value */
231                 value_free,                     /* free_value */
232                 val_from_unparsed,              /* val_from_unparsed */
233                 val_from_string,                /* val_from_string */
234                 NULL,                           /* val_to_string_repr */
235                 NULL,                           /* len_string_repr */
236
237                 value_set,
238                 NULL,
239                 NULL,
240
241                 value_get,
242                 NULL,
243                 NULL,
244
245
246                 /* TODO - tvb's *can* do 'eq', etc. */
247
248                 NULL,                           /* cmp_eq */
249                 NULL,                           /* cmp_ne */
250                 NULL,                           /* cmp_gt */
251                 NULL,                           /* cmp_ge */
252                 NULL,                           /* cmp_lt */
253                 NULL,                           /* cmp_le */
254                 NULL,                           /* cmp_bitwise_and */
255                 cmp_contains,
256                 CMP_MATCHES,
257
258                 len,
259                 slice,
260
261         };
262
263
264         ftype_register(FT_PROTOCOL, &protocol_type);
265 }