wireshark/packet-dsi.c
Guy Harris 857318d3b7 Use "tvb_get_string()" instead of allocating a (len+1)-sized buffer,
"tvb_memcpy()"ing to it, and putting in a null terminator;
"tvb_get_string()" will check whether all bytes of the string are
present before allocating the buffer, so that you don't leak memory if
the copy throws an exception, and don't crash if the length is absurdly
large.

Use "tvb_memdup()" instead of allocating a buffer and "tvb_memcpy()"ing
to it, so that an exception is thrown before you try to allocate the
buffer (for the same reasons as listed above).

Before allocating a buffer used when processing a chunk of data from a
packet, get a pointer to the chunk with "tvb_get_ptr()", or check that
the data is all there with "tvb_ensure_bytes_exist()", so that an
exception is thrown before you try to allocate the buffer (for the same
reasons as listed above).

Fix up the lengths of the tvbuff used when dissecting ONC RPC opaque data
with a particular dissector.

svn path=/trunk/; revision=10236
2004-02-25 09:31:07 +00:00

847 lines
26 KiB
C

/* packet-dsi.c
* Routines for dsi packet dissection
* Copyright 2001, Randy McEoin <rmceoin@pe.com>
*
* $Id: packet-dsi.c,v 1.30 2004/02/25 09:31:05 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Copied from packet-pop.c
*
* 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <glib.h>
#include <epan/packet.h>
#include "prefs.h"
#include "packet-tcp.h"
#include "packet-afp.h"
/* The information in this module (DSI) comes from:
AFP 2.1 & 2.2.pdf contained in AppleShare_IP_6.3_SDK
available from http://www.apple.com
The netatalk source code by Wesley Craig & Adrian Sun
* What a Data Stream Interface packet looks like:
* 0 32
* |-------------------------------|
* |flags |command| requestID |
* |-------------------------------|
* |error code/enclosed data offset|
* |-------------------------------|
* |total data length |
* |-------------------------------|
* |reserved field |
* |-------------------------------|
*/
static int proto_dsi = -1;
static int hf_dsi_flags = -1;
static int hf_dsi_command = -1;
static int hf_dsi_requestid = -1;
static int hf_dsi_offset = -1;
static int hf_dsi_error = -1;
static int hf_dsi_length = -1;
static int hf_dsi_reserved = -1;
static gint ett_dsi = -1;
static int hf_dsi_open_type = -1;
static int hf_dsi_open_len = -1;
static int hf_dsi_open_quantum = -1;
static int hf_dsi_open_option = -1;
static int hf_dsi_attn_flag = -1;
static int hf_dsi_attn_flag_shutdown = -1;
static int hf_dsi_attn_flag_crash = -1;
static int hf_dsi_attn_flag_msg = -1;
static int hf_dsi_attn_flag_reconnect = -1;
static int hf_dsi_attn_flag_time = -1;
static int hf_dsi_attn_flag_bitmap = -1;
static gint ett_dsi_open = -1;
static gint ett_dsi_attn = -1;
static gint ett_dsi_attn_flag = -1;
static const value_string dsi_attn_flag_vals[] = {
{0x0, "Reserved" }, /* 0000 */
{0x1, "Reserved" }, /* 0001 */
{0x2, "Server message" }, /* 0010 */
{0x3, "Server notification, cf. extended bitmap" }, /* 0011 */
{0x4, "Server is shutting down, internal error" }, /* 0100 */
{0x8, "Server is shutting down" }, /* 1000 */
{0x9, "Server disconnects user" }, /* 1001 */
{0x10,"Server is shutting down, message" }, /* 1010 */
{0x11,"Server is shutting down, message,no reconnect"}, /* 1011 */
{0, NULL } };
static const value_string dsi_open_type_vals[] = {
{0, "Server quantum" },
{1, "Attention quantum" },
{0, NULL } };
/* status stuff same for asp and afp */
static int hf_dsi_server_name = -1;
static int hf_dsi_utf8_server_name_len = -1;
static int hf_dsi_utf8_server_name = -1;
static int hf_dsi_server_type = -1;
static int hf_dsi_server_vers = -1;
static int hf_dsi_server_uams = -1;
static int hf_dsi_server_icon = -1;
static int hf_dsi_server_directory = -1;
static int hf_dsi_server_flag = -1;
static int hf_dsi_server_flag_copyfile = -1;
static int hf_dsi_server_flag_passwd = -1;
static int hf_dsi_server_flag_no_save_passwd = -1;
static int hf_dsi_server_flag_srv_msg = -1;
static int hf_dsi_server_flag_srv_sig = -1;
static int hf_dsi_server_flag_tcpip = -1;
static int hf_dsi_server_flag_notify = -1;
static int hf_dsi_server_flag_reconnect = -1;
static int hf_dsi_server_flag_directory = -1;
static int hf_dsi_server_flag_utf8_name = -1;
static int hf_dsi_server_flag_fast_copy = -1;
static int hf_dsi_server_signature = -1;
static int hf_dsi_server_addr_len = -1;
static int hf_dsi_server_addr_type = -1;
static int hf_dsi_server_addr_value = -1;
static gint ett_dsi_status = -1;
static gint ett_dsi_uams = -1;
static gint ett_dsi_vers = -1;
static gint ett_dsi_addr = -1;
static gint ett_dsi_addr_line = -1;
static gint ett_dsi_directory = -1;
static gint ett_dsi_utf8_name = -1;
static gint ett_dsi_status_server_flag = -1;
const value_string afp_server_addr_type_vals[] = {
{1, "IP address" },
{2, "IP+port address" },
{3, "DDP address" },
{4, "DNS name" },
{5, "IP+port ssh tunnel" },
{0, NULL } };
/* end status stuff */
/* desegmentation of DSI */
static gboolean dsi_desegment = TRUE;
static dissector_handle_t data_handle;
static dissector_handle_t afp_handle;
#define TCP_PORT_DSI 548
#define DSI_BLOCKSIZ 16
/* DSI flags */
#define DSIFL_REQUEST 0x00
#define DSIFL_REPLY 0x01
#define DSIFL_MAX 0x01
/* DSI Commands */
#define DSIFUNC_CLOSE 1 /* DSICloseSession */
#define DSIFUNC_CMD 2 /* DSICommand */
#define DSIFUNC_STAT 3 /* DSIGetStatus */
#define DSIFUNC_OPEN 4 /* DSIOpenSession */
#define DSIFUNC_TICKLE 5 /* DSITickle */
#define DSIFUNC_WRITE 6 /* DSIWrite */
#define DSIFUNC_ATTN 8 /* DSIAttention */
#define DSIFUNC_MAX 8 /* largest command */
static const value_string flag_vals[] = {
{DSIFL_REQUEST, "Request" },
{DSIFL_REPLY, "Reply" },
{0, NULL } };
static const value_string func_vals[] = {
{DSIFUNC_CLOSE, "CloseSession" },
{DSIFUNC_CMD, "Command" },
{DSIFUNC_STAT, "GetStatus" },
{DSIFUNC_OPEN, "OpenSession" },
{DSIFUNC_TICKLE, "Tickle" },
{DSIFUNC_WRITE, "Write" },
{DSIFUNC_ATTN, "Attention" },
{0, NULL } };
static gint
dissect_dsi_open_session(tvbuff_t *tvb, proto_tree *dsi_tree, gint offset)
{
proto_tree *tree;
proto_item *ti;
guint8 type;
guint8 len;
ti = proto_tree_add_text(dsi_tree, tvb, offset, -1, "Open Session");
tree = proto_item_add_subtree(ti, ett_dsi_open);
type = tvb_get_guint8(tvb, offset);
proto_tree_add_item(tree, hf_dsi_open_type, tvb, offset, 1, FALSE);
offset++;
len = tvb_get_guint8(tvb, offset);
proto_tree_add_item(tree, hf_dsi_open_len, tvb, offset, 1, FALSE);
offset++;
if (type <= 1) {
proto_tree_add_item(tree, hf_dsi_open_quantum, tvb, offset, 4, FALSE);
}
else {
proto_tree_add_item(tree, hf_dsi_open_option, tvb, offset, len, FALSE);
}
offset += len;
return offset;
}
static gint
dissect_dsi_attention(tvbuff_t *tvb, proto_tree *dsi_tree, gint offset)
{
proto_tree *tree;
proto_item *ti;
guint16 flag;
if (!tvb_reported_length_remaining(tvb,offset))
return offset;
flag = tvb_get_ntohs(tvb, offset);
ti = proto_tree_add_text(dsi_tree, tvb, offset, -1, "Attention");
tree = proto_item_add_subtree(ti, ett_dsi_attn);
ti = proto_tree_add_item(tree, hf_dsi_attn_flag, tvb, offset, 2, FALSE);
tree = proto_item_add_subtree(ti, ett_dsi_attn_flag);
proto_tree_add_item(tree, hf_dsi_attn_flag_shutdown, tvb, offset, 2, FALSE);
proto_tree_add_item(tree, hf_dsi_attn_flag_crash, tvb, offset, 2, FALSE);
proto_tree_add_item(tree, hf_dsi_attn_flag_msg, tvb, offset, 2, FALSE);
proto_tree_add_item(tree, hf_dsi_attn_flag_reconnect, tvb, offset, 2, FALSE);
/* FIXME */
if ((flag & 0xf000) != 0x3000)
proto_tree_add_item(tree, hf_dsi_attn_flag_time, tvb, offset, 2, FALSE);
else
proto_tree_add_item(tree, hf_dsi_attn_flag_bitmap, tvb, offset, 2, FALSE);
offset += 2;
return offset;
}
/* -----------------------------
from netatalk/etc/afpd/status.c
*/
static gint
dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
{
proto_tree *sub_tree;
proto_item *ti;
guint16 ofs;
guint16 flag;
guint16 sign_ofs = 0;
guint16 adr_ofs = 0;
guint16 dir_ofs = 0;
guint16 utf_ofs = 0;
guint8 nbe;
guint8 len;
guint8 i;
if (!tree)
return offset;
ti = proto_tree_add_text(tree, tvb, offset, -1, "Get Status");
tree = proto_item_add_subtree(ti, ett_dsi_status);
ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
proto_tree_add_text(tree, tvb, offset +AFPSTATUS_MACHOFF, 2, "Machine offset: %d", ofs);
ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
proto_tree_add_text(tree, tvb, offset +AFPSTATUS_VERSOFF, 2, "Version offset: %d", ofs);
ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
proto_tree_add_text(tree, tvb, offset +AFPSTATUS_UAMSOFF, 2, "UAMS offset: %d", ofs);
ofs = tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
proto_tree_add_text(tree, tvb, offset +AFPSTATUS_ICONOFF, 2, "Icon offset: %d", ofs);
ofs = offset +AFPSTATUS_FLAGOFF;
ti = proto_tree_add_item(tree, hf_dsi_server_flag, tvb, ofs, 2, FALSE);
sub_tree = proto_item_add_subtree(ti, ett_dsi_status_server_flag);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_copyfile , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_passwd , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_no_save_passwd, tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_msg , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_srv_sig , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_tcpip , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_notify , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_reconnect , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_directory , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_utf8_name , tvb, ofs, 2, FALSE);
proto_tree_add_item(sub_tree, hf_dsi_server_flag_fast_copy , tvb, ofs, 2, FALSE);
proto_tree_add_item(tree, hf_dsi_server_name, tvb, offset +AFPSTATUS_PRELEN, 1, FALSE);
flag = tvb_get_ntohs(tvb, ofs);
if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1;
if ((ofs & 1))
ofs++;
sign_ofs = tvb_get_ntohs(tvb, ofs);
proto_tree_add_text(tree, tvb, ofs, 2, "Signature offset: %d", sign_ofs);
sign_ofs += offset;
if ((flag & AFPSRVRINFO_TCPIP)) {
ofs += 2;
adr_ofs = tvb_get_ntohs(tvb, ofs);
proto_tree_add_text(tree, tvb, ofs, 2, "Network address offset: %d", adr_ofs);
adr_ofs += offset;
}
if ((flag & AFPSRVRINFO_SRVDIRECTORY)) {
ofs += 2;
dir_ofs = tvb_get_ntohs(tvb, ofs);
proto_tree_add_text(tree, tvb, ofs, 2, "Directory services offset: %d", dir_ofs);
dir_ofs += offset;
}
if ((flag & AFPSRVRINFO_SRVUTF8)) {
ofs += 2;
utf_ofs = tvb_get_ntohs(tvb, ofs);
proto_tree_add_text(tree, tvb, ofs, 2, "UTF8 server name offset: %d", utf_ofs);
utf_ofs += offset;
}
}
ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_MACHOFF);
if (ofs)
proto_tree_add_item(tree, hf_dsi_server_type, tvb, ofs, 1, FALSE);
ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_VERSOFF);
if (ofs) {
nbe = tvb_get_guint8(tvb, ofs);
ti = proto_tree_add_text(tree, tvb, ofs, 1, "Version list: %d", nbe);
ofs++;
sub_tree = proto_item_add_subtree(ti, ett_dsi_vers);
for (i = 0; i < nbe; i++) {
len = tvb_get_guint8(tvb, ofs);
proto_tree_add_item(sub_tree, hf_dsi_server_vers, tvb, ofs, 1, FALSE);
ofs += len + 1;
}
}
ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
if (ofs) {
nbe = tvb_get_guint8(tvb, ofs);
ti = proto_tree_add_text(tree, tvb, ofs, 1, "UAMS list: %d", nbe);
ofs++;
sub_tree = proto_item_add_subtree(ti, ett_dsi_uams);
for (i = 0; i < nbe; i++) {
len = tvb_get_guint8(tvb, ofs);
proto_tree_add_item(sub_tree, hf_dsi_server_uams, tvb, ofs, 1, FALSE);
ofs += len + 1;
}
}
ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_ICONOFF);
if (ofs)
proto_tree_add_item(tree, hf_dsi_server_icon, tvb, ofs, 256, FALSE);
if (sign_ofs) {
proto_tree_add_item(tree, hf_dsi_server_signature, tvb, sign_ofs, 16, FALSE);
}
if (adr_ofs) {
proto_tree *adr_tree;
char *tmp;
const guint8 *ip;
guint16 net;
guint8 node;
guint16 port;
ofs = adr_ofs;
nbe = tvb_get_guint8(tvb, ofs);
ti = proto_tree_add_text(tree, tvb, ofs, 1, "Address list: %d", nbe);
ofs++;
adr_tree = proto_item_add_subtree(ti, ett_dsi_addr);
for (i = 0; i < nbe; i++) {
guint8 type;
len = tvb_get_guint8(tvb, ofs);
type = tvb_get_guint8(tvb, ofs +1);
switch (type) {
case 1: /* IP */
ip = tvb_get_ptr(tvb, ofs+2, 4);
ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip: %s", ip_to_str(ip));
break;
case 2: /* IP + port */
ip = tvb_get_ptr(tvb, ofs+2, 4);
port = tvb_get_ntohs(tvb, ofs+6);
ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ip %s:%d",ip_to_str(ip),port);
break;
case 3: /* DDP, atalk_addr_to_str want host order not network */
net = tvb_get_ntohs(tvb, ofs+2);
node = tvb_get_guint8(tvb, ofs +4);
port = tvb_get_guint8(tvb, ofs +5);
ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "ddp: %u.%u:%u",
net, node, port);
break;
case 4: /* DNS */
case 5: /* SSH tunnel */
if (len > 2) {
tmp = tvb_get_string(tvb, ofs +2, len -2);
ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "%s: %s",
(type==4)?"dns":"ssh tunnel", tmp);
g_free(tmp);
break;
}
else {
ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Malformed address type %d", type);
}
break;
default:
ti = proto_tree_add_text(adr_tree, tvb, ofs, len,"Unknow type : %d", type);
break;
}
len -= 2;
sub_tree = proto_item_add_subtree(ti,ett_dsi_addr_line);
proto_tree_add_item(sub_tree, hf_dsi_server_addr_len, tvb, ofs, 1, FALSE);
ofs++;
proto_tree_add_item(sub_tree, hf_dsi_server_addr_type, tvb, ofs, 1, FALSE);
ofs++;
proto_tree_add_item(sub_tree, hf_dsi_server_addr_value,tvb, ofs, len, FALSE);
ofs += len;
}
}
if (dir_ofs) {
ofs = dir_ofs;
nbe = tvb_get_guint8(tvb, ofs);
ti = proto_tree_add_text(tree, tvb, ofs, 1, "Directory services list: %d", nbe);
ofs++;
sub_tree = proto_item_add_subtree(ti, ett_dsi_directory);
for (i = 0; i < nbe; i++) {
len = tvb_get_guint8(tvb, ofs);
proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, FALSE);
ofs += len + 1;
}
}
if (utf_ofs) {
guint16 ulen;
char *tmp;
ofs = utf_ofs;
ulen = tvb_get_ntohs(tvb, ofs);
tmp = tvb_get_string(tvb, ofs + 2, ulen);
ti = proto_tree_add_text(tree, tvb, ofs, ulen + 2, "UTF8 server name: %s", tmp);
sub_tree = proto_item_add_subtree(ti, ett_dsi_utf8_name);
proto_tree_add_uint(sub_tree, hf_dsi_utf8_server_name_len, tvb, ofs, 2, ulen);
ofs += 2;
proto_tree_add_string(sub_tree, hf_dsi_utf8_server_name, tvb, ofs, ulen, tmp);
ofs += ulen;
g_free(tmp);
}
return offset;
}
static void
dissect_dsi_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *dsi_tree;
proto_item *ti;
guint8 dsi_flags,dsi_command;
guint16 dsi_requestid;
gint32 dsi_code;
guint32 dsi_length;
guint32 dsi_reserved;
struct aspinfo aspinfo;
gint col_info;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
col_info = check_col(pinfo->cinfo, COL_INFO);
if (col_info)
col_clear(pinfo->cinfo, COL_INFO);
dsi_flags = tvb_get_guint8(tvb, 0);
dsi_command = tvb_get_guint8(tvb, 1);
dsi_requestid = tvb_get_ntohs(tvb, 2);
dsi_code = tvb_get_ntohl(tvb, 4);
dsi_length = tvb_get_ntohl(tvb, 8);
dsi_reserved = tvb_get_ntohl(tvb, 12);
if (col_info) {
col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%u)",
val_to_str(dsi_flags, flag_vals,
"Unknown flag (0x%02x)"),
val_to_str(dsi_command, func_vals,
"Unknown function (0x%02x)"),
dsi_requestid);
}
if (tree) {
ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, FALSE);
dsi_tree = proto_item_add_subtree(ti, ett_dsi);
proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb,
0, 1, dsi_flags);
proto_tree_add_uint(dsi_tree, hf_dsi_command, tvb,
1, 1, dsi_command);
proto_tree_add_uint(dsi_tree, hf_dsi_requestid, tvb,
2, 2, dsi_requestid);
switch (dsi_flags) {
case DSIFL_REQUEST:
proto_tree_add_int(dsi_tree, hf_dsi_offset, tvb,
4, 4, dsi_code);
break;
case DSIFL_REPLY:
proto_tree_add_int(dsi_tree, hf_dsi_error, tvb,
4, 4, dsi_code);
break;
}
proto_tree_add_uint_format(dsi_tree, hf_dsi_length, tvb,
8, 4, dsi_length,
"Length: %u bytes", dsi_length);
proto_tree_add_uint(dsi_tree, hf_dsi_reserved, tvb,
12, 4, dsi_reserved);
}
else
dsi_tree = tree;
switch (dsi_command) {
case DSIFUNC_OPEN:
if (tree) {
dissect_dsi_open_session(tvb, dsi_tree, DSI_BLOCKSIZ);
}
break;
case DSIFUNC_ATTN:
if (tree) {
dissect_dsi_attention(tvb, dsi_tree, DSI_BLOCKSIZ);
}
break;
case DSIFUNC_STAT:
if (tree && (dsi_flags == DSIFL_REPLY)) {
dissect_dsi_reply_get_status(tvb, dsi_tree, DSI_BLOCKSIZ);
}
break;
case DSIFUNC_CMD:
case DSIFUNC_WRITE:
{
tvbuff_t *new_tvb;
int len = tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ);
aspinfo.reply = (dsi_flags == DSIFL_REPLY);
aspinfo.command = dsi_command;
aspinfo.seq = dsi_requestid;
aspinfo.code = dsi_code;
pinfo->private_data = &aspinfo;
proto_item_set_len(dsi_tree, DSI_BLOCKSIZ);
new_tvb = tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,len);
call_dissector(afp_handle, new_tvb, pinfo, tree);
}
break;
default:
if (tree) {
call_dissector(data_handle,
tvb_new_subset(tvb, DSI_BLOCKSIZ, -1, -1),
pinfo, dsi_tree);
}
break;
}
}
static guint
get_dsi_pdu_len(tvbuff_t *tvb, int offset)
{
guint32 plen;
guint8 dsi_flags,dsi_command;
dsi_flags = tvb_get_guint8(tvb, offset);
dsi_command = tvb_get_guint8(tvb, offset+ 1);
if ( dsi_flags > DSIFL_MAX || !dsi_command || dsi_command > DSIFUNC_MAX)
{
/* it's not a known dsi pdu start sequence */
return tvb_length_remaining(tvb, offset);
}
/*
* Get the length of the DSI packet.
*/
plen = tvb_get_ntohl(tvb, offset+8);
/*
* That length doesn't include the length of the header itself;
* add that in.
*/
return plen + 16;
}
static void
dissect_dsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
tcp_dissect_pdus(tvb, pinfo, tree, dsi_desegment, 12,
get_dsi_pdu_len, dissect_dsi_packet);
}
void
proto_register_dsi(void)
{
static hf_register_info hf[] = {
{ &hf_dsi_flags,
{ "Flags", "dsi.flags",
FT_UINT8, BASE_HEX, VALS(flag_vals), 0x0,
"Indicates request or reply.", HFILL }},
{ &hf_dsi_command,
{ "Command", "dsi.command",
FT_UINT8, BASE_DEC, VALS(func_vals), 0x0,
"Represents a DSI command.", HFILL }},
{ &hf_dsi_requestid,
{ "Request ID", "dsi.requestid",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Keeps track of which request this is. Replies must match a Request. IDs must be generated in sequential order.", HFILL }},
{ &hf_dsi_offset,
{ "Data offset", "dsi.data_offset",
FT_INT32, BASE_DEC, NULL, 0x0,
"Data offset", HFILL }},
{ &hf_dsi_error,
{ "Error code", "dsi.error_code",
FT_INT32, BASE_DEC, VALS(asp_error_vals), 0x0,
"Error code", HFILL }},
{ &hf_dsi_length,
{ "Length", "dsi.length",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Total length of the data that follows the DSI header.", HFILL }},
{ &hf_dsi_reserved,
{ "Reserved", "dsi.reserved",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Reserved for future use. Should be set to zero.", HFILL }},
/* asp , afp */
{ &hf_dsi_utf8_server_name_len,
{ "Length", "dsi.utf8_server_name_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"UTF8 server name length.", HFILL }},
{ &hf_dsi_utf8_server_name,
{ "UTF8 Server name", "dsi.utf8_server_name",
FT_STRING, BASE_NONE, NULL, 0x0,
"UTF8 Server name", HFILL }},
{ &hf_dsi_server_name,
{ "Server name", "dsi.server_name",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
"Server name", HFILL }},
{ &hf_dsi_server_type,
{ "Server type", "dsi.server_type",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
"Server type", HFILL }},
{ &hf_dsi_server_vers,
{ "AFP version", "dsi.server_vers",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
"AFP version", HFILL }},
{ &hf_dsi_server_uams,
{ "UAM", "dsi.server_uams",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
"UAM", HFILL }},
{ &hf_dsi_server_icon,
{ "Icon bitmap", "dsi.server_icon",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Server icon bitmap", HFILL }},
{ &hf_dsi_server_directory,
{ "Directory service", "dsi.server_directory",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
"Server directory service", HFILL }},
{ &hf_dsi_server_signature,
{ "Server signature", "dsi.server_signature",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Server signature", HFILL }},
{ &hf_dsi_server_flag,
{ "Flag", "dsi.server_flag",
FT_UINT16, BASE_HEX, NULL, 0x0,
"Server capabilities flag", HFILL }},
{ &hf_dsi_server_flag_copyfile,
{ "Support copyfile", "dsi.server_flag.copyfile",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_COPY,
"Server support copyfile", HFILL }},
{ &hf_dsi_server_flag_passwd,
{ "Support change password", "dsi.server_flag.passwd",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_PASSWD,
"Server support change password", HFILL }},
{ &hf_dsi_server_flag_no_save_passwd,
{ "Don't allow save password", "dsi.server_flag.no_save_passwd",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_NOSAVEPASSWD,
"Don't allow save password", HFILL }},
{ &hf_dsi_server_flag_srv_msg,
{ "Support server message", "dsi.server_flag.srv_msg",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVMSGS,
"Support server message", HFILL }},
{ &hf_dsi_server_flag_srv_sig,
{ "Support server signature", "dsi.server_flag.srv_sig",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVSIGNATURE,
"Support server signature", HFILL }},
{ &hf_dsi_server_flag_tcpip,
{ "Support TCP/IP", "dsi.server_flag.tcpip",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_TCPIP,
"Server support TCP/IP", HFILL }},
{ &hf_dsi_server_flag_notify,
{ "Support server notifications", "dsi.server_flag.notify",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVNOTIFY,
"Server support notifications", HFILL }},
{ &hf_dsi_server_flag_reconnect,
{ "Support server reconnect", "dsi.server_flag.reconnect",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVRECONNECT,
"Server support reconnect", HFILL }},
{ &hf_dsi_server_flag_directory,
{ "Support directory services", "dsi.server_flag.directory",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVDIRECTORY,
"Server support directory services", HFILL }},
{ &hf_dsi_server_flag_utf8_name,
{ "Support UTF8 server name", "dsi.server_flag.utf8_name",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_SRVUTF8,
"Server support UTF8 server name", HFILL }},
{ &hf_dsi_server_flag_fast_copy,
{ "Support fast copy", "dsi.server_flag.fast_copy",
FT_BOOLEAN, 16, NULL, AFPSRVRINFO_FASTBOZO,
"Server support fast copy", HFILL }},
{ &hf_dsi_server_addr_len,
{ "Length", "dsi.server_addr.len",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Address length.", HFILL }},
{ &hf_dsi_server_addr_type,
{ "Type", "dsi.server_addr.type",
FT_UINT8, BASE_DEC, VALS(afp_server_addr_type_vals), 0x0,
"Address type.", HFILL }},
{ &hf_dsi_server_addr_value,
{ "Value", "dsi.server_addr.value",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Address value", HFILL }},
{ &hf_dsi_open_type,
{ "Flags", "dsi.open_type",
FT_UINT8, BASE_DEC, VALS(dsi_open_type_vals), 0x0,
"Open session option type.", HFILL }},
{ &hf_dsi_open_len,
{ "Length", "dsi.open_len",
FT_UINT8, BASE_DEC, NULL, 0x0,
"Open session option len", HFILL }},
{ &hf_dsi_open_quantum,
{ "Quantum", "dsi.open_quantum",
FT_UINT32, BASE_DEC, NULL, 0x0,
"Server/Attention quantum", HFILL }},
{ &hf_dsi_open_option,
{ "Option", "dsi.open_option",
FT_BYTES, BASE_HEX, NULL, 0x0,
"Open session options (undecoded)", HFILL }},
{ &hf_dsi_attn_flag,
{ "Flags", "dsi.attn_flag",
FT_UINT16, BASE_HEX, VALS(dsi_attn_flag_vals), 0xf000,
"Server attention flag", HFILL }},
{ &hf_dsi_attn_flag_shutdown,
{ "Shutdown", "dsi.attn_flag.shutdown",
FT_BOOLEAN, 16, NULL, 1<<15,
"Attention flag, server is shutting down", HFILL }},
{ &hf_dsi_attn_flag_crash,
{ "Crash", "dsi.attn_flag.crash",
FT_BOOLEAN, 16, NULL, 1<<14,
"Attention flag, server crash bit", HFILL }},
{ &hf_dsi_attn_flag_msg,
{ "Message", "dsi.attn_flag.msg",
FT_BOOLEAN, 16, NULL, 1<<13,
"Attention flag, server message bit", HFILL }},
{ &hf_dsi_attn_flag_reconnect,
{ "Don't reconnect", "dsi.attn_flag.reconnect",
FT_BOOLEAN, 16, NULL, 1<<12,
"Attention flag, don't reconnect bit", HFILL }},
{ &hf_dsi_attn_flag_time,
{ "Minutes", "dsi.attn_flag.time",
FT_UINT16, BASE_DEC, NULL, 0xfff,
"Number of minutes", HFILL }},
{ &hf_dsi_attn_flag_bitmap,
{ "Bitmap", "dsi.attn_flag.time",
FT_UINT16, BASE_HEX, NULL, 0xfff,
"Attention extended bitmap", HFILL }},
};
static gint *ett[] = {
&ett_dsi,
&ett_dsi_open,
&ett_dsi_attn,
&ett_dsi_attn_flag,
/* asp afp */
&ett_dsi_status,
&ett_dsi_status_server_flag,
&ett_dsi_vers,
&ett_dsi_uams,
&ett_dsi_addr,
&ett_dsi_addr_line,
&ett_dsi_directory,
&ett_dsi_utf8_name,
};
module_t *dsi_module;
proto_dsi = proto_register_protocol("Data Stream Interface", "DSI", "dsi");
proto_register_field_array(proto_dsi, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
dsi_module = prefs_register_protocol(proto_dsi, NULL);
prefs_register_bool_preference(dsi_module, "desegment",
"Desegment all DSI messages spanning multiple TCP segments",
"Whether the DSI dissector should desegment all messages spanning multiple TCP segments",
&dsi_desegment);
}
void
proto_reg_handoff_dsi(void)
{
static dissector_handle_t dsi_handle;
dsi_handle = create_dissector_handle(dissect_dsi, proto_dsi);
dissector_add("tcp.port", TCP_PORT_DSI, dsi_handle);
data_handle = find_dissector("data");
afp_handle = find_dissector("afp");
}