aboutsummaryrefslogtreecommitdiffstats
path: root/epan/wslua/wslua_frame_info.c
blob: 091850593375a8779e04bb54ece75eab8b6486c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
/*
 * wslua_frame_info.c
 *
 * Wireshark's interface to the Lua Programming Language
 * for frame data and meta-data from a capture file.
 *
 * (c) 2014, Hadriel Kaplan <hadrielk@yahoo.com>
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "wslua_file_common.h"
#include <wsutil/ws_printf.h> /* ws_g_warning */


/* WSLUA_CONTINUE_MODULE File */


WSLUA_CLASS_DEFINE(FrameInfo,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
/*
    A FrameInfo object, passed into Lua as an argument by FileHandler callback
    functions (e.g., `read`, `seek_read`, etc.).

    This object represents frame data and meta-data (data about the frame/packet)
    for a given `read`/`seek_read`/`write`'s frame.

    This object's fields are written-to/set when used by read function callbacks, and
    read-from/get when used by file write function callbacks.  In other words, when
    the Lua plugin's FileHandler `read`/`seek_read`/etc. functions are invoked, a
    FrameInfo object will be passed in as one of the arguments, and its fields
    should be written-to/set based on the frame information read from the file;
    whereas when the Lua plugin's `FileHandler.write()` function is invoked, the
    `FrameInfo` object passed in should have its fields read-from/get, to write that
    frame information to the file.

    @since 1.11.3
 */

FrameInfo* push_FrameInfo(lua_State* L, struct wtap_pkthdr *phdr, Buffer* buf) {
    FrameInfo f = (FrameInfo) g_malloc0(sizeof(struct _wslua_phdr));
    f->phdr = phdr;
    f->buf = buf;
    f->expired = FALSE;
    return pushFrameInfo(L,f);
}

WSLUA_METAMETHOD FrameInfo__tostring(lua_State* L) {
    /* Generates a string of debug info for the FrameInfo */
    FrameInfo fi = toFrameInfo(L,1);

    if (!fi) {
        lua_pushstring(L,"FrameInfo pointer is NULL!");
    } else {
        if (fi->phdr)
            lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'",
                fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment);
        else
            lua_pushstring(L, "FrameInfo phdr pointer is NULL!");
    }

    WSLUA_RETURN(1); /* String of debug information. */
}

/* XXX: should this function be a method of File instead? */
WSLUA_METHOD FrameInfo_read_data(lua_State* L) {
    /* Tells Wireshark to read directly from given file into frame data buffer, for length bytes. Returns true if succeeded, else false. */
#define WSLUA_ARG_FrameInfo_read_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a reading-based callback. */
#define WSLUA_ARG_FrameInfo_read_data_LENGTH 3 /* The number of bytes to read from the file at the current cursor position. */
    FrameInfo fi = checkFrameInfo(L,1);
    File fh = checkFile(L,WSLUA_ARG_FrameInfo_read_data_FILE);
    guint32 len = wslua_checkguint32(L, WSLUA_ARG_FrameInfo_read_data_LENGTH);
    int err = 0;
    gchar *err_info = NULL;

    if (!fi->buf || !fh->file) {
        luaL_error(L, "FrameInfo read_data() got null buffer or file pointer internally");
        return 0;
    }

    if (!wtap_read_packet_bytes(fh->file, fi->buf, len, &err, &err_info)) {
        lua_pushboolean(L, FALSE);
        if (err_info) {
            lua_pushstring(L, err_info);
            g_free(err_info); /* is this right? */
        }
        else lua_pushnil(L);
        lua_pushnumber(L, err);
        return 3;
    }

    lua_pushboolean(L, TRUE);

    WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
}

/* free the struct we created, but not the phdr/buf it points to */
static int FrameInfo__gc(lua_State* L) {
    FrameInfo fi = toFrameInfo(L,1);
    if (fi)
        g_free(fi);
    return 0;
}

