HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / wslua / wslua_field.c
blobe81d74f726615f91fdb7d9fdd90f0deda14d23a9
1 /*
2 * wslua_field.c
4 * Wireshark's interface to the Lua Programming Language
6 * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
8 * $Id$
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
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.
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.
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.
29 #include "config.h"
31 #include <epan/emem.h>
32 #include <epan/ftypes/ftypes-int.h>
34 /* WSLUA_MODULE Field Obtaining dissection data */
36 #include "wslua.h"
38 WSLUA_CLASS_DEFINE(FieldInfo,NOP,NOP);
40 An extracted Field
43 WSLUA_METAMETHOD FieldInfo__len(lua_State* L) {
45 Obtain the Length of the field
47 FieldInfo fi = checkFieldInfo(L,1);
48 lua_pushnumber(L,fi->length);
49 return 1;
52 WSLUA_METAMETHOD FieldInfo__unm(lua_State* L) {
54 Obtain the Offset of the field
56 FieldInfo fi = checkFieldInfo(L,1);
57 lua_pushnumber(L,fi->start);
58 return 1;
61 WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
63 Obtain the Value of the field
65 FieldInfo fi = checkFieldInfo(L,1);
67 switch(fi->hfinfo->type) {
68 case FT_BOOLEAN:
69 lua_pushboolean(L,(int)fvalue_get_uinteger(&(fi->value)));
70 return 1;
71 case FT_UINT8:
72 case FT_UINT16:
73 case FT_UINT24:
74 case FT_UINT32:
75 case FT_FRAMENUM:
76 lua_pushnumber(L,(lua_Number)fvalue_get_uinteger(&(fi->value)));
77 return 1;
78 case FT_INT8:
79 case FT_INT16:
80 case FT_INT24:
81 case FT_INT32:
82 lua_pushnumber(L,(lua_Number)fvalue_get_sinteger(&(fi->value)));
83 return 1;
84 case FT_FLOAT:
85 case FT_DOUBLE:
86 lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->value)));
87 return 1;
88 case FT_INT64: {
89 Int64 num = (Int64)g_malloc(sizeof(gint64));
90 *num = fvalue_get_integer64(&(fi->value));
91 pushInt64(L,num);
92 return 1;
94 case FT_UINT64: {
95 UInt64 num = (UInt64)g_malloc(sizeof(guint64));
96 *num = fvalue_get_integer64(&(fi->value));
97 pushUInt64(L,num);
98 return 1;
100 case FT_ETHER: {
101 Address eth = (Address)g_malloc(sizeof(address));
102 eth->type = AT_ETHER;
103 eth->len = fi->length;
104 eth->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length);
105 pushAddress(L,eth);
106 return 1;
108 case FT_IPv4:{
109 Address ipv4 = (Address)g_malloc(sizeof(address));
110 ipv4->type = AT_IPv4;
111 ipv4->len = fi->length;
112 ipv4->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length);
113 pushAddress(L,ipv4);
114 return 1;
116 case FT_IPv6: {
117 Address ipv6 = (Address)g_malloc(sizeof(address));
118 ipv6->type = AT_IPv6;
119 ipv6->len = fi->length;
120 ipv6->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length);
121 pushAddress(L,ipv6);
122 return 1;
124 case FT_IPXNET:{
125 Address ipx = (Address)g_malloc(sizeof(address));
126 ipx->type = AT_IPX;
127 ipx->len = fi->length;
128 ipx->data = tvb_memdup(NULL,fi->ds_tvb,fi->start,fi->length);
129 pushAddress(L,ipx);
130 return 1;
132 case FT_ABSOLUTE_TIME:
133 case FT_RELATIVE_TIME: {
134 NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));
135 *nstime = *(NSTime)fvalue_get(&(fi->value));
136 pushNSTime(L,nstime);
137 return 1;
139 case FT_STRING:
140 case FT_STRINGZ: {
141 gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL);
142 if (repr)
143 lua_pushstring(L,repr);
144 else
145 luaL_error(L,"field cannot be represented as string because it may contain invalid characters");
147 return 1;
149 case FT_NONE:
150 if (fi->length == 0) {
151 lua_pushnil(L);
152 return 1;
154 /* FALLTHROUGH */
155 case FT_BYTES:
156 case FT_UINT_BYTES:
157 case FT_GUID:
158 case FT_PROTOCOL:
159 case FT_REL_OID:
160 case FT_OID: {
161 ByteArray ba = g_byte_array_new();
162 g_byte_array_append(ba, (const guint8 *)tvb_memdup(wmem_packet_scope(),fi->ds_tvb,fi->start,fi->length),fi->length);
163 pushByteArray(L,ba);
164 return 1;
166 default:
167 luaL_error(L,"FT_ not yet supported");
168 return 1;
172 WSLUA_METAMETHOD FieldInfo__tostring(lua_State* L) {
173 /* The string representation of the field */
174 FieldInfo fi = checkFieldInfo(L,1);
176 if (!fi) {
177 return luaL_error(L,"Missing FieldInfo object");
180 if (fi->value.ftype->val_to_string_repr) {
181 gchar* repr = fvalue_to_string_repr(&fi->value,FTREPR_DISPLAY,NULL);
182 if (repr) {
183 lua_pushstring(L,repr);
185 else {
186 lua_pushstring(L,"(unknown)");
189 else if (fi->hfinfo->type == FT_NONE) {
190 lua_pushstring(L, "(none)");
192 else {
193 lua_pushstring(L,"(n/a)");
196 return 1;
199 static int FieldInfo_display(lua_State* L) {
200 /* The display string of this field as seen in GUI */
201 FieldInfo fi = checkFieldInfo(L,1);
202 gchar label_str[ITEM_LABEL_LENGTH+1];
203 gchar *label_ptr;
204 gchar *value_ptr;
206 if (!fi) return 0;
208 if (!fi->rep) {
209 label_ptr = label_str;
210 proto_item_fill_label(fi, label_str);
211 } else
212 label_ptr = fi->rep->representation;
214 if (!label_ptr) return 0;
216 value_ptr = strstr(label_ptr, ": ");
217 if (!value_ptr) {
218 /* just use whatever's there */
219 lua_pushstring(L, label_ptr);
220 } else {
221 value_ptr += 2; /* get past the ': ' */
222 lua_pushstring(L, value_ptr);
225 return 1;
228 static int FieldInfo_get_range(lua_State* L) {
229 /* The TvbRange covering this field */
230 FieldInfo fi = checkFieldInfo(L,1);
231 TvbRange r = ep_new(struct _wslua_tvbrange);
232 r->tvb = ep_new(struct _wslua_tvb);
234 r->tvb->ws_tvb = fi->ds_tvb;
235 r->tvb->expired = FALSE;
236 r->tvb->need_free = FALSE;
237 r->offset = fi->start;
238 r->len = fi->length;
240 pushTvbRange(L,r);
241 return 1;
244 static int FieldInfo_get_generated(lua_State* L) {
245 /* Whether this field was marked as generated. */
246 FieldInfo fi = checkFieldInfo(L,1);
247 lua_pushboolean(L,FI_GET_FLAG(fi, FI_GENERATED));
248 return 1;
251 static int FieldInfo_get_name(lua_State* L) {
252 /* The filter name of this field. */
253 FieldInfo fi = checkFieldInfo(L,1);
254 lua_pushstring(L,fi->hfinfo->abbrev);
255 return 1;
258 static const luaL_Reg FieldInfo_get[] = {
259 /* {"data_source", FieldInfo_get_data_source }, */
260 {"range", FieldInfo_get_range},
261 /* {"hidden", FieldInfo_get_hidden}, */
262 {"generated", FieldInfo_get_generated},
264 /* WSLUA_ATTRIBUTE FieldInfo_name RO The name of this field */
265 {"name", FieldInfo_get_name},
266 /* WSLUA_ATTRIBUTE FieldInfo_label RO The string representing this field */
267 {"label", FieldInfo__tostring},
268 /* WSLUA_ATTRIBUTE FieldInfo_value RO The value of this field */
269 {"value", FieldInfo__call},
270 /* WSLUA_ATTRIBUTE FieldInfo_tvb RO A tvbrange covering this field */
271 {"tvb", FieldInfo_get_range},
272 /* WSLUA_ATTRIBUTE FieldInfo_len RO The length of this field */
273 {"len", FieldInfo__len},
274 /* WSLUA_ATTRIBUTE FieldInfo_offset RO The offset of this field */
275 {"offset", FieldInfo__unm},
276 /* WSLUA_ATTRIBUTE FieldInfo_display RO The string display of this field as seen in GUI */
277 {"display", FieldInfo_display},
278 { NULL, NULL }
281 static int FieldInfo__index(lua_State* L) {
283 Other attributes:
285 const gchar* idx = luaL_checkstring(L,2);
286 const luaL_Reg* r;
288 checkFieldInfo(L,1);
290 for (r = FieldInfo_get; r->name; r++) {
291 if (g_str_equal(r->name, idx)) {
292 return r->func(L);
296 return 0;
299 WSLUA_METAMETHOD FieldInfo__eq(lua_State* L) {
300 /* Checks whether lhs is within rhs */
301 FieldInfo l = checkFieldInfo(L,1);
302 FieldInfo r = checkFieldInfo(L,2);
304 if (l->ds_tvb != r->ds_tvb)
305 WSLUA_ERROR(FieldInfo__eq,"Data source must be the same for both fields");
307 if (l->start <= r->start && r->start + r->length <= l->start + r->length) {
308 lua_pushboolean(L,1);
309 return 1;
310 } else {
311 return 0;
315 WSLUA_METAMETHOD FieldInfo__le(lua_State* L) {
316 /* Checks whether the end byte of lhs is before the end of rhs */
317 FieldInfo l = checkFieldInfo(L,1);
318 FieldInfo r = checkFieldInfo(L,2);
320 if (l->ds_tvb != r->ds_tvb)
321 WSLUA_ERROR(FieldInfo__le,"Data source must be the same for both fields");
323 if (r->start + r->length <= l->start + r->length) {
324 lua_pushboolean(L,1);
325 return 1;
326 } else {
327 return 0;
331 WSLUA_METAMETHOD FieldInfo__lt(lua_State* L) {
332 /* Checks whether the end byte of rhs is before the beginning of rhs */
333 FieldInfo l = checkFieldInfo(L,1);
334 FieldInfo r = checkFieldInfo(L,2);
336 if (l->ds_tvb != r->ds_tvb)
337 WSLUA_ERROR(FieldInfo__lt,"Data source must be the same for both fields");
339 if ( r->start + r->length < l->start ) {
340 lua_pushboolean(L,1);
341 return 1;
342 } else {
343 return 0;
347 static int FieldInfo__gc(lua_State* L _U_) {
348 /* do NOT free FieldInfo */
349 return 0;
352 static const luaL_Reg FieldInfo_meta[] = {
353 {"__tostring", FieldInfo__tostring},
354 {"__call", FieldInfo__call},
355 {"__index", FieldInfo__index},
356 {"__len", FieldInfo__len},
357 {"__unm", FieldInfo__unm},
358 {"__eq", FieldInfo__eq},
359 {"__le", FieldInfo__le},
360 {"__lt", FieldInfo__lt},
361 { NULL, NULL }
364 int FieldInfo_register(lua_State* L) {
365 WSLUA_REGISTER_META(FieldInfo);
366 return 1;
370 WSLUA_FUNCTION wslua_all_field_infos(lua_State* L) {
372 Obtain all fields from the current tree. Note this only gets whatever fields the underlying
373 dissectors have filled in for this packet at this time - there may be fields applicable to
374 the packet that simply aren't being filled in because at this time they're not needed for anything.
375 This function only gets what the C-side code has currently populated, not the full list.
377 GPtrArray* found;
378 int items_found = 0;
379 guint i;
381 if (! lua_tree || ! lua_tree->tree ) {
382 WSLUA_ERROR(wslua_all_field_infos,"Cannot be called outside a listener or dissector");
385 found = proto_all_finfos(lua_tree->tree);
387 if (found) {
388 for (i=0; i<found->len; i++) {
389 pushFieldInfo(L,(FieldInfo)g_ptr_array_index(found,i));
390 items_found++;
393 g_ptr_array_free(found,TRUE);
396 return items_found;
399 WSLUA_CLASS_DEFINE(Field,NOP,NOP);
401 A Field extractor to to obtain field values.
404 static GPtrArray* wanted_fields = NULL;
405 static dfilter_t* wslua_dfilter = NULL;
407 /* We use a fake dfilter for Lua field extractors, so that
408 * epan_dissect_run() will populate the fields. This won't happen
409 * if the passed-in edt->tree is NULL, which it will be if the
410 * proto_tree isn't created by epan_dissect_init(). But that's by
411 * design - if shark doesn't pass in a proto_tree, it's probably for
412 * a good reason and we shouldn't override that. (right?)
414 void wslua_prime_dfilter(epan_dissect_t *edt) {
415 if (wslua_dfilter && edt && edt->tree) {
416 dfilter_prime_proto_tree(wslua_dfilter, edt->tree);
421 * field extractor registartion is tricky, In order to allow
422 * the user to define them in the body of the script we will
423 * populate the Field value with a pointer of the abbrev of it
424 * to later replace it with the hfi.
426 * This will be added to the wanted_fields array that will
427 * exists only while they can be defined, and be cleared right
428 * after the fields are primed.
431 void lua_prime_all_fields(proto_tree* tree _U_) {
432 GString* fake_tap_filter = g_string_new("frame");
433 guint i;
434 static gboolean fake_tap = FALSE;
436 for(i=0; i < wanted_fields->len; i++) {
437 Field f = (Field)g_ptr_array_index(wanted_fields,i);
438 gchar* name = *((gchar**)f);
440 *f = proto_registrar_get_byname(name);
442 if (!*f) {
443 report_failure("Could not find field `%s'",name);
444 *f = NULL;
445 g_free(name);
446 continue;
449 g_free(name);
451 g_string_append_printf(fake_tap_filter," || %s",(*f)->abbrev);
452 fake_tap = TRUE;
455 g_ptr_array_free(wanted_fields,TRUE);
456 wanted_fields = NULL;
458 if (fake_tap) {
459 /* a boring tap :-) */
460 GString* error = register_tap_listener("frame",
461 &fake_tap,
462 fake_tap_filter->str,
463 0, /* XXX - do we need the protocol tree or columns? */
464 NULL, NULL, NULL);
466 if (error) {
467 report_failure("while registering lua_fake_tap:\n%s",error->str);
468 g_string_free(error,TRUE);
470 else if (!dfilter_compile(fake_tap_filter->str, &wslua_dfilter)) {
471 report_failure("while compiling dfilter for wslua: '%s'", fake_tap_filter->str);
477 WSLUA_CONSTRUCTOR Field_new(lua_State *L) {
479 Create a Field extractor
481 #define WSLUA_ARG_Field_new_FIELDNAME 1 /* The filter name of the field (e.g. ip.addr) */
482 const gchar* name = luaL_checkstring(L,WSLUA_ARG_Field_new_FIELDNAME);
483 Field f;
485 if (!name) return 0;
487 if (!proto_registrar_get_byname(name) && !wslua_is_field_available(L, name))
488 WSLUA_ARG_ERROR(Field_new,FIELDNAME,"a field with this name must exist");
490 if (!wanted_fields)
491 WSLUA_ERROR(Field_new,"A Field extractor must be defined before Taps or Dissectors get called");
493 f = (Field)g_malloc(sizeof(void*));
494 *f = (header_field_info*)g_strdup(name); /* cheating */
496 g_ptr_array_add(wanted_fields,f);
498 pushField(L,f);
499 WSLUA_RETURN(1); /* The field extractor */
502 WSLUA_METAMETHOD Field__call (lua_State* L) {
503 /* Obtain all values (see FieldInfo) for this field. */
504 Field f = checkField(L,1);
505 header_field_info* in = *f;
506 int items_found = 0;
508 if (! in) {
509 luaL_error(L,"invalid field");
510 return 0;
513 if (! lua_pinfo ) {
514 WSLUA_ERROR(Field__call,"Fields cannot be used outside dissectors or taps");
517 while (in) {
518 GPtrArray* found = proto_get_finfo_ptr_array(lua_tree->tree, in->id);
519 guint i;
520 if (found) {
521 for (i=0; i<found->len; i++) {
522 pushFieldInfo(L,(FieldInfo)g_ptr_array_index(found,i));
523 items_found++;
526 in = (in->same_name_prev_id != -1) ? proto_registrar_get_nth(in->same_name_prev_id) : NULL;
529 WSLUA_RETURN(items_found); /* All the values of this field */
532 WSLUA_METAMETHOD Field__tostring(lua_State* L) {
533 /* Obtain a string with the field name */
534 Field f = checkField(L,1);
536 if ( !(f && *f) ) {
537 luaL_error(L,"invalid Field");
538 return 0;
541 if (wanted_fields) {
542 lua_pushstring(L,*((gchar**)f));
543 } else {
544 lua_pushstring(L,(*f)->abbrev);
547 return 1;
550 static int Field__gc(lua_State* L _U_) {
551 /* do NOT free Field */
552 return 0;
555 static const luaL_Reg Field_methods[] = {
556 {"new", Field_new},
557 { NULL, NULL }
560 static const luaL_Reg Field_meta[] = {
561 {"__tostring", Field__tostring},
562 {"__call", Field__call},
563 { NULL, NULL }
566 int Field_register(lua_State* L) {
568 wanted_fields = g_ptr_array_new();
570 WSLUA_REGISTER_CLASS(Field);
572 return 1;
576 * Editor modelines - http://www.wireshark.org/tools/modelines.html
578 * Local variables:
579 * c-basic-offset: 4
580 * tab-width: 8
581 * indent-tabs-mode: nil
582 * End:
584 * vi: set shiftwidth=4 tabstop=8 expandtab:
585 * :indentSize=4:tabSize=8:noTabs=true: