aboutsummaryrefslogtreecommitdiffstats
path: root/epan/exported_pdu.c
blob: d1f80a32881fac19cf70d05727f648991ccb7b70 (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
/*
 * 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
 *
 * 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 "config.h"
#include <glib.h>

#include <epan/packet.h>
#include <epan/exported_pdu.h>
#include <epan/address_types.h>
#include <epan/tap.h>

static GSList *export_pdu_tap_name_list = 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){
		tlv_buffer[0] = 0;
		tlv_buffer[1] = EXP_PDU_TAG_IPV4_SRC;
		tlv_buffer[2] = 0;
		tlv_buffer[3] = 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){
		tlv_buffer[0] = 0;
		tlv_buffer[1] = EXP_PDU_TAG_IPV6_SRC;
		tlv_buffer[2] = 0;
		tlv_buffer[3] = 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){
		tlv_buffer[0] = 0;
		tlv_buffer[1] = EXP_PDU_TAG_IPV4_DST;
		tlv_buffer[2] = 0;
		tlv_buffer[3] = 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){
		tlv_buffer[0] = 0;
		tlv_buffer[1] = EXP_PDU_TAG_IPV6_DST;
		tlv_buffer[2] = 0;
		tlv_buffer[3] = 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_new_to_old_port_type(port_type pt)
{
	switch (pt)
	{
	case PT_NONE:
		return OLD_PT_NONE;
	case PT_SCTP:
		return OLD_PT_SCTP;
	case PT_TCP:
		return OLD_PT_TCP;
	case PT_UDP:
		return OLD_PT_UDP;
	case PT_DCCP:
		return OLD_PT_DCCP;
	case PT_IPX:
		return OLD_PT_IPX;
	case PT_DDP:
		return OLD_PT_DDP;
	case PT_IDP:
		return OLD_PT_IDP;
	case PT_USB:
		return OLD_PT_USB;
	case PT_I2C:
		return OLD_PT_I2C;
	case PT_IBQP:
		return OLD_PT_IBQP;
	case PT_BLUETOOTH:
		return OLD_PT_BLUETOOTH;
	}

	DISSECTOR_ASSERT(FALSE);
	return OLD_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;

	tlv_buffer[0] = 0;
	tlv_buffer[1] = EXP_PDU_TAG_PORT_TYPE;
	tlv_buffer[2] = 0;
	tlv_buffer[3] = EXP_PDU_TAG_PORT_TYPE_LEN; /* tag length */
	pt = exp_pdu_new_to_old_port_type(pinfo->ptype);
	tlv_buffer[4] = (pt & 0xff000000) >> 24;
	tlv_buffer[5] = (pt & 0x00ff0000) >> 16;
	tlv_buffer[6] = (pt & 0x0000ff00) >> 8;
	tlv_buffer[7] = (pt & 0x000000ff);

	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_)
{
	tlv_buffer[0] = 0;
	tlv_buffer[1] = porttype;
	tlv_buffer[2] = 0;
	tlv_buffer[3] = EXP_PDU_TAG_PORT_LEN; /* tag length */
	tlv_buffer[4] = (port & 0xff000000) >> 24;
	tlv_buffer[5] = (port & 0x00ff0000) >> 16;
	tlv_buffer[6] = (port & 0x0000ff00) >> 8;
	tlv_buffer[7] = (port & 0x000000ff);

	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_)
{
	tlv_buffer[0] = 0;
	tlv_buffer[1] = EXP_PDU_TAG_ORIG_FNO;
	tlv_buffer[2] = 0;
	tlv_buffer[3] = EXP_PDU_TAG_ORIG_FNO_LEN; /* tag length */
	tlv_buffer[4] = (pinfo->num & 0xff000000) >> 24;
	tlv_buffer[5] = (pinfo->num & 0x00ff0000) >> 16;
	tlv_buffer[6] = (pinfo->num & 0x0000ff00) >> 8;
	tlv_buffer[7] = (pinfo->num & 0x000000ff);

	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);

	tlv_buffer[0] = 0;
	tlv_buffer[1] = EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL;
	tlv_buffer[2] = 0;
	tlv_buffer[3] = EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN; /* tag length */
	tlv_buffer[4] = (value & 0xff000000) >> 24;
	tlv_buffer[5] = (value & 0x00ff0000) >> 16;
	tlv_buffer[6] = (value & 0x0000ff00) >> 8;
	tlv_buffer[7] = (value & 0x000000ff);

	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_PROTO_NAME) || (tag_type == EXP_PDU_TAG_HEUR_PROTO_NAME) || (tag_type == EXP_PDU_TAG_DISSECTOR_TABLE_NAME));

	exp_pdu_data = (exp_pdu_data_t *)g_malloc(sizeof(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 *)g_malloc0(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 */
	buffer_data[0] = (tag_type & 0xff00) >> 8;
	buffer_data[1] = tag_type & 0x00ff;
	buffer_data[2] = (proto_tag_len & 0xff00) >> 8;
	buffer_data[3] = proto_tag_len & 0x00ff; /* 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(const char *name)
{
	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;
}

void export_pdu_init(void)
{
}

static void
free_list_element(gpointer elem, gpointer data _U_)
{
	g_free(elem);
}

void export_pdu_cleanup(void)
{
	g_slist_foreach(export_pdu_tap_name_list, free_list_element, NULL);
	g_slist_free(export_pdu_tap_name_list);
}

/*
 * Editor modelines  -  http://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:
 */