2 * Routines for 9P dissection
3 * Copyright 2005, Nils O. Selåsdal
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * File permission bits decoding taken from packet-nfs.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include <epan/packet.h>
39 #include <epan/strutil.h>
43 /*Message types for 9P */
44 /*See man 5 intro on Plan 9 - or;
45 http://www.cs.bell-labs.com/sys/man/5/INDEX.html
54 TERROR = 106, /* Not used */
82 #define P9_MODEMASK 0x3
83 #define P9_OTRUNC 0x10
84 #define P9_ORCLOSE 0x40
87 #define DMDIR 0x80000000 /* Directory */
88 #define DMAPPEND 0x40000000 /* Append only */
89 #define DMEXCL 0x20000000 /* Exclusive use */
90 #define DMMOUNT 0x10000000 /* Mounted channel */
91 #define DMAUTH 0x08000000 /* Authentication */
92 #define DMTMP 0x04000000 /* Temporary */
94 #define QTDIR 0x80 /* Directory */
95 #define QTAPPEND 0x40 /* Append only */
96 #define QTEXCL 0x20 /* Exclusive use */
97 #define QTMOUNT 0x10 /* Mounted channel */
98 #define QTAUTH 0x08 /* Authentication */
99 #define QTTMP 0x04 /* Temporary */
100 #define QTFILE 0x00 /* plain file ?? */
102 /* Initialize the protocol and registered fields */
103 static int proto_9P = -1;
104 static int hf_9P_msgsz = -1;
105 static int hf_9P_msgtype = -1;
106 static int hf_9P_tag = -1;
107 static int hf_9P_oldtag = -1;
108 static int hf_9P_parmsz = -1;
109 static int hf_9P_maxsize = -1;
110 static int hf_9P_fid = -1;
111 static int hf_9P_nqid = -1;
112 static int hf_9P_mode = -1;
113 static int hf_9P_mode_rwx = -1;
114 static int hf_9P_mode_t = -1;
115 static int hf_9P_mode_c = -1;
116 static int hf_9P_iounit = -1;
117 static int hf_9P_count = -1;
118 static int hf_9P_offset = -1;
119 static int hf_9P_perm = -1;
120 static int hf_9P_qidtype = -1;
121 static int hf_9P_qidvers = -1;
122 static int hf_9P_qidpath = -1;
123 static int hf_9P_stattype = -1;
124 static int hf_9P_statmode = -1;
125 static int hf_9P_atime = -1;
126 static int hf_9P_mtime = -1;
127 static int hf_9P_length = -1;
128 static int hf_9P_dev = -1;
129 static int hf_9P_wname = -1;
130 static int hf_9P_version = -1;
131 static int hf_9P_afid = -1;
132 static int hf_9P_uname = -1;
133 static int hf_9P_aname = -1;
134 static int hf_9P_ename = -1;
135 static int hf_9P_name = -1;
136 static int hf_9P_filename = -1;
137 static int hf_9P_sdlen = -1;
138 static int hf_9P_uid = -1;
139 static int hf_9P_gid = -1;
140 static int hf_9P_muid = -1;
141 static int hf_9P_nwalk = -1;
142 static int hf_9P_newfid = -1;
144 /*handle for dissecting data in 9P msgs*/
145 static dissector_handle_t data_handle;
147 /* subtree pointers */
148 static gint ett_9P = -1;
149 static gint ett_9P_omode = -1;
150 static gint ett_9P_dm = -1;
151 static gint ett_9P_wname = -1;
152 static gint ett_9P_aname = -1;
153 static gint ett_9P_ename = -1;
154 static gint ett_9P_uname = -1;
155 static gint ett_9P_uid = -1;
156 static gint ett_9P_gid = -1;
157 static gint ett_9P_muid = -1;
158 static gint ett_9P_filename = -1;
159 static gint ett_9P_version = -1;
160 static gint ett_9P_qid = -1;
161 static gint ett_9P_qidtype = -1;
163 /*9P Msg types to name mapping */
164 static const value_string ninep_msg_type[] =
165 { {TVERSION, "Tversion"},
166 {RVERSION, "Rversion"},
169 {TATTACH, "Tattach"},
170 {RATTACH, "Rattach"},
178 {TCREATE, "Tcreate"},
179 {RCREATE, "Rcreate"},
186 {TREMOVE, "Tremove"},
187 {RREMOVE, "Rremove"},
194 /* Open/Create modes */
195 static const value_string ninep_mode_vals[] =
197 {P9_OREAD, "Read Access"},
198 {P9_OWRITE, "Write Access"},
199 {P9_ORDWR, "Read/Write Access "},
200 {P9_OEXEC, "Execute Access"},
204 static void dissect_9P_mode(tvbuff_t * tvb, proto_item * tree,int offset);
205 static void dissect_9P_dm(tvbuff_t * tvb, proto_item * tree,int offset,int iscreate);
206 static void dissect_9P_qid(tvbuff_t * tvb, proto_tree * tree,int offset);
208 /* Dissect 9P messages*/
209 static void dissect_9P(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
211 guint32 ninesz,tmp,i;
216 gint len,reportedlen;
219 proto_tree *ninep_tree,*tmp_tree;
222 if (check_col(pinfo->cinfo, COL_PROTOCOL))
223 col_set_str(pinfo->cinfo, COL_PROTOCOL, "9P");
224 if (check_col(pinfo->cinfo, COL_INFO))
225 col_clear(pinfo->cinfo, COL_INFO);
227 ninesz = tvb_get_letohl(tvb, offset);
228 ninemsg = tvb_get_guint8(tvb, offset + 4);
230 mname = val_to_str(ninemsg, ninep_msg_type,"Unknown");
232 if(strcmp(mname,"Unknown") == 0) {
233 if (check_col(pinfo->cinfo, COL_INFO))
234 col_add_fstr(pinfo->cinfo, COL_INFO, "9P Data Continuitation(?) (Tag %u)",(guint)ninemsg);
239 if (check_col(pinfo->cinfo, COL_INFO))
240 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Tag=%u",mname,(guint)tvb_get_letohs(tvb,offset+5));
242 if (!tree) /*not much more of one line summary interrest yet.. */
245 ti = proto_tree_add_item(tree, proto_9P, tvb, 0, -1, FALSE);
246 ninep_tree = proto_item_add_subtree(ti, ett_9P);
247 proto_tree_add_item(ninep_tree, hf_9P_msgsz, tvb, offset, 4, TRUE);
250 proto_tree_add_item(ninep_tree, hf_9P_msgtype, tvb, offset, 1, TRUE);
252 proto_tree_add_item(ninep_tree, hf_9P_tag, tvb, offset, 2, TRUE);
258 proto_tree_add_item(ninep_tree, hf_9P_maxsize, tvb, offset, 4, TRUE);
261 tmp16 = tvb_get_letohs(tvb,offset);
262 ti = proto_tree_add_item(ninep_tree, hf_9P_version, tvb, offset+2, tmp16, TRUE);
263 tmp_tree = proto_item_add_subtree(ti,ett_9P_version);
264 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
268 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, TRUE);
271 tmp16 = tvb_get_letohs(tvb,offset);
272 ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, tmp16, TRUE);
273 tmp_tree = proto_item_add_subtree(ti,ett_9P_uname);
274 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
277 tmp16 = tvb_get_letohs(tvb,offset);
278 ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, tmp16, TRUE);
279 tmp_tree = proto_item_add_subtree(ti,ett_9P_aname);
280 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
284 dissect_9P_qid(tvb,ninep_tree,offset);
288 tmp16 = tvb_get_letohs(tvb,offset);
289 ti = proto_tree_add_item(ninep_tree, hf_9P_ename, tvb, offset+2, tmp16, TRUE);
290 tmp_tree = proto_item_add_subtree(ti,ett_9P_ename);
291 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
296 proto_tree_add_item(ninep_tree, hf_9P_oldtag, tvb, offset, 2, TRUE);
301 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
304 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, TRUE);
307 tmp16 = tvb_get_letohs(tvb,offset);
308 ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, tmp16, TRUE);
309 tmp_tree = proto_item_add_subtree(ti,ett_9P_uname);
310 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
313 tmp16 = tvb_get_letohs(tvb,offset);
314 ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, tmp16, TRUE);
315 tmp_tree = proto_item_add_subtree(ti,ett_9P_aname);
316 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
320 dissect_9P_qid(tvb,ninep_tree,offset);
324 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
327 proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, TRUE);
330 tmp16 = tvb_get_letohs(tvb,offset);
331 proto_tree_add_item(ninep_tree, hf_9P_nwalk, tvb, offset, 2, TRUE);
333 /* I can't imagine anyone having a directory depth more than 25,
334 Limit to 10 times that to be sure, 2^16 is too much */
337 tmp_tree = proto_tree_add_text(ninep_tree, tvb, 0, 0, "Only first 250 items shown");
338 PROTO_ITEM_SET_GENERATED(tmp_tree);
341 for(i = 0 ; i < tmp16; i++) {
344 proto_tree *wname_tree;
346 tmplen = tvb_get_letohs(tvb,offset);
347 wname = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, tmplen, TRUE);
348 wname_tree = proto_item_add_subtree(wname,ett_9P_wname);
349 proto_tree_add_item(wname_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
351 offset += tmplen + 2;
356 tmp16 = tvb_get_letohs(tvb,offset);
357 proto_tree_add_item(ninep_tree, hf_9P_nqid, tvb, offset, 2, TRUE);
359 /* I can't imagine anyone having a directory depth more than 25,
360 Limit to 10 times that to be sure, 2^16 is too much */
363 tmp_tree = proto_tree_add_text(ninep_tree, tvb, 0, 0, "Only first 250 items shown");
364 PROTO_ITEM_SET_GENERATED(tmp_tree);
367 for(i = 0; i < tmp16; i++) {
368 dissect_9P_qid(tvb,ninep_tree,offset);
373 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
375 ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
376 dissect_9P_mode(tvb,ti,offset);
379 dissect_9P_qid(tvb,ninep_tree,offset);
381 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, TRUE);
384 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
387 tmp16 = tvb_get_letohs(tvb,offset);
388 ti = proto_tree_add_item(ninep_tree, hf_9P_name, tvb, offset+2, tmp16, TRUE);
389 tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
390 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
393 ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, TRUE);
394 dissect_9P_dm(tvb,ti,offset,1);
397 ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, TRUE);
398 dissect_9P_mode(tvb,ti,offset);
402 dissect_9P_qid(tvb,ninep_tree,offset);
404 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, TRUE);
407 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
410 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, TRUE);
413 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, TRUE);
416 tmp = tvb_get_letohl(tvb,offset);
417 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, TRUE);
420 len = tvb_reported_length_remaining(tvb, offset);
421 reportedlen = ((gint)tmp&0xffff) > len ? len : (gint)tmp&0xffff;
422 next_tvb = tvb_new_subset(tvb, offset, len, reportedlen);
423 call_dissector(data_handle,next_tvb, pinfo, tree);
426 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
429 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, TRUE);
432 tmp = tvb_get_letohl(tvb,offset);
433 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, TRUE);
435 len = tvb_reported_length_remaining(tvb, offset);
436 reportedlen = ((gint)tmp&0xffff) > len ? len : (gint)tmp&0xffff;
437 next_tvb = tvb_new_subset(tvb, offset, len, reportedlen);
438 call_dissector(data_handle,next_tvb, pinfo, tree);
441 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, TRUE);
444 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
450 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
456 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
459 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
462 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, TRUE);
465 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, TRUE);
468 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, TRUE);
471 dissect_9P_qid(tvb,ninep_tree,offset);
474 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
475 dissect_9P_dm(tvb,ti,offset,0);
478 tv.secs = tvb_get_letohl(tvb,offset);
480 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
483 tv.secs = tvb_get_letohl(tvb,offset);
485 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 4, &tv);
488 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, TRUE);
491 tmp16 = tvb_get_letohs(tvb,offset);
492 ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, tmp16, TRUE);
493 tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
494 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
497 tmp16 = tvb_get_letohs(tvb,offset);
498 ti = proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset+2, tmp16, TRUE);
499 tmp_tree = proto_item_add_subtree(ti,ett_9P_uid);
500 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
503 tmp16 = tvb_get_letohs(tvb,offset);
504 ti = proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset+2, tmp16, TRUE);
505 tmp_tree = proto_item_add_subtree(ti,ett_9P_gid);
506 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
509 tmp16 = tvb_get_letohs(tvb,offset);
510 ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, tmp16, TRUE);
511 tmp_tree = proto_item_add_subtree(ti,ett_9P_muid);
512 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
516 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, TRUE);
519 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
522 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, TRUE);
525 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, TRUE);
528 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, TRUE);
531 dissect_9P_qid(tvb,ninep_tree,offset);
534 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, TRUE);
535 dissect_9P_dm(tvb,ti,offset,0);
538 tv.secs = tvb_get_letohl(tvb,offset);
540 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
543 tv.secs = tvb_get_letohl(tvb,offset);
545 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 4, &tv);
548 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, TRUE);
551 tmp16 = tvb_get_letohs(tvb,offset);
552 ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, tmp16, TRUE);
553 tmp_tree = proto_item_add_subtree(ti,ett_9P_filename);
554 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
557 tmp16 = tvb_get_letohs(tvb,offset);
558 ti = proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset+2, tmp16, TRUE);
559 tmp_tree = proto_item_add_subtree(ti,ett_9P_uid);
560 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
563 tmp16 = tvb_get_letohs(tvb,offset);
564 ti = proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset+2, tmp16, TRUE);
565 tmp_tree = proto_item_add_subtree(ti,ett_9P_gid);
566 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
569 tmp16 = tvb_get_letohs(tvb,offset);
570 ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, tmp16, TRUE);
571 tmp_tree = proto_item_add_subtree(ti,ett_9P_muid);
572 proto_tree_add_item(tmp_tree, hf_9P_parmsz, tvb, offset, 2, TRUE);
577 /* dissect 9P open mode flags */
578 static void dissect_9P_mode(tvbuff_t * tvb, proto_item * item,int offset)
580 proto_item *mode_tree;
583 mode = tvb_get_guint8(tvb,offset);
584 mode_tree = proto_item_add_subtree(item, ett_9P_omode);
587 proto_tree_add_boolean(mode_tree, hf_9P_mode_c, tvb, offset, 1, mode);
588 proto_tree_add_boolean(mode_tree, hf_9P_mode_t, tvb, offset, 1, mode);
589 proto_tree_add_item(mode_tree, hf_9P_mode_rwx, tvb, offset, 1, mode);
593 static void dissect_9P_qid(tvbuff_t * tvb, proto_tree * tree,int offset)
595 proto_item *qid_item,*qidtype_item;
596 proto_tree *qid_tree,*qidtype_tree;
604 type = tvb_get_guint8(tvb,offset);
605 vers = tvb_get_letohs(tvb,offset+1);
606 path = tvb_get_letoh64(tvb,offset+1+4);
608 qid_item = proto_tree_add_text(tree,tvb,offset,13,"Qid type=0x%02x vers=%d path=%"PRIu64,type,vers,path);
609 qid_tree = proto_item_add_subtree(qid_item,ett_9P_qid);
611 qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
612 qidtype_tree = proto_item_add_subtree(qidtype_item,ett_9P_qidtype);
614 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
615 decode_boolean_bitfield(type, QTDIR, 8, "Directory", "not a Directory"));
616 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
617 decode_boolean_bitfield(type, QTAPPEND, 8, "Append only", "not Append only"));
618 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
619 decode_boolean_bitfield(type, QTEXCL, 8, "Exclusive use", "not Exclusive use"));
620 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
621 decode_boolean_bitfield(type, QTMOUNT, 8, "Mounted channel", "not a Mounted channel"));
622 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
623 decode_boolean_bitfield(type, QTAUTH, 8, "Authentication file", "not an Authentication file"));
624 proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
625 decode_boolean_bitfield(type, QTTMP, 8, "Temporary file (not backed up)", "not a Temporary file"));
627 proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, TRUE);
628 proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, TRUE);
631 /*dissect 9P stat mode and create perm flags */
632 static void dissect_9P_dm(tvbuff_t * tvb, proto_item * item,int offset,int iscreate)
634 proto_item *mode_tree;
638 dm = tvb_get_letohl(tvb,offset);
639 mode_tree = proto_item_add_subtree(item, ett_9P_dm);
643 proto_tree_add_text(mode_tree, tvb, offset, 1, "%s",
644 decode_boolean_bitfield(dm, DMDIR, 32, "Directory", "not a Directory"));
645 if(!iscreate) { /* Not applicable to Tcreate (?) */
646 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
647 decode_boolean_bitfield(dm, DMAPPEND, 32, "Append only", "not Append only"));
648 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
649 decode_boolean_bitfield(dm, DMEXCL, 32, "Exclusive use", "not Exclusive use"));
650 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
651 decode_boolean_bitfield(dm, DMMOUNT, 32, "Mounted channel", "not a Mounted channel"));
652 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
653 decode_boolean_bitfield(dm, DMAUTH, 32, "Authentication file", "not an Authentication file"));
654 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
655 decode_boolean_bitfield(dm, DMTMP, 32, "Temporary file (not backed up)", "not a Temporary file"));
658 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
659 decode_boolean_bitfield(dm, 0400, 32, "Read permission for owner", "no Read permission for owner"));
660 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
661 decode_boolean_bitfield(dm, 0200, 32, "Write permission for owner", "no Write permission for owner"));
662 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
663 decode_boolean_bitfield(dm, 0100, 32, "Execute permission for owner", "no Execute permission for owner"));
664 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
665 decode_boolean_bitfield(dm, 040, 32, "Read permission for group", "no Read permission for group"));
666 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
667 decode_boolean_bitfield(dm, 020, 32, "Write permission for group", "no Write permission for group"));
668 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
669 decode_boolean_bitfield(dm, 010, 32, "Execute permission for group", "no Execute permission for group"));
670 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
671 decode_boolean_bitfield(dm, 04, 32, "Read permission for others", "no Read permission for others"));
672 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
673 decode_boolean_bitfield(dm, 02, 32, "Write permission for others", "no Write permission for others"));
674 proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
675 decode_boolean_bitfield(dm, 01, 32, "Execute permission for others", "no Execute permission for others"));
678 /* Register 9P with Wireshark */
679 void proto_register_9P(void);
681 void proto_register_9P(void)
683 static hf_register_info hf[] = {
685 {"Msg length", "9p.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
686 "9P Message Length", HFILL}},
688 {"Msg Type", "9p.msgtype", FT_UINT8, BASE_DEC, VALS(ninep_msg_type), 0x0,
689 "Message Type", HFILL}},
691 {"Tag", "9p.tag", FT_UINT16, BASE_DEC, NULL, 0x0,
694 {"Old tag", "9p.oldtag", FT_UINT16, BASE_DEC, NULL, 0x0,
697 {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
698 "Parameter length", HFILL}},
700 {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
701 "Max message size", HFILL}},
703 {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
706 {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
707 "Number of Qid results", HFILL}},
709 {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
712 {"Open/Create Mode", "9p.mode.rwx", FT_UINT8, BASE_DEC,VALS(ninep_mode_vals),P9_MODEMASK,
713 "Open/Create Mode", HFILL}},
715 {"Trunc", "9p.mode.trunc", FT_BOOLEAN, 8, TFS(&flags_set_truth), P9_OTRUNC,
718 {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&flags_set_truth), P9_ORCLOSE,
721 {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
724 {"Count", "9p.count", FT_UINT32, BASE_DEC, NULL, 0x0,
727 {"Offset", "9p.offset", FT_UINT64, BASE_DEC, NULL, 0x0,
730 {"Permissions", "9p.perm", FT_UINT32, BASE_OCT, NULL, 0x0,
731 "Permission bits", HFILL}},
733 {"Qid path", "9p.qidpath", FT_UINT64, BASE_DEC, NULL, 0x0,
736 {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
737 "Qid version", HFILL}},
739 {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
742 {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
743 "File mode flags", HFILL}},
745 {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
748 {"Atime", "9p.atime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
749 "Access Time", HFILL}},
751 {"Mtime", "9p.mtime", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
752 "Modified Time", HFILL}},
754 {"Length", "9p.length", FT_UINT64, BASE_DEC, NULL, 0x0,
755 "File Length", HFILL}},
757 {"Dev", "9p.dev", FT_UINT32, BASE_DEC, NULL, 0x0,
760 {"Wname", "9p.wname", FT_STRING, BASE_NONE, NULL, 0x0,
761 "Path Name Element", HFILL}},
763 {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
766 {"Afid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
767 "Authenticating FID", HFILL}},
769 {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
770 "User Name", HFILL}},
772 {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
773 "Access Name", HFILL}},
775 {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
778 {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
779 "Name of file", HFILL}},
781 {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
782 "Stat data length", HFILL}},
784 {"File name", "9p.filename", FT_STRING, BASE_NONE, NULL, 0x0,
785 "File name", HFILL}},
787 {"Uid", "9p.uid", FT_STRING, BASE_NONE, NULL, 0x0,
790 {"Gid", "9p.gid", FT_STRING, BASE_NONE, NULL, 0x0,
793 {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
794 "Last modifiers uid", HFILL}},
796 {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
797 "New file ID", HFILL}},
799 {"Nr Walks", "9p.nwalk", FT_UINT32, BASE_DEC, NULL, 0x0,
800 "Nr of walk items", HFILL}}
804 static gint *ett[] = {
821 proto_9P = proto_register_protocol("Plan 9 9P", "9P", "9p");
823 proto_register_field_array(proto_9P, hf, array_length(hf));
825 proto_register_subtree_array(ett, array_length(ett));
828 void proto_reg_handoff_9P(void);
830 void proto_reg_handoff_9P(void)
832 dissector_handle_t ninep_handle;
834 data_handle = find_dissector("data");
836 ninep_handle = create_dissector_handle(dissect_9P, proto_9P);
838 dissector_add("tcp.port", NINEPORT, ninep_handle);