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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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;
287 if (rec->header_name == NULL) {
288 *err = ep_strdup_printf("Header name can't be empty");
292 g_strstrip(rec->header_name);
293 if (rec->header_name[0] == 0) {
294 *err = ep_strdup_printf("Header name can't be empty");
298 /* Check for invalid characters (to avoid asserting out when
299 * registering the field).
301 c = proto_check_field_name(rec->header_name);
303 *err = ep_strdup_printf("Header name can't contain '%c'", c);
311 header_fields_copy_cb(void *n, const void *o, size_t siz _U_)
313 header_field_t *new_rec = n;
314 const header_field_t *old_rec = o;
316 new_rec->header_name = g_strdup(old_rec->header_name);
317 new_rec->description = g_strdup(old_rec->description);
318 new_rec->header_format = old_rec->header_format;
319 new_rec->add_to_col_info = old_rec->add_to_col_info;
325 header_fields_free_cb(void *r)
327 header_field_t *rec = r;
329 g_free(rec->header_name);
330 g_free(rec->description);
333 UAT_CSTRING_CB_DEF(header_fields, header_name, header_field_t)
334 UAT_CSTRING_CB_DEF(header_fields, description, header_field_t)
335 UAT_VS_DEF(header_fields, header_format, header_field_t, 0, "Unstructured")
336 UAT_VS_DEF(header_fields, add_to_col_info, header_field_t, 0, "No")
339 /* Define media_type/Content type table */
340 static dissector_table_t media_type_dissector_table;
343 dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
345 proto_tree *group_tree;
346 proto_item *group_item;
349 /* if there is a colon present it is a group */
350 if((addr_pos = tvb_find_guint8(tvb, offset, length, ':')) == -1) {
352 /* there isn't - so it must be a mailbox */
353 dissect_imf_mailbox(tvb, offset, length, item, pinfo);
358 group_tree = proto_item_add_subtree(item, ett_imf_group);
360 /* the display-name is mandatory */
361 group_item = proto_tree_add_item(group_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII|ENC_NA);
363 /* consume any whitespace */
364 for(addr_pos++ ;addr_pos < (offset + length); addr_pos++) {
365 if(!isspace(tvb_get_guint8(tvb, addr_pos))) {
370 if(tvb_get_guint8(tvb, addr_pos) != ';') {
372 dissect_imf_mailbox_list(tvb, addr_pos, length - (addr_pos - offset), group_item, pinfo);
374 /* XXX: need to check for final ';' */
382 dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo _U_)
384 proto_tree *mbox_tree;
385 int addr_pos, end_pos;
387 mbox_tree = proto_item_add_subtree(item, ett_imf_mailbox);
390 If we can't find and angle brackets, then the whole field is an address.
391 If we find angle brackets, then the address is between them and the display name is
392 anything before the opening angle bracket
395 if((addr_pos = tvb_find_guint8(tvb, offset, length, '<')) == -1) {
396 /* we can't find an angle bracket - the whole field is therefore the address */
398 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, offset, length, ENC_ASCII|ENC_NA);
401 /* we can find an angle bracket - let's see if we can find a display name */
402 /* XXX: the '<' could be in the display name */
404 for(; offset < addr_pos; offset++) {
405 if(!isspace(tvb_get_guint8(tvb, offset))) {
410 if(offset != addr_pos) { /* there is a display name */
411 (void) proto_tree_add_item(mbox_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, ENC_ASCII|ENC_NA);
413 end_pos = tvb_find_guint8(tvb, addr_pos + 1, length - (addr_pos + 1 - offset), '>');
416 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, addr_pos + 1, end_pos - addr_pos - 1, ENC_ASCII|ENC_NA);
422 dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
424 proto_item *addr_item = NULL;
425 proto_tree *tree = NULL;
431 /* a comma separated list of addresses */
432 tree = proto_item_add_subtree(item, ett_imf_address_list);
434 item_offset = offset;
438 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
440 count++; /* increase the number of items */
442 if(end_offset == -1) {
443 /* length is to the end of the buffer */
444 item_length = length - (item_offset - offset);
446 item_length = end_offset - item_offset;
448 addr_item = proto_tree_add_item(tree, hf_imf_address_list_item, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
449 dissect_imf_address(tvb, item_offset, item_length, addr_item, pinfo);
451 if(end_offset != -1) {
452 item_offset = end_offset + 1;
454 } while(end_offset != -1);
456 /* now indicate the number of items found */
457 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
461 dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
463 proto_item *mbox_item = NULL;
464 proto_tree *tree = NULL;
470 /* a comma separated list of mailboxes */
471 tree = proto_item_add_subtree(item, ett_imf_mailbox_list);
473 item_offset = offset;
477 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
479 count++; /* increase the number of items */
481 if(end_offset == -1) {
482 /* length is to the end of the buffer */
483 item_length = length - (item_offset - offset);
485 item_length = end_offset - item_offset;
487 mbox_item = proto_tree_add_item(tree, hf_imf_mailbox_list_item, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
488 dissect_imf_mailbox(tvb, item_offset, item_length, mbox_item, pinfo);
490 if(end_offset != -1) {
491 item_offset = end_offset + 1;
493 } while(end_offset != -1);
495 /* now indicate the number of items found */
496 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
500 dissect_imf_siolabel(tvbuff_t *tvb, int offset, int length, proto_item *item, packet_info *pinfo)
502 proto_tree *tree = NULL;
503 proto_item *sub_item = NULL;
504 int item_offset, item_length;
505 int value_offset, value_length;
509 GString *label_string = g_string_new ("");
511 /* a semicolon separated list of attributes */
512 tree = proto_item_add_subtree(item, ett_imf_siolabel);
513 item_offset = offset;
516 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ';');
518 /* skip leading space */
519 while (isspace(tvb_get_guint8(tvb, item_offset))) {
523 if (end_offset == -1) {
524 /* length is to the end of the buffer */
525 item_length = tvb_find_line_end(tvb, item_offset, length - (item_offset - offset), NULL, FALSE);
527 item_length = end_offset - item_offset;
530 value_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), '=') + 1;
531 while (isspace(tvb_get_guint8(tvb, value_offset))) {
535 value_length = item_length - (value_offset - item_offset);
536 while (isspace(tvb_get_guint8(tvb, value_offset + value_length - 1))) {
540 if (tvb_strneql(tvb, item_offset, "marking", 7) == 0) {
541 proto_item_append_text(item, ": %s", tvb_get_ephemeral_string(tvb, value_offset, value_length));
542 proto_tree_add_item(tree, hf_imf_siolabel_marking, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
544 } else if (tvb_strneql(tvb, item_offset, "fgcolor", 7) == 0) {
545 proto_tree_add_item(tree, hf_imf_siolabel_fgcolor, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
547 } else if (tvb_strneql(tvb, item_offset, "bgcolor", 7) == 0) {
548 proto_tree_add_item(tree, hf_imf_siolabel_bgcolor, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
550 } else if (tvb_strneql(tvb, item_offset, "type", 4) == 0) {
551 type = tvb_get_ephemeral_string(tvb, value_offset + 1, value_length - 2); /* quoted */
552 proto_tree_add_item(tree, hf_imf_siolabel_type, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
554 } else if (tvb_strneql(tvb, item_offset, "label", 5) == 0) {
555 gchar *label = tvb_get_ephemeral_string(tvb, value_offset + 1, value_length - 2); /* quoted */
556 label_string = g_string_append(label_string, label);
558 if (tvb_get_guint8(tvb, item_offset + 5) == '*') { /* continuations */
559 int num = strtol(tvb_get_ephemeral_string(tvb, item_offset + 6, value_offset - item_offset + 6), NULL, 10);
560 proto_tree_add_string_format(tree, hf_imf_siolabel_label, tvb, value_offset, value_length,
561 label, "Label[%d]: \"%s\"", num, label);
563 proto_tree_add_item(tree, hf_imf_siolabel_label, tvb, value_offset, value_length, ENC_ASCII|ENC_NA);
567 sub_item = proto_tree_add_item(tree, hf_imf_siolabel_unknown, tvb, item_offset, item_length, ENC_ASCII|ENC_NA);
568 expert_add_info_format(pinfo, sub_item, PI_PROTOCOL, PI_WARN, "Unknown parameter");
571 if (end_offset != -1) {
572 item_offset = end_offset + 1;
574 } while (end_offset != -1);
576 if (type && label_string->len > 0) {
577 if (strcmp (type, ":ess") == 0) {
578 label_tvb = base64_to_tvb(tvb, label_string->str);
579 add_new_data_source(pinfo, label_tvb, "ESS Security Label");
580 dissect_ess_ESSSecurityLabel_PDU(label_tvb, pinfo, tree);
581 } else if (strcmp (type, ":x411") == 0) {
582 label_tvb = base64_to_tvb(tvb, label_string->str);
583 add_new_data_source(pinfo, label_tvb, "X.411 Security Label");
584 dissect_p1_MessageSecurityLabel_PDU(label_tvb, pinfo, tree);
588 g_string_free (label_string, TRUE);
592 dissect_imf_content_type(tvbuff_t *tvb, int offset, int length, proto_item *item,
593 char **type, char **parameters)
600 /* first strip any whitespace */
601 for(i = 0; i < length; i++) {
602 if(!isspace(tvb_get_guint8(tvb, offset + i))) {
608 /* find the first colon - there has to be a colon as there will have to be a boundary */
609 first_colon = tvb_find_guint8(tvb, offset, length, ';');
611 if(first_colon != -1) {
612 ct_tree = proto_item_add_subtree(item, ett_imf_content_type);
614 len = first_colon - offset;
615 proto_tree_add_item(ct_tree, hf_imf_content_type_type, tvb, offset, len, ENC_ASCII|ENC_NA);
617 /* This string will be automatically freed */
618 (*type) = tvb_get_ephemeral_string(tvb, offset, len);
620 len = tvb_find_line_end(tvb, first_colon + 1, length, NULL, FALSE);
621 proto_tree_add_item(ct_tree, hf_imf_content_type_parameters, tvb, first_colon + 1, len, ENC_ASCII|ENC_NA);
623 /* This string will be automatically freed */
624 (*parameters) = tvb_get_ephemeral_string(tvb, first_colon + 1, len);
631 imf_find_field_end(tvbuff_t *tvb, int offset, gint max_length, gboolean *last_field)
634 while(offset < max_length) {
637 offset = tvb_find_guint8(tvb, offset, max_length - offset, '\r');
640 if(tvb_get_guint8(tvb, ++offset) == '\n') {
641 /* OK - so we have found CRLF */
642 /* peek the next character */
643 switch(tvb_get_guint8(tvb, ++offset)) {
645 /* probably end of the fields */
646 if(tvb_get_guint8(tvb, ++offset) == '\n') {
655 /* continuation line */
658 /* this is a new field */
663 /* couldn't find a CR - strange */
669 return -1; /* Fail: No CR found (other than possible continuation) */
674 dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
677 proto_tree *unknown_tree, *text_tree;
678 char *content_type_str = NULL;
679 char *parameters = NULL;
681 gint start_offset = 0;
682 gint value_offset = 0;
683 gint unknown_offset = 0;
687 gboolean last_field = FALSE;
689 struct imf_field *f_info;
691 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
692 col_clear(pinfo->cinfo, COL_INFO);
695 item = proto_tree_add_item(tree, proto_imf, tvb, 0, -1, ENC_NA);
696 tree = proto_item_add_subtree(item, ett_imf);
699 max_length = tvb_length(tvb);
700 /* first go through the tvb until we find a blank line and extract the content type if
703 /* XXX: What if the tvb contains encrypted data ? is there a way to bypass dissection if so ? */
704 /* As it is, the following code blithely tries to parse what may be binary data. */
708 /* look for a colon first */
709 end_offset = tvb_find_guint8(tvb, start_offset, max_length - start_offset, ':');
711 if(end_offset == -1) {
712 /* we couldn't find another colon - strange - we should have broken out of here by now */
713 /* XXX: flag an error */
716 key = tvb_get_ephemeral_string(tvb, start_offset, end_offset - start_offset);
718 /* convert to lower case */
719 ascii_strdown_inplace (key);
721 /* look up the key in built-in fields */
722 f_info = (struct imf_field *)g_hash_table_lookup(imf_field_table, key);
724 if(f_info == NULL && custom_field_table) {
725 /* look up the key in custom fields */
726 f_info = (struct imf_field *)g_hash_table_lookup(custom_field_table, key);
730 /* set as an unknown extension */
732 unknown_offset = start_offset;
735 hf_id = *(f_info->hf_id);
737 /* value starts immediately after the colon */
738 start_offset = end_offset+1;
740 end_offset = imf_find_field_end(tvb, start_offset, max_length, &last_field);
741 if(end_offset == -1) {
742 break; /* Something's fishy */
745 /* remove any leading whitespace */
747 for(value_offset = start_offset; value_offset < end_offset; value_offset++)
748 if(!isspace(tvb_get_guint8(tvb, value_offset))) {
752 if(value_offset == end_offset) {
753 /* empty field - show whole value */
754 value_offset = start_offset;
757 if(hf_id == hf_imf_extension_type) {
759 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
760 item = proto_tree_add_item(tree, hf_imf_extension, tvb, unknown_offset, end_offset - unknown_offset - 2, ENC_ASCII|ENC_NA);
762 proto_item_append_text(item, " (Contact Wireshark developers if you want this supported.)");
764 unknown_tree = proto_item_add_subtree(item, ett_imf_extension);
766 proto_tree_add_item(unknown_tree, hf_imf_extension_type, tvb, unknown_offset, start_offset - 1 - unknown_offset, ENC_ASCII|ENC_NA);
768 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
769 item = proto_tree_add_item(unknown_tree, hf_imf_extension_value, tvb, start_offset, end_offset - start_offset - 2, ENC_ASCII|ENC_NA);
772 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
773 item = proto_tree_add_item(tree, hf_id, tvb, value_offset, end_offset - value_offset - 2, ENC_ASCII|ENC_NA);
775 if(f_info->add_to_col_info && check_col(pinfo->cinfo, COL_INFO)) {
777 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s, ", f_info->name,
778 tvb_format_text(tvb, value_offset, end_offset - value_offset - 2));
781 if(hf_id == hf_imf_content_type) {
782 /* we need some additional processing to extract the content type and parameters */
784 dissect_imf_content_type(tvb, start_offset, end_offset - start_offset, item,
785 &content_type_str, ¶meters);
787 } else if(f_info->subdissector) {
789 /* we have a subdissector */
790 f_info->subdissector(tvb, value_offset, end_offset - value_offset, item, pinfo);
794 start_offset = end_offset;
797 if (end_offset == -1) {
801 /* specify a content type until we can work it out for ourselves */
802 /* content_type_str = "multipart/mixed"; */
804 /* now dissect the MIME based upon the content type */
806 if(content_type_str && media_type_dissector_table) {
808 pd_save = pinfo->private_data;
809 pinfo->private_data = parameters;
811 next_tvb = tvb_new_subset_remaining(tvb, end_offset);
813 dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree);
815 pinfo->private_data = pd_save;
818 /* just show the lines or highlight the rest of the buffer as message text */
820 item = proto_tree_add_item(tree, hf_imf_message_text, tvb, end_offset, -1 , ENC_NA);
821 text_tree = proto_item_add_subtree(item, ett_imf_message_text);
823 start_offset = end_offset;
824 while (tvb_offset_exists(tvb, start_offset)) {
827 * Find the end of the line.
829 tvb_find_line_end(tvb, start_offset, -1, &end_offset, FALSE);
834 proto_tree_add_text(text_tree, tvb, start_offset, end_offset - start_offset,
836 tvb_format_text_wsp(tvb, start_offset, end_offset - start_offset));
837 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ",
838 tvb_format_text_wsp(tvb, start_offset, end_offset - start_offset));
841 * Step to the next line.
843 start_offset = end_offset;
849 free_imf_field (gpointer data)
851 struct imf_field *imffield = (struct imf_field *) data;
853 g_free ((char *) imffield->name);
858 header_fields_initialize_cb (void)
860 static hf_register_info *hf;
862 struct imf_field *imffield;
866 if (custom_field_table && hf) {
867 guint hf_size = g_hash_table_size (custom_field_table);
868 /* Unregister all fields */
869 for (i = 0; i < hf_size; i++) {
870 proto_unregister_field (proto_imf, *(hf[i].p_id));
873 g_free ((char *) hf[i].hfinfo.name);
874 g_free ((char *) hf[i].hfinfo.abbrev);
875 g_free ((char *) hf[i].hfinfo.blurb);
877 g_hash_table_destroy (custom_field_table);
879 custom_field_table = NULL;
882 if (num_header_fields) {
883 custom_field_table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_imf_field);
884 hf = g_malloc0 (sizeof (hf_register_info) * num_header_fields);
886 for (i = 0; i < num_header_fields; i++) {
887 hf_id = g_malloc (sizeof (gint));
889 header_name = g_strdup (header_fields[i].header_name);
892 hf[i].hfinfo.name = header_name;
893 hf[i].hfinfo.abbrev = g_strdup_printf ("imf.header.%s", header_name);
894 hf[i].hfinfo.type = FT_STRING;
895 hf[i].hfinfo.display = BASE_NONE;
896 hf[i].hfinfo.strings = NULL;
897 hf[i].hfinfo.blurb = g_strdup (header_fields[i].description);
898 hf[i].hfinfo.same_name_prev = NULL;
899 hf[i].hfinfo.same_name_next = NULL;
901 imffield = g_malloc (sizeof (struct imf_field));
902 imffield->hf_id = hf_id;
903 imffield->name = ascii_strdown_inplace (g_strdup (header_name));
904 switch (header_fields[i].header_format) {
905 case FORMAT_UNSTRUCTURED:
906 imffield->subdissector = NO_SUBDISSECTION;
909 imffield->subdissector = dissect_imf_mailbox;
912 imffield->subdissector = dissect_imf_address;
914 case FORMAT_MAILBOX_LIST:
915 imffield->subdissector = dissect_imf_mailbox_list;
917 case FORMAT_ADDRESS_LIST:
918 imffield->subdissector = dissect_imf_address_list;
920 case FORMAT_SIO_LABEL:
921 hf[i].hfinfo.type = FT_NONE; /* constructed */
922 imffield->subdissector = dissect_imf_siolabel;
926 imffield->subdissector = NO_SUBDISSECTION;
929 imffield->add_to_col_info = header_fields[i].add_to_col_info;
930 g_hash_table_insert (custom_field_table, (gpointer)imffield->name, (gpointer)imffield);
933 proto_register_field_array (proto_imf, hf, num_header_fields);
937 /* Register all the bits needed by the filtering engine */
940 proto_register_imf(void)
942 static hf_register_info hf[] = {
944 { "Date", "imf.date", FT_STRING, BASE_NONE, NULL, 0x0,
945 "DateTime", HFILL }},
947 { "From", "imf.from", FT_STRING, BASE_NONE, NULL, 0x0,
948 "MailboxList", HFILL }},
950 { "Sender", "imf.sender", FT_STRING, BASE_NONE, NULL, 0x0,
953 { "Reply-To", "imf.reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
956 { "To", "imf.to", FT_STRING, BASE_NONE, NULL, 0x0,
959 { "Cc", "imf.cc", FT_STRING, BASE_NONE, NULL, 0x0,
962 { "Bcc", "imf.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
964 { &hf_imf_message_id,
965 { "Message-ID", "imf.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
967 { &hf_imf_in_reply_to,
968 { "In-Reply-To", "imf.in_reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
970 { &hf_imf_references,
971 { "References", "imf.references", FT_STRING, BASE_NONE, NULL, 0x0,
974 { "Subject", "imf.subject", FT_STRING, BASE_NONE, NULL, 0x0,
977 { "Comments", "imf.comments", FT_STRING, BASE_NONE, NULL, 0x0,
979 { &hf_imf_user_agent,
980 { "User-Agent", "imf.user_agent", FT_STRING, BASE_NONE, NULL, 0x0,
983 { "Keywords", "imf.keywords", FT_STRING, BASE_NONE, NULL, 0x0,
985 { &hf_imf_resent_date,
986 { "Resent-Date", "imf.resent.date", FT_STRING, BASE_NONE, NULL, 0x0,
988 { &hf_imf_resent_from,
989 { "Resent-From", "imf.resent.from", FT_STRING, BASE_NONE, NULL, 0x0,
991 { &hf_imf_resent_sender,
992 { "Resent-Sender", "imf.resent.sender", FT_STRING, BASE_NONE, NULL, 0x0,
995 { "Resent-To", "imf.resent.to", FT_STRING, BASE_NONE, NULL, 0x0,
998 { "Resent-Cc", "imf.resent.cc", FT_STRING, BASE_NONE, NULL, 0x0,
1000 { &hf_imf_resent_bcc,
1001 { "Resent-Bcc", "imf.resent.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
1003 { &hf_imf_resent_message_id,
1004 { "Resent-Message-ID", "imf.resent.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
1006 { &hf_imf_return_path,
1007 { "Return-Path", "imf.return_path", FT_STRING, BASE_NONE, NULL, 0x0,
1010 { "Received", "imf.received", FT_STRING, BASE_NONE, NULL, 0x0,
1012 { &hf_imf_content_type,
1013 { "Content-Type", "imf.content.type", FT_STRING, BASE_NONE, NULL, 0x0,
1015 { &hf_imf_content_type_type,
1016 { "Type", "imf.content.type.type", FT_STRING, BASE_NONE, NULL, 0x0,
1018 { &hf_imf_content_type_parameters,
1019 { "Parameters", "imf.content.type.parameters", FT_STRING, BASE_NONE, NULL, 0x0,
1021 { &hf_imf_content_description,
1022 { "Content-Description", "imf.content.description", FT_STRING, BASE_NONE, NULL, 0x0,
1024 { &hf_imf_content_id,
1025 { "Content-ID", "imf.content.id", FT_STRING, BASE_NONE, NULL, 0x0,
1027 { &hf_imf_content_transfer_encoding,
1028 { "Content-Transfer-Encoding", "imf.content.transfer_encoding", FT_STRING, BASE_NONE, NULL, 0x0,
1030 { &hf_imf_mime_version,
1031 { "MIME-Version", "imf.mime_version", FT_STRING, BASE_NONE, NULL, 0x0,
1033 { &hf_imf_autoforwarded,
1034 { "Autoforwarded", "imf.autoforwarded", FT_STRING, BASE_NONE, NULL, 0x0,
1036 { &hf_imf_autosubmitted,
1037 { "Autosubmitted", "imf.autosubmitted", FT_STRING, BASE_NONE, NULL, 0x0,
1039 { &hf_imf_x400_content_identifier,
1040 { "X400-Content-Identifier", "imf.x400_content_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
1042 { &hf_imf_content_language,
1043 { "Content-Language", "imf.content_language", FT_STRING, BASE_NONE, NULL, 0x0,
1045 { &hf_imf_conversion,
1046 { "Conversion", "imf.conversion", FT_STRING, BASE_NONE, NULL, 0x0,
1048 { &hf_imf_conversion_with_loss,
1049 { "Conversion-With-Loss", "imf.conversion_with_loss", FT_STRING, BASE_NONE, NULL, 0x0,
1051 { &hf_imf_delivery_date,
1052 { "Delivery-Date", "imf.delivery_date", FT_STRING, BASE_NONE, NULL, 0x0,
1054 { &hf_imf_discarded_x400_ipms_extensions,
1055 { "Discarded-X400-IPMS-Extensions", "imf.discarded_x400_ipms_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
1057 { &hf_imf_discarded_x400_mts_extensions,
1058 { "Discarded-X400-MTS-Extensions", "imf.discarded_x400_mts_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
1060 { &hf_imf_dl_expansion_history,
1061 { "DL-Expansion-History", "imf.dl_expansion_history", FT_STRING, BASE_NONE, NULL, 0x0,
1063 { &hf_imf_deferred_delivery,
1064 { "Deferred-Delivery", "imf.deferred_delivery", FT_STRING, BASE_NONE, NULL, 0x0,
1067 { "Expires", "imf.expires", FT_STRING, BASE_NONE, NULL, 0x0,
1069 { &hf_imf_importance,
1070 { "Importance", "imf.importance", FT_STRING, BASE_NONE, NULL, 0x0,
1072 { &hf_imf_incomplete_copy,
1073 { "Incomplete-Copy", "imf.incomplete_copy", FT_STRING, BASE_NONE, NULL, 0x0,
1075 { &hf_imf_latest_delivery_time,
1076 { "Latest-Delivery-Time", "imf.latest_delivery_time", FT_STRING, BASE_NONE, NULL, 0x0,
1078 { &hf_imf_message_type,
1079 { "Message-Type", "imf.message_type", FT_STRING, BASE_NONE, NULL, 0x0,
1081 { &hf_imf_original_encoded_information_types,
1082 { "Original-Encoded-Information-Types", "imf.original_encoded_information_types", FT_STRING, BASE_NONE, NULL, 0x0,
1084 { &hf_imf_originator_return_address,
1085 { "Originator-Return-Address", "imf.originator_return_address", FT_STRING, BASE_NONE, NULL, 0x0,
1088 { "Priority", "imf.priority", FT_STRING, BASE_NONE, NULL, 0x0,
1091 { "Reply-By", "imf.reply_by", FT_STRING, BASE_NONE, NULL, 0x0,
1093 { &hf_imf_sensitivity,
1094 { "Sensitivity", "imf.sensitivity", FT_STRING, BASE_NONE, NULL, 0x0,
1096 { &hf_imf_supersedes,
1097 { "Supersedes", "imf.supersedes", FT_STRING, BASE_NONE, NULL, 0x0,
1099 { &hf_imf_x400_content_type,
1100 { "X400-Content-Type", "imf.x400_content_type", FT_STRING, BASE_NONE, NULL, 0x0,
1102 { &hf_imf_x400_mts_identifier,
1103 { "X400-MTS-Identifier", "imf.x400_mts_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
1105 { &hf_imf_x400_originator,
1106 { "X400-Originator", "imf.x400_originator", FT_STRING, BASE_NONE, NULL, 0x0,
1108 { &hf_imf_x400_received,
1109 { "X400-Received", "imf.x400_received", FT_STRING, BASE_NONE, NULL, 0x0,
1111 { &hf_imf_x400_recipients,
1112 { "X400-Recipients", "imf.x400_recipients", FT_STRING, BASE_NONE, NULL, 0x0,
1114 { &hf_imf_delivered_to,
1115 { "Delivered-To", "imf.delivered_to", FT_STRING, BASE_NONE, NULL, 0x0,
1117 { &hf_imf_ext_mailer,
1118 { "X-Mailer", "imf.ext.mailer", FT_STRING, BASE_NONE, NULL, 0x0,
1120 { &hf_imf_ext_mimeole,
1121 { "X-MimeOLE", "imf.ext.mimeole", FT_STRING, BASE_NONE, NULL, 0x0,
1123 { &hf_imf_ext_expiry_date,
1124 { "Expiry-Date", "imf.ext.expiry-date", FT_STRING, BASE_NONE, NULL, 0x0,
1126 { &hf_imf_ext_tnef_correlator,
1127 { "X-MS-TNEF-Correlator", "imf.ext.tnef-correlator", FT_STRING, BASE_NONE, NULL, 0x0,
1130 { "X-UIDL", "imf.ext.uidl", FT_STRING, BASE_NONE, NULL, 0x0,
1132 { &hf_imf_ext_authentication_warning,
1133 { "X-Authentication-Warning", "imf.ext.authentication_warning", FT_STRING, BASE_NONE,
1134 NULL, 0x0, NULL, HFILL }},
1135 { &hf_imf_ext_virus_scanned,
1136 { "X-Virus-Scanned", "imf.ext.virus_scanned", FT_STRING, BASE_NONE, NULL, 0x0,
1138 { &hf_imf_thread_index,
1139 { "Thread-Index", "imf.thread-index", FT_STRING, BASE_NONE, NULL, 0x0,
1141 { &hf_imf_extension,
1142 { "Unknown-Extension", "imf.extension", FT_STRING, BASE_NONE, NULL, 0x0,
1144 { &hf_imf_extension_type,
1145 { "Type", "imf.extension.type", FT_STRING, BASE_NONE, NULL, 0x0,
1147 { &hf_imf_extension_value,
1148 { "Value", "imf.extension.value", FT_STRING, BASE_NONE, NULL, 0x0,
1150 { &hf_imf_display_name,
1151 { "Display-Name", "imf.display_name", FT_STRING, BASE_NONE, NULL, 0x0,
1154 { "Address", "imf.address", FT_STRING, BASE_NONE, NULL, 0x0,
1156 { &hf_imf_address_list,
1157 { "Address List", "imf.address_list", FT_UINT32, BASE_DEC, NULL, 0x0,
1159 { &hf_imf_address_list_item,
1160 { "Item", "imf.address_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
1162 { &hf_imf_mailbox_list,
1163 { "Mailbox List", "imf.mailbox_list", FT_UINT32, BASE_DEC, NULL, 0x0,
1165 { &hf_imf_mailbox_list_item,
1166 { "Item", "imf.mailbox_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
1169 { "SIO-Label", "imf.siolabel", FT_NONE, BASE_NONE, NULL, 0x0,
1171 { &hf_imf_siolabel_marking,
1172 { "Marking", "imf.siolabel.marking", FT_STRING, BASE_NONE, NULL, 0x0,
1174 { &hf_imf_siolabel_fgcolor,
1175 { "Foreground Color", "imf.siolabel.fgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
1177 { &hf_imf_siolabel_bgcolor,
1178 { "Background Color", "imf.siolabel.bgcolor", FT_STRING, BASE_NONE, NULL, 0x0,
1180 { &hf_imf_siolabel_type,
1181 { "Type", "imf.siolabel.type", FT_STRING, BASE_NONE, NULL, 0x0,
1183 { &hf_imf_siolabel_label,
1184 { "Label", "imf.siolabel.label", FT_STRING, BASE_NONE, NULL, 0x0,
1186 { &hf_imf_siolabel_unknown,
1187 { "Unknown parameter", "imf.siolabel.unknown", FT_STRING, BASE_NONE, NULL, 0x0,
1189 { &hf_imf_message_text,
1190 { "Message-Text", "imf.message_text", FT_NONE, BASE_NONE, NULL, 0x0,
1193 static gint *ett[] = {
1195 &ett_imf_content_type,
1198 &ett_imf_mailbox_list,
1199 &ett_imf_address_list,
1202 &ett_imf_message_text,
1205 static uat_field_t attributes_flds[] = {
1206 UAT_FLD_CSTRING(header_fields, header_name, "Header name", "IMF header name"),
1207 UAT_FLD_CSTRING(header_fields, description, "Description", "Description of the value contained in the header"),
1208 UAT_FLD_VS(header_fields, header_format, "Format", header_format, 0),
1209 UAT_FLD_VS(header_fields, add_to_col_info, "Add to Info column", add_to_col_info, 0),
1213 uat_t *headers_uat = uat_new("Custom IMF headers",
1214 sizeof(header_field_t),
1215 "imf_header_fields",
1217 (void*) &header_fields,
1221 header_fields_copy_cb,
1222 header_fields_update_cb,
1223 header_fields_free_cb,
1224 header_fields_initialize_cb,
1227 module_t *imf_module;
1228 struct imf_field *f;
1230 proto_imf = proto_register_protocol(PNAME, PSNAME, PFNAME);
1232 proto_register_field_array(proto_imf, hf, array_length(hf));
1233 proto_register_subtree_array(ett, array_length(ett));
1235 /* Allow dissector to find be found by name. */
1236 register_dissector(PFNAME, dissect_imf, proto_imf);
1238 imf_module = prefs_register_protocol(proto_imf, NULL);
1239 prefs_register_uat_preference(imf_module, "custom_header_fields", "Custom IMF headers",
1240 "A table to define custom IMF headers for which fields can be "
1241 "setup and used for filtering/data extraction etc.",
1244 imf_field_table=g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
1246 /* register the fields for lookup */
1247 for(f = imf_fields; f->name; f++)
1248 g_hash_table_insert(imf_field_table, (gpointer)f->name, (gpointer)f);
1252 /* The registration hand-off routine */
1254 proto_reg_handoff_imf(void)
1256 dissector_handle_t imf_handle;
1258 imf_handle = find_dissector(PFNAME);
1260 dissector_add_string("media_type",
1261 "message/rfc822", imf_handle);
1263 register_ber_oid_dissector("1.2.840.113549.1.7.1", dissect_imf, proto_imf, "id-data");
1266 * Get the content type and Internet media type table
1268 media_type_dissector_table = find_dissector_table("media_type");