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