aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dsi.c
diff options
context:
space:
mode:
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>2004-07-18 18:06:47 +0000
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>2004-07-18 18:06:47 +0000
commit35a6e092c3153cc7fbd1337c2230d596b0f7abcb (patch)
tree4eff24a2e16c8963e497e1fc575f35e6af59bd26 /epan/dissectors/packet-dsi.c
parent8dd1ee5ef22a787f4035d68e8e2ec8371fd23266 (diff)
Move dissectors to epan/dissectors directory.
Also move ncp222.py, x11-fields, process-x11-fields.pl, make-reg-dotc, and make-reg-dotc.py. Adjust #include lines in files that include packet-*.h files. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@11410 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'epan/dissectors/packet-dsi.c')
-rw-r--r--epan/dissectors/packet-dsi.c846
1 files changed, 846 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dsi.c b/epan/dissectors/packet-dsi.c
new file mode 100644
index 0000000000..adbc28ed64
--- /dev/null
+++ b/epan/dissectors/packet-dsi.c
@@ -0,0 +1,846 @@
+/* packet-dsi.c
+ * Routines for dsi packet dissection
+ * Copyright 2001, Randy McEoin <rmceoin@pe.com>
+ *
+ * $Id$
+ *
+ * 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");
+}