Ethereal-dev: [Ethereal-dev] patch to packet-tds.c

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Yaniv Kaul <ykaul@xxxxxxxxxxxx>
Date: Sun, 04 Jan 2004 20:13:55 +0200
Please find attached tds.diff.

Adds:
- parsing of message token (Unicode and regular)
- Adds parsing of error token (Unicode only - do not have a non Unicode sample. Anyone?)
- parsing of done token (only minimal actually)
- parsing of Collation Information structure in Environment Change token.


--- packet-tds.orig.c	Fri Aug 29 04:54:53 2003
+++ packet-tds.c	Sun Jan  4 20:09:29 2004
@@ -286,6 +286,7 @@
 static int hf_tds7_reserved_flags = -1;
 static int hf_tds7_time_zone = -1;
 static int hf_tds7_collation = -1;
+static int hf_tds7_message = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_tds = -1;
@@ -394,6 +395,7 @@
         {4, "Blocksize"},
         {5, "Unicode Locale ID"},
         {6, "Unicode Comparison Style"},
+		{7, "Collation Info"},
         {0, NULL},
 };
 
@@ -786,6 +788,8 @@
 	char *new_val = NULL, *old_val = NULL;
 	guint32 string_offset;
 	gboolean is_unicode = FALSE;
+	guint16 collate_codepage, collate_flags;
+	guint8 collate_charset_id;
 
 	env_type = tvb_get_guint8(tvb, offset);
 	proto_tree_add_text(tree, tvb, offset, 1, "Type: %u (%s)", env_type,
@@ -808,16 +812,30 @@
 	proto_tree_add_text(tree, tvb, offset + 1, 1, "New Value Length: %u",
 	    new_len);
 	if (new_len) {
-		string_offset = offset + 2;
-		if (is_unicode == TRUE) {
-			new_val = tvb_fake_unicode(tvb, string_offset,
-			    new_len, TRUE);
-			new_len *= 2;
-		} else
-			new_val = tvb_get_string(tvb, string_offset, new_len);
-		proto_tree_add_text(tree, tvb, string_offset, new_len,
-		    "New Value: %s", new_val);
-		g_free(new_val);
+		if (env_type != 7) { /* if it's not 'Collation Info - which is not textual! */
+			string_offset = offset + 2;
+			if (is_unicode == TRUE) {
+				new_val = tvb_fake_unicode(tvb, string_offset,
+					new_len, TRUE);
+				new_len *= 2;
+			} else
+				new_val = tvb_get_string(tvb, string_offset, new_len);
+			proto_tree_add_text(tree, tvb, string_offset, new_len,
+				"New Value: %s", new_val);
+			g_free(new_val);
+		}
+		else { /* parse collation info structure. From http://www.freetds.org/tds.html#collate */
+			offset +=2;
+			collate_codepage = tvb_get_letohs(tvb, offset);
+			proto_tree_add_text(tree, tvb, offset, 2, "Codepage: %d" , collate_codepage);
+			offset += 2;
+			collate_flags = tvb_get_letohs(tvb, offset);
+			proto_tree_add_text(tree, tvb, offset, 2, "Flags: 0x%x", collate_flags);
+			offset += 2;
+			collate_charset_id = tvb_get_guint8(tvb, offset);
+			proto_tree_add_text(tree, tvb, offset, 1, "Charset ID: %d", collate_charset_id);
+			offset +=1;
+		}
 	}
 
 	proto_tree_add_text(tree, tvb, old_len_offset, 1, "Old Value Length: %u",
@@ -837,6 +855,84 @@
 }
 
 static void
+dissect_tds_msg_token(tvbuff_t *tvb, guint offset, guint token_sz, proto_tree *tree)
+{
+	guint16 msg_len;
+	guint8 srvr_len;
+	char *msg;
+	gboolean is_unicode = FALSE;
+
+	proto_tree_add_text(tree, tvb, offset, 4, "SQL Message Number: %d", tvb_get_letohl(tvb, offset));
+	offset += 4;
+	proto_tree_add_text(tree, tvb, offset, 1, "State: %d", tvb_get_guint8(tvb, offset));
+	offset +=1;
+	proto_tree_add_text(tree, tvb, offset, 1, "Level: %d", tvb_get_guint8(tvb, offset));
+	offset +=1;
+	
+	msg_len = tvb_get_letohs(tvb, offset);
+	proto_tree_add_text(tree, tvb, offset, 2, "Message length: %d characters", msg_len);
+	offset +=2;
+	
+	srvr_len = tvb_get_guint8(tvb, offset + msg_len);
+	
+	if(msg_len + srvr_len + 9 + 3 != token_sz) /* 9 is the lenth of message number (4), state (1), level (1), msg_len (2), srvr_len (1) fields */
+		is_unicode = TRUE;
+
+	if(is_unicode) {
+		msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+		msg_len *= 2;
+	} else {
+		msg = tvb_get_string(tvb, offset, msg_len);
+	}
+	proto_tree_add_text(tree, tvb, offset, msg_len, "Message: %s", msg);
+	g_free(msg);
+	offset += msg_len;
+
+	srvr_len = tvb_get_guint8(tvb, offset);
+	proto_tree_add_text(tree, tvb, offset, 1, "Server name length: %d characters", srvr_len);
+	offset +=1;
+	
+	if (is_unicode) {
+		msg = tvb_fake_unicode(tvb, offset, srvr_len, TRUE);
+		srvr_len *=2;
+	} else {
+		msg = tvb_get_string(tvb, offset, srvr_len);
+	}
+	proto_tree_add_text(tree, tvb, offset, srvr_len, "Server name: %s", msg, srvr_len);
+	g_free(msg);
+}
+
+static void
+dissect_tds_err_token(tvbuff_t *tvb, guint offset, proto_tree *tree)
+{
+	guint16 msg_len;
+	char *msg;
+	proto_tree_add_text(tree, tvb, offset, 4, "SQL Error Number: %d", tvb_get_letohl(tvb, offset));
+	offset += 4;
+	proto_tree_add_text(tree, tvb, offset, 1, "State: %d", tvb_get_guint8(tvb, offset));
+	offset +=1;
+	proto_tree_add_text(tree, tvb, offset, 1, "Level: %d", tvb_get_guint8(tvb, offset));
+	offset +=1;
+	msg_len = tvb_get_letohs(tvb, offset);
+	proto_tree_add_text(tree, tvb, offset, 1, "Error length: %d characters", msg_len);
+	offset +=2;
+	msg = tvb_fake_unicode(tvb, offset, msg_len, TRUE);
+	proto_tree_add_text(tree, tvb, offset, msg_len*2, "Error: %s", msg);
+	g_free(msg);
+}
+
+static void
+dissect_tds_done_token(tvbuff_t *tvb, guint offset, proto_tree *tree)
+{
+	proto_tree_add_text(tree, tvb, offset, 2, "bit flag");
+	offset += 2;
+	proto_tree_add_text(tree, tvb, offset, 2, "unknown");
+	offset += 2;
+	proto_tree_add_text(tree, tvb, offset, 4, "row count: %d", tvb_get_letohl(tvb, offset));
+	offset += 2;
+}
+
+static void
 dissect_tds_rpc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
 	int offset = 0;
@@ -930,8 +1026,17 @@
 			dissect_tds_ntlmssp(tvb, pinfo, token_tree, pos + 3,
 			    token_sz - 3);
 			break;
+		case TDS_MSG_TOKEN:
+			dissect_tds_msg_token(tvb, pos + 3, token_sz - 3, token_tree);
+			break;
+		case TDS_ERR_TOKEN:
+			dissect_tds_err_token(tvb, pos + 3, token_tree);
+			break;
+		case TDS_DONE_TOKEN:
+			dissect_tds_done_token(tvb, pos + 1, token_tree);
+			break;
 		}
-
+		
 		/* and step to the end of the token, rinse, lather, repeat */
 		pos += token_sz;
 	}
@@ -1458,6 +1563,11 @@
                         FT_UINT32, BASE_HEX, NULL, 0x0,
                         "Collation", HFILL }
                 },
+		{ &hf_tds7_message,
+						{ "Message", "tds7.message", 
+						FT_STRING, BASE_NONE, NULL, 0x0, 
+						"", HFILL }
+				},
 	};
 	static gint *ett[] = {
 		&ett_tds,