/* WSLUA_ATTRIBUTE FrameInfo_time RW The packet timestamp as an NSTime object.

    Note: Set the `FileHandler.time_precision` to the appropriate `wtap_file_tsprec` value as well.
 */
static int FrameInfo_set_time (lua_State* L) {
    FrameInfo fi = checkFrameInfo(L,1);
    NSTime nstime = checkNSTime(L,2);

    if (!fi->phdr) return 0;

    fi->phdr->ts.secs  = nstime->secs;
    fi->phdr->ts.nsecs = nstime->nsecs;

    return 0;
}

static int FrameInfo_get_time (lua_State* L) {
    FrameInfo fi = checkFrameInfo(L,1);
    NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));

    if (!nstime) return 0;

    nstime->secs  = fi->phdr->ts.secs;
    nstime->nsecs = fi->phdr->ts.nsecs;

    pushNSTime(L,nstime);

    return 1; /* An NSTime object of the frame's timestamp. */
}

/* WSLUA_ATTRIBUTE FrameInfo_data RW The data buffer containing the packet.

   @note This cannot be cleared once set.
 */
static int FrameInfo_set_data (lua_State* L) {
    FrameInfo fi = checkFrameInfo(L,1);

    if (!fi->phdr) {
        ws_g_warning("Error in FrameInfo set data: NULL pointer");
        return 0;
    }

    if (!fi->buf) {
        ws_g_warning("Error in FrameInfo set data: NULL frame_buffer pointer");
        return 0;
    }

   if (lua_isstring(L,2)) {
        size_t len = 0;
        const gchar* s = luaL_checklstring(L,2,&len);

        /* Make sure we have enough room for the packet */
        ws_buffer_assure_space(fi->buf, len);
        memcpy(ws_buffer_start_ptr(fi->buf), s, len);
        fi->phdr->caplen = (guint32) len;
        fi->phdr->len = (guint32) len;
    }
    else
        luaL_error(L, "FrameInfo's attribute 'data' must be a Lua string");

    return 0;
}

static int FrameInfo_get_data (lua_State* L) {
    FrameInfo fi = checkFrameInfo(L,1);

    if (!fi->buf) return 0;

    lua_pushlstring(L, ws_buffer_start_ptr(fi->buf), ws_buffer_length(fi->buf));

    WSLUA_RETURN(1); /* A Lua string of the frame buffer's data. */
}

/* WSLUA_ATTRIBUTE FrameInfo_rec_type RW The record type of the packet frame

    See `wtap_rec_types` in `init.lua` for values. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,rec_type,phdr->rec_type);
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,rec_type,phdr->rec_type,guint);

/* WSLUA_ATTRIBUTE FrameInfo_flags RW The presence flags of the packet frame.

    See `wtap_presence_flags` in `init.lua` for bit values. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,flags,phdr->presence_flags);
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,flags,phdr->presence_flags,guint32);

/* WSLUA_ATTRIBUTE FrameInfo_captured_length RW The captured packet length,
    and thus the length of the buffer passed to the `FrameInfo.data` field. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,captured_length,phdr->caplen);
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,captured_length,phdr->caplen,guint32);

/* WSLUA_ATTRIBUTE FrameInfo_original_length RW The on-the-wire packet length,
    which may be longer than the `captured_length`. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,original_length,phdr->len);
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,original_length,phdr->len,guint32);

/* WSLUA_ATTRIBUTE FrameInfo_encap RW The packet encapsulation type for the frame/packet,
    if the file supports per-packet types. See `wtap_encaps` in `init.lua` for possible
    packet encapsulation types to use as the value for this field. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfo,encap,phdr->pkt_encap);
WSLUA_ATTRIBUTE_NAMED_NUMBER_SETTER(FrameInfo,encap,phdr->pkt_encap,int);

/* WSLUA_ATTRIBUTE FrameInfo_comment RW A string comment for the packet, if the
    `wtap_presence_flags.COMMENTS` was set in the presence flags; nil if there is no comment. */
WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfo,comment,phdr->opt_comment);
WSLUA_ATTRIBUTE_NAMED_STRING_SETTER(FrameInfo,comment,phdr->opt_comment,TRUE);

