Ethereal-dev: [Ethereal-dev] Patch: Final bits to packet-9p.c

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

From: "Nils O. Selåsdal" <noselasd@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 27 Apr 2005 19:29:18 +0200
Hello,
Since I heard some rumors about a release next week, it would be fine if
this patch made it in before that. It should (hopefully) be the finishing of the 9P
dissector. It;
- Decodes all the remaining bitfields in 9P
- Tidies up display a bit (using more subtrees)
- Fixes a few fields that are better off displayed as decimal/octal.

Thanks,
--
Nils Olav Selåsdal
NOS@xxxxxxx
noselasd@xxxxxxxxxxxxxxxxxxxxx

Index: packet-9p.c
===================================================================
--- packet-9p.c	(revision 14203)
+++ packet-9p.c	(working copy)
@@ -8,6 +8,8 @@
  * By Gerald Combs <gerald@xxxxxxxxxxxx>
  * Copyright 1998 Gerald Combs
  *
+ * File permission bits decoding taken from packet-nfs.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
@@ -80,8 +82,23 @@
 #define P9_MODEMASK	   0x3 
 #define P9_OTRUNC	  0x10 
 #define P9_ORCLOSE	  0x40 
-#define P9_OEXCL	0x1000 
 
+/* stat mode flags */
+#define DMDIR		0x80000000 /* Directory */
+#define DMAPPEND	0x40000000 /* Append only */
+#define DMEXCL		0x20000000 /* Exclusive use */
+#define DMMOUNT		0x10000000 /* Mounted channel */
+#define DMAUTH		0x08000000 /* Authentication */
+#define DMTMP		0x04000000 /* Temporary */
+
+#define QTDIR		0x80	/* Directory */
+#define QTAPPEND	0x40	/* Append only */
+#define QTEXCL		0x20	/* Exclusive use */
+#define QTMOUNT		0x10	/* Mounted channel */
+#define QTAUTH		0x08	/* Authentication */
+#define QTTMP		0x04	/* Temporary */
+#define QTFILE		0x00	/* plain file ?? */
+
 /* Initialize the protocol and registered fields */
 static int proto_9P = -1;
 static int hf_9P_msgsz = -1;
@@ -96,7 +113,6 @@
 static int hf_9P_mode_rwx = -1;
 static int hf_9P_mode_t = -1;
 static int hf_9P_mode_c = -1;
-static int hf_9P_mode_x = -1;
 static int hf_9P_iounit = -1;
 static int hf_9P_count = -1;
 static int hf_9P_offset = -1;
@@ -131,6 +147,18 @@
 /* subtree pointers */
 static gint ett_9P = -1;
 static gint ett_9P_omode = -1;
+static gint ett_9P_dm = -1;
+static gint ett_9P_wname = -1;
+static gint ett_9P_aname = -1;
+static gint ett_9P_ename = -1;
+static gint ett_9P_uname = -1;
+static gint ett_9P_uid = -1;
+static gint ett_9P_gid = -1;
+static gint ett_9P_muid = -1;
+static gint ett_9P_filename = -1;
+static gint ett_9P_version = -1;
+static gint ett_9P_qid = -1;
+static gint ett_9P_qidtype = -1;
 
 /*9P Msg types to name mapping */
 static const value_string ninep_msg_type[] = 
@@ -172,9 +200,11 @@
 	{P9_OEXEC,	"Execute Access"},
 	{0,		NULL}
 };
-	
-static void dissect_9P_mode(tvbuff_t * tvb,  proto_tree * tree,int offset,int iscreate);
 
+static void dissect_9P_mode(tvbuff_t * tvb,  proto_item * tree,int offset);
+static void dissect_9P_dm(tvbuff_t * tvb,  proto_item * tree,int offset,int iscreate);
+static void dissect_9P_qid(tvbuff_t * tvb,  proto_tree * tree,int offset);
+
 /* Dissect 9P messages*/
 static void dissect_9P(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
 {
@@ -229,40 +259,37 @@
 		offset +=4;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_version, tvb, offset, tmp16, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_version, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_version);	
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += 2;
 		break;
 	case TAUTH:
 		proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, TRUE);
 		offset +=4;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_uname);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_aname);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
 		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset, tmp16, TRUE);
 		break;
 	case RAUTH:
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
-
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
-		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 		break;
 	case RERROR:
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_ename, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_ename);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
 		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_ename, tvb, offset, tmp16, TRUE);
 
 		break;
 	case TFLUSH:
@@ -278,24 +305,20 @@
 		offset +=4;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_uname);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16 + 2;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset, tmp16, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_aname);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 		break;
 	case RATTACH:
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
-
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
-		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 		break;
 	case TWALK:
 		proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
@@ -317,12 +340,15 @@
 
 		for(i = 0 ; i < tmp16; i++) {
 			guint16 tmplen;
+			proto_item *wname;
+			proto_tree *wname_tree;
+			
+			tmplen = tvb_get_letohs(tvb,offset);
+			wname = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, tmplen, TRUE);
+			wname_tree = proto_item_add_subtree(wname,ett_9P_wname);
+			proto_tree_add_item(wname_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
 
-			tmplen = tvb_get_letohs(tvb,offset);
-			proto_tree_add_uint_format(ninep_tree, hf_9P_parmsz, tvb, offset, 2, tmplen, "%d. param length: %u",i,tmplen);
-			offset +=2;
-			proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset, tmplen, TRUE);
-			offset += tmplen;
+			offset += tmplen + 2;
 		}
 
 		break;
@@ -339,33 +365,19 @@
 		}
 
 		for(i = 0; i < tmp16; i++) {
-			proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-			++offset;
-
-			proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
-			offset +=4;
-		
-			proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-			offset +=8;
+			dissect_9P_qid(tvb,ninep_tree,offset);
+			offset += 13;
 		}	
 		break;	
 	case TOPEN:
 		proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
 		offset +=4;
-		tmp_tree = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
-		dissect_9P_mode(tvb,tmp_tree,offset,0);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
+		dissect_9P_mode(tvb,ti,offset);
 		break;
 	case ROPEN:
-
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
-
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
-		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-		offset +=8;
-
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 		proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, TRUE);
 		break;
 	case TCREATE:
@@ -373,28 +385,22 @@
 		offset +=4;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_name, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_name, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16 + 2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, TRUE);
+		dissect_9P_dm(tvb,ti,offset,1);
 		offset +=4;
 
-		tmp_tree = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
-		dissect_9P_mode(tvb,tmp_tree,offset,1);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
+		dissect_9P_mode(tvb,ti,offset);
 
 		break;
 	case RCREATE:
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
-
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
-		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-		offset +=8;
-
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 		proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, TRUE);
 		break;
 	case TREAD:
@@ -462,18 +468,13 @@
 		proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, TRUE);
 		offset +=4;
 
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
+		dissect_9P_dm(tvb,ti,offset,0);
 		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-		offset +=8;
 
-		proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
-		offset +=4;
-
 		tv.secs = tvb_get_letohl(tvb,offset);
 		tv.nsecs = 0;
 		proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
@@ -488,31 +489,28 @@
 		offset +=8;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_uid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_gid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_muid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 		break;
 	case TWSTAT:
 		proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
@@ -530,18 +528,13 @@
 		proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, TRUE);
 		offset +=4;
 
-		proto_tree_add_item(ninep_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
-		++offset;
+		dissect_9P_qid(tvb,ninep_tree,offset);
+		offset += 13;
 
-		proto_tree_add_item(ninep_tree, hf_9P_qidvers, tvb, offset, 4, TRUE);
+		ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
+		dissect_9P_dm(tvb,ti,offset,0);
 		offset +=4;
-		
-		proto_tree_add_item(ninep_tree, hf_9P_qidpath, tvb, offset, 8, TRUE);
-		offset +=8;
 
-		proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
-		offset +=4;
-
 		tv.secs = tvb_get_letohl(tvb,offset);
 		tv.nsecs = 0;
 		proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
@@ -556,52 +549,130 @@
 		offset +=8;
 
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_uid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_gid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 
-		proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
-
 		tmp16 = tvb_get_letohs(tvb,offset);
-		proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
-		offset +=2;
-		proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset, tmp16, TRUE);
-		offset += tmp16;
+		ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, tmp16, TRUE);
+		tmp_tree = proto_item_add_subtree(ti,ett_9P_muid);
+		proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
+		offset += tmp16+2;
 		break;
 	}
