Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-mmse.c
blobf521f2b9bba315e2d6abe3dc897e462e2922acc6
1 /* packet-mmse.c
2 * Routines for MMS Message Encapsulation dissection
3 * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
4 * Copyright 2004, Olivier Biot
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 * ----------
13 * Dissector of an encoded Multimedia message PDU, as defined by the WAPForum
14 * (http://www.wapforum.org) in "WAP-209-MMSEncapsulation-20020105-a".
15 * Subsequent releases of MMS are in control of the Open Mobile Alliance (OMA):
16 * Dissection of MMS 1.1 as in OMA-MMS-ENC-v1.1.
17 * Dissection of MMS 1.2 as in OMA-MMS-ENC-v1.2 (not finished yet).
20 /* This file has been edited with 8-space tabs and 4-space indentation */
22 #include "config.h"
25 #include <epan/packet.h>
26 #include <epan/expert.h>
27 #include <epan/to_str.h>
28 #include <epan/strutil.h>
29 #include <epan/iana_charsets.h>
30 #include "packet-wap.h"
31 #include "packet-wsp.h"
33 void proto_register_mmse(void);
34 void proto_reg_handoff_mmse(void);
36 static dissector_handle_t mmse_standalone_handle;
37 static dissector_handle_t mmse_encapsulated_handle;
39 #define MM_QUOTE 0x7F /* Quoted string */
41 #define MMS_CONTENT_TYPE 0x3E /* WINA-value for mms-message */
43 /* General-purpose debug logger.
44 * Requires double parentheses because of variable arguments of printf().
46 * Enable debug logging for MMSE by defining AM_CFLAGS
47 * so that it contains "-DDEBUG_mmse"
49 #ifdef DEBUG_mmse
50 #define DebugLog(x) \
51 g_print("%s:%u: ", __FILE__, __LINE__); \
52 g_print x
53 #else
54 #define DebugLog(x) ;
55 #endif
58 * Forward declarations
60 static int dissect_mmse_standalone(tvbuff_t *, packet_info *, proto_tree *, void*);
61 static void dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
62 uint8_t pdut, const char *message_type);
65 * Header field values
67 /* MMS 1.0 */
68 #define MM_BCC_HDR 0x81 /* Bcc */
69 #define MM_CC_HDR 0x82 /* Cc */
70 #define MM_CLOCATION_HDR 0x83 /* X-Mms-Content-Location */
71 #define MM_CTYPE_HDR 0x84 /* Content-Type */
72 #define MM_DATE_HDR 0x85 /* Date */
73 #define MM_DREPORT_HDR 0x86 /* X-Mms-Delivery-Report */
74 #define MM_DTIME_HDR 0x87 /* X-Mms-Delivery-Time */
75 #define MM_EXPIRY_HDR 0x88 /* X-Mms-Expiry */
76 #define MM_FROM_HDR 0x89 /* From */
77 #define MM_MCLASS_HDR 0x8A /* X-Mms-Message-Class */
78 #define MM_MID_HDR 0x8B /* Message-ID */
79 #define MM_MTYPE_HDR 0x8C /* X-Mms-Message-Type */
80 #define MM_VERSION_HDR 0x8D /* X-Mms-MMS-Version */
81 #define MM_MSIZE_HDR 0x8E /* X-Mms-Message-Size */
82 #define MM_PRIORITY_HDR 0x8F /* X-Mms-Priority */
83 #define MM_RREPLY_HDR 0x90 /* X-Mms-Read-Reply */
84 #define MM_RALLOWED_HDR 0x91 /* X-Mms-Report-Allowed */
85 #define MM_RSTATUS_HDR 0x92 /* X-Mms-Response-Status */
86 #define MM_RTEXT_HDR 0x93 /* X-Mms-Response-Text */
87 #define MM_SVISIBILITY_HDR 0x94 /* X-Mms-Sender-Visibility */
88 #define MM_STATUS_HDR 0x95 /* X-Mms-Status */
89 #define MM_SUBJECT_HDR 0x96 /* Subject */
90 #define MM_TO_HDR 0x97 /* To */
91 #define MM_TID_HDR 0x98 /* X-Mms-Transaction-Id */
92 /* MMS 1.1 */
93 #define MM_RETRIEVE_STATUS_HDR 0x99 /* X-Mms-Retrieve-Status */
94 #define MM_RETRIEVE_TEXT_HDR 0x9A /* X-Mms-Retrieve-Text */
95 #define MM_READ_STATUS_HDR 0x9B /* X-Mms-Read-Status */
96 #define MM_REPLY_CHARGING_HDR 0x9C /* X-Mms-Reply-Charging */
97 #define MM_REPLY_CHARGING_DEADLINE_HDR \
98 0x9D /* X-Mms-Reply-Charging-Deadline*/
99 #define MM_REPLY_CHARGING_ID_HDR \
100 0x9E /* X-Mms-Reply-Charging-ID */
101 #define MM_REPLY_CHARGING_SIZE_HDR \
102 0x9F /* X-Mms-Reply-Charging-Size */
103 #define MM_PREV_SENT_BY_HDR 0xA0 /* X-Mms-Previously-Sent-By */
104 #define MM_PREV_SENT_DATE_HDR 0xA1 /* X-Mms-Previously-Sent-Date */
105 /* MMS 1.2 */
106 #define MM_STORE_HDR 0xA2 /* X-Mms-Store */
107 #define MM_MM_STATE_HDR 0xA3 /* X-Mms-MM-State */
108 #define MM_MM_FLAGS_HDR 0xA4 /* X-Mms-MM-Flags */
109 #define MM_STORE_STATUS_HDR 0xA5 /* X-Mms-Store-Status */
110 #define MM_STORE_STATUS_TEXT_HDR \
111 0xA6 /* X-Mms-Store-Status-Text */
112 #define MM_STORED_HDR 0xA7 /* X-Mms-Stored */
113 #define MM_ATTRIBUTES_HDR 0xA8 /* X-Mms-Attributes */
114 #define MM_TOTALS_HDR 0xA9 /* X-Mms-Totals */
115 #define MM_MBOX_TOTALS_HDR 0xAA /* X-Mms-Mbox-Totals */
116 #define MM_QUOTAS_HDR 0xAB /* X-Mms-Quotas */
117 #define MM_MBOX_QUOTAS_HDR 0xAC /* X-Mms-Mbox-Quotas */
118 #define MM_MBOX_MSG_COUNT_HDR 0xAD /* X-Mms-Message-Count */
119 #define MM_CONTENT_HDR 0xAE /* Content */
120 #define MM_START_HDR 0xAF /* X-Mms-Start */
121 #define MM_ADDITIONAL_HDR 0xB0 /* Additional-headers */
122 #define MM_DISTRIBUION_IND_HDR 0xB1 /* X-Mms-Distribution-Indicator */
123 #define MM_ELEMENT_DESCR_HDR 0xB2 /* X-Mms-Element-Descriptor */
124 #define MM_LIMIT_HDR 0xB3 /* X-Mms-Limit */
126 static const value_string vals_mm_header_names[] = {
127 /* MMS 1.0 */
128 { MM_BCC_HDR, "Bcc" },
129 { MM_CC_HDR, "Cc" },
130 { MM_CLOCATION_HDR, "X-Mms-Content-Location" },
131 { MM_CTYPE_HDR, "X-Mms-Content-Type" },
132 { MM_DATE_HDR, "Date" },
133 { MM_DREPORT_HDR, "X-Mms-Delivery-Report" },
134 { MM_DTIME_HDR, "X-Mms-Delivery-Time" },
135 { MM_EXPIRY_HDR, "X-Mms-Expiry" },
136 { MM_FROM_HDR, "From" },
137 { MM_MCLASS_HDR, "X-Mms-Message-Class" },
138 { MM_MID_HDR, "Message-ID" },
139 { MM_MTYPE_HDR, "X-Mms-Message-Type" },
140 { MM_VERSION_HDR, "X-Mms-MMS-Version" },
141 { MM_MSIZE_HDR, "X-Mms-Message-Size" },
142 { MM_PRIORITY_HDR, "X-Mms-Priority" },
143 { MM_RREPLY_HDR, "X-Mms-Read-Reply" },
144 { MM_RALLOWED_HDR, "X-Mms-Report-Allowed" },
145 { MM_RSTATUS_HDR, "X-Mms-Response-Status" },
146 { MM_RTEXT_HDR, "X-Mms-Response-Text" },
147 { MM_SVISIBILITY_HDR, "X-Mms-Sender-Visibility" },
148 { MM_STATUS_HDR, "X-Mms-Status" },
149 { MM_SUBJECT_HDR, "Subject" },
150 { MM_TO_HDR, "To" },
151 { MM_TID_HDR, "X-Mms-Transaction-Id" },
152 /* MMS 1.1 */
153 { MM_RETRIEVE_STATUS_HDR, "X-Mms-Retrieve-Status" },
154 { MM_RETRIEVE_TEXT_HDR, "X-Mms-Retrieve-Text" },
155 { MM_READ_STATUS_HDR, "X-Mms-Read-Status" },
156 { MM_REPLY_CHARGING_HDR, "X-Mms-Reply-Charging" },
157 { MM_REPLY_CHARGING_DEADLINE_HDR,
158 "X-Mms-Reply-Charging-Deadline" },
159 { MM_REPLY_CHARGING_ID_HDR, "X-Mms-Reply-Charging-ID" },
160 { MM_REPLY_CHARGING_SIZE_HDR, "X-Mms-Reply-Charging-Size" },
161 { MM_PREV_SENT_BY_HDR, "X-Mms-Previously-Sent-By" },
162 { MM_PREV_SENT_DATE_HDR, "X-Mms-Previously-Sent-Date" },
163 /* MMS 1.2 */
164 { MM_STORE_HDR, "X-Mms-Store" },
165 { MM_MM_STATE_HDR, "X-Mms-MM-State" },
166 { MM_MM_FLAGS_HDR, "X-Mms-MM-Flags" },
167 { MM_STORE_STATUS_HDR, "X-Mms-Store-Status" },
168 { MM_STORE_STATUS_TEXT_HDR, "X-Mms-Store-Status-Text" },
169 { MM_STORED_HDR, "X-Mms-Stored" },
170 { MM_ATTRIBUTES_HDR, "X-Mms-Attributes" },
171 { MM_TOTALS_HDR, "X-Mms-Totals" },
172 { MM_MBOX_TOTALS_HDR, "X-Mms-Mbox-Totals" },
173 { MM_QUOTAS_HDR, "X-Mms-Quotas" },
174 { MM_MBOX_QUOTAS_HDR, "X-Mms-Mbox-Quotas" },
175 { MM_MBOX_MSG_COUNT_HDR, "X-Mms-Message-Count" },
176 { MM_CONTENT_HDR, "Content" },
177 { MM_START_HDR, "X-Mms-Start" },
178 { MM_ADDITIONAL_HDR, "Additional-headers" },
179 { MM_DISTRIBUION_IND_HDR, "X-Mms-Distribution-Indicator" },
180 { MM_ELEMENT_DESCR_HDR, "X-Mms-Element-Descriptor" },
181 { MM_LIMIT_HDR, "X-Mms-Limit" },
183 { 0x00, NULL },
186 * Initialize the protocol and registered fields
188 static int proto_mmse;
190 static int hf_mmse_message_type;
191 static int hf_mmse_transaction_id;
192 static int hf_mmse_mms_version;
193 static int hf_mmse_bcc;
194 static int hf_mmse_cc;
195 static int hf_mmse_content_location;
196 static int hf_mmse_date;
197 static int hf_mmse_delivery_report;
198 static int hf_mmse_delivery_time_abs;
199 static int hf_mmse_delivery_time_rel;
200 static int hf_mmse_expiry_abs;
201 static int hf_mmse_expiry_rel;
202 static int hf_mmse_from;
203 static int hf_mmse_message_class_id;
204 static int hf_mmse_message_class_str;
205 static int hf_mmse_message_id;
206 static int hf_mmse_message_size;
207 static int hf_mmse_priority;
208 static int hf_mmse_read_reply;
209 static int hf_mmse_report_allowed;
210 static int hf_mmse_response_status;
211 static int hf_mmse_response_text;
212 static int hf_mmse_sender_visibility;
213 static int hf_mmse_status;
214 static int hf_mmse_subject;
215 static int hf_mmse_to;
216 /* static int hf_mmse_content_type; */
217 static int hf_mmse_ffheader;
218 /* MMSE 1.1 */
219 static int hf_mmse_read_report;
220 static int hf_mmse_retrieve_status;
221 static int hf_mmse_retrieve_text;
222 static int hf_mmse_read_status;
223 static int hf_mmse_reply_charging;
224 static int hf_mmse_reply_charging_deadline_abs;
225 static int hf_mmse_reply_charging_deadline_rel;
226 static int hf_mmse_reply_charging_id;
227 static int hf_mmse_reply_charging_size;
228 static int hf_mmse_prev_sent_by;
229 static int hf_mmse_prev_sent_by_fwd_count;
230 static int hf_mmse_prev_sent_by_address;
231 static int hf_mmse_prev_sent_date;
232 static int hf_mmse_prev_sent_date_fwd_count;
233 static int hf_mmse_prev_sent_date_date;
234 static int hf_mmse_header_uint;
235 static int hf_mmse_header_string;
236 static int hf_mmse_header_bytes;
239 * Initialize the subtree pointers
241 static int ett_mmse;
242 static int ett_mmse_hdr_details;
244 static expert_field ei_mmse_oversized_uintvar;
247 * Valuestrings for PDU types
249 /* MMS 1.0 */
250 #define PDU_M_SEND_REQ 0x80
251 #define PDU_M_SEND_CONF 0x81
252 #define PDU_M_NOTIFICATION_IND 0x82
253 #define PDU_M_NOTIFYRESP_IND 0x83
254 #define PDU_M_RETRIEVE_CONF 0x84
255 #define PDU_M_ACKNOWLEDGE_IND 0x85
256 #define PDU_M_DELIVERY_IND 0x86
257 /* MMS 1.1 */
258 #define PDU_M_READ_REC_IND 0x87
259 #define PDU_M_READ_ORIG_IND 0x88
260 #define PDU_M_FORWARD_REQ 0x89
261 #define PDU_M_FORWARD_CONF 0x8A
262 /* MMS 1.2 */
263 #define PDU_M_MBOX_STORE_REQ 0x8B
264 #define PDU_M_MBOX_STORE_CONF 0x8C
265 #define PDU_M_MBOX_VIEW_REQ 0x8D
266 #define PDU_M_MBOX_VIEW_CONF 0x8E
267 #define PDU_M_MBOX_UPLOAD_REQ 0x8F
268 #define PDU_M_MBOX_UPLOAD_CONF 0x90
269 #define PDU_M_MBOX_DELETE_REQ 0x91
270 #define PDU_M_MBOX_DELETE_CONF 0x92
271 #define PDU_M_MBOX_DESCR 0x93
273 #define pdu_has_content(pdut) \
274 ( ((pdut) == PDU_M_SEND_REQ) \
275 || ((pdut) == PDU_M_DELIVERY_IND) \
276 || ((pdut) == PDU_M_RETRIEVE_CONF) \
277 || ((pdut) == PDU_M_MBOX_VIEW_CONF) \
278 || ((pdut) == PDU_M_MBOX_DESCR) \
279 || ((pdut) == PDU_M_MBOX_UPLOAD_REQ) \
282 static const value_string vals_message_type[] = {
283 /* MMS 1.0 */
284 { PDU_M_SEND_REQ, "m-send-req" },
285 { PDU_M_SEND_CONF, "m-send-conf" },
286 { PDU_M_NOTIFICATION_IND, "m-notification-ind" },
287 { PDU_M_NOTIFYRESP_IND, "m-notifyresp-ind" },
288 { PDU_M_RETRIEVE_CONF, "m-retrieve-conf" },
289 { PDU_M_ACKNOWLEDGE_IND, "m-acknowledge-ind" },
290 { PDU_M_DELIVERY_IND, "m-delivery-ind" },
291 /* MMS 1.1 */
292 { PDU_M_READ_REC_IND, "m-read-rec-ind" },
293 { PDU_M_READ_ORIG_IND, "m-read-orig-ind" },
294 { PDU_M_FORWARD_REQ, "m-forward-req" },
295 { PDU_M_FORWARD_CONF, "m-forward-conf" },
296 /* MMS 1.2 */
297 { PDU_M_MBOX_STORE_REQ, "m-mbox-store-req" },
298 { PDU_M_MBOX_STORE_CONF, "m-mbox-store-conf" },
299 { PDU_M_MBOX_VIEW_REQ, "m-mbox-view-req" },
300 { PDU_M_MBOX_VIEW_CONF, "m-mbox-view-conf" },
301 { PDU_M_MBOX_UPLOAD_REQ, "m-mbox-upload-req" },
302 { PDU_M_MBOX_UPLOAD_CONF, "m-mbox-upload-conf" },
303 { PDU_M_MBOX_DELETE_REQ, "m-mbox-delete-req" },
304 { PDU_M_MBOX_DELETE_CONF, "m-mbox-delete-conf" },
305 { PDU_M_MBOX_DESCR, "m-mbox-descr" },
306 { 0x00, NULL },
309 static const value_string vals_yes_no[] = {
310 { 0x80, "Yes" },
311 { 0x81, "No" },
312 { 0x00, NULL },
315 static const value_string vals_message_class[] = {
316 { 0x80, "Personal" },
317 { 0x81, "Advertisement" },
318 { 0x82, "Informational" },
319 { 0x83, "Auto" },
320 { 0x00, NULL },
323 static const value_string vals_priority[] = {
324 { 0x80, "Low" },
325 { 0x81, "Normal" },
326 { 0x82, "High" },
327 { 0x00, NULL },
330 static const value_string vals_response_status[] = {
331 /* MMS 1.0 - obsolete as from MMS 1.1 */
332 { 0x80, "Ok" },
333 { 0x81, "Unspecified" },
334 { 0x82, "Service denied" },
335 { 0x83, "Message format corrupt" },
336 { 0x84, "Sending address unresolved" },
337 { 0x85, "Message not found" },
338 { 0x86, "Network problem" },
339 { 0x87, "Content not accepted" },
340 { 0x88, "Unsupported message" },
343 * Transient errors
345 /* MMS 1.1 */
346 { 0xC0, "Transient failure" },
347 { 0xC1, "Transient: Sending address unresolved" },
348 { 0xC2, "Transient: Message not found" },
349 { 0xC3, "Transient: Network problem" },
350 /* MMS 1.2 */
351 { 0xC4, "Transient: Partial success" },
354 * Permanent errors
356 /* MMS 1.1 */
357 { 0xE0, "Permanent failure" },
358 { 0xE1, "Permanent: Service denied" },
359 { 0xE2, "Permanent: Message format corrupt" },
360 { 0xE3, "Permanent: Sending address unresolved" },
361 { 0xE4, "Permanent: Message not found" },
362 { 0xE5, "Permanent: Content not accepted" },
363 { 0xE6, "Permanent: Reply charging limitations not met" },
364 { 0xE7, "Permanent: Reply charging request not accepted" },
365 { 0xE8, "Permanent: Reply charging forwarding denied" },
366 { 0xE9, "Permanent: Reply charging not supported" },
367 /* MMS 1.2 */
368 { 0xEA, "Permanent: Address hiding not supported" },
370 { 0x00, NULL },
373 static const value_string vals_sender_visibility[] = {
374 { 0x80, "Hide" },
375 { 0x81, "Show" },
376 { 0x00, NULL },
379 static const value_string vals_message_status[] = {
380 /* MMS 1.0 */
381 { 0x80, "Expired" },
382 { 0x81, "Retrieved" },
383 { 0x82, "Rejected" },
384 { 0x83, "Deferred" },
385 { 0x84, "Unrecognized" },
386 /* MMS 1.1 */
387 { 0x85, "Indeterminate" },
388 { 0x86, "Forwarded" },
389 /* MMS 1.2 */
390 { 0x87, "Unreachable" },
392 { 0x00, NULL },
395 static const value_string vals_retrieve_status[] = {
396 /* MMS 1.1 */
397 { 0x80, "Ok" },
400 * Transient errors
402 /* MMS 1.1 */
403 { 0xC0, "Transient failure" },
404 { 0xC1, "Transient: Message not found" },
405 { 0xC2, "Transient: Network problem" },
408 * Permanent errors
410 /* MMS 1.1 */
411 { 0xE0, "Permanent failure" },
412 { 0xE1, "Permanent: Service denied" },
413 { 0xE2, "Permanent: Message not found" },
414 { 0xE3, "Permanent: Content unsupported" },
416 { 0x00, NULL },
419 static const value_string vals_read_status[] = {
420 { 0x80, "Read" },
421 { 0x81, "Deleted without being read" },
423 { 0x00, NULL },
426 static const value_string vals_reply_charging[] = {
427 { 0x80, "Requested" },
428 { 0x81, "Requested text only" },
429 { 0x82, "Accepted" },
430 { 0x83, "Accepted text only" },
432 { 0x00, NULL },
436 * Decodes a Text-string from the protocol data
437 * Text-string = [Quote] *TEXT End-of-string
438 * Quote = <Octet 127>
439 * End-of-string = <Octet 0>
441 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
443 * \param tvb The buffer with PDU-data
444 * \param offset Offset within that buffer
445 * \param pool wmem allocation pool from which to allocate
446 * memory for strval
447 * \param strval Pointer to variable into which to put pointer to
448 * buffer allocated to hold the text; must be freed
449 * when no longer used
451 * \return The length in bytes of the entire field
453 static unsigned
454 get_text_string(tvbuff_t *tvb, unsigned offset, wmem_allocator_t *pool, const char **strval)
456 unsigned len;
458 DebugLog(("get_text_string(tvb = %p, offset = %u, **strval) - start\n",
459 tvb, offset));
460 /* OMA-TS-MMS-CONF says that Text-string encoding is always US-ASCII.
461 * (In other WSP protocols it might be the document encoding.)
462 * It is allowed to be Base64 or Quoted-Printable encoded, but
463 * we won't bother with that.
465 if (tvb_get_uint8(tvb, offset) == MM_QUOTE) {
466 *strval = (const char *)tvb_get_stringz_enc(pool, tvb, offset+1, &len, ENC_ASCII);
467 len += 1;
468 } else {
469 *strval = (const char *)tvb_get_stringz_enc(pool, tvb, offset, &len, ENC_ASCII);
471 DebugLog((" [3] Return(len) == %u\n", len));
472 return len;
476 * Decodes a Value-length from the protocol data.
477 * Value-length = Short-length | (Length-quote Length)
478 * Short-length = <Any octet 0-30>
479 * Length-quote = <Octet 31>
480 * Length = Uintvar-integer
482 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
484 * \param tvb The buffer with PDU-data
485 * \param offset Offset within that buffer
486 * \param byte_count Returns the length in bytes of
487 * the "Value-length" field.
488 * \param pinfo packet_info structure
490 * \return The actual value of "Value-length"
492 static unsigned
493 get_value_length(tvbuff_t *tvb, unsigned offset, unsigned *byte_count, packet_info *pinfo)
495 unsigned field;
497 field = tvb_get_uint8(tvb, offset++);
498 if (field < 31)
499 *byte_count = 1;
500 else { /* Must be 31 so, Uintvar follows */
501 field = tvb_get_uintvar(tvb, offset, byte_count, pinfo, &ei_mmse_oversized_uintvar);
502 (*byte_count)++;
505 /* The packet says there are this many bytes; ensure they're there.
506 * We do this here because several callers do math on the length we
507 * return here and may not catch an overflow.
509 tvb_ensure_bytes_exist(tvb, offset, field);
510 return field;
514 * Decodes a Long-integer from the protocol data
515 * Long-integer = Short-length Multi-octet-integer
516 * Short-length = <Any octet 0-30>
517 * Multi-octet-integer = 1*30OCTET
519 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
521 * \param tvb The buffer with PDU-data
522 * \param offset Offset within that buffer
523 * \param byte_count Returns the length in bytes of the field
525 * \return The value of the Long-integer
527 * \note A maximum of 4-byte integers will be handled.
529 static unsigned
530 get_long_integer(tvbuff_t *tvb, unsigned offset, unsigned *byte_count)
532 unsigned val;
534 *byte_count = tvb_get_uint8(tvb, offset++);
535 switch (*byte_count) {
536 case 1:
537 val = tvb_get_uint8(tvb, offset);
538 break;
539 case 2:
540 val = tvb_get_ntohs(tvb, offset);
541 break;
542 case 3:
543 val = tvb_get_ntoh24(tvb, offset);
544 break;
545 case 4:
546 val = tvb_get_ntohl(tvb, offset);
547 break;
548 default:
549 val = 0;
550 break;
552 (*byte_count)++;
553 return val;
557 * Decodes an Integer-value from the protocol data
558 * Integer-value = Short-integer | Long-integer
559 * Short-integer = OCTET
560 * Long-integer = Short-length Multi-octet-integer
561 * Short-length = <Any octet 0-30>
562 * Multi-octet-integer = 1*30OCTET
564 * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
566 * \param tvb The buffer with PDU-data
567 * \param offset Offset within that buffer
568 * \param byte_count Returns the length in bytes of the field
570 * \return The value of the Long-integer
572 * \note A maximum of 4-byte integers will be handled.
574 static unsigned
575 get_integer_value(tvbuff_t *tvb, unsigned offset, unsigned *byte_count)
577 unsigned val;
578 uint8_t peek;
580 peek = tvb_get_uint8(tvb, offset++);
581 if (peek & 0x80) {
582 val = peek & 0x7F;
583 *byte_count = 1;
584 return val;
585 } else {
586 *byte_count = peek;
587 switch (peek) {
588 case 1:
589 val = tvb_get_uint8(tvb, offset);
590 break;
591 case 2:
592 val = tvb_get_ntohs(tvb, offset);
593 break;
594 case 3:
595 val = tvb_get_ntoh24(tvb, offset);
596 break;
597 case 4:
598 val = tvb_get_ntohl(tvb, offset);
599 break;
600 default:
601 val = 0;
602 break;
605 (*byte_count)++;
606 return val;
610 * Decodes an Encoded-string-value from the protocol data
611 * Encoded-string-value = Text-string | Value-length Char-set Text-string
613 * \param tvb The buffer with PDU-data
614 * \param offset Offset within that buffer
615 * \param strval Pointer to variable into which to put pointer to
616 * buffer allocated to hold the text; must be freed
617 * when no longer used
619 * \return The length in bytes of the entire field
621 static unsigned
622 get_encoded_strval(tvbuff_t *tvb, unsigned offset, const char **strval, packet_info *pinfo)
624 unsigned field;
625 unsigned length;
626 unsigned count, count1;
627 unsigned charset;
629 field = tvb_get_uint8(tvb, offset);
631 if (field < 32) {
632 length = get_value_length(tvb, offset, &count, pinfo);
633 if (length < 2) {
634 *strval = "";
635 } else {
636 /* OMA-TS-MMS-CONF says that char-set is encoded as an integer
637 * value, so don't bother to handle the string case. */
638 field = tvb_get_uint8(tvb, offset + count);
639 if ((field < 32) | (field & 0x80)) {
640 charset = get_integer_value(tvb, offset + count, &count1);
641 *strval = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset + count + count1, length - count1, mibenum_charset_to_encoding(charset));
642 } else {
643 *strval = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset + count, length, ENC_ASCII);
646 return count + length;
647 } else
648 return get_text_string(tvb, offset, pinfo->pool, strval);
651 /* Code to actually dissect the packets */
652 static bool
653 dissect_mmse_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
655 uint8_t pdut;
657 DebugLog(("dissect_mmse_heur()\n"));
659 * Check if data makes sense for it to be dissected as MMSE: Message-type
660 * field must make sense and followed by either Transaction-Id
661 * or MMS-Version header
663 if (tvb_get_uint8(tvb, 0) != MM_MTYPE_HDR)
664 return false;
665 pdut = tvb_get_uint8(tvb, 1);
666 if (try_val_to_str(pdut, vals_message_type) == NULL)
667 return false;
668 if ((tvb_get_uint8(tvb, 2) != MM_TID_HDR) &&
669 (tvb_get_uint8(tvb, 2) != MM_VERSION_HDR))
670 return false;
671 dissect_mmse_standalone(tvb, pinfo, tree, data);
672 return true;
675 static int
676 dissect_mmse_standalone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
678 uint8_t pdut;
679 const char *message_type;
681 DebugLog(("dissect_mmse_standalone() - START (Packet %u)\n",
682 pinfo->num));
684 pdut = tvb_get_uint8(tvb, 1);
685 message_type = val_to_str(pdut, vals_message_type, "Unknown type %u");
687 /* Make entries in Protocol column and Info column on summary display */
688 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMSE");
690 col_add_fstr(pinfo->cinfo, COL_INFO, "MMS %s", message_type);
692 dissect_mmse(tvb, pinfo, tree, pdut, message_type);
693 return tvb_captured_length(tvb);
696 static int
697 dissect_mmse_encapsulated(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
699 uint8_t pdut;
700 const char *message_type;
702 DebugLog(("dissect_mmse_encapsulated() - START (Packet %u)\n",
703 pinfo->num));
705 pdut = tvb_get_uint8(tvb, 1);
706 message_type = val_to_str(pdut, vals_message_type, "Unknown type %u");
708 /* Make entries in Info column on summary display */
709 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(MMS %s)",
710 message_type);
712 dissect_mmse(tvb, pinfo, tree, pdut, message_type);
713 return tvb_captured_length(tvb);
716 static void
717 dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint8_t pdut,
718 const char *message_type)
720 unsigned offset, old_offset;
721 uint8_t field = 0;
722 const char *strval;
723 unsigned length;
724 unsigned count;
725 uint8_t version = 0x80; /* Default to MMSE 1.0 */
727 /* Set up structures needed to add the protocol subtree and manage it */
728 proto_item *ti = NULL;
729 proto_tree *mmse_tree = NULL;
731 DebugLog(("dissect_mmse() - START (Packet %u)\n", pinfo->num));
733 ti = proto_tree_add_item(tree, proto_mmse, tvb, 0, -1, ENC_NA);
734 proto_item_append_text(ti, ", Type: %s", message_type);
735 /* create display subtree for the protocol */
736 mmse_tree = proto_item_add_subtree(ti, ett_mmse);
738 /* Report PDU-type */
739 proto_tree_add_uint(mmse_tree, hf_mmse_message_type, tvb, 0, 2, pdut);
741 offset = 2; /* Skip Message-Type */
742 old_offset = 1;
745 * Cycle through MMS-headers
747 * NOTE - some PDUs may convey content that can be handed off
748 * to subdissectors.
750 if (tree == NULL && !pdu_has_content(pdut)) {
751 DebugLog(("tree == NULL and PDU has no potential content\n"));
752 return;
755 while ((offset < tvb_reported_length(tvb)) &&
756 (field = tvb_get_uint8(tvb, offset++)) != MM_CTYPE_HDR)
758 DebugLog(("\tField = 0x%02X (offset = %u): %s\n",
759 field, offset,
760 val_to_str(field, vals_mm_header_names,
761 "Unknown MMS header 0x%02X")));
762 switch (field)
764 case MM_TID_HDR: /* Text-string */
765 length = get_text_string(tvb, offset, pinfo->pool, &strval);
766 proto_tree_add_string(mmse_tree, hf_mmse_transaction_id,
767 tvb, offset - 1, length + 1,strval);
768 offset += length;
769 break;
770 case MM_VERSION_HDR: /* nibble-Major/nibble-minor*/
772 uint8_t major, minor;
773 char *vers_string;
775 version = tvb_get_uint8(tvb, offset++);
776 major = (version & 0x70) >> 4;
777 minor = version & 0x0F;
778 if (minor == 0x0F)
779 vers_string = wmem_strdup_printf(pinfo->pool, "%u", major);
780 else
781 vers_string = wmem_strdup_printf(pinfo->pool, "%u.%u", major, minor);
782 proto_tree_add_string(mmse_tree, hf_mmse_mms_version,
783 tvb, offset - 2, 2, vers_string);
785 break;
786 case MM_BCC_HDR: /* Encoded-string-value */
787 length = get_encoded_strval(tvb, offset, &strval, pinfo);
788 proto_tree_add_string(mmse_tree, hf_mmse_bcc, tvb,
789 offset - 1, length + 1, strval);
790 offset += length;
791 break;
792 case MM_CC_HDR: /* Encoded-string-value */
793 length = get_encoded_strval(tvb, offset, &strval, pinfo);
794 proto_tree_add_string(mmse_tree, hf_mmse_cc, tvb,
795 offset - 1, length + 1, strval);
796 offset += length;
797 break;
798 case MM_CLOCATION_HDR: /* Uri-value */
799 if (pdut == PDU_M_MBOX_DELETE_CONF) {
800 /* General form with length */
801 length = tvb_get_uint8(tvb, offset);
802 if (length == 0x1F) {
803 unsigned length_len = 0;
804 length = tvb_get_uintvar(tvb, offset + 1,
805 &length_len, pinfo, &ei_mmse_oversized_uintvar);
806 length += 1 + length_len;
807 } else {
808 length += 1;
810 proto_tree_add_string(mmse_tree,
811 hf_mmse_content_location,
812 tvb, offset - 1, length + 1,
813 "<Undecoded value for m-mbox-delete-conf>");
814 } else {
815 length = get_text_string(tvb, offset, pinfo->pool, &strval);
816 proto_tree_add_string(mmse_tree,
817 hf_mmse_content_location,
818 tvb, offset - 1, length + 1, strval);
820 offset += length;
821 break;
822 case MM_DATE_HDR: /* Long-integer */
824 unsigned tval;
825 nstime_t tmptime;
827 tval = get_long_integer(tvb, offset, &count);
828 tmptime.secs = tval;
829 tmptime.nsecs = 0;
830 proto_tree_add_time(mmse_tree, hf_mmse_date, tvb,
831 offset - 1, count + 1, &tmptime);
833 offset += count;
834 break;
835 case MM_DREPORT_HDR: /* Yes|No */
836 field = tvb_get_uint8(tvb, offset++);
837 proto_tree_add_uint(mmse_tree,
838 hf_mmse_delivery_report,
839 tvb, offset - 2, 2, field);
840 break;
841 case MM_DTIME_HDR:
843 unsigned tval;
844 nstime_t tmptime;
845 unsigned cnt;
848 * Value-length(Absolute-token Date-value|
849 * Relative-token Delta-seconds-value)
851 length = get_value_length(tvb, offset, &count, pinfo);
852 field = tvb_get_uint8(tvb, offset + count);
854 tval = get_long_integer(tvb, offset + count + 1, &cnt);
855 tmptime.secs = tval;
856 tmptime.nsecs = 0;
858 if (field == 0x80)
859 proto_tree_add_time(mmse_tree,
860 hf_mmse_delivery_time_abs,
861 tvb, offset - 1,
862 length + count + 1, &tmptime);
863 else
864 proto_tree_add_time(mmse_tree,
865 hf_mmse_delivery_time_rel,
866 tvb, offset - 1,
867 length + count + 1, &tmptime);
869 offset += length + count;
870 break;
871 case MM_EXPIRY_HDR:
873 unsigned tval;
874 nstime_t tmptime;
875 unsigned cnt;
878 * Value-length(Absolute-token Date-value|
879 * Relative-token Delta-seconds-value)
881 length = get_value_length(tvb, offset, &count, pinfo);
882 field = tvb_get_uint8(tvb, offset + count);
884 tval = get_long_integer(tvb, offset + count + 1, &cnt);
885 tmptime.secs = tval;
886 tmptime.nsecs = 0;
888 if (field == 0x80)
889 proto_tree_add_time(mmse_tree, hf_mmse_expiry_abs,
890 tvb, offset - 1,
891 length + count + 1, &tmptime);
892 else
893 proto_tree_add_time(mmse_tree, hf_mmse_expiry_rel,
894 tvb, offset - 1,
895 length + count + 1, &tmptime);
897 offset += length + count;
898 break;
899 case MM_FROM_HDR:
901 * Value-length(Address-present-token Encoded-string-value
902 * |Insert-address-token)
904 length = get_value_length(tvb, offset, &count, pinfo);
905 field = tvb_get_uint8(tvb, offset + count);
906 if (field == 0x81) {
907 proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
908 offset-1, length + count + 1,
909 "<insert address>");
910 } else {
911 (void) get_encoded_strval(tvb, offset + count + 1,
912 &strval, pinfo);
913 proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
914 offset-1, length + count + 1, strval);
916 offset += length + count;
917 break;
918 case MM_MCLASS_HDR:
920 * Class-identifier|Text-string
922 field = tvb_get_uint8(tvb, offset);
923 if (field & 0x80) {
924 offset++;
925 proto_tree_add_uint(mmse_tree,
926 hf_mmse_message_class_id,
927 tvb, offset - 2, 2, field);
928 } else {
929 length = get_text_string(tvb, offset, pinfo->pool, &strval);
930 proto_tree_add_string(mmse_tree,
931 hf_mmse_message_class_str,
932 tvb, offset - 1, length + 1,
933 strval);
934 offset += length;
936 break;
937 case MM_MID_HDR: /* Text-string */
938 length = get_text_string(tvb, offset, pinfo->pool, &strval);
939 proto_tree_add_string(mmse_tree, hf_mmse_message_id,
940 tvb, offset - 1, length + 1, strval);
941 offset += length;
942 break;
943 case MM_MSIZE_HDR: /* Long-integer */
944 length = get_long_integer(tvb, offset, &count);
945 proto_tree_add_uint(mmse_tree, hf_mmse_message_size,
946 tvb, offset - 1, count + 1, length);
947 offset += count;
948 break;
949 case MM_PRIORITY_HDR: /* Low|Normal|High */
950 field = tvb_get_uint8(tvb, offset++);
951 proto_tree_add_uint(mmse_tree, hf_mmse_priority, tvb,
952 offset - 2, 2, field);
953 break;
954 case MM_RREPLY_HDR: /* Yes|No */
955 field = tvb_get_uint8(tvb, offset++);
956 if (version == 0x80) { /* MMSE 1.0 */
957 proto_tree_add_uint(mmse_tree, hf_mmse_read_reply,
958 tvb, offset - 2, 2, field);
959 } else {
960 proto_tree_add_uint(mmse_tree, hf_mmse_read_report,
961 tvb, offset - 2, 2, field);
963 break;
964 case MM_RALLOWED_HDR: /* Yes|No */
965 field = tvb_get_uint8(tvb, offset++);
966 proto_tree_add_uint(mmse_tree, hf_mmse_report_allowed,
967 tvb, offset - 2, 2, field);
968 break;
969 case MM_RSTATUS_HDR:
970 field = tvb_get_uint8(tvb, offset++);
971 proto_tree_add_uint(mmse_tree, hf_mmse_response_status,
972 tvb, offset - 2, 2, field);
973 break;
974 case MM_RTEXT_HDR: /* Encoded-string-value */
975 if (pdut == PDU_M_MBOX_DELETE_CONF) {
976 /* General form with length */
977 length = tvb_get_uint8(tvb, offset);
978 if (length == 0x1F) {
979 unsigned length_len = 0;
980 length = tvb_get_uintvar(tvb, offset + 1,
981 &length_len, pinfo, &ei_mmse_oversized_uintvar);
982 length += 1 + length_len;
983 } else {
984 length += 1;
986 proto_tree_add_string(mmse_tree,
987 hf_mmse_content_location,
988 tvb, offset - 1, length + 1,
989 "<Undecoded value for m-mbox-delete-conf>");
990 } else {
991 length = get_encoded_strval(tvb, offset, &strval, pinfo);
992 proto_tree_add_string(mmse_tree,
993 hf_mmse_response_text, tvb, offset - 1,
994 length + 1, strval);
996 offset += length;
997 break;
998 case MM_SVISIBILITY_HDR: /* Hide|Show */
999 field = tvb_get_uint8(tvb, offset++);
1000 proto_tree_add_uint(mmse_tree,hf_mmse_sender_visibility,
1001 tvb, offset - 2, 2, field);
1002 break;
1003 case MM_STATUS_HDR:
1004 field = tvb_get_uint8(tvb, offset++);
1005 proto_tree_add_uint(mmse_tree, hf_mmse_status, tvb,
1006 offset - 2, 2, field);
1007 break;
1008 case MM_SUBJECT_HDR: /* Encoded-string-value */
1009 length = get_encoded_strval(tvb, offset, &strval, pinfo);
1010 proto_tree_add_string(mmse_tree, hf_mmse_subject, tvb,
1011 offset - 1, length + 1, strval);
1012 offset += length;
1013 break;
1014 case MM_TO_HDR: /* Encoded-string-value */
1015 length = get_encoded_strval(tvb, offset, &strval, pinfo);
1016 proto_tree_add_string(mmse_tree, hf_mmse_to, tvb,
1017 offset - 1, length + 1, strval);
1018 offset += length;
1019 break;
1022 * MMS Encapsulation 1.1
1024 case MM_RETRIEVE_STATUS_HDR: /* Well-known-value */
1025 field = tvb_get_uint8(tvb, offset++);
1026 proto_tree_add_uint(mmse_tree, hf_mmse_retrieve_status,
1027 tvb, offset - 2, 2, field);
1028 break;
1029 case MM_RETRIEVE_TEXT_HDR:
1030 if (pdut == PDU_M_MBOX_DELETE_CONF) {
1031 /* General form with length */
1032 length = tvb_get_uint8(tvb, offset);
1033 if (length == 0x1F) {
1034 unsigned length_len = 0;
1035 length = tvb_get_uintvar(tvb, offset + 1,
1036 &length_len, pinfo, &ei_mmse_oversized_uintvar);
1037 length += 1 + length_len;
1038 } else {
1039 length += 1;
1042 proto_tree_add_string(mmse_tree,
1043 hf_mmse_content_location,
1044 tvb, offset - 1, length + 1,
1045 "<Undecoded value for m-mbox-delete-conf>");
1046 } else {
1047 /* Encoded-string-value */
1048 length = get_encoded_strval(tvb, offset, &strval, pinfo);
1049 proto_tree_add_string(mmse_tree,
1050 hf_mmse_retrieve_text, tvb, offset - 1,
1051 length + 1, strval);
1053 offset += length;
1054 break;
1055 case MM_READ_STATUS_HDR: /* Well-known-value */
1056 field = tvb_get_uint8(tvb, offset++);
1057 proto_tree_add_uint(mmse_tree, hf_mmse_read_status,
1058 tvb, offset - 2, 2, field);
1059 break;
1060 case MM_REPLY_CHARGING_HDR: /* Well-known-value */
1061 field = tvb_get_uint8(tvb, offset++);
1062 proto_tree_add_uint(mmse_tree, hf_mmse_reply_charging,
1063 tvb, offset - 2, 2, field);
1064 break;
1065 case MM_REPLY_CHARGING_DEADLINE_HDR: /* Well-known-value */
1067 unsigned tval;
1068 nstime_t tmptime;
1069 unsigned cnt;
1072 * Value-length(Absolute-token Date-value|
1073 * Relative-token Delta-seconds-value)
1076 length = get_value_length(tvb, offset, &count, pinfo);
1077 field = tvb_get_uint8(tvb, offset + count);
1079 tval = get_long_integer(tvb, offset + count + 1, &cnt);
1080 tmptime.secs = tval;
1081 tmptime.nsecs = 0;
1083 if (field == 0x80)
1084 proto_tree_add_time(mmse_tree, hf_mmse_reply_charging_deadline_abs,
1085 tvb, offset - 1,
1086 length + count + 1, &tmptime);
1087 else
1088 proto_tree_add_time(mmse_tree, hf_mmse_reply_charging_deadline_rel,
1089 tvb, offset - 1,
1090 length + count + 1, &tmptime);
1092 offset += length + count;
1093 break;
1094 case MM_REPLY_CHARGING_ID_HDR: /* Text-string */
1095 length = get_text_string(tvb, offset, pinfo->pool, &strval);
1096 proto_tree_add_string(mmse_tree,
1097 hf_mmse_reply_charging_id,
1098 tvb, offset - 1, length + 1, strval);
1099 offset += length;
1100 break;
1101 case MM_REPLY_CHARGING_SIZE_HDR: /* Long-integer */
1102 length = get_long_integer(tvb, offset, &count);
1103 proto_tree_add_uint(mmse_tree,
1104 hf_mmse_reply_charging_size,
1105 tvb, offset - 1, count + 1, length);
1106 offset += count;
1107 break;
1108 case MM_PREV_SENT_BY_HDR:
1110 uint32_t fwd_count, count1, count2;
1111 proto_tree *subtree = NULL;
1112 proto_item *tii = NULL;
1114 /* Value-length Integer-value Encoded-string-value */
1115 length = get_value_length(tvb, offset, &count, pinfo);
1117 /* 1. Forwarded-count-value := Integer-value */
1118 fwd_count = get_integer_value(tvb, offset + count,
1119 &count1);
1120 /* 2. Encoded-string-value */
1121 count2 = get_encoded_strval(tvb,
1122 offset + count + count1, &strval, pinfo);
1123 /* Now render the fields */
1124 tii = proto_tree_add_string_format(mmse_tree,
1125 hf_mmse_prev_sent_by,
1126 tvb, offset - 1, 1 + count + length,
1127 strval, "%s (Forwarded-count=%u)",
1128 format_text(pinfo->pool, strval, strlen(strval)),
1129 fwd_count);
1130 subtree = proto_item_add_subtree(tii,
1131 ett_mmse_hdr_details);
1132 proto_tree_add_uint(subtree,
1133 hf_mmse_prev_sent_by_fwd_count,
1134 tvb, offset + count, count1, fwd_count);
1135 proto_tree_add_string(subtree,
1136 hf_mmse_prev_sent_by_address,
1137 tvb, offset + count + count1, count2, strval);
1139 offset += length + count;
1140 break;
1141 case MM_PREV_SENT_DATE_HDR:
1143 uint32_t fwd_count, count1, count2;
1144 unsigned tval;
1145 nstime_t tmptime;
1146 proto_tree *subtree = NULL;
1147 proto_item *tii = NULL;
1149 /* Value-Length Forwarded-count-value Date-value */
1150 length = get_value_length(tvb, offset, &count, pinfo);
1151 /* 1. Forwarded-count-value := Integer-value */
1152 fwd_count = get_integer_value(tvb, offset + count, &count1);
1153 /* 2. Date-value := Long-integer */
1154 tval = get_long_integer(tvb, offset + count + count1,
1155 &count2);
1156 tmptime.secs = tval;
1157 tmptime.nsecs = 0;
1158 strval = abs_time_to_str(pinfo->pool, &tmptime, ABSOLUTE_TIME_LOCAL,
1159 true);
1160 /* Now render the fields */
1161 tii = proto_tree_add_string_format(mmse_tree,
1162 hf_mmse_prev_sent_date,
1163 tvb, offset - 1, 1 + count + length,
1164 strval, "%s (Forwarded-count=%u)",
1165 format_text(pinfo->pool, strval, strlen(strval)),
1166 fwd_count);
1167 subtree = proto_item_add_subtree(tii,
1168 ett_mmse_hdr_details);
1169 proto_tree_add_uint(subtree,
1170 hf_mmse_prev_sent_date_fwd_count,
1171 tvb, offset + count, count1, fwd_count);
1172 proto_tree_add_string(subtree,
1173 hf_mmse_prev_sent_date_date,
1174 tvb, offset + count + count1, count2, strval);
1176 offset += length + count;
1177 break;
1179 /* MMS Encapsulation 1.2 */
1181 default:
1182 if (field & 0x80) { /* Well-known WSP header encoding */
1183 uint8_t peek = tvb_get_uint8(tvb, offset);
1184 const char *hdr_name = val_to_str(field, vals_mm_header_names,
1185 "Unknown field (0x%02x)");
1186 const char *str;
1187 DebugLog(("\t\tUndecoded well-known header: %s\n",
1188 hdr_name));
1190 if (peek & 0x80) { /* Well-known value */
1191 length = 1;
1192 proto_tree_add_uint_format(mmse_tree, hf_mmse_header_uint, tvb, offset - 1,
1193 length + 1, peek,
1194 "%s: <Well-known value 0x%02x>"
1195 " (not decoded)",
1196 hdr_name, peek);
1197 } else if ((peek == 0) || (peek >= 0x20)) { /* Text */
1198 length = get_text_string(tvb, offset, pinfo->pool, &strval);
1199 str = format_text(pinfo->pool, strval, strlen(strval));
1200 proto_tree_add_string_format(mmse_tree, hf_mmse_header_string, tvb, offset - 1,
1201 length + 1, str, "%s: %s (Not decoded)", hdr_name, str);
1202 } else { /* General form with length */
1203 if (peek == 0x1F) { /* Value length in uintvar */
1204 unsigned length_len = 0;
1205 length = 1 + tvb_get_uintvar(tvb, offset + 1,
1206 &length_len, pinfo, &ei_mmse_oversized_uintvar);
1207 length += length_len;
1208 } else { /* Value length in octet */
1209 length = 1 + tvb_get_uint8(tvb, offset);
1211 proto_tree_add_bytes_format(mmse_tree, hf_mmse_header_bytes, tvb, offset - 1,
1212 length + 1, NULL, "%s: "
1213 "<Value in general form> (not decoded)",
1214 hdr_name);
1216 offset += length;
1217 } else { /* Literal WSP header encoding */
1218 unsigned length2;
1219 const char *strval2;
1221 --offset;
1222 length = get_text_string(tvb, offset, pinfo->pool, &strval);
1223 DebugLog(("\t\tUndecoded literal header: %s\n",
1224 strval));
1225 length2= get_text_string(tvb, offset+length, pinfo->pool, &strval2);
1227 proto_tree_add_string_format(mmse_tree,
1228 hf_mmse_ffheader, tvb, offset,
1229 length + length2,
1230 tvb_get_string_enc(pinfo->pool, tvb, offset,
1231 length + length2, ENC_ASCII),
1232 "%s: %s",
1233 format_text(pinfo->pool, strval, strlen(strval)),
1234 format_text(pinfo->pool, strval2, strlen(strval2)));
1236 offset += length + length2;
1238 break;
1240 DebugLog(("\tEnd(case)\n"));
1242 if (offset <= old_offset) {
1243 REPORT_DISSECTOR_BUG("Offset isn't increasing (offset=%u, old offset=%u)", offset, old_offset);
1245 old_offset = offset;
1248 DebugLog(("\tEnd(switch)\n"));
1249 if (field == MM_CTYPE_HDR) {
1251 * Eeehh, we're now actually back to good old WSP content-type
1252 * encoding. Let's steal that from the WSP-dissector.
1254 tvbuff_t *tmp_tvb;
1255 unsigned type;
1256 const char *type_str;
1258 DebugLog(("Content-Type: [from WSP dissector]\n"));
1259 DebugLog(("Calling add_content_type() in WSP dissector\n"));
1260 offset = add_content_type(mmse_tree, pinfo, tvb, offset, &type, &type_str);
1261 DebugLog(("Generating new TVB subset (offset = %u)\n", offset));
1262 tmp_tvb = tvb_new_subset_remaining(tvb, offset);
1263 DebugLog(("Add POST data\n"));
1264 add_post_data(mmse_tree, tmp_tvb, type, type_str, pinfo);
1265 DebugLog(("Done!\n"));
1268 /* If this protocol has a sub-dissector call it here, see section 1.8 */
1269 DebugLog(("dissect_mmse() - END\n"));
1273 /* Register the protocol with Wireshark */
1275 /* this format is required because a script is used to build the C function
1276 * that calls all the protocol registration.
1278 void
1279 proto_register_mmse(void)
1281 /* Setup list of header fields See Section 1.6.1 for details */
1282 static hf_register_info hf[] = {
1283 { &hf_mmse_message_type,
1284 { "X-Mms-Message-Type", "mmse.message_type",
1285 FT_UINT8, BASE_HEX, VALS(vals_message_type), 0x00,
1286 "Specifies the transaction type. Effectively defines PDU.",
1287 HFILL
1290 { &hf_mmse_transaction_id,
1291 { "X-Mms-Transaction-ID", "mmse.transaction_id",
1292 FT_STRING, BASE_NONE, NULL, 0x00,
1293 "A unique identifier for this transaction. Identifies request and corresponding response only.",
1294 HFILL
1297 { &hf_mmse_mms_version,
1298 { "X-Mms-MMS-Version", "mmse.mms_version",
1299 FT_STRING, BASE_NONE, NULL, 0x00,
1300 "Version of the protocol used.",
1301 HFILL
1304 { &hf_mmse_bcc,
1305 { "Bcc", "mmse.bcc",
1306 FT_STRING, BASE_NONE, NULL, 0x00,
1307 "Blind carbon copy.",
1308 HFILL
1311 { &hf_mmse_cc,
1312 { "Cc", "mmse.cc",
1313 FT_STRING, BASE_NONE, NULL, 0x00,
1314 "Carbon copy.",
1315 HFILL
1318 { &hf_mmse_content_location,
1319 { "X-Mms-Content-Location", "mmse.content_location",
1320 FT_STRING, BASE_NONE, NULL, 0x00,
1321 "Defines the location of the message.",
1322 HFILL
1325 { &hf_mmse_date,
1326 { "Date", "mmse.date",
1327 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
1328 "Arrival timestamp of the message or sending timestamp.",
1329 HFILL
1332 { &hf_mmse_delivery_report,
1333 { "X-Mms-Delivery-Report", "mmse.delivery_report",
1334 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1335 "Whether a report of message delivery is wanted or not.",
1336 HFILL
1339 { &hf_mmse_delivery_time_abs,
1340 { "X-Mms-Delivery-Time", "mmse.delivery_time.abs",
1341 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
1342 "The time at which message delivery is desired.",
1343 HFILL
1346 { &hf_mmse_delivery_time_rel,
1347 { "X-Mms-Delivery-Time", "mmse.delivery_time.rel",
1348 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1349 "The desired message delivery delay.",
1350 HFILL
1353 { &hf_mmse_expiry_abs,
1354 { "X-Mms-Expiry", "mmse.expiry.abs",
1355 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
1356 "Time when message expires and need not be delivered anymore.",
1357 HFILL
1360 { &hf_mmse_expiry_rel,
1361 { "X-Mms-Expiry", "mmse.expiry.rel",
1362 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1363 "Delay before message expires and need not be delivered anymore.",
1364 HFILL
1367 { &hf_mmse_from,
1368 { "From", "mmse.from",
1369 FT_STRING, BASE_NONE, NULL, 0x00,
1370 "Address of the message sender.",
1371 HFILL
1374 { &hf_mmse_message_class_id,
1375 { "X-Mms-Message-Class", "mmse.message_class.id",
1376 FT_UINT8, BASE_HEX, VALS(vals_message_class), 0x00,
1377 "Of what category is the message.",
1378 HFILL
1381 { &hf_mmse_message_class_str,
1382 { "X-Mms-Message-Class", "mmse.message_class.str",
1383 FT_STRING, BASE_NONE, NULL, 0x00,
1384 "Of what category is the message.",
1385 HFILL
1388 { &hf_mmse_message_id,
1389 { "Message-Id", "mmse.message_id",
1390 FT_STRING, BASE_NONE, NULL, 0x00,
1391 "Unique identification of the message.",
1392 HFILL
1395 { &hf_mmse_message_size,
1396 { "X-Mms-Message-Size", "mmse.message_size",
1397 FT_UINT32, BASE_DEC, NULL, 0x00,
1398 "The size of the message in octets.",
1399 HFILL
1402 { &hf_mmse_priority,
1403 { "X-Mms-Priority", "mmse.priority",
1404 FT_UINT8, BASE_HEX, VALS(vals_priority), 0x00,
1405 "Priority of the message.",
1406 HFILL
1409 { &hf_mmse_read_reply,
1410 { "X-Mms-Read-Reply", "mmse.read_reply",
1411 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1412 "Whether a read report from every recipient is wanted.",
1413 HFILL
1416 { &hf_mmse_read_report,
1417 { "X-Mms-Read-Report", "mmse.read_report",
1418 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1419 "Whether a read report from every recipient is wanted.",
1420 HFILL
1423 { &hf_mmse_report_allowed,
1424 { "X-Mms-Report-Allowed", "mmse.report_allowed",
1425 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
1426 "Sending of delivery report allowed or not.",
1427 HFILL
1430 { &hf_mmse_response_status,
1431 { "Response-Status", "mmse.response_status",
1432 FT_UINT8, BASE_HEX, VALS(vals_response_status), 0x00,
1433 "MMS-specific result of a message submission or retrieval.",
1434 HFILL
1437 { &hf_mmse_response_text,
1438 { "Response-Text", "mmse.response_text",
1439 FT_STRING, BASE_NONE, NULL, 0x00,
1440 "Additional information on MMS-specific result.",
1441 HFILL
1444 { &hf_mmse_sender_visibility,
1445 { "Sender-Visibility", "mmse.sender_visibility",
1446 FT_UINT8, BASE_HEX, VALS(vals_sender_visibility), 0x00,
1447 "Disclose sender identity to receiver or not.",
1448 HFILL
1451 { &hf_mmse_status,
1452 { "Status", "mmse.status",
1453 FT_UINT8, BASE_HEX, VALS(vals_message_status), 0x00,
1454 "Current status of the message.",
1455 HFILL
1458 { &hf_mmse_subject,
1459 { "Subject", "mmse.subject",
1460 FT_STRING, BASE_NONE, NULL, 0x00,
1461 "Subject of the message.",
1462 HFILL
1465 { &hf_mmse_to,
1466 { "To", "mmse.to",
1467 FT_STRING, BASE_NONE, NULL, 0x00,
1468 "Recipient(s) of the message.",
1469 HFILL
1472 #if 0
1473 { &hf_mmse_content_type,
1474 { "Data", "mmse.content_type",
1475 FT_NONE, BASE_NONE, NULL, 0x00,
1476 "Media content of the message.",
1477 HFILL
1480 #endif
1481 { &hf_mmse_ffheader,
1482 { "Free format (not encoded) header", "mmse.ffheader",
1483 FT_STRING, BASE_NONE, NULL, 0x00,
1484 "Application header without corresponding encoding.",
1485 HFILL
1488 /* MMSE 1.1 */
1489 { &hf_mmse_retrieve_status,
1490 { "X-Mms-Retrieve-Status", "mmse.retrieve_status",
1491 FT_UINT8, BASE_HEX, VALS(vals_retrieve_status), 0x00,
1492 "MMS-specific result of a message retrieval.",
1493 HFILL
1496 { &hf_mmse_retrieve_text,
1497 { "X-Mms-Retrieve-Text", "mmse.retrieve_text",
1498 FT_STRING, BASE_NONE, NULL, 0x00,
1499 "Status text of a MMS message retrieval.",
1500 HFILL
1503 { &hf_mmse_read_status,
1504 { "X-Mms-Read-Status", "mmse.read_status",
1505 FT_UINT8, BASE_HEX, VALS(vals_read_status), 0x00,
1506 "MMS-specific message read status.",
1507 HFILL
1510 { &hf_mmse_reply_charging,
1511 { "X-Mms-Reply-Charging", "mmse.reply_charging",
1512 FT_UINT8, BASE_HEX, VALS(vals_reply_charging), 0x00,
1513 "MMS-specific message reply charging method.",
1514 HFILL
1517 { &hf_mmse_reply_charging_deadline_abs,
1518 { "X-Mms-Reply-Charging-Deadline", "mmse.reply_charging_deadline.abs",
1519 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
1520 "The latest time of the recipient(s) to submit the Reply MM.",
1521 HFILL
1524 { &hf_mmse_reply_charging_deadline_rel,
1525 { "X-Mms-Reply-Charging-Deadline", "mmse.reply_charging_deadline.rel",
1526 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1527 "The latest time of the recipient(s) to submit the Reply MM.",
1528 HFILL
1531 { &hf_mmse_reply_charging_id,
1532 { "X-Mms-Reply-Charging-Id", "mmse.reply_charging_id",
1533 FT_STRING, BASE_NONE, NULL, 0x00,
1534 "Unique reply charging identification of the message.",
1535 HFILL
1538 { &hf_mmse_reply_charging_size,
1539 { "X-Mms-Reply-Charging-Size", "mmse.reply_charging_size",
1540 FT_UINT32, BASE_DEC, NULL, 0x00,
1541 "The size of the reply charging in octets.",
1542 HFILL
1545 { &hf_mmse_prev_sent_by,
1546 { "X-Mms-Previously-Sent-By", "mmse.previously_sent_by",
1547 FT_STRING, BASE_NONE, NULL, 0x00,
1548 "Indicates that the MM has been previously sent by this user.",
1549 HFILL
1552 { &hf_mmse_prev_sent_by_fwd_count,
1553 { "Forward Count", "mmse.previously_sent_by.forward_count",
1554 FT_UINT32, BASE_DEC, NULL, 0x00,
1555 "Forward count of the previously sent MM.",
1556 HFILL
1559 { &hf_mmse_prev_sent_by_address,
1560 { "Address", "mmse.previously_sent_by.address",
1561 FT_STRING, BASE_NONE, NULL, 0x00,
1562 "Indicates from whom the MM has been previously sent.",
1563 HFILL
1566 { &hf_mmse_prev_sent_date,
1567 { "X-Mms-Previously-Sent-Date", "mmse.previously_sent_date",
1568 FT_STRING, BASE_NONE, NULL, 0x00,
1569 "Indicates the date that the MM has been previously sent.",
1570 HFILL
1573 { &hf_mmse_prev_sent_date_fwd_count,
1574 { "Forward Count", "mmse.previously_sent_date.forward_count",
1575 FT_UINT32, BASE_DEC, NULL, 0x00,
1576 "Forward count of the previously sent MM.",
1577 HFILL
1580 { &hf_mmse_prev_sent_date_date,
1581 { "Date", "mmse.previously_sent_date.date",
1582 FT_STRING, BASE_NONE, NULL, 0x00,
1583 "Time when the MM has been previously sent.",
1584 HFILL
1587 { &hf_mmse_header_uint,
1588 { "Header Uint Value", "mmse.header.uint",
1589 FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL
1592 { &hf_mmse_header_string,
1593 { "Header String Value", "mmse.header.string",
1594 FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL
1597 { &hf_mmse_header_bytes,
1598 { "Header Byte array", "mmse.header.bytes",
1599 FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL
1605 /* Setup protocol subtree array */
1606 static int *ett[] = {
1607 &ett_mmse,
1608 &ett_mmse_hdr_details,
1611 static ei_register_info ei[] = {
1612 { &ei_mmse_oversized_uintvar, { "mmse.oversized_uintvar", PI_MALFORMED, PI_ERROR, "Uintvar is oversized", EXPFILL }}
1615 expert_module_t* expert_mmse;
1617 /* Register the protocol name and description */
1618 proto_mmse = proto_register_protocol("MMS Message Encapsulation",
1619 "MMSE", "mmse");
1621 /* Required function calls to register header fields and subtrees used */
1622 proto_register_field_array(proto_mmse, hf, array_length(hf));
1623 proto_register_subtree_array(ett, array_length(ett));
1625 expert_mmse = expert_register_protocol(proto_mmse);
1626 expert_register_field_array(expert_mmse, ei, array_length(ei));
1628 /* Register the dissectors */
1629 mmse_standalone_handle = register_dissector("mmse", dissect_mmse_standalone, proto_mmse);
1630 mmse_encapsulated_handle = register_dissector("mmse_encapsulated", dissect_mmse_encapsulated, proto_mmse);
1633 /* If this dissector uses sub-dissector registration add registration routine.
1634 * This format is required because a script is used to find these routines and
1635 * create the code that calls these routines.
1637 void
1638 proto_reg_handoff_mmse(void)
1640 heur_dissector_add("wsp", dissect_mmse_heur, "MMS Message Encapsulation over WSP", "mmse_wsp", proto_mmse, HEURISTIC_ENABLE);
1641 /* As the media types for WSP and HTTP are the same, the WSP dissector
1642 * uses the same string dissector table as the HTTP protocol. */
1643 dissector_add_string("media_type",
1644 "application/vnd.wap.mms-message", mmse_standalone_handle);
1645 dissector_add_string("multipart_media_type",
1646 "application/vnd.wap.mms-message", mmse_encapsulated_handle);
1650 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1652 * Local variables:
1653 * c-basic-offset: 4
1654 * tab-width: 8
1655 * indent-tabs-mode: nil
1656 * End:
1658 * vi: set shiftwidth=4 tabstop=8 expandtab:
1659 * :indentSize=4:tabSize=8:noTabs=true: