/src/wireshark/epan/dissectors/packet-imf.c
Line | Count | Source |
1 | | /* packet-imf.c |
2 | | * Routines for Internet Message Format (IMF) packet disassembly |
3 | | * |
4 | | * Copyright (c) 2007 by Graeme Lunt |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1999 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/prefs.h> |
17 | | #include <epan/uat.h> |
18 | | #include <epan/expert.h> |
19 | | #include <wsutil/str_util.h> |
20 | | #include <wsutil/array.h> |
21 | | |
22 | | #include <epan/tap.h> |
23 | | #include <epan/export_object.h> |
24 | | |
25 | | #include "packet-ber.h" |
26 | | #include "packet-media-type.h" |
27 | | #include "packet-imf.h" |
28 | | #include "packet-ess.h" |
29 | | #include "packet-p1.h" |
30 | | |
31 | | void proto_register_imf(void); |
32 | | void proto_reg_handoff_imf(void); |
33 | | |
34 | | static int imf_eo_tap; |
35 | | |
36 | | static int proto_imf; |
37 | | |
38 | | static int hf_imf_date; |
39 | | static int hf_imf_from; |
40 | | static int hf_imf_sender; |
41 | | static int hf_imf_reply_to; |
42 | | static int hf_imf_to; |
43 | | static int hf_imf_cc; |
44 | | static int hf_imf_bcc; |
45 | | static int hf_imf_message_id; |
46 | | static int hf_imf_in_reply_to; |
47 | | static int hf_imf_references; |
48 | | static int hf_imf_subject; |
49 | | static int hf_imf_comments; |
50 | | static int hf_imf_user_agent; |
51 | | static int hf_imf_keywords; |
52 | | static int hf_imf_resent_date; |
53 | | static int hf_imf_resent_from; |
54 | | static int hf_imf_resent_sender; |
55 | | static int hf_imf_resent_to; |
56 | | static int hf_imf_resent_cc; |
57 | | static int hf_imf_resent_bcc; |
58 | | static int hf_imf_resent_message_id; |
59 | | static int hf_imf_return_path; |
60 | | static int hf_imf_received; |
61 | | static int hf_imf_content_type; |
62 | | static int hf_imf_content_type_type; |
63 | | static int hf_imf_content_type_parameters; |
64 | | static int hf_imf_content_id; |
65 | | static int hf_imf_content_transfer_encoding; |
66 | | static int hf_imf_content_description; |
67 | | static int hf_imf_mime_version; |
68 | | static int hf_imf_thread_index; |
69 | | static int hf_imf_lines; |
70 | | static int hf_imf_precedence; |
71 | | static int hf_imf_ext_mailer; |
72 | | static int hf_imf_ext_mimeole; |
73 | | static int hf_imf_ext_tnef_correlator; |
74 | | static int hf_imf_ext_expiry_date; |
75 | | static int hf_imf_ext_uidl; |
76 | | static int hf_imf_ext_authentication_warning; |
77 | | static int hf_imf_ext_virus_scanned; |
78 | | static int hf_imf_ext_original_to; |
79 | | static int hf_imf_extension; |
80 | | static int hf_imf_extension_type; |
81 | | static int hf_imf_extension_value; |
82 | | |
83 | | /* RFC 2156 */ |
84 | | static int hf_imf_autoforwarded; |
85 | | static int hf_imf_autosubmitted; |
86 | | static int hf_imf_x400_content_identifier; |
87 | | static int hf_imf_content_language; |
88 | | static int hf_imf_conversion; |
89 | | static int hf_imf_conversion_with_loss; |
90 | | static int hf_imf_delivery_date; |
91 | | static int hf_imf_discarded_x400_ipms_extensions; |
92 | | static int hf_imf_discarded_x400_mts_extensions; |
93 | | static int hf_imf_dl_expansion_history; |
94 | | static int hf_imf_deferred_delivery; |
95 | | static int hf_imf_expires; |
96 | | static int hf_imf_importance; |
97 | | static int hf_imf_incomplete_copy; |
98 | | static int hf_imf_latest_delivery_time; |
99 | | static int hf_imf_message_type; |
100 | | static int hf_imf_original_encoded_information_types; |
101 | | static int hf_imf_originator_return_address; |
102 | | static int hf_imf_priority; |
103 | | static int hf_imf_reply_by; |
104 | | static int hf_imf_sensitivity; |
105 | | static int hf_imf_supersedes; |
106 | | static int hf_imf_x400_content_type; |
107 | | static int hf_imf_x400_mts_identifier; |
108 | | static int hf_imf_x400_originator; |
109 | | static int hf_imf_x400_received; |
110 | | static int hf_imf_x400_recipients; |
111 | | |
112 | | static int hf_imf_delivered_to; |
113 | | |
114 | | static int hf_imf_message_text; |
115 | | |
116 | | static int hf_imf_display_name; |
117 | | static int hf_imf_address; |
118 | | /* static int hf_imf_mailbox_list; */ |
119 | | static int hf_imf_mailbox_list_item; |
120 | | /* static int hf_imf_address_list; */ |
121 | | static int hf_imf_address_list_item; |
122 | | |
123 | | /* draft-zeilenga-email-seclabel-04 */ |
124 | | static int hf_imf_siolabel; |
125 | | static int hf_imf_siolabel_marking; |
126 | | static int hf_imf_siolabel_fgcolor; |
127 | | static int hf_imf_siolabel_bgcolor; |
128 | | static int hf_imf_siolabel_type; |
129 | | static int hf_imf_siolabel_label; |
130 | | static int hf_imf_siolabel_unknown; |
131 | | |
132 | | static int ett_imf; |
133 | | static int ett_imf_content_type; |
134 | | static int ett_imf_mailbox; |
135 | | static int ett_imf_group; |
136 | | static int ett_imf_mailbox_list; |
137 | | static int ett_imf_address_list; |
138 | | static int ett_imf_siolabel; |
139 | | static int ett_imf_extension; |
140 | | static int ett_imf_message_text; |
141 | | |
142 | | static dissector_handle_t imf_handle; |
143 | | |
144 | | static expert_field ei_imf_unknown_param; |
145 | | |
146 | | /* Used for IMF Export Object feature */ |
147 | | typedef struct _imf_eo_t { |
148 | | char *filename; |
149 | | char *sender_data; |
150 | | char *subject_data; |
151 | | uint32_t payload_len; |
152 | | char *payload_data; |
153 | | } imf_eo_t; |
154 | | |
155 | | static tap_packet_status |
156 | | imf_eo_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_) |
157 | 0 | { |
158 | 0 | export_object_list_t *object_list = (export_object_list_t *)tapdata; |
159 | 0 | const imf_eo_t *eo_info = (const imf_eo_t *)data; |
160 | 0 | export_object_entry_t *entry; |
161 | |
|
162 | 0 | if(eo_info) { /* We have data waiting for us */ |
163 | | /* These values will be freed when the Export Object window |
164 | | * is closed. */ |
165 | 0 | entry = g_new(export_object_entry_t, 1); |
166 | |
|
167 | 0 | char *start = g_strrstr_len(eo_info->sender_data, -1, "<"); |
168 | 0 | char *stop = g_strrstr_len(eo_info->sender_data, -1, ">"); |
169 | | /* Only include the string inside of the "<>" brackets. If there is nothing between |
170 | | the two brackets use the sender_data string */ |
171 | 0 | if(start && stop && stop > start && (stop - start) > 2){ |
172 | 0 | entry->hostname = ws_strdup_printf("%.*s", (int) (stop - start - 1), start + 1); |
173 | 0 | } else { |
174 | 0 | entry->hostname = g_strdup(eo_info->sender_data); |
175 | 0 | } |
176 | |
|
177 | 0 | entry->pkt_num = pinfo->num; |
178 | 0 | entry->content_type = g_strdup("EML file"); |
179 | 0 | entry->filename = ws_strdup_printf("%s.eml", eo_info->subject_data); |
180 | 0 | entry->payload_len = eo_info->payload_len; |
181 | 0 | entry->payload_data = (uint8_t *)g_memdup2(eo_info->payload_data, eo_info->payload_len); |
182 | |
|
183 | 0 | object_list->add_entry(object_list->gui_data, entry); |
184 | |
|
185 | 0 | return TAP_PACKET_REDRAW; /* State changed - window should be redrawn */ |
186 | 0 | } else { |
187 | 0 | return TAP_PACKET_DONT_REDRAW; /* State unchanged - no window updates needed */ |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | | |
192 | | struct imf_field { |
193 | | char *name; /* field name - in lower case for matching purposes */ |
194 | | int *hf_id; /* wireshark field */ |
195 | | void (*subdissector)(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
196 | | bool add_to_col_info; /* add field to column info */ |
197 | | }; |
198 | | |
199 | 0 | #define NO_SUBDISSECTION NULL |
200 | | |
201 | | static void dissect_imf_mailbox(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
202 | | static void dissect_imf_address(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
203 | | static void dissect_imf_address_list(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
204 | | static void dissect_imf_mailbox_list(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
205 | | static void dissect_imf_siolabel(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo); |
206 | | |
207 | | static const struct imf_field imf_fields[] = { |
208 | | {"unknown-extension", &hf_imf_extension_type, NO_SUBDISSECTION, false}, /* unknown extension */ |
209 | | {"date", &hf_imf_date, NO_SUBDISSECTION, false}, /* date-time */ |
210 | | {"from", &hf_imf_from, dissect_imf_mailbox_list , true}, /* mailbox_list */ |
211 | | {"sender", &hf_imf_sender, dissect_imf_mailbox, false}, /* mailbox */ |
212 | | {"reply-to", &hf_imf_reply_to, dissect_imf_address_list , false}, /* address_list */ |
213 | | {"to", &hf_imf_to, dissect_imf_address_list , false}, /* address_list */ |
214 | | {"cc", &hf_imf_cc, dissect_imf_address_list , false}, /* address_list */ |
215 | | {"bcc", &hf_imf_bcc, dissect_imf_address_list , false}, /* address_list */ |
216 | | {"message-id", &hf_imf_message_id, NO_SUBDISSECTION, false}, /* msg-id */ |
217 | | {"in-reply-to", &hf_imf_in_reply_to, NO_SUBDISSECTION, false}, /* msg-id */ |
218 | | {"references", &hf_imf_references, NO_SUBDISSECTION, false}, /* msg-id */ |
219 | | {"subject", &hf_imf_subject, NO_SUBDISSECTION, true}, /* unstructured */ |
220 | | {"comments", &hf_imf_comments, NO_SUBDISSECTION, false}, /* unstructured */ |
221 | | {"user-agent", &hf_imf_user_agent, NO_SUBDISSECTION, false}, /* unstructured */ |
222 | | {"keywords", &hf_imf_keywords, NULL, false}, /* phrase_list */ |
223 | | {"resent-date", &hf_imf_resent_date, NO_SUBDISSECTION, false}, |
224 | | {"resent-from", &hf_imf_resent_from, dissect_imf_mailbox_list, false}, |
225 | | {"resent-sender", &hf_imf_resent_sender, dissect_imf_mailbox, false}, |
226 | | {"resent-to", &hf_imf_resent_to, dissect_imf_address_list, false}, |
227 | | {"resent-cc", &hf_imf_resent_cc, dissect_imf_address_list, false}, |
228 | | {"resent-bcc", &hf_imf_resent_bcc, dissect_imf_address_list, false}, |
229 | | {"resent-message-id", &hf_imf_resent_message_id, NO_SUBDISSECTION, false}, |
230 | | {"return-path", &hf_imf_return_path, NULL, false}, |
231 | | {"received", &hf_imf_received, NO_SUBDISSECTION, false}, |
232 | | /* these are really multi-part - but we parse them anyway */ |
233 | | {"content-type", &hf_imf_content_type, NULL, false}, /* handled separately as a special case */ |
234 | | {"content-id", &hf_imf_content_id, NULL, false}, |
235 | | {"content-description", &hf_imf_content_description, NULL, false}, |
236 | | {"content-transfer-encoding", &hf_imf_content_transfer_encoding, NULL, false}, |
237 | | {"mime-version", &hf_imf_mime_version, NO_SUBDISSECTION, false}, |
238 | | /* MIXER - RFC 2156 */ |
239 | | {"autoforwarded", &hf_imf_autoforwarded, NULL, false}, |
240 | | {"autosubmitted", &hf_imf_autosubmitted, NULL, false}, |
241 | | {"x400-content-identifier", &hf_imf_x400_content_identifier, NULL, false}, |
242 | | {"content-language", &hf_imf_content_language, NULL, false}, |
243 | | {"conversion", &hf_imf_conversion, NULL, false}, |
244 | | {"conversion-with-loss", &hf_imf_conversion_with_loss, NULL, false}, |
245 | | {"delivery-date", &hf_imf_delivery_date, NULL, false}, |
246 | | {"discarded-x400-ipms-extensions", &hf_imf_discarded_x400_ipms_extensions, NULL, false}, |
247 | | {"discarded-x400-mts-extensions", &hf_imf_discarded_x400_mts_extensions, NULL, false}, |
248 | | {"dl-expansion-history", &hf_imf_dl_expansion_history, NULL, false}, |
249 | | {"deferred-delivery", &hf_imf_deferred_delivery, NULL, false}, |
250 | | {"expires", &hf_imf_expires, NULL, false}, |
251 | | {"importance", &hf_imf_importance, NULL, false}, |
252 | | {"incomplete-copy", &hf_imf_incomplete_copy, NULL, false}, |
253 | | {"latest-delivery-time", &hf_imf_latest_delivery_time, NULL, false}, |
254 | | {"message-type", &hf_imf_message_type, NULL, false}, |
255 | | {"original-encoded-information-types", &hf_imf_original_encoded_information_types, NULL, false}, |
256 | | {"originator-return-address", &hf_imf_originator_return_address, NULL, false}, |
257 | | {"priority", &hf_imf_priority, NULL, false}, |
258 | | {"reply-by", &hf_imf_reply_by, NULL, false}, |
259 | | {"sensitivity", &hf_imf_sensitivity, NULL, false}, |
260 | | {"supersedes", &hf_imf_supersedes, NULL, false}, |
261 | | {"x400-content-type", &hf_imf_x400_content_type, NULL, false}, |
262 | | {"x400-mts-identifier", &hf_imf_x400_mts_identifier, NULL, false}, |
263 | | {"x400-originator", &hf_imf_x400_originator, NULL, false}, |
264 | | {"x400-received", &hf_imf_x400_received, NULL, false}, |
265 | | {"x400-recipients", &hf_imf_x400_recipients, NULL, false}, |
266 | | /* delivery */ |
267 | | {"delivered-to", &hf_imf_delivered_to, dissect_imf_mailbox, false}, /* mailbox */ |
268 | | /* some others */ |
269 | | {"x-mailer", &hf_imf_ext_mailer, NO_SUBDISSECTION, false}, /* unstructured */ |
270 | | {"thread-index", &hf_imf_thread_index, NO_SUBDISSECTION, false}, /* unstructured */ |
271 | | {"lines", &hf_imf_lines, NULL, false}, |
272 | | {"precedence", &hf_imf_precedence, NULL, false}, |
273 | | {"x-mimeole", &hf_imf_ext_mimeole, NO_SUBDISSECTION, false}, /* unstructured */ |
274 | | {"expiry-date", &hf_imf_ext_expiry_date, NO_SUBDISSECTION, false}, /* unstructured */ |
275 | | {"x-ms-tnef-correlator", &hf_imf_ext_tnef_correlator, NO_SUBDISSECTION, false}, /* unstructured */ |
276 | | {"x-uidl", &hf_imf_ext_uidl, NO_SUBDISSECTION, false}, /* unstructured */ |
277 | | {"x-authentication-warning", &hf_imf_ext_authentication_warning, NO_SUBDISSECTION, false}, /* unstructured */ |
278 | | {"x-virus-scanned", &hf_imf_ext_virus_scanned, NO_SUBDISSECTION, false}, /* unstructured */ |
279 | | {"x-original-to", &hf_imf_ext_original_to, dissect_imf_address_list, false}, |
280 | | {"sio-label", &hf_imf_siolabel, dissect_imf_siolabel, false}, /* sio-label */ |
281 | | {NULL, NULL, NULL, false}, |
282 | | }; |
283 | | |
284 | | static wmem_map_t *imf_field_table; |
285 | | |
286 | 0 | #define FORMAT_UNSTRUCTURED 0 |
287 | 0 | #define FORMAT_MAILBOX 1 |
288 | 0 | #define FORMAT_ADDRESS 2 |
289 | 0 | #define FORMAT_MAILBOX_LIST 3 |
290 | 0 | #define FORMAT_ADDRESS_LIST 4 |
291 | 0 | #define FORMAT_SIO_LABEL 5 |
292 | | |
293 | | static const value_string header_format[] = { |
294 | | { FORMAT_UNSTRUCTURED, "Unstructured" }, |
295 | | { FORMAT_MAILBOX, "Mailbox" }, |
296 | | { FORMAT_ADDRESS, "Address" }, |
297 | | { FORMAT_MAILBOX_LIST, "Mailbox List" }, |
298 | | { FORMAT_ADDRESS_LIST, "Address List" }, |
299 | | { FORMAT_SIO_LABEL, "SIO-Label" }, |
300 | | { 0, NULL } |
301 | | }; |
302 | | |
303 | | static const value_string add_to_col_info[] = { |
304 | | { 0, "No" }, |
305 | | { 1, "Yes" }, |
306 | | { 0, NULL } |
307 | | }; |
308 | | |
309 | | typedef struct _header_field_t { |
310 | | char *header_name; |
311 | | char *description; |
312 | | unsigned header_format; |
313 | | unsigned add_to_col_info; |
314 | | } header_field_t; |
315 | | |
316 | | static header_field_t *header_fields; |
317 | | static unsigned num_header_fields; |
318 | | |
319 | | static GHashTable *custom_field_table; |
320 | | static hf_register_info *dynamic_hf; |
321 | | static unsigned dynamic_hf_size; |
322 | | |
323 | | static bool |
324 | | header_fields_update_cb(void *r, char **err) |
325 | 0 | { |
326 | 0 | header_field_t *rec = (header_field_t *)r; |
327 | 0 | char c; |
328 | |
|
329 | 0 | if (rec->header_name == NULL) { |
330 | 0 | *err = g_strdup("Header name can't be empty"); |
331 | 0 | return false; |
332 | 0 | } |
333 | | |
334 | 0 | g_strstrip(rec->header_name); |
335 | 0 | if (rec->header_name[0] == 0) { |
336 | 0 | *err = g_strdup("Header name can't be empty"); |
337 | 0 | return false; |
338 | 0 | } |
339 | | |
340 | | /* Check for invalid characters (to avoid asserting out when |
341 | | * registering the field). |
342 | | */ |
343 | 0 | c = proto_check_field_name(rec->header_name); |
344 | 0 | if (c) { |
345 | 0 | *err = ws_strdup_printf("Header name can't contain '%c'", c); |
346 | 0 | return false; |
347 | 0 | } |
348 | | |
349 | 0 | *err = NULL; |
350 | 0 | return true; |
351 | 0 | } |
352 | | |
353 | | static void * |
354 | | header_fields_copy_cb(void *n, const void *o, size_t siz _U_) |
355 | 0 | { |
356 | 0 | header_field_t *new_rec = (header_field_t *)n; |
357 | 0 | const header_field_t *old_rec = (const header_field_t *)o; |
358 | |
|
359 | 0 | new_rec->header_name = g_strdup(old_rec->header_name); |
360 | 0 | new_rec->description = g_strdup(old_rec->description); |
361 | 0 | new_rec->header_format = old_rec->header_format; |
362 | 0 | new_rec->add_to_col_info = old_rec->add_to_col_info; |
363 | |
|
364 | 0 | return new_rec; |
365 | 0 | } |
366 | | |
367 | | static void |
368 | | header_fields_free_cb(void *r) |
369 | 0 | { |
370 | 0 | header_field_t *rec = (header_field_t *)r; |
371 | |
|
372 | 0 | g_free(rec->header_name); |
373 | 0 | g_free(rec->description); |
374 | 0 | } |
375 | | |
376 | 0 | UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t) |
377 | 0 | UAT_CSTRING_CB_DEF(header_fields, description, header_field_t) |
378 | 0 | UAT_VS_DEF(header_fields, header_format, header_field_t, unsigned, 0, "Unstructured") Unexecuted instantiation: packet-imf.c:header_fields_header_format_set_cb Unexecuted instantiation: packet-imf.c:header_fields_header_format_tostr_cb |
379 | 0 | UAT_VS_DEF(header_fields, add_to_col_info, header_field_t, unsigned, 0, "No") Unexecuted instantiation: packet-imf.c:header_fields_add_to_col_info_set_cb Unexecuted instantiation: packet-imf.c:header_fields_add_to_col_info_tostr_cb |
380 | | |
381 | | |
382 | | /* Define media_type/Content type table */ |
383 | | static dissector_table_t media_type_dissector_table; |
384 | | |
385 | | static void |
386 | | dissect_imf_address(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo) |
387 | 0 | { |
388 | 0 | proto_tree *group_tree; |
389 | 0 | proto_item *group_item; |
390 | 0 | unsigned addr_pos; |
391 | | |
392 | | /* if there is a colon present it is a group */ |
393 | 0 | if(!tvb_find_uint8_length(tvb, offset, length, ':', &addr_pos)) { |
394 | | |
395 | | /* there isn't - so it must be a mailbox */ |
396 | 0 | dissect_imf_mailbox(tvb, offset, length, item, pinfo); |
397 | |
|
398 | 0 | } else { |
399 | | |
400 | | /* it is a group */ |
401 | 0 | group_tree = proto_item_add_subtree(item, ett_imf_group); |
402 | | |
403 | | /* the display-name is mandatory */ |
404 | 0 | group_item = proto_tree_add_item(group_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII); |
405 | | |
406 | | /* consume any whitespace */ |
407 | 0 | for(addr_pos++ ;addr_pos < (offset + length); addr_pos++) { |
408 | 0 | if(!g_ascii_isspace(tvb_get_uint8(tvb, addr_pos))) { |
409 | 0 | break; |
410 | 0 | } |
411 | 0 | } |
412 | |
|
413 | 0 | if(tvb_get_uint8(tvb, addr_pos) != ';') { |
414 | |
|
415 | 0 | dissect_imf_mailbox_list(tvb, addr_pos, length - (addr_pos - offset), group_item, pinfo); |
416 | | |
417 | | /* XXX: need to check for final ';' */ |
418 | |
|
419 | 0 | } |
420 | |
|
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | | static void |
425 | | dissect_imf_mailbox(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo _U_) |
426 | 0 | { |
427 | 0 | proto_tree *mbox_tree; |
428 | 0 | unsigned addr_pos, end_pos; |
429 | |
|
430 | 0 | mbox_tree = proto_item_add_subtree(item, ett_imf_mailbox); |
431 | | |
432 | | /* Here is the plan: |
433 | | If we can't find and angle brackets, then the whole field is an address. |
434 | | If we find angle brackets, then the address is between them and the display name is |
435 | | anything before the opening angle bracket |
436 | | */ |
437 | |
|
438 | 0 | if(!tvb_find_uint8_length(tvb, offset, length, '<', &addr_pos)) { |
439 | | /* we can't find an angle bracket - the whole field is therefore the address */ |
440 | |
|
441 | 0 | (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, offset, length, ENC_ASCII); |
442 | |
|
443 | 0 | } else { |
444 | | /* we can find an angle bracket - let's see if we can find a display name */ |
445 | | /* XXX: the '<' could be in the display name */ |
446 | |
|
447 | 0 | for(; offset < addr_pos; offset++) { |
448 | 0 | if(!g_ascii_isspace(tvb_get_uint8(tvb, offset))) { |
449 | 0 | break; |
450 | 0 | } |
451 | 0 | } |
452 | |
|
453 | 0 | if(offset != addr_pos) { /* there is a display name */ |
454 | 0 | (void) proto_tree_add_item(mbox_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII); |
455 | 0 | } |
456 | |
|
457 | 0 | if(!tvb_find_uint8_length(tvb, addr_pos + 1, length - (addr_pos + 1 - offset), '>', &end_pos)) { |
458 | 0 | (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, addr_pos + 1, end_pos - addr_pos - 1, ENC_ASCII); |
459 | 0 | } |
460 | 0 | } |
461 | 0 | } |
462 | | |
463 | | static void |
464 | | dissect_imf_address_list(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo) |
465 | 0 | { |
466 | 0 | proto_item *addr_item = NULL; |
467 | 0 | proto_tree *tree = NULL; |
468 | 0 | unsigned count = 0; |
469 | 0 | unsigned item_offset; |
470 | 0 | unsigned end_offset; |
471 | 0 | unsigned item_length; |
472 | 0 | bool end_offset_found; |
473 | | |
474 | | /* a comma separated list of addresses */ |
475 | 0 | tree = proto_item_add_subtree(item, ett_imf_address_list); |
476 | |
|
477 | 0 | item_offset = offset; |
478 | |
|
479 | 0 | do { |
480 | |
|
481 | 0 | count++; /* increase the number of items */ |
482 | 0 | end_offset_found = tvb_find_uint8_length(tvb, item_offset, length - (item_offset - offset), ',', &end_offset); |
483 | 0 | if(end_offset_found == false) { |
484 | | /* length is to the end of the buffer */ |
485 | 0 | item_length = length - (item_offset - offset); |
486 | 0 | } else { |
487 | 0 | item_length = end_offset - item_offset; |
488 | 0 | } |
489 | 0 | addr_item = proto_tree_add_item(tree, hf_imf_address_list_item, tvb, item_offset, item_length, ENC_ASCII); |
490 | 0 | dissect_imf_address(tvb, item_offset, item_length, addr_item, pinfo); |
491 | |
|
492 | 0 | if(end_offset_found == true) { |
493 | 0 | item_offset = end_offset + 1; |
494 | 0 | } |
495 | 0 | } while(end_offset_found == true); |
496 | | |
497 | | /* now indicate the number of items found */ |
498 | 0 | proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s")); |
499 | 0 | } |
500 | | |
501 | | static void |
502 | | dissect_imf_mailbox_list(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo) |
503 | 0 | { |
504 | 0 | proto_item *mbox_item = NULL; |
505 | 0 | proto_tree *tree = NULL; |
506 | 0 | unsigned count = 0; |
507 | 0 | unsigned item_offset; |
508 | 0 | unsigned end_offset; |
509 | 0 | unsigned item_length; |
510 | 0 | bool end_offset_found; |
511 | | |
512 | | /* a comma separated list of mailboxes */ |
513 | 0 | tree = proto_item_add_subtree(item, ett_imf_mailbox_list); |
514 | |
|
515 | 0 | item_offset = offset; |
516 | |
|
517 | 0 | do { |
518 | |
|
519 | 0 | end_offset_found = tvb_find_uint8_length(tvb, item_offset, length - (item_offset - offset), ',', &end_offset); |
520 | |
|
521 | 0 | count++; /* increase the number of items */ |
522 | |
|
523 | 0 | if(end_offset_found == false) { |
524 | | /* length is to the end of the buffer */ |
525 | 0 | item_length = length - (item_offset - offset); |
526 | 0 | } else { |
527 | 0 | item_length = end_offset - item_offset; |
528 | 0 | } |
529 | 0 | mbox_item = proto_tree_add_item(tree, hf_imf_mailbox_list_item, tvb, item_offset, item_length, ENC_ASCII); |
530 | 0 | dissect_imf_mailbox(tvb, item_offset, item_length, mbox_item, pinfo); |
531 | |
|
532 | 0 | if(end_offset_found == true) { |
533 | 0 | item_offset = end_offset + 1; |
534 | 0 | } |
535 | 0 | } while(end_offset_found == true); |
536 | | |
537 | | /* now indicate the number of items found */ |
538 | 0 | proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s")); |
539 | 0 | } |
540 | | |
541 | | static void |
542 | | dissect_imf_siolabel(tvbuff_t *tvb, unsigned offset, unsigned length, proto_item *item, packet_info *pinfo) |
543 | 0 | { |
544 | 0 | proto_tree *tree = NULL; |
545 | 0 | proto_item *sub_item = NULL; |
546 | 0 | unsigned item_offset, item_length; |
547 | 0 | unsigned value_offset, value_length; |
548 | 0 | unsigned end_offset; |
549 | 0 | bool end_offset_found; |
550 | 0 | tvbuff_t *label_tvb; |
551 | 0 | char *type = NULL; |
552 | 0 | wmem_strbuf_t *label_string = wmem_strbuf_new(pinfo->pool, ""); |
553 | | |
554 | | /* a semicolon separated list of attributes */ |
555 | 0 | tree = proto_item_add_subtree(item, ett_imf_siolabel); |
556 | 0 | item_offset = offset; |
557 | |
|
558 | 0 | do { |
559 | 0 | end_offset_found = tvb_find_uint8_length(tvb, item_offset, length - (item_offset - offset), ';', &end_offset); |
560 | | |
561 | | /* skip leading space */ |
562 | 0 | item_offset = tvb_skip_wsp(tvb, item_offset, end_offset); |
563 | |
|
564 | 0 | if (end_offset_found == false) { |
565 | | /* length is to the end of the buffer */ |
566 | 0 | tvb_find_line_end_length(tvb, item_offset, length - (item_offset - offset), &item_length, NULL); |
567 | 0 | } else { |
568 | 0 | item_length = end_offset - item_offset; |
569 | 0 | } |
570 | |
|
571 | 0 | tvb_find_uint8_length(tvb, item_offset, length - (item_offset - offset), '=', &value_offset); |
572 | 0 | value_offset = value_offset +1; |
573 | 0 | value_offset = tvb_skip_wsp(tvb, value_offset, end_offset); |
574 | |
|
575 | 0 | value_length = item_length - (value_offset - item_offset); |
576 | 0 | value_length = tvb_skip_wsp_return(tvb, value_offset + value_length - 1); |
577 | |
|
578 | 0 | if (tvb_strneql(tvb, item_offset, "marking", 7) == 0) { |
579 | 0 | const uint8_t* marking; |
580 | 0 | proto_tree_add_item_ret_string(tree, hf_imf_siolabel_marking, tvb, value_offset, value_length, ENC_ASCII|ENC_NA, pinfo->pool, &marking); |
581 | 0 | proto_item_append_text(item, ": %s", marking); |
582 | |
|
583 | 0 | } else if (tvb_strneql(tvb, item_offset, "fgcolor", 7) == 0) { |
584 | 0 | proto_tree_add_item(tree, hf_imf_siolabel_fgcolor, tvb, value_offset, value_length, ENC_ASCII); |
585 | |
|
586 | 0 | } else if (tvb_strneql(tvb, item_offset, "bgcolor", 7) == 0) { |
587 | 0 | proto_tree_add_item(tree, hf_imf_siolabel_bgcolor, tvb, value_offset, value_length, ENC_ASCII); |
588 | |
|
589 | 0 | } else if (tvb_strneql(tvb, item_offset, "type", 4) == 0) { |
590 | 0 | type = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset + 1, value_length - 2, ENC_ASCII); /* quoted */ |
591 | 0 | proto_tree_add_item(tree, hf_imf_siolabel_type, tvb, value_offset, value_length, ENC_ASCII); |
592 | |
|
593 | 0 | } else if (tvb_strneql(tvb, item_offset, "label", 5) == 0) { |
594 | 0 | char *label = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset + 1, value_length - 2, ENC_ASCII); /* quoted */ |
595 | 0 | wmem_strbuf_append(label_string, label); |
596 | |
|
597 | 0 | if (tvb_get_uint8(tvb, item_offset + 5) == '*') { /* continuations */ |
598 | 0 | int num; |
599 | 0 | tvb_get_string_int(tvb, item_offset + 6, value_offset - item_offset + 6, ENC_STR_DEC, &num, NULL); |
600 | 0 | proto_tree_add_string_format(tree, hf_imf_siolabel_label, tvb, value_offset, value_length, |
601 | 0 | label, "Label[%d]: \"%s\"", num, label); |
602 | 0 | } else { |
603 | 0 | proto_tree_add_item(tree, hf_imf_siolabel_label, tvb, value_offset, value_length, ENC_ASCII); |
604 | 0 | } |
605 | |
|
606 | 0 | } else { |
607 | 0 | sub_item = proto_tree_add_item(tree, hf_imf_siolabel_unknown, tvb, item_offset, item_length, ENC_ASCII); |
608 | 0 | expert_add_info(pinfo, sub_item, &ei_imf_unknown_param); |
609 | 0 | } |
610 | |
|
611 | 0 | if (end_offset_found == true) { |
612 | 0 | item_offset = end_offset + 1; |
613 | 0 | } |
614 | 0 | } while (end_offset_found == true); |
615 | |
|
616 | 0 | if (type && wmem_strbuf_get_len(label_string) > 0) { |
617 | 0 | if (strcmp (type, ":ess") == 0) { |
618 | 0 | label_tvb = base64_to_tvb(tvb, wmem_strbuf_get_str(label_string)); |
619 | 0 | add_new_data_source(pinfo, label_tvb, "ESS Security Label"); |
620 | 0 | dissect_ess_ESSSecurityLabel_PDU(label_tvb, pinfo, tree, NULL); |
621 | 0 | } else if (strcmp (type, ":x411") == 0) { |
622 | 0 | label_tvb = base64_to_tvb(tvb, wmem_strbuf_get_str(label_string)); |
623 | 0 | add_new_data_source(pinfo, label_tvb, "X.411 Security Label"); |
624 | 0 | dissect_p1_MessageSecurityLabel_PDU(label_tvb, pinfo, tree, NULL); |
625 | 0 | } |
626 | 0 | } |
627 | 0 | } |
628 | | |
629 | | static void |
630 | | dissect_imf_content_type(tvbuff_t *tvb, packet_info *pinfo, unsigned offset, unsigned length, proto_item *item, |
631 | | const char **type, const char **parameters) |
632 | 0 | { |
633 | 0 | unsigned first_colon; |
634 | 0 | unsigned end_offset; |
635 | 0 | unsigned len; |
636 | 0 | int t_offset; |
637 | 0 | proto_tree *ct_tree; |
638 | | |
639 | | /* first strip any whitespace */ |
640 | 0 | tvb_skip_wsp(tvb, offset, length); |
641 | | |
642 | | /* find the first colon - there has to be a colon as there will have to be a boundary */ |
643 | 0 | first_colon = tvb_find_uint8_length(tvb, offset, length, ';', &first_colon); |
644 | |
|
645 | 0 | if(tvb_find_uint8_length(tvb, offset, length, ';', &first_colon)) { |
646 | 0 | ct_tree = proto_item_add_subtree(item, ett_imf_content_type); |
647 | |
|
648 | 0 | len = first_colon - offset; |
649 | 0 | proto_tree_add_item_ret_string(ct_tree, hf_imf_content_type_type, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)type); |
650 | 0 | t_offset = imf_find_field_end (tvb, first_colon + 1, offset + length, NULL); |
651 | 0 | if (t_offset == -1) { |
652 | | /* No end found */ |
653 | 0 | return; |
654 | 0 | } |
655 | 0 | end_offset = (unsigned)t_offset; |
656 | 0 | len = end_offset - (first_colon + 1) - 2; /* Do not include the last CRLF */ |
657 | 0 | proto_tree_add_item_ret_string(ct_tree, hf_imf_content_type_parameters, tvb, first_colon + 1, len, ENC_ASCII|ENC_NA, pinfo->pool, (const uint8_t**)parameters); |
658 | 0 | } |
659 | 0 | } |
660 | | |
661 | | |
662 | | int |
663 | | imf_find_field_end(tvbuff_t *tvb, unsigned offset, unsigned max_length, bool *last_field) |
664 | 82 | { |
665 | | |
666 | 215 | while(offset < max_length) { |
667 | | |
668 | | /* look for CR */ |
669 | 212 | if(tvb_find_uint8_length(tvb, offset, max_length - offset, '\r', &offset)) { |
670 | | /* protect against buffer overrun and only then look for next char */ |
671 | 182 | if (++offset < max_length && tvb_get_uint8(tvb, offset) == '\n') { |
672 | | /* OK - so we have found CRLF */ |
673 | 50 | if (++offset >= max_length) { |
674 | | /* end of buffer and also end of fields */ |
675 | 0 | if (last_field) { |
676 | 0 | *last_field = true; |
677 | 0 | } |
678 | | /* caller expects that there is CRLF after returned offset, if last_field is set */ |
679 | 0 | return offset - 2; |
680 | 0 | } |
681 | | /* peek the next character */ |
682 | 50 | switch(tvb_get_uint8(tvb, offset)) { |
683 | 22 | case '\r': |
684 | | /* probably end of the fields */ |
685 | 22 | if ((offset + 1) < max_length && tvb_get_uint8(tvb, offset + 1) == '\n') { |
686 | 2 | if(last_field) { |
687 | 2 | *last_field = true; |
688 | 2 | } |
689 | 2 | } |
690 | 22 | return offset; |
691 | 0 | case ' ': |
692 | 1 | case '\t': |
693 | | /* continuation line */ |
694 | 1 | break; |
695 | 27 | default: |
696 | | /* this is a new field */ |
697 | 27 | return offset; |
698 | 50 | } |
699 | 50 | } |
700 | 182 | } else { |
701 | | /* couldn't find a CR - strange */ |
702 | 30 | break; |
703 | 30 | } |
704 | | |
705 | 212 | } |
706 | | |
707 | 33 | return -1; /* Fail: No CR found (other than possible continuation) */ |
708 | | |
709 | 82 | } |
710 | | |
711 | | static int |
712 | | dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
713 | 55 | { |
714 | 55 | proto_item *item; |
715 | 55 | proto_tree *unknown_tree, *text_tree; |
716 | 55 | const char *content_type_str = NULL; |
717 | 55 | char *content_encoding_str = NULL; |
718 | 55 | const char *parameters = NULL; |
719 | 55 | int hf_id; |
720 | 55 | unsigned start_offset = 0; |
721 | 55 | unsigned value_offset = 0; |
722 | 55 | unsigned unknown_offset = 0; |
723 | 55 | unsigned end_offset = 0; |
724 | 55 | int t_offset; |
725 | 55 | unsigned max_length; |
726 | 55 | bool end_offset_found; |
727 | 55 | char *key; |
728 | 55 | bool last_field = false; |
729 | 55 | tvbuff_t *next_tvb; |
730 | 55 | const struct imf_field *f_info; |
731 | 55 | imf_eo_t *eo_info = NULL; |
732 | | |
733 | 55 | if (have_tap_listener(imf_eo_tap)) { |
734 | 0 | eo_info = wmem_new(pinfo->pool, imf_eo_t); |
735 | | /* initialize the eo_info fields in case they are missing later */ |
736 | 0 | eo_info->sender_data = ""; |
737 | 0 | eo_info->subject_data = ""; |
738 | 0 | } |
739 | | |
740 | | /* Want to preserve existing protocol name and show that it is carrying IMF */ |
741 | 55 | col_append_str(pinfo->cinfo, COL_PROTOCOL, "/"); |
742 | 55 | col_set_fence(pinfo->cinfo, COL_PROTOCOL); |
743 | 55 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMF"); |
744 | | |
745 | 55 | col_clear(pinfo->cinfo, COL_INFO); |
746 | | |
747 | 55 | item = proto_tree_add_item(tree, proto_imf, tvb, 0, -1, ENC_NA); |
748 | 55 | tree = proto_item_add_subtree(item, ett_imf); |
749 | | |
750 | 55 | max_length = tvb_captured_length(tvb); |
751 | | /* first go through the tvb until we find a blank line and extract the content type if |
752 | | we find one */ |
753 | | |
754 | | /* XXX: What if the tvb contains encrypted data ? is there a way to bypass dissection if so ? */ |
755 | | /* As it is, the following code blithely tries to parse what may be binary data. */ |
756 | | |
757 | 104 | while(!last_field) { |
758 | | |
759 | | /* look for a colon first */ |
760 | 102 | end_offset_found = tvb_find_uint8_length(tvb, start_offset, max_length - start_offset, ':', &end_offset); |
761 | | |
762 | 102 | if(end_offset_found == false) { |
763 | | /* we couldn't find another colon - strange - we should have broken out of here by now */ |
764 | | /* XXX: flag an error */ |
765 | 20 | break; |
766 | 82 | } else { |
767 | 82 | key = (char*)tvb_get_string_enc(pinfo->pool, tvb, start_offset, end_offset - start_offset, ENC_ASCII); |
768 | | |
769 | | /* convert to lower case */ |
770 | 82 | ascii_strdown_inplace (key); |
771 | | |
772 | | /* look up the key in built-in fields */ |
773 | 82 | f_info = (const struct imf_field *)wmem_map_lookup(imf_field_table, key); |
774 | | |
775 | 82 | if(f_info == NULL && custom_field_table) { |
776 | | /* look up the key in custom fields */ |
777 | 0 | f_info = (const struct imf_field *)g_hash_table_lookup(custom_field_table, key); |
778 | 0 | } |
779 | | |
780 | 82 | if(f_info == NULL) { |
781 | | /* set as an unknown extension */ |
782 | 82 | f_info = imf_fields; |
783 | 82 | unknown_offset = start_offset; |
784 | 82 | } |
785 | | |
786 | 82 | hf_id = *(f_info->hf_id); |
787 | | |
788 | | /* value starts immediately after the colon */ |
789 | 82 | start_offset = end_offset+1; |
790 | | |
791 | 82 | t_offset = imf_find_field_end(tvb, start_offset, max_length, &last_field); |
792 | 82 | if(t_offset == -1) { |
793 | 33 | break; /* Something's fishy */ |
794 | 33 | } |
795 | 49 | end_offset = (unsigned)t_offset; |
796 | | |
797 | | /* remove any leading whitespace */ |
798 | | |
799 | 59 | for(value_offset = start_offset; value_offset < end_offset; value_offset++) |
800 | 59 | if(!g_ascii_isspace(tvb_get_uint8(tvb, value_offset))) { |
801 | 49 | break; |
802 | 49 | } |
803 | | |
804 | 49 | if(value_offset == end_offset) { |
805 | | /* empty field - show whole value */ |
806 | 0 | value_offset = start_offset; |
807 | 0 | } |
808 | | |
809 | 49 | if(hf_id == hf_imf_extension_type) { |
810 | | |
811 | | /* remove 2 bytes to take off the final CRLF to make things a little prettier */ |
812 | 49 | item = proto_tree_add_item(tree, hf_imf_extension, tvb, unknown_offset, end_offset - unknown_offset - 2, ENC_ASCII); |
813 | | |
814 | 49 | proto_item_append_text(item, " (Contact Wireshark developers if you want this supported.)"); |
815 | | |
816 | 49 | unknown_tree = proto_item_add_subtree(item, ett_imf_extension); |
817 | | |
818 | 49 | proto_tree_add_item(unknown_tree, hf_imf_extension_type, tvb, unknown_offset, start_offset - 1 - unknown_offset, ENC_ASCII); |
819 | | |
820 | | /* remove 2 bytes to take off the final CRLF to make things a little prettier */ |
821 | 49 | item = proto_tree_add_item(unknown_tree, hf_imf_extension_value, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII); |
822 | | |
823 | 49 | } else { |
824 | | /* remove 2 bytes to take off the final CRLF to make things a little prettier */ |
825 | 0 | item = proto_tree_add_item(tree, hf_id, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA); |
826 | 0 | } |
827 | 49 | if(f_info->add_to_col_info) { |
828 | |
|
829 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s, ", f_info->name, |
830 | 0 | tvb_format_text(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2)); |
831 | | |
832 | | /* if sender or subject, store for sending to the tap */ |
833 | 0 | if (eo_info && have_tap_listener(imf_eo_tap)) { |
834 | 0 | if (*f_info->hf_id == hf_imf_from) { |
835 | 0 | eo_info->sender_data = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA); |
836 | 0 | } else if(*f_info->hf_id == hf_imf_subject) { |
837 | 0 | eo_info->subject_data = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA); |
838 | 0 | } |
839 | 0 | } |
840 | 0 | } |
841 | | |
842 | 49 | if(hf_id == hf_imf_content_type) { |
843 | | /* we need some additional processing to extract the content type and parameters */ |
844 | |
|
845 | 0 | dissect_imf_content_type(tvb, pinfo, start_offset, end_offset - start_offset, item, |
846 | 0 | &content_type_str, ¶meters); |
847 | |
|
848 | 49 | } else if (hf_id == hf_imf_content_transfer_encoding) { |
849 | 0 | content_encoding_str = (char*)tvb_get_string_enc (pinfo->pool, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII); |
850 | 49 | } else if(f_info->subdissector) { |
851 | | |
852 | | /* we have a subdissector */ |
853 | 0 | f_info->subdissector(tvb, value_offset, end_offset - value_offset, item, pinfo); |
854 | |
|
855 | 0 | } |
856 | 49 | } |
857 | 49 | start_offset = end_offset; |
858 | 49 | } |
859 | | |
860 | 55 | if (last_field) { |
861 | | /* Remove the extra CRLF after all the fields */ |
862 | 2 | end_offset += 2; |
863 | 2 | } |
864 | | |
865 | 55 | if (end_offset_found == false) { |
866 | 20 | end_offset = 0; |
867 | 20 | } |
868 | | |
869 | | /* specify a content type until we can work it out for ourselves */ |
870 | | /* content_type_str = "multipart/mixed"; */ |
871 | | |
872 | | /* now dissect the MIME based upon the content type */ |
873 | | |
874 | 55 | if(content_type_str && media_type_dissector_table) { |
875 | 0 | media_content_info_t content_info; |
876 | |
|
877 | 0 | col_set_fence(pinfo->cinfo, COL_INFO); |
878 | |
|
879 | 0 | if(content_encoding_str && !g_ascii_strncasecmp(content_encoding_str, "base64", 6)) { |
880 | 0 | char *string_data = (char*)tvb_get_string_enc(pinfo->pool, tvb, end_offset, tvb_reported_length(tvb) - end_offset, ENC_ASCII); |
881 | 0 | next_tvb = base64_to_tvb(tvb, string_data); |
882 | 0 | add_new_data_source(pinfo, next_tvb, content_encoding_str); |
883 | 0 | } else { |
884 | 0 | next_tvb = tvb_new_subset_remaining(tvb, end_offset); |
885 | 0 | } |
886 | |
|
887 | 0 | content_info.type = MEDIA_CONTAINER_OTHER; |
888 | 0 | content_info.media_str = parameters; |
889 | 0 | content_info.data = NULL; |
890 | 0 | dissector_try_string_with_data(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree, true, (void*)&content_info); |
891 | 55 | } else { |
892 | | |
893 | | /* just show the lines or highlight the rest of the buffer as message text */ |
894 | | |
895 | 55 | item = proto_tree_add_item(tree, hf_imf_message_text, tvb, end_offset, tvb_reported_length_remaining(tvb, end_offset) , ENC_NA); |
896 | 55 | text_tree = proto_item_add_subtree(item, ett_imf_message_text); |
897 | | |
898 | 55 | start_offset = end_offset; |
899 | 369 | while (tvb_offset_exists(tvb, start_offset)) { |
900 | | |
901 | | /* |
902 | | * Find the end of the line. |
903 | | */ |
904 | 314 | tvb_find_line_end_remaining(tvb, start_offset, NULL, &end_offset); |
905 | | |
906 | | /* |
907 | | * Put this line. |
908 | | */ |
909 | 314 | proto_tree_add_format_wsp_text(text_tree, tvb, start_offset, end_offset - start_offset); |
910 | 314 | col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", |
911 | 314 | tvb_format_text_wsp(pinfo->pool, tvb, start_offset, end_offset - start_offset)); |
912 | | |
913 | | /* |
914 | | * Step to the next line. |
915 | | */ |
916 | 314 | start_offset = end_offset; |
917 | 314 | } |
918 | 55 | } |
919 | | |
920 | 55 | if (eo_info && have_tap_listener(imf_eo_tap)) { |
921 | | /* Set payload info */ |
922 | 0 | eo_info->payload_len = max_length; |
923 | 0 | eo_info->payload_data = (char *) tvb_memdup(pinfo->pool, tvb, 0, max_length); |
924 | | |
925 | | /* Send to tap */ |
926 | 0 | tap_queue_packet(imf_eo_tap, pinfo, eo_info); |
927 | 0 | } |
928 | 55 | return tvb_captured_length(tvb); |
929 | 55 | } |
930 | | |
931 | | static void |
932 | | free_imf_field (void *data) |
933 | 0 | { |
934 | 0 | struct imf_field *imffield = (struct imf_field *) data; |
935 | |
|
936 | 0 | g_free (imffield->name); |
937 | 0 | g_free (imffield); |
938 | 0 | } |
939 | | |
940 | | static void |
941 | | deregister_header_fields(void) |
942 | 14 | { |
943 | 14 | if (dynamic_hf) { |
944 | | /* Deregister all fields */ |
945 | 0 | for (unsigned i = 0; i < dynamic_hf_size; i++) { |
946 | 0 | proto_deregister_field (proto_imf, *(dynamic_hf[i].p_id)); |
947 | 0 | g_free (dynamic_hf[i].p_id); |
948 | 0 | } |
949 | |
|
950 | 0 | proto_add_deregistered_data (dynamic_hf); |
951 | 0 | dynamic_hf = NULL; |
952 | 0 | dynamic_hf_size = 0; |
953 | 0 | } |
954 | | |
955 | 14 | if (custom_field_table) { |
956 | 0 | g_hash_table_destroy (custom_field_table); |
957 | 0 | custom_field_table = NULL; |
958 | 0 | } |
959 | 14 | } |
960 | | |
961 | | static void |
962 | | header_fields_post_update_cb (void) |
963 | 14 | { |
964 | 14 | int *hf_id; |
965 | 14 | struct imf_field *imffield; |
966 | 14 | char *header_name; |
967 | | |
968 | 14 | deregister_header_fields(); |
969 | | |
970 | 14 | if (num_header_fields) { |
971 | 0 | custom_field_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_imf_field); |
972 | 0 | dynamic_hf = g_new0(hf_register_info, num_header_fields); |
973 | 0 | dynamic_hf_size = num_header_fields; |
974 | |
|
975 | 0 | for (unsigned i = 0; i < dynamic_hf_size; i++) { |
976 | 0 | hf_id = g_new(int, 1); |
977 | 0 | *hf_id = -1; |
978 | 0 | header_name = g_strdup (header_fields[i].header_name); |
979 | |
|
980 | 0 | dynamic_hf[i].p_id = hf_id; |
981 | 0 | dynamic_hf[i].hfinfo.name = header_name; |
982 | 0 | dynamic_hf[i].hfinfo.abbrev = ws_strdup_printf ("imf.header.%s", header_name); |
983 | 0 | dynamic_hf[i].hfinfo.type = FT_STRING; |
984 | 0 | dynamic_hf[i].hfinfo.display = BASE_NONE; |
985 | 0 | dynamic_hf[i].hfinfo.strings = NULL; |
986 | 0 | dynamic_hf[i].hfinfo.bitmask = 0; |
987 | 0 | dynamic_hf[i].hfinfo.blurb = g_strdup (header_fields[i].description); |
988 | 0 | HFILL_INIT(dynamic_hf[i]); |
989 | |
|
990 | 0 | imffield = g_new(struct imf_field, 1); |
991 | 0 | imffield->hf_id = hf_id; |
992 | 0 | imffield->name = g_ascii_strdown(header_name, -1); |
993 | 0 | switch (header_fields[i].header_format) { |
994 | 0 | case FORMAT_UNSTRUCTURED: |
995 | 0 | imffield->subdissector = NO_SUBDISSECTION; |
996 | 0 | break; |
997 | 0 | case FORMAT_MAILBOX: |
998 | 0 | imffield->subdissector = dissect_imf_mailbox; |
999 | 0 | break; |
1000 | 0 | case FORMAT_ADDRESS: |
1001 | 0 | imffield->subdissector = dissect_imf_address; |
1002 | 0 | break; |
1003 | 0 | case FORMAT_MAILBOX_LIST: |
1004 | 0 | imffield->subdissector = dissect_imf_mailbox_list; |
1005 | 0 | break; |
1006 | 0 | case FORMAT_ADDRESS_LIST: |
1007 | 0 | imffield->subdissector = dissect_imf_address_list; |
1008 | 0 | break; |
1009 | 0 | case FORMAT_SIO_LABEL: |
1010 | 0 | dynamic_hf[i].hfinfo.type = FT_NONE; /* constructed */ |
1011 | 0 | imffield->subdissector = dissect_imf_siolabel; |
1012 | 0 | break; |
1013 | 0 | default: |
1014 | | /* unknown */ |
1015 | 0 | imffield->subdissector = NO_SUBDISSECTION; |
1016 | 0 | break; |
1017 | 0 | } |
1018 | 0 | imffield->add_to_col_info = header_fields[i].add_to_col_info; |
1019 | 0 | g_hash_table_insert (custom_field_table, (void *)imffield->name, (void *)imffield); |
1020 | 0 | } |
1021 | | |
1022 | 0 | proto_register_field_array (proto_imf, dynamic_hf, dynamic_hf_size); |
1023 | 0 | } |
1024 | 14 | } |
1025 | | |
1026 | | static void |
1027 | | header_fields_reset_cb(void) |
1028 | 0 | { |
1029 | 0 | deregister_header_fields(); |
1030 | 0 | } |
1031 | | |
1032 | | /* Register all the bits needed by the filtering engine */ |
1033 | | |
1034 | | void |
1035 | | proto_register_imf(void) |
1036 | 14 | { |
1037 | 14 | static hf_register_info hf[] = { |
1038 | 14 | { &hf_imf_date, |
1039 | 14 | { "Date", "imf.date", FT_STRING, BASE_NONE, NULL, 0x0, |
1040 | 14 | "DateTime", HFILL }}, |
1041 | 14 | { &hf_imf_from, |
1042 | 14 | { "From", "imf.from", FT_STRING, BASE_NONE, NULL, 0x0, |
1043 | 14 | "MailboxList", HFILL }}, |
1044 | 14 | { &hf_imf_sender, |
1045 | 14 | { "Sender", "imf.sender", FT_STRING, BASE_NONE, NULL, 0x0, |
1046 | 14 | NULL, HFILL }}, |
1047 | 14 | { &hf_imf_reply_to, |
1048 | 14 | { "Reply-To", "imf.reply_to", FT_STRING, BASE_NONE, NULL, 0x0, |
1049 | 14 | NULL, HFILL }}, |
1050 | 14 | { &hf_imf_to, |
1051 | 14 | { "To", "imf.to", FT_STRING, BASE_NONE, NULL, 0x0, |
1052 | 14 | NULL, HFILL }}, |
1053 | 14 | { &hf_imf_cc, |
1054 | 14 | { "Cc", "imf.cc", FT_STRING, BASE_NONE, NULL, 0x0, |
1055 | 14 | NULL, HFILL }}, |
1056 | 14 | { &hf_imf_bcc, |
1057 | 14 | { "Bcc", "imf.bcc", FT_STRING, BASE_NONE, NULL, 0x0, |
1058 | 14 | NULL, HFILL }}, |
1059 | 14 | { &hf_imf_message_id, |
1060 | 14 | { "Message-ID", "imf.message_id", FT_STRING, BASE_NONE, NULL, 0x0, |
1061 | 14 | NULL, HFILL }}, |
1062 | 14 | { &hf_imf_in_reply_to, |
1063 | 14 | { "In-Reply-To", "imf.in_reply_to", FT_STRING, BASE_NONE, NULL, 0x0, |
1064 | 14 | NULL, HFILL }}, |
1065 | 14 | { &hf_imf_references, |
1066 | 14 | { "References", "imf.references", FT_STRING, BASE_NONE, NULL, 0x0, |
1067 | 14 | NULL, HFILL }}, |
1068 | 14 | { &hf_imf_subject, |
1069 | 14 | { "Subject", "imf.subject", FT_STRING, BASE_NONE, NULL, 0x0, |
1070 | 14 | NULL, HFILL }}, |
1071 | 14 | { &hf_imf_comments, |
1072 | 14 | { "Comments", "imf.comments", FT_STRING, BASE_NONE, NULL, 0x0, |
1073 | 14 | NULL, HFILL }}, |
1074 | 14 | { &hf_imf_user_agent, |
1075 | 14 | { "User-Agent", "imf.user_agent", FT_STRING, BASE_NONE, NULL, 0x0, |
1076 | 14 | NULL, HFILL }}, |
1077 | 14 | { &hf_imf_keywords, |
1078 | 14 | { "Keywords", "imf.keywords", FT_STRING, BASE_NONE, NULL, 0x0, |
1079 | 14 | NULL, HFILL }}, |
1080 | 14 | { &hf_imf_resent_date, |
1081 | 14 | { "Resent-Date", "imf.resent.date", FT_STRING, BASE_NONE, NULL, 0x0, |
1082 | 14 | NULL, HFILL }}, |
1083 | 14 | { &hf_imf_resent_from, |
1084 | 14 | { "Resent-From", "imf.resent.from", FT_STRING, BASE_NONE, NULL, 0x0, |
1085 | 14 | NULL, HFILL }}, |
1086 | 14 | { &hf_imf_resent_sender, |
1087 | 14 | { "Resent-Sender", "imf.resent.sender", FT_STRING, BASE_NONE, NULL, 0x0, |
1088 | 14 | NULL, HFILL }}, |
1089 | 14 | { &hf_imf_resent_to, |
1090 | 14 | { "Resent-To", "imf.resent.to", FT_STRING, BASE_NONE, NULL, 0x0, |
1091 | 14 | NULL, HFILL }}, |
1092 | 14 | { &hf_imf_resent_cc, |
1093 | 14 | { "Resent-Cc", "imf.resent.cc", FT_STRING, BASE_NONE, NULL, 0x0, |
1094 | 14 | NULL, HFILL }}, |
1095 | 14 | { &hf_imf_resent_bcc, |
1096 | 14 | { "Resent-Bcc", "imf.resent.bcc", FT_STRING, BASE_NONE, NULL, 0x0, |
1097 | 14 | NULL, HFILL }}, |
1098 | 14 | { &hf_imf_resent_message_id, |
1099 | 14 | { "Resent-Message-ID", "imf.resent.message_id", FT_STRING, BASE_NONE, NULL, 0x0, |
1100 | 14 | NULL, HFILL }}, |
1101 | 14 | { &hf_imf_return_path, |
1102 | 14 | { "Return-Path", "imf.return_path", FT_STRING, BASE_NONE, NULL, 0x0, |
1103 | 14 | NULL, HFILL }}, |
1104 | 14 | { &hf_imf_received, |
1105 | 14 | { "Received", "imf.received", FT_STRING, BASE_NONE, NULL, 0x0, |
1106 | 14 | NULL, HFILL }}, |
1107 | 14 | { &hf_imf_content_type, |
1108 | 14 | { "Content-Type", "imf.content.type", FT_STRING, BASE_NONE, NULL, 0x0, |
1109 | 14 | NULL, HFILL }}, |
1110 | 14 | { &hf_imf_content_type_type, |
1111 | 14 | { "Type", "imf.content.type.type", FT_STRING, BASE_NONE, NULL, 0x0, |
1112 | 14 | NULL, HFILL }}, |
1113 | 14 | { &hf_imf_content_type_parameters, |
1114 | 14 | { "Parameters", "imf.content.type.parameters", FT_STRING, BASE_NONE, NULL, 0x0, |
1115 | 14 | NULL, HFILL }}, |
1116 | 14 | { &hf_imf_content_description, |
1117 | 14 | { "Content-Description", "imf.content.description", FT_STRING, BASE_NONE, NULL, 0x0, |
1118 | 14 | NULL, HFILL }}, |
1119 | 14 | { &hf_imf_content_id, |
1120 | 14 | { "Content-ID", "imf.content.id", FT_STRING, BASE_NONE, NULL, 0x0, |
1121 | 14 | NULL, HFILL }}, |
1122 | 14 | { &hf_imf_content_transfer_encoding, |
1123 | 14 | { "Content-Transfer-Encoding", "imf.content.transfer_encoding", FT_STRING, BASE_NONE, NULL, 0x0, |
1124 | 14 | NULL, HFILL }}, |
1125 | 14 | { &hf_imf_mime_version, |
1126 | 14 | { "MIME-Version", "imf.mime_version", FT_STRING, BASE_NONE, NULL, 0x0, |
1127 | 14 | NULL, HFILL }}, |
1128 | 14 | { &hf_imf_autoforwarded, |
1129 | 14 | { "Autoforwarded", "imf.autoforwarded", FT_STRING, BASE_NONE, NULL, 0x0, |
1130 | 14 | NULL, HFILL }}, |
1131 | 14 | { &hf_imf_autosubmitted, |
1132 | 14 | { "Autosubmitted", "imf.autosubmitted", FT_STRING, BASE_NONE, NULL, 0x0, |
1133 | 14 | NULL, HFILL }}, |
1134 | 14 | { &hf_imf_x400_content_identifier, |
1135 | 14 | { "X400-Content-Identifier", "imf.x400_content_identifier", FT_STRING, BASE_NONE, NULL, 0x0, |
1136 | 14 | NULL, HFILL }}, |
1137 | 14 | { &hf_imf_content_language, |
1138 | 14 | { "Content-Language", "imf.content_language", FT_STRING, BASE_NONE, NULL, 0x0, |
1139 | 14 | NULL, HFILL }}, |
1140 | 14 | { &hf_imf_conversion, |
1141 | 14 | { "Conversion", "imf.conversion", FT_STRING, BASE_NONE, NULL, 0x0, |
1142 | 14 | NULL, HFILL }}, |
1143 | 14 | { &hf_imf_conversion_with_loss, |
1144 | 14 | { "Conversion-With-Loss", "imf.conversion_with_loss", FT_STRING, BASE_NONE, NULL, 0x0, |
1145 | 14 | NULL, HFILL }}, |
1146 | 14 | { &hf_imf_delivery_date, |
1147 | 14 | { "Delivery-Date", "imf.delivery_date", FT_STRING, BASE_NONE, NULL, 0x0, |
1148 | 14 | NULL, HFILL }}, |
1149 | 14 | { &hf_imf_discarded_x400_ipms_extensions, |
1150 | 14 | { "Discarded-X400-IPMS-Extensions", "imf.discarded_x400_ipms_extensions", FT_STRING, BASE_NONE, NULL, 0x0, |
1151 | 14 | NULL, HFILL }}, |
1152 | 14 | { &hf_imf_discarded_x400_mts_extensions, |
1153 | 14 | { "Discarded-X400-MTS-Extensions", "imf.discarded_x400_mts_extensions", FT_STRING, BASE_NONE, NULL, 0x0, |
1154 | 14 | NULL, HFILL }}, |
1155 | 14 | { &hf_imf_dl_expansion_history, |
1156 | 14 | { "DL-Expansion-History", "imf.dl_expansion_history", FT_STRING, BASE_NONE, NULL, 0x0, |
1157 | 14 | NULL, HFILL }}, |
1158 | 14 | { &hf_imf_deferred_delivery, |
1159 | 14 | { "Deferred-Delivery", "imf.deferred_delivery", FT_STRING, BASE_NONE, NULL, 0x0, |
1160 | 14 | NULL, HFILL }}, |
1161 | 14 | { &hf_imf_expires, |
1162 | 14 | { "Expires", "imf.expires", FT_STRING, BASE_NONE, NULL, 0x0, |
1163 | 14 | NULL, HFILL }}, |
1164 | 14 | { &hf_imf_importance, |
1165 | 14 | { "Importance", "imf.importance", FT_STRING, BASE_NONE, NULL, 0x0, |
1166 | 14 | NULL, HFILL }}, |
1167 | 14 | { &hf_imf_incomplete_copy, |
1168 | 14 | { "Incomplete-Copy", "imf.incomplete_copy", FT_STRING, BASE_NONE, NULL, 0x0, |
1169 | 14 | NULL, HFILL }}, |
1170 | 14 | { &hf_imf_latest_delivery_time, |
1171 | 14 | { "Latest-Delivery-Time", "imf.latest_delivery_time", FT_STRING, BASE_NONE, NULL, 0x0, |
1172 | 14 | NULL, HFILL }}, |
1173 | 14 | { &hf_imf_message_type, |
1174 | 14 | { "Message-Type", "imf.message_type", FT_STRING, BASE_NONE, NULL, 0x0, |
1175 | 14 | NULL, HFILL }}, |
1176 | 14 | { &hf_imf_original_encoded_information_types, |
1177 | 14 | { "Original-Encoded-Information-Types", "imf.original_encoded_information_types", FT_STRING, BASE_NONE, NULL, 0x0, |
1178 | 14 | NULL, HFILL }}, |
1179 | 14 | { &hf_imf_originator_return_address, |
1180 | 14 | { "Originator-Return-Address", "imf.originator_return_address", FT_STRING, BASE_NONE, NULL, 0x0, |
1181 | 14 | NULL, HFILL }}, |
1182 | 14 | { &hf_imf_priority, |
1183 | 14 | { "Priority", "imf.priority", FT_STRING, BASE_NONE, NULL, 0x0, |
1184 | 14 | NULL, HFILL }}, |
1185 | 14 | { &hf_imf_reply_by, |
1186 | 14 | { "Reply-By", "imf.reply_by", FT_STRING, BASE_NONE, NULL, 0x0, |
1187 | 14 | NULL, HFILL }}, |
1188 | 14 | { &hf_imf_sensitivity, |
1189 | 14 | { "Sensitivity", "imf.sensitivity", FT_STRING, BASE_NONE, NULL, 0x0, |
1190 | 14 | NULL, HFILL }}, |
1191 | 14 | { &hf_imf_supersedes, |
1192 | 14 | { "Supersedes", "imf.supersedes", FT_STRING, BASE_NONE, NULL, 0x0, |
1193 | 14 | NULL, HFILL }}, |
1194 | 14 | { &hf_imf_x400_content_type, |
1195 | 14 | { "X400-Content-Type", "imf.x400_content_type", FT_STRING, BASE_NONE, NULL, 0x0, |
1196 | 14 | NULL, HFILL }}, |
1197 | 14 | { &hf_imf_x400_mts_identifier, |
1198 | 14 | { "X400-MTS-Identifier", "imf.x400_mts_identifier", FT_STRING, BASE_NONE, NULL, 0x0, |
1199 | 14 | NULL, HFILL }}, |
1200 | 14 | { &hf_imf_x400_originator, |
1201 | 14 | { "X400-Originator", "imf.x400_originator", FT_STRING, BASE_NONE, NULL, 0x0, |
1202 | 14 | NULL, HFILL }}, |
1203 | 14 | { &hf_imf_x400_received, |
1204 | 14 | { "X400-Received", "imf.x400_received", FT_STRING, BASE_NONE, NULL, 0x0, |
1205 | 14 | NULL, HFILL }}, |
1206 | 14 | { &hf_imf_x400_recipients, |
1207 | 14 | { "X400-Recipients", "imf.x400_recipients", FT_STRING, BASE_NONE, NULL, 0x0, |
1208 | 14 | NULL, HFILL }}, |
1209 | 14 | { &hf_imf_delivered_to, |
1210 | 14 | { "Delivered-To", "imf.delivered_to", FT_STRING, BASE_NONE, NULL, 0x0, |
1211 | 14 | NULL, HFILL }}, |
1212 | 14 | { &hf_imf_ext_mailer, |
1213 | 14 | { "X-Mailer", "imf.ext.mailer", FT_STRING, BASE_NONE, NULL, 0x0, |
1214 | 14 | NULL, HFILL }}, |
1215 | 14 | { &hf_imf_ext_mimeole, |
1216 | 14 | { "X-MimeOLE", "imf.ext.mimeole", FT_STRING, BASE_NONE, NULL, 0x0, |
1217 | 14 | NULL, HFILL }}, |
1218 | 14 | { &hf_imf_ext_expiry_date, |
1219 | 14 | { "Expiry-Date", "imf.ext.expiry-date", FT_STRING, BASE_NONE, NULL, 0x0, |
1220 | 14 | NULL, HFILL }}, |
1221 | 14 | { &hf_imf_ext_tnef_correlator, |
1222 | 14 | { "X-MS-TNEF-Correlator", "imf.ext.tnef-correlator", FT_STRING, BASE_NONE, NULL, 0x0, |
1223 | 14 | NULL, HFILL }}, |
1224 | 14 | { &hf_imf_ext_uidl, |
1225 | 14 | { "X-UIDL", "imf.ext.uidl", FT_STRING, BASE_NONE, NULL, 0x0, |
1226 | 14 | NULL, HFILL }}, |
1227 | 14 | { &hf_imf_ext_authentication_warning, |
1228 | 14 | { "X-Authentication-Warning", "imf.ext.authentication_warning", FT_STRING, BASE_NONE, |
1229 | 14 | NULL, 0x0, NULL, HFILL }}, |
1230 | 14 | { &hf_imf_ext_virus_scanned, |
1231 | 14 | { "X-Virus-Scanned", "imf.ext.virus_scanned", FT_STRING, BASE_NONE, NULL, 0x0, |
1232 | 14 | NULL, HFILL }}, |
1233 | 14 | { &hf_imf_ext_original_to, |
1234 | 14 | { "X-Original-To", "imf.ext.original-to", FT_STRING, BASE_NONE, NULL, 0x0, |
1235 | 14 | NULL, HFILL }}, |
1236 | 14 | { &hf_imf_thread_index, |
1237 | 14 | { "Thread-Index", "imf.thread-index", FT_STRING, BASE_NONE, NULL, 0x0, |
1238 | 14 | NULL, HFILL }}, |
1239 | 14 | { &hf_imf_lines, |
1240 | 14 | { "Lines", "imf.lines", FT_STRING, BASE_NONE, NULL, 0x0, |
1241 | 14 | NULL, HFILL }}, |
1242 | 14 | { &hf_imf_precedence, |
1243 | 14 | { "Precedence", "imf.precedence", FT_STRING, BASE_NONE, NULL, 0x0, |
1244 | 14 | NULL, HFILL }}, |
1245 | 14 | { &hf_imf_extension, |
1246 | 14 | { "Unknown-Extension", "imf.extension", FT_STRING, BASE_NONE, NULL, 0x0, |
1247 | 14 | NULL, HFILL }}, |
1248 | 14 | { &hf_imf_extension_type, |
1249 | 14 | { "Type", "imf.extension.type", FT_STRING, BASE_NONE, NULL, 0x0, |
1250 | 14 | NULL, HFILL }}, |
1251 | 14 | { &hf_imf_extension_value, |
1252 | 14 | { "Value", "imf.extension.value", FT_STRING, BASE_NONE, NULL, 0x0, |
1253 | 14 | NULL, HFILL }}, |
1254 | 14 | { &hf_imf_display_name, |
1255 | 14 | { "Display-Name", "imf.display_name", FT_STRING, BASE_NONE, NULL, 0x0, |
1256 | 14 | NULL, HFILL }}, |
1257 | 14 | { &hf_imf_address, |
1258 | 14 | { "Address", "imf.address", FT_STRING, BASE_NONE, NULL, 0x0, |
1259 | 14 | NULL, HFILL }}, |
1260 | | #if 0 |
1261 | | { &hf_imf_address_list, |
1262 | | { "Address List", "imf.address_list", FT_UINT32, BASE_DEC, NULL, 0x0, |
1263 | | NULL, HFILL }}, |
1264 | | #endif |
1265 | 14 | { &hf_imf_address_list_item, |
1266 | 14 | { "Item", "imf.address_list.item", FT_STRING, BASE_NONE, NULL, 0x0, |
1267 | 14 | NULL, HFILL }}, |
1268 | | #if 0 |
1269 | | { &hf_imf_mailbox_list, |
1270 | | { "Mailbox List", "imf.mailbox_list", FT_UINT32, BASE_DEC, NULL, 0x0, |
1271 | | NULL, HFILL }}, |
1272 | | #endif |
1273 | 14 | { &hf_imf_mailbox_list_item, |
1274 | 14 | { "Item", "imf.mailbox_list.item", FT_STRING, BASE_NONE, NULL, 0x0, |
1275 | 14 | NULL, HFILL }}, |
1276 | 14 | { &hf_imf_siolabel, |
1277 | 14 | { "SIO-Label", "imf.siolabel", FT_NONE, BASE_NONE, NULL, 0x0, |
1278 | 14 | NULL, HFILL }}, |
1279 | 14 | { &hf_imf_siolabel_marking, |
1280 | 14 | { "Marking", "imf.siolabel.marking", FT_STRING, BASE_NONE, NULL, 0x0, |
1281 | 14 | NULL, HFILL }}, |
1282 | 14 | { &hf_imf_siolabel_fgcolor, |
1283 | 14 | { "Foreground Color", "imf.siolabel.fgcolor", FT_STRING, BASE_NONE, NULL, 0x0, |
1284 | 14 | NULL, HFILL }}, |
1285 | 14 | { &hf_imf_siolabel_bgcolor, |
1286 | 14 | { "Background Color", "imf.siolabel.bgcolor", FT_STRING, BASE_NONE, NULL, 0x0, |
1287 | 14 | NULL, HFILL }}, |
1288 | 14 | { &hf_imf_siolabel_type, |
1289 | 14 | { "Type", "imf.siolabel.type", FT_STRING, BASE_NONE, NULL, 0x0, |
1290 | 14 | NULL, HFILL }}, |
1291 | 14 | { &hf_imf_siolabel_label, |
1292 | 14 | { "Label", "imf.siolabel.label", FT_STRING, BASE_NONE, NULL, 0x0, |
1293 | 14 | NULL, HFILL }}, |
1294 | 14 | { &hf_imf_siolabel_unknown, |
1295 | 14 | { "Unknown parameter", "imf.siolabel.unknown", FT_STRING, BASE_NONE, NULL, 0x0, |
1296 | 14 | NULL, HFILL }}, |
1297 | 14 | { &hf_imf_message_text, |
1298 | 14 | { "Message-Text", "imf.message_text", FT_NONE, BASE_NONE, NULL, 0x0, |
1299 | 14 | NULL, HFILL }}, |
1300 | 14 | }; |
1301 | 14 | static int *ett[] = { |
1302 | 14 | &ett_imf, |
1303 | 14 | &ett_imf_content_type, |
1304 | 14 | &ett_imf_group, |
1305 | 14 | &ett_imf_mailbox, |
1306 | 14 | &ett_imf_mailbox_list, |
1307 | 14 | &ett_imf_address_list, |
1308 | 14 | &ett_imf_siolabel, |
1309 | 14 | &ett_imf_extension, |
1310 | 14 | &ett_imf_message_text, |
1311 | 14 | }; |
1312 | | |
1313 | 14 | static ei_register_info ei[] = { |
1314 | 14 | { &ei_imf_unknown_param, { "imf.unknown_param", PI_PROTOCOL, PI_WARN, "Unknown parameter", EXPFILL }}, |
1315 | 14 | }; |
1316 | | |
1317 | 14 | static uat_field_t attributes_flds[] = { |
1318 | 14 | UAT_FLD_CSTRING(header_fields, header_name, "Header name", "IMF header name"), |
1319 | 14 | UAT_FLD_CSTRING(header_fields, description, "Description", "Description of the value contained in the header"), |
1320 | 14 | UAT_FLD_VS(header_fields, header_format, "Format", header_format, 0), |
1321 | 14 | UAT_FLD_VS(header_fields, add_to_col_info, "Add to Info column", add_to_col_info, 0), |
1322 | 14 | UAT_END_FIELDS |
1323 | 14 | }; |
1324 | | |
1325 | 14 | uat_t *headers_uat = uat_new("Custom IMF headers", |
1326 | 14 | sizeof(header_field_t), |
1327 | 14 | "imf_header_fields", |
1328 | 14 | true, |
1329 | 14 | &header_fields, |
1330 | 14 | &num_header_fields, |
1331 | | /* specifies named fields, so affects dissection |
1332 | | and the set of named fields */ |
1333 | 14 | UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS, |
1334 | 14 | NULL, |
1335 | 14 | header_fields_copy_cb, |
1336 | 14 | header_fields_update_cb, |
1337 | 14 | header_fields_free_cb, |
1338 | 14 | header_fields_post_update_cb, |
1339 | 14 | header_fields_reset_cb, |
1340 | 14 | attributes_flds); |
1341 | | |
1342 | 14 | module_t *imf_module; |
1343 | 14 | expert_module_t* expert_imf; |
1344 | 14 | const struct imf_field *f; |
1345 | | |
1346 | 14 | proto_imf = proto_register_protocol("Internet Message Format", "IMF", "imf"); |
1347 | | |
1348 | 14 | proto_register_field_array(proto_imf, hf, array_length(hf)); |
1349 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1350 | 14 | expert_imf = expert_register_protocol(proto_imf); |
1351 | 14 | expert_register_field_array(expert_imf, ei, array_length(ei)); |
1352 | | |
1353 | | /* Allow dissector to find be found by name. */ |
1354 | 14 | imf_handle = register_dissector("imf", dissect_imf, proto_imf); |
1355 | | |
1356 | 14 | imf_module = prefs_register_protocol(proto_imf, NULL); |
1357 | 14 | prefs_register_uat_preference(imf_module, "custom_header_fields", "Custom IMF headers", |
1358 | 14 | "A table to define custom IMF headers for which fields can be " |
1359 | 14 | "setup and used for filtering/data extraction etc.", |
1360 | 14 | headers_uat); |
1361 | | |
1362 | 14 | imf_field_table=wmem_map_new(wmem_epan_scope(), wmem_str_hash, g_str_equal); /* oid to syntax */ |
1363 | | |
1364 | | /* register the fields for lookup */ |
1365 | 980 | for(f = imf_fields; f->name; f++) |
1366 | 966 | wmem_map_insert(imf_field_table, (void *)f->name, (void *)f); |
1367 | | |
1368 | | /* Register for tapping */ |
1369 | 14 | imf_eo_tap = register_export_object(proto_imf, imf_eo_packet, NULL); |
1370 | | |
1371 | 14 | } |
1372 | | |
1373 | | /* The registration hand-off routine */ |
1374 | | void |
1375 | | proto_reg_handoff_imf(void) |
1376 | 14 | { |
1377 | 14 | dissector_add_string("media_type", |
1378 | 14 | "message/rfc822", imf_handle); |
1379 | | |
1380 | 14 | register_ber_oid_dissector_handle("1.2.840.113549.1.7.1", imf_handle, proto_imf, "id-data"); |
1381 | | |
1382 | | /* |
1383 | | * Get the content type and Internet media type table |
1384 | | */ |
1385 | 14 | media_type_dissector_table = find_dissector_table("media_type"); |
1386 | | |
1387 | 14 | } |
1388 | | |
1389 | | /* |
1390 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1391 | | * |
1392 | | * Local Variables: |
1393 | | * c-basic-offset: 2 |
1394 | | * tab-width: 8 |
1395 | | * indent-tabs-mode: nil |
1396 | | * End: |
1397 | | * |
1398 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
1399 | | * :indentSize=2:tabSize=8:noTabs=true: |
1400 | | */ |