+}
+/* dissect 9P open mode flags */
+static void dissect_9P_mode(tvbuff_t * tvb,  proto_item * item,int offset)
+{
+	proto_item *mode_tree;
+	guint8 mode;
 
+	mode = tvb_get_guint8(tvb,offset);
+	mode_tree = proto_item_add_subtree(item, ett_9P_omode);
+	if(!mode_tree)
+		return;
+	proto_tree_add_boolean(mode_tree, hf_9P_mode_c, tvb, offset, 1, mode);
+	proto_tree_add_boolean(mode_tree, hf_9P_mode_t, tvb, offset, 1, mode);
+	proto_tree_add_item(mode_tree, hf_9P_mode_rwx, tvb, offset, 1, mode);
 }
 
+/* dissect 9P Qid */
+static void dissect_9P_qid(tvbuff_t * tvb,  proto_tree * tree,int offset)
+{
+	proto_item *qid_item,*qidtype_item;
+	proto_tree *qid_tree,*qidtype_tree;
+	guint64 path;
+	guint32 vers;
+	guint8 type;
 
-static void dissect_9P_mode(tvbuff_t * tvb,  proto_tree * tree,int offset,int iscreate)
+	if(!tree)
+		return;
+	
+	type = tvb_get_guint8(tvb,offset);
+	vers = tvb_get_letohs(tvb,offset+1);
+	path = tvb_get_letoh64(tvb,offset+1+4);
+
+	qid_item = proto_tree_add_text(tree,tvb,offset,13,"Qid type=0x%02x vers=%d path=%"PRIu64,type,vers,path);
+	qid_tree = proto_item_add_subtree(qid_item,ett_9P_qid);
+
+	qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
+	qidtype_tree = proto_item_add_subtree(qidtype_item,ett_9P_qidtype);
+
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTDIR, 8, "Directory", "not a Directory"));
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTAPPEND, 8, "Append only", "not Append only"));
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTEXCL, 8, "Exclusive use", "not Exclusive use"));
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTMOUNT, 8, "Mounted channel", "not a Mounted channel"));
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTAUTH, 8, "Authentication file", "not an Authentication file"));
+	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(type,    QTTMP, 8, "Temporary file (not backed up)", "not a Temporary file"));
+
+	proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, TRUE);
+	proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, TRUE);
+}
+
+/*dissect 9P stat mode and create perm flags */
+static void dissect_9P_dm(tvbuff_t * tvb,  proto_item * item,int offset,int iscreate)
 {
 	proto_item *mode_tree;
-	guint8 mode;
+	guint32 dm;
 
-	if(!tree)
+
+	dm = tvb_get_letohl(tvb,offset);
+	mode_tree = proto_item_add_subtree(item, ett_9P_dm);
+	if(!mode_tree)
 		return;
 
-	mode = tvb_get_guint8(tvb,offset);
-	mode_tree = proto_item_add_subtree(tree, ett_9P_omode);
-	proto_tree_add_item(mode_tree, hf_9P_mode_rwx, tvb, offset, 1, mode);
-	proto_tree_add_boolean(mode_tree, hf_9P_mode_t, tvb, offset, 1, mode);
-	proto_tree_add_boolean(mode_tree, hf_9P_mode_c, tvb, offset, 1, mode);
-	if(iscreate) /* only in create calls */
-		proto_tree_add_boolean(mode_tree, hf_9P_mode_x, tvb, offset, 1, mode);
+	proto_tree_add_text(mode_tree, tvb, offset, 1, "%s",
+	decode_boolean_bitfield(dm,    DMDIR, 32, "Directory", "not a Directory"));
+	if(!iscreate) { /* Not applicable to Tcreate (?) */
+		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+		decode_boolean_bitfield(dm,    DMAPPEND, 32, "Append only", "not Append only"));
+		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+		decode_boolean_bitfield(dm,    DMEXCL, 32, "Exclusive use", "not Exclusive use"));
+		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+		decode_boolean_bitfield(dm,    DMMOUNT, 32, "Mounted channel", "not a Mounted channel"));
+		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+		decode_boolean_bitfield(dm,    DMAUTH, 32, "Authentication file", "not an Authentication file"));
+		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+		decode_boolean_bitfield(dm,    DMTMP, 32, "Temporary file (not backed up)", "not a Temporary file"));
+	}
+
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,    0400, 32, "Read permission for owner", "no Read permission for owner"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,    0200, 32, "Write permission for owner", "no Write permission for owner"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,    0100, 32, "Execute permission for owner", "no Execute permission for owner"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,     040, 32, "Read permission for group", "no Read permission for group"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,     020, 32, "Write permission for group", "no Write permission for group"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,     010, 32, "Execute permission for group", "no Execute permission for group"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,      04, 32, "Read permission for others", "no Read permission for others"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,      02, 32, "Write permission for others", "no Write permission for others"));
+	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
+	decode_boolean_bitfield(dm,      01, 32, "Execute permission for others", "no Execute permission for others"));
 }
 
 /* Register 9P with Ethereal */
