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