2 * Allow users to specify the dissectors for DLTs
3 * Luis E. Garcia Ontanon <luis@ontanon.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
9 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include <epan/prefs.h>
19 #include <epan/exported_pdu.h>
21 #include <wiretap/wtap.h>
24 /* disable: warning C4090: 'XY' : different 'const' qualifiers */
25 #pragma warning(disable:4090)
28 void proto_register_user_encap(void);
29 void proto_reg_handoff_user_encap(void);
31 typedef struct _user_encap_t
{
33 char* payload_proto_name
;
34 dissector_handle_t payload_proto
;
35 char* header_proto_name
;
36 dissector_handle_t header_proto
;
37 char* trailer_proto_name
;
38 dissector_handle_t trailer_proto
;
40 unsigned trailer_size
;
43 #define ENCAP0_STR "User 0 (DLT=147)"
44 static const value_string user_dlts
[] = {
45 { WTAP_ENCAP_USER0
, ENCAP0_STR
},
46 { WTAP_ENCAP_USER1
, "User 1 (DLT=148)"},
47 { WTAP_ENCAP_USER2
, "User 2 (DLT=149)"},
48 { WTAP_ENCAP_USER3
, "User 3 (DLT=150)"},
49 { WTAP_ENCAP_USER4
, "User 4 (DLT=151)"},
50 { WTAP_ENCAP_USER5
, "User 5 (DLT=152)"},
51 { WTAP_ENCAP_USER6
, "User 6 (DLT=153)"},
52 { WTAP_ENCAP_USER7
, "User 7 (DLT=154)"},
53 { WTAP_ENCAP_USER8
, "User 8 (DLT=155)"},
54 { WTAP_ENCAP_USER9
, "User 9 (DLT=156)"},
55 { WTAP_ENCAP_USER10
, "User 10 (DLT=157)"},
56 { WTAP_ENCAP_USER11
, "User 11 (DLT=158)"},
57 { WTAP_ENCAP_USER12
, "User 12 (DLT=159)"},
58 { WTAP_ENCAP_USER13
, "User 13 (DLT=160)"},
59 { WTAP_ENCAP_USER14
, "User 14 (DLT=161)"},
60 { WTAP_ENCAP_USER15
, "User 15 (DLT=162)"},
63 static int proto_user_encap
;
65 static expert_field ei_user_encap_not_handled
;
67 static user_encap_t
* encaps
;
68 static unsigned num_encaps
;
69 static uat_t
* encaps_uat
;
71 static int exported_pdu_tap
= -1;
73 static dissector_handle_t user_encap_handle
;
76 * Use this for DLT_USER2 if we don't have an encapsulation for it.
78 static user_encap_t user2_encap
= {WTAP_ENCAP_USER2
, "pktap", NULL
, "", NULL
, "", NULL
, 0, 0};
80 static void export_pdu(tvbuff_t
*tvb
, packet_info
* pinfo
, char *proto_name
)
82 if (have_tap_listener(exported_pdu_tap
)) {
83 static const exp_pdu_data_item_t
*user_encap_exp_pdu_items
[] = {
84 &exp_pdu_data_orig_frame_num
,
88 exp_pdu_data_t
*exp_pdu_data
= export_pdu_create_tags(pinfo
, proto_name
, EXP_PDU_TAG_DISSECTOR_NAME
, user_encap_exp_pdu_items
);
90 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
91 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
92 exp_pdu_data
->pdu_tvb
= tvb
;
93 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
97 static int dissect_user(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
) {
98 user_encap_t
* encap
= NULL
;
99 tvbuff_t
* payload_tvb
;
101 int len
, reported_len
;
104 for (i
= 0; i
< num_encaps
; i
++) {
105 if (encaps
[i
].encap
== pinfo
->match_uint
) {
106 encap
= &(encaps
[i
]);
111 item
= proto_tree_add_item(tree
,proto_user_encap
,tvb
,0,-1,ENC_NA
);
112 if (!encap
&& pinfo
->match_uint
== WTAP_ENCAP_USER2
) {
114 * Special-case DLT_USER2 - Apple hijacked it for use as DLT_PKTAP.
115 * The user hasn't assigned anything to it, so default it to
116 * the PKTAP dissector.
118 encap
= &user2_encap
;
121 char* msg
= wmem_strdup_printf(pinfo
->pool
,
122 "User encapsulation not handled: DLT=%d, "
123 "check your Preferences->Protocols->DLT_USER",
124 pinfo
->match_uint
+ 147 - WTAP_ENCAP_USER0
);
125 proto_item_set_text(item
,"%s",msg
);
126 expert_add_info_format(pinfo
, item
, &ei_user_encap_not_handled
, "%s", msg
);
128 call_data_dissector(tvb
, pinfo
, tree
);
129 return tvb_captured_length(tvb
);
131 if (encap
->payload_proto
== NULL
) {
132 char* msg
= wmem_strdup_printf(pinfo
->pool
,
133 "User encapsulation's protocol %s not found: "
134 "DLT=%d, check your Preferences->Protocols->DLT_USER",
135 encap
->payload_proto_name
,
136 pinfo
->match_uint
+ 147 - WTAP_ENCAP_USER0
);
137 proto_item_set_text(item
,"%s",msg
);
138 expert_add_info_format(pinfo
, item
, &ei_user_encap_not_handled
, "%s", msg
);
140 call_data_dissector(tvb
, pinfo
, tree
);
141 return tvb_captured_length(tvb
);
144 proto_item_set_text(item
,"DLT: %d",pinfo
->match_uint
+ 147 - WTAP_ENCAP_USER0
);
146 if (encap
->header_size
) {
147 tvbuff_t
* hdr_tvb
= tvb_new_subset_length(tvb
, 0, encap
->header_size
);
148 export_pdu(hdr_tvb
, pinfo
, encap
->header_proto_name
);
149 call_dissector(encap
->header_proto
, hdr_tvb
, pinfo
, tree
);
150 if (encap
->header_proto_name
) {
151 const char *proto_name
= dissector_handle_get_protocol_long_name(encap
->header_proto
);
153 proto_item_append_text(item
, ", Header: %s (%s)", encap
->header_proto_name
, proto_name
);
158 len
= tvb_captured_length(tvb
) - (encap
->header_size
+ encap
->trailer_size
);
159 reported_len
= tvb_reported_length(tvb
) - (encap
->header_size
+ encap
->trailer_size
);
161 payload_tvb
= tvb_new_subset_length_caplen(tvb
, encap
->header_size
, len
, reported_len
);
162 export_pdu(payload_tvb
, pinfo
, encap
->payload_proto_name
);
163 call_dissector(encap
->payload_proto
, payload_tvb
, pinfo
, tree
);
164 if (encap
->payload_proto_name
) {
165 const char *proto_name
= dissector_handle_get_protocol_long_name(encap
->payload_proto
);
167 proto_item_append_text(item
, ", Payload: %s (%s)", encap
->payload_proto_name
, proto_name
);
171 if (encap
->trailer_size
) {
172 tvbuff_t
* trailer_tvb
= tvb_new_subset_length(tvb
, encap
->header_size
+ len
, encap
->trailer_size
);
173 export_pdu(trailer_tvb
, pinfo
, encap
->trailer_proto_name
);
174 call_dissector(encap
->trailer_proto
, trailer_tvb
, pinfo
, tree
);
175 if (encap
->trailer_proto_name
) {
176 const char *proto_name
= dissector_handle_get_protocol_long_name(encap
->trailer_proto
);
178 proto_item_append_text(item
, ", Trailer: %s (%s)", encap
->trailer_proto_name
, proto_name
);
182 return tvb_captured_length(tvb
);
185 static void* user_copy_cb(void* dest
, const void* orig
, size_t len _U_
)
187 const user_encap_t
*o
= (const user_encap_t
*)orig
;
188 user_encap_t
*d
= (user_encap_t
*)dest
;
191 d
->payload_proto_name
= g_strdup(o
->payload_proto_name
);
192 d
->payload_proto
= o
->payload_proto
;
193 d
->header_proto_name
= g_strdup(o
->header_proto_name
);
194 d
->header_proto
= o
->header_proto
;
195 d
->trailer_proto_name
= g_strdup(o
->trailer_proto_name
);
196 d
->trailer_proto
= o
->trailer_proto
;
197 d
->header_size
= o
->header_size
;
198 d
->trailer_size
= o
->trailer_size
;
203 static void user_free_cb(void* record
)
205 user_encap_t
*u
= (user_encap_t
*)record
;
207 g_free(u
->payload_proto_name
);
208 g_free(u
->header_proto_name
);
209 g_free(u
->trailer_proto_name
);
212 UAT_VS_DEF(user_encap
, encap
, user_encap_t
, unsigned, WTAP_ENCAP_USER0
, ENCAP0_STR
)
213 UAT_DISSECTOR_DEF(user_encap
, payload_proto
, payload_proto
, payload_proto_name
, user_encap_t
)
214 UAT_DEC_CB_DEF(user_encap
, header_size
, user_encap_t
)
215 UAT_DISSECTOR_DEF(user_encap
, header_proto
, header_proto
, header_proto_name
, user_encap_t
)
216 UAT_DEC_CB_DEF(user_encap
, trailer_size
, user_encap_t
)
217 UAT_DISSECTOR_DEF(user_encap
, trailer_proto
, trailer_proto
, trailer_proto_name
, user_encap_t
)
219 void proto_reg_handoff_user_encap(void)
223 user2_encap
.payload_proto
= find_dissector("pktap");
225 for (i
= WTAP_ENCAP_USER0
; i
<= WTAP_ENCAP_USER15
; i
++)
226 dissector_add_uint("wtap_encap", i
, user_encap_handle
);
230 void proto_register_user_encap(void)
233 expert_module_t
* expert_user_encap
;
235 static uat_field_t user_flds
[] = {
236 UAT_FLD_VS(user_encap
,encap
,"DLT",user_dlts
,"The DLT"),
237 UAT_FLD_DISSECTOR(user_encap
,payload_proto
,"Payload dissector",
238 "Dissector to be used for the payload of this DLT"),
239 UAT_FLD_DEC(user_encap
,header_size
,"Header size",
240 "Size of an eventual header that precedes the actual payload, 0 means none"),
241 UAT_FLD_DISSECTOR(user_encap
,header_proto
,"Header dissector",
242 "Dissector to be used for the header (empty = data)"),
243 UAT_FLD_DEC(user_encap
,trailer_size
,"Trailer size",
244 "Size of an eventual trailer that follows the actual payload, 0 means none"),
245 UAT_FLD_DISSECTOR(user_encap
,trailer_proto
,"Trailer dissector",
246 "Dissector to be used for the trailer (empty = data)"),
250 static ei_register_info ei
[] = {
251 { &ei_user_encap_not_handled
, { "user_dlt.not_handled", PI_UNDECODED
, PI_WARN
, "Formatted text", EXPFILL
}},
254 proto_user_encap
= proto_register_protocol("DLT User","DLT_USER","user_dlt");
255 expert_user_encap
= expert_register_protocol(proto_user_encap
);
256 expert_register_field_array(expert_user_encap
, ei
, array_length(ei
));
258 module
= prefs_register_protocol(proto_user_encap
, NULL
);
260 encaps_uat
= uat_new("User DLTs Table",
261 sizeof(user_encap_t
),
266 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
275 prefs_register_uat_preference(module
,
277 "Encapsulations Table",
278 "A table that enumerates the various protocols to be used against a certain user DLT",
282 user_encap_handle
= register_dissector("user_dlt",dissect_user
,proto_user_encap
);
285 prefs_register_protocol_obsolete(proto_register_protocol("DLT User A","DLT_USER_A","user_dlt_a"));
286 prefs_register_protocol_obsolete(proto_register_protocol("DLT User B","DLT_USER_B","user_dlt_b"));
287 prefs_register_protocol_obsolete(proto_register_protocol("DLT User C","DLT_USER_C","user_dlt_c"));
288 prefs_register_protocol_obsolete(proto_register_protocol("DLT User D","DLT_USER_D","user_dlt_d"));
291 exported_pdu_tap
= register_export_pdu_tap("DLT User");
295 * Editor modelines - https://www.wireshark.org/tools/modelines.html
300 * indent-tabs-mode: nil
303 * vi: set shiftwidth=4 tabstop=8 expandtab:
304 * :indentSize=4:tabSize=8:noTabs=true: