From Martin Mathieson

New protocol : MS MediaServer protocol


svn path=/trunk/; revision=14754
This commit is contained in:
Ronnie Sahlberg 2005-06-25 21:57:11 +00:00
parent df7520d2a1
commit 06df848879
4 changed files with 1000 additions and 0 deletions

View File

@ -2088,6 +2088,7 @@ Martin Mathieson <martin [AT] arca-technologies.com> {
SIP statistics tap
Show setupframe in RTP and RTCP
H.225.0 updates
MMS support (MS Media Server protocol)
}
Christian Wagner <Christian.Wagner [AT] stud.uni-karlsruhe.de> {

View File

@ -382,6 +382,8 @@ DISSECTOR_SRC = \
packet-media.c \
packet-mip.c \
packet-mip6.c \
packet-mms-control.c \
packet-mms-data.c \
packet-mmse.c \
packet-mount.c \
packet-mpeg1.c \

View File

@ -0,0 +1,691 @@
/* packet-mms-control.c
*
* Routines for MMS control message dissection
* MMS = Microsoft Media Server
*
* Copyright 2005
* Written by Martin Mathieson
*
* $Id: packet-rdt.c 14456 2005-05-27 18:35:19Z etxrab $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Information sources:
* sdp.ppona.com
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <epan/packet.h>
#include <epan/conversation.h>
#include "packet-tcp.h"
static dissector_handle_t mms_command_handle;
static gint proto_mms_command = -1;
/* Fields */
/* Command header */
static gint hf_mms_command_common_header = -1;
static gint hf_mms_command_version = -1;
static gint hf_mms_command_signature = -1;
static gint hf_mms_command_length = -1;
static gint hf_mms_command_protocol_type = -1;
static gint hf_mms_command_length_remaining = -1;
static gint hf_mms_command_sequence_number = -1;
static gint hf_mms_command_timestamp = -1;
static gint hf_mms_command_length_remaining2 = -1;
static gint hf_mms_command_to_client_id = -1;
static gint hf_mms_command_to_server_id = -1;
static gint hf_mms_command_direction = -1;
static gint hf_mms_command_prefix1 = -1;
static gint hf_mms_command_prefix2 = -1;
static gint hf_mms_command_unknown = -1;
static gint hf_mms_command_client_transport_info = -1;
static gint hf_mms_command_client_player_info = -1;
/* Subtrees */
static gint ett_mms_command = -1;
static gint ett_mms_command_common_header = -1;
#define MMS_TCP_PORT 1755
extern void mms_data_add_address(packet_info *pinfo, address *addr,
port_type pt, int port);
/* Main dissection function */
static void dissect_mms_command_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
/* Command details */
static void dissect_client_transport_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint offset, guint length_remaining);
static void dissect_client_player_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint offset, guint length_remaining);
/* Known command types */
#define SERVER_COMMAND_CONNECT_INFO 0x01
#define SERVER_COMMAND_TRANSPORT_INFO 0x02
#define SERVER_COMMAND_PROTOCOL_SELECTION_ERROR 0x03
#define SERVER_COMMAND_REQUEST_SERVER_FILE 0x05
#define SERVER_COMMAND_START_SENDING_FROM 0x07
#define SERVER_COMMAND_STOP_BUTTON_PRESSED 0x09
#define SERVER_COMMAND_CANCEL_PROTOCOL 0x0d
#define SERVER_COMMAND_HEADER_REQUEST 0x15
#define SERVER_COMMAND_TIMING_TEST_DATA_RESPONSE 0x18
#define SERVER_COMMAND_AUTHENTICATION_RESPONSE 0x1a
#define SERVER_COMMAND_NETWORK_TIMER_TEST_RESPONSE 0x1b
#define SERVER_COMMAND_ACTIVATE_FF_RW_BUTTONS 0x28
#define SERVER_COMMAND_HAVE_STOPPED_PLAYING 0x30
#define SERVER_COMMAND_LOCAL_COMPUTER_DETAILS 0x32
#define SERVER_COMMAND_MEDIA_STREAM_MBR_SELECTOR 0x33
static const value_string to_server_command_vals[] =
{
{ SERVER_COMMAND_CONNECT_INFO, "Connect info" },
{ SERVER_COMMAND_TRANSPORT_INFO, "Transport info" },
{ SERVER_COMMAND_PROTOCOL_SELECTION_ERROR, "Protocol selection error" },
{ SERVER_COMMAND_REQUEST_SERVER_FILE, "Request server file" },
{ SERVER_COMMAND_START_SENDING_FROM, "Start sending from.." },
{ SERVER_COMMAND_STOP_BUTTON_PRESSED, "Stop button pressed" },
{ SERVER_COMMAND_CANCEL_PROTOCOL, "Cancel protocol" },
{ SERVER_COMMAND_HEADER_REQUEST, "Header request" },
{ SERVER_COMMAND_TIMING_TEST_DATA_RESPONSE, "Timing test data request" },
{ SERVER_COMMAND_AUTHENTICATION_RESPONSE, "Authentication response" },
{ SERVER_COMMAND_NETWORK_TIMER_TEST_RESPONSE, "Network timer test response" },
{ SERVER_COMMAND_ACTIVATE_FF_RW_BUTTONS, "Activate FF/Rewind buttons" },
{ SERVER_COMMAND_HAVE_STOPPED_PLAYING, "Have stopped playing" },
{ SERVER_COMMAND_LOCAL_COMPUTER_DETAILS, "Local computer details" },
{ SERVER_COMMAND_MEDIA_STREAM_MBR_SELECTOR, "Media Stream MBR selector" },
{ 0, NULL }
};
#define CLIENT_COMMAND_SERVER_INFO 0x01
#define CLIENT_COMMAND_TRANSPORT_INFO_ACK 0x02
#define CLIENT_COMMAND_PROTOCOL_SELECTION_ERROR 0x03
#define CLIENT_COMMAND_SENDING_MEDIA_FILE_NOW 0x05
#define CLIENT_COMMAND_MEDIA_DETAILS 0x06
#define CLIENT_COMMAND_FF_RW 0x0a
#define CLIENT_COMMAND_SENDING_HEADER_RESPONSE 0x11
#define CLIENT_COMMAND_TIMING_TEST_DATA_RESPONSE 0x15
#define CLIENT_COMMAND_TIMING_TEST_DATA_REQUEST 0x18
#define CLIENT_COMMAND_AUTHENTICATION_CHALLENGE 0x1a
#define CLIENT_COMMAND_NETWORK_TIMER_TEST 0x1b
#define CLIENT_COMMAND_END_OF_MEDIA_STREAM 0x1e
#define CLIENT_COMMAND_MEDIA_CHANGING_INDICATOR 0x20
#define CLIENT_COMMAND_STREAM_SELECTION_INDICATOR 0x21
static const value_string to_client_command_vals[] =
{
{ CLIENT_COMMAND_SERVER_INFO, "Server info" },
{ CLIENT_COMMAND_TRANSPORT_INFO_ACK, "Transport info ack" },
{ CLIENT_COMMAND_PROTOCOL_SELECTION_ERROR, "Protocol selection error" },
{ CLIENT_COMMAND_SENDING_MEDIA_FILE_NOW, "Sending media file now" },
{ CLIENT_COMMAND_MEDIA_DETAILS, "Media details" },
{ CLIENT_COMMAND_FF_RW, "FF/Rewind" },
{ CLIENT_COMMAND_SENDING_HEADER_RESPONSE, "Sending header response" },
{ CLIENT_COMMAND_TIMING_TEST_DATA_RESPONSE, "Timing test data response" },
{ CLIENT_COMMAND_TIMING_TEST_DATA_REQUEST, "Timing test data request" },
{ CLIENT_COMMAND_AUTHENTICATION_CHALLENGE, "Authentication challenge" },
{ CLIENT_COMMAND_NETWORK_TIMER_TEST, "Network timer test" },
{ CLIENT_COMMAND_END_OF_MEDIA_STREAM, "End of media stream" },
{ CLIENT_COMMAND_MEDIA_CHANGING_INDICATOR, "Media changing indicator" },
{ CLIENT_COMMAND_STREAM_SELECTION_INDICATOR, "Stream selection indicator" },
{ 0, NULL }
};
/* Command direction */
#define TO_SERVER 0x03
#define TO_CLIENT 0x04
static const value_string command_direction_vals[] =
{
{ TO_SERVER, "To Server"},
{ TO_CLIENT, "To Client"},
{ 0, NULL }
};
/**************************************************************************/
/* Packet dissection functions */
/**************************************************************************/
static void dissect_mms_command_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
gint offset = 0;
proto_item *ti = NULL;
proto_tree *mms_tree = NULL;
proto_tree *mms_common_command_tree = NULL;
guint32 sequence_number;
guint16 command_id;
guint16 command_dir;
guint32 length_remaining;
/* Set columns */
if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMS-c");
}
if (check_col(pinfo->cinfo, COL_INFO))
{
col_set_str(pinfo->cinfo, COL_INFO, "Control: ");
}
/* Create MMS control protocol tree */
if (tree)
{
ti = proto_tree_add_item(tree, proto_mms_command, tvb, offset, -1, FALSE);
mms_tree = proto_item_add_subtree(ti, ett_mms_command);
}
/*************************/
/* Common command header */
/* Add a tree for common header */
if (tree)
{
ti = proto_tree_add_string(mms_tree, hf_mms_command_common_header, tvb, offset, -1,
"");
mms_common_command_tree = proto_item_add_subtree(ti, ett_mms_command_common_header);
}
/* Format of 1st 4 bytes unknown. May be version... */
offset += 4;
/* Rude signature */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_signature, tvb, offset, 4, TRUE);
offset += 4;
/* Length of command */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_length, tvb, offset, 4, TRUE);
offset += 4;
/* Protocol name */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_protocol_type, tvb, offset, 4, TRUE);
offset += 4;
/* Remaining length in multiples of 8 bytes */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_length_remaining, tvb, offset, 4, TRUE);
offset += 4;
/* Sequence number */
sequence_number = tvb_get_letohl(tvb, offset);
proto_tree_add_item(mms_common_command_tree, hf_mms_command_sequence_number, tvb, offset, 4, TRUE);
offset += 4;
/* Timestamp */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_timestamp, tvb, offset, 8, TRUE);
offset += 8;
/* Another length remaining field... */
length_remaining = tvb_get_letohl(tvb, offset);
proto_tree_add_item(mms_common_command_tree, hf_mms_command_length_remaining2, tvb, offset, 4, TRUE);
offset += 4;
/* Command ID */
command_dir = tvb_get_letohs(tvb, offset+2);
command_id = tvb_get_letohs(tvb, offset);
proto_tree_add_item(mms_common_command_tree,
(command_id == TO_SERVER) ?
hf_mms_command_to_server_id :
hf_mms_command_to_client_id,
tvb, offset, 2, TRUE);
offset += 2;
/* Command direction */
proto_tree_add_item(mms_common_command_tree, hf_mms_command_direction, tvb, offset, 2, TRUE);
offset += 2;
/* This is the end of the common command header */
proto_item_set_len(mms_common_command_tree, offset);
/* Show summary in info column */
if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
col_append_fstr(pinfo->cinfo, COL_INFO,
"s=%03u: %s %s",
sequence_number,
(command_dir == TO_SERVER) ? "-->" : "<--",
(command_dir == TO_SERVER) ?
val_to_str(command_id, to_server_command_vals, "Unknown") :
val_to_str(command_id, to_client_command_vals, "Unknown"));
}
/* Adjust this value for passing to command-specific details */
length_remaining = (length_remaining*8) - 8;
/* Now parse command-specific params */
if (command_dir == TO_SERVER)
{
/* Commands to server */
switch (command_id)
{
case SERVER_COMMAND_TRANSPORT_INFO:
dissect_client_transport_info(tvb, pinfo, mms_tree,
offset, length_remaining);
break;
case SERVER_COMMAND_CONNECT_INFO:
dissect_client_player_info(tvb, pinfo, mms_tree,
offset, length_remaining);
break;
/* TODO: other commands */
default:
break;
}
}
else
{
/* Commands to client */
switch (command_id)
{
/* TODO commands: */
default:
break;
}
}
}
/* Return the number of bytes in this PDU */
static guint32 get_mms_command_pdu_len(tvbuff_t *tvb, gint offset)
{
return tvb_get_letohl(tvb, offset+8) + 16;
}
/* Dissect a TCP command PDU */
static void dissect_mms_command_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
tcp_dissect_pdus(tvb, pinfo, tree,
TRUE, /* i.e. always desegment */
12, /* Must have 12 bytes to determine length */
get_mms_command_pdu_len,
dissect_mms_command_pdu);
}
/******************************/
/* Individual command details */
/******************************/
/* Transport information (address, port, etc) */
void dissect_client_transport_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint offset, guint length_remaining)
{
char *transport_info = "";
guint ipaddr[4];
char protocol[3];
guint port;
int fields_matched;
/* These are flags */
proto_tree_add_item(tree, hf_mms_command_prefix1, tvb, offset, 4, TRUE);
offset += 4;
proto_tree_add_item(tree, hf_mms_command_prefix1, tvb, offset, 4, TRUE);
offset += 4;
/* These 12 bytes are not understood */
proto_tree_add_item(tree, hf_mms_command_unknown, tvb, offset, 4, TRUE);
offset += 4;
proto_tree_add_item(tree, hf_mms_command_unknown, tvb, offset, 4, TRUE);
offset += 4;
proto_tree_add_item(tree, hf_mms_command_unknown, tvb, offset, 4, TRUE);
offset += 4;
/* Extract and show the string in tree and info column */
transport_info = tvb_fake_unicode(tvb, offset, (length_remaining - 20)/2, TRUE);
proto_tree_add_string_format(tree, hf_mms_command_client_transport_info, tvb,
offset, length_remaining-20,
transport_info, "Transport: (%s)", transport_info);
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", transport_info);
}
/* Extract details from this string */
fields_matched = sscanf(transport_info, "%*c%*c%u.%u.%u.%u%*c%3s%*c%u",
&ipaddr[0], &ipaddr[1], &ipaddr[2], &ipaddr[3],
protocol, &port);
/* Use this information to set up a conversation for the data stream */
if (fields_matched == 6)
{
port_type pt = PT_NONE;
/* Work out the port type */
if (strncmp(protocol, "UDP", 3) == 0)
{
pt = PT_UDP;
}
/* TODO: add when tested with capture
else
if (strncmp(protocol, "TCP", 3) == 0)
{
pt = PT_TCP;
}
*/
/* Set the dissector for indicated conversation */
if (pt != PT_NONE)
{
guint8 octets[4] = {ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]};
address addr = {AT_IPv4, 4, octets};
mms_data_add_address(pinfo, &addr, pt, port);
}
}
/* Can now free this string */
if (transport_info != NULL && strlen(transport_info))
{
g_free(transport_info);
}
}
/* Player (client) information */
void dissect_client_player_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint offset, guint length_remaining)
{
char *player_info = "";
/* These are flags */
proto_tree_add_item(tree, hf_mms_command_prefix1, tvb, offset, 4, TRUE);
offset += 4;
proto_tree_add_item(tree, hf_mms_command_prefix1, tvb, offset, 4, TRUE);
offset += 4;
/* These 4 bytes are not understood */
proto_tree_add_item(tree, hf_mms_command_unknown, tvb, offset, 4, TRUE);
offset += 4;
/* Extract and show the string in tree and info column */
player_info = tvb_fake_unicode(tvb, offset, (length_remaining - 12)/2, TRUE);
proto_tree_add_string_format(tree, hf_mms_command_client_player_info, tvb,
offset, length_remaining-12,
player_info, "Player details: (%s)", player_info);
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", player_info);
}
/* Can now free this string */
if (player_info != NULL && strlen(player_info))
{
g_free(player_info);
}
}
/*************************/
/* Register protocol */
void proto_register_mms_command(void)
{
static hf_register_info hf[] =
{
{
&hf_mms_command_common_header,
{
"Command common header",
"mms.command.common-header",
FT_STRING,
BASE_NONE,
NULL,
0x0,
"MMS command common header", HFILL
}
},
{
&hf_mms_command_version,
{
"Version",
"mms.command.version",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_signature,
{
"Command signature",
"mms.command.signature",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_length,
{
"Command length",
"mms.command.length",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_protocol_type,
{
"Protocol type",
"mms.command.protocol-type",
FT_STRING,
BASE_NONE,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_length_remaining,
{
"Length until end (8-byte blocks)",
"mms.command.length-remaining",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_sequence_number,
{
"Sequence number",
"mms.command.sequence-number",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_timestamp,
{
"Time stamp (s)",
"mms.command.timestamp",
FT_DOUBLE,
BASE_NONE,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_length_remaining2,
{
"Length until end (8-byte blocks)",
"mms.command.length-remaining2",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_to_server_id,
{
"Command",
"mms.command.to-server-id",
FT_UINT16,
BASE_HEX,
VALS(to_server_command_vals),
0x0,
"", HFILL
}
},
{
&hf_mms_command_to_client_id,
{
"Command",
"mms.command.to-client-id",
FT_UINT16,
BASE_HEX,
VALS(to_client_command_vals),
0x0,
"", HFILL
}
},
{
&hf_mms_command_direction,
{
"Command direction",
"mms.command.direction",
FT_UINT16,
BASE_HEX,
VALS(command_direction_vals),
0x0,
"", HFILL
}
},
{
&hf_mms_command_prefix1,
{
"Prefix 1",
"mms.command.prefix1",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_prefix2,
{
"Prefix 2",
"mms.command.prefix2",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_unknown,
{
"Unknown",
"mms.command.unknown",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_client_transport_info,
{
"Client transport info",
"mms.command.client-transport-info",
FT_STRING,
BASE_NONE,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_command_client_player_info,
{
"Player info",
"mms.command.player-info",
FT_STRING,
BASE_NONE,
NULL,
0x0,
"", HFILL
}
}
};
static gint *ett[] =
{
&ett_mms_command,
&ett_mms_command_common_header
};
/* Register protocol and fields */
proto_mms_command = proto_register_protocol("Microsoft Media Server Control",
"MMS-c", "mms-c");
proto_register_field_array(proto_mms_command, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("mms-c", dissect_mms_command_pdu, proto_mms_command);
}
void proto_reg_handoff_mms_command(void)
{
mms_command_handle = create_dissector_handle(dissect_mms_command_tcp,
proto_mms_command);
dissector_add("tcp.port", MMS_TCP_PORT, mms_command_handle);
}

View File

@ -0,0 +1,306 @@
/* packet-mms-data.c
*
* Routines for MMS data message dissection
* MMS = Microsoft Media Server
*
* Copyright 2005
* Written by Martin Mathieson
*
* $Id: packet-rdt.c 14456 2005-05-27 18:35:19Z etxrab $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Information sources:
* sdp.ppona.com
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <epan/packet.h>
#include <epan/conversation.h>
static dissector_handle_t mms_data_handle;
static gint proto_mms_data = -1;
/* Fields */
/* Pre-header fields */
static gint hf_mms_data_sequence_number = -1;
static gint hf_mms_data_packet_id_type = -1;
static gint hf_mms_data_packet_length = -1;
/* UDP command fields */
static gint hf_mms_data_header_id = -1;
static gint hf_mms_data_client_id = -1;
static gint hf_mms_data_command_id = -1;
static gint hf_mms_data_packet_to_resend = -1;
static gint ett_mms_data = -1;
#define MMS_UDP_COMMAND_PORT 1755
/* Parse the only known UDP command (0x01) */
static void dissect_mms_data_udp_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
gint offset = 0;
/* Header ID */
proto_tree_add_item(tree, hf_mms_data_header_id, tvb, offset, 4, TRUE);
offset += 4;
/* Client ID */
proto_tree_add_item(tree, hf_mms_data_client_id, tvb, offset, 4, TRUE);
offset += 4;
/* Command ID */
proto_tree_add_item(tree, hf_mms_data_command_id, tvb, offset, 2, TRUE);
offset += 4;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_add_str(pinfo->cinfo, COL_INFO, "Request to resend packet(s):");
}
/* Show list of packets to resend */
while (tvb_length_remaining(tvb, offset) >= 4)
{
guint32 packet_number = tvb_get_letohl(tvb, offset);
proto_tree_add_item(tree, hf_mms_data_packet_to_resend, tvb, offset, 4, TRUE);
offset += 4;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " %u", packet_number);
}
}
}
/****************************************************************************/
/* Main dissection function */
/****************************************************************************/
static void dissect_mms_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
gint offset = 0;
proto_item *ti = NULL;
proto_tree *mms_tree = NULL;
guint32 sequence_number;
guint16 packet_length;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MMS-d");
}
/* Create MMS data protocol tree */
if (tree)
{
ti = proto_tree_add_item(tree, proto_mms_data, tvb, offset, -1, FALSE);
mms_tree = proto_item_add_subtree(ti, ett_mms_data);
}
/* May be the command asking for packets to be resent */
if ((pinfo->ptype == PT_UDP) && (pinfo->destport == MMS_UDP_COMMAND_PORT))
{
dissect_mms_data_udp_command(tvb, pinfo, mms_tree);
return;
}
/* Sequence number */
sequence_number = tvb_get_letohl(tvb, offset);
proto_tree_add_item(mms_tree, hf_mms_data_sequence_number, tvb, offset, 4, TRUE);
offset += 4;
/* Packet ID type */
proto_tree_add_item(mms_tree, hf_mms_data_packet_id_type, tvb, offset, 1, TRUE);
offset++;
/* TODO: flags depending upon whether UDP or TCP */
offset++;
/* Packet Length */
packet_length = tvb_get_letohs(tvb, offset);
proto_tree_add_item(mms_tree, hf_mms_data_packet_length, tvb, offset, 2, TRUE);
offset += 2;
/* Show summary in info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_add_fstr(pinfo->cinfo, COL_INFO, "Data: s=%05u, l=%05u",
sequence_number, packet_length);
}
}
/* Set up an MMS-d conversation */
void mms_data_add_address(packet_info *pinfo, address *addr, port_type pt, int port)
{
address null_addr;
conversation_t* p_conv;
/* If this isn't the first time this packet has been processed,
* we've already done this work, so we don't need to do it
* again. */
if (pinfo->fd->flags.visited)
{
return;
}
SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
/* Check if the ip address and port combination is not
* already registered as a conversation. */
p_conv = find_conversation(pinfo->fd->num, addr, &null_addr, pt, port, 0,
NO_ADDR_B | NO_PORT_B);
/* If not, create a new conversation. */
if (!p_conv)
{
p_conv = conversation_new(pinfo->fd->num, addr, &null_addr, pt,
(guint32)port, 0, NO_ADDR2 | NO_PORT2);
}
/* Set dissector */
conversation_set_dissector(p_conv, mms_data_handle);
}
/**************************/
/* Register protocol */
void proto_register_mms_data(void)
{
static hf_register_info hf[] =
{
{
&hf_mms_data_sequence_number,
{
"Sequence number",
"mms.data.sequence",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_packet_id_type,
{
"Packet ID type",
"mms.data.packet-id-type",
FT_UINT8,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_packet_length,
{
"Packet length",
"mms.data.packet-length",
FT_UINT16,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_header_id,
{
"Header ID",
"mms.data.header-id",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_client_id,
{
"Client ID",
"mms.data.client-id",
FT_UINT32,
BASE_HEX,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_command_id,
{
"Command ID",
"mms.data.command-id",
FT_UINT16,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_mms_data_packet_to_resend,
{
"Packet to resend",
"mms.data.packet-to-resend",
FT_UINT32,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
};
static gint *ett[] =
{
&ett_mms_data
};
/* Register protocol and fields */
proto_mms_data = proto_register_protocol("Microsoft Media Server Data",
"MMS-d", "mms-d");
proto_register_field_array(proto_mms_data, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("mms-d", dissect_mms_data, proto_mms_data);
}
void proto_reg_handoff_mms_data(void)
{
mms_data_handle = find_dissector("mms-d");
dissector_add_handle("udp.port", mms_data_handle);
dissector_add_handle("tcp.port", mms_data_handle);
dissector_add("udp.port", MMS_UDP_COMMAND_PORT, mms_data_handle);
}