@@ -624,14 +695,14 @@
 		 {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
 		  "Parameter length", HFILL}},
 		{&hf_9P_maxsize,
-		 {"Max msg size", "9p.maxsize", FT_UINT32, BASE_HEX, NULL, 0x0,
+		 {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "Max message size", HFILL}},
 		{&hf_9P_fid,
 		 {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "File ID", HFILL}},
 		{&hf_9P_nqid,
 		 {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
-		  "Number of Qids", HFILL}},
+		  "Number of Qid results", HFILL}},
 		{&hf_9P_mode,
 		 {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
 		  "Mode", HFILL}},
@@ -644,9 +715,6 @@
 		{&hf_9P_mode_c,
 		 {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&flags_set_truth), P9_ORCLOSE,
 		  "", HFILL}},
-		{&hf_9P_mode_x,
-		 {"Exclusive", "9p.mode.excl", FT_BOOLEAN, 8, TFS(&flags_set_truth), P9_OEXCL,
-		  "", HFILL}},
 		{&hf_9P_iounit,
 		 {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "I/O Unit", HFILL}},
@@ -666,14 +734,14 @@
 		 {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "Qid version", HFILL}},
 		{&hf_9P_qidtype,
-		 {"Qid type", "9p.qidtype", FT_UINT8, BASE_DEC, NULL, 0x0,
+		 {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
 		  "Qid type", HFILL}},
 		{&hf_9P_statmode,
-		 {"Stat mode", "9p.statmode", FT_UINT32, BASE_HEX, NULL, 0x0,
-		  "Stat mode", HFILL}},
+		 {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
+		  "File mode flags", HFILL}},
 		{&hf_9P_stattype,
-		 {"Stat type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
-		  "Stat type", HFILL}},
+		 {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
+		  "Type", HFILL}},
 		{&hf_9P_atime,
 		 {"Atime", "9p.atime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
 		  "Access Time", HFILL}},
@@ -693,20 +761,20 @@
 		 {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
 		  "Version", HFILL}},
 		{&hf_9P_afid,
-		 {"AFid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
+		 {"Afid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "Authenticating FID", HFILL}},
 		{&hf_9P_uname,
 		 {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
 		  "User Name", HFILL}},
 		{&hf_9P_aname,
 		 {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
-		  "Attach Name", HFILL}},
+		  "Access Name", HFILL}},
 		{&hf_9P_ename,
 		 {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
 		  "Error", HFILL}},
 		{&hf_9P_name,
 		 {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
-		  "Name (of file)", HFILL}},
+		  "Name of file", HFILL}},
 		{&hf_9P_sdlen,
 		 {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
 		  "Stat data length", HFILL}},
@@ -715,25 +783,37 @@
 		  "File name", HFILL}},
 		{&hf_9P_uid,
 		 {"Uid", "9p.uid", FT_STRING, BASE_NONE, NULL, 0x0,
-		  "User ID", HFILL}},
+		  "User id", HFILL}},
 		{&hf_9P_gid,
 		 {"Gid", "9p.gid", FT_STRING, BASE_NONE, NULL, 0x0,
-		  "Group ID", HFILL}},
+		  "Group id", HFILL}},
 		{&hf_9P_muid,
 		 {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
-		  "Modified Uid", HFILL}},
+		  "Last modifiers uid", HFILL}},
 		{&hf_9P_newfid,
 		 {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
 		  "New file ID", HFILL}},
 		{&hf_9P_nwalk,
 		 {"Nr Walks", "9p.nwalk", FT_UINT32, BASE_DEC, NULL, 0x0,
-		  "Nr of walk results", HFILL}}
+		  "Nr of walk items", HFILL}}
 
 	};
 
 	static gint *ett[] = {
 		&ett_9P,
 		&ett_9P_omode,
+		&ett_9P_dm,
+		&ett_9P_wname,
+		&ett_9P_aname,
+		&ett_9P_ename,
+		&ett_9P_uname,
+		&ett_9P_uid,
+		&ett_9P_gid,
+		&ett_9P_muid,
+		&ett_9P_filename,
+		&ett_9P_version,
+		&ett_9P_qid,
+		&ett_9P_qidtype,
 	};
 
 	proto_9P = proto_register_protocol("Plan 9 9P", "9P", "9p");