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