2 * Routines for Message Session Relay Protocol(MSRP) dissection
3 * Copyright 2005, Anders Broman <anders.broman[at]ericsson.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
26 * http://www.ietf.org/internet-drafts/draft-ietf-simple-message-sessions-10.txt
39 #include <epan/conversation.h>
41 #include <epan/packet.h>
42 #include <epan/emem.h>
45 #include "packet-msrp.h"
47 #define TCP_PORT_MSRP 0
49 #define MSRP_HDR "MSRP"
50 #define MSRP_HDR_LEN (strlen (MSRP_HDR))
52 /* Initialize the protocol and registered fields */
53 static int proto_msrp = -1;
55 /* Initialize the subtree pointers */
56 static int ett_msrp = -1;
57 static int ett_raw_text = -1;
58 static int ett_msrp_reqresp = -1;
59 static int ett_msrp_hdr = -1;
60 static int ett_msrp_element = -1;
61 static int ett_msrp_data = -1;
62 static int ett_msrp_end_line = -1;
63 static int ett_msrp_setup = -1;
65 static int hf_msrp_response_line = -1;
66 static int hf_msrp_request_line = -1;
67 static int hf_msrp_transactionID = -1;
68 static int hf_msrp_method = -1;
69 static int hf_msrp_status_code = -1;
70 static int hf_msrp_msg_hdr = -1;
71 static int hf_msrp_end_line = -1;
72 static int hf_msrp_cnt_flg = -1;
74 static int hf_msrp_data = -1;
76 /* MSRP setup fields */
77 static int hf_msrp_setup = -1;
78 static int hf_msrp_setup_frame = -1;
79 static int hf_msrp_setup_method = -1;
85 static const msrp_header_t msrp_headers[] = {
87 { "From-Path"}, /* 1 */
89 { "Message-ID"}, /* 3 */
90 { "Success-Report"}, /* 4 */
91 { "Failure-Report"}, /* 5 */
92 { "Byte-Range"}, /* 6 */
94 { "Content-Type"}, /* 8 */
95 { "Content-ID"}, /* 9 */
96 { "Content-Description"}, /* 10 */
97 { "Content-Disposition"}, /* 11 */
98 { "Use-Path"}, /* 12 */
99 { "WWW-Authenticate"}, /* 13 */
100 { "Authorization"}, /* 14 */
101 { "Authentication-Info"}, /* 15 */
104 static gint hf_header_array[] = {
105 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
106 -1, /* 1"From-Path */
108 -1, /* 3"Message-ID" */
109 -1, /* 4"Success-Report" */
110 -1, /* 5"Failure-Report" */
111 -1, /* 6"Byte-Range" */
113 -1, /* 8"Content-Type" */
114 -1, /* 9"Content-ID" */
115 -1, /* 10"Content-Description" */
116 -1, /* 11"Content-Disposition" */
117 -1, /* 12"Use-Path" */
118 -1, /* 13"WWW-Authenticate" */
119 -1, /* 14"Authorization" */
120 -1, /* 15"Authentication-Info" */
123 #define MSRP_FROM_PATH 1
124 #define MSRP_TO_PATH 2
125 #define MSRP_MESSAGE_ID 3
126 #define MSRP_SUCCESS_REPORT 4
127 #define MSRP_FAILURE_REPORT 5
128 #define MSRP_BYTE_RANGE 6
129 #define MSRP_STATUS 7
130 #define MSRP_CONTENT_TYPE 8
131 #define MSRP_CONTENT_ID 9
132 #define MSRP_CONTENT_DISCRIPTION 10
133 #define MSRP_CONTENT_DISPOSITION 11
134 #define MSRP_USE_PATH 12
135 #define MSRP_WWW_AUTHENTICATE 13
136 #define MSRP_AUTHORIZATION 14
137 #define MSRP_AUTHENTICATION_INFO 15
139 static dissector_handle_t msrp_handle;
140 gboolean global_msrp_raw_text = TRUE;
142 /* MSRP content type and internet media type used by other dissectors
143 * are the same. List of media types from IANA at:
144 * http://www.iana.org/assignments/media-types/index.html */
145 static dissector_table_t media_type_dissector_table;
147 static int dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
150 /* Displaying conversation setup info */
151 static gboolean global_msrp_show_setup_info = TRUE;
152 static void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
154 /* Set up an MSRP conversation using the info given */
155 void msrp_add_address( packet_info *pinfo,
156 address *addr, int port,
157 const gchar *setup_method, guint32 setup_frame_number)
160 conversation_t* p_conv;
161 struct _msrp_conversation_info *p_conv_data = NULL;
164 * If this isn't the first time this packet has been processed,
165 * we've already done this work, so we don't need to do it
168 if (pinfo->fd->flags.visited)
173 SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
176 * Check if the ip address and port combination is not
177 * already registered as a conversation.
179 p_conv = find_conversation( pinfo->fd->num, addr, &null_addr, PT_TCP, port, 0,
180 NO_ADDR_B | NO_PORT_B);
183 * If not, create a new conversation.
186 p_conv = conversation_new( pinfo->fd->num, addr, &null_addr, PT_TCP,
188 NO_ADDR2 | NO_PORT2);
192 conversation_set_dissector(p_conv, msrp_handle);
195 * Check if the conversation has data associated with it.
197 p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);
200 * If not, add a new data item.
203 /* Create conversation data */
204 p_conv_data = se_alloc(sizeof(struct _msrp_conversation_info));
209 memset(p_conv_data, 0, sizeof(struct _msrp_conversation_info));
210 conversation_add_proto_data(p_conv, proto_msrp, p_conv_data);
214 * Update the conversation data.
216 p_conv_data->setup_method_set = TRUE;
217 strncpy(p_conv_data->setup_method, setup_method, MAX_MSRP_SETUP_METHOD_SIZE);
218 p_conv_data->setup_method[MAX_MSRP_SETUP_METHOD_SIZE] = '\0';
219 p_conv_data->setup_frame_number = setup_frame_number;
224 /* Look for conversation info and display any setup info found */
225 void show_setup_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
227 /* Conversation and current data */
228 conversation_t *p_conv = NULL;
229 struct _msrp_conversation_info *p_conv_data = NULL;
231 /* Use existing packet data if available */
232 p_conv_data = p_get_proto_data(pinfo->fd, proto_msrp);
236 /* First time, get info from conversation */
237 p_conv = find_conversation(pinfo->fd->num, &pinfo->net_dst, &pinfo->net_src,
239 pinfo->destport, pinfo->srcport, 0);
243 /* Look for data in conversation */
244 struct _msrp_conversation_info *p_conv_packet_data;
245 p_conv_data = conversation_get_proto_data(p_conv, proto_msrp);
249 /* Save this conversation info into packet info */
250 p_conv_packet_data = se_alloc(sizeof(struct _msrp_conversation_info));
251 if (!p_conv_packet_data)
255 memcpy(p_conv_packet_data, p_conv_data,
256 sizeof(struct _msrp_conversation_info));
258 p_add_proto_data(pinfo->fd, proto_msrp, p_conv_packet_data);
263 /* Create setup info subtree with summary info. */
264 if (p_conv_data && p_conv_data->setup_method_set)
266 proto_tree *msrp_setup_tree;
267 proto_item *ti = proto_tree_add_string_format(tree, hf_msrp_setup, tvb, 0, 0,
269 "Stream setup by %s (frame %u)",
270 p_conv_data->setup_method,
271 p_conv_data->setup_frame_number);
272 PROTO_ITEM_SET_GENERATED(ti);
273 msrp_setup_tree = proto_item_add_subtree(ti, ett_msrp_setup);
276 /* Add details into subtree */
277 proto_item* item = proto_tree_add_uint(msrp_setup_tree, hf_msrp_setup_frame,
278 tvb, 0, 0, p_conv_data->setup_frame_number);
279 PROTO_ITEM_SET_GENERATED(item);
280 item = proto_tree_add_string(msrp_setup_tree, hf_msrp_setup_method,
281 tvb, 0, 0, p_conv_data->setup_method);
282 PROTO_ITEM_SET_GENERATED(item);
289 /* Returns index of headers */
290 static gint msrp_is_known_msrp_header(tvbuff_t *tvb, int offset, guint header_len)
294 for (i = 1; i < array_length(msrp_headers); i++) {
295 if (header_len == strlen(msrp_headers[i].name) &&
296 tvb_strncaseeql(tvb, offset, msrp_headers[i].name, header_len) == 0)
307 * Display the entire message as raw text.
310 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
312 int offset, next_offset, linelen;
315 while (tvb_offset_exists(tvb, offset)) {
316 /* 'desegment' is FALSE so will set next_offset to beyond the end of
317 the buffer if no line ending is found */
318 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
319 linelen = next_offset - offset;
321 proto_tree_add_text(tree, tvb, offset, linelen,
322 "%s", tvb_format_text(tvb, offset, linelen));
324 offset = next_offset;
328 /* This code is modeled on the code in packet-sip.c
329 * ABNF code for the MSRP header:
330 * The following syntax specification uses the augmented Backus-Naur
331 * Form (BNF) as described in RFC-2234 [6].
334 * msrp-req-or-resp = msrp-request / msrp-response
335 * msrp-request = req-start headers [content-stuff] end-line
336 * msrp-response = resp-start headers end-line
338 * req-start = pMSRP SP transact-id SP method CRLF
339 * resp-start = pMSRP SP transact-id SP status-code [SP phrase] CRLF
342 * pMSRP = %x4D.53.52.50 ; MSRP in caps
343 * transact-id = ident
344 * method = mSEND / mREPORT / other-method
345 * mSEND = %x53.45.4e.44 ; SEND in caps
346 * mREPORT = %x52.45.50.4f.52.54; REPORT in caps
347 * other-method = 1*UPALPHA
349 * "MSRP 1234 SEND(CRLF)"
350 * "MSRP 1234 200 OK(CRLF)
353 check_msrp_header(tvbuff_t *tvb)
358 gint next_offset = 0;
363 * Note that "tvb_find_line_end()" will return a value that
364 * is not longer than what's in the buffer, so the
365 * "tvb_get_ptr()" calls below won't throw exceptions. *
368 linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
369 /* Find the first SP */
370 space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
372 if (space_offset <= 0) {
374 * Either there's no space in the line (which means
375 * the line is empty or doesn't have a token followed
376 * by a space; neither is valid for a request or response), or
377 * the first character in the line is a space ( which isn't valid
378 * for a MSRP header.)
383 token_1_len = space_offset;
384 token_2_start = space_offset + 1;
385 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
386 if (space_offset == -1) {
388 * There's no space after the second token, so we don't
389 * have a third token.
394 * Is the first token "MSRP"?
396 if (token_1_len == MSRP_HDR_LEN && tvb_strneql(tvb, 0, MSRP_HDR, MSRP_HDR_LEN) == 0){
397 /* This check can be made more strict but accept we do have MSRP for now */
405 * end-line = "-------" transact-id continuation-flag CRLF
406 * This code is modeled on the code in packet-multipart.c
409 find_end_line(tvbuff_t *tvb, gint start)
411 gint offset = start, next_offset, linelen;
413 while (tvb_length_remaining(tvb, offset) > 0) {
414 /* 'desegment' is FALSE so will set next_offset to beyond the end of
415 the buffer if no line ending is found */
416 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
420 if (tvb_strneql(tvb, next_offset, (const gchar *)"-------", 7) == 0)
422 offset = next_offset;
429 dissect_msrp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
432 conversation_t* conversation;
434 if ( check_msrp_header(tvb)){
436 * TODO Set up conversation here
438 if (pinfo->fd->flags.visited){
439 /* Look for existing conversation */
440 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
441 pinfo->srcport, pinfo->destport, 0);
442 /* Create new one if not found */
443 if (conversation == NULL){
444 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
445 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
447 conversation_set_dissector(conversation, msrp_handle);
450 offset = dissect_msrp(tvb, pinfo, tree);
456 /* Code to actually dissect the packets */
458 dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
461 gint next_offset = 0;
462 proto_item *ti, *th, *msrp_headers_item, *msrp_element_item;
463 proto_tree *msrp_tree, *reqresp_tree, *raw_tree, *msrp_hdr_tree, *msrp_end_tree;
464 proto_tree *msrp_element_tree, *msrp_data_tree;
471 gint token_4_start = 0;
472 guint token_4_len = 0;
473 gboolean is_msrp_response;
474 gint end_line_offset;
476 gint line_end_offset;
477 gint message_end_offset;
479 char *transaction_id_str = NULL;
486 gboolean have_body = FALSE;
487 gboolean found_match = FALSE;
488 gint content_type_len, content_type_parameter_str_len;
489 char *media_type_str = NULL;
490 char *media_type_str_lower_case = NULL;
491 char *content_type_parameter_str = NULL;
493 gint parameter_offset;
494 gint semi_colon_offset;
496 if ( !check_msrp_header(tvb)){
499 /* We have a MSRP header with at least three tokens
501 * Note that "tvb_find_line_end()" will return a value that
502 * is not longer than what's in the buffer, so the
503 * "tvb_get_ptr()" calls below won't throw exceptions. *
506 linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
508 /* Find the first SP and skip the first token */
509 token_2_start = tvb_find_guint8(tvb, 0, linelen, ' ') + 1;
511 /* Work out 2nd token's length by finding next space */
512 space_offset = tvb_find_guint8(tvb, token_2_start, linelen-token_2_start, ' ');
513 token_2_len = space_offset - token_2_start;
515 /* Transaction ID found store it for later use */
516 transaction_id_str = tvb_get_ephemeral_string(tvb, token_2_start, token_2_len);
518 /* Look for another space in this line to indicate a 4th token */
519 token_3_start = space_offset + 1;
520 space_offset = tvb_find_guint8(tvb, token_3_start,linelen-token_3_start, ' ');
521 if ( space_offset == -1){
522 /* 3rd token runs to the end of the line */
523 token_3_len = linelen - token_3_start;
525 /* We have a fourth token */
526 token_3_len = space_offset - token_3_start;
527 token_4_start = space_offset + 1;
528 token_4_len = linelen - token_4_start;
532 * Yes, so this is either a msrp-request or msrp-response.
533 * To be a msrp-response, the second token must be
536 is_msrp_response = FALSE;
537 if (token_3_len == 3) {
538 if (isdigit(tvb_get_guint8(tvb, token_3_start)) &&
539 isdigit(tvb_get_guint8(tvb, token_3_start + 1)) &&
540 isdigit(tvb_get_guint8(tvb, token_3_start + 2))) {
541 is_msrp_response = TRUE;
545 /* Make entries in Protocol column and Info column on summary display */
546 if (check_col(pinfo->cinfo, COL_PROTOCOL))
547 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSRP");
548 if (is_msrp_response){
549 if (check_col(pinfo->cinfo, COL_INFO)) {
550 col_add_fstr(pinfo->cinfo, COL_INFO, "Response: %s ",
551 tvb_format_text(tvb, token_3_start, token_3_len));
554 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
555 tvb_format_text(tvb, token_4_start, token_4_len));
557 col_append_fstr(pinfo->cinfo, COL_INFO, "Transaction ID: %s",
558 tvb_format_text(tvb, token_2_start, token_2_len));
561 if (check_col(pinfo->cinfo, COL_INFO)) {
562 proto_tree_add_text(tree, tvb, token_3_start, token_3_len,
563 "Col %s L=%u", tvb_format_text(tvb, token_3_start, token_3_len),token_3_len);
565 col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s ",
566 tvb_format_text(tvb, token_3_start, token_3_len));
568 col_append_fstr(pinfo->cinfo, COL_INFO, "Transaction ID: %s",
569 tvb_format_text(tvb, token_2_start, token_2_len));
573 /* Find the end line to be able to process the headers
574 * Note that in case of [content-stuff] headers and [content-stuff] is separated by CRLF
577 offset = next_offset;
578 end_line_offset = find_end_line(tvb,offset);
579 /* TODO if -1 (No end line found, is returned do something) */
580 end_line_len = tvb_find_line_end(tvb, end_line_offset, -1, &next_offset, FALSE);
581 message_end_offset = end_line_offset + end_line_len + 2;
585 ti = proto_tree_add_item(tree, proto_msrp, tvb, 0, message_end_offset, FALSE);
586 msrp_tree = proto_item_add_subtree(ti, ett_msrp);
588 if (is_msrp_response){
589 th = proto_tree_add_item(msrp_tree,hf_msrp_response_line,tvb,0,linelen,FALSE);
590 reqresp_tree = proto_item_add_subtree(th, ett_msrp_reqresp);
591 proto_tree_add_item(reqresp_tree,hf_msrp_transactionID,tvb,token_2_start,token_2_len,FALSE);
592 proto_tree_add_uint(reqresp_tree,hf_msrp_status_code,tvb,token_3_start,token_3_len,
593 atoi(tvb_get_string(tvb, token_3_start, token_3_len)));
596 th = proto_tree_add_item(msrp_tree,hf_msrp_request_line,tvb,0,linelen,FALSE);
597 reqresp_tree = proto_item_add_subtree(th, ett_msrp_reqresp);
598 proto_tree_add_item(reqresp_tree,hf_msrp_transactionID,tvb,token_2_start,token_2_len,FALSE);
599 proto_tree_add_item(reqresp_tree,hf_msrp_method,tvb,token_3_start,token_3_len,FALSE);
602 /* Conversation setup info */
603 if (global_msrp_show_setup_info)
605 show_setup_info(tvb, pinfo, msrp_tree);
609 msrp_headers_item = proto_tree_add_item(msrp_tree, hf_msrp_msg_hdr, tvb, offset,(end_line_offset - offset), FALSE);
610 msrp_hdr_tree = proto_item_add_subtree(msrp_headers_item, ett_msrp_hdr);
613 * Process the headers
615 while (tvb_reported_length_remaining(tvb, offset) > 0 && offset < end_line_offset ) {
616 /* 'desegment' is FALSE so will set next_offset to beyond the end of
617 the buffer if no line ending is found */
618 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
621 * This is a blank line separating the
622 * message header from the message body.
627 line_end_offset = offset + linelen;
628 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
629 if (colon_offset == -1) {
631 * Malformed header - no colon after the name.
633 proto_tree_add_text(msrp_hdr_tree, tvb, offset,
634 next_offset - offset, "%s",
635 tvb_format_text(tvb, offset, linelen));
637 header_len = colon_offset - offset;
638 hf_index = msrp_is_known_msrp_header(tvb, offset, header_len);
640 if (hf_index == -1) {
641 proto_tree_add_text(msrp_hdr_tree, tvb,
642 offset, next_offset - offset, "%s",
643 tvb_format_text(tvb, offset, linelen));
646 * Skip whitespace after the colon.
648 value_offset = colon_offset + 1;
649 while (value_offset < line_end_offset &&
650 ((c = tvb_get_guint8(tvb, value_offset)) == ' ' ||
656 value_len = line_end_offset - value_offset;
657 value = tvb_get_ephemeral_string(tvb, value_offset,
661 * Add it to the protocol tree,
662 * but display the line as is.
664 msrp_element_item = proto_tree_add_string_format(msrp_hdr_tree,
665 hf_header_array[hf_index], tvb,
666 offset, next_offset - offset,
668 tvb_format_text(tvb, offset, linelen));
669 msrp_element_tree = proto_item_add_subtree( msrp_element_item, ett_msrp_element);
671 switch ( hf_index ) {
673 case MSRP_CONTENT_TYPE :
674 content_type_len = value_len;
675 semi_colon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';');
676 if ( semi_colon_offset != -1) {
677 parameter_offset = semi_colon_offset +1;
679 * Skip whitespace after the semicolon.
681 while (parameter_offset < line_end_offset
682 && ((c = tvb_get_guint8(tvb, parameter_offset)) == ' '
685 content_type_len = semi_colon_offset - value_offset;
686 content_type_parameter_str_len = line_end_offset - parameter_offset;
687 content_type_parameter_str = tvb_get_ephemeral_string(tvb,
688 parameter_offset, content_type_parameter_str_len);
690 media_type_str = tvb_get_ephemeral_string(tvb, value_offset, content_type_len);
691 #if GLIB_MAJOR_VERSION < 2
692 media_type_str_lower_case = g_strdup(media_type_str);
693 g_strdown(media_type_str_lower_case);
695 media_type_str_lower_case = g_ascii_strdown(media_type_str, -1);
704 offset = next_offset;
709 * There's a message body starting at "next_offset".
710 * Set the length of the header item.
712 proto_item_set_end(msrp_headers_item, tvb, next_offset);
714 /* Create new tree & tvb for data */
715 next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
716 ti = proto_tree_add_item(msrp_tree, hf_msrp_data, tvb,
717 next_offset, -1, FALSE);
718 msrp_data_tree = proto_item_add_subtree(ti, ett_msrp_data);
720 /* give the content type parameters to sub dissectors */
722 if ( media_type_str_lower_case != NULL ) {
723 void *save_private_data = pinfo->private_data;
724 pinfo->private_data = content_type_parameter_str;
725 found_match = dissector_try_string(media_type_dissector_table,
726 media_type_str_lower_case,
729 g_free(media_type_str_lower_case);
730 pinfo->private_data = save_private_data;
731 /* If no match dump as text */
733 if ( found_match != TRUE )
736 while (tvb_offset_exists(next_tvb, offset)) {
737 tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE);
738 linelen = next_offset - offset;
739 proto_tree_add_text(msrp_data_tree, next_tvb, offset, linelen,
740 "%s", tvb_format_text(next_tvb, offset, linelen));
741 offset = next_offset;
750 ti = proto_tree_add_item(msrp_tree,hf_msrp_end_line,tvb,end_line_offset,end_line_len,FALSE);
751 msrp_end_tree = proto_item_add_subtree(ti, ett_msrp_end_line);
753 proto_tree_add_item(msrp_end_tree,hf_msrp_transactionID,tvb,end_line_offset + 7,token_2_len,FALSE);
754 /* continuation-flag */
755 proto_tree_add_item(msrp_end_tree,hf_msrp_cnt_flg,tvb,end_line_offset+end_line_len-1,1,FALSE);
757 if (global_msrp_raw_text){
758 ti = proto_tree_add_text(tree, tvb, 0, -1,"Message Session Relay Protocol(as raw text)");
759 raw_tree = proto_item_add_subtree(ti, ett_msrp);
760 tvb_raw_text_add(tvb,raw_tree);
764 return message_end_offset;
765 /* return tvb_length(tvb); */
767 /* If this protocol has a sub-dissector call it here, see section 1.8 */
771 /* Register the protocol with Wireshark */
772 /* If this dissector uses sub-dissector registration add a registration routine.
773 This format is required because a script is used to find these routines and
774 create the code that calls these routines.
777 proto_reg_handoff_msrp(void)
779 msrp_handle = new_create_dissector_handle(dissect_msrp, proto_msrp);
780 dissector_add("tcp.port", 0, msrp_handle);
781 heur_dissector_add("tcp", dissect_msrp_heur, proto_msrp);
785 proto_register_msrp(void)
787 /* Setup protocol subtree array */
788 static gint *ett[] = {
799 /* Setup list of header fields */
800 static hf_register_info hf[] = {
801 { &hf_msrp_request_line,
802 { "Request Line", "msrp.request.line",
803 FT_STRING, BASE_NONE,NULL,0x0,
804 "Request Line", HFILL }
806 { &hf_msrp_response_line,
807 { "Response Line", "msrp.response.line",
808 FT_STRING, BASE_NONE,NULL,0x0,
809 "Response Line", HFILL }
811 { &hf_msrp_transactionID,
812 { "Transaction Id", "msrp.transaction.id",
813 FT_STRING, BASE_NONE,NULL,0x0,
814 "Transaction Id", HFILL }
817 { "Method", "msrp.method",
818 FT_STRING, BASE_NONE,NULL,0x0,
821 { &hf_msrp_status_code,
822 { "Status code", "msrp.status.code",
823 FT_UINT16, BASE_DEC,NULL,0x0,
824 "Status code", HFILL }
827 { "Message Header", "msrp.msg.hdr",
829 "Message Header", HFILL }
832 { "End Line", "msrp.end.line",
833 FT_STRING, BASE_NONE,NULL,0x0,
837 { "Continuation-flag", "msrp.cnt.flg",
838 FT_STRING, BASE_NONE,NULL,0x0,
839 "Continuation-flag", HFILL }
841 { &hf_header_array[MSRP_FROM_PATH],
842 { "From Path", "msrp.from.path",
843 FT_STRING, BASE_NONE,NULL,0x0,
846 { &hf_header_array[MSRP_TO_PATH],
847 { "To Path", "msrp.to.path",
848 FT_STRING, BASE_NONE,NULL,0x0,
851 { &hf_header_array[MSRP_MESSAGE_ID],
852 { "Message ID", "msrp.messageid",
853 FT_STRING, BASE_NONE,NULL,0x0,
854 "Message ID", HFILL }
856 { &hf_header_array[MSRP_SUCCESS_REPORT],
857 { "Success Report", "msrp.success.report",
858 FT_STRING, BASE_NONE,NULL,0x0,
859 "Success Report", HFILL }
861 { &hf_header_array[MSRP_FAILURE_REPORT],
862 { "Failure Report", "msrp.failure.report",
863 FT_STRING, BASE_NONE,NULL,0x0,
864 "Failure Report", HFILL }
866 { &hf_header_array[MSRP_BYTE_RANGE],
867 { "Byte Range", "msrp.byte.range",
868 FT_STRING, BASE_NONE,NULL,0x0,
869 "Byte Range", HFILL }
871 { &hf_header_array[MSRP_STATUS],
872 { "Status", "msrp.status",
873 FT_STRING, BASE_NONE,NULL,0x0,
876 { &hf_header_array[MSRP_CONTENT_TYPE],
877 { "Content-Type", "msrp.content.type",
878 FT_STRING, BASE_NONE,NULL,0x0,
879 "Content-Type", HFILL }
881 { &hf_header_array[MSRP_CONTENT_ID],
882 { "Content-ID", "msrp.content.id",
883 FT_STRING, BASE_NONE,NULL,0x0,
884 "Content-ID", HFILL }
886 { &hf_header_array[MSRP_CONTENT_DISCRIPTION],
887 { "Content-Description", "msrp.content.description",
888 FT_STRING, BASE_NONE,NULL,0x0,
889 "Content-Description", HFILL }
891 { &hf_header_array[MSRP_CONTENT_DISPOSITION],
892 { "Content-Disposition", "msrp.content.disposition",
893 FT_STRING, BASE_NONE,NULL,0x0,
894 "Content-Disposition", HFILL }
896 { &hf_header_array[MSRP_USE_PATH],
897 { "Use-Path", "msrp.use.path",
898 FT_STRING, BASE_NONE,NULL,0x0,
901 { &hf_header_array[MSRP_WWW_AUTHENTICATE],
902 { "WWW-Authenticate", "msrp.www.authenticate",
903 FT_STRING, BASE_NONE,NULL,0x0,
904 "WWW-Authenticate", HFILL }
906 { &hf_header_array[MSRP_AUTHORIZATION],
907 { "Authorization", "msrp.authorization",
908 FT_STRING, BASE_NONE,NULL,0x0,
909 "Authorization", HFILL }
911 { &hf_header_array[MSRP_AUTHENTICATION_INFO],
912 { "Authentication-Info", "msrp.authentication.info",
913 FT_STRING, BASE_NONE,NULL,0x0,
914 "Authentication-Info", HFILL }
917 { "Data", "msrp.data",
918 FT_STRING, BASE_NONE, NULL, 0x0,
922 { "Stream setup", "msrp.setup",
923 FT_STRING, BASE_NONE, NULL, 0x0,
924 "Stream setup, method and frame number", HFILL}
926 { &hf_msrp_setup_frame,
927 { "Setup frame", "msrp.setup-frame",
928 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
929 "Frame that set up this stream", HFILL}
931 { &hf_msrp_setup_method,
932 { "Setup Method", "msrp.setup-method",
933 FT_STRING, BASE_NONE, NULL, 0x0,
934 "Method used to set up this stream", HFILL}
938 module_t *msrp_module;
939 /* Register the protocol name and description */
940 proto_msrp = proto_register_protocol("Message Session Relay Protocol","MSRP", "msrp");
942 /* Required function calls to register the header fields and subtrees used */
943 proto_register_field_array(proto_msrp, hf, array_length(hf));
944 proto_register_subtree_array(ett, array_length(ett));
946 media_type_dissector_table = find_dissector_table("media_type");
948 msrp_module = prefs_register_protocol(proto_msrp, NULL);
950 prefs_register_bool_preference(msrp_module, "display_raw_text",
951 "Display raw text for MSRP message",
952 "Specifies that the raw text of the "
953 "MSRP message should be displayed "
954 "in addition to the dissection tree",
955 &global_msrp_raw_text);
957 prefs_register_bool_preference(msrp_module, "show_setup_info",
958 "Show stream setup information",
959 "Where available, show which protocol and frame caused "
960 "this MSRP stream to be created",
961 &global_msrp_show_setup_info);
965 * Register the dissector by name, so other dissectors can
966 * grab it by name rather than just referring to it directly.
968 new_register_dissector("msrp", dissect_msrp, proto_msrp);