1 /*
2  * wslua_column.c
3  *
4  * Wireshark's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis@ontanon.org>
7  * (c) 2008, Balint Reczey <balint.reczey@ericsson.com>
8  * (c) 2011, Stig Bjorlykke <stig@bjorlykke.org>
9  * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * SPDX-License-Identifier: GPL-2.0-or-later
16  */
17 #include "config.h"
18 
19 #include "wslua_pinfo_common.h"
20 
21 
22 /* WSLUA_CONTINUE_MODULE Pinfo */
23 
24 
25 static GPtrArray* outstanding_Column = NULL;
26 static GPtrArray* outstanding_Columns = NULL;
27 
CLEAR_OUTSTANDING(Column,expired,TRUE)28 CLEAR_OUTSTANDING(Column,expired, TRUE)
29 CLEAR_OUTSTANDING(Columns,expired, TRUE)
30 
31 #define PUSH_COLUMN(L,c) {g_ptr_array_add(outstanding_Column,c);pushColumn(L,c);}
32 
33 void Push_Columns(lua_State *L, Columns c)
34 {
35     g_ptr_array_add(outstanding_Columns, c);
36     pushColumns(L, c);
37 }
38 
39 
40 WSLUA_CLASS_DEFINE(Column,FAIL_ON_NULL("Column")); /* A Column in the packet list. */
41 
42 struct col_names_t {
43     const gchar* name;
44     int id;
45 };
46 
47 // Duplicated belown in Columns__newindex.
48 static const struct col_names_t colnames[] = {
49     {"number",COL_NUMBER},
50     {"abs_time",COL_ABS_TIME},
51     {"utc_time",COL_UTC_TIME},
52     {"cls_time",COL_CLS_TIME},
53     {"rel_time",COL_REL_TIME},
54     {"date",COL_ABS_YMD_TIME},
55     {"date_doy",COL_ABS_YDOY_TIME},
56     {"utc_date",COL_UTC_YMD_TIME},
57     {"utc_date_doy",COL_UTC_YDOY_TIME},
58     {"delta_time",COL_DELTA_TIME},
59     {"delta_time_displayed",COL_DELTA_TIME_DIS},
60     {"src",COL_DEF_SRC},
61     {"src_res",COL_RES_SRC},
62     {"src_unres",COL_UNRES_SRC},
63     {"dl_src",COL_DEF_DL_SRC},
64     {"dl_src_res",COL_RES_DL_SRC},
65     {"dl_src_unres",COL_UNRES_DL_SRC},
66     {"net_src",COL_DEF_NET_SRC},
67     {"net_src_res",COL_RES_NET_SRC},
68     {"net_src_unres",COL_UNRES_NET_SRC},
69     {"dst",COL_DEF_DST},
70     {"dst_res",COL_RES_DST},
71     {"dst_unres",COL_UNRES_DST},
72     {"dl_dst",COL_DEF_DL_DST},
73     {"dl_dst_res",COL_RES_DL_DST},
74     {"dl_dst_unres",COL_UNRES_DL_DST},
75     {"net_dst",COL_DEF_NET_DST},
76     {"net_dst_res",COL_RES_NET_DST},
77     {"net_dst_unres",COL_UNRES_NET_DST},
78     {"src_port",COL_DEF_SRC_PORT},
79     {"src_port_res",COL_RES_SRC_PORT},
80     {"src_port_unres",COL_UNRES_SRC_PORT},
81     {"dst_port",COL_DEF_DST_PORT},
82     {"dst_port_res",COL_RES_DST_PORT},
83     {"dst_port_unres",COL_UNRES_DST_PORT},
84     {"protocol",COL_PROTOCOL},
85     {"info",COL_INFO},
86     {"packet_len",COL_PACKET_LENGTH},
87     {"cumulative_bytes",COL_CUMULATIVE_BYTES},
88     {"direction",COL_IF_DIR},
89     {"vsan",COL_VSAN},
90     {"tx_rate",COL_TX_RATE},
91     {"rssi",COL_RSSI},
92     {"dce_call",COL_DCE_CALL},
93     {NULL,0}
94 };
95 
col_name_to_id(const gchar * name)96 static gint col_name_to_id(const gchar* name) {
97     const struct col_names_t* cn;
98     for(cn = colnames; cn->name; cn++) {
99         if (g_str_equal(cn->name,name)) {
100             return cn->id;
101         }
102     }
103 
104     return 0;
105 }
106 
col_id_to_name(gint id)107 static const gchar*  col_id_to_name(gint id) {
108     const struct col_names_t* cn;
109     for(cn = colnames; cn->name; cn++) {
110         if ( cn->id == id ) {
111             return cn->name;
112         }
113     }
114     return NULL;
115 }
116 
117 
Column__tostring(lua_State * L)118 WSLUA_METAMETHOD Column__tostring(lua_State *L) {
119     Column c = checkColumn(L,1);
120     const gchar* text;
121 
122     if (!c->cinfo) {
123         text = col_id_to_name(c->col);
124         lua_pushfstring(L, "(%s)", text ? text : "unknown");
125     }
126     else {
127         text = col_get_text(c->cinfo, c->col);
128         lua_pushstring(L, text ? text : "(nil)");
129     }
130 
131     WSLUA_RETURN(1); /* The column's string text (in parenthesis if not available). */
132 }
133 
134 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS */
Column__gc(lua_State * L)135 static int Column__gc(lua_State* L) {
136     Column col = toColumn(L,1);
137 
138     if (!col) return 0;
139 
140     if (!col->expired)
141         col->expired = TRUE;
142     else
143         g_free(col);
144 
145     return 0;
146 
147 }
148 
Column_clear(lua_State * L)149 WSLUA_METHOD Column_clear(lua_State *L) {
150     /* Clears a Column. */
151     Column c = checkColumn(L,1);
152 
153     if (!(c->cinfo)) return 0;
154 
155     col_clear(c->cinfo, c->col);
156 
157     return 0;
158 }
159 
Column_set(lua_State * L)160 WSLUA_METHOD Column_set(lua_State *L) {
161     /* Sets the text of a Column. */
162 #define WSLUA_ARG_Column_set_TEXT 2 /* The text to which to set the Column. */
163     Column c = checkColumn(L,1);
164     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_set_TEXT);
165 
166     if (!(c->cinfo))
167         return 0;
168 
169     col_add_str(c->cinfo, c->col, s);
170 
171     return 0;
172 }
173 
Column_append(lua_State * L)174 WSLUA_METHOD Column_append(lua_State *L) {
175     /* Appends text to a Column. */
176 #define WSLUA_ARG_Column_append_TEXT 2 /* The text to append to the Column. */
177     Column c = checkColumn(L,1);
178     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_append_TEXT);
179 
180     if (!(c->cinfo))
181         return 0;
182 
183     col_append_str(c->cinfo, c->col, s);
184 
185     return 0;
186 }
187 
Column_prepend(lua_State * L)188 WSLUA_METHOD Column_prepend(lua_State *L) {
189     /* Prepends text to a Column. */
190 #define WSLUA_ARG_Column_prepend_TEXT 2 /* The text to prepend to the Column. */
191     Column c = checkColumn(L,1);
192     const gchar* s = luaL_checkstring(L,WSLUA_ARG_Column_prepend_TEXT);
193 
194     if (!(c->cinfo))
195         return 0;
196 
197     col_prepend_fstr(c->cinfo, c->col, "%s",s);
198 
199     return 0;
200 }
201 
Column_fence(lua_State * L)202 WSLUA_METHOD Column_fence(lua_State *L) {
203     /* Sets Column text fence, to prevent overwriting.
204 
205        @since 1.10.6
206      */
207     Column c = checkColumn(L,1);
208 
209     if (c->cinfo)
210         col_set_fence(c->cinfo, c->col);
211 
212     return 0;
213 }
214 
Column_clear_fence(lua_State * L)215 WSLUA_METHOD Column_clear_fence(lua_State *L) {
216     /* Clear Column text fence.
217 
218        @since 1.11.3
219      */
220     Column c = checkColumn(L,1);
221 
222     if (c->cinfo)
223         col_clear_fence(c->cinfo, c->col);
224 
225     return 0;
226 }
227 
228 
229 WSLUA_METHODS Column_methods[] = {
230     WSLUA_CLASS_FNREG(Column,clear),
231     WSLUA_CLASS_FNREG(Column,set),
232     WSLUA_CLASS_FNREG(Column,append),
233     WSLUA_CLASS_FNREG(Column,prepend),
234     WSLUA_CLASS_FNREG_ALIAS(Column,preppend,prepend),
235     WSLUA_CLASS_FNREG(Column,fence),
236     WSLUA_CLASS_FNREG(Column,clear_fence),
237     { NULL, NULL }
238 };
239 
240 
241 WSLUA_META Column_meta[] = {
242     WSLUA_CLASS_MTREG(Column,tostring),
243     { NULL, NULL }
244 };
245 
246 
Column_register(lua_State * L)247 int Column_register(lua_State *L) {
248     WSLUA_REGISTER_CLASS(Column);
249     outstanding_Column = g_ptr_array_new();
250     return 0;
251 }
252 
253 
254 WSLUA_CLASS_DEFINE(Columns,NOP); /* The <<lua_class_Column,``Column``>>s of the packet list. */
255 
Columns__tostring(lua_State * L)256 WSLUA_METAMETHOD Columns__tostring(lua_State *L) {
257     lua_pushstring(L,"Columns");
258     WSLUA_RETURN(1);
259     /* The string "Columns". This has no real use aside from debugging. */
260 }
261 
262 /*
263  * To document this is very odd - it won't make sense to a person reading the
264  * API docs to see this metamethod as a method, but oh well.
265  */
Columns__newindex(lua_State * L)266 WSLUA_METAMETHOD Columns__newindex(lua_State *L) { /*
267     Sets the text of a specific column.
268     Some columns cannot be modified, and no error is raised if attempted.
269     The columns that are known to allow modification are "info" and "protocol".
270     */
271 #define WSLUA_ARG_Columns__newindex_COLUMN 2 /*
272     The name of the column to set.
273     Valid values are:
274 
275     [options="header"]
276     |===
277     |Name |Description
278     |number |Frame number
279     |abs_time |Absolute timestamp
280     |utc_time |UTC timestamp
281     |cls_time |CLS timestamp
282     |rel_time |Relative timestamp
283     |date |Absolute date and time
284     |date_doy |Absolute year, day of year, and time
285     |utc_date |UTC date and time
286     |utc_date_doy |UTC year, day of year, and time
287     |delta_time |Delta time from previous packet
288     |delta_time_displayed |Delta time from previous displayed packet
289     |src |Source address
290     |src_res |Resolved source address
291     |src_unres |Numeric source address
292     |dl_src |Source data link address
293     |dl_src_res |Resolved source data link address
294     |dl_src_unres |Numeric source data link address
295     |net_src |Source network address
296     |net_src_res |Resolved source network address
297     |net_src_unres |Numeric source network address
298     |dst |Destination address
299     |dst_res |Resolve destination address
300     |dst_unres |Numeric destination address
301     |dl_dst |Destination data link address
302     |dl_dst_res |Resolved destination data link address
303     |dl_dst_unres |Numeric destination data link address
304     |net_dst |Destination network address
305     |net_dst_res |Resolved destination network address
306     |net_dst_unres |Numeric destination network address
307     |src_port |Source port
308     |src_port_res |Resolved source port
309     |src_port_unres |Numeric source port
310     |dst_port |Destination port
311     |dst_port_res |Resolved destination port
312     |dst_port_unres |Numeric destination port
313     |protocol |Protocol name
314     |info |General packet information
315     |packet_len |Packet length
316     |cumulative_bytes |Cumulative bytes in the capture
317     |direction |Packet direction
318     |vsan |Virtual SAN
319     |tx_rate |Transmit rate
320     |rssi |RSSI value
321     |dce_call |DCE call
322     |===
323 
324     ===== Example
325     pinfo.cols['info'] = 'foo bar'
326 
327     -- syntactic sugar (equivalent to above)
328     pinfo.cols.info = 'foo bar'
329     */
330 #define WSLUA_ARG_Columns__newindex_TEXT 3 /* The text for the column. */
331     Columns cols = checkColumns(L,1);
332     const struct col_names_t* cn;
333     const char* colname;
334     const char* text;
335 
336     if (!cols) return 0;
337     if (cols->expired) {
338         luaL_error(L,"expired column");
339         return 0;
340     }
341 
342     colname = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_COLUMN);
343     text = luaL_checkstring(L,WSLUA_ARG_Columns__newindex_TEXT);
344 
345     for(cn = colnames; cn->name; cn++) {
346         if( g_str_equal(cn->name,colname) ) {
347             col_add_str(cols->cinfo, cn->id, text);
348             return 0;
349         }
350     }
351 
352     WSLUA_ARG_ERROR(Columns__newindex,COLUMN,"the column name must be a valid column");
353     return 0;
354 }
355 
Columns__index(lua_State * L)356 WSLUA_METAMETHOD Columns__index(lua_State *L) {
357     /* Get a specific <<lua_class_Column,``Column``>>. */
358     Columns cols = checkColumns(L,1);
359     const struct col_names_t* cn;
360     const char* colname = luaL_checkstring(L,2);
361 
362     if (!cols) {
363         Column c = (Column)g_malloc(sizeof(struct _wslua_col_info));
364         c->cinfo = NULL;
365         c->col = col_name_to_id(colname);
366         c->expired = FALSE;
367 
368         PUSH_COLUMN(L,c);
369         return 1;
370     }
371 
372 
373     if (cols->expired) {
374         luaL_error(L,"expired column");
375         return 0;
376     }
377 
378     for(cn = colnames; cn->name; cn++) {
379         if( g_str_equal(cn->name,colname) ) {
380             Column c = (Column)g_malloc(sizeof(struct _wslua_col_info));
381             c->cinfo = cols->cinfo;
382             c->col = col_name_to_id(colname);
383             c->expired = FALSE;
384 
385             PUSH_COLUMN(L,c);
386             return 1;
387         }
388     }
389 
390     return 0;
391 }
392 
393 /* for internal use - used by Pinfo */
get_Columns_index(lua_State * L)394 int get_Columns_index(lua_State *L)
395 {
396     return Columns__index(L);
397 }
398 
399 
400 /* Gets registered as metamethod automatically by WSLUA_REGISTER_META */
Columns__gc(lua_State * L)401 static int Columns__gc(lua_State* L) {
402     Columns cols = toColumns(L,1);
403 
404     if (!cols) return 0;
405 
406     if (!cols->expired)
407         cols->expired = TRUE;
408     else
409         g_free(cols);
410 
411     return 0;
412 
413 }
414 
415 
416 WSLUA_META Columns_meta[] = {
417     WSLUA_CLASS_MTREG(Columns,tostring),
418     WSLUA_CLASS_MTREG(Columns,newindex),
419     WSLUA_CLASS_MTREG(Columns,index),
420     { NULL, NULL }
421 };
422 
423 
Columns_register(lua_State * L)424 int Columns_register(lua_State *L) {
425     WSLUA_REGISTER_META(Columns);
426     outstanding_Columns = g_ptr_array_new();
427     return 0;
428 }
429 
430 
431 
432 /*
433  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
434  *
435  * Local variables:
436  * c-basic-offset: 4
437  * tab-width: 8
438  * indent-tabs-mode: nil
439  * End:
440  *
441  * vi: set shiftwidth=4 tabstop=8 expandtab:
442  * :indentSize=4:tabSize=8:noTabs=true:
443  */
444