From Olivier Biot: have a separate subtree ett_ value for concatenated
[obnox/wireshark/wip.git] / packet-mmse.c
1 /* packet-mmse.c
2  * Routines for MMS Message Encapsulation dissection
3  * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
4  *
5  * $Id: packet-mmse.c,v 1.20 2003/10/09 18:54:06 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  * ----------
25  *
26  * Dissector of an encoded Multimedia message PDU, as defined by the WAPForum
27  * (http://www.wapforum.org) in "WAP-209-MMSEncapsulation-20020105-a".
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <glib.h>
39
40 #include <epan/packet.h>
41 #include "packet-wap.h"
42 #include "packet-wsp.h"
43 /* #include "packet-mmse.h" */          /* We autoregister      */
44
45 #define MM_QUOTE                0x7F    /* Quoted string        */
46
47 #define MMS_CONTENT_TYPE        0x3E    /* WINA-value for mms-message   */
48
49 /*
50  * Forward declarations
51  */
52 static void dissect_mmse(tvbuff_t *, packet_info *, proto_tree *);
53
54 /*
55  * Header field values
56  */
57 #define MM_BCC_HDR              0x81    /* Bcc                  */
58 #define MM_CC_HDR               0x82    /* Cc                   */
59 #define MM_CLOCATION_HDR        0x83    /* Content-Location     */
60 #define MM_CTYPE_HDR            0x84    /* Content-Type         */
61 #define MM_DATE_HDR             0x85    /* Date                 */
62 #define MM_DREPORT_HDR          0x86    /* Delivery-Report      */
63 #define MM_DTIME_HDR            0x87    /* Delivery-Time        */
64 #define MM_EXPIRY_HDR           0x88    /* Expiry               */
65 #define MM_FROM_HDR             0x89    /* From                 */
66 #define MM_MCLASS_HDR           0x8A    /* Message-Class        */
67 #define MM_MID_HDR              0x8B    /* Message-ID           */
68 #define MM_MTYPE_HDR            0x8C    /* Message-Type         */
69 #define MM_VERSION_HDR          0x8D    /* MMS-Version          */
70 #define MM_MSIZE_HDR            0x8E    /* Message-Size         */
71 #define MM_PRIORITY_HDR         0x8F    /* Priority             */
72 #define MM_RREPLY_HDR           0x90    /* Read-Reply           */
73 #define MM_RALLOWED_HDR         0x91    /* Report-Allowed       */
74 #define MM_RSTATUS_HDR          0x92    /* Response-Status      */
75 #define MM_RTEXT_HDR            0x93    /* Response-Text        */
76 #define MM_SVISIBILITY_HDR      0x94    /* Sender-Visibility    */
77 #define MM_STATUS_HDR           0x95    /* Status               */
78 #define MM_SUBJECT_HDR          0x96    /* Subject              */
79 #define MM_TO_HDR               0x97    /* To                   */
80 #define MM_TID_HDR              0x98    /* Transaction-Id       */
81
82 /*
83  * Initialize the protocol and registered fields
84  */
85 static int proto_mmse = -1;
86
87 static int hf_mmse_message_type         = -1;
88 static int hf_mmse_transaction_id       = -1;
89 static int hf_mmse_mms_version          = -1;
90 static int hf_mmse_bcc                  = -1;
91 static int hf_mmse_cc                   = -1;
92 static int hf_mmse_content_location     = -1;
93 static int hf_mmse_date                 = -1;
94 static int hf_mmse_delivery_report      = -1;
95 static int hf_mmse_delivery_time_abs    = -1;
96 static int hf_mmse_delivery_time_rel    = -1;
97 static int hf_mmse_expiry_abs           = -1;
98 static int hf_mmse_expiry_rel           = -1;
99 static int hf_mmse_from                 = -1;
100 static int hf_mmse_message_class_id     = -1;
101 static int hf_mmse_message_class_str    = -1;
102 static int hf_mmse_message_id           = -1;
103 static int hf_mmse_message_size         = -1;
104 static int hf_mmse_priority             = -1;
105 static int hf_mmse_read_reply           = -1;
106 static int hf_mmse_report_allowed       = -1;
107 static int hf_mmse_response_status      = -1;
108 static int hf_mmse_response_text        = -1;
109 static int hf_mmse_sender_visibility    = -1;
110 static int hf_mmse_status               = -1;
111 static int hf_mmse_subject              = -1;
112 static int hf_mmse_to                   = -1;
113 static int hf_mmse_content_type         = -1;
114 static int hf_mmse_ffheader             = -1;
115
116 /*
117  * Initialize the subtree pointers
118  */
119 static gint ett_mmse = -1;
120
121 /*
122  * Valuestrings for header contents
123  */
124 static const value_string vals_message_type[] = {
125     { 0x80, "m-send-req" },
126     { 0x81, "m-send-conf" },
127     { 0x82, "m-notification-ind" },
128     { 0x83, "m-notifyresp-ind" },
129     { 0x84, "m-retrieve-conf" },
130     { 0x85, "m-acknowledge-ind" },
131     { 0x86, "m-delivery-ind" },
132     { 0x00, NULL },
133 };
134
135 static const value_string vals_yes_no[] = {
136     { 0x80, "Yes" },
137     { 0x81, "No" },
138     { 0x00, NULL },
139 };
140
141 static const value_string vals_message_class[] = {
142     { 0x80, "Personal" },
143     { 0x81, "Advertisement" },
144     { 0x82, "Informational" },
145     { 0x83, "Auto" },
146     { 0x00, NULL },
147 };
148
149 static const value_string vals_priority[] = {
150     { 0x80, "Low" },
151     { 0x81, "Normal" },
152     { 0x82, "High" },
153     { 0x00, NULL },
154 };
155
156 static const value_string vals_response_status[] = {
157     { 0x80, "Ok" },
158     { 0x81, "Unspecified" },
159     { 0x82, "Service denied" },
160     { 0x83, "Message format corrupt" },
161     { 0x84, "Sending address unresolved" },
162     { 0x85, "Message not found" },
163     { 0x86, "Network problem" },
164     { 0x87, "Content not accepted" },
165     { 0x88, "Unsupported message" },
166     { 0x00, NULL },
167 };
168
169 static const value_string vals_sender_visibility[] = {
170     { 0x80, "Hide" },
171     { 0x81, "Show" },
172     { 0x00, NULL },
173 };
174
175 static const value_string vals_status[] = {
176     { 0x80, "Expired" },
177     { 0x81, "Retrieved" },
178     { 0x82, "Rejected" },
179     { 0x83, "Deferred" },
180     { 0x84, "Unrecognized" },
181     { 0x00, NULL },
182 };
183
184 /*!
185  * Decodes a Text-string from the protocol data
186  *      Text-string = [Quote] *TEXT End-of-string
187  *      Quote       = <Octet 127>
188  *      End-of-string = <Octet 0>
189  *
190  * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
191  *
192  * \param       tvb     The buffer with PDU-data
193  * \param       offset  Offset within that buffer
194  * \param       strval  String buffer to receive the text, reserve memory!
195  *
196  * \return              The length in bytes of the entire field
197  */
198 static guint
199 get_text_string(tvbuff_t *tvb, guint offset, char *strval)
200 {
201     guint        len;
202
203     len = tvb_strsize(tvb, offset);
204     if (tvb_get_guint8(tvb, offset) == MM_QUOTE)
205         tvb_memcpy(tvb, strval, offset + 1, len - 1);
206     else
207         tvb_memcpy(tvb, strval, offset, len);
208     return len;
209 }
210
211 /*!
212  * Decodes a Value-length from the protocol data.
213  *      Value-length = Short-length | (Length-quote Length)
214  *      Short-length = <Any octet 0-30>
215  *      Length-quote = <Octet 31>
216  *      Length       = Uintvar-integer
217  *
218  * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
219  *
220  * \param       tvb             The buffer with PDU-data
221  * \param       offset          Offset within that buffer
222  * \param       byte_count      Returns the length in bytes of
223  *                              the "Value-length" field.
224  *
225  * \return                      The actual value of "Value-length"
226  */
227 static guint
228 get_value_length(tvbuff_t *tvb, guint offset, guint *byte_count)
229 {
230     guint        field;
231
232     field = tvb_get_guint8(tvb, offset++);
233     if (field < 31)
234         *byte_count = 1;
235     else {                      /* Must be 31 so, Uintvar follows       */
236         field = tvb_get_guintvar(tvb, offset, byte_count);
237         (*byte_count)++;
238     }
239     return field;
240 }
241
242 /*!
243  * Decodes an Encoded-string-value from the protocol data
244  *      Encoded-string-value = Text-string | Value-length Char-set Text-string
245  *
246  * \param       tvb     The buffer with PDU-data
247  * \param       offset  Offset within that buffer
248  * \param       strval  String buffer to receive the text, reserve memory!
249  *
250  * \return              The length in bytes of the entire field
251  */
252 static guint
253 get_encoded_strval(tvbuff_t *tvb, guint offset, char *strval)
254 {
255     guint        field;
256     guint        length;
257     guint        count;
258
259     field = tvb_get_guint8(tvb, offset);
260
261     if (field < 32) {
262         length = get_value_length(tvb, offset, &count);
263         /* \todo        Something with "Char-set", skip for now */
264         tvb_memcpy(tvb, strval, offset + count + 1, length - 1);
265         strval[length - 1] = '\0';      /* Just to make sure    */
266         return count + length;
267     } else
268         return get_text_string(tvb, offset, strval);
269 }
270
271 /*!
272  * Decodes a Long-integer from the protocol data
273  *      Long-integer = Short-length Multi-octet-integer
274  *      Short-length = <Any octet 0-30>
275  *      Multi-octet-integer = 1*30OCTET
276  *
277  * \todo Shouldn't we be sharing this with WSP (packet-wap.c)?
278  *
279  * \param       tvb             The buffer with PDU-data
280  * \param       offset          Offset within that buffer
281  * \param       byte_count      Returns the length in bytes of the field
282  *
283  * \return                      The value of the Long-integer
284  *
285  * \note        A maximum of 4-byte integers will be handled.
286  */
287 static guint
288 get_long_integer(tvbuff_t *tvb, guint offset, guint *byte_count)
289 {
290     guint        val;
291
292     *byte_count = tvb_get_guint8(tvb, offset++);
293     switch (*byte_count) {
294         case 1:
295             val = tvb_get_guint8(tvb, offset);
296             break;
297         case 2:
298             val = tvb_get_ntohs(tvb, offset);
299             break;
300         case 3:
301             val = tvb_get_ntoh24(tvb, offset);
302             break;
303         case 4:
304             val = tvb_get_ntohl(tvb, offset);
305             break;
306         default:
307             val = 0;
308             break;
309     }
310     (*byte_count)++;
311     return val;
312 }
313
314 /* Code to actually dissect the packets */
315 static gboolean
316 dissect_mmse_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
317 {
318     guint8       pdut;
319
320     /*
321      * Check if data makes sense for it to be dissected as MMSE:  Message-type
322      * field must make sense and followed by either Transaction-Id
323      * or MMS-Version header
324      */
325     if (tvb_get_guint8(tvb, 0) != MM_MTYPE_HDR)
326         return FALSE;
327     pdut = tvb_get_guint8(tvb, 1);
328     if (match_strval(pdut, vals_message_type) == NULL)
329         return FALSE;
330     if ((tvb_get_guint8(tvb, 2) != MM_TID_HDR) &&
331         (tvb_get_guint8(tvb, 2) != MM_VERSION_HDR))
332         return FALSE;
333     dissect_mmse(tvb, pinfo, tree);
334     return TRUE;
335 }
336
337 static void
338 dissect_mmse(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
339 {
340     guint8       pdut;
341     guint        offset;
342     guint8       field = 0;
343     char         strval[BUFSIZ];
344     guint        length;
345     guint        count;
346
347     /* Set up structures needed to add the protocol subtree and manage it */
348     proto_item *ti;
349     proto_tree *mmse_tree;
350
351     pdut = tvb_get_guint8(tvb, 1);
352     /* Make entries in Protocol column and Info column on summary display */
353     if (check_col(pinfo->cinfo, COL_PROTOCOL))
354         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMSE");
355
356     if (check_col(pinfo->cinfo, COL_INFO)) {
357         col_clear(pinfo->cinfo, COL_INFO);
358         col_add_fstr(pinfo->cinfo, COL_INFO, "MMS %s",
359                      match_strval(pdut, vals_message_type));
360     }
361
362     /* In the interest of speed, if "tree" is NULL, don't do any work not
363      * necessary to generate protocol tree items.
364      */
365     if (tree) {
366         offset = 2;                     /* Skip Message-Type    */
367
368         /* create display subtree for the protocol */
369         ti = proto_tree_add_item(tree, proto_mmse, tvb, 0, -1, FALSE);
370         mmse_tree = proto_item_add_subtree(ti, ett_mmse);
371
372         /* Report PDU-type      */
373         proto_tree_add_uint(mmse_tree, hf_mmse_message_type, tvb, 0, 2, pdut);
374         /*
375          * Cycle through MMS-headers
376          */
377         while ((offset < tvb_reported_length(tvb)) &&
378                (field = tvb_get_guint8(tvb, offset++)) != MM_CTYPE_HDR)
379         {
380             switch (field)
381             {
382                 case MM_TID_HDR:                /* Text-string  */
383                     length = get_text_string(tvb, offset, strval);
384                     proto_tree_add_string(mmse_tree, hf_mmse_transaction_id,
385                                           tvb, offset - 1, length + 1,strval);
386                     offset += length;
387                     break;
388                 case MM_VERSION_HDR:            /* nibble-Major/nibble-minor*/
389                     field = tvb_get_guint8(tvb, offset++);
390                     {
391                         guint8   major, minor;
392
393                         major = (field & 0x70) >> 4;
394                         minor = field & 0x0F;
395                         if (minor == 0x0F)
396                             sprintf(strval, "%d", major);
397                         else
398                             sprintf(strval, "%d.%d", major, minor);
399                     }
400                     proto_tree_add_string(mmse_tree, hf_mmse_mms_version, tvb,
401                                           offset - 2, 2, strval);
402                     break;
403                 case MM_BCC_HDR:                /* Encoded-string-value */
404                     length = get_encoded_strval(tvb, offset, strval);
405                     proto_tree_add_string(mmse_tree, hf_mmse_bcc, tvb,
406                                         offset - 1, length + 1, strval);
407                     offset += length;
408                     break;
409                 case MM_CC_HDR:                 /* Encoded-string-value */
410                     length = get_encoded_strval(tvb, offset, strval);
411                     proto_tree_add_string(mmse_tree, hf_mmse_cc, tvb,
412                                         offset - 1, length + 1, strval);
413                     offset += length;
414                     break;
415                 case MM_CLOCATION_HDR:          /* Uri-value            */
416                     length = get_text_string(tvb, offset, strval);
417                     proto_tree_add_string(mmse_tree, hf_mmse_content_location,
418                                           tvb, offset - 1, length + 1,strval);
419                     offset += length;
420                     break;
421                 case MM_DATE_HDR:               /* Long-integer         */
422                     {
423                         guint            tval;
424                         nstime_t         tmptime;
425
426                         tval = get_long_integer(tvb, offset, &count);
427                         tmptime.secs = tval;
428                         tmptime.nsecs = 0;
429                         proto_tree_add_time(mmse_tree, hf_mmse_date, tvb,
430                                             offset - 1, count + 1, &tmptime);
431                     }
432                     offset += count;
433                     break;
434                 case MM_DREPORT_HDR:            /* Yes|No               */
435                     field = tvb_get_guint8(tvb, offset++);
436                     proto_tree_add_uint(mmse_tree, hf_mmse_delivery_report, tvb,
437                                         offset - 2, 2, field);
438                     break;
439                 case MM_DTIME_HDR:
440                     /*
441                      * Value-length(Absolute-token Date-value|
442                      *              Relative-token Delta-seconds-value)
443                      */
444                     length = get_value_length(tvb, offset, &count);
445                     field = tvb_get_guint8(tvb, offset + count);
446                     {
447                         guint            tval;
448                         nstime_t         tmptime;
449                         guint            cnt;
450
451                         tval =  get_long_integer(tvb, offset + count + 1, &cnt);
452                         tmptime.secs = tval;
453                         tmptime.nsecs = 0;
454
455                         if (field == 0x80)
456                             proto_tree_add_time(mmse_tree,
457                                                 hf_mmse_delivery_time_abs,
458                                                 tvb, offset - 1,
459                                                 length + count + 1, &tmptime);
460                         else
461                             proto_tree_add_time(mmse_tree,
462                                                 hf_mmse_delivery_time_rel,
463                                                 tvb, offset - 1,
464                                                 length + count + 1, &tmptime);
465                     }
466                     offset += length + count;
467                     break;
468                 case MM_EXPIRY_HDR:
469                     /*
470                      * Value-length(Absolute-token Date-value|
471                      *              Relative-token Delta-seconds-value)
472                      */
473                     length = get_value_length(tvb, offset, &count);
474                     field = tvb_get_guint8(tvb, offset + count);
475                     {
476                         guint            tval;
477                         nstime_t         tmptime;
478                         guint            cnt;
479
480                         tval = get_long_integer(tvb, offset + count + 1, &cnt);
481                         tmptime.secs = tval;
482                         tmptime.nsecs = 0;
483                         if (field == 0x80)
484                             proto_tree_add_time(mmse_tree, hf_mmse_expiry_abs,
485                                                 tvb, offset - 1,
486                                                 length + count + 1, &tmptime);
487                         else
488                             proto_tree_add_time(mmse_tree, hf_mmse_expiry_rel,
489                                                 tvb, offset - 1,
490                                                 length + count + 1, &tmptime);
491                     }
492                     offset += length + count;
493                     break;
494                 case MM_FROM_HDR:
495                     /*
496                      * Value-length(Address-present-token Encoded-string-value
497                      *              |Insert-address-token)
498                      */
499                     length = get_value_length(tvb, offset, &count);
500                     field = tvb_get_guint8(tvb, offset + count);
501                     if (field == 0x81) {
502                         strcpy(strval, "<insert address>");
503                     } else {
504                         (void) get_encoded_strval(tvb, offset + count + 1,
505                                                   strval);
506                     }
507                     proto_tree_add_string(mmse_tree, hf_mmse_from, tvb,
508                                           offset-1, length + count + 1, strval);
509                     offset += length + count;
510                     break;
511                 case MM_MCLASS_HDR:
512                     /*
513                      * Class-identifier|Text-string
514                      */
515                     field = tvb_get_guint8(tvb, offset);
516                     if (field & 0x80) {
517                         offset++;
518                         proto_tree_add_uint(mmse_tree,
519                                             hf_mmse_message_class_id,
520                                             tvb, offset - 2, 2, field);
521                     } else {
522                         length = get_text_string(tvb, offset, strval);
523                         proto_tree_add_string(mmse_tree,
524                                               hf_mmse_message_class_str,
525                                               tvb, offset - 1, length + 1,
526                                               strval);
527                         offset += length;
528                     }
529                     break;
530                 case MM_MID_HDR:                /* Text-string          */
531                     length = get_text_string(tvb, offset, strval);
532                     proto_tree_add_string(mmse_tree, hf_mmse_message_id, tvb,
533                                           offset - 1, length + 1, strval);
534                     offset += length;
535                     break;
536                 case MM_MSIZE_HDR:              /* Long-integer         */
537                     length = get_long_integer(tvb, offset, &count);
538                     proto_tree_add_uint(mmse_tree, hf_mmse_message_size, tvb,
539                                         offset - 1, count + 1, length);
540                     offset += count;
541                     break;
542                 case MM_PRIORITY_HDR:           /* Low|Normal|High      */
543                     field = tvb_get_guint8(tvb, offset++);
544                     proto_tree_add_uint(mmse_tree, hf_mmse_priority, tvb,
545                                         offset - 2, 2, field);
546                     break;
547                 case MM_RREPLY_HDR:             /* Yes|No               */
548                     field = tvb_get_guint8(tvb, offset++);
549                     proto_tree_add_uint(mmse_tree, hf_mmse_read_reply, tvb,
550                                         offset - 2, 2, field);
551                     break;
552                 case MM_RALLOWED_HDR:           /* Yes|No               */
553                     field = tvb_get_guint8(tvb, offset++);
554                     proto_tree_add_uint(mmse_tree, hf_mmse_report_allowed, tvb,
555                                         offset - 2, 2, field);
556                     break;
557                 case MM_RSTATUS_HDR:
558                     field = tvb_get_guint8(tvb, offset++);
559                     proto_tree_add_uint(mmse_tree, hf_mmse_response_status, tvb,
560                                         offset - 2, 2, field);
561                     break;
562                 case MM_RTEXT_HDR:              /* Encoded-string-value */
563                     length = get_encoded_strval(tvb, offset, strval);
564                     proto_tree_add_string(mmse_tree, hf_mmse_response_text, tvb,
565                                         offset - 1, length + 1, strval);
566                     offset += length;
567                     break;
568                 case MM_SVISIBILITY_HDR:        /* Hide|Show            */
569                     field = tvb_get_guint8(tvb, offset++);
570                     proto_tree_add_uint(mmse_tree,hf_mmse_sender_visibility,
571                                         tvb, offset - 2, 2, field);
572                     break;
573                 case MM_STATUS_HDR:
574                     field = tvb_get_guint8(tvb, offset++);
575                     proto_tree_add_uint(mmse_tree, hf_mmse_status, tvb,
576                                         offset - 2, 2, field);
577                     break;
578                 case MM_SUBJECT_HDR:            /* Encoded-string-value */
579                     length = get_encoded_strval(tvb, offset, strval);
580                     proto_tree_add_string(mmse_tree, hf_mmse_subject, tvb,
581                                         offset - 1, length + 1, strval);
582                     offset += length;
583                     break;
584                 case MM_TO_HDR:                 /* Encoded-string-value */
585                     length = get_encoded_strval(tvb, offset, strval);
586                     proto_tree_add_string(mmse_tree, hf_mmse_to, tvb,
587                                         offset - 1, length + 1, strval);
588                     offset += length;
589                     break;
590                 default:
591                     if (field & 0x80) {
592                         proto_tree_add_text(mmse_tree, tvb, offset - 1, 1,
593                                 "Unknown field (0x%02x)", field);
594                     } else {
595                         guint    length2;
596                         char     strval2[BUFSIZ];
597
598                         --offset;
599                         length = get_text_string(tvb, offset, strval);
600                         length2= get_text_string(tvb, offset+length, strval2);
601
602                         proto_tree_add_string_format(mmse_tree,
603                                                      hf_mmse_ffheader,
604                                                      tvb, offset,
605                                                      length + length2,
606                                                      tvb_get_ptr(tvb,offset,length + length2),
607                                                      "%s: %s",strval,strval2);
608                         offset += length + length2;
609                     }
610                     break;
611             }
612         }
613         if (field == MM_CTYPE_HDR) {
614             /*
615              * Eeehh, we're now actually back to good old WSP content-type
616              * encoding. Let's steal that from the WSP-dissector.
617              */
618             tvbuff_t    *tmp_tvb;
619             guint        type;
620             const char  *type_str;
621
622             offset = add_content_type(mmse_tree, tvb, offset, &type, &type_str);
623             tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
624             add_post_data(mmse_tree, tmp_tvb, type, type_str);
625         }
626     }
627
628     /* If this protocol has a sub-dissector call it here, see section 1.8 */
629 }
630
631
632 /* Register the protocol with Ethereal */
633
634 /* this format is required because a script is used to build the C function
635  * that calls all the protocol registration.
636  */
637 void
638 proto_register_mmse(void)
639 {
640     /* Setup list of header fields  See Section 1.6.1 for details       */
641     static hf_register_info hf[] = {
642         {   &hf_mmse_message_type,
643             {   "Message-Type", "mmse.message_type",
644                 FT_UINT8, BASE_HEX, VALS(vals_message_type), 0x00,
645                 "Specifies the transaction type. Effectively defines PDU.",
646                 HFILL
647             }
648         },
649         {   &hf_mmse_transaction_id,
650             {   "Transaction-ID", "mmse.transaction_id",
651                 FT_STRING, BASE_NONE, NULL, 0x00,
652                 "A unique identifier for this transaction. "
653                 "Identifies request and corresponding response only.",
654                 HFILL
655             }
656         },
657         {   &hf_mmse_mms_version,
658             {   "MMS-Version", "mmse.mms_version",
659                 FT_STRING, BASE_NONE, NULL, 0x00,
660                 "Version of the protocol used.",
661                 HFILL
662             }
663         },
664         {   &hf_mmse_bcc,
665             {   "Bcc", "mmse.bcc",
666                 FT_STRING, BASE_NONE, NULL, 0x00,
667                 "Blind carbon copy.",
668                 HFILL
669             }
670         },
671         {   &hf_mmse_cc,
672             {   "Cc", "mmse.cc",
673                 FT_STRING, BASE_NONE, NULL, 0x00,
674                 "Carbon copy.",
675                 HFILL
676             }
677         },
678         {   &hf_mmse_content_location,
679             {   "Content-Location", "mmse.content_location",
680                 FT_STRING, BASE_NONE, NULL, 0x00,
681                 "Defines the location of the message.",
682                 HFILL
683             }
684         },
685         {   &hf_mmse_date,
686             {   "Date", "mmse.date",
687                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
688                 "Arrival timestamp of the message or sending timestamp.",
689                 HFILL
690             }
691         },
692         {   &hf_mmse_delivery_report,
693             {   "Delivery-Report", "mmse.delivery_report",
694                 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
695                 "Whether a report of message delivery is wanted or not.",
696                 HFILL
697             }
698         },
699         {   &hf_mmse_delivery_time_abs,
700             {   "Delivery-Time", "mmse.delivery_time.abs",
701                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
702                 "The time at which message delivery is desired.",
703                 HFILL
704             }
705         },
706         {   &hf_mmse_delivery_time_rel,
707             {   "Delivery-Time", "mmse.delivery_time.rel",
708                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
709                 "The desired message delivery delay.",
710                 HFILL
711             }
712         },
713         {   &hf_mmse_expiry_abs,
714             {   "Expiry", "mmse.expiry.abs",
715                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
716                 "Time when message expires and need not be delivered anymore.",
717                 HFILL
718             }
719         },
720         {   &hf_mmse_expiry_rel,
721             {   "Expiry", "mmse.expiry.rel",
722                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
723                 "Delay before message expires and need not be delivered anymore.",
724                 HFILL
725             }
726         },
727         {   &hf_mmse_from,
728             {   "From", "mmse.from",
729                 FT_STRING, BASE_NONE, NULL, 0x00,
730                 "Address of the message sender.",
731                 HFILL
732             }
733         },
734         {   &hf_mmse_message_class_id,
735             {   "Message-Class", "mmse.message_class.id",
736                 FT_UINT8, BASE_HEX, VALS(vals_message_class), 0x00,
737                 "Of what category is the message.",
738                 HFILL
739             }
740         },
741         {   &hf_mmse_message_class_str,
742             {   "Message-Class", "mmse.message_class.str",
743                 FT_STRING, BASE_NONE, NULL, 0x00,
744                 "Of what category is the message.",
745                 HFILL
746             }
747         },
748         {   &hf_mmse_message_id,
749             {   "Message-Id", "mmse.message_id",
750                 FT_STRING, BASE_NONE, NULL, 0x00,
751                 "Unique identification of the message.",
752                 HFILL
753             }
754         },
755         {   &hf_mmse_message_size,
756             {   "Message-Size", "mmse.message_size",
757                 FT_UINT32, BASE_DEC, NULL, 0x00,
758                 "The size of the message in octets.",
759                 HFILL
760             }
761         },
762         {   &hf_mmse_priority,
763             {   "Priority", "mmse.priority",
764                 FT_UINT8, BASE_HEX, VALS(vals_priority), 0x00,
765                 "Priority of the message.",
766                 HFILL
767             }
768         },
769         {   &hf_mmse_read_reply,
770             {   "Read-Reply", "mmse.read_reply",
771                 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
772                 "Whether a read report from every recipient is wanted.",
773                 HFILL
774             }
775         },
776         {   &hf_mmse_report_allowed,
777             {   "Report-Allowed", "mmse.report_allowed",
778                 FT_UINT8, BASE_HEX, VALS(vals_yes_no), 0x00,
779                 "Sending of delivery report allowed or not.",
780                 HFILL
781             }
782         },
783         {   &hf_mmse_response_status,
784             {   "Response-Status", "mmse.response_status",
785                 FT_UINT8, BASE_HEX, VALS(vals_response_status), 0x00,
786                 "MMS-specific result of a message submission or retrieval.",
787                 HFILL
788             }
789         },
790         {   &hf_mmse_response_text,
791             {   "Response-Text", "mmse.response_text",
792                 FT_STRING, BASE_NONE, NULL, 0x00,
793                 "Additional information on MMS-specific result.",
794                 HFILL
795             }
796         },
797         {   &hf_mmse_sender_visibility,
798             {   "Sender-Visibility", "mmse.sender_visibility",
799                 FT_UINT8, BASE_HEX, VALS(vals_sender_visibility), 0x00,
800                 "Disclose sender identity to receiver or not.",
801                 HFILL
802             }
803         },
804         {   &hf_mmse_status,
805             {   "Status", "mmse.status",
806                 FT_UINT8, BASE_HEX, VALS(vals_status), 0x00,
807                 "Current status of the message.",
808                 HFILL
809             }
810         },
811         {   &hf_mmse_subject,
812             {   "Subject", "mmse.subject",
813                 FT_STRING, BASE_NONE, NULL, 0x00,
814                 "Subject of the message.",
815                 HFILL
816             }
817         },
818         {   &hf_mmse_to,
819             {   "To", "mmse.to",
820                 FT_STRING, BASE_NONE, NULL, 0x00,
821                 "Recipient(s) of the message.",
822                 HFILL
823             }
824         },
825         {   &hf_mmse_content_type,
826             {   "Data", "mmse.content_type",
827                 FT_NONE, BASE_NONE, NULL, 0x00,
828                 "Media content of the message.",
829                 HFILL
830             }
831         },
832         {   &hf_mmse_ffheader,
833             {   "Free format (not encoded) header", "mmse.ffheader",
834                 FT_STRING, BASE_NONE, NULL, 0x00,
835                 "Application header without corresponding encoding.",
836                 HFILL
837             }
838         },
839     };
840     /* Setup protocol subtree array */
841     static gint *ett[] = {
842         &ett_mmse,
843     };
844
845     /* Register the protocol name and description */
846     proto_mmse = proto_register_protocol("MMS Message Encapsulation",
847                                          "MMSE", "mmse");
848
849     /* Required function calls to register header fields and subtrees used */
850     proto_register_field_array(proto_mmse, hf, array_length(hf));
851     proto_register_subtree_array(ett, array_length(ett));
852 }
853
854 /* If this dissector uses sub-dissector registration add registration routine.
855  * This format is required because a script is used to find these routines and
856  * create the code that calls these routines.
857  */
858 void
859 proto_reg_handoff_mmse(void)
860 {
861     dissector_handle_t mmse_handle;
862
863     heur_dissector_add("wsp", dissect_mmse_heur, proto_mmse);
864     mmse_handle = create_dissector_handle(dissect_mmse, proto_mmse);
865     dissector_add("wsp.content_type.integer",
866                         MMS_CONTENT_TYPE,
867                         mmse_handle);
868     dissector_add_string("wsp.content_type.literal",
869                         "application/vnd.wap.mms-message",
870                         mmse_handle);
871     /*
872      * \todo
873      * The bearer could also be http (through the content-type field).
874      */
875     heur_dissector_add("http", dissect_mmse_heur, proto_mmse);
876 }