1 /*
2  * exported_pdu.c
3  * exported_pdu helper functions
4  * Copyright 2013, Anders Broman <anders-broman@ericsson.com>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 #include <glib.h>
15 
16 #include <epan/packet.h>
17 #include <epan/exported_pdu.h>
18 #include <epan/address_types.h>
19 #include <epan/tap.h>
20 
21 #include <wsutil/pint.h>
22 
23 static GSList *export_pdu_tap_name_list = NULL;
24 
exp_pdu_data_ip_size(const address * addr)25 static int exp_pdu_data_ip_size(const address* addr)
26 {
27 	if (addr->type == AT_IPv4){
28 		return 4 + EXP_PDU_TAG_IPV4_LEN;
29 	} else if(addr->type == AT_IPv6){
30 		return 4 + EXP_PDU_TAG_IPV6_LEN;
31 	}
32 
33 	return 0;
34 }
35 
exp_pdu_data_src_ip_size(packet_info * pinfo,void * data _U_)36 static int exp_pdu_data_src_ip_size(packet_info *pinfo, void* data _U_)
37 {
38 	return exp_pdu_data_ip_size(&pinfo->net_src);
39 }
40 
exp_pdu_data_src_ip_populate_data(packet_info * pinfo,void * data _U_,guint8 * tlv_buffer,guint32 buffer_size _U_)41 static int exp_pdu_data_src_ip_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size _U_)
42 {
43 	if(pinfo->net_src.type == AT_IPv4){
44 		phton16(tlv_buffer+0, EXP_PDU_TAG_IPV4_SRC);
45 		phton16(tlv_buffer+2, EXP_PDU_TAG_IPV4_LEN); /* tag length */
46 		memcpy(tlv_buffer+4, pinfo->net_src.data, EXP_PDU_TAG_IPV4_LEN);
47 		return 4 + EXP_PDU_TAG_IPV4_LEN;
48 	}else if(pinfo->net_src.type == AT_IPv6){
49 		phton16(tlv_buffer+0, EXP_PDU_TAG_IPV6_SRC);
50 		phton16(tlv_buffer+2, EXP_PDU_TAG_IPV6_LEN); /* tag length */
51 		memcpy(tlv_buffer+4, pinfo->net_src.data, EXP_PDU_TAG_IPV6_LEN);
52 		return 4 + EXP_PDU_TAG_IPV6_LEN;
53 	}
54 
55 	return 0;
56 }
57 
exp_pdu_data_dst_ip_size(packet_info * pinfo,void * data _U_)58 static int exp_pdu_data_dst_ip_size(packet_info *pinfo, void* data _U_)
59 {
60 	return exp_pdu_data_ip_size(&pinfo->net_dst);
61 }
62 
exp_pdu_data_dst_ip_populate_data(packet_info * pinfo,void * data _U_,guint8 * tlv_buffer,guint32 buffer_size _U_)63 static int exp_pdu_data_dst_ip_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size _U_)
64 {
65 	if(pinfo->net_dst.type == AT_IPv4){
66 		phton16(tlv_buffer+0, EXP_PDU_TAG_IPV4_DST);
67 		phton16(tlv_buffer+2, EXP_PDU_TAG_IPV4_LEN); /* tag length */
68 		memcpy(tlv_buffer+4, pinfo->net_dst.data, EXP_PDU_TAG_IPV4_LEN);
69 		return 4 + EXP_PDU_TAG_IPV4_LEN;
70 	}else if(pinfo->net_dst.type == AT_IPv6){
71 		phton16(tlv_buffer+0, EXP_PDU_TAG_IPV6_DST);
72 		phton16(tlv_buffer+2, EXP_PDU_TAG_IPV6_LEN); /* tag length */
73 		memcpy(tlv_buffer+4, pinfo->net_dst.data, EXP_PDU_TAG_IPV6_LEN);
74 		return 4 + EXP_PDU_TAG_IPV6_LEN;
75 	}
76 
77 	return 0;
78 }
79 
exp_pdu_data_port_type_size(packet_info * pinfo _U_,void * data _U_)80 static int exp_pdu_data_port_type_size(packet_info *pinfo _U_, void* data _U_)
81 {
82 	return EXP_PDU_TAG_PORT_LEN + 4;
83 }
84 
exp_pdu_ws_port_type_to_exp_pdu_port_type(port_type pt)85 static guint exp_pdu_ws_port_type_to_exp_pdu_port_type(port_type pt)
86 {
87 	switch (pt)
88 	{
89 	case PT_NONE:
90 		return EXP_PDU_PT_NONE;
91 	case PT_SCTP:
92 		return EXP_PDU_PT_SCTP;
93 	case PT_TCP:
94 		return EXP_PDU_PT_TCP;
95 	case PT_UDP:
96 		return EXP_PDU_PT_UDP;
97 	case PT_DCCP:
98 		return EXP_PDU_PT_DCCP;
99 	case PT_IPX:
100 		return EXP_PDU_PT_IPX;
101 	case PT_DDP:
102 		return EXP_PDU_PT_DDP;
103 	case PT_IDP:
104 		return EXP_PDU_PT_IDP;
105 	case PT_USB:
106 		return EXP_PDU_PT_USB;
107 	case PT_I2C:
108 		return EXP_PDU_PT_I2C;
109 	case PT_IBQP:
110 		return EXP_PDU_PT_IBQP;
111 	case PT_BLUETOOTH:
112 		return EXP_PDU_PT_BLUETOOTH;
113 	case PT_IWARP_MPA:
114 		return EXP_PDU_PT_IWARP_MPA;
115 	}
116 
117 	DISSECTOR_ASSERT(FALSE);
118 	return EXP_PDU_PT_NONE;
119 }
120 
exp_pdu_data_port_type_populate_data(packet_info * pinfo,void * data,guint8 * tlv_buffer,guint32 buffer_size _U_)121 static int exp_pdu_data_port_type_populate_data(packet_info *pinfo, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_)
122 {
123 	guint pt;
124 
125 	phton16(tlv_buffer+0, EXP_PDU_TAG_PORT_TYPE);
126 	phton16(tlv_buffer+2, EXP_PDU_TAG_PORT_TYPE_LEN); /* tag length */
127 	pt = exp_pdu_ws_port_type_to_exp_pdu_port_type(pinfo->ptype);
128 	phton32(tlv_buffer+4, pt);
129 
130 	return exp_pdu_data_port_type_size(pinfo, data);
131 }
132 
exp_pdu_data_port_size(packet_info * pinfo _U_,void * data _U_)133 static int exp_pdu_data_port_size(packet_info *pinfo _U_, void* data _U_)
134 {
135 	return EXP_PDU_TAG_PORT_LEN + 4;
136 }
137 
exp_pdu_data_port_populate_data(guint32 port,guint8 porttype,guint8 * tlv_buffer,guint32 buffer_size _U_)138 static int exp_pdu_data_port_populate_data(guint32 port, guint8 porttype, guint8 *tlv_buffer, guint32 buffer_size _U_)
139 {
140 	phton16(tlv_buffer+0, porttype);
141 	phton16(tlv_buffer+2, EXP_PDU_TAG_PORT_LEN); /* tag length */
142 	phton32(tlv_buffer+4, port);
143 
144 	return EXP_PDU_TAG_PORT_LEN + 4;
145 }
146 
exp_pdu_data_src_port_populate_data(packet_info * pinfo,void * data _U_,guint8 * tlv_buffer,guint32 buffer_size)147 static int exp_pdu_data_src_port_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size)
148 {
149 	return exp_pdu_data_port_populate_data(pinfo->srcport, EXP_PDU_TAG_SRC_PORT, tlv_buffer, buffer_size);
150 }
151 
exp_pdu_data_dst_port_populate_data(packet_info * pinfo,void * data _U_,guint8 * tlv_buffer,guint32 buffer_size)152 static int exp_pdu_data_dst_port_populate_data(packet_info *pinfo, void* data _U_, guint8 *tlv_buffer, guint32 buffer_size)
153 {
154 	return exp_pdu_data_port_populate_data(pinfo->destport, EXP_PDU_TAG_DST_PORT, tlv_buffer, buffer_size);
155 }
156 
exp_pdu_data_orig_frame_num_size(packet_info * pinfo _U_,void * data _U_)157 static int exp_pdu_data_orig_frame_num_size(packet_info *pinfo _U_, void* data _U_)
158 {
159 	return EXP_PDU_TAG_ORIG_FNO_LEN + 4;
160 }
161 
exp_pdu_data_orig_frame_num_populate_data(packet_info * pinfo,void * data,guint8 * tlv_buffer,guint32 buffer_size _U_)162 static int exp_pdu_data_orig_frame_num_populate_data(packet_info *pinfo, void* data, guint8 *tlv_buffer, guint32 buffer_size _U_)
163 {
164 	phton16(tlv_buffer+0, EXP_PDU_TAG_ORIG_FNO);
165 	phton16(tlv_buffer+2, EXP_PDU_TAG_ORIG_FNO_LEN); /* tag length */
166 	phton32(tlv_buffer+4, pinfo->num);
167 
168 	return exp_pdu_data_orig_frame_num_size(pinfo, data);
169 }
170 
exp_pdu_data_dissector_table_num_value_size(packet_info * pinfo _U_,void * data _U_)171 WS_DLL_PUBLIC int exp_pdu_data_dissector_table_num_value_size(packet_info *pinfo _U_, void* data _U_)
172 {
173 	return EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN + 4;
174 }
175 
exp_pdu_data_dissector_table_num_value_populate_data(packet_info * pinfo _U_,void * data,guint8 * tlv_buffer,guint32 buffer_size _U_)176 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_)
177 {
178 	guint32 value = GPOINTER_TO_UINT(data);
179 
180 	phton16(tlv_buffer+0, EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL);
181 	phton16(tlv_buffer+2, EXP_PDU_TAG_DISSECTOR_TABLE_NUM_VAL_LEN); /* tag length */
182 	phton32(tlv_buffer+4, value);
183 
184 	return exp_pdu_data_dissector_table_num_value_size(pinfo, data);
185 }
186 
187 
188 exp_pdu_data_item_t exp_pdu_data_src_ip = {exp_pdu_data_src_ip_size, exp_pdu_data_src_ip_populate_data, NULL};
189 exp_pdu_data_item_t exp_pdu_data_dst_ip = {exp_pdu_data_dst_ip_size, exp_pdu_data_dst_ip_populate_data, NULL};
190 exp_pdu_data_item_t exp_pdu_data_port_type = {exp_pdu_data_port_type_size, exp_pdu_data_port_type_populate_data, NULL};
191 exp_pdu_data_item_t exp_pdu_data_src_port = {exp_pdu_data_port_size, exp_pdu_data_src_port_populate_data, NULL};
192 exp_pdu_data_item_t exp_pdu_data_dst_port = {exp_pdu_data_port_size, exp_pdu_data_dst_port_populate_data, NULL};
193 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};
194 
export_pdu_create_common_tags(packet_info * pinfo,const char * proto_name,guint16 tag_type)195 exp_pdu_data_t *export_pdu_create_common_tags(packet_info *pinfo, const char *proto_name, guint16 tag_type)
196 {
197 	const exp_pdu_data_item_t *common_exp_pdu_items[] = {
198 		&exp_pdu_data_src_ip,
199 		&exp_pdu_data_dst_ip,
200 		&exp_pdu_data_port_type,
201 		&exp_pdu_data_src_port,
202 		&exp_pdu_data_dst_port,
203 		&exp_pdu_data_orig_frame_num,
204 		NULL
205 	};
206 
207 	return export_pdu_create_tags(pinfo, proto_name, tag_type, common_exp_pdu_items);
208 }
209 
210 /**
211  * Allocates and fills the exp_pdu_data_t struct according to the list of items
212  *
213  * The tags in the tag buffer SHOULD be added in numerical order.
214  */
215 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)216 export_pdu_create_tags(packet_info *pinfo, const char* proto_name, guint16 tag_type, const exp_pdu_data_item_t **items_list)
217 {
218 	exp_pdu_data_t *exp_pdu_data;
219 	const exp_pdu_data_item_t **loop_items = items_list;
220 	int tag_buf_size = 0;
221 	int proto_str_len, proto_tag_len, buf_remaining, item_size;
222 	guint8* buffer_data;
223 
224 	DISSECTOR_ASSERT(proto_name != NULL);
225 	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));
226 
227 	exp_pdu_data = wmem_new(pinfo->pool, exp_pdu_data_t);
228 
229 	/* Start by computing size of protocol name as a tag */
230 	proto_str_len = (int)strlen(proto_name);
231 
232 	/* Ensure that tag length is a multiple of 4 bytes */
233 	proto_tag_len = ((proto_str_len + 3) & 0xfffffffc);
234 
235 	/* Add Tag + length */
236 	tag_buf_size += (proto_tag_len + 4);
237 
238 	/* Compute size of items */
239 	while (*loop_items) {
240 		tag_buf_size += (*loop_items)->size_func(pinfo, (*loop_items)->data);
241 		loop_items++;
242 	}
243 
244 	/* Add end of options length */
245 	tag_buf_size+=4;
246 
247 	exp_pdu_data->tlv_buffer = (guint8 *)wmem_alloc0(pinfo->pool, tag_buf_size);
248 	exp_pdu_data->tlv_buffer_len = tag_buf_size;
249 
250 	buffer_data = exp_pdu_data->tlv_buffer;
251 	buf_remaining = exp_pdu_data->tlv_buffer_len;
252 
253 	/* Start by adding protocol name as a tag */
254 	phton16(buffer_data+0, tag_type);
255 	phton16(buffer_data+2, proto_tag_len); /* tag length */
256 	memcpy(buffer_data+4, proto_name, proto_str_len);
257 	buffer_data += (proto_tag_len+4);
258 	buf_remaining -= (proto_tag_len+4);
259 
260 	/* Populate data */
261 	loop_items = items_list;
262 	while (*loop_items) {
263 		item_size = (*loop_items)->populate_data(pinfo, (*loop_items)->data, buffer_data, buf_remaining);
264 		buffer_data += item_size;
265 		buf_remaining -= item_size;
266 		loop_items++;
267 	}
268 
269 	return exp_pdu_data;
270 }
271 
272 gint
register_export_pdu_tap(const char * name)273 register_export_pdu_tap(const char *name)
274 {
275 	gchar *tap_name = g_strdup(name);
276 	export_pdu_tap_name_list = g_slist_prepend(export_pdu_tap_name_list, tap_name);
277 	return register_tap(tap_name);
278 }
279 
280 static
sort_pdu_tap_name_list(gconstpointer a,gconstpointer b)281 gint sort_pdu_tap_name_list(gconstpointer a, gconstpointer b)
282 {
283 	return g_strcmp0((const char *)a, (const char*)b);
284 }
285 
286 GSList *
get_export_pdu_tap_list(void)287 get_export_pdu_tap_list(void)
288 {
289 	export_pdu_tap_name_list = g_slist_sort(export_pdu_tap_name_list, sort_pdu_tap_name_list);
290 	return export_pdu_tap_name_list;
291 }
292 
export_pdu_init(void)293 void export_pdu_init(void)
294 {
295 }
296 
export_pdu_cleanup(void)297 void export_pdu_cleanup(void)
298 {
299 	g_slist_free_full(export_pdu_tap_name_list, g_free);
300 }
301 
302 /*
303  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
304  *
305  * Local variables:
306  * c-basic-offset: 8
307  * tab-width: 8
308  * indent-tabs-mode: t
309  * End:
310  *
311  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
312  * :indentSize=8:tabSize=8:noTabs=false:
313  */
314