/* This table is ultimately registered as a sub-table of the class' metatable,
 * and if __index/__newindex is invoked then it calls the appropriate function
 * from this table for getting/setting the members.
 */
WSLUA_ATTRIBUTES FrameInfo_attributes[] = {
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,rec_type),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,flags),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,captured_length),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,original_length),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,comment),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,encap),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,time),
    WSLUA_ATTRIBUTE_RWREG(FrameInfo,data),
    { NULL, NULL, NULL }
};

WSLUA_METHODS FrameInfo_methods[] = {
    WSLUA_CLASS_FNREG(FrameInfo,read_data),
    { NULL, NULL }
};

WSLUA_META FrameInfo_meta[] = {
    WSLUA_CLASS_MTREG(FrameInfo,tostring),
    { NULL, NULL }
};

int FrameInfo_register(lua_State* L) {
    WSLUA_REGISTER_CLASS(FrameInfo);
    WSLUA_REGISTER_ATTRIBUTES(FrameInfo);
    return 0;
}

WSLUA_CLASS_DEFINE(FrameInfoConst,FAIL_ON_NULL_OR_EXPIRED("FrameInfo"));
/*
    A constant FrameInfo object, passed into Lua as an argument by the FileHandler write
    callback function.  This has similar attributes/properties as FrameInfo, but the fields can
    only be read from, not written to.

    @since 1.11.3
 */

FrameInfoConst* push_FrameInfoConst(lua_State* L, const struct wtap_pkthdr *phdr, const guint8 *pd) {
    FrameInfoConst f = (FrameInfoConst) g_malloc(sizeof(struct _wslua_const_phdr));
    f->phdr = phdr;
    f->pd = pd;
    f->expired = FALSE;
    return pushFrameInfoConst(L,f);
}

WSLUA_METAMETHOD FrameInfoConst__tostring(lua_State* L) {
    /* Generates a string of debug info for the FrameInfo */
    FrameInfoConst fi = toFrameInfoConst(L,1);

    if (!fi) {
        lua_pushstring(L,"FrameInfo pointer is NULL!");
    } else {
        if (fi->phdr && !fi->expired)
            lua_pushfstring(L, "FrameInfo: rec_type=%u, presence_flags=%d, caplen=%d, len=%d, pkt_encap=%d, opt_comment='%s'",
                fi->phdr->rec_type, fi->phdr->presence_flags, fi->phdr->caplen, fi->phdr->len, fi->phdr->pkt_encap, fi->phdr->opt_comment);
        else
            lua_pushfstring(L, "FrameInfo has %s", fi->phdr?"expired":"null phdr pointer");
    }

    WSLUA_RETURN(1); /* String of debug information. */
}

/* XXX: should this function be a method of File instead? */
WSLUA_METHOD FrameInfoConst_write_data(lua_State* L) {
    /* Tells Wireshark to write directly to given file from the frame data buffer, for length bytes. Returns true if succeeded, else false. */
#define WSLUA_ARG_FrameInfoConst_write_data_FILE 2 /* The File object userdata, provided by Wireshark previously in a writing-based callback. */
#define WSLUA_OPTARG_FrameInfoConst_write_data_LENGTH 3 /* The number of bytes to write to the file at the current cursor position, or all if not supplied. */
    FrameInfoConst fi = checkFrameInfoConst(L,1);
    File fh = checkFile(L,WSLUA_ARG_FrameInfoConst_write_data_FILE);
    guint32 len = wslua_optguint32(L, WSLUA_OPTARG_FrameInfoConst_write_data_LENGTH, fi->phdr ? fi->phdr->caplen:0);
    int err = 0;

    if (!fi->pd || !fi->phdr || !fh->wdh) {
        luaL_error(L, "FrameInfoConst write_data() got null buffer or file pointer internally");
        return 0;
    }

    if (len > fi->phdr->caplen)
        len = fi->phdr->caplen;

    if (!wtap_dump_file_write(fh->wdh, fi->pd, (size_t)(len), &err)) {
        lua_pushboolean(L, FALSE);
        lua_pushfstring(L, "FrameInfoConst write_data() error: %s", g_strerror(err));
        lua_pushnumber(L, err);
        return 3;
    }

    lua_pushboolean(L, TRUE);

    WSLUA_RETURN(1); /* True if succeeded, else returns false along with the error number and string error description. */
}

