* Routines for dsi packet dissection
* Copyright 2001, Randy McEoin <rmceoin@pe.com>
*
- * $Id: packet-dsi.c,v 1.17 2002/05/01 07:07:09 guy Exp $
+ * $Id: packet-dsi.c,v 1.25 2002/10/17 22:38:19 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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.
#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
#include <glib.h>
#include <epan/packet.h>
#include "prefs.h"
-#include "packet-frame.h"
+#include "packet-tcp.h"
#include "packet-afp.h"
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_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_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 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_status_server_flag = -1;
const value_string afp_server_addr_type_vals[] = {
{2, "IP+port address" },
{3, "DDP address" },
{4, "DNS name" },
+ {5, "IP+port ssh tunnel" },
{0, NULL } };
/* end status stuff */
{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
+static gint
dissect_dsi_reply_get_status(tvbuff_t *tvb, proto_tree *tree, gint offset)
{
proto_tree *sub_tree;
guint16 flag;
guint16 sign_ofs = 0;
guint16 adr_ofs = 0;
+ guint16 dir_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);
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);
- /* FIXME wild guess */
flag = tvb_get_ntohs(tvb, ofs);
if ((flag & AFPSRVRINFO_SRVSIGNATURE)) {
- ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN);
+ ofs = offset +AFPSTATUS_PRELEN +tvb_get_guint8(tvb, offset +AFPSTATUS_PRELEN) +1;
if ((ofs & 1))
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;
+ }
}
-
+
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 += len;
}
}
-
+
ofs = offset +tvb_get_ntohs(tvb, offset +AFPSTATUS_UAMSOFF);
if (ofs) {
nbe = tvb_get_guint8(tvb, ofs);
}
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++;
- sub_tree = proto_item_add_subtree(ti, ett_dsi_addr);
+ adr_tree = proto_item_add_subtree(ti, ett_dsi_addr);
for (i = 0; i < nbe; i++) {
- len = tvb_get_guint8(tvb, ofs) -2;
+ 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 */
+ if (len > 2) {
+ tmp = g_malloc( len -1);
+ tvb_memcpy(tvb, tmp, ofs +2, len -2);
+ tmp[len -2] = 0;
+ ti = proto_tree_add_text(adr_tree, tvb, ofs, len, "dns %s", tmp);
+ g_free(tmp);
+ break;
+ }
+ /* else fall to default malformed record */
+ 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);
+ 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) +1;
+ proto_tree_add_item(sub_tree, hf_dsi_server_directory, tvb, ofs, 1, FALSE);
+ ofs += len;
+ }
+ }
+
return offset;
}
guint32 dsi_length;
guint32 dsi_reserved;
struct aspinfo aspinfo;
-
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DSI");
if (check_col(pinfo->cinfo, COL_INFO))
proto_tree_add_uint(dsi_tree, hf_dsi_reserved, tvb,
12, 4, dsi_reserved);
}
- else
+ 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;
+ break;
case DSIFUNC_CMD:
case DSIFUNC_WRITE:
{
}
break;
default:
- if (tree) {
- call_dissector(data_handle,tvb_new_subset(tvb, DSI_BLOCKSIZ,-1,tvb_reported_length_remaining(tvb,DSI_BLOCKSIZ)), pinfo, dsi_tree);
+ if (tree) {
+ call_dissector(data_handle,
+ tvb_new_subset(tvb, DSI_BLOCKSIZ, -1, -1),
+ pinfo, dsi_tree);
}
break;
}
}
-static void
-dissect_dsi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static guint
+get_dsi_pdu_len(tvbuff_t *tvb, int offset)
{
- volatile int offset = 0;
- int length_remaining;
guint32 plen;
- int length;
- tvbuff_t *next_tvb;
-
- while (tvb_reported_length_remaining(tvb, offset) != 0) {
- length_remaining = tvb_length_remaining(tvb, offset);
-
- /*
- * Can we do reassembly?
- */
- if (dsi_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the DSI header split across segment
- * boundaries?
- */
- if (length_remaining < 12) {
- /*
- * Yes. Tell the TCP dissector where
- * the data for this message starts in
- * the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = 12 - length_remaining;
- return;
- }
- }
- /*
- * Get the length of the DSI packet.
- */
- plen = tvb_get_ntohl(tvb, offset+8);
-
- /*
- * Can we do reassembly?
- */
- if (dsi_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the DSI packet split across segment
- * boundaries?
- */
- if ((guint32)length_remaining < plen + 16) {
- /*
- * Yes. Tell the TCP dissector where
- * the data for this message starts in
- * the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len =
- (plen + 16) - length_remaining;
- return;
- }
- }
+ /*
+ * Get the length of the DSI packet.
+ */
+ plen = tvb_get_ntohl(tvb, offset+8);
- /*
- * Construct a tvbuff containing the amount of the payload
- * we have available. Make its reported length the
- * amount of data in the DSI packet.
- *
- * XXX - if reassembly isn't enabled. the subdissector
- * will throw a BoundsError exception, rather than a
- * ReportedBoundsError exception. We really want
- * a tvbuff where the length is "length", the reported
- * length is "plen + 16", and the "if the snapshot length
- * were infinite" length is the minimum of the
- * reported length of the tvbuff handed to us and "plen+16",
- * with a new type of exception thrown if the offset is
- * within the reported length but beyond that third length,
- * with that exception getting the "Unreassembled Packet"
- * error.
- */
- length = length_remaining;
- if ((guint32)length > plen + 16)
- length = plen + 16;
- next_tvb = tvb_new_subset(tvb, offset, length, plen + 16);
-
- /*
- * Dissect the DSI packet.
- *
- * Catch the ReportedBoundsError exception; if this
- * particular message happens to get a ReportedBoundsError
- * exception, that doesn't mean that we should stop
- * dissecting DSI messages within this frame or chunk
- * of reassembled data.
- *
- * If it gets a BoundsError, we can stop, as there's nothing
- * more to see, so we just re-throw it.
- */
- TRY {
- dissect_dsi_packet(next_tvb, pinfo, tree);
- }
- CATCH(BoundsError) {
- RETHROW;
- }
- CATCH(ReportedBoundsError) {
- show_reported_bounds_error(tvb, pinfo, tree);
- }
- ENDTRY;
+ /*
+ * That length doesn't include the length of the header itself;
+ * add that in.
+ */
+ return plen + 16;
+}
- /*
- * Skip the DSI header and the payload.
- */
- offset += 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
{ "Reserved", "dsi.reserved",
FT_UINT32, BASE_HEX, NULL, 0x0,
"Reserved for future use. Should be set to zero.", HFILL }},
-
+ /* asp , afp */
{ &hf_dsi_server_name,
{ "Server name", "dsi.server_name",
FT_UINT_STRING, BASE_NONE, NULL, 0x0,
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,
{ "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,
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,
};
module_t *dsi_module;