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
|
/*
* exported_pdu.c
* exported_pdu helper functions
* Copyright 2013, Anders Broman <anders-broman@ericsson.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib.h>
#include <epan/packet.h>
#include <epan/exported_pdu.h>
#include <epan/address_types.h>
#include <epan/tap.h>
#include <wiretap/wtap.h>
#include <wsutil/pint.h>
static GSList *export_pdu_tap_name_list = NULL;
static wmem_map_t *export_pdu_encap_table = NULL;
static int exp_pdu_data_ip_size(const address* addr)
{
if (addr->type == AT_IPv4){
return 4 + EXP_PDU_TAG_IPV4_LEN;
} else if(addr->type == AT_IPv6){
return 4 + EXP_PDU_TAG_IPV6_LEN;
}
return 0;
}
static int exp_pdu_data_src_ip_size(packet_info *pinfo, void* data _U_)
{
return exp_pdu_data_ip_size(&pinfo->net_src);
}
static int exp_pdu_data_src_ip_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
if(pinfo->net_src.type == AT_IPv4){
phton16(tlv_buffer+0, EXP_PDU_TAG_IPV4_SRC);
phton16(tlv_buffer+2, EXP_PDU_TAG_IPV4_LEN); /* tag length */
memcpy(tlv_buffer+4, pinfo->net_src.data, EXP_PDU_TAG_IPV4_LEN);
return 4 + EXP_PDU_TAG_IPV4_LEN;
}else if(pinfo->net_src.type == AT_IPv6){
phton16(tlv_buffer+0, EXP_PDU_TAG_IPV6_SRC);
phton16(tlv_buffer+2, EXP_PDU_TAG_IPV6_LEN); /* tag length */
memcpy(tlv_buffer+4, pinfo->net_src.data, EXP_PDU_TAG_IPV6_LEN);
return 4 + EXP_PDU_TAG_IPV6_LEN;
}
return 0;
}
static int exp_pdu_data_dst_ip_size(packet_info *pinfo, void* data _U_)
{
return exp_pdu_data_ip_size(&pinfo->net_dst);
}
static int exp_pdu_data_dst_ip_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
if(pinfo->net_dst.type == AT_IPv4){
phton16(tlv_buffer+0, EXP_PDU_TAG_IPV4_DST);
phton16(tlv_buffer+2, EXP_PDU_TAG_IPV4_LEN); /* tag length */
memcpy(tlv_buffer+4, pinfo->net_dst.data, EXP_PDU_TAG_IPV4_LEN);
return 4 + EXP_PDU_TAG_IPV4_LEN;
}else if(pinfo->net_dst.type == AT_IPv6){
phton16(tlv_buffer+0, EXP_PDU_TAG_IPV6_DST);
phton16(tlv_buffer+2, EXP_PDU_TAG_IPV6_LEN); /* tag length */
memcpy(tlv_buffer+4, pinfo->net_dst.data, EXP_PDU_TAG_IPV6_LEN);
return 4 + EXP_PDU_TAG_IPV6_LEN;
}
return 0;
}
static int exp_pdu_data_port_type_size(packet_info *pinfo _U_, void* data _U_)
{
return EXP_PDU_TAG_PORT_LEN + 4;
}
static guint exp_pdu_ws_port_type_to_exp_pdu_port_type(port_type pt)
{
switch (pt)
{
case PT_NONE:
return EXP_PDU_PT_NONE;
case PT_SCTP:
return EXP_PDU_PT_SCTP;
case PT_TCP:
return EXP_PDU_PT_TCP;
case PT_UDP:
return EXP_PDU_PT_UDP;
case PT_DCCP:
return EXP_PDU_PT_DCCP;
case PT_IPX:
return EXP_PDU_PT_IPX;
case PT_DDP:
return EXP_PDU_PT_DDP;
case PT_IDP:
return EXP_PDU_PT_IDP;
case PT_USB:
return EXP_PDU_PT_USB;
case PT_I2C:
return EXP_PDU_PT_I2C;
case PT_IBQP:
return EXP_PDU_PT_IBQP;
case PT_BLUETOOTH:
return EXP_PDU_PT_BLUETOOTH;
case PT_IWARP_MPA:
return EXP_PDU_PT_IWARP_MPA;
case PT_MCTP:
return EXP_PDU_PT_MCTP;
}
DISSECTOR_ASSERT(FALSE);
return EXP_PDU_PT_NONE;
}
static int exp_pdu_data_port_type_populate_data(packet_info *pinfo, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
guint pt;
phton16(tlv_buffer+0, EXP_PDU_TAG_PORT_TYPE);
phton16(tlv_buffer+2, EXP_PDU_TAG_PORT_TYPE_LEN); /* tag length */
pt = exp_pdu_ws_port_type_to_exp_pdu_port_type(pinfo->ptype);
phton32(tlv_buffer+4, pt);
return exp_pdu_data_port_type_size(pinfo, data);
}
static int exp_pdu_data_port_size(packet_info *pinfo _U_, void* data _U_)
{
return EXP_PDU_TAG_PORT_LEN + 4;
}
static int exp_pdu_data_port_populate_data(guint32 port, guint8 porttype, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
phton16(tlv_buffer+0, porttype);
phton16(tlv_buffer+2, EXP_PDU_TAG_PORT_LEN); /* tag length */
phton32(tlv_buffer+4, port);
return EXP_PDU_TAG_PORT_LEN + 4;
}
static int exp_pdu_data_src_port_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size)
{
return exp_pdu_data_port_populate_data(pinfo->srcport, EXP_PDU_TAG_SRC_PORT, tlv_buffer, buffer_size);
}
static int exp_pdu_data_dst_port_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size)
{
return exp_pdu_data_port_populate_data(pinfo->destport, EXP_PDU_TAG_DST_PORT, tlv_buffer, buffer_size);
}
static int exp_pdu_data_orig_frame_num_size(packet_info *pinfo _U_, void* data _U_)
{
return EXP_PDU_TAG_ORIG_FNO_LEN + 4;
}
static int exp_pdu_data_orig_frame_num_populate_data(packet_info *pinfo, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
phton16(tlv_buffer+0, EXP_PDU_TAG_ORIG_FNO);
phton16(tlv_buffer+2, EXP_PDU_TAG_ORIG_FNO_LEN); /* tag length */
phton32(tlv_buffer+4, pinfo->num);
return exp_pdu_data_orig_frame_num_size(pinfo, data);
}
WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_size(packet_info *pinfo _U_, void* data _U_)
{
return EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN + 4;
}
WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_populate_data(packet_info *pinfo _U_, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_)
{
guint32 value = GPOINTER_TO_UINT(data);
phton16(tlv_buffer+0, EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL);
phton16(tlv_buffer+2, EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN); /* tag length */
phton32(tlv_buffer+4, value);
return exp_pdu_data_dissector_table_num_value_size(pinfo, data);
}
exp_pdu_data_item_t exp_pdu_data_src_ip = {exp_pdu_data_src_ip_size, exp_pdu_data_src_ip_populate_data, NULL};
exp_pdu_data_item_t exp_pdu_data_dst_ip = {exp_pdu_data_dst_ip_size, exp_pdu_data_dst_ip_populate_data, NULL};
exp_pdu_data_item_t exp_pdu_data_port_type = {exp_pdu_data_port_type_size, exp_pdu_data_port_type_populate_data, NULL};
exp_pdu_data_item_t exp_pdu_data_src_port = {exp_pdu_data_port_size, exp_pdu_data_src_port_populate_data, NULL};
exp_pdu_data_item_t exp_pdu_data_dst_port = {exp_pdu_data_port_size, exp_pdu_data_dst_port_populate_data, NULL};
exp_pdu_data_item_t exp_pdu_data_orig_frame_num = {exp_pdu_data_orig_frame_num_size, exp_pdu_data_orig_frame_num_populate_data, NULL};
exp_pdu_data_t *export_pdu_create_common_tags(packet_info *pinfo, const char *proto_name, guint16 tag_type)
{
const exp_pdu_data_item_t *common_exp_pdu_items[] = {
&exp_pdu_data_src_ip,
&exp_pdu_data_dst_ip,
&exp_pdu_data_port_type,
&exp_pdu_data_src_port,
&exp_pdu_data_dst_port,
&exp_pdu_data_orig_frame_num,
NULL
};
return export_pdu_create_tags(pinfo, proto_name, tag_type, common_exp_pdu_items);
}
/**
* Allocates and fills the exp_pdu_data_t struct according to the list of items
*
* The tags in the tag buffer SHOULD be added in numerical order.
*/
exp_pdu_data_t *
export_pdu_create_tags(packet_info *pinfo, const char* proto_name, guint16 tag_type, const exp_pdu_data_item_t **items_list)
{
exp_pdu_data_t *exp_pdu_data;
const exp_pdu_data_item_t **loop_items = items_list;
int tag_buf_size = 0;
int proto_str_len, proto_tag_len, buf_remaining, item_size;
guint8* buffer_data;
DISSECTOR_ASSERT(proto_name != NULL);
DISSECTOR_ASSERT((tag_type == EXP_PDU_TAG_DISSECTOR_NAME) || (tag_type == EXP_PDU_TAG_HEUR_DISSECTOR_NAME) || (tag_type == EXP_PDU_TAG_DISSECTOR_TABLE_NAME));
exp_pdu_data = wmem_new(pinfo->pool, exp_pdu_data_t);
/* Start by computing size of protocol name as a tag */
proto_str_len = (int)strlen(proto_name);
/* Ensure that tag length is a multiple of 4 bytes */
proto_tag_len = ((proto_str_len + 3) & 0xfffffffc);
/* Add Tag + length */
tag_buf_size += (proto_tag_len + 4);
/* Compute size of items */
while (*loop_items) {
tag_buf_size += (*loop_items)->size_func(pinfo, (*loop_items)->data);
loop_items++;
}
/* Add end of options length */
tag_buf_size+=4;
exp_pdu_data->tlv_buffer = (guint8 *)wmem_alloc0(pinfo->pool, tag_buf_size);
exp_pdu_data->tlv_buffer_len = tag_buf_size;
buffer_data = exp_pdu_data->tlv_buffer;
buf_remaining = exp_pdu_data->tlv_buffer_len;
/* Start by adding protocol name as a tag */
phton16(buffer_data+0, tag_type);
phton16(buffer_data+2, proto_tag_len); /* tag length */
memcpy(buffer_data+4, proto_name, proto_str_len);
buffer_data += (proto_tag_len+4);
buf_remaining -= (proto_tag_len+4);
/* Populate data */
loop_items = items_list;
while (*loop_items) {
item_size = (*loop_items)->populate_data(pinfo, (*loop_items)->data, buffer_data, buf_remaining);
buffer_data += item_size;
buf_remaining -= item_size;
loop_items++;
}
return exp_pdu_data;
}
gint
register_export_pdu_tap_with_encap(const char *name, gint encap)
{
gchar *tap_name = g_strdup(name);
export_pdu_tap_name_list = g_slist_prepend(export_pdu_tap_name_list, tap_name);
wmem_map_insert(export_pdu_encap_table, tap_name, GINT_TO_POINTER(encap));
return register_tap(tap_name);
}
gint
register_export_pdu_tap(const char *name)
{
#if 0
/* XXX: We could register it like this, but don't have to, since
* export_pdu_tap_get_encap() returns WTAP_ENCAP_WIRESHARK_UPPER_PDU
* if it's not in the encap hash table anyway.
*/
return register_export_pdu_tap_with_encap(name, WTAP_ENCAP_WIRESHARK_UPPER_PDU);
#endif
gchar *tap_name = g_strdup(name);
export_pdu_tap_name_list = g_slist_prepend(export_pdu_tap_name_list, tap_name);
return register_tap(tap_name);
}
static
gint sort_pdu_tap_name_list(gconstpointer a, gconstpointer b)
{
return g_strcmp0((const char *)a, (const char*)b);
}
GSList *
get_export_pdu_tap_list(void)
{
export_pdu_tap_name_list = g_slist_sort(export_pdu_tap_name_list, sort_pdu_tap_name_list);
return export_pdu_tap_name_list;
}
gint
export_pdu_tap_get_encap(const char* name)
{
gpointer value;
if (wmem_map_lookup_extended(export_pdu_encap_table, name, NULL, &value)) {
return GPOINTER_TO_INT(value);
}
return WTAP_ENCAP_WIRESHARK_UPPER_PDU;
}
void export_pdu_init(void)
{
export_pdu_encap_table = wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal);
}
void export_pdu_cleanup(void)
{
g_slist_free_full(export_pdu_tap_name_list, g_free);
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/
|