/* free the struct we created, but not the wtap_pkthdr it points to */
static int FrameInfoConst__gc(lua_State* L) {
    FrameInfoConst fi = toFrameInfoConst(L,1);
    if (fi)
        g_free(fi);
    return 0;
}

/* WSLUA_ATTRIBUTE FrameInfoConst_time RO The packet timestamp as an NSTime object. */
static int FrameInfoConst_get_time (lua_State* L) {
    FrameInfoConst fi = checkFrameInfoConst(L,1);
    NSTime nstime = (NSTime)g_malloc(sizeof(nstime_t));

    if (!nstime) return 0;

    nstime->secs  = fi->phdr->ts.secs;
    nstime->nsecs = fi->phdr->ts.nsecs;

    pushNSTime(L,nstime);

    return 1; /* An NSTime object of the frame's timestamp. */
}

/* WSLUA_ATTRIBUTE FrameInfoConst_data RO The data buffer containing the packet.  */
static int FrameInfoConst_get_data (lua_State* L) {
    FrameInfoConst fi = checkFrameInfoConst(L,1);

    if (!fi->pd || !fi->phdr) return 0;

    lua_pushlstring(L, fi->pd, fi->phdr->caplen);

    return 1;
}

/* WSLUA_ATTRIBUTE FrameInfoConst_rec_type RO The record type of the packet frame - see `wtap_presence_flags` in `init.lua` for values. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,rec_type,phdr->rec_type);

/* WSLUA_ATTRIBUTE FrameInfoConst_flags RO The presence flags of the packet frame - see `wtap_presence_flags` in `init.lua` for bits. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,flags,phdr->presence_flags);

/* WSLUA_ATTRIBUTE FrameInfoConst_captured_length RO The captured packet length, and thus the length of the buffer in the FrameInfoConst.data field. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,captured_length,phdr->caplen);

/* WSLUA_ATTRIBUTE FrameInfoConst_original_length RO The on-the-wire packet length, which may be longer than the `captured_length`. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,original_length,phdr->len);

/* WSLUA_ATTRIBUTE FrameInfoConst_encap RO The packet encapsulation type, if the file supports per-packet types.

      See `wtap_encaps` in `init.lua` for possible packet encapsulation types to use as the value for this field. */
WSLUA_ATTRIBUTE_NAMED_NUMBER_GETTER(FrameInfoConst,encap,phdr->pkt_encap);

/* WSLUA_ATTRIBUTE FrameInfoConst_comment RO A comment for the packet; nil if there is none. */
WSLUA_ATTRIBUTE_NAMED_STRING_GETTER(FrameInfoConst,comment,phdr->opt_comment);

WSLUA_ATTRIBUTES FrameInfoConst_attributes[] = {
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,rec_type),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,flags),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,captured_length),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,original_length),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,encap),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,comment),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,time),
    WSLUA_ATTRIBUTE_ROREG(FrameInfoConst,data),
    { NULL, NULL, NULL }
};

WSLUA_METHODS FrameInfoConst_methods[] = {
    WSLUA_CLASS_FNREG(FrameInfoConst,write_data),
    { NULL, NULL }
};

WSLUA_META FrameInfoConst_meta[] = {
    WSLUA_CLASS_MTREG(FrameInfoConst,tostring),
    { NULL, NULL }
};

int FrameInfoConst_register(lua_State* L) {
    WSLUA_REGISTER_CLASS(FrameInfoConst);
    WSLUA_REGISTER_ATTRIBUTES(FrameInfoConst);
    return 0;
}


/*
 * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */