Fixed FieldInfo documentation.
[metze/wireshark/wip.git] / epan / wslua / wslua_field.c
1 /*
2  *  wslua_field.c
3  *
4  * Wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  */
28
29 #include "config.h"
30
31 /* WSLUA_MODULE Field Obtaining dissection data */
32
33 #include "wslua.h"
34
35 WSLUA_CLASS_DEFINE(FieldInfo,NOP,NOP);
36 /*
37    An extracted Field
38    */
39
40 WSLUA_METAMETHOD FieldInfo__len(lua_State* L) {
41     /*
42        Obtain the Length of the field
43        */
44     FieldInfo fi = checkFieldInfo(L,1);
45     lua_pushnumber(L,fi->length);
46     return 1;
47 }
48
49 WSLUA_METAMETHOD FieldInfo__unm(lua_State* L) {
50     /*
51        Obtain the Offset of the field
52        */
53     FieldInfo fi = checkFieldInfo(L,1);
54     lua_pushnumber(L,fi->start);
55     return 1;
56 }
57
58 WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
59     /*
60        Obtain the Value of the field
61        */
62     FieldInfo fi = checkFieldInfo(L,1);
63
64     switch(fi->hfinfo->type) {
65         case FT_BOOLEAN:
66                 lua_pushboolean(L,(int)fvalue_get_uinteger(&(fi->value)));
67                 return 1;
68         case FT_UINT8:
69         case FT_UINT16:
70         case FT_UINT24:
71         case FT_UINT32:
72         case FT_FRAMENUM:
73                 lua_pushnumber(L,(lua_Number)fvalue_get_uinteger(&(fi->value)));
74                 return 1;
75         case FT_INT8:
76         case FT_INT16:
77         case FT_INT24:
78         case FT_INT32:
79                 lua_pushnumber(L,(lua_Number)fvalue_get_sinteger(&(fi->value)));
80                 return 1;
81         case FT_FLOAT:
82         case FT_DOUBLE:
83                 lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->value)));
84                 return 1;
85         case FT_INT64: {
86                 Int64 num = (Int64)g_malloc(sizeof(gint64));
87                 *num = fvalue_get_integer64(&(fi->value));
88                 pushInt64(L,num);
89                 return 1;
90             }
91         case FT_UINT64: {
92                 UInt64 num = (UInt64)g_malloc(sizeof(guint64));
93                 *num = fvalue_get_integer64(&(fi->value));
94                 pushUInt64(L,num);
95                 return 1;
96             }
97         case FT_ETHER: {
98                 Address eth = (Address)g_malloc(sizeof(address));
99                 eth->type = AT_ETHER;
100                 eth->len = fi->length;
101                 eth->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
102                 pushAddress(L,eth);
103                 return 1;
104             }
105         case FT_IPv4:{
106                 Address ipv4 = (Address)g_malloc(sizeof(address));
107                 ipv4->type = AT_IPv4;
108                 ipv4->len = fi->length;
109                 ipv4->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
110                 pushAddress(L,ipv4);
111                 return 1;
112             }
113         case FT_IPv6: {
114                 Address ipv6 = (Address)g_malloc(sizeof(address));
115                 ipv6->type = AT_IPv6;
116                 ipv6->len = fi->length;
117                 ipv6->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
118                 pushAddress(L,ipv6);
119                 return 1;
120             }
121         case FT_IPXNET:{
122                 Address ipx = (Address)g_malloc(sizeof(address));
123                 ipx->type = AT_IPX;
124                 ipx->len = fi->length;
125                 ipx->data = tvb_memdup(fi->ds_tvb,fi->start,fi->length);
126                 pushAddress(L,ipx);
127                 return 1;
128             }
129         case FT_ABSOLUTE_TIME:
130         case FT_RELATIVE_TIME: {
131                 NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));
132                 *nstime = *(NSTime)fvalue_get(&(fi->value));
133                 pushNSTime(L,nstime);
134                 return 1;
135             }
136         case FT_STRING:
137         case FT_STRINGZ: {
138                 gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL);
139                 if (repr)
140                     lua_pushstring(L,repr);
141                 else
142                     luaL_error(L,"field cannot be represented as string because it may contain invalid characters");
143
144                 return 1;
145             }
146         case FT_NONE:
147                 if (fi->length == 0) {
148                         lua_pushnil(L);
149                         return 1;
150                 }
151                 /* FALLTHROUGH */
152         case FT_BYTES:
153         case FT_UINT_BYTES:
154         case FT_GUID:
155         case FT_PROTOCOL:
156         case FT_OID: {
157                 ByteArray ba = g_byte_array_new();
158                 g_byte_array_append(ba, (const guint8 *)ep_tvb_memdup(fi->ds_tvb,fi->start,fi->length),fi->length);
159                 pushByteArray(L,ba);
160                 return 1;
161             }
162         default:
163                 luaL_error(L,"FT_ not yet supported");
164                 return 1;
165     }
166 }
167
168 WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
169     /* The string representation of the field */
170     FieldInfo fi = checkFieldInfo(L,1);
171
172     if (!fi) {
173         return luaL_error(L,"Missing FieldInfo object");
174     }
175
176     if (fi->value.ftype->val_to_string_repr) {
177         gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL);
178         if (repr) {
179             lua_pushstring(L,repr);
180         }
181         else {
182             lua_pushstring(L,"(unknown)");
183         }
184     }
185     else if (fi->hfinfo->type == FT_NONE) {
186         lua_pushstring(L, "(none)");
187     }
188     else {
189         lua_pushstring(L,"(n/a)");
190     }
191
192     return 1;
193 }
194
195 static int FieldInfo_display(lua_State* L) {
196     /* The display string of this field as seen in GUI */
197     FieldInfo fi = checkFieldInfo(L,1);
198     gchar         label_str[ITEM_LABEL_LENGTH+1];
199     gchar        *label_ptr;
200     gchar        *value_ptr;
201
202     if (!fi) return 0;
203
204     if (!fi->rep) {
205         label_ptr = label_str;
206         proto_item_fill_label(fi, label_str);
207     } else 
208         label_ptr = fi->rep->representation;
209
210     if (!label_ptr) return 0;
211
212     value_ptr = strstr(label_ptr, ": ");
213     if (!value_ptr) {
214         /* just use whatever's there */
215         lua_pushstring(L, label_ptr);
216     } else {
217         value_ptr += 2;  /* get past the ': ' */
218         lua_pushstring(L, value_ptr);
219     }
220
221     return 1;
222 }
223
224 static int FieldInfo_get_range(lua_State* L) {
225     /* The TvbRange covering this field */
226     FieldInfo fi = checkFieldInfo(L,1);
227     TvbRange r = ep_new(struct _wslua_tvbrange);
228     r->tvb = ep_new(struct _wslua_tvb);
229
230     r->tvb->ws_tvb = fi->ds_tvb;
231     r->tvb->expired = FALSE;
232     r->tvb->need_free = FALSE;
233     r->offset = fi->start;
234     r->len = fi->length;
235
236     pushTvbRange(L,r);
237     return 1;
238 }
239
240 static int FieldInfo_get_generated(lua_State* L) {
241     /* Whether this field was marked as generated. */
242     FieldInfo fi = checkFieldInfo(L,1);
243     lua_pushboolean(L,FI_GET_FLAG(fi, FI_GENERATED));
244     return 1;
245 }
246
247 static int FieldInfo_get_name(lua_State* L) {
248     /* The filter name of this field. */
249     FieldInfo fi = checkFieldInfo(L,1);
250     lua_pushstring(L,fi->hfinfo->abbrev);
251     return 1;
252 }
253
254 static const luaL_Reg FieldInfo_get[] = {
255     /*    {"data_source", FieldInfo_get_data_source }, */
256     {"range", FieldInfo_get_range},
257     /*    {"hidden", FieldInfo_get_hidden}, */
258     {"generated", FieldInfo_get_generated},
259
260     /* WSLUA_ATTRIBUTE FieldInfo_name RO The name of this field */
261     {"name", FieldInfo_get_name},
262     /* WSLUA_ATTRIBUTE FieldInfo_label RO The string representing this field */
263     {"label", FieldInfo__tostring},
264     /* WSLUA_ATTRIBUTE FieldInfo_value RO The value of this field */
265     {"value", FieldInfo__call},
266     /* WSLUA_ATTRIBUTE FieldInfo_tvb RO A tvbrange covering this field */
267     {"tvb", FieldInfo_get_range},
268     /* WSLUA_ATTRIBUTE FieldInfo_len RO The length of this field */
269     {"len", FieldInfo__len},
270     /* WSLUA_ATTRIBUTE FieldInfo_offset RO The offset of this field */
271     {"offset", FieldInfo__unm},
272     /* WSLUA_ATTRIBUTE FieldInfo_display RO The string display of this field as seen in GUI */
273     {"display", FieldInfo_display},
274     { NULL, NULL }
275 };
276
277 static int FieldInfo__index(lua_State* L) {
278     /*
279        Other attributes:
280        */
281     const gchar* idx = luaL_checkstring(L,2);
282     const luaL_Reg* r;
283
284     checkFieldInfo(L,1);
285
286     for (r = FieldInfo_get; r->name; r++) {
287         if (g_str_equal(r->name, idx)) {
288             return r->func(L);
289         }
290     }
291
292     return 0;
293 }
294
295 WSLUA_METAMETHOD FieldInfo__eq(lua_State* L) {
296     /* Checks whether lhs is within rhs */
297     FieldInfo l = checkFieldInfo(L,1);
298     FieldInfo r = checkFieldInfo(L,2);
299
300     if (l->ds_tvb != r->ds_tvb)
301         WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
302
303     if (l->start <= r->start && r->start + r->length <= l->start + r->length) {
304         lua_pushboolean(L,1);
305         return 1;
306     } else {
307         return 0;
308     }
309 }
310
311 WSLUA_METAMETHOD FieldInfo__le(lua_State* L) {
312     /* Checks whether the end byte of lhs is before the end of rhs */
313     FieldInfo l = checkFieldInfo(L,1);
314     FieldInfo r = checkFieldInfo(L,2);
315
316     if (l->ds_tvb != r->ds_tvb)
317         WSLUA_ERROR(FieldInfo__le,"Data source must be the same for both fields");
318
319     if (r->start + r->length <= l->start + r->length) {
320         lua_pushboolean(L,1);
321         return 1;
322     } else {
323         return 0;
324     }
325 }
326
327 WSLUA_METAMETHOD FieldInfo__lt(lua_State* L) {
328     /* Checks whether the end byte of rhs is before the beginning of rhs */
329     FieldInfo l = checkFieldInfo(L,1);
330     FieldInfo r = checkFieldInfo(L,2);
331
332     if (l->ds_tvb != r->ds_tvb)
333         WSLUA_ERROR(FieldInfo__lt,"Data source must be the same for both fields");
334
335     if ( r->start + r->length < l->start ) {
336         lua_pushboolean(L,1);
337         return 1;
338     } else {
339         return 0;
340     }
341 }
342
343 static int FieldInfo__gc(lua_State* L _U_) {
344     /* do NOT free FieldInfo */
345     return 0;
346 }
347
348 static const luaL_Reg FieldInfo_meta[] = {
349     {"__tostring", FieldInfo__tostring},
350     {"__call", FieldInfo__call},
351     {"__index", FieldInfo__index},
352     {"__len", FieldInfo__len},
353     {"__unm", FieldInfo__unm},
354     {"__eq", FieldInfo__eq},
355     {"__le", FieldInfo__le},
356     {"__lt", FieldInfo__lt},
357     { NULL, NULL }
358 };
359
360 int FieldInfo_register(lua_State* L) {
361     WSLUA_REGISTER_META(FieldInfo);
362     return 1;
363 }
364
365
366 WSLUA_FUNCTION wslua_all_field_infos(lua_State* L) {
367     /*
368     Obtain all fields from the current tree.  Note this only gets whatever fields the underlying
369     dissectors have filled in for this packet at this time - there may be fields applicable to
370     the packet that simply aren't being filled in because at this time they're not needed for anything.
371     This function only gets what the C-side code has currently populated, not the full list.
372     */
373     GPtrArray* found;
374     int items_found = 0;
375     guint i;
376
377     if (! lua_tree || ! lua_tree->tree ) {
378         WSLUA_ERROR(wslua_all_field_infos,"Cannot be called outside a listener or dissector");
379     }
380
381     found = proto_all_finfos(lua_tree->tree);
382
383     if (found) {
384         for (i=0; i<found->len; i++) {
385             pushFieldInfo(L,(FieldInfo)g_ptr_array_index(found,i));
386             items_found++;
387         }
388
389         g_ptr_array_free(found,TRUE);
390     }
391
392     return items_found;
393 }
394
395 WSLUA_CLASS_DEFINE(Field,NOP,NOP);
396 /*
397    A Field extractor to to obtain field values.
398  */
399
400 static GPtrArray* wanted_fields = NULL;
401 static dfilter_t* wslua_dfilter = NULL;
402
403 /* We use a fake dfilter for Lua field extractors, so that 
404  * epan_dissect_run() will populate the fields.  This won't happen
405  * if the passed-in edt->tree is NULL, which it will be if the 
406  * proto_tree isn't created by epan_dissect_init().  But that's by
407  * design - if shark doesn't pass in a proto_tree, it's probably for
408  * a good reason and we shouldn't override that. (right?)
409  */
410 void wslua_prime_dfilter(epan_dissect_t *edt) {
411     if (wslua_dfilter && edt && edt->tree) {
412         dfilter_prime_proto_tree(wslua_dfilter, edt->tree);
413     }
414 }
415
416 /*
417  * field extractor registartion is tricky, In order to allow
418  * the user to define them in the body of the script we will
419  * populate the Field value with a pointer of the abbrev of it
420  * to later replace it with the hfi.
421  *
422  * This will be added to the wanted_fields array that will
423  * exists only while they can be defined, and be cleared right
424  * after the fields are primed.
425  */
426
427 void lua_prime_all_fields(proto_tree* tree _U_) {
428     GString* fake_tap_filter = g_string_new("frame");
429     guint i;
430     static gboolean fake_tap = FALSE;
431
432     for(i=0; i < wanted_fields->len; i++) {
433         Field f = (Field)g_ptr_array_index(wanted_fields,i);
434         gchar* name = *((gchar**)f);
435
436         *f = proto_registrar_get_byname(name);
437
438         if (!*f) {
439             report_failure("Could not find field `%s'",name);
440             *f = NULL;
441             g_free(name);
442             continue;
443         }
444
445         g_free(name);
446
447         g_string_append_printf(fake_tap_filter," || %s",(*f)->abbrev);
448         fake_tap = TRUE;
449     }
450
451     g_ptr_array_free(wanted_fields,TRUE);
452     wanted_fields = NULL;
453
454     if (fake_tap) {
455         /* a boring tap :-) */
456         GString* error = register_tap_listener("frame",
457                 &fake_tap,
458                 fake_tap_filter->str,
459                 0, /* XXX - do we need the protocol tree or columns? */
460                 NULL, NULL, NULL);
461
462         if (error) {
463             report_failure("while registering lua_fake_tap:\n%s",error->str);
464             g_string_free(error,TRUE);
465         }
466         else if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter)) {
467             report_failure("while compiling dfilter for wslua: '%s'", fake_tap_filter->str);
468         }
469     }
470
471 }
472
473 WSLUA_CONSTRUCTOR Field_new(lua_State *L) {
474     /*
475        Create a Field extractor
476        */
477 #define WSLUA_ARG_Field_new_FIELDNAME 1 /* The filter name of the field (e.g. ip.addr) */
478     const gchar* name = luaL_checkstring(L,WSLUA_ARG_Field_new_FIELDNAME);
479     Field f;
480
481     if (!name) return 0;
482
483     if (!proto_registrar_get_byname(name))
484         WSLUA_ARG_ERROR(Field_new,FIELDNAME,"a field with this name must exist");
485
486     if (!wanted_fields)
487         WSLUA_ERROR(Field_new,"A Field extractor must be defined before Taps or Dissectors get called");
488
489     f = (Field)g_malloc(sizeof(void*));
490     *f = (header_field_info*)g_strdup(name); /* cheating */
491
492     g_ptr_array_add(wanted_fields,f);
493
494     pushField(L,f);
495     WSLUA_RETURN(1); /* The field extractor */
496 }
497
498 WSLUA_METAMETHOD Field__call (lua_State* L) {
499     /* Obtain all values (see FieldInfo) for this field. */
500     Field f = checkField(L,1);
501     header_field_info* in = *f;
502     int items_found = 0;
503
504     if (! in) {
505         luaL_error(L,"invalid field");
506         return 0;
507     }
508
509     if (! lua_pinfo ) {
510         WSLUA_ERROR(Field__call,"Fields cannot be used outside dissectors or taps");
511     }
512
513     while (in) {
514         GPtrArray* found = proto_get_finfo_ptr_array(lua_tree->tree, in->id);
515         guint i;
516         if (found) {
517             for (i=0; i<found->len; i++) {
518                 pushFieldInfo(L,(FieldInfo)g_ptr_array_index(found,i));
519                 items_found++;
520             }
521         }
522         in = (in->same_name_prev_id != -1) ? proto_registrar_get_nth(in->same_name_prev_id) : NULL;
523     }
524
525     WSLUA_RETURN(items_found); /* All the values of this field */
526 }
527
528 WSLUA_METAMETHOD Field__tostring(lua_State* L) {
529         /* Obtain a string with the field name */
530     Field f = checkField(L,1);
531
532     if ( !(f && *f) ) {
533         luaL_error(L,"invalid Field");
534         return 0;
535     }
536
537     if (wanted_fields) {
538         lua_pushstring(L,*((gchar**)f));
539     } else {
540         lua_pushstring(L,(*f)->abbrev);
541     }
542
543     return 1;
544 }
545
546 static int Field__gc(lua_State* L _U_) {
547     /* do NOT free Field */
548     return 0;
549 }
550
551 static const luaL_Reg Field_methods[] = {
552     {"new", Field_new},
553     { NULL, NULL }
554 };
555
556 static const luaL_Reg Field_meta[] = {
557     {"__tostring", Field__tostring},
558     {"__call", Field__call},
559     { NULL, NULL }
560 };
561
562 int Field_register(lua_State* L) {
563
564     wanted_fields = g_ptr_array_new();
565
566     WSLUA_REGISTER_CLASS(Field);
567
568     return 1;
569 }
570
571 /*
572  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
573  *
574  * Local variables:
575  * c-basic-offset: 4
576  * tab-width: 8
577  * indent-tabs-mode: nil
578  * End:
579  *
580  * vi: set shiftwidth=4 tabstop=8 expandtab:
581  * :indentSize=4:tabSize=8:noTabs=true:
582  */