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.
37 #include <epan/packet.h>
38 #include <epan/addr_resolv.h>
39 #include <epan/strutil.h>
42 #include "packet-ber.h"
43 #include "packet-imf.h"
45 #define PNAME "Internet Message Format"
49 static int proto_imf = -1;
51 static int hf_imf_date = -1;
52 static int hf_imf_from = -1;
53 static int hf_imf_sender = -1;
54 static int hf_imf_reply_to = -1;
55 static int hf_imf_to = -1;
56 static int hf_imf_cc = -1;
57 static int hf_imf_bcc = -1;
58 static int hf_imf_message_id = -1;
59 static int hf_imf_in_reply_to = -1;
60 static int hf_imf_references = -1;
61 static int hf_imf_subject = -1;
62 static int hf_imf_comments = -1;
63 static int hf_imf_keywords = -1;
64 static int hf_imf_resent_date = -1;
65 static int hf_imf_resent_from = -1;
66 static int hf_imf_resent_sender = -1;
67 static int hf_imf_resent_to = -1;
68 static int hf_imf_resent_cc = -1;
69 static int hf_imf_resent_bcc = -1;
70 static int hf_imf_resent_message_id = -1;
71 static int hf_imf_return_path = -1;
72 static int hf_imf_received = -1;
73 static int hf_imf_content_type = -1;
74 static int hf_imf_content_type_type = -1;
75 static int hf_imf_content_type_parameters = -1;
76 static int hf_imf_content_id = -1;
77 static int hf_imf_content_transfer_encoding = -1;
78 static int hf_imf_content_description = -1;
79 static int hf_imf_mime_version = -1;
80 static int hf_imf_thread_index = -1;
81 static int hf_imf_ext_mailer = -1;
82 static int hf_imf_ext_mimeole = -1;
83 static int hf_imf_ext_tnef_correlator = -1;
84 static int hf_imf_ext_expiry_date = -1;
85 static int hf_imf_ext_uidl = -1;
86 static int hf_imf_ext_authentication_warning = -1;
87 static int hf_imf_ext_virus_scanned = -1;
88 static int hf_imf_extension = -1;
89 static int hf_imf_extension_type = -1;
90 static int hf_imf_extension_value = -1;
93 static int hf_imf_autoforwarded = -1;
94 static int hf_imf_autosubmitted = -1;
95 static int hf_imf_x400_content_identifier = -1;
96 static int hf_imf_content_language = -1;
97 static int hf_imf_conversion = -1;
98 static int hf_imf_conversion_with_loss = -1;
99 static int hf_imf_delivery_date = -1;
100 static int hf_imf_discarded_x400_ipms_extensions = -1;
101 static int hf_imf_discarded_x400_mts_extensions = -1;
102 static int hf_imf_dl_expansion_history = -1;
103 static int hf_imf_deferred_delivery = -1;
104 static int hf_imf_expires = -1;
105 static int hf_imf_importance = -1;
106 static int hf_imf_incomplete_copy = -1;
107 static int hf_imf_latest_delivery_time = -1;
108 static int hf_imf_message_type = -1;
109 static int hf_imf_original_encoded_information_types = -1;
110 static int hf_imf_originator_return_address = -1;
111 static int hf_imf_priority = -1;
112 static int hf_imf_reply_by = -1;
113 static int hf_imf_sensitivity = -1;
114 static int hf_imf_supersedes = -1;
115 static int hf_imf_x400_content_type = -1;
116 static int hf_imf_x400_mts_identifier = -1;
117 static int hf_imf_x400_originator = -1;
118 static int hf_imf_x400_received = -1;
119 static int hf_imf_x400_recipients = -1;
121 static int hf_imf_delivered_to = -1;
123 static int hf_imf_message_text = -1;
125 static int hf_imf_display_name = -1;
126 static int hf_imf_address = -1;
127 static int hf_imf_mailbox_list = -1;
128 static int hf_imf_mailbox_list_item = -1;
129 static int hf_imf_address_list = -1;
130 static int hf_imf_address_list_item = -1;
132 static int ett_imf = -1;
133 static int ett_imf_content_type = -1;
134 static int ett_imf_mailbox = -1;
135 static int ett_imf_group = -1;
136 static int ett_imf_mailbox_list = -1;
137 static int ett_imf_address_list = -1;
138 static int ett_imf_extension = -1;
139 static int ett_imf_message_text = -1;
142 const char *name; /* field name - in lower case for matching purposes */
143 int *hf_id; /* wireshark field */
144 void (*subdissector)(tvbuff_t *tvb, int offset, int length, proto_item *item);
145 gboolean add_to_col_info; /* add field to column info */
148 #define NO_SUBDISSECTION NULL
150 static void dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item);
151 static void dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item);
152 static void dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item);
153 static void dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item);
155 struct imf_field imf_fields[] = {
156 {"unknown-extension", &hf_imf_extension_type, NO_SUBDISSECTION, FALSE}, /* unknown extension */
157 {"date", &hf_imf_date, NO_SUBDISSECTION, FALSE}, /* date-time */
158 {"from", &hf_imf_from, dissect_imf_mailbox_list , TRUE}, /* mailbox_list */
159 {"sender", &hf_imf_sender, dissect_imf_mailbox, FALSE}, /* mailbox */
160 {"reply-to", &hf_imf_reply_to, dissect_imf_address_list , FALSE}, /* address_list */
161 {"to", &hf_imf_to, dissect_imf_address_list , FALSE}, /* address_list */
162 {"cc", &hf_imf_cc, dissect_imf_address_list , FALSE}, /* address_list */
163 {"bcc", &hf_imf_bcc, dissect_imf_address_list , FALSE}, /* address_list */
164 {"message-id", &hf_imf_message_id, NO_SUBDISSECTION, FALSE}, /* msg-id */
165 {"in-reply-to", &hf_imf_in_reply_to, NO_SUBDISSECTION, FALSE}, /* msg-id */
166 {"references", &hf_imf_references, NO_SUBDISSECTION, FALSE}, /* msg-id */
167 {"subject", &hf_imf_subject, NO_SUBDISSECTION, TRUE}, /* unstructured */
168 {"comments", &hf_imf_comments, NO_SUBDISSECTION, FALSE}, /* unstructured */
169 {"keywords", &hf_imf_keywords, NULL, FALSE}, /* phrase_list */
170 {"resent-date", &hf_imf_resent_date, NO_SUBDISSECTION, FALSE},
171 {"resent-from", &hf_imf_resent_from, dissect_imf_mailbox_list, FALSE},
172 {"resent-sender", &hf_imf_resent_sender, dissect_imf_mailbox, FALSE},
173 {"resent-to", &hf_imf_resent_to, dissect_imf_address_list, FALSE},
174 {"resent-cc", &hf_imf_resent_cc, dissect_imf_address_list, FALSE},
175 {"resent-bcc", &hf_imf_resent_bcc, dissect_imf_address_list, FALSE},
176 {"resent-message-id", &hf_imf_resent_message_id, NO_SUBDISSECTION, FALSE},
177 {"return-path", &hf_imf_return_path, NULL, FALSE},
178 {"received", &hf_imf_received, NO_SUBDISSECTION, FALSE},
179 /* these are really multi-part - but we parse them anyway */
180 {"content-type", &hf_imf_content_type, NULL, FALSE}, /* handled separately as a special case */
181 {"content-id", &hf_imf_content_id, NULL, FALSE},
182 {"content-description", &hf_imf_content_description, NULL, FALSE},
183 {"content-transfer-encoding", &hf_imf_content_transfer_encoding, NULL, FALSE},
184 {"mime-version", &hf_imf_mime_version, NO_SUBDISSECTION, FALSE},
185 /* MIXER - RFC 2156 */
186 {"autoforwarded", &hf_imf_autoforwarded, NULL, FALSE},
187 {"autosubmitted", &hf_imf_autosubmitted, NULL, FALSE},
188 {"x400-content-identifier", &hf_imf_x400_content_identifier, NULL, FALSE},
189 {"content-language", &hf_imf_content_language, NULL, FALSE},
190 {"conversion", &hf_imf_conversion, NULL, FALSE},
191 {"conversion-with-loss", &hf_imf_conversion_with_loss, NULL, FALSE},
192 {"delivery-date", &hf_imf_delivery_date, NULL, FALSE},
193 {"discarded-x400-ipms-extensions", &hf_imf_discarded_x400_ipms_extensions, NULL, FALSE},
194 {"discarded-x400-mts-extensions", &hf_imf_discarded_x400_mts_extensions, NULL, FALSE},
195 {"dl-expansion-history", &hf_imf_dl_expansion_history, NULL, FALSE},
196 {"deferred-delivery", &hf_imf_deferred_delivery, NULL, FALSE},
197 {"expires", &hf_imf_expires, NULL, FALSE},
198 {"importance", &hf_imf_importance, NULL, FALSE},
199 {"incomplete-copy", &hf_imf_incomplete_copy, NULL, FALSE},
200 {"latest-delivery-time", &hf_imf_latest_delivery_time, NULL, FALSE},
201 {"message-type", &hf_imf_message_type, NULL, FALSE},
202 {"original-encoded-information-types", &hf_imf_original_encoded_information_types, NULL, FALSE},
203 {"originator-return-address", &hf_imf_originator_return_address, NULL, FALSE},
204 {"priority", &hf_imf_priority, NULL, FALSE},
205 {"reply-by", &hf_imf_reply_by, NULL, FALSE},
206 {"sensitivity", &hf_imf_sensitivity, NULL, FALSE},
207 {"supersedes", &hf_imf_supersedes, NULL, FALSE},
208 {"x400-content-type", &hf_imf_x400_content_type, NULL, FALSE},
209 {"x400-mts-identifier", &hf_imf_x400_mts_identifier, NULL, FALSE},
210 {"x400-originator", &hf_imf_x400_originator, NULL, FALSE},
211 {"x400-received", &hf_imf_x400_received, NULL, FALSE},
212 {"x400-recipients", &hf_imf_x400_recipients, NULL, FALSE},
214 {"delivered-to", &hf_imf_delivered_to, dissect_imf_mailbox, FALSE}, /* mailbox */
216 {"x-mailer", &hf_imf_ext_mailer, NO_SUBDISSECTION, FALSE}, /* unstructured */
217 {"thread-index", &hf_imf_thread_index, NO_SUBDISSECTION, FALSE}, /* unstructured */
218 {"x-mimeole", &hf_imf_ext_mimeole, NO_SUBDISSECTION, FALSE}, /* unstructured */
219 {"expiry-date", &hf_imf_ext_expiry_date, NO_SUBDISSECTION, FALSE}, /* unstructured */
220 {"x-ms-tnef-correlator", &hf_imf_ext_tnef_correlator, NO_SUBDISSECTION, FALSE}, /* unstructured */
221 {"x-uidl", &hf_imf_ext_uidl, NO_SUBDISSECTION, FALSE}, /* unstructured */
222 {"x-authentication-warning", &hf_imf_ext_authentication_warning, NO_SUBDISSECTION, FALSE}, /* unstructured */
223 {"x-virus-scanned", &hf_imf_ext_virus_scanned, NO_SUBDISSECTION, FALSE}, /* unstructured */
224 {NULL, NULL, NULL, FALSE},
227 static GHashTable *imf_field_table=NULL;
229 /* Define media_type/Content type table */
230 static dissector_table_t media_type_dissector_table;
232 static void dissect_imf_address(tvbuff_t *tvb, int offset, int length, proto_item *item)
234 proto_tree *group_tree;
235 proto_item *group_item;
238 /* if there is a colon present it is a group */
239 if((addr_pos = tvb_find_guint8(tvb, offset, length, ':')) == -1) {
241 /* there isn't - so it must be a mailbox */
242 dissect_imf_mailbox(tvb, offset, length, item);
247 group_tree = proto_item_add_subtree(item, ett_imf_group);
249 /* the display-name is mandatory */
250 group_item = proto_tree_add_item(group_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, FALSE);
252 /* consume any whitespace */
253 for(addr_pos++ ;addr_pos < (offset + length); addr_pos++) {
254 if(!isspace(tvb_get_guint8(tvb, addr_pos))) {
259 if(tvb_get_guint8(tvb, addr_pos) != ';') {
261 dissect_imf_mailbox_list(tvb, addr_pos, length - (addr_pos - offset), group_item);
263 /* XXX: need to check for final ';' */
274 static void dissect_imf_mailbox(tvbuff_t *tvb, int offset, int length, proto_item *item)
276 proto_tree *mbox_tree;
277 int addr_pos, end_pos;
279 mbox_tree = proto_item_add_subtree(item, ett_imf_mailbox);
282 If we can't find and angle brackets, then the whole field is an address.
283 If we find angle brackets, then the address is between them and the display name is
284 anything before the opening angle bracket
287 if((addr_pos = tvb_find_guint8(tvb, offset, length, '<')) == -1) {
288 /* we can't find an angle bracket - the whole field is therefore the address */
290 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, offset, length, FALSE);
293 /* we can find an angle bracket - let's see if we can find a display name */
294 /* XXX: the '<' could be in the display name */
296 for(; offset < addr_pos; offset++) {
297 if(!isspace(tvb_get_guint8(tvb, offset))) {
302 if(offset != addr_pos) /* there is a display name */
303 (void) proto_tree_add_item(mbox_tree, hf_imf_display_name, tvb, offset, addr_pos - offset - 1, FALSE);
305 end_pos = tvb_find_guint8(tvb, addr_pos + 1, length - (addr_pos + 1 - offset), '>');
308 (void) proto_tree_add_item(mbox_tree, hf_imf_address, tvb, addr_pos + 1, end_pos - addr_pos - 1, FALSE);
313 static void dissect_imf_address_list(tvbuff_t *tvb, int offset, int length, proto_item *item)
315 proto_item *addr_item = NULL;
316 proto_tree *tree = NULL;
322 /* a comma separated list of addresses */
323 tree = proto_item_add_subtree(item, ett_imf_address_list);
325 item_offset = offset;
329 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
331 count++; /* increase the number of items */
334 /* length is to the end of the buffer */
335 item_length = length - (item_offset - offset);
337 item_length = end_offset - item_offset;
339 addr_item = proto_tree_add_item(tree, hf_imf_address_list_item, tvb, item_offset, item_length, FALSE);
340 dissect_imf_address(tvb, item_offset, item_length, addr_item);
343 item_offset = end_offset + 1;
345 } while(end_offset != -1);
347 /* now indicate the number of items found */
348 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
353 static void dissect_imf_mailbox_list(tvbuff_t *tvb, int offset, int length, proto_item *item)
355 proto_item *mbox_item = NULL;
356 proto_tree *tree = NULL;
362 /* a comma separated list of mailboxes */
363 tree = proto_item_add_subtree(item, ett_imf_mailbox_list);
365 item_offset = offset;
369 end_offset = tvb_find_guint8(tvb, item_offset, length - (item_offset - offset), ',');
371 count++; /* increase the number of items */
374 /* length is to the end of the buffer */
375 item_length = length - (item_offset - offset);
377 item_length = end_offset - item_offset;
379 mbox_item = proto_tree_add_item(tree, hf_imf_mailbox_list_item, tvb, item_offset, item_length, FALSE);
380 dissect_imf_mailbox(tvb, item_offset, item_length, mbox_item);
383 item_offset = end_offset + 1;
385 } while(end_offset != -1);
387 /* now indicate the number of items found */
388 proto_item_append_text(item, ", %d item%s", count, plurality(count, "", "s"));
394 static void dissect_imf_content_type(tvbuff_t *tvb, int offset, int length, proto_item *item,
395 char **type, char **parameters)
402 /* first strip any whitespace */
403 for(i = 0; i < length; i++) {
404 if(!isspace(tvb_get_guint8(tvb, offset + i))) {
410 /* find the first colon - there has to be a colon as there will have to be a boundary */
411 first_colon = tvb_find_guint8(tvb, offset, length, ';');
413 if(first_colon != -1) {
414 ct_tree = proto_item_add_subtree(item, ett_imf_content_type);
416 len = first_colon - offset;
417 proto_tree_add_item(ct_tree, hf_imf_content_type_type, tvb, offset, len, FALSE);
419 /* This string will be automatically freed */
420 (*type) = tvb_get_ephemeral_string(tvb, offset, len);
422 len = length - (first_colon + 1 - offset);
423 proto_tree_add_item(ct_tree, hf_imf_content_type_parameters, tvb, first_colon + 1, len, FALSE);
425 /* This string will be automatically freed */
426 (*parameters) = tvb_get_ephemeral_string(tvb, first_colon + 1, len);
431 int imf_find_field_end(tvbuff_t *tvb, int offset, gint max_length, gboolean *last_field)
434 while(offset < max_length) {
437 offset = tvb_find_guint8(tvb, offset, max_length - offset, '\r');
440 if(tvb_get_guint8(tvb, ++offset) == '\n') {
441 /* OK - so we have found CRLF */
442 /* peek the next character */
443 switch(tvb_get_guint8(tvb, ++offset)) {
445 /* probably end of the fields */
446 if(tvb_get_guint8(tvb, ++offset) == '\n')
453 /* continuation line */
456 /* this is a new field */
461 /* couldn't find a CR - strange */
471 static void dissect_imf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
474 proto_tree *unknown_tree, *text_tree;
475 char *content_type_str = NULL;
476 char *parameters = NULL;
478 gint start_offset = 0;
479 gint value_offset = 0;
480 gint unknown_offset = 0;
484 gboolean last_field = FALSE;
485 gboolean dissected = FALSE;
487 struct imf_field *f_info;
489 if (check_col(pinfo->cinfo, COL_PROTOCOL))
490 col_set_str(pinfo->cinfo, COL_PROTOCOL, PSNAME);
491 col_clear(pinfo->cinfo, COL_INFO);
494 item = proto_tree_add_item(tree, proto_imf, tvb, 0, -1, FALSE);
495 tree = proto_item_add_subtree(item, ett_imf);
498 max_length = tvb_length(tvb);
499 /* first go through the tvb until we find a blank line and extract the content type if
504 /* look for a colon first */
505 end_offset = tvb_find_guint8(tvb, start_offset, max_length - start_offset, ':');
507 if(end_offset == -1) {
508 /* we couldn't find another colon - strange - we should have broken out of here by now */
509 /* XXX: flag an error */
514 key = tvb_get_ephemeral_string(tvb, start_offset, end_offset - start_offset);
516 /* convert to lower case */
522 /* look up the key */
523 f_info = (struct imf_field *)g_hash_table_lookup(imf_field_table, key);
525 if(f_info == (struct imf_field *)NULL) {
526 /* set as an unknown extension */
528 unknown_offset = start_offset;
531 hf_id = *(f_info->hf_id);
533 /* value starts immediately after the colon */
534 start_offset = end_offset+1;
536 end_offset = imf_find_field_end(tvb, start_offset, max_length, &last_field);
538 if(end_offset != -1) {
540 /* remove any leading whitespace */
542 for(value_offset = start_offset; value_offset < end_offset; value_offset++)
543 if(!isspace(tvb_get_guint8(tvb, value_offset))) {
547 if(value_offset == end_offset) {
548 /* empty field - show whole value */
549 value_offset = start_offset;
552 if(hf_id == hf_imf_extension_type) {
554 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
555 item = proto_tree_add_item(tree, hf_imf_extension, tvb, unknown_offset, end_offset - unknown_offset - 2, FALSE);
557 proto_item_append_text(item, " (Contact Wireshark developers if you want this supported.)");
559 unknown_tree = proto_item_add_subtree(item, ett_imf_extension);
561 item = proto_tree_add_item(unknown_tree, hf_imf_extension_type, tvb, unknown_offset, start_offset - 1 - unknown_offset, FALSE);
563 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
564 item = proto_tree_add_item(unknown_tree, hf_imf_extension_value, tvb, start_offset, end_offset - start_offset - 2, FALSE);
568 /* remove 2 bytes to take off the final CRLF to make things a little prettier */
569 item = proto_tree_add_item(tree, hf_id, tvb, value_offset, end_offset - value_offset - 2, FALSE);
571 if(f_info->add_to_col_info && check_col(pinfo->cinfo, COL_INFO)) {
573 col_append_fstr(pinfo->cinfo, COL_INFO, "%s: %s, ", f_info->name,
574 tvb_format_text(tvb, value_offset, end_offset - value_offset - 2));
577 if(hf_id == hf_imf_content_type) {
578 /* we need some additional processing to extract the content type and parameters */
580 dissect_imf_content_type(tvb, start_offset, end_offset - start_offset, item,
581 &content_type_str, ¶meters);
583 } else if(f_info && f_info->subdissector) {
585 /* we have a subdissector */
586 f_info->subdissector(tvb, value_offset, end_offset - value_offset, item);
591 start_offset = end_offset;
594 /* specify a content type until we can work it out for ourselves */
595 /* content_type_str = "multipart/mixed"; */
597 /* now dissect the MIME based upon the content type */
599 if(content_type_str && media_type_dissector_table) {
601 pd_save = pinfo->private_data;
602 pinfo->private_data = parameters;
604 next_tvb = tvb_new_subset(tvb, end_offset, -1, -1);
606 dissected = dissector_try_string(media_type_dissector_table, content_type_str, next_tvb, pinfo, tree);
608 pinfo->private_data = pd_save;
611 /* just show the lines or highlight the rest of the buffer as message text */
613 item = proto_tree_add_item(tree, hf_imf_message_text, tvb, start_offset, -1 , FALSE);
614 text_tree = proto_item_add_subtree(item, ett_imf_message_text);
616 start_offset = end_offset;
617 while (tvb_offset_exists(tvb, start_offset)) {
620 * Find the end of the line.
622 tvb_find_line_end(tvb, start_offset, -1, &end_offset, FALSE);
627 proto_tree_add_text(text_tree, tvb, start_offset, end_offset - start_offset,
629 tvb_format_text(tvb, start_offset, end_offset - start_offset - 2));
632 * Step to the next line.
634 start_offset = end_offset;
640 /* Register all the bits needed by the filtering engine */
643 proto_register_imf(void)
645 static hf_register_info hf[] = {
647 { "Date", "imf.date", FT_STRING, BASE_NONE, NULL, 0x0,
648 "imf.DateTime", HFILL }},
650 { "From", "imf.from", FT_STRING, BASE_NONE, NULL, 0x0,
651 "imf.MailboxList", HFILL }},
653 { "Sender", "imf.sender", FT_STRING, BASE_NONE, NULL, 0x0,
656 { "Reply-To", "imf.reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
659 { "To", "imf.to", FT_STRING, BASE_NONE, NULL, 0x0,
662 { "Cc", "imf.cc", FT_STRING, BASE_NONE, NULL, 0x0,
665 { "Bcc", "imf.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
667 { &hf_imf_message_id,
668 { "Message-ID", "imf.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
670 { &hf_imf_in_reply_to,
671 { "In-Reply-To", "imf.in_reply_to", FT_STRING, BASE_NONE, NULL, 0x0,
673 { &hf_imf_references,
674 { "References", "imf.references", FT_STRING, BASE_NONE, NULL, 0x0,
677 { "Subject", "imf.subject", FT_STRING, BASE_NONE, NULL, 0x0,
680 { "Comments", "imf.comments", FT_STRING, BASE_NONE, NULL, 0x0,
683 { "Keywords", "imf.keywords", FT_STRING, BASE_NONE, NULL, 0x0,
685 { &hf_imf_resent_date,
686 { "Resent-Date", "imf.resent.date", FT_STRING, BASE_NONE, NULL, 0x0,
688 { &hf_imf_resent_from,
689 { "Resent-From", "imf.resent.from", FT_STRING, BASE_NONE, NULL, 0x0,
691 { &hf_imf_resent_sender,
692 { "Resent-Sender", "imf.resent.sender", FT_STRING, BASE_NONE, NULL, 0x0,
695 { "Resent-To", "imf.resent.to", FT_STRING, BASE_NONE, NULL, 0x0,
698 { "Resent-Cc", "imf.resent.cc", FT_STRING, BASE_NONE, NULL, 0x0,
700 { &hf_imf_resent_bcc,
701 { "Resent-Bcc", "imf.resent.bcc", FT_STRING, BASE_NONE, NULL, 0x0,
703 { &hf_imf_resent_message_id,
704 { "Resent-Message-ID", "imf.resent.message_id", FT_STRING, BASE_NONE, NULL, 0x0,
706 { &hf_imf_return_path,
707 { "Return-Path", "imf.return_path", FT_STRING, BASE_NONE, NULL, 0x0,
710 { "Received", "imf.received", FT_STRING, BASE_NONE, NULL, 0x0,
712 { &hf_imf_content_type,
713 { "Content-Type", "imf.content.type", FT_STRING, BASE_NONE, NULL, 0x0,
715 { &hf_imf_content_type_type,
716 { "Type", "imf.content.type.type", FT_STRING, BASE_NONE, NULL, 0x0,
718 { &hf_imf_content_type_parameters,
719 { "Parameters", "imf.content.type.parameters", FT_STRING, BASE_NONE, NULL, 0x0,
721 { &hf_imf_content_description,
722 { "Content-Description", "imf.content.description", FT_STRING, BASE_NONE, NULL, 0x0,
724 { &hf_imf_content_id,
725 { "Content-ID", "imf.content.id", FT_STRING, BASE_NONE, NULL, 0x0,
727 { &hf_imf_content_transfer_encoding,
728 { "Content-Transfer-Encoding", "imf.content.transfer_encoding", FT_STRING, BASE_NONE, NULL, 0x0,
730 { &hf_imf_mime_version,
731 { "MIME-Version", "imf.mime_version", FT_STRING, BASE_NONE, NULL, 0x0,
733 { &hf_imf_autoforwarded,
734 { "Autoforwarded", "imf.autoforwarded", FT_STRING, BASE_NONE, NULL, 0x0,
736 { &hf_imf_autosubmitted,
737 { "Autosubmitted", "imf.autosubmitted", FT_STRING, BASE_NONE, NULL, 0x0,
739 { &hf_imf_x400_content_identifier,
740 { "X400-Content-Identifier", "imf.x400_content_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
742 { &hf_imf_content_language,
743 { "Content-Language", "imf.content_language", FT_STRING, BASE_NONE, NULL, 0x0,
745 { &hf_imf_conversion,
746 { "Conversion", "imf.conversion", FT_STRING, BASE_NONE, NULL, 0x0,
748 { &hf_imf_conversion_with_loss,
749 { "Conversion-With-Loss", "imf.conversion_with_loss", FT_STRING, BASE_NONE, NULL, 0x0,
751 { &hf_imf_delivery_date,
752 { "Delivery-Date", "imf.delivery_date", FT_STRING, BASE_NONE, NULL, 0x0,
754 { &hf_imf_discarded_x400_ipms_extensions,
755 { "Discarded-X400-IPMS-Extensions", "imf.discarded_x400_ipms_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
757 { &hf_imf_discarded_x400_mts_extensions,
758 { "Discarded-X400-MTS-Extensions", "imf.discarded_x400_mts_extensions", FT_STRING, BASE_NONE, NULL, 0x0,
760 { &hf_imf_dl_expansion_history,
761 { "DL-Expansion-History", "imf.dl_expansion_history", FT_STRING, BASE_NONE, NULL, 0x0,
763 { &hf_imf_deferred_delivery,
764 { "Deferred-Delivery", "imf.deferred_delivery", FT_STRING, BASE_NONE, NULL, 0x0,
767 { "Expires", "imf.expires", FT_STRING, BASE_NONE, NULL, 0x0,
769 { &hf_imf_importance,
770 { "Importance", "imf.importance", FT_STRING, BASE_NONE, NULL, 0x0,
772 { &hf_imf_incomplete_copy,
773 { "Incomplete-Copy", "imf.incomplete_copy", FT_STRING, BASE_NONE, NULL, 0x0,
775 { &hf_imf_latest_delivery_time,
776 { "Latest-Delivery-Time", "imf.latest_delivery_time", FT_STRING, BASE_NONE, NULL, 0x0,
778 { &hf_imf_message_type,
779 { "Message-Type", "imf.message_type", FT_STRING, BASE_NONE, NULL, 0x0,
781 { &hf_imf_original_encoded_information_types,
782 { "Original-Encoded-Information-Types", "imf.original_encoded_information_types", FT_STRING, BASE_NONE, NULL, 0x0,
784 { &hf_imf_originator_return_address,
785 { "Originator-Return-Address", "imf.originator_return_address", FT_STRING, BASE_NONE, NULL, 0x0,
788 { "Priority", "imf.priority", FT_STRING, BASE_NONE, NULL, 0x0,
791 { "Reply-By", "imf.reply_by", FT_STRING, BASE_NONE, NULL, 0x0,
793 { &hf_imf_sensitivity,
794 { "Sensitivity", "imf.sensitivity", FT_STRING, BASE_NONE, NULL, 0x0,
796 { &hf_imf_supersedes,
797 { "Supersedes", "imf.supersedes", FT_STRING, BASE_NONE, NULL, 0x0,
799 { &hf_imf_x400_content_type,
800 { "X400-Content-Type", "imf.x400_content_type", FT_STRING, BASE_NONE, NULL, 0x0,
802 { &hf_imf_x400_mts_identifier,
803 { "X400-MTS-Identifier", "imf.x400_mts_identifier", FT_STRING, BASE_NONE, NULL, 0x0,
805 { &hf_imf_x400_originator,
806 { "X400-Originator", "imf.x400_originator", FT_STRING, BASE_NONE, NULL, 0x0,
808 { &hf_imf_x400_received,
809 { "X400-Received", "imf.x400_received", FT_STRING, BASE_NONE, NULL, 0x0,
811 { &hf_imf_x400_recipients,
812 { "X400-Recipients", "imf.x400_recipients", FT_STRING, BASE_NONE, NULL, 0x0,
814 { &hf_imf_delivered_to,
815 { "Delivered-To", "imf.delivered_to", FT_STRING, BASE_NONE, NULL, 0x0,
817 { &hf_imf_ext_mailer,
818 { "X-Mailer", "imf.ext.mailer", FT_STRING, BASE_NONE, NULL, 0x0,
820 { &hf_imf_ext_mimeole,
821 { "X-MimeOLE", "imf.ext.mimeole", FT_STRING, BASE_NONE, NULL, 0x0,
823 { &hf_imf_ext_expiry_date,
824 { "Expiry-Date", "imf.ext.expiry-date", FT_STRING, BASE_NONE, NULL, 0x0,
826 { &hf_imf_ext_tnef_correlator,
827 { "X-MS-TNEF-Correlator", "imf.ext.tnef-correlator", FT_STRING, BASE_NONE, NULL, 0x0,
830 { "X-UIDL", "imf.ext.uidl", FT_STRING, BASE_NONE, NULL, 0x0,
832 { &hf_imf_ext_authentication_warning,
833 { "X-Authentication-Warning", "imf.ext.authentication_warning", FT_STRING, BASE_NONE,
834 NULL, 0x0, NULL, HFILL }},
835 { &hf_imf_ext_virus_scanned,
836 { "X-Virus-Scanned", "imf.ext.virus_scanned", FT_STRING, BASE_NONE, NULL, 0x0,
838 { &hf_imf_thread_index,
839 { "Thread-Index", "imf.thread-index", FT_STRING, BASE_NONE, NULL, 0x0,
842 { "Unknown-Extension", "imf.extension", FT_STRING, BASE_NONE, NULL, 0x0,
844 { &hf_imf_extension_type,
845 { "Type", "imf.extension.type", FT_STRING, BASE_NONE, NULL, 0x0,
847 { &hf_imf_extension_value,
848 { "Value", "imf.extension.value", FT_STRING, BASE_NONE, NULL, 0x0,
850 { &hf_imf_display_name,
851 { "Display-Name", "imf.display_name", FT_STRING, BASE_NONE, NULL, 0x0,
854 { "Address", "imf.address", FT_STRING, BASE_NONE, NULL, 0x0,
856 { &hf_imf_address_list,
857 { "Address List", "imf.address_list", FT_UINT32, BASE_DEC, NULL, 0x0,
859 { &hf_imf_address_list_item,
860 { "Item", "imf.address_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
862 { &hf_imf_mailbox_list,
863 { "Mailbox List", "imf.mailbox_list", FT_UINT32, BASE_DEC, NULL, 0x0,
865 { &hf_imf_mailbox_list_item,
866 { "Item", "imf.mailbox_list.item", FT_STRING, BASE_NONE, NULL, 0x0,
868 { &hf_imf_message_text,
869 { "Message-Text", "imf.message_text", FT_NONE, BASE_NONE, NULL, 0x0,
872 static gint *ett[] = {
874 &ett_imf_content_type,
877 &ett_imf_mailbox_list,
878 &ett_imf_address_list,
880 &ett_imf_message_text,
885 proto_imf = proto_register_protocol(PNAME, PSNAME, PFNAME);
887 proto_register_field_array(proto_imf, hf, array_length(hf));
888 proto_register_subtree_array(ett, array_length(ett));
890 /* Allow dissector to find be found by name. */
891 register_dissector(PFNAME, dissect_imf, proto_imf);
893 imf_field_table=g_hash_table_new(g_str_hash, g_str_equal); /* oid to syntax */
895 /* register the fields for lookup */
896 for(f = imf_fields; f->name; f++)
897 g_hash_table_insert(imf_field_table, (const gpointer)f->name, (const gpointer)f);
901 /* The registration hand-off routine */
903 proto_reg_handoff_imf(void)
905 dissector_handle_t imf_handle;
907 imf_handle = find_dissector(PFNAME);
909 dissector_add_string("media_type",
910 "message/rfc822", imf_handle);
912 register_ber_oid_dissector("1.2.840.113549.1.7.1", dissect_imf, proto_imf, "id-data");
915 * Get the content type and Internet media type table
917 media_type_dissector_table = find_dissector_table("media_type");