2 * Routines for MMS Message Encapsulation dissection
3 * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
4 * Copyright 2004, Olivier Biot
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 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.
27 * Dissector of an encoded Multimedia message PDU, as defined by the WAPForum
28 * (http://www.wapforum.org) in "WAP-209-MMSEncapsulation-20020105-a".
29 * Subsequent releases of MMS are in control of the Open Mobile Alliance (OMA):
30 * Dissection of MMS 1.1 as in OMA-MMS-ENC-v1.1.
31 * Dissection of MMS 1.2 as in OMA-MMS-ENC-v1.2 (not finished yet).
34 /* This file has been edited with 8-space tabs and 4-space indentation */
46 #include <epan/packet.h>
47 #include <epan/strutil.h>
48 #include "packet-wap.h"
49 #include "packet-wsp.h"
50 /* #include "packet-mmse.h" */ /* We autoregister */
51 #include <epan/emem.h>
53 #define MM_QUOTE 0x7F /* Quoted string */
55 #define MMS_CONTENT_TYPE 0x3E /* WINA-value for mms-message */
57 /* General-purpose debug logger.
58 * Requires double parentheses because of variable arguments of printf().
60 * Enable debug logging for MMSE by defining AM_CFLAGS
61 * so that it contains "-DDEBUG_mmse"
65 g_print("%s:%u: ", __FILE__, __LINE__); \
73 * Forward declarations
75 static void dissect_mmse_standalone(tvbuff_t *, packet_info *, proto_tree *);
76 static void dissect_mmse_encapsulated(tvbuff_t *, packet_info *, proto_tree *);
77 static void dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
78 guint8 pdut, const char *message_type);
84 #define MM_BCC_HDR 0x81 /* Bcc */
85 #define MM_CC_HDR 0x82 /* Cc */
86 #define MM_CLOCATION_HDR 0x83 /* X-Mms-Content-Location */
87 #define MM_CTYPE_HDR 0x84 /* Content-Type */
88 #define MM_DATE_HDR 0x85 /* Date */
89 #define MM_DREPORT_HDR 0x86 /* X-Mms-Delivery-Report */
90 #define MM_DTIME_HDR 0x87 /* X-Mms-Delivery-Time */
91 #define MM_EXPIRY_HDR 0x88 /* X-Mms-Expiry */
92 #define MM_FROM_HDR 0x89 /* From */
93 #define MM_MCLASS_HDR 0x8A /* X-Mms-Message-Class */
94 #define MM_MID_HDR 0x8B /* Message-ID */
95 #define MM_MTYPE_HDR 0x8C /* X-Mms-Message-Type */
96 #define MM_VERSION_HDR 0x8D /* X-Mms-MMS-Version */
97 #define MM_MSIZE_HDR 0x8E /* X-Mms-Message-Size */
98 #define MM_PRIORITY_HDR 0x8F /* X-Mms-Priority */
99 #define MM_RREPLY_HDR 0x90 /* X-Mms-Read-Reply */
100 #define MM_RALLOWED_HDR 0x91 /* X-Mms-Report-Allowed */
101 #define MM_RSTATUS_HDR 0x92 /* X-Mms-Response-Status */
102 #define MM_RTEXT_HDR 0x93 /* X-Mms-Response-Text */
103 #define MM_SVISIBILITY_HDR 0x94 /* X-Mms-Sender-Visibility */
104 #define MM_STATUS_HDR 0x95 /* X-Mms-Status */
105 #define MM_SUBJECT_HDR 0x96 /* Subject */
106 #define MM_TO_HDR 0x97 /* To */
107 #define MM_TID_HDR 0x98 /* X-Mms-Transaction-Id */
109 #define MM_RETRIEVE_STATUS_HDR 0x99 /* X-Mms-Retrieve-Status */
110 #define MM_RETRIEVE_TEXT_HDR 0x9A /* X-Mms-Retrieve-Text */
111 #define MM_READ_STATUS_HDR 0x9B /* X-Mms-Read-Status */
112 #define MM_REPLY_CHARGING_HDR 0x9C /* X-Mms-Reply-Charging */
113 #define MM_REPLY_CHARGING_DEADLINE_HDR \
114 0x9D /* X-Mms-Reply-Charging-Deadline*/
115 #define MM_REPLY_CHARGING_ID_HDR \
116 0x9E /* X-Mms-Reply-Charging-ID */
117 #define MM_REPLY_CHARGING_SIZE_HDR \
118 0x9F /* X-Mms-Reply-Charging-Size */
119 #define MM_PREV_SENT_BY_HDR 0xA0 /* X-Mms-Previously-Sent-By */
120 #define MM_PREV_SENT_DATE_HDR 0xA1 /* X-Mms-Previously-Sent-Date */
122 #define MM_STORE_HDR 0xA2 /* X-Mms-Store */
123 #define MM_MM_STATE_HDR 0xA3 /* X-Mms-MM-State */
124 #define MM_MM_FLAGS_HDR 0xA4 /* X-Mms-MM-Flags */
125 #define MM_STORE_STATUS_HDR 0xA5 /* X-Mms-Store-Status */
126 #define MM_STORE_STATUS_TEXT_HDR \
127 0xA6 /* X-Mms-Store-Status-Text */
128 #define MM_STORED_HDR 0xA7 /* X-Mms-Stored */
129 #define MM_ATTRIBUTES_HDR 0xA8 /* X-Mms-Attributes */
130 #define MM_TOTALS_HDR 0xA9 /* X-Mms-Totals */
131 #define MM_MBOX_TOTALS_HDR 0xAA /* X-Mms-Mbox-Totals */
132 #define MM_QUOTAS_HDR 0xAB /* X-Mms-Quotas */
133 #define MM_MBOX_QUOTAS_HDR 0xAC /* X-Mms-Mbox-Quotas */
134 #define MM_MBOX_MSG_COUNT_HDR 0xAD /* X-Mms-Message-Count */
135 #define MM_CONTENT_HDR 0xAE /* Content */
136 #define MM_START_HDR 0xAF /* X-Mms-Start */
137 #define MM_ADDITIONAL_HDR 0xB0 /* Additional-headers */
138 #define MM_DISTRIBUION_IND_HDR 0xB1 /* X-Mms-Distribution-Indcator */
139 #define MM_ELEMENT_DESCR_HDR 0xB2 /* X-Mms-Element-Descriptor */
140 #define MM_LIMIT_HDR 0xB3 /* X-Mms-Limit */
142 static const value_string vals_mm_header_names[] = {
144 { MM_BCC_HDR, "Bcc" },
146 { MM_CLOCATION_HDR, "X-Mms-Content-Location" },
147 { MM_CTYPE_HDR, "X-Mms-Content-Type" },
148 { MM_DATE_HDR, "Date" },
149 { MM_DREPORT_HDR, "X-Mms-Delivery-Report" },
150 { MM_DTIME_HDR, "X-Mms-Delivery-Time" },
151 { MM_EXPIRY_HDR, "X-Mms-Expiry" },
152 { MM_FROM_HDR, "From" },
153 { MM_MCLASS_HDR, "X-Mms-Message-Class" },
154 { MM_MID_HDR, "Message-ID" },
155 { MM_MTYPE_HDR, "X-Mms-Message-Type" },
156 { MM_VERSION_HDR, "X-Mms-MMS-Version" },
157 { MM_MSIZE_HDR, "X-Mms-Message-Size" },
158 { MM_PRIORITY_HDR, "X-Mms-Priority" },
159 { MM_RREPLY_HDR, "X-Mms-Read-Reply" },
160 { MM_RALLOWED_HDR, "X-Mms-Report-Allowed" },
161 { MM_RSTATUS_HDR, "X-Mms-Response-Status" },
162 { MM_RTEXT_HDR, "X-Mms-Response-Text" },
163 { MM_SVISIBILITY_HDR, "X-Mms-Sender-Visibility" },
164 { MM_STATUS_HDR, "X-Mms-Status" },
165 { MM_SUBJECT_HDR, "Subject" },
167 { MM_TID_HDR, "X-Mms-Transaction-Id" },
169 { MM_RETRIEVE_STATUS_HDR, "X-Mms-Retrieve-Status" },
170 { MM_RETRIEVE_TEXT_HDR, "X-Mms-Retrieve-Text" },
171 { MM_READ_STATUS_HDR, "X-Mms-Read-Status" },
172 { MM_REPLY_CHARGING_HDR, "X-Mms-Reply-Charging" },
173 { MM_REPLY_CHARGING_DEADLINE_HDR,
174 "X-Mms-Reply-Charging-Deadline" },
175 { MM_REPLY_CHARGING_ID_HDR, "X-Mms-Reply-Charging-ID" },
176 { MM_REPLY_CHARGING_SIZE_HDR, "X-Mms-Reply-Charging-Size" },
177 { MM_PREV_SENT_BY_HDR, "X-Mms-Previously-Sent-By" },
178 { MM_PREV_SENT_DATE_HDR, "X-Mms-Previously-Sent-Date" },
180 { MM_STORE_HDR, "X-Mms-Store" },
181 { MM_MM_STATE_HDR, "X-Mms-MM-State " },
182 { MM_MM_FLAGS_HDR, "X-Mms-MM-Flags " },
183 { MM_STORE_STATUS_HDR, "X-Mms-Store-Status" },
184 { MM_STORE_STATUS_TEXT_HDR, "X-Mms-Store-Status-Text" },
185 { MM_STORED_HDR, "X-Mms-Stored" },
186 { MM_ATTRIBUTES_HDR, "X-Mms-Attributes" },
187 { MM_TOTALS_HDR, "X-Mms-Totals" },
188 { MM_MBOX_TOTALS_HDR, "X-Mms-Mbox-Totals" },
189 { MM_QUOTAS_HDR, "X-Mms-Quotas" },
190 { MM_MBOX_QUOTAS_HDR, "X-Mms-Mbox-Quotas" },
191 { MM_MBOX_MSG_COUNT_HDR, "X-Mms-Message-Count" },
192 { MM_CONTENT_HDR, "Content" },
193 { MM_START_HDR, "X-Mms-Start" },
194 { MM_ADDITIONAL_HDR, "Additional-headers" },
195 { MM_DISTRIBUION_IND_HDR, "X-Mms-Distribution-Indcator" },
196 { MM_ELEMENT_DESCR_HDR, "X-Mms-Element-Descriptor" },
197 { MM_LIMIT_HDR, "X-Mms-Limit" },
202 * Initialize the protocol and registered fields
204 static int proto_mmse = -1;
206 static int hf_mmse_message_type = -1;
207 static int hf_mmse_transaction_id = -1;
208 static int hf_mmse_mms_version = -1;
209 static int hf_mmse_bcc = -1;
210 static int hf_mmse_cc = -1;
211 static int hf_mmse_content_location = -1;
212 static int hf_mmse_date = -1;
213 static int hf_mmse_delivery_report = -1;
214 static int hf_mmse_delivery_time_abs = -1;
215 static int hf_mmse_delivery_time_rel = -1;
216 static int hf_mmse_expiry_abs = -1;
217 static int hf_mmse_expiry_rel = -1;
218 static int hf_mmse_from = -1;
219 static int hf_mmse_message_class_id = -1;
220 static int hf_mmse_message_class_str = -1;
221 static int hf_mmse_message_id = -1;
222 static int hf_mmse_message_size = -1;
223 static int hf_mmse_priority = -1;
224 static int hf_mmse_read_reply = -1;
225 static int hf_mmse_report_allowed = -1;
226 static int hf_mmse_response_status = -1;
227 static int hf_mmse_response_text = -1;
228 static int hf_mmse_sender_visibility = -1;
229 static int hf_mmse_status = -1;
230 static int hf_mmse_subject = -1;
231 static int hf_mmse_to = -1;
232 static int hf_mmse_content_type = -1;
233 static int hf_mmse_ffheader = -1;
235 static int hf_mmse_read_report = -1;
236 static int hf_mmse_retrieve_status = -1;
237 static int hf_mmse_retrieve_text = -1;
238 static int hf_mmse_read_status = -1;
239 static int hf_mmse_reply_charging = -1;
240 static int hf_mmse_reply_charging_deadline_abs = -1;
241 static int hf_mmse_reply_charging_deadline_rel = -1;
242 static int hf_mmse_reply_charging_id = -1;
243 static int hf_mmse_reply_charging_size = -1;
244 static int hf_mmse_prev_sent_by = -1;
245 static int hf_mmse_prev_sent_by_fwd_count = -1;
246 static int hf_mmse_prev_sent_by_address = -1;
247 static int hf_mmse_prev_sent_date = -1;
248 static int hf_mmse_prev_sent_date_fwd_count = -1;
249 static int hf_mmse_prev_sent_date_date = -1;
252 * Initialize the subtree pointers
254 static gint ett_mmse = -1;
255 static gint ett_mmse_hdr_details = -1;
258 * Valuestrings for PDU types
261 #define PDU_M_SEND_REQ 0x80
262 #define PDU_M_SEND_CONF 0x81
263 #define PDU_M_NOTIFICATION_IND 0x82
264 #define PDU_M_NOTIFYRESP_IND 0x83
265 #define PDU_M_RETRIEVE_CONF 0x84
266 #define PDU_M_ACKNOWLEDGE_IND 0x85
267 #define PDU_M_DELIVERY_IND 0x86
269 #define PDU_M_READ_REC_IND 0x87
270 #define PDU_M_READ_ORIG_IND 0x88
271 #define PDU_M_FORWARD_REQ 0x89
272 #define PDU_M_FORWARD_CONF 0x8A
274 #define PDU_M_MBOX_STORE_REQ 0x8B
275 #define PDU_M_MBOX_STORE_CONF 0x8C
276 #define PDU_M_MBOX_VIEW_REQ 0x8D
277 #define PDU_M_MBOX_VIEW_CONF 0x8E
278 #define PDU_M_MBOX_UPLOAD_REQ 0x8F
279 #define PDU_M_MBOX_UPLOAD_CONF 0x90
280 #define PDU_M_MBOX_DELETE_REQ 0x91
281 #define PDU_M_MBOX_DELETE_CONF 0x92
282 #define PDU_M_MBOX_DESCR 0x93
284 #define pdu_has_content(pdut) \
285 ( ((pdut) == PDU_M_SEND_REQ) \
286 || ((pdut) == PDU_M_DELIVERY_IND) \
287 || ((pdut) == PDU_M_RETRIEVE_CONF) \
288 || ((pdut) == PDU_M_MBOX_VIEW_CONF) \
289 || ((pdut) == PDU_M_MBOX_DESCR) \
290 || ((pdut) == PDU_M_MBOX_UPLOAD_REQ) \
293 static const value_string vals_message_type[] = {
295 { PDU_M_SEND_REQ, "m-send-req" },
296 { PDU_M_SEND_CONF, "m-send-conf" },
297 { PDU_M_NOTIFICATION_IND, "m-notification-ind" },
298 { PDU_M_NOTIFYRESP_IND, "m-notifyresp-ind" },
299 { PDU_M_RETRIEVE_CONF, "m-retrieve-conf" },
300 { PDU_M_ACKNOWLEDGE_IND, "m-acknowledge-ind" },
301 { PDU_M_DELIVERY_IND, "m-delivery-ind" },
303 { PDU_M_READ_REC_IND, "m-read-rec-ind" },
304 { PDU_M_READ_ORIG_IND, "m-read-orig-ind" },
305 { PDU_M_FORWARD_REQ, "m-forward-req" },
306 { PDU_M_FORWARD_CONF, "m-forward-conf" },
308 { PDU_M_MBOX_STORE_REQ, "m-mbox-store-req" },
309 { PDU_M_MBOX_STORE_CONF, "m-mbox-store-conf" },
310 { PDU_M_MBOX_VIEW_REQ, "m-mbox-view-req" },
311 { PDU_M_MBOX_VIEW_CONF, "m-mbox-view-conf" },
312 { PDU_M_MBOX_UPLOAD_REQ, "m-mbox-upload-req" },
313 { PDU_M_MBOX_UPLOAD_CONF, "m-mbox-upload-conf" },
314 { PDU_M_MBOX_DELETE_REQ, "m-mbox-delete-req" },
315 { PDU_M_MBOX_DELETE_CONF, "m-mbox-delete-conf" },
316 { PDU_M_MBOX_DESCR, "m-mbox-descr" },
320 static const value_string vals_yes_no[] = {
326 static const value_string vals_message_class[] = {
327 { 0x80, "Personal" },
328 { 0x81, "Advertisement" },
329 { 0x82, "Informational" },
334 static const value_string vals_priority[] = {
341 static const value_string vals_response_status[] = {
342 /* MMS 1.0 - obsolete as from MMS 1.1 */
344 { 0x81, "Unspecified" },
345 { 0x82, "Service denied" },
346 { 0x83, "Message format corrupt" },
347 { 0x84, "Sending address unresolved" },
348 { 0x85, "Message not found" },
349 { 0x86, "Network problem" },
350 { 0x87, "Content not accepted" },
351 { 0x88, "Unsupported message" },
357 { 0xC0, "Transient failure" },
358 { 0xC1, "Transient: Sending address unresolved" },
359 { 0xC2, "Transient: Message not found" },
360 { 0xC3, "Transient: Network problem" },
362 { 0xC4, "Transient: Partial success" },
368 { 0xE0, "Permanent failure" },
369 { 0xE1, "Permanent: Service denied" },
370 { 0xE2, "Permanent: Message format corrupt" },
371 { 0xE3, "Permanent: Sending address unresolved" },
372 { 0xE4, "Permanent: Message not found" },
373 { 0xE5, "Permanent: Content not accepted" },
374 { 0xE6, "Permanent: Reply charging limitations not met" },
375 { 0xE7, "Permanent: Reply charging request not accepted" },
376 { 0xE8, "Permanent: Reply charging forwarding denied" },
377 { 0xE9, "Permanent: Reply charging not supported" },
379 { 0xEA, "Permanent: Address hiding not supported" },
384 static const value_string vals_sender_visibility[] = {
390 static const value_string vals_message_status[] = {
393 { 0x81, "Retrieved" },
394 { 0x82, "Rejected" },
395 { 0x83, "Deferred" },
396 { 0x84, "Unrecognized" },
398 { 0x85, "Indeterminate" },
399 { 0x86, "Forwarded" },
401 { 0x87, "Unreachable" },
406 static const value_string vals_retrieve_status[] = {
411 { 0xC0, "Transient failure" },
412 { 0xC1, "Transient: Message not found" },
413 { 0xC2, "Transient: Network problem" },
419 { 0xE0, "Permanent failure" },
420 { 0xE1, "Permanent: Service denied" },
421 { 0xE2, "Permanent: Message not found" },
422 { 0xE3, "Permanent: Content unsupported" },
427 static const value_string vals_read_status[] = {
429 { 0x81, "Deleted without being read" },
434 static const value_string vals_reply_charging[] = {
435 { 0x80, "Requested" },
436 { 0x81, "Requested text only" },
437 { 0x82, "Accepted" },
438 { 0x83, "Accepted text only" },
444 * Decodes a Text-string from the protocol data
445 * Text-string = [Quote] *TEXT End-of-string
446 * Quote = <Octet 127>
447 * End-of-string = <Octet 0>
449 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
451 * \param tvb The buffer with PDU-data
452 * \param offset Offset within that buffer
453 * \param strval Pointer to variable into which to put pointer to
454 * buffer allocated to hold the text; must be freed
455 * when no longer used
457 * \return The length in bytes of the entire field
460 get_text_string(tvbuff_t *tvb, guint offset, char **strval)
464 DebugLog(("get_text_string(tvb = %p, offset = %u, **strval) - start\n",
466 len = tvb_strsize(tvb, offset);
467 DebugLog((" [1] tvb_strsize(tvb, offset) == %u\n", len));
468 if (tvb_get_guint8(tvb, offset) == MM_QUOTE)
469 *strval = (char *)tvb_memcpy(tvb, ep_alloc(len-1), offset+1, len-1);
471 *strval = (char *)tvb_memcpy(tvb, ep_alloc(len), offset, len);
472 DebugLog((" [3] Return(len) == %u\n", len));
477 * Decodes a Value-length from the protocol data.
478 * Value-length = Short-length | (Length-quote Length)
479 * Short-length = <Any octet 0-30>
480 * Length-quote = <Octet 31>
481 * Length = Uintvar-integer
483 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
485 * \param tvb The buffer with PDU-data
486 * \param offset Offset within that buffer
487 * \param byte_count Returns the length in bytes of
488 * the "Value-length" field.
490 * \return The actual value of "Value-length"
493 get_value_length(tvbuff_t *tvb, guint offset, guint *byte_count)
497 field = tvb_get_guint8(tvb, offset++);
500 else { /* Must be 31 so, Uintvar follows */
501 field = tvb_get_guintvar(tvb, offset, byte_count);
508 * Decodes an Encoded-string-value from the protocol data
509 * Encoded-string-value = Text-string | Value-length Char-set Text-string
511 * \param tvb The buffer with PDU-data
512 * \param offset Offset within that buffer
513 * \param strval Pointer to variable into which to put pointer to
514 * buffer allocated to hold the text; must be freed
515 * when no longer used
517 * \return The length in bytes of the entire field
520 get_encoded_strval(tvbuff_t *tvb, guint offset, char **strval)
526 field = tvb_get_guint8(tvb, offset);
529 length = get_value_length(tvb, offset, &count);
533 /* \todo Something with "Char-set", skip for now */
534 *strval = (char *)tvb_get_ephemeral_string(tvb, offset + count + 1, length - 1);
536 return count + length;
538 return get_text_string(tvb, offset, strval);
542 * Decodes a Long-integer from the protocol data
543 * Long-integer = Short-length Multi-octet-integer
544 * Short-length = <Any octet 0-30>
545 * Multi-octet-integer = 1*30OCTET
547 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
549 * \param tvb The buffer with PDU-data
550 * \param offset Offset within that buffer
551 * \param byte_count Returns the length in bytes of the field
553 * \return The value of the Long-integer
555 * \note A maximum of 4-byte integers will be handled.
558 get_long_integer(tvbuff_t *tvb, guint offset, guint *byte_count)
562 *byte_count = tvb_get_guint8(tvb, offset++);
563 switch (*byte_count) {
565 val = tvb_get_guint8(tvb, offset);
568 val = tvb_get_ntohs(tvb, offset);
571 val = tvb_get_ntoh24(tvb, offset);
574 val = tvb_get_ntohl(tvb, offset);
585 * Decodes an Integer-value from the protocol data
586 * Integer-value = Short-integer | Long-integer
587 * Short-integer = OCTET
588 * Long-integer = Short-length Multi-octet-integer
589 * Short-length = <Any octet 0-30>
590 * Multi-octet-integer = 1*30OCTET
592 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
594 * \param tvb The buffer with PDU-data
595 * \param offset Offset within that buffer
596 * \param byte_count Returns the length in bytes of the field
598 * \return The value of the Long-integer
600 * \note A maximum of 4-byte integers will be handled.
603 get_integer_value(tvbuff_t *tvb, guint offset, guint *byte_count)
608 peek = tvb_get_guint8(tvb, offset++);
617 val = tvb_get_guint8(tvb, offset);
620 val = tvb_get_ntohs(tvb, offset);
623 val = tvb_get_ntoh24(tvb, offset);
626 val = tvb_get_ntohl(tvb, offset);
637 /* Code to actually dissect the packets */
639 dissect_mmse_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
643 DebugLog(("dissect_mmse_heur()\n"));
645 * Check if data makes sense for it to be dissected as MMSE: Message-type
646 * field must make sense and followed by either Transaction-Id
647 * or MMS-Version header
649 if (tvb_get_guint8(tvb, 0) != MM_MTYPE_HDR)
651 pdut = tvb_get_guint8(tvb, 1);
652 if (match_strval(pdut, vals_message_type) == NULL)
654 if ((tvb_get_guint8(tvb, 2) != MM_TID_HDR) &&
655 (tvb_get_guint8(tvb, 2) != MM_VERSION_HDR))
657 dissect_mmse_standalone(tvb, pinfo, tree);
662 dissect_mmse_standalone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
665 const char *message_type;
667 DebugLog(("dissect_mmse_standalone() - START (Packet %u)\n",
670 pdut = tvb_get_guint8(tvb, 1);
671 message_type = val_to_str(pdut, vals_message_type, "Unknown type %u");
673 /* Make entries in Protocol column and Info column on summary display */
674 if (check_col(pinfo->cinfo, COL_PROTOCOL))
675 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMSE");
677 if (check_col(pinfo->cinfo, COL_INFO)) {
678 col_clear(pinfo->cinfo, COL_INFO);
679 col_add_fstr(pinfo->cinfo, COL_INFO, "MMS %s", message_type);
682 dissect_mmse(tvb, pinfo, tree, pdut, message_type);
686 dissect_mmse_encapsulated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
689 const char *message_type;
691 DebugLog(("dissect_mmse_encapsulated() - START (Packet %u)\n",
694 pdut = tvb_get_guint8(tvb, 1);
695 message_type = val_to_str(pdut, vals_message_type, "Unknown type %u");
697 /* Make entries in Info column on summary display */
698 if (check_col(pinfo->cinfo, COL_INFO)) {
699 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(MMS %s)",
703 dissect_mmse(tvb, pinfo, tree, pdut, message_type);
707 dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 pdut,
708 const char *message_type)
715 guint8 version = 0x80; /* Default to MMSE 1.0 */
717 /* Set up structures needed to add the protocol subtree and manage it */
718 proto_item *ti = NULL;
719 proto_tree *mmse_tree = NULL;
721 DebugLog(("dissect_mmse() - START (Packet %u)\n", pinfo->fd->num));
723 /* If tree == NULL then we are only interested in protocol dissection
724 * up to reassembly and handoff to subdissectors if applicable; the
725 * columns must be set appropriately too.
726 * If tree != NULL then we also want to display the protocol tree
729 * In the interest of speed, skip protocol tree item generation
733 DebugLog(("tree != NULL\n"));
735 ti = proto_tree_add_item(tree, proto_mmse, tvb, 0, -1, FALSE);
736 proto_item_append_text(ti, ", Type: %s", message_type);
737 /* create display subtree for the protocol */
738 mmse_tree = proto_item_add_subtree(ti, ett_mmse);
740 /* Report PDU-type */
741 proto_tree_add_uint(mmse_tree, hf_mmse_message_type, tvb, 0, 2, pdut);
744 offset = 2; /* Skip Message-Type */
747 * Cycle through MMS-headers
749 * NOTE - some PDUs may convey content which can be handed off
752 if (tree || pdu_has_content(pdut)) {
753 while ((offset < tvb_reported_length(tvb)) &&
754 (field = tvb_get_guint8(tvb, offset++)) != MM_CTYPE_HDR)
756 DebugLog(("\tField = 0x%02X (offset = %u): %s\n",
758 val_to_str(field, vals_mm_header_names,
759 "Unknown MMS header 0x%02X")));
762 case MM_TID_HDR: /* Text-string */
763 length = get_text_string(tvb, offset, &strval);
765 proto_tree_add_string(mmse_tree, hf_mmse_transaction_id,
766 tvb, offset - 1, length + 1,strval);
770 case MM_VERSION_HDR: /* nibble-Major/nibble-minor*/
771 version = tvb_get_guint8(tvb, offset++);
775 major = (version & 0x70) >> 4;
776 minor = version & 0x0F;
778 strval = g_strdup_printf("%u", major);
780 strval = g_strdup_printf("%u.%u", major, minor);
781 proto_tree_add_string(mmse_tree, hf_mmse_mms_version,
782 tvb, offset - 2, 2, strval);
786 case MM_BCC_HDR: /* Encoded-string-value */
787 length = get_encoded_strval(tvb, offset, &strval);
789 proto_tree_add_string(mmse_tree, hf_mmse_bcc, tvb,
790 offset - 1, length + 1, strval);
794 case MM_CC_HDR: /* Encoded-string-value */
795 length = get_encoded_strval(tvb, offset, &strval);
797 proto_tree_add_string(mmse_tree, hf_mmse_cc, tvb,
798 offset - 1, length + 1, strval);
802 case MM_CLOCATION_HDR: /* Uri-value */
803 if (pdut == PDU_M_MBOX_DELETE_CONF) {
804 /* General form with length */
805 length = tvb_get_guint8(tvb, offset);
806 if (length == 0x1F) {
807 guint length_len = 0;
808 length = tvb_get_guintvar(tvb, offset + 1,
810 length += 1 + length_len;
815 tvb_ensure_bytes_exist(tvb, offset - 1, length + 1);
816 proto_tree_add_string(mmse_tree,
817 hf_mmse_content_location,
818 tvb, offset - 1, length + 1,
819 "<Undecoded value for m-mbox-delete-conf>");
822 length = get_text_string(tvb, offset, &strval);
824 proto_tree_add_string(mmse_tree,
825 hf_mmse_content_location,
826 tvb, offset - 1, length + 1, strval);
831 case MM_DATE_HDR: /* Long-integer */
836 tval = get_long_integer(tvb, offset, &count);
840 tvb_ensure_bytes_exist(tvb, offset - 1, count + 1);
841 proto_tree_add_time(mmse_tree, hf_mmse_date, tvb,
842 offset - 1, count + 1, &tmptime);
847 case MM_DREPORT_HDR: /* Yes|No */
848 field = tvb_get_guint8(tvb, offset++);
850 proto_tree_add_uint(mmse_tree,
851 hf_mmse_delivery_report,
852 tvb, offset - 2, 2, field);
857 * Value-length(Absolute-token Date-value|
858 * Relative-token Delta-seconds-value)
860 length = get_value_length(tvb, offset, &count);
861 field = tvb_get_guint8(tvb, offset + count);
867 tval = get_long_integer(tvb, offset + count + 1, &cnt);
871 tvb_ensure_bytes_exist(tvb, offset - 1, length + count + 1);
873 proto_tree_add_time(mmse_tree,
874 hf_mmse_delivery_time_abs,
876 length + count + 1, &tmptime);
878 proto_tree_add_time(mmse_tree,
879 hf_mmse_delivery_time_rel,
881 length + count + 1, &tmptime);
883 offset += length + count;
887 * Value-length(Absolute-token Date-value|
888 * Relative-token Delta-seconds-value)
890 length = get_value_length(tvb, offset, &count);
891 field = tvb_get_guint8(tvb, offset + count);
897 tval = get_long_integer(tvb, offset + count + 1, &cnt);
901 tvb_ensure_bytes_exist(tvb, offset - 1, length + count + 1);
903 proto_tree_add_time(mmse_tree, hf_mmse_expiry_abs,
905 length + count + 1, &tmptime);
907 proto_tree_add_time(mmse_tree, hf_mmse_expiry_rel,
909 length + count + 1, &tmptime);
911 offset += length + count;
915 * Value-length(Address-present-token Encoded-string-value
916 * |Insert-address-token)
918 length = get_value_length(tvb, offset, &count);
920 field = tvb_get_guint8(tvb, offset + count);
921 tvb_ensure_bytes_exist(tvb, offset - 1, length + count + 1);
923 proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
924 offset-1, length + count + 1,
927 (void) get_encoded_strval(tvb, offset + count + 1,
929 proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
930 offset-1, length + count + 1, strval);
933 offset += length + count;
937 * Class-identifier|Text-string
939 field = tvb_get_guint8(tvb, offset);
943 proto_tree_add_uint(mmse_tree,
944 hf_mmse_message_class_id,
945 tvb, offset - 2, 2, field);
948 length = get_text_string(tvb, offset, &strval);
950 proto_tree_add_string(mmse_tree,
951 hf_mmse_message_class_str,
952 tvb, offset - 1, length + 1,
958 case MM_MID_HDR: /* Text-string */
959 length = get_text_string(tvb, offset, &strval);
961 proto_tree_add_string(mmse_tree, hf_mmse_message_id,
962 tvb, offset - 1, length + 1, strval);
966 case MM_MSIZE_HDR: /* Long-integer */
967 length = get_long_integer(tvb, offset, &count);
969 proto_tree_add_uint(mmse_tree, hf_mmse_message_size,
970 tvb, offset - 1, count + 1, length);
974 case MM_PRIORITY_HDR: /* Low|Normal|High */
975 field = tvb_get_guint8(tvb, offset++);
977 proto_tree_add_uint(mmse_tree, hf_mmse_priority, tvb,
978 offset - 2, 2, field);
981 case MM_RREPLY_HDR: /* Yes|No */
982 field = tvb_get_guint8(tvb, offset++);
984 if (version == 0x80) { /* MMSE 1.0 */
985 proto_tree_add_uint(mmse_tree, hf_mmse_read_reply,
986 tvb, offset - 2, 2, field);
988 proto_tree_add_uint(mmse_tree, hf_mmse_read_report,
989 tvb, offset - 2, 2, field);
993 case MM_RALLOWED_HDR: /* Yes|No */
994 field = tvb_get_guint8(tvb, offset++);
996 proto_tree_add_uint(mmse_tree, hf_mmse_report_allowed,
997 tvb, offset - 2, 2, field);
1000 case MM_RSTATUS_HDR:
1001 field = tvb_get_guint8(tvb, offset++);
1003 proto_tree_add_uint(mmse_tree, hf_mmse_response_status,
1004 tvb, offset - 2, 2, field);
1007 case MM_RTEXT_HDR: /* Encoded-string-value */
1008 if (pdut == PDU_M_MBOX_DELETE_CONF) {
1009 /* General form with length */
1010 length = tvb_get_guint8(tvb, offset);
1011 if (length == 0x1F) {
1012 guint length_len = 0;
1013 length = tvb_get_guintvar(tvb, offset + 1,
1015 length += 1 + length_len;
1020 proto_tree_add_string(mmse_tree,
1021 hf_mmse_content_location,
1022 tvb, offset - 1, length + 1,
1023 "<Undecoded value for m-mbox-delete-conf>");
1026 length = get_encoded_strval(tvb, offset, &strval);
1028 proto_tree_add_string(mmse_tree,
1029 hf_mmse_response_text, tvb, offset - 1,
1030 length + 1, strval);
1035 case MM_SVISIBILITY_HDR: /* Hide|Show */
1036 field = tvb_get_guint8(tvb, offset++);
1038 proto_tree_add_uint(mmse_tree,hf_mmse_sender_visibility,
1039 tvb, offset - 2, 2, field);
1043 field = tvb_get_guint8(tvb, offset++);
1045 proto_tree_add_uint(mmse_tree, hf_mmse_status, tvb,
1046 offset - 2, 2, field);
1049 case MM_SUBJECT_HDR: /* Encoded-string-value */
1050 length = get_encoded_strval(tvb, offset, &strval);
1052 proto_tree_add_string(mmse_tree, hf_mmse_subject, tvb,
1053 offset - 1, length + 1, strval);
1057 case MM_TO_HDR: /* Encoded-string-value */
1058 length = get_encoded_strval(tvb, offset, &strval);
1060 proto_tree_add_string(mmse_tree, hf_mmse_to, tvb,
1061 offset - 1, length + 1, strval);
1067 * MMS Encapsulation 1.1
1069 case MM_RETRIEVE_STATUS_HDR: /* Well-known-value */
1070 field = tvb_get_guint8(tvb, offset++);
1072 proto_tree_add_uint(mmse_tree, hf_mmse_retrieve_status,
1073 tvb, offset - 2, 2, field);
1076 case MM_RETRIEVE_TEXT_HDR:
1077 if (pdut == PDU_M_MBOX_DELETE_CONF) {
1078 /* General form with length */
1079 length = tvb_get_guint8(tvb, offset);
1080 if (length == 0x1F) {
1081 guint length_len = 0;
1082 length = tvb_get_guintvar(tvb, offset + 1,
1084 length += 1 + length_len;
1089 proto_tree_add_string(mmse_tree,
1090 hf_mmse_content_location,
1091 tvb, offset - 1, length + 1,
1092 "<Undecoded value for m-mbox-delete-conf>");
1095 /* Encoded-string-value */
1096 length = get_encoded_strval(tvb, offset, &strval);
1098 proto_tree_add_string(mmse_tree,
1099 hf_mmse_retrieve_text, tvb, offset - 1,
1100 length + 1, strval);
1105 case MM_READ_STATUS_HDR: /* Well-known-value */
1106 field = tvb_get_guint8(tvb, offset++);
1108 proto_tree_add_uint(mmse_tree, hf_mmse_read_status,
1109 tvb, offset - 2, 2, field);
1112 case MM_REPLY_CHARGING_HDR: /* Well-known-value */
1113 field = tvb_get_guint8(tvb, offset++);
1115 proto_tree_add_uint(mmse_tree, hf_mmse_reply_charging,
1116 tvb, offset - 2, 2, field);
1119 case MM_REPLY_CHARGING_DEADLINE_HDR: /* Well-known-value */
1121 * Value-length(Absolute-token Date-value|
1122 * Relative-token Delta-seconds-value)
1124 length = get_value_length(tvb, offset, &count);
1125 field = tvb_get_guint8(tvb, offset + count);
1131 tval = get_long_integer(tvb, offset + count + 1, &cnt);
1132 tmptime.secs = tval;
1135 tvb_ensure_bytes_exist(tvb, offset - 1, length + count + 1);
1137 proto_tree_add_time(mmse_tree, hf_mmse_reply_charging_deadline_abs,
1139 length + count + 1, &tmptime);
1141 proto_tree_add_time(mmse_tree, hf_mmse_reply_charging_deadline_rel,
1143 length + count + 1, &tmptime);
1145 offset += length + count;
1147 case MM_REPLY_CHARGING_ID_HDR: /* Text-string */
1148 length = get_text_string(tvb, offset, &strval);
1150 proto_tree_add_string(mmse_tree,
1151 hf_mmse_reply_charging_id,
1152 tvb, offset - 1, length + 1, strval);
1156 case MM_REPLY_CHARGING_SIZE_HDR: /* Long-integer */
1157 length = get_long_integer(tvb, offset, &count);
1159 proto_tree_add_uint(mmse_tree,
1160 hf_mmse_reply_charging_size,
1161 tvb, offset - 1, count + 1, length);
1165 case MM_PREV_SENT_BY_HDR:
1166 /* Value-length Integer-value Encoded-string-value */
1167 length = get_value_length(tvb, offset, &count);
1169 guint32 fwd_count, count1, count2;
1170 proto_tree *subtree = NULL;
1171 proto_item *ti = NULL;
1172 /* 1. Forwarded-count-value := Integer-value */
1173 fwd_count = get_integer_value(tvb, offset + count,
1175 /* 2. Encoded-string-value */
1176 count2 = get_encoded_strval(tvb,
1177 offset + count + count1, &strval);
1178 /* Now render the fields */
1179 ti = proto_tree_add_string_format(mmse_tree,
1180 hf_mmse_prev_sent_by,
1181 tvb, offset - 1, 1 + count + length,
1182 strval, "%s (Forwarded-count=%u)",
1183 format_text(strval, strlen(strval)),
1185 subtree = proto_item_add_subtree(ti,
1186 ett_mmse_hdr_details);
1187 proto_tree_add_uint(subtree,
1188 hf_mmse_prev_sent_by_fwd_count,
1189 tvb, offset + count, count1, fwd_count);
1190 proto_tree_add_string(subtree,
1191 hf_mmse_prev_sent_by_address,
1192 tvb, offset + count + count1, count2, strval);
1194 offset += length + count;
1196 case MM_PREV_SENT_DATE_HDR:
1197 /* Value-Length Forwarded-count-value Date-value */
1198 length = get_value_length(tvb, offset, &count);
1200 guint32 fwd_count, count1, count2;
1203 proto_tree *subtree = NULL;
1204 proto_item *ti = NULL;
1205 /* 1. Forwarded-count-value := Integer-value */
1206 fwd_count = get_integer_value(tvb, offset + count,
1208 /* 2. Date-value := Long-integer */
1209 tval = get_long_integer(tvb, offset + count + count1,
1211 tmptime.secs = tval;
1213 strval = abs_time_to_str(&tmptime);
1214 /* Now render the fields */
1215 tvb_ensure_bytes_exist(tvb, offset - 1, length + count + 1);
1216 ti = proto_tree_add_string_format(mmse_tree,
1217 hf_mmse_prev_sent_date,
1218 tvb, offset - 1, 1 + count + length,
1219 strval, "%s (Forwarded-count=%u)",
1220 format_text(strval, strlen(strval)),
1222 subtree = proto_item_add_subtree(ti,
1223 ett_mmse_hdr_details);
1224 proto_tree_add_uint(subtree,
1225 hf_mmse_prev_sent_date_fwd_count,
1226 tvb, offset + count, count1, fwd_count);
1227 proto_tree_add_string(subtree,
1228 hf_mmse_prev_sent_date_date,
1229 tvb, offset + count + count1, count2, strval);
1231 offset += length + count;
1234 /* MMS Encapsulation 1.2 */
1237 if (field & 0x80) { /* Well-known WSP header encoding */
1238 guint8 peek = tvb_get_guint8(tvb, offset);
1239 const char *hdr_name = val_to_str(field, vals_mm_header_names,
1240 "Unknown field (0x%02x)");
1241 DebugLog(("\t\tUndecoded well-known header: %s\n",
1244 if (peek & 0x80) { /* Well-known value */
1247 proto_tree_add_text(mmse_tree, tvb, offset - 1,
1249 "%s: <Well-known value 0x%02x>"
1253 } else if ((peek == 0) || (peek >= 0x20)) { /* Text */
1254 length = get_text_string(tvb, offset, &strval);
1256 proto_tree_add_text(mmse_tree, tvb, offset - 1,
1257 length + 1, "%s: %s (Not decoded)",
1259 format_text(strval, strlen(strval)));
1261 } else { /* General form with length */
1262 if (peek == 0x1F) { /* Value length in guintvar */
1263 guint length_len = 0;
1264 length = 1 + tvb_get_guintvar(tvb, offset + 1,
1266 length += length_len;
1267 } else { /* Value length in octet */
1268 length = 1 + tvb_get_guint8(tvb, offset);
1271 proto_tree_add_text(mmse_tree, tvb, offset - 1,
1273 "<Value in general form> (not decoded)",
1278 } else { /* Literal WSP header encoding */
1283 length = get_text_string(tvb, offset, &strval);
1284 DebugLog(("\t\tUndecoded literal header: %s\n",
1286 length2= get_text_string(tvb, offset+length, &strval2);
1289 proto_tree_add_string_format(mmse_tree,
1290 hf_mmse_ffheader, tvb, offset,
1292 (const char *) tvb_get_ptr(
1293 tvb, offset, length + length2),
1295 format_text(strval, strlen(strval)),
1296 format_text(strval2, strlen(strval2)));
1298 offset += length + length2;
1302 DebugLog(("\tEnd(case)\n"));
1304 DebugLog(("\tEnd(switch)\n"));
1305 if (field == MM_CTYPE_HDR) {
1307 * Eeehh, we're now actually back to good old WSP content-type
1308 * encoding. Let's steal that from the WSP-dissector.
1312 const char *type_str;
1314 DebugLog(("Content-Type: [from WSP dissector]\n"));
1315 DebugLog(("Calling add_content_type() in WSP dissector\n"));
1316 offset = add_content_type(mmse_tree, tvb, offset, &type, &type_str);
1317 DebugLog(("Generating new TVB subset (offset = %u)\n", offset));
1318 tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
1319 DebugLog(("Add POST data\n"));
1320 add_post_data(mmse_tree, tmp_tvb, type, type_str, pinfo);
1321 DebugLog(("Done!\n"));
1324 DebugLog(("tree == NULL and PDU has no potential content\n"));
1327 /* If this protocol has a sub-dissector call it here, see section 1.8 */
1328 DebugLog(("dissect_mmse() - END\n"));
1332 /* Register the protocol with Wireshark */
1334 /* this format is required because a script is used to build the C function
1335 * that calls all the protocol registration.
1338 proto_register_mmse(void)
1340 /* Setup list of header fields See Section 1.6.1 for details */
1341 static hf_register_info hf[] = {
1342 { &hf_mmse_message_type,
1343 { "X-Mms-Message-Type", "mmse.message_type",
1344 FT_UINT8, BASE_HEX, VALS(vals_message_type), 0x00,
1345 "Specifies the transaction type. Effectively defines PDU.",
1349 { &hf_mmse_transaction_id,
1350 { "X-Mms-Transaction-ID", "mmse.transaction_id",
1351 FT_STRING, BASE_NONE, NULL, 0x00,
1352 "A unique identifier for this transaction. "
1353 "Identifies request and corresponding response only.",
1357 { &hf_mmse_mms_version,
1358 { "X-Mms-MMS-Version", "mmse.mms_version",
1359 FT_STRING, BASE_NONE, NULL, 0x00,
1360 "Version of the protocol used.",
1365 { "Bcc", "mmse.bcc",
1366 FT_STRING, BASE_NONE, NULL, 0x00,
1367 "Blind carbon copy.",
1373 FT_STRING, BASE_NONE, NULL, 0x00,
1378 { &hf_mmse_content_location,
1379 { "X-Mms-Content-Location", "mmse.content_location",
1380 FT_STRING, BASE_NONE, NULL, 0x00,
1381 "Defines the location of the message.",
1386 { "Date", "mmse.date",
1387 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1388 "Arrival timestamp of the message or sending timestamp.",
1392 { &hf_mmse_delivery_report,
1393 { "X-Mms-Delivery-Report", "mmse.delivery_report",
1394 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1395 "Whether a report of message delivery is wanted or not.",
1399 { &hf_mmse_delivery_time_abs,
1400 { "X-Mms-Delivery-Time", "mmse.delivery_time.abs",
1401 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1402 "The time at which message delivery is desired.",
1406 { &hf_mmse_delivery_time_rel,
1407 { "X-Mms-Delivery-Time", "mmse.delivery_time.rel",
1408 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1409 "The desired message delivery delay.",
1413 { &hf_mmse_expiry_abs,
1414 { "X-Mms-Expiry", "mmse.expiry.abs",
1415 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1416 "Time when message expires and need not be delivered anymore.",
1420 { &hf_mmse_expiry_rel,
1421 { "X-Mms-Expiry", "mmse.expiry.rel",
1422 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1423 "Delay before message expires and need not be delivered anymore.",
1428 { "From", "mmse.from",
1429 FT_STRING, BASE_NONE, NULL, 0x00,
1430 "Address of the message sender.",
1434 { &hf_mmse_message_class_id,
1435 { "X-Mms-Message-Class", "mmse.message_class.id",
1436 FT_UINT8, BASE_HEX, VALS(vals_message_class), 0x00,
1437 "Of what category is the message.",
1441 { &hf_mmse_message_class_str,
1442 { "X-Mms-Message-Class", "mmse.message_class.str",
1443 FT_STRING, BASE_NONE, NULL, 0x00,
1444 "Of what category is the message.",
1448 { &hf_mmse_message_id,
1449 { "Message-Id", "mmse.message_id",
1450 FT_STRING, BASE_NONE, NULL, 0x00,
1451 "Unique identification of the message.",
1455 { &hf_mmse_message_size,
1456 { "X-Mms-Message-Size", "mmse.message_size",
1457 FT_UINT32, BASE_DEC, NULL, 0x00,
1458 "The size of the message in octets.",
1462 { &hf_mmse_priority,
1463 { "X-Mms-Priority", "mmse.priority",
1464 FT_UINT8, BASE_HEX, VALS(vals_priority), 0x00,
1465 "Priority of the message.",
1469 { &hf_mmse_read_reply,
1470 { "X-Mms-Read-Reply", "mmse.read_reply",
1471 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1472 "Whether a read report from every recipient is wanted.",
1476 { &hf_mmse_read_report,
1477 { "X-Mms-Read-Report", "mmse.read_report",
1478 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1479 "Whether a read report from every recipient is wanted.",
1483 { &hf_mmse_report_allowed,
1484 { "X-Mms-Report-Allowed", "mmse.report_allowed",
1485 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1486 "Sending of delivery report allowed or not.",
1490 { &hf_mmse_response_status,
1491 { "Response-Status", "mmse.response_status",
1492 FT_UINT8, BASE_HEX, VALS(vals_response_status), 0x00,
1493 "MMS-specific result of a message submission or retrieval.",
1497 { &hf_mmse_response_text,
1498 { "Response-Text", "mmse.response_text",
1499 FT_STRING, BASE_NONE, NULL, 0x00,
1500 "Additional information on MMS-specific result.",
1504 { &hf_mmse_sender_visibility,
1505 { "Sender-Visibility", "mmse.sender_visibility",
1506 FT_UINT8, BASE_HEX, VALS(vals_sender_visibility), 0x00,
1507 "Disclose sender identity to receiver or not.",
1512 { "Status", "mmse.status",
1513 FT_UINT8, BASE_HEX, VALS(vals_message_status), 0x00,
1514 "Current status of the message.",
1519 { "Subject", "mmse.subject",
1520 FT_STRING, BASE_NONE, NULL, 0x00,
1521 "Subject of the message.",
1527 FT_STRING, BASE_NONE, NULL, 0x00,
1528 "Recipient(s) of the message.",
1532 { &hf_mmse_content_type,
1533 { "Data", "mmse.content_type",
1534 FT_NONE, BASE_NONE, NULL, 0x00,
1535 "Media content of the message.",
1539 { &hf_mmse_ffheader,
1540 { "Free format (not encoded) header", "mmse.ffheader",
1541 FT_STRING, BASE_NONE, NULL, 0x00,
1542 "Application header without corresponding encoding.",
1547 { &hf_mmse_retrieve_status,
1548 { "X-Mms-Retrieve-Status", "mmse.retrieve_status",
1549 FT_UINT8, BASE_HEX, VALS(vals_retrieve_status), 0x00,
1550 "MMS-specific result of a message retrieval.",
1554 { &hf_mmse_retrieve_text,
1555 { "X-Mms-Retrieve-Text", "mmse.retrieve_text",
1556 FT_STRING, BASE_NONE, NULL, 0x00,
1557 "Status text of a MMS message retrieval.",
1561 { &hf_mmse_read_status,
1562 { "X-Mms-Read-Status", "mmse.read_status",
1563 FT_UINT8, BASE_HEX, VALS(vals_read_status), 0x00,
1564 "MMS-specific message read status.",
1568 { &hf_mmse_reply_charging,
1569 { "X-Mms-Reply-Charging", "mmse.reply_charging",
1570 FT_UINT8, BASE_HEX, VALS(vals_reply_charging), 0x00,
1571 "MMS-specific message reply charging method.",
1575 { &hf_mmse_reply_charging_deadline_abs,
1576 { "X-Mms-Reply-Charging-Deadline", "mmse.reply_charging_deadline.abs",
1577 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1578 "The latest time of the recipient(s) to submit the Reply MM.",
1582 { &hf_mmse_reply_charging_deadline_rel,
1583 { "X-Mms-Reply-Charging-Deadline", "mmse.reply_charging_deadline.rel",
1584 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1585 "The latest time of the recipient(s) to submit the Reply MM.",
1589 { &hf_mmse_reply_charging_id,
1590 { "X-Mms-Reply-Charging-Id", "mmse.reply_charging_id",
1591 FT_STRING, BASE_NONE, NULL, 0x00,
1592 "Unique reply charging identification of the message.",
1596 { &hf_mmse_reply_charging_size,
1597 { "X-Mms-Reply-Charging-Size", "mmse.reply_charging_size",
1598 FT_UINT32, BASE_DEC, NULL, 0x00,
1599 "The size of the reply charging in octets.",
1603 { &hf_mmse_prev_sent_by,
1604 { "X-Mms-Previously-Sent-By", "mmse.previously_sent_by",
1605 FT_STRING, BASE_NONE, NULL, 0x00,
1606 "Indicates that the MM has been previously sent by this user.",
1610 { &hf_mmse_prev_sent_by_fwd_count,
1611 { "Forward Count", "mmse.previously_sent_by.forward_count",
1612 FT_UINT32, BASE_DEC, NULL, 0x00,
1613 "Forward count of the previously sent MM.",
1617 { &hf_mmse_prev_sent_by_address,
1618 { "Address", "mmse.previously_sent_by.address",
1619 FT_STRING, BASE_NONE, NULL, 0x00,
1620 "Indicates from whom the MM has been previously sent.",
1624 { &hf_mmse_prev_sent_date,
1625 { "X-Mms-Previously-Sent-Date", "mmse.previously_sent_date",
1626 FT_STRING, BASE_NONE, NULL, 0x00,
1627 "Indicates the date that the MM has been previously sent.",
1631 { &hf_mmse_prev_sent_date_fwd_count,
1632 { "Forward Count", "mmse.previously_sent_date.forward_count",
1633 FT_UINT32, BASE_DEC, NULL, 0x00,
1634 "Forward count of the previously sent MM.",
1638 { &hf_mmse_prev_sent_date_date,
1639 { "Date", "mmse.previously_sent_date.date",
1640 FT_STRING, BASE_NONE, NULL, 0x00,
1641 "Time when the MM has been previously sent.",
1649 /* Setup protocol subtree array */
1650 static gint *ett[] = {
1652 &ett_mmse_hdr_details,
1655 /* Register the protocol name and description */
1656 proto_mmse = proto_register_protocol("MMS Message Encapsulation",
1659 /* Required function calls to register header fields and subtrees used */
1660 proto_register_field_array(proto_mmse, hf, array_length(hf));
1661 proto_register_subtree_array(ett, array_length(ett));
1664 /* If this dissector uses sub-dissector registration add registration routine.
1665 * This format is required because a script is used to find these routines and
1666 * create the code that calls these routines.
1669 proto_reg_handoff_mmse(void)
1671 dissector_handle_t mmse_standalone_handle;
1672 dissector_handle_t mmse_encapsulated_handle;
1674 heur_dissector_add("wsp", dissect_mmse_heur, proto_mmse);
1675 mmse_standalone_handle = create_dissector_handle(
1676 dissect_mmse_standalone, proto_mmse);
1677 mmse_encapsulated_handle = create_dissector_handle(
1678 dissect_mmse_encapsulated, proto_mmse);
1679 /* As the media types for WSP and HTTP are the same, the WSP dissector
1680 * uses the same string dissector table as the HTTP protocol. */
1681 dissector_add_string("media_type",
1682 "application/vnd.wap.mms-message", mmse_standalone_handle);
1683 dissector_add_string("multipart_media_type",
1684 "application/vnd.wap.mms-message", mmse_encapsulated_handle);