2 * Routines for Internet Message Format (IMF) packet disassembly
6 * Copyright (c) 2007 by Graeme Lunt
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1999 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/packet.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/strutil.h>
36 #include <epan/prefs.h>
38 #include <epan/base64.h>
39 #include <epan/expert.h>
41 #include <wsutil/str_util.h>
43 #include "packet-ber.h"
44 #include "packet-imf.h"
45 #include "packet-ess.h"
46 #include "packet-p1.h"
48 #define PNAME "Internet Message Format"
52 static int proto_imf = -1;
54 static int hf_imf_date = -1;
55 static int hf_imf_from = -1;
56 static int hf_imf_sender = -1;
57 static int hf_imf_reply_to = -1;
58 static int hf_imf_to = -1;
59 static int hf_imf_cc = -1;
60 static int hf_imf_bcc = -1;
61 static int hf_imf_message_id = -1;
62 static int hf_imf_in_reply_to = -1;
63 static int hf_imf_references = -1;
64 static int hf_imf_subject = -1;
65 static int hf_imf_comments = -1;
66 static int hf_imf_user_agent = -1;
67 static int hf_imf_keywords = -1;
68 static int hf_imf_resent_date = -1;
69 static int hf_imf_resent_from = -1;
70 static int hf_imf_resent_sender = -1;
71 static int hf_imf_resent_to = -1;
72 static int hf_imf_resent_cc = -1;
73 static int hf_imf_resent_bcc = -1;
74 static int hf_imf_resent_message_id = -1;
75 static int hf_imf_return_path = -1;
76 static int hf_imf_received = -1;
77 static int hf_imf_content_type = -1;
78 static int hf_imf_content_type_type = -1;
79 static int hf_imf_content_type_parameters = -1;
80 static int hf_imf_content_id = -1;
81 static int hf_imf_content_transfer_encoding = -1;
82 static int hf_imf_content_description = -1;
83 static int hf_imf_mime_version = -1;
84 static int hf_imf_thread_index = -1;
85 static int hf_imf_ext_mailer = -1;
86 static int hf_imf_ext_mimeole = -1;
87 static int hf_imf_ext_tnef_correlator = -1;
88 static int hf_imf_ext_expiry_date = -1;
89 static int hf_imf_ext_uidl = -1;
90 static int hf_imf_ext_authentication_warning = -1;
91 static int hf_imf_ext_virus_scanned = -1;
92 static int hf_imf_extension = -1;
93 static int hf_imf_extension_type = -1;
94 static int hf_imf_extension_value = -1;
97 static int hf_imf_autoforwarded = -1;
98 static int hf_imf_autosubmitted = -1;
99 static int hf_imf_x400_content_identifier = -1;
100 static int hf_imf_content_language = -1;
101 static int hf_imf_conversion = -1;
102 static int hf_imf_conversion_with_loss = -1;
103 static int hf_imf_delivery_date = -1;
104 static int hf_imf_discarded_x400_ipms_extensions = -1;
105 static int hf_imf_discarded_x400_mts_extensions = -1;
106 static int hf_imf_dl_expansion_history = -1;
107 static int hf_imf_deferred_delivery = -1;
108 static int hf_imf_expires = -1;
109 static int hf_imf_importance = -1;
110 static int hf_imf_incomplete_copy = -1;
111 static int hf_imf_latest_delivery_time = -1;
112 static int hf_imf_message_type = -1;
113 static int hf_imf_original_encoded_information_types = -1;
114 static int hf_imf_originator_return_address = -1;
115 static int hf_imf_priority = -1;
116 static int hf_imf_reply_by = -1;
117 static int hf_imf_sensitivity = -1;
118 static int hf_imf_supersedes = -1;
119 static int hf_imf_x400_content_type = -1;
120 static int hf_imf_x400_mts_identifier = -1;
121 static int hf_imf_x400_originator = -1;
122 static int hf_imf_x400_received = -1;
123 static int hf_imf_x400_recipients = -1;
125 static int hf_imf_delivered_to = -1;
127 static int hf_imf_message_text = -1;
129 static int hf_imf_display_name = -1;
130 static int hf_imf_address = -1;
131 static int hf_imf_mailbox_list = -1;
132 static int hf_imf_mailbox_list_item = -1;
133 static int hf_imf_address_list = -1;
134 static int hf_imf_address_list_item = -1;
136 /* draft-zeilenga-email-seclabel-04 */
137 static int hf_imf_siolabel = -1;
138 static int hf_imf_siolabel_marking = -1;
139 static int hf_imf_siolabel_fgcolor = -1;
140 static int hf_imf_siolabel_bgcolor = -1;
141 static int hf_imf_siolabel_type = -1;
142 static int hf_imf_siolabel_label = -1;
143 static int hf_imf_siolabel_unknown = -1;
145 static int ett_imf = -1;
146 static int ett_imf_content_type = -1;
147 static int ett_imf_mailbox = -1;
148 static int ett_imf_group = -1;
149 static int ett_imf_mailbox_list = -1;
150 static int ett_imf_address_list = -1;
151 static int ett_imf_siolabel = -1;
152 static int ett_imf_extension = -1;
153 static int ett_imf_message_text = -1;
156 const char *name; /* field name - in lower case for matching purposes */
157 int *hf_id; /* wireshark field */
158 void (*subdissector)(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
159 gboolean add_to_col_info; /* add field to column info */
162 #define NO_SUBDISSECTION NULL
164 static void dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
165 static void dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
166 static void dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
167 static void dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
168 static void dissect_imf_siolabel(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo);
170 static struct imf_field imf_fields[] = {
171 {"unknown-extension", &hf_imf_extension_type, NO_SUBDISSECTION, FALSE}, /* unknown extension */
172 {"date", &hf_imf_date, NO_SUBDISSECTION, FALSE}, /* date-time */
173 {"from", &hf_imf_from, dissect_imf_mailbox_list , TRUE}, /* mailbox_list */
174 {"sender", &hf_imf_sender, dissect_imf_mailbox, FALSE}, /* mailbox */
175 {"reply-to", &hf_imf_reply_to, dissect_imf_address_list , FALSE}, /* address_list */
176 {"to", &hf_imf_to, dissect_imf_address_list , FALSE}, /* address_list */
177 {"cc", &hf_imf_cc, dissect_imf_address_list , FALSE}, /* address_list */
178 {"bcc", &hf_imf_bcc, dissect_imf_address_list , FALSE}, /* address_list */
179 {"message-id", &hf_imf_message_id, NO_SUBDISSECTION, FALSE}, /* msg-id */
180 {"in-reply-to", &hf_imf_in_reply_to, NO_SUBDISSECTION, FALSE}, /* msg-id */
181 {"references", &hf_imf_references, NO_SUBDISSECTION, FALSE}, /* msg-id */
182 {"subject", &hf_imf_subject, NO_SUBDISSECTION, TRUE}, /* unstructured */
183 {"comments", &hf_imf_comments, NO_SUBDISSECTION, FALSE}, /* unstructured */
184 {"user-agent", &hf_imf_user_agent, NO_SUBDISSECTION, FALSE}, /* unstructured */
185 {"keywords", &hf_imf_keywords, NULL, FALSE}, /* phrase_list */
186 {"resent-date", &hf_imf_resent_date, NO_SUBDISSECTION, FALSE},
187 {"resent-from", &hf_imf_resent_from, dissect_imf_mailbox_list, FALSE},
188 {"resent-sender", &hf_imf_resent_sender, dissect_imf_mailbox, FALSE},
189 {"resent-to", &hf_imf_resent_to, dissect_imf_address_list, FALSE},
190 {"resent-cc", &hf_imf_resent_cc, dissect_imf_address_list, FALSE},
191 {"resent-bcc", &hf_imf_resent_bcc, dissect_imf_address_list, FALSE},
192 {"resent-message-id", &hf_imf_resent_message_id, NO_SUBDISSECTION, FALSE},
193 {"return-path", &hf_imf_return_path, NULL, FALSE},
194 {"received", &hf_imf_received, NO_SUBDISSECTION, FALSE},
195 /* these are really multi-part - but we parse them anyway */
196 {"content-type", &hf_imf_content_type, NULL, FALSE}, /* handled separately as a special case */
197 {"content-id", &hf_imf_content_id, NULL, FALSE},
198 {"content-description", &hf_imf_content_description, NULL, FALSE},
199 {"content-transfer-encoding", &hf_imf_content_transfer_encoding, NULL, FALSE},
200 {"mime-version", &hf_imf_mime_version, NO_SUBDISSECTION, FALSE},
201 /* MIXER - RFC 2156 */
202 {"autoforwarded", &hf_imf_autoforwarded, NULL, FALSE},
203 {"autosubmitted", &hf_imf_autosubmitted, NULL, FALSE},
204 {"x400-content-identifier", &hf_imf_x400_content_identifier, NULL, FALSE},
205 {"content-language", &hf_imf_content_language, NULL, FALSE},
206 {"conversion", &hf_imf_conversion, NULL, FALSE},
207 {"conversion-with-loss", &hf_imf_conversion_with_loss, NULL, FALSE},
208 {"delivery-date", &hf_imf_delivery_date, NULL, FALSE},
209 {"discarded-x400-ipms-extensions", &hf_imf_discarded_x400_ipms_extensions, NULL, FALSE},
210 {"discarded-x400-mts-extensions", &hf_imf_discarded_x400_mts_extensions, NULL, FALSE},
211 {"dl-expansion-history", &hf_imf_dl_expansion_history, NULL, FALSE},
212 {"deferred-delivery", &hf_imf_deferred_delivery, NULL, FALSE},
213 {"expires", &hf_imf_expires, NULL, FALSE},
214 {"importance", &hf_imf_importance, NULL, FALSE},
215 {"incomplete-copy", &hf_imf_incomplete_copy, NULL, FALSE},
216 {"latest-delivery-time", &hf_imf_latest_delivery_time, NULL, FALSE},
217 {"message-type", &hf_imf_message_type, NULL, FALSE},
218 {"original-encoded-information-types", &hf_imf_original_encoded_information_types, NULL, FALSE},
219 {"originator-return-address", &hf_imf_originator_return_address, NULL, FALSE},
220 {"priority", &hf_imf_priority, NULL, FALSE},
221 {"reply-by", &hf_imf_reply_by, NULL, FALSE},
222 {"sensitivity", &hf_imf_sensitivity, NULL, FALSE},
223 {"supersedes", &hf_imf_supersedes, NULL, FALSE},
224 {"x400-content-type", &hf_imf_x400_content_type, NULL, FALSE},
225 {"x400-mts-identifier", &hf_imf_x400_mts_identifier, NULL, FALSE},
226 {"x400-originator", &hf_imf_x400_originator, NULL, FALSE},
227 {"x400-received", &hf_imf_x400_received, NULL, FALSE},
228 {"x400-recipients", &hf_imf_x400_recipients, NULL, FALSE},
230 {"delivered-to", &hf_imf_delivered_to, dissect_imf_mailbox, FALSE}, /* mailbox */
232 {"x-mailer", &hf_imf_ext_mailer, NO_SUBDISSECTION, FALSE}, /* unstructured */
233 {"thread-index", &hf_imf_thread_index, NO_SUBDISSECTION, FALSE}, /* unstructured */
234 {"x-mimeole", &hf_imf_ext_mimeole, NO_SUBDISSECTION, FALSE}, /* unstructured */
235 {"expiry-date", &hf_imf_ext_expiry_date, NO_SUBDISSECTION, FALSE}, /* unstructured */
236 {"x-ms-tnef-correlator", &hf_imf_ext_tnef_correlator, NO_SUBDISSECTION, FALSE}, /* unstructured */
237 {"x-uidl", &hf_imf_ext_uidl, NO_SUBDISSECTION, FALSE}, /* unstructured */
238 {"x-authentication-warning", &hf_imf_ext_authentication_warning, NO_SUBDISSECTION, FALSE}, /* unstructured */
239 {"x-virus-scanned", &hf_imf_ext_virus_scanned, NO_SUBDISSECTION, FALSE}, /* unstructured */
240 {"sio-label", &hf_imf_siolabel, dissect_imf_siolabel, FALSE}, /* sio-label */
241 {NULL, NULL, NULL, FALSE},
244 static GHashTable *imf_field_table=NULL;
246 #define FORMAT_UNSTRUCTURED 0
247 #define FORMAT_MAILBOX 1
248 #define FORMAT_ADDRESS 2
249 #define FORMAT_MAILBOX_LIST 3
250 #define FORMAT_ADDRESS_LIST 4
251 #define FORMAT_SIO_LABEL 5
253 static const value_string header_format[] = {
254 { FORMAT_UNSTRUCTURED, "Unstructured" },
255 { FORMAT_MAILBOX, "Mailbox" },
256 { FORMAT_ADDRESS, "Address" },
257 { FORMAT_MAILBOX_LIST, "Mailbox List" },
258 { FORMAT_ADDRESS_LIST, "Address List" },
259 { FORMAT_SIO_LABEL, "SIO-Label" },
263 static const value_string add_to_col_info[] = {
269 typedef struct _header_field_t {
273 guint add_to_col_info;
276 static header_field_t *header_fields = NULL;
277 static guint num_header_fields = 0;
279 static GHashTable *custom_field_table = NULL;
282 header_fields_update_cb(void *r, const char **err)
284 header_field_t *rec = r;
286 if (rec->header_name == NULL) {
287 *err = ep_strdup_printf("Header name can't be empty");
289 g_strstrip(rec->header_name);
290 if (rec->header_name[0] == 0) {
291 *err = ep_strdup_printf("Header name can't be empty");
299 header_fields_copy_cb(void *n, const void *o, size_t siz _U_)
301 header_field_t *new_rec = n;
302 const header_field_t *old_rec = o;
304 new_rec->header_name = g_strdup(old_rec->header_name);
305 new_rec->description = g_strdup(old_rec->description);
306 new_rec->header_format = old_rec->header_format;
307 new_rec->add_to_col_info = old_rec->add_to_col_info;
313 header_fields_free_cb(void *r)
315 header_field_t *rec = r;
317 g_free(rec->header_name);
318 g_free(rec->description);
321 UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
322 UAT_CSTRING_CB_DEF(header_fields, description, header_field_t)
323 UAT_VS_DEF(header_fields, header_format, header_field_t, 0, "Unstructured")
324 UAT_VS_DEF(header_fields, add_to_col_info, header_field_t, 0, "No")
327 /* Define media_type/Content type table */
328 static dissector_table_t media_type_dissector_table;
331 dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
333 proto_tree *group_tree;
334 proto_item *group_item;
337 /* if there is a colon present it is a group */
338 if((addr_pos = tvb_find_guint8(tvb, offset, length, ':')) == -1) {
340 /* there isn't - so it must be a mailbox */
341 dissect_imf_mailbox(tvb, offset, length, item, pinfo);
346 group_tree = proto_item_add_subtree(item, ett_imf_group);
348 /* the display-name is mandatory */
349 group_item = proto_tree_add_item(group_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII|ENC_NA);
351 /* consume any whitespace */
352 for(addr_pos++ ;addr_pos < (offset + length); addr_pos++) {
353 if(!isspace(tvb_get_guint8(tvb, addr_pos))) {
358 if(tvb_get_guint8(tvb, addr_pos) != ';') {
360 dissect_imf_mailbox_list(tvb, addr_pos, length - (addr_pos - offset), group_item, pinfo);
362 /* XXX: need to check for final ';' */
370 dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo _U_)
372 proto_tree *mbox_tree;
373 int addr_pos, end_pos;
375 mbox_tree = proto_item_add_subtree(item, ett_imf_mailbox);
378 If we can't find and angle brackets, then the whole field is an address.
379 If we find angle brackets, then the address is between them and the display name is
380 anything before the opening angle bracket
383 if((addr_pos = tvb_find_guint8(tvb, offset, length, '<')) == -1) {
384 /* we can't find an angle bracket - the whole field is therefore the address */
386 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, offset, length, ENC_ASCII|ENC_NA);
389 /* we can find an angle bracket - let's see if we can find a display name */
390 /* XXX: the '<' could be in the display name */
392 for(; offset < addr_pos; offset++) {
393 if(!isspace(tvb_get_guint8(tvb, offset))) {
398 if(offset != addr_pos) { /* there is a display name */
399 (void) proto_tree_add_item(mbox_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII|ENC_NA);
401 end_pos = tvb_find_guint8(tvb, addr_pos + 1, length - (addr_pos + 1 - offset), '>');
404 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, addr_pos + 1, end_pos - addr_pos - 1, ENC_ASCII|ENC_NA);
410 dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
412 proto_item *addr_item = NULL;
413 proto_tree *tree = NULL;
419 /* a comma separated list of addresses */
420 tree = proto_item_add_subtree(item, ett_imf_address_list);
422 item_offset = offset;
426 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
428 count++; /* increase the number of items */
430 if(end_offset == -1) {
431 /* length is to the end of the buffer */
432 item_length = length - (item_offset - offset);
434 item_length = end_offset - item_offset;
436 addr_item = proto_tree_add_item(tree, hf_imf_address_list_item, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
437 dissect_imf_address(tvb, item_offset, item_length, addr_item, pinfo);
439 if(end_offset != -1) {
440 item_offset = end_offset + 1;
442 } while(end_offset != -1);
444 /* now indicate the number of items found */
445 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
449 dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
451 proto_item *mbox_item = NULL;
452 proto_tree *tree = NULL;
458 /* a comma separated list of mailboxes */
459 tree = proto_item_add_subtree(item, ett_imf_mailbox_list);
461 item_offset = offset;
465 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
467 count++; /* increase the number of items */
469 if(end_offset == -1) {
470 /* length is to the end of the buffer */
471 item_length = length - (item_offset - offset);
473 item_length = end_offset - item_offset;
475 mbox_item = proto_tree_add_item(tree, hf_imf_mailbox_list_item, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
476 dissect_imf_mailbox(tvb, item_offset, item_length, mbox_item, pinfo);
478 if(end_offset != -1) {
479 item_offset = end_offset + 1;
481 } while(end_offset != -1);
483 /* now indicate the number of items found */
484 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
488 dissect_imf_siolabel(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
490 proto_tree *tree = NULL;
491 proto_item *sub_item = NULL;
492 int item_offset, item_length;
493 int value_offset, value_length;
497 GString *label_string = g_string_new ("");
499 /* a semicolon separated list of attributes */
500 tree = proto_item_add_subtree(item, ett_imf_siolabel);
501 item_offset = offset;
504 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ';');
506 /* skip leading space */
507 while (isspace(tvb_get_guint8(tvb, item_offset))) {
511 if (end_offset == -1) {
512 /* length is to the end of the buffer */
513 item_length = tvb_find_line_end(tvb, item_offset, length - (item_offset - offset), NULL, FALSE);
515 item_length = end_offset - item_offset;
518 value_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), '=') + 1;
519 while (isspace(tvb_get_guint8(tvb, value_offset))) {
523 value_length = item_length - (value_offset - item_offset);
524 while (isspace(tvb_get_guint8(tvb, value_offset + value_length - 1))) {
528 if (tvb_strneql(tvb, item_offset, "marking", 7) == 0) {
529 proto_item_append_text(item, ": %s", tvb_get_ephemeral_string(tvb, value_offset, value_length));
530 proto_tree_add_item(tree, hf_imf_siolabel_marking, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
532 } else if (tvb_strneql(tvb, item_offset, "fgcolor", 7) == 0) {
533 proto_tree_add_item(tree, hf_imf_siolabel_fgcolor, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
535 } else if (tvb_strneql(tvb, item_offset, "bgcolor", 7) == 0) {
536 proto_tree_add_item(tree, hf_imf_siolabel_bgcolor, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
538 } else if (tvb_strneql(tvb, item_offset, "type", 4) == 0) {
539 type = tvb_get_ephemeral_string(tvb, value_offset + 1, value_length - 2); /* quoted */
540 proto_tree_add_item(tree, hf_imf_siolabel_type, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
542 } else if (tvb_strneql(tvb, item_offset, "label", 5) == 0) {
543 gchar *label = tvb_get_ephemeral_string(tvb, value_offset + 1, value_length - 2); /* quoted */
544 label_string = g_string_append(label_string, label);
546 if (tvb_get_guint8(tvb, item_offset + 5) == '*') { /* continuations */
547 int num = strtol(tvb_get_ephemeral_string(tvb, item_offset + 6, value_offset - item_offset + 6), NULL, 10);
548 proto_tree_add_string_format(tree, hf_imf_siolabel_label, tvb, value_offset, value_length,
549 label, "Label[%d]: \"%s\"", num, label);
551 proto_tree_add_item(tree, hf_imf_siolabel_label, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
555 sub_item = proto_tree_add_item(tree, hf_imf_siolabel_unknown, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
556 expert_add_info_format(pinfo, sub_item, PI_PROTOCOL, PI_WARN, "Unknown parameter");
559 if (end_offset != -1) {
560 item_offset = end_offset + 1;
562 } while (end_offset != -1);
564 if (type && label_string->len > 0) {
565 if (strcmp (type, ":ess") == 0) {
566 label_tvb = base64_to_tvb(tvb, label_string->str);
567 add_new_data_source(pinfo, label_tvb, "ESS Security Label");
568 dissect_ess_ESSSecurityLabel_PDU(label_tvb, pinfo, tree);
569 } else if (strcmp (type, ":x411") == 0) {
570 label_tvb = base64_to_tvb(tvb, label_string->str);
571 add_new_data_source(pinfo, label_tvb, "X.411 Security Label");
572 dissect_p1_MessageSecurityLabel_PDU(label_tvb, pinfo, tree);
576 g_string_free (label_string, TRUE);
580 dissect_imf_content_type(tvbuff_t *tvb, int offset, int length, proto_item *item,
581 char **type, char **parameters)
588 /* first strip any whitespace */
589 for(i = 0; i < length; i++) {
590 if(!isspace(tvb_get_guint8(tvb, offset + i))) {
596 /* find the first colon - there has to be a colon as there will have to be a boundary */
597 first_colon = tvb_find_guint8(tvb, offset, length, ';');
599 if(first_colon != -1) {
600 ct_tree = proto_item_add_subtree(item, ett_imf_content_type);
602 len = first_colon - offset;
603 proto_tree_add_item(ct_tree, hf_imf_content_type_type, tvb, offset, len, ENC_ASCII|ENC_NA);
605 /* This string will be automatically freed */
606 (*type) = tvb_get_ephemeral_string(tvb, offset, len);
608 len = tvb_find_line_end(tvb, first_colon + 1, length, NULL, FALSE);
609 proto_tree_add_item(ct_tree, hf_imf_content_type_parameters, tvb, first_colon + 1, len, ENC_ASCII|ENC_NA);
611 /* This string will be automatically freed */
612 (*parameters) = tvb_get_ephemeral_string(tvb, first_colon + 1, len);
619 imf_find_field_end(tvbuff_t *tvb, int offset, gint max_length, gboolean *last_field)
622 while(offset < max_length) {
625 offset = tvb_find_guint8(tvb, offset, max_length - offset, '\r');
628 if(tvb_get_guint8(tvb, ++offset) == '\n') {
629 /* OK - so we have found CRLF */
630 /* peek the next character */
631 switch(tvb_get_guint8(tvb, ++offset)) {
633 /* probably end of the fields */
634 if(tvb_get_guint8(tvb, ++offset) == '\n') {
643 /* continuation line */
646 /* this is a new field */
651 /* couldn't find a CR - strange */
657 return -1; /* Fail: No CR found (other than possible continuation) */
662 dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
665 proto_tree *unknown_tree, *text_tree;
666 char *content_type_str = NULL;
667 char *parameters = NULL;
669 gint start_offset = 0;
670 gint value_offset = 0;
671 gint unknown_offset = 0;
675 gboolean last_field = FALSE;
677 struct imf_field *f_info;
679 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
680 col_clear(pinfo->cinfo, COL_INFO);
683 item = proto_tree_add_item(tree, proto_imf, tvb, 0, -1, ENC_NA);
684 tree = proto_item_add_subtree(item, ett_imf);
687 max_length = tvb_length(tvb);
688 /* first go through the tvb until we find a blank line and extract the content type if
691 /* XXX: What if the tvb contains encrypted data ? is there a way to bypass dissection if so ? */
692 /* As it is, the following code blithely tries to parse what may be binary data. */
696 /* look for a colon first */
697 end_offset = tvb_find_guint8(tvb, start_offset, max_length - start_offset, ':');
699 if(end_offset == -1) {
700 /* we couldn't find another colon - strange - we should have broken out of here by now */
701 /* XXX: flag an error */
704 key = tvb_get_ephemeral_string(tvb, start_offset, end_offset - start_offset);
706 /* convert to lower case */
707 ascii_strdown_inplace (key);
709 /* look up the key in built-in fields */
710 f_info = (struct imf_field *)g_hash_table_lookup(imf_field_table, key);
712 if(f_info == NULL && custom_field_table) {
713 /* look up the key in custom fields */
714 f_info = (struct imf_field *)g_hash_table_lookup(custom_field_table, key);
718 /* set as an unknown extension */
720 unknown_offset = start_offset;
723 hf_id = *(f_info->hf_id);
725 /* value starts immediately after the colon */
726 start_offset = end_offset+1;
728 end_offset = imf_find_field_end(tvb, start_offset, max_length, &last_field);
729 if(end_offset == -1) {
730 break; /* Something's fishy */
733 /* remove any leading whitespace */
735 for(value_offset = start_offset; value_offset < end_offset; value_offset++)
736 if(!isspace(tvb_get_guint8(tvb, value_offset))) {
740 if(value_offset == end_offset) {
741 /* empty field - show whole value */
742 value_offset = start_offset;
745 if(hf_id == hf_imf_extension_type) {
747 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
748 item = proto_tree_add_item(tree, hf_imf_extension, tvb, unknown_offset, end_offset - unknown_offset - 2, ENC_ASCII|ENC_NA);
750 proto_item_append_text(item, " (Contact Wireshark developers if you want this supported.)");
752 unknown_tree = proto_item_add_subtree(item, ett_imf_extension);
754 proto_tree_add_item(unknown_tree, hf_imf_extension_type, tvb, unknown_offset, start_offset - 1 - unknown_offset, ENC_ASCII|ENC_NA);
756 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
757 item = proto_tree_add_item(unknown_tree, hf_imf_extension_value, tvb, start_offset, end_offset - start_offset - 2, ENC_ASCII|ENC_NA);
760 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
761 item = proto_tree_add_item(tree, hf_id, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA);
763 if(f_info->add_to_col_info && check_col(pinfo->cinfo, COL_INFO)) {
765 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s, ", f_info->name,
766 tvb_format_text(tvb, value_offset, end_offset - value_offset - 2));
769 if(hf_id == hf_imf_content_type) {
770 /* we need some additional processing to extract the content type and parameters */
772 dissect_imf_content_type(tvb, start_offset, end_offset - start_offset, item,
773 &content_type_str, ¶meters);
775 } else if(f_info->subdissector) {
777 /* we have a subdissector */
778 f_info->subdissector(tvb, value_offset, end_offset - value_offset, item, pinfo);
782 start_offset = end_offset;
785 if (end_offset == -1) {
789 /* specify a content type until we can work it out for ourselves */
790 /* content_type_str = "multipart/mixed"; */
792 /* now dissect the MIME based upon the content type */
794 if(content_type_str && media_type_dissector_table) {
796 pd_save = pinfo->private_data;
797 pinfo->private_data = parameters;
799 next_tvb = tvb_new_subset_remaining(tvb, end_offset);
801 dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree);
803 pinfo->private_data = pd_save;
806 /* just show the lines or highlight the rest of the buffer as message text */
808 item = proto_tree_add_item(tree, hf_imf_message_text, tvb, end_offset, -1 , ENC_NA);
809 text_tree = proto_item_add_subtree(item, ett_imf_message_text);
811 start_offset = end_offset;
812 while (tvb_offset_exists(tvb, start_offset)) {
815 * Find the end of the line.
817 tvb_find_line_end(tvb, start_offset, -1, &end_offset, FALSE);
822 proto_tree_add_text(text_tree, tvb, start_offset, end_offset - start_offset,
824 tvb_format_text_wsp(tvb, start_offset, end_offset - start_offset));
825 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
826 tvb_format_text_wsp(tvb, start_offset, end_offset - start_offset));
829 * Step to the next line.
831 start_offset = end_offset;
837 free_imf_field (gpointer data)
839 struct imf_field *imffield = (struct imf_field *) data;
841 g_free ((char *) imffield->name);
846 header_fields_initialize_cb (void)
848 static hf_register_info *hf;
850 struct imf_field *imffield;
854 if (custom_field_table) {
855 guint hf_size = g_hash_table_size (custom_field_table);
856 /* Unregister all fields */
857 for (i = 0; i < hf_size; i++) {
858 proto_unregister_field (proto_imf, *(hf[i].p_id));
861 g_free ((char *) hf[i].hfinfo.name);
862 g_free ((char *) hf[i].hfinfo.abbrev);
863 g_free ((char *) hf[i].hfinfo.blurb);
865 g_hash_table_destroy (custom_field_table);
867 custom_field_table = NULL;
870 if (num_header_fields) {
871 custom_field_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_imf_field);
872 hf = g_malloc0 (sizeof (hf_register_info) * num_header_fields);
874 for (i = 0; i < num_header_fields; i++) {
875 hf_id = g_malloc (sizeof (gint));
877 header_name = g_strdup (header_fields[i].header_name);
880 hf[i].hfinfo.name = header_name;
881 hf[i].hfinfo.abbrev = g_strdup_printf ("imf.header.%s", header_name);
882 hf[i].hfinfo.type = FT_STRING;
883 hf[i].hfinfo.display = BASE_NONE;
884 hf[i].hfinfo.strings = NULL;
885 hf[i].hfinfo.blurb = g_strdup (header_fields[i].description);
886 hf[i].hfinfo.same_name_prev = NULL;
887 hf[i].hfinfo.same_name_next = NULL;
889 imffield = g_malloc (sizeof (struct imf_field));
890 imffield->hf_id = hf_id;
891 imffield->name = ascii_strdown_inplace (g_strdup (header_name));
892 switch (header_fields[i].header_format) {
893 case FORMAT_UNSTRUCTURED:
894 imffield->subdissector = NO_SUBDISSECTION;
897 imffield->subdissector = dissect_imf_mailbox;
900 imffield->subdissector = dissect_imf_address;
902 case FORMAT_MAILBOX_LIST:
903 imffield->subdissector = dissect_imf_mailbox_list;
905 case FORMAT_ADDRESS_LIST:
906 imffield->subdissector = dissect_imf_address_list;
908 case FORMAT_SIO_LABEL:
909 hf[i].hfinfo.type = FT_NONE; /* constructed */
910 imffield->subdissector = dissect_imf_siolabel;
914 imffield->subdissector = NO_SUBDISSECTION;
917 imffield->add_to_col_info = header_fields[i].add_to_col_info;
918 g_hash_table_insert (custom_field_table, (gpointer)imffield->name, (gpointer)imffield);
921 proto_register_field_array (proto_imf, hf, num_header_fields);
925 /* Register all the bits needed by the filtering engine */
928 proto_register_imf(void)
930 static hf_register_info hf[] = {
932 { "Date", "imf.date", FT_STRING, BASE_NONE, NULL, 0x0,
933 "DateTime", HFILL }},
935 { "From", "imf.from", FT_STRING, BASE_NONE, NULL, 0x0,
936 "MailboxList", HFILL }},
938 { "Sender", "imf.sender", FT_STRING, BASE_NONE, NULL, 0x0,
941 { "Reply-To", "imf.reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
944 { "To", "imf.to", FT_STRING, BASE_NONE, NULL, 0x0,
947 { "Cc", "imf.cc", FT_STRING, BASE_NONE, NULL, 0x0,
950 { "Bcc", "imf.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
952 { &hf_imf_message_id,
953 { "Message-ID", "imf.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
955 { &hf_imf_in_reply_to,
956 { "In-Reply-To", "imf.in_reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
958 { &hf_imf_references,
959 { "References", "imf.references", FT_STRING, BASE_NONE, NULL, 0x0,
962 { "Subject", "imf.subject", FT_STRING, BASE_NONE, NULL, 0x0,
965 { "Comments", "imf.comments", FT_STRING, BASE_NONE, NULL, 0x0,
967 { &hf_imf_user_agent,
968 { "User-Agent", "imf.user_agent", FT_STRING, BASE_NONE, NULL, 0x0,
971 { "Keywords", "imf.keywords", FT_STRING, BASE_NONE, NULL, 0x0,
973 { &hf_imf_resent_date,
974 { "Resent-Date", "imf.resent.date", FT_STRING, BASE_NONE, NULL, 0x0,
976 { &hf_imf_resent_from,
977 { "Resent-From", "imf.resent.from", FT_STRING, BASE_NONE, NULL, 0x0,
979 { &hf_imf_resent_sender,
980 { "Resent-Sender", "imf.resent.sender", FT_STRING, BASE_NONE, NULL, 0x0,
983 { "Resent-To", "imf.resent.to", FT_STRING, BASE_NONE, NULL, 0x0,
986 { "Resent-Cc", "imf.resent.cc", FT_STRING, BASE_NONE, NULL, 0x0,
988 { &hf_imf_resent_bcc,
989 { "Resent-Bcc", "imf.resent.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
991 { &hf_imf_resent_message_id,
992 { "Resent-Message-ID", "imf.resent.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
994 { &hf_imf_return_path,
995 { "Return-Path", "imf.return_path", FT_STRING, BASE_NONE, NULL, 0x0,
998 { "Received", "imf.received", FT_STRING, BASE_NONE, NULL, 0x0,
1000 { &hf_imf_content_type,
1001 { "Content-Type", "imf.content.type", FT_STRING, BASE_NONE, NULL, 0x0,
1003 { &hf_imf_content_type_type,
1004 { "Type", "imf.content.type.type", FT_STRING, BASE_NONE, NULL, 0x0,
1006 { &hf_imf_content_type_parameters,
1007 { "Parameters", "imf.content.type.parameters", FT_STRING, BASE_NONE, NULL, 0x0,
1009 { &hf_imf_content_description,
1010 { "Content-Description", "imf.content.description", FT_STRING, BASE_NONE, NULL, 0x0,
1012 { &hf_imf_content_id,
1013 { "Content-ID", "imf.content.id", FT_STRING, BASE_NONE, NULL, 0x0,
1015 { &hf_imf_content_transfer_encoding,
1016 { "Content-Transfer-Encoding", "imf.content.transfer_encoding", FT_STRING, BASE_NONE, NULL, 0x0,
1018 { &hf_imf_mime_version,
1019 { "MIME-Version", "imf.mime_version", FT_STRING, BASE_NONE, NULL, 0x0,
1021 { &hf_imf_autoforwarded,
1022 { "Autoforwarded", "imf.autoforwarded", FT_STRING, BASE_NONE, NULL, 0x0,
1024 { &hf_imf_autosubmitted,
1025 { "Autosubmitted", "imf.autosubmitted", FT_STRING, BASE_NONE, NULL, 0x0,
1027 { &hf_imf_x400_content_identifier,
1028 { "X400-Content-Identifier", "imf.x400_content_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
1030 { &hf_imf_content_language,
1031 { "Content-Language", "imf.content_language", FT_STRING, BASE_NONE, NULL, 0x0,
1033 { &hf_imf_conversion,
1034 { "Conversion", "imf.conversion", FT_STRING, BASE_NONE, NULL, 0x0,
1036 { &hf_imf_conversion_with_loss,
1037 { "Conversion-With-Loss", "imf.conversion_with_loss", FT_STRING, BASE_NONE, NULL, 0x0,
1039 { &hf_imf_delivery_date,
1040 { "Delivery-Date", "imf.delivery_date", FT_STRING, BASE_NONE, NULL, 0x0,
1042 { &hf_imf_discarded_x400_ipms_extensions,
1043 { "Discarded-X400-IPMS-Extensions", "imf.discarded_x400_ipms_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
1045 { &hf_imf_discarded_x400_mts_extensions,
1046 { "Discarded-X400-MTS-Extensions", "imf.discarded_x400_mts_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
1048 { &hf_imf_dl_expansion_history,
1049 { "DL-Expansion-History", "imf.dl_expansion_history", FT_STRING, BASE_NONE, NULL, 0x0,
1051 { &hf_imf_deferred_delivery,
1052 { "Deferred-Delivery", "imf.deferred_delivery", FT_STRING, BASE_NONE, NULL, 0x0,
1055 { "Expires", "imf.expires", FT_STRING, BASE_NONE, NULL, 0x0,
1057 { &hf_imf_importance,
1058 { "Importance", "imf.importance", FT_STRING, BASE_NONE, NULL, 0x0,
1060 { &hf_imf_incomplete_copy,
1061 { "Incomplete-Copy", "imf.incomplete_copy", FT_STRING, BASE_NONE, NULL, 0x0,
1063 { &hf_imf_latest_delivery_time,
1064 { "Latest-Delivery-Time", "imf.latest_delivery_time", FT_STRING, BASE_NONE, NULL, 0x0,
1066 { &hf_imf_message_type,
1067 { "Message-Type", "imf.message_type", FT_STRING, BASE_NONE, NULL, 0x0,
1069 { &hf_imf_original_encoded_information_types,
1070 { "Original-Encoded-Information-Types", "imf.original_encoded_information_types", FT_STRING, BASE_NONE, NULL, 0x0,
1072 { &hf_imf_originator_return_address,
1073 { "Originator-Return-Address", "imf.originator_return_address", FT_STRING, BASE_NONE, NULL, 0x0,
1076 { "Priority", "imf.priority", FT_STRING, BASE_NONE, NULL, 0x0,
1079 { "Reply-By", "imf.reply_by", FT_STRING, BASE_NONE, NULL, 0x0,
1081 { &hf_imf_sensitivity,
1082 { "Sensitivity", "imf.sensitivity", FT_STRING, BASE_NONE, NULL, 0x0,
1084 { &hf_imf_supersedes,
1085 { "Supersedes", "imf.supersedes", FT_STRING, BASE_NONE, NULL, 0x0,
1087 { &hf_imf_x400_content_type,
1088 { "X400-Content-Type", "imf.x400_content_type", FT_STRING, BASE_NONE, NULL, 0x0,
1090 { &hf_imf_x400_mts_identifier,
1091 { "X400-MTS-Identifier", "imf.x400_mts_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
1093 { &hf_imf_x400_originator,
1094 { "X400-Originator", "imf.x400_originator", FT_STRING, BASE_NONE, NULL, 0x0,
1096 { &hf_imf_x400_received,
1097 { "X400-Received", "imf.x400_received", FT_STRING, BASE_NONE, NULL, 0x0,
1099 { &hf_imf_x400_recipients,
1100 { "X400-Recipients", "imf.x400_recipients", FT_STRING, BASE_NONE, NULL, 0x0,
1102 { &hf_imf_delivered_to,
1103 { "Delivered-To", "imf.delivered_to", FT_STRING, BASE_NONE, NULL, 0x0,
1105 { &hf_imf_ext_mailer,
1106 { "X-Mailer", "imf.ext.mailer", FT_STRING, BASE_NONE, NULL, 0x0,
1108 { &hf_imf_ext_mimeole,
1109 { "X-MimeOLE", "imf.ext.mimeole", FT_STRING, BASE_NONE, NULL, 0x0,
1111 { &hf_imf_ext_expiry_date,
1112 { "Expiry-Date", "imf.ext.expiry-date", FT_STRING, BASE_NONE, NULL, 0x0,
1114 { &hf_imf_ext_tnef_correlator,
1115 { "X-MS-TNEF-Correlator", "imf.ext.tnef-correlator", FT_STRING, BASE_NONE, NULL, 0x0,
1118 { "X-UIDL", "imf.ext.uidl", FT_STRING, BASE_NONE, NULL, 0x0,
1120 { &hf_imf_ext_authentication_warning,
1121 { "X-Authentication-Warning", "imf.ext.authentication_warning", FT_STRING, BASE_NONE,
1122 NULL, 0x0, NULL, HFILL }},
1123 { &hf_imf_ext_virus_scanned,
1124 { "X-Virus-Scanned", "imf.ext.virus_scanned", FT_STRING, BASE_NONE, NULL, 0x0,
1126 { &hf_imf_thread_index,
1127 { "Thread-Index", "imf.thread-index", FT_STRING, BASE_NONE, NULL, 0x0,
1129 { &hf_imf_extension,
1130 { "Unknown-Extension", "imf.extension", FT_STRING, BASE_NONE, NULL, 0x0,
1132 { &hf_imf_extension_type,
1133 { "Type", "imf.extension.type", FT_STRING, BASE_NONE, NULL, 0x0,
1135 { &hf_imf_extension_value,
1136 { "Value", "imf.extension.value", FT_STRING, BASE_NONE, NULL, 0x0,
1138 { &hf_imf_display_name,
1139 { "Display-Name", "imf.display_name", FT_STRING, BASE_NONE, NULL, 0x0,
1142 { "Address", "imf.address", FT_STRING, BASE_NONE, NULL, 0x0,
1144 { &hf_imf_address_list,
1145 { "Address List", "imf.address_list", FT_UINT32, BASE_DEC, NULL, 0x0,
1147 { &hf_imf_address_list_item,
1148 { "Item", "imf.address_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
1150 { &hf_imf_mailbox_list,
1151 { "Mailbox List", "imf.mailbox_list", FT_UINT32, BASE_DEC, NULL, 0x0,
1153 { &hf_imf_mailbox_list_item,
1154 { "Item", "imf.mailbox_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
1157 { "SIO-Label", "imf.siolabel", FT_NONE, BASE_NONE, NULL, 0x0,
1159 { &hf_imf_siolabel_marking,
1160 { "Marking", "imf.siolabel.marking", FT_STRING, BASE_NONE, NULL, 0x0,
1162 { &hf_imf_siolabel_fgcolor,
1163 { "Foreground Color", "imf.siolabel.fgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
1165 { &hf_imf_siolabel_bgcolor,
1166 { "Background Color", "imf.siolabel.bgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
1168 { &hf_imf_siolabel_type,
1169 { "Type", "imf.siolabel.type", FT_STRING, BASE_NONE, NULL, 0x0,
1171 { &hf_imf_siolabel_label,
1172 { "Label", "imf.siolabel.label", FT_STRING, BASE_NONE, NULL, 0x0,
1174 { &hf_imf_siolabel_unknown,
1175 { "Unknown parameter", "imf.siolabel.unknown", FT_STRING, BASE_NONE, NULL, 0x0,
1177 { &hf_imf_message_text,
1178 { "Message-Text", "imf.message_text", FT_NONE, BASE_NONE, NULL, 0x0,
1181 static gint *ett[] = {
1183 &ett_imf_content_type,
1186 &ett_imf_mailbox_list,
1187 &ett_imf_address_list,
1190 &ett_imf_message_text,
1193 static uat_field_t attributes_flds[] = {
1194 UAT_FLD_CSTRING(header_fields, header_name, "Header name", "IMF header name"),
1195 UAT_FLD_CSTRING(header_fields, description, "Description", "Description of the value contained in the header"),
1196 UAT_FLD_VS(header_fields, header_format, "Format", header_format, 0),
1197 UAT_FLD_VS(header_fields, add_to_col_info, "Add to Info column", add_to_col_info, 0),
1201 uat_t *headers_uat = uat_new("Custom IMF headers",
1202 sizeof(header_field_t),
1203 "imf_header_fields",
1205 (void*) &header_fields,
1209 header_fields_copy_cb,
1210 header_fields_update_cb,
1211 header_fields_free_cb,
1212 header_fields_initialize_cb,
1215 module_t *imf_module;
1216 struct imf_field *f;
1218 proto_imf = proto_register_protocol(PNAME, PSNAME, PFNAME);
1220 proto_register_field_array(proto_imf, hf, array_length(hf));
1221 proto_register_subtree_array(ett, array_length(ett));
1223 /* Allow dissector to find be found by name. */
1224 register_dissector(PFNAME, dissect_imf, proto_imf);
1226 imf_module = prefs_register_protocol(proto_imf, NULL);
1227 prefs_register_uat_preference(imf_module, "custom_header_fields", "Custom IMF headers",
1228 "A table to define custom IMF headers for which fields can be "
1229 "setup and used for filtering/data extraction etc.",
1232 imf_field_table=g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
1234 /* register the fields for lookup */
1235 for(f = imf_fields; f->name; f++)
1236 g_hash_table_insert(imf_field_table, (gpointer)f->name, (gpointer)f);
1240 /* The registration hand-off routine */
1242 proto_reg_handoff_imf(void)
1244 dissector_handle_t imf_handle;
1246 imf_handle = find_dissector(PFNAME);
1248 dissector_add_string("media_type",
1249 "message/rfc822", imf_handle);
1251 register_ber_oid_dissector("1.2.840.113549.1.7.1", dissect_imf, proto_imf, "id-data");
1254 * Get the content type and Internet media type table
1256 media_type_dissector_table = find_dissector_table("media_type");