MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-9p.c
blobd942636e83c9aa192272e12f21def0a2d7b613cb
1 /* packet-9P.c
2 * Routines for 9P dissection
3 * Copyright 2005, Nils O. Selaasdal
5 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <string.h>
31 #include <stdio.h>
33 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/strutil.h>
37 #include <epan/conversation.h>
39 #include <epan/wmem/wmem.h>
41 #define FIRSTPASS(pinfo) (pinfo->fd->flags.visited == 0)
43 /**
44 * enum _9p_msg_t - 9P message types
45 * @_9P_TLERROR: not used
46 * @_9P_RLERROR: response for any failed request for 9P2000.L
47 * @_9P_TSTATFS: file system status request
48 * @_9P_RSTATFS: file system status response
49 * @_9P_TSYMLINK: make symlink request
50 * @_9P_RSYMLINK: make symlink response
51 * @_9P_TMKNOD: create a special file object request
52 * @_9P_RMKNOD: create a special file object response
53 * @_9P_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
54 * @_9P_RLCREATE: response with file access information for 9P2000.L
55 * @_9P_TRENAME: rename request
56 * @_9P_RRENAME: rename response
57 * @_9P_TMKDIR: create a directory request
58 * @_9P_RMKDIR: create a directory response
59 * @_9P_TVERSION: version handshake request
60 * @_9P_RVERSION: version handshake response
61 * @_9P_TAUTH: request to establish authentication channel
62 * @_9P_RAUTH: response with authentication information
63 * @_9P_TATTACH: establish user access to file service
64 * @_9P_RATTACH: response with top level handle to file hierarchy
65 * @_9P_TERROR: not used
66 * @_9P_RERROR: response for any failed request
67 * @_9P_TFLUSH: request to abort a previous request
68 * @_9P_RFLUSH: response when previous request has been cancelled
69 * @_9P_TWALK: descend a directory hierarchy
70 * @_9P_RWALK: response with new handle for position within hierarchy
71 * @_9P_TOPEN: prepare a handle for I/O on an existing file
72 * @_9P_ROPEN: response with file access information
73 * @_9P_TCREATE: prepare a handle for I/O on a new file
74 * @_9P_RCREATE: response with file access information
75 * @_9P_TREAD: request to transfer data from a file or directory
76 * @_9P_RREAD: response with data requested
77 * @_9P_TWRITE: reuqest to transfer data to a file
78 * @_9P_RWRITE: response with out much data was transfered to file
79 * @_9P_TCLUNK: forget about a handle to an entity within the file system
80 * @_9P_RCLUNK: response when server has forgotten about the handle
81 * @_9P_TREMOVE: request to remove an entity from the hierarchy
82 * @_9P_RREMOVE: response when server has removed the entity
83 * @_9P_TSTAT: request file entity attributes
84 * @_9P_RSTAT: response with file entity attributes
85 * @_9P_TWSTAT: request to update file entity attributes
86 * @_9P_RWSTAT: response when file entity attributes are updated
88 * There are 14 basic operations in 9P2000, paired as
89 * requests and responses. The one special case is ERROR
90 * as there is no @_9P_TERROR request for clients to transmit to
91 * the server, but the server may respond to any other request
92 * with an @_9P_RERROR.
94 * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
97 enum _9p_msg_t {
98 _9P_TLERROR = 6,
99 _9P_RLERROR,
100 _9P_TSTATFS = 8,
101 _9P_RSTATFS,
102 _9P_TLOPEN = 12,
103 _9P_RLOPEN,
104 _9P_TLCREATE = 14,
105 _9P_RLCREATE,
106 _9P_TSYMLINK = 16,
107 _9P_RSYMLINK,
108 _9P_TMKNOD = 18,
109 _9P_RMKNOD,
110 _9P_TRENAME = 20,
111 _9P_RRENAME,
112 _9P_TREADLINK = 22,
113 _9P_RREADLINK,
114 _9P_TGETATTR = 24,
115 _9P_RGETATTR,
116 _9P_TSETATTR = 26,
117 _9P_RSETATTR,
118 _9P_TXATTRWALK = 30,
119 _9P_RXATTRWALK,
120 _9P_TXATTRCREATE = 32,
121 _9P_RXATTRCREATE,
122 _9P_TREADDIR = 40,
123 _9P_RREADDIR,
124 _9P_TFSYNC = 50,
125 _9P_RFSYNC,
126 _9P_TLOCK = 52,
127 _9P_RLOCK,
128 _9P_TGETLOCK = 54,
129 _9P_RGETLOCK,
130 _9P_TLINK = 70,
131 _9P_RLINK,
132 _9P_TMKDIR = 72,
133 _9P_RMKDIR,
134 _9P_TRENAMEAT = 74,
135 _9P_RRENAMEAT,
136 _9P_TUNLINKAT = 76,
137 _9P_RUNLINKAT,
138 _9P_TVERSION = 100,
139 _9P_RVERSION,
140 _9P_TAUTH = 102,
141 _9P_RAUTH,
142 _9P_TATTACH = 104,
143 _9P_RATTACH,
144 _9P_TERROR = 106,
145 _9P_RERROR,
146 _9P_TFLUSH = 108,
147 _9P_RFLUSH,
148 _9P_TWALK = 110,
149 _9P_RWALK,
150 _9P_TOPEN = 112,
151 _9P_ROPEN,
152 _9P_TCREATE = 114,
153 _9P_RCREATE,
154 _9P_TREAD = 116,
155 _9P_RREAD,
156 _9P_TWRITE = 118,
157 _9P_RWRITE,
158 _9P_TCLUNK = 120,
159 _9P_RCLUNK,
160 _9P_TREMOVE = 122,
161 _9P_RREMOVE,
162 _9P_TSTAT = 124,
163 _9P_RSTAT,
164 _9P_TWSTAT = 126,
165 _9P_RWSTAT
168 /* 9P Msg types to name mapping */
169 static const value_string ninep_msg_type[] =
171 {_9P_TLERROR, "Tlerror"},
172 {_9P_RLERROR, "Rlerror"},
173 {_9P_TSTATFS, "Tstatfs"},
174 {_9P_RSTATFS, "Rstatfs"},
175 {_9P_TLOPEN, "Tlopen"},
176 {_9P_RLOPEN, "Rlopen"},
177 {_9P_TLCREATE, "Tlcreate"},
178 {_9P_RLCREATE, "Rlcreate"},
179 {_9P_TSYMLINK, "Tsymlink"},
180 {_9P_RSYMLINK, "Rsymlink"},
181 {_9P_TMKNOD, "Tmknod"},
182 {_9P_RMKNOD, "Rmknod"},
183 {_9P_TRENAME, "Trename"},
184 {_9P_RRENAME, "Rrename"},
185 {_9P_TREADLINK, "Treadlink"},
186 {_9P_RREADLINK, "Rreadlink"},
187 {_9P_TGETATTR, "Tgetattr"},
188 {_9P_RGETATTR, "Rgetattr"},
189 {_9P_TSETATTR, "Tsetattr"},
190 {_9P_RSETATTR, "Rsetattr"},
191 {_9P_TXATTRWALK, "Txattrwalk"},
192 {_9P_RXATTRWALK, "Rxattrwalk"},
193 {_9P_TXATTRCREATE, "Txattrcreate"},
194 {_9P_RXATTRCREATE, "Rxattrcreate"},
195 {_9P_TREADDIR, "Treaddir"},
196 {_9P_RREADDIR, "Rreaddir"},
197 {_9P_TFSYNC, "Tfsync"},
198 {_9P_RFSYNC, "Rfsync"},
199 {_9P_TLOCK, "Tlock"},
200 {_9P_RLOCK, "Rlock"},
201 {_9P_TGETLOCK, "Tgetlock"},
202 {_9P_RGETLOCK, "Rgetlock"},
203 {_9P_TLINK, "Tlink"},
204 {_9P_RLINK, "Rlink"},
205 {_9P_TMKDIR, "Tmkdir"},
206 {_9P_RMKDIR, "Rmkdir"},
207 {_9P_TRENAMEAT, "Trenameat"},
208 {_9P_RRENAMEAT, "Rrenameat"},
209 {_9P_TUNLINKAT, "Tunlinkat"},
210 {_9P_RUNLINKAT, "Runlinkat"},
211 {_9P_TVERSION, "Tversion"},
212 {_9P_RVERSION, "Rversion"},
213 {_9P_TAUTH, "Tauth"},
214 {_9P_RAUTH, "Rauth"},
215 {_9P_TATTACH, "Tattach"},
216 {_9P_RATTACH, "Rattach"},
217 {_9P_TERROR, "Terror"},
218 {_9P_RERROR, "Rerror"},
219 {_9P_TFLUSH, "Tflush"},
220 {_9P_RFLUSH, "Rflush"},
221 {_9P_TWALK, "Twalk"},
222 {_9P_RWALK, "Rwalk"},
223 {_9P_TOPEN, "Topen"},
224 {_9P_ROPEN, "Ropen"},
225 {_9P_TCREATE, "Tcreate"},
226 {_9P_RCREATE, "Rcreate"},
227 {_9P_TREAD, "Tread"},
228 {_9P_RREAD, "Rread"},
229 {_9P_TWRITE, "Twrite"},
230 {_9P_RWRITE, "Rwrite"},
231 {_9P_TCLUNK, "Tclunk"},
232 {_9P_RCLUNK, "Rclunk"},
233 {_9P_TREMOVE, "Tremove"},
234 {_9P_RREMOVE, "Rremove"},
235 {_9P_TSTAT, "Tstat"},
236 {_9P_RSTAT, "Rstat"},
237 {_9P_TWSTAT, "Twstat"},
238 {_9P_RWSTAT, "Rwstat"},
239 {0, NULL},
241 static value_string_ext ninep_msg_type_ext = VALUE_STRING_EXT_INIT(ninep_msg_type);
243 enum _9p_version {
244 _9P = 1,
245 _9P2000,
246 _9P2000_L,
247 _9P2000_u
250 static const value_string ninep_version[] =
252 {_9P, "9P"},
253 {_9P2000, "9P2000"},
254 {_9P2000_L, "9P2000.L"},
255 {_9P2000_u, "9P2000.u"},
256 {0, NULL},
258 static value_string_ext ninep_version_ext = VALUE_STRING_EXT_INIT(ninep_version);
261 /* File open modes */
262 #define _9P_OREAD 0x0
263 #define _9P_OWRITE 0x1
264 #define _9P_ORDWR 0x2
265 #define _9P_OEXEC 0x3
266 #define _9P_MODEMASK 0x3
267 #define _9P_OTRUNC 0x10
268 #define _9P_ORCLOSE 0x40
270 /* Open/Create modes */
271 static const value_string ninep_mode_vals[] =
273 {_9P_OREAD, "Read Access"},
274 {_9P_OWRITE, "Write Access"},
275 {_9P_ORDWR, "Read/Write Access "},
276 {_9P_OEXEC, "Execute Access"},
277 {0, NULL},
279 static value_string_ext ninep_mode_vals_ext = VALUE_STRING_EXT_INIT(ninep_mode_vals);
282 /* stat mode flags */
283 #define DMDIR 0x80000000 /* Directory */
284 #define DMAPPEND 0x40000000 /* Append only */
285 #define DMEXCL 0x20000000 /* Exclusive use */
286 #define DMMOUNT 0x10000000 /* Mounted channel */
287 #define DMAUTH 0x08000000 /* Authentication */
288 #define DMTMP 0x04000000 /* Temporary */
292 * enum _9p_qid_t - QID types
293 * @_9P_QTDIR: directory
294 * @_9P_QTAPPEND: append-only
295 * @_9P_QTEXCL: excluse use (only one open handle allowed)
296 * @_9P_QTMOUNT: mount points
297 * @_9P_QTAUTH: authentication file
298 * @_9P_QTTMP: non-backed-up files
299 * @_9P_QTSYMLINK: symbolic links (9P2000.u)
300 * @_9P_QTLINK: hard-link (9P2000.u)
301 * @_9P_QTFILE: normal files
303 * QID types are a subset of permissions - they are primarily
304 * used to differentiate semantics for a file system entity via
305 * a jump-table. Their value is also the most signifigant 16 bits
306 * of the permission_t
308 * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
310 enum _9p_qid_t {
311 _9P_QTDIR = 0x80,
312 _9P_QTAPPEND = 0x40,
313 _9P_QTEXCL = 0x20,
314 _9P_QTMOUNT = 0x10,
315 _9P_QTAUTH = 0x08,
316 _9P_QTTMP = 0x04,
317 _9P_QTSYMLINK = 0x02,
318 _9P_QTLINK = 0x01,
319 _9P_QTFILE = 0x00
322 /* 9P Magic Numbers */
323 #define _9P_NOTAG (guint16)(~0)
324 #define _9P_NOFID (guint32)(~0)
325 #define _9P_NONUNAME (guint32)(~0)
326 #define _9P_MAXWELEM 16
328 #ifndef MAXPATHLEN
329 #define MAXPATHLEN 1024
330 #endif
334 * @brief Length prefixed string type
336 * The protocol uses length prefixed strings for all
337 * string data, so we replicate that for our internal
338 * string members.
341 struct _9p_str {
342 guint16 len; /* Length of the string */
343 char *str; /* The string */
347 * @brief file system entity information
349 * qids are /identifiers used by 9P servers to track file system
350 * entities. The type is used to differentiate semantics for operations
351 * on the entity (ie. read means something different on a directory than
352 * on a file). The path provides a server unique index for an entity
353 * (roughly analogous to an inode number), while the version is updated
354 * every time a file is modified and can be used to maintain cache
355 * coherency between clients and serves.
356 * Servers will often differentiate purely synthetic entities by setting
357 * their version to 0, signaling that they should never be cached and
358 * should be accessed synchronously.
360 * See Also://plan9.bell-labs.com/magic/man2html/2/stat
363 struct _9p_qid {
364 guint8 type; /* Type */
365 guint32 version; /* Monotonically incrementing version number */
366 guint64 path; /* Per-server-unique ID for a file system element */
370 /* Bit values for getattr valid field.
372 #define _9P_GETATTR_MODE 0x00000001ULL
373 #define _9P_GETATTR_NLINK 0x00000002ULL
374 #define _9P_GETATTR_UID 0x00000004ULL
375 #define _9P_GETATTR_GID 0x00000008ULL
376 #define _9P_GETATTR_RDEV 0x00000010ULL
377 #define _9P_GETATTR_ATIME 0x00000020ULL
378 #define _9P_GETATTR_MTIME 0x00000040ULL
379 #define _9P_GETATTR_CTIME 0x00000080ULL
380 #define _9P_GETATTR_INO 0x00000100ULL
381 #define _9P_GETATTR_SIZE 0x00000200ULL
382 #define _9P_GETATTR_BLOCKS 0x00000400ULL
384 #define _9P_GETATTR_BTIME 0x00000800ULL
385 #define _9P_GETATTR_GEN 0x00001000ULL
386 #define _9P_GETATTR_DATA_VERSION 0x00002000ULL
388 #define _9P_GETATTR_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */
389 #define _9P_GETATTR_ALL 0x00003fffULL /* Mask for All fields above */
392 /* Bit values for setattr valid field from <linux/fs.h>.
394 #define _9P_SETATTR_MODE 0x00000001UL
395 #define _9P_SETATTR_UID 0x00000002UL
396 #define _9P_SETATTR_GID 0x00000004UL
397 #define _9P_SETATTR_SIZE 0x00000008UL
398 #define _9P_SETATTR_ATIME 0x00000010UL
399 #define _9P_SETATTR_MTIME 0x00000020UL
400 #define _9P_SETATTR_CTIME 0x00000040UL
401 #define _9P_SETATTR_ATIME_SET 0x00000080UL
402 #define _9P_SETATTR_MTIME_SET 0x00000100UL
404 #define _9P_SETATTR_ALL 0x000001FFUL
406 /* 9p2000.L open flags */
407 #define _9P_DOTL_RDONLY 00000000
408 #define _9P_DOTL_WRONLY 00000001
409 #define _9P_DOTL_RDWR 00000002
410 #define _9P_DOTL_NOACCESS 00000003
411 #define _9P_DOTL_CREATE 00000100
412 #define _9P_DOTL_EXCL 00000200
413 #define _9P_DOTL_NOCTTY 00000400
414 #define _9P_DOTL_TRUNC 00001000
415 #define _9P_DOTL_APPEND 00002000
416 #define _9P_DOTL_NONBLOCK 00004000
417 #define _9P_DOTL_DSYNC 00010000
418 #define _9P_DOTL_FASYNC 00020000
419 #define _9P_DOTL_DIRECT 00040000
420 #define _9P_DOTL_LARGEFILE 00100000
421 #define _9P_DOTL_DIRECTORY 00200000
422 #define _9P_DOTL_NOFOLLOW 00400000
423 #define _9P_DOTL_NOATIME 01000000
424 #define _9P_DOTL_CLOEXEC 02000000
425 #define _9P_DOTL_SYNC 04000000
428 /* Bit values for lock type.
430 #define _9P_LOCK_TYPE_RDLCK 0
431 #define _9P_LOCK_TYPE_WRLCK 1
432 #define _9P_LOCK_TYPE_UNLCK 2
434 /* 9P lock type to string table */
435 static const value_string ninep_lock_type[] =
437 {_9P_LOCK_TYPE_RDLCK, "Read lock"},
438 {_9P_LOCK_TYPE_WRLCK, "Write lock"},
439 {_9P_LOCK_TYPE_UNLCK, "Unlock"},
440 { 0, NULL},
442 static value_string_ext ninep_lock_type_ext = VALUE_STRING_EXT_INIT(ninep_lock_type);
444 /* Bit values for lock status.
446 #define _9P_LOCK_SUCCESS 0
447 #define _9P_LOCK_BLOCKED 1
448 #define _9P_LOCK_ERROR 2
449 #define _9P_LOCK_GRACE 3
451 /* 9P lock status to string table */
452 static const value_string ninep_lock_status[] =
454 {_9P_LOCK_SUCCESS, "Success"},
455 {_9P_LOCK_BLOCKED, "Blocked"},
456 {_9P_LOCK_ERROR, "Error"},
457 {_9P_LOCK_GRACE, "Grace"},
458 { 0, NULL},
460 static value_string_ext ninep_lock_status_ext = VALUE_STRING_EXT_INIT(ninep_lock_status);
462 /* Bit values for lock flags.
464 #define _9P_LOCK_FLAGS_NONE 0
465 #define _9P_LOCK_FLAGS_BLOCK 1
466 #define _9P_LOCK_FLAGS_RECLAIM 2
468 /* 9P lock flag to string table */
469 static const value_string ninep_lock_flag[] =
471 {_9P_LOCK_FLAGS_NONE, "No flag"},
472 {_9P_LOCK_FLAGS_BLOCK, "Block"},
473 {_9P_LOCK_BLOCKED, "Reclaim"},
474 { 0, NULL},
476 static value_string_ext ninep_lock_flag_ext = VALUE_STRING_EXT_INIT(ninep_lock_flag);
478 static const char *invalid_fid_str = "<invalid fid>";
479 static const char *afid_str = "<afid>";
481 /* Structures for Protocol Operations */
482 struct _9p_rlerror {
483 guint32 ecode;
485 struct _9p_tstatfs {
486 guint32 fid;
488 struct _9p_rstatfs {
489 guint32 type;
490 guint32 bsize;
491 guint64 blocks;
492 guint64 bfree;
493 guint64 bavail;
494 guint64 files;
495 guint64 ffree;
496 guint64 fsid;
497 guint32 namelen;
499 struct _9p_tlopen {
500 guint32 fid;
501 guint32 flags;
503 struct _9p_rlopen {
504 struct _9p_qid qid;
505 guint32 iounit;
507 struct _9p_tlcreate {
508 guint32 fid;
509 struct _9p_str name;
510 guint32 flags;
511 guint32 mode;
512 guint32 gid;
514 struct _9p_rlcreate {
515 struct _9p_qid qid;
516 guint32 iounit;
518 struct _9p_tsymlink {
519 guint32 fid;
520 struct _9p_str name;
521 struct _9p_str symtgt;
522 guint32 gid;
524 struct _9p_rsymlink {
525 struct _9p_qid qid;
527 struct _9p_tmknod {
528 guint32 fid;
529 struct _9p_str name;
530 guint32 mode;
531 guint32 major;
532 guint32 minor;
533 guint32 gid;
535 struct _9p_rmknod {
536 struct _9p_qid qid;
538 struct _9p_trename {
539 guint32 fid;
540 guint32 dfid;
541 struct _9p_str name;
543 #if 0
544 struct _9p_rrename {
546 #endif
547 struct _9p_treadlink {
548 guint32 fid;
550 struct _9p_rreadlink {
551 struct _9p_str target;
553 struct _9p_tgetattr {
554 guint32 fid;
555 guint64 request_mask;
557 struct _9p_rgetattr {
558 guint64 valid;
559 struct _9p_qid qid;
560 guint32 mode;
561 guint32 uid;
562 guint32 gid;
563 guint64 nlink;
564 guint64 rdev;
565 guint64 size;
566 guint64 blksize;
567 guint64 blocks;
568 guint64 atime_sec;
569 guint64 atime_nsec;
570 guint64 mtime_sec;
571 guint64 mtime_nsec;
572 guint64 ctime_sec;
573 guint64 ctime_nsec;
574 guint64 btime_sec;
575 guint64 btime_nsec;
576 guint64 gen;
577 guint64 data_version;
579 struct _9p_tsetattr {
580 guint32 fid;
581 guint32 valid;
582 guint32 mode;
583 guint32 uid;
584 guint32 gid;
585 guint64 size;
586 guint64 atime_sec;
587 guint64 atime_nsec;
588 guint64 mtime_sec;
589 guint64 mtime_nsec;
591 #if 0
592 struct _9p_rsetattr {
594 #endif
595 struct _9p_txattrwalk {
596 guint32 fid;
597 guint32 attrfid;
598 struct _9p_str name;
600 struct _9p_rxattrwalk {
601 guint64 size;
603 struct _9p_txattrcreate {
604 guint32 fid;
605 struct _9p_str name;
606 guint64 size;
607 guint32 flag;
609 #if 0
610 struct _9p_rxattrcreate {
612 #endif
613 struct _9p_treaddir {
614 guint32 fid;
615 guint64 offset;
616 guint32 count;
618 struct _9p_rreaddir {
619 guint32 count;
620 guint8 *data;
622 struct _9p_tfsync {
623 guint32 fid;
625 #if 0
626 struct _9p_rfsync {
628 #endif
629 struct _9p_tlock {
630 guint32 fid;
631 guint8 type;
632 guint32 flags;
633 guint64 start;
634 guint64 length;
635 guint32 proc_id;
636 struct _9p_str client_id;
638 struct _9p_rlock {
639 guint8 status;
641 struct _9p_tgetlock {
642 guint32 fid;
643 guint8 type;
644 guint64 start;
645 guint64 length;
646 guint32 proc_id;
647 struct _9p_str client_id;
649 struct _9p_rgetlock {
650 guint8 type;
651 guint64 start;
652 guint64 length;
653 guint32 proc_id;
654 struct _9p_str client_id;
656 struct _9p_tlink {
657 guint32 dfid;
658 guint32 fid;
659 struct _9p_str name;
661 #if 0
662 struct _9p_rlink {
664 #endif
665 struct _9p_tmkdir {
666 guint32 fid;
667 struct _9p_str name;
668 guint32 mode;
669 guint32 gid;
671 struct _9p_rmkdir {
672 struct _9p_qid qid;
674 struct _9p_trenameat {
675 guint32 olddirfid;
676 struct _9p_str oldname;
677 guint32 newdirfid;
678 struct _9p_str newname;
680 #if 0
681 struct _9p_rrenameat {
683 #endif
684 struct _9p_tunlinkat {
685 guint32 dirfid;
686 struct _9p_str name;
687 guint32 flags;
689 #if 0
690 struct _9p_runlinkat {
692 #endif
693 struct _9p_tawrite {
694 guint32 fid;
695 guint8 datacheck;
696 guint64 offset;
697 guint32 count;
698 guint32 rsize;
699 guint8 *data;
700 guint32 check;
702 struct _9p_rawrite {
703 guint32 count;
705 struct _9p_tversion {
706 guint32 msize ;
707 struct _9p_str version ;
709 struct _9p_rversion {
710 guint32 msize;
711 struct _9p_str version;
713 struct _9p_tauth {
714 guint32 afid;
715 struct _9p_str uname;
716 struct _9p_str aname;
717 guint32 n_uname; /* 9P2000.u extensions */
719 struct _9p_rauth {
720 struct _9p_qid qid;
722 struct _9p_rerror {
723 struct _9p_str error;
724 guint32 errnum; /* 9p2000.u extension */
726 struct _9p_tflush {
727 guint16 oldtag;
729 #if 0
730 struct _9p_rflush {
732 #endif
733 struct _9p_tattach {
734 guint32 fid;
735 guint32 afid;
736 struct _9p_str uname;
737 struct _9p_str aname;
738 guint32 n_uname; /* 9P2000.u extensions */
740 struct _9p_rattach {
741 struct _9p_qid qid;
743 struct _9p_twalk {
744 guint32 fid;
745 guint32 newfid;
746 guint16 nwname;
747 struct _9p_str wnames[_9P_MAXWELEM];
749 struct _9p_rwalk {
750 guint16 nwqid;
751 struct _9p_qid wqids[_9P_MAXWELEM];
753 struct _9p_topen {
754 guint32 fid;
755 guint8 mode;
757 struct _9p_ropen {
758 struct _9p_qid qid;
759 guint32 iounit;
761 struct _9p_tcreate {
762 guint32 fid;
763 struct _9p_str name;
764 guint32 perm;
765 guint8 mode;
766 struct _9p_str extension;
768 struct _9p_rcreate {
769 struct _9p_qid qid;
770 guint32 iounit;
772 struct _9p_tread {
773 guint32 fid;
774 guint64 offset;
775 guint32 count;
777 struct _9p_rread {
778 guint32 count;
779 guint8 *data;
781 struct _9p_twrite {
782 guint32 fid;
783 guint64 offset;
784 guint32 count;
785 guint8 *data;
787 struct _9p_rwrite {
788 guint32 count;
790 struct _9p_tclunk {
791 guint32 fid;
793 #if 0
794 struct _9p_rclunk {
796 #endif
797 struct _9p_tremove {
798 guint32 fid;
800 #if 0
801 struct _9p_rremove {
804 union _9p_tmsg {
806 #endif
807 #define NINEPORT 564
809 /* Forward declarations */
810 void proto_register_9P(void);
811 void proto_reg_handoff_9P(void);
813 /* Initialize the protocol and registered fields */
814 static int proto_9P = -1;
815 static int hf_9P_msgsz = -1;
816 static int hf_9P_msgtype = -1;
817 static int hf_9P_tag = -1;
818 static int hf_9P_oldtag = -1;
819 static int hf_9P_parmsz = -1;
820 static int hf_9P_maxsize = -1;
821 static int hf_9P_fid = -1;
822 static int hf_9P_nqid = -1;
823 static int hf_9P_mode = -1;
824 static int hf_9P_mode_rwx = -1;
825 static int hf_9P_mode_t = -1;
826 static int hf_9P_mode_c = -1;
827 static int hf_9P_iounit = -1;
828 static int hf_9P_count = -1;
829 static int hf_9P_offset = -1;
830 static int hf_9P_perm = -1;
831 static int hf_9P_qidtype = -1;
832 static int hf_9P_qidtype_dir = -1;
833 static int hf_9P_qidtype_append = -1;
834 static int hf_9P_qidtype_exclusive = -1;
835 static int hf_9P_qidtype_mount = -1;
836 static int hf_9P_qidtype_auth_file = -1;
837 static int hf_9P_qidtype_temp_file = -1;
838 static int hf_9P_qidvers = -1;
839 static int hf_9P_qidpath = -1;
840 static int hf_9P_dm_dir = -1;
841 static int hf_9P_dm_append = -1;
842 static int hf_9P_dm_exclusive = -1;
843 static int hf_9P_dm_mount = -1;
844 static int hf_9P_dm_auth_file = -1;
845 static int hf_9P_dm_temp_file = -1;
846 static int hf_9P_dm_read_owner = -1;
847 static int hf_9P_dm_write_owner = -1;
848 static int hf_9P_dm_exec_owner = -1;
849 static int hf_9P_dm_read_group = -1;
850 static int hf_9P_dm_write_group = -1;
851 static int hf_9P_dm_exec_group = -1;
852 static int hf_9P_dm_read_others = -1;
853 static int hf_9P_dm_write_others = -1;
854 static int hf_9P_dm_exec_others = -1;
855 static int hf_9P_stattype = -1;
856 static int hf_9P_statmode = -1;
857 static int hf_9P_atime = -1;
858 static int hf_9P_mtime = -1;
859 static int hf_9P_ctime = -1;
860 static int hf_9P_btime = -1;
861 static int hf_9P_length = -1;
862 static int hf_9P_dev = -1;
863 static int hf_9P_wname = -1;
864 static int hf_9P_version = -1;
865 static int hf_9P_afid = -1;
866 static int hf_9P_uname = -1;
867 static int hf_9P_aname = -1;
868 static int hf_9P_ename = -1;
869 static int hf_9P_enum = -1;
870 static int hf_9P_name = -1;
871 static int hf_9P_filename = -1;
872 static int hf_9P_sdlen = -1;
873 static int hf_9P_user = -1;
874 static int hf_9P_group = -1;
875 static int hf_9P_uid = -1;
876 static int hf_9P_gid = -1;
877 static int hf_9P_muid = -1;
878 static int hf_9P_nwalk = -1;
879 static int hf_9P_newfid = -1;
880 static int hf_9P_dfid = -1;
881 static int hf_9P_getattr_flags = -1;
882 static int hf_9P_getattr_mode = -1;
883 static int hf_9P_getattr_nlink = -1;
884 static int hf_9P_getattr_uid = -1;
885 static int hf_9P_getattr_gid = -1;
886 static int hf_9P_getattr_rdev = -1;
887 static int hf_9P_getattr_atime = -1;
888 static int hf_9P_getattr_mtime = -1;
889 static int hf_9P_getattr_ctime = -1;
890 static int hf_9P_getattr_ino = -1;
891 static int hf_9P_getattr_size = -1;
892 static int hf_9P_getattr_blocks = -1;
893 static int hf_9P_getattr_btime = -1;
894 static int hf_9P_getattr_gen = -1;
895 static int hf_9P_getattr_dataversion = -1;
896 static int hf_9P_setattr_flags = -1;
897 static int hf_9P_setattr_mode = -1;
898 static int hf_9P_setattr_uid = -1;
899 static int hf_9P_setattr_gid = -1;
900 static int hf_9P_setattr_size = -1;
901 static int hf_9P_setattr_atime = -1;
902 static int hf_9P_setattr_mtime = -1;
903 static int hf_9P_setattr_ctime = -1;
904 static int hf_9P_setattr_atime_set = -1;
905 static int hf_9P_setattr_mtime_set = -1;
906 static int hf_9P_nlink = -1;
907 static int hf_9P_rdev = -1;
908 static int hf_9P_size = -1;
909 static int hf_9P_blksize = -1;
910 static int hf_9P_blocks = -1;
911 static int hf_9P_gen = -1;
912 static int hf_9P_dataversion = -1;
913 static int hf_9P_fstype = -1;
914 static int hf_9P_bfree = -1;
915 static int hf_9P_bavail = -1;
916 static int hf_9P_files = -1;
917 static int hf_9P_ffree = -1;
918 static int hf_9P_fsid = -1;
919 static int hf_9P_namelen = -1;
920 static int hf_9P_mknod_major = -1;
921 static int hf_9P_mknod_minor = -1;
922 static int hf_9P_lflags = -1;
923 static int hf_9P_lflags_rdonly = -1;
924 static int hf_9P_lflags_wronly = -1;
925 static int hf_9P_lflags_rdwr = -1;
926 static int hf_9P_lflags_create = -1;
927 static int hf_9P_lflags_excl = -1;
928 static int hf_9P_lflags_noctty = -1;
929 static int hf_9P_lflags_trunc = -1;
930 static int hf_9P_lflags_append = -1;
931 static int hf_9P_lflags_nonblock = -1;
932 static int hf_9P_lflags_dsync = -1;
933 static int hf_9P_lflags_fasync = -1;
934 static int hf_9P_lflags_direct = -1;
935 static int hf_9P_lflags_largefile = -1;
936 static int hf_9P_lflags_directory = -1;
937 static int hf_9P_lflags_nofollow = -1;
938 static int hf_9P_lflags_noatime = -1;
939 static int hf_9P_lflags_cloexec = -1;
940 static int hf_9P_lflags_sync = -1;
941 static int hf_9P_xattr_flag = -1;
942 static int hf_9P_lock_type = -1;
943 static int hf_9P_lock_flag = -1;
944 static int hf_9P_lock_start = -1;
945 static int hf_9P_lock_length = -1;
946 static int hf_9P_lock_procid = -1;
947 static int hf_9P_lock_status = -1;
949 /*handle for dissecting data in 9P msgs*/
950 static dissector_handle_t data_handle;
952 /* subtree pointers */
953 static gint ett_9P = -1;
954 static gint ett_9P_omode = -1;
955 static gint ett_9P_dm = -1;
956 static gint ett_9P_wname = -1;
957 static gint ett_9P_aname = -1;
958 static gint ett_9P_ename = -1;
959 static gint ett_9P_uname = -1;
960 static gint ett_9P_user = -1;
961 static gint ett_9P_group = -1;
962 static gint ett_9P_muid = -1;
963 static gint ett_9P_filename = -1;
964 static gint ett_9P_version = -1;
965 static gint ett_9P_qid = -1;
966 static gint ett_9P_qidtype = -1;
967 static gint ett_9P_getattr_flags = -1;
968 static gint ett_9P_setattr_flags = -1;
969 static gint ett_9P_lflags = -1;
971 static GHashTable *_9p_hashtable = NULL;
973 static void dissect_9P_mode(tvbuff_t *tvb, proto_item *tree, int offset);
974 static void dissect_9P_dm(tvbuff_t *tvb, proto_item *tree, int offset, int iscreate);
975 static void dissect_9P_qid(tvbuff_t *tvb, proto_tree *tree, int offset);
976 static void dissect_9P_lflags(tvbuff_t *tvb, proto_tree *tree, int offset);
977 static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_tree *tree, int offset);
978 static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_tree *tree, int offset);
980 struct _9p_hashkey {
981 guint32 conv_index;
982 guint16 tag;
983 guint32 fid;
986 struct _9p_hashval {
987 gsize len;
988 void *data;
991 struct _9p_taginfo {
992 enum _9p_msg_t msgtype;
993 guint32 fid;
994 /* fid path used for create and lcreate */
995 char *fid_path;
998 static gint _9p_hash_equal(gconstpointer k1, gconstpointer k2) {
999 const struct _9p_hashkey *key1 = (struct _9p_hashkey *)k1, *key2 = (struct _9p_hashkey *)k2;
1001 return ((key1->conv_index == key2->conv_index) && (key1->tag == key2->tag) && (key1->fid == key2->fid));
1004 static guint _9p_hash_hash(gconstpointer k)
1006 const struct _9p_hashkey *key = (struct _9p_hashkey *)k;
1008 return (key->conv_index ^ key->tag ^ key->fid);
1011 static gboolean _9p_hash_free_all(gpointer key _U_, gpointer value _U_, gpointer user_data _U_)
1013 return TRUE;
1016 static void _9p_hash_free_val(gpointer value)
1018 struct _9p_hashval *val = (struct _9p_hashval *)value;
1020 if (val->data && val->len) {
1021 g_free(val->data);
1022 val->data = NULL;
1025 g_free(value);
1028 static struct _9p_hashval *_9p_hash_new_val(gsize len)
1030 struct _9p_hashval *val;
1031 val = (struct _9p_hashval *)g_malloc(sizeof(struct _9p_hashval));
1033 val->data = g_malloc(len);
1034 val->len = len;
1036 return val;
1039 static void _9p_hash_init(void)
1041 if (_9p_hashtable != NULL) {
1042 g_hash_table_foreach_remove(_9p_hashtable, _9p_hash_free_all, NULL);
1043 } else {
1044 _9p_hashtable = g_hash_table_new_full(_9p_hash_hash, _9p_hash_equal, g_free, _9p_hash_free_val);
1048 static void _9p_hash_set(packet_info *pinfo, guint16 tag, guint32 fid, struct _9p_hashval *val)
1050 struct _9p_hashkey *key;
1051 struct _9p_hashval *oldval;
1052 conversation_t *conv;
1054 conv = find_or_create_conversation(pinfo);
1056 key = (struct _9p_hashkey *)g_malloc(sizeof(struct _9p_hashkey));
1058 key->conv_index = conv->index;
1059 key->tag = tag;
1060 key->fid = fid;
1062 /* remove eventual old entry */
1063 oldval = (struct _9p_hashval *)g_hash_table_lookup(_9p_hashtable, key);
1064 if (oldval) {
1065 g_hash_table_remove(_9p_hashtable, key);
1067 g_hash_table_insert(_9p_hashtable, key, val);
1070 static struct _9p_hashval *_9p_hash_get(packet_info *pinfo, guint16 tag, guint32 fid)
1072 struct _9p_hashkey key;
1073 conversation_t *conv;
1075 conv = find_or_create_conversation(pinfo);
1077 key.conv_index = conv->index;
1078 key.tag = tag;
1079 key.fid = fid;
1081 return (struct _9p_hashval *)g_hash_table_lookup(_9p_hashtable, &key);
1084 static void _9p_hash_free(packet_info *pinfo, guint16 tag, guint32 fid)
1086 struct _9p_hashkey key;
1087 conversation_t *conv;
1089 conv = find_or_create_conversation(pinfo);
1091 key.conv_index = conv->index;
1092 key.tag = tag;
1093 key.fid = fid;
1095 g_hash_table_remove(_9p_hashtable, &key);
1098 static void conv_set_version(packet_info *pinfo, enum _9p_version version)
1100 struct _9p_hashval *val;
1102 val = _9p_hash_new_val(sizeof(enum _9p_version));
1105 *(enum _9p_version*)val->data = version;
1107 _9p_hash_set(pinfo, _9P_NOTAG, _9P_NOFID, val);
1110 static enum _9p_version conv_get_version(packet_info *pinfo)
1112 struct _9p_hashval *val;
1114 val = _9p_hash_get(pinfo, _9P_NOTAG, _9P_NOFID);
1116 return val ? *(enum _9p_version*)val->data : _9P;
1119 static void conv_set_fid_nocopy(packet_info *pinfo, guint32 fid, const char *path)
1121 struct _9p_hashval *val;
1123 if (!FIRSTPASS(pinfo) || fid == _9P_NOFID)
1124 return;
1126 /* get or create&insert fid tree */
1127 val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1128 if (!val) {
1129 val = _9p_hash_new_val(0);
1130 val->data = wmem_tree_new(wmem_file_scope());
1131 /* val->len is intentionnaly left to 0 so the tree won't be freed */
1132 _9p_hash_set(pinfo, _9P_NOTAG, fid, val);
1135 /* fill it */
1136 wmem_tree_insert32((wmem_tree_t*)val->data, pinfo->fd->num, (void*)path);
1139 static void conv_set_fid(packet_info *pinfo, guint32 fid, const gchar *path, gsize len)
1141 char *str;
1143 if (!FIRSTPASS(pinfo) || fid == _9P_NOFID || len == 0)
1144 return;
1146 str = (char*)wmem_alloc(wmem_file_scope(), len);
1147 g_strlcpy(str, path, len);
1148 conv_set_fid_nocopy(pinfo, fid, str);
1151 static const char *conv_get_fid(packet_info *pinfo, guint32 fid)
1153 struct _9p_hashval *val;
1155 if (fid == _9P_NOFID)
1156 return invalid_fid_str;
1158 val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1159 if (!val)
1160 return invalid_fid_str;
1162 /* -1 because the fid needs to have been set on a previous message.
1163 Let's ignore the possibility of num == 0... */
1164 return (char*)wmem_tree_lookup32_le((wmem_tree_t*)val->data, pinfo->fd->num-1);
1167 static inline void conv_free_fid(packet_info *pinfo, guint32 fid)
1169 conv_set_fid_nocopy(pinfo, fid, invalid_fid_str);
1172 static void conv_set_tag(packet_info *pinfo, guint16 tag, enum _9p_msg_t msgtype, guint32 fid, wmem_strbuf_t *fid_path)
1174 struct _9p_hashval *val;
1175 struct _9p_taginfo *taginfo;
1177 if (!FIRSTPASS(pinfo) || tag == _9P_NOTAG)
1178 return;
1180 val = _9p_hash_new_val(sizeof(struct _9p_taginfo));
1181 taginfo = (struct _9p_taginfo*)val->data;
1183 taginfo->msgtype = msgtype;
1184 taginfo->fid = fid;
1185 if (fid_path) {
1186 taginfo->fid_path = (char*)wmem_alloc(wmem_file_scope(), wmem_strbuf_get_len(fid_path)+1);
1187 g_strlcpy(taginfo->fid_path, wmem_strbuf_get_str(fid_path), wmem_strbuf_get_len(fid_path)+1);
1188 } else {
1189 taginfo->fid_path = NULL;
1192 _9p_hash_set(pinfo, tag, _9P_NOFID, val);
1195 static inline struct _9p_taginfo *conv_get_tag(packet_info *pinfo, guint16 tag)
1197 struct _9p_hashval *val;
1199 /* get tag only makes sense on first pass, as tree isn't built like fid */
1200 if (!FIRSTPASS(pinfo) || tag == _9P_NOTAG)
1201 return NULL;
1203 /* check that length matches? */
1204 val = _9p_hash_get(pinfo, tag, _9P_NOFID);
1206 return val ? (struct _9p_taginfo*)val->data : NULL;
1209 static inline void conv_free_tag(packet_info *pinfo, guint16 tag)
1211 if (!FIRSTPASS(pinfo) || tag == _9P_NOTAG)
1212 return;
1214 _9p_hash_free(pinfo, tag, _9P_NOFID);
1217 /* Dissect 9P messages*/
1218 static int dissect_9P(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1220 guint32 u32, i, fid, dfid, newfid;
1221 guint16 u16, tag, _9p_len;
1222 enum _9p_msg_t ninemsg;
1223 guint offset = 0;
1224 const char *mname, *fid_path;
1225 char *tvb_s;
1226 wmem_strbuf_t *tmppath = NULL;
1227 gint len, reportedlen;
1228 tvbuff_t *next_tvb;
1229 proto_item *ti;
1230 proto_tree *ninep_tree, *sub_tree;
1231 struct _9p_taginfo* taginfo;
1232 nstime_t tv;
1233 int _9p_version;
1234 const int firstpass = FIRSTPASS(pinfo);
1236 _9p_version = conv_get_version(pinfo);
1237 col_set_str(pinfo->cinfo, COL_PROTOCOL, val_to_str_ext_const(_9p_version, &ninep_version_ext, "9P"));
1239 col_clear(pinfo->cinfo, COL_INFO);
1241 /*ninesz = tvb_get_letohl(tvb, offset);*/
1242 ninemsg = (enum _9p_msg_t)tvb_get_guint8(tvb, offset + 4);
1244 mname = val_to_str_ext_const(ninemsg, &ninep_msg_type_ext, "Unknown");
1246 if(strcmp(mname, "Unknown") == 0) {
1247 col_add_fstr(pinfo->cinfo, COL_INFO, "9P Data (Message type %u)", (guint)ninemsg);
1248 return 0;
1251 tag = tvb_get_letohs(tvb, offset+5);
1252 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Tag=%u", mname, (guint)tag);
1254 ti = proto_tree_add_item(tree, proto_9P, tvb, 0, -1, ENC_NA);
1255 ninep_tree = proto_item_add_subtree(ti, ett_9P);
1256 proto_tree_add_item(ninep_tree, hf_9P_msgsz, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1257 offset+=4;
1259 proto_tree_add_item(ninep_tree, hf_9P_msgtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1260 ++offset;
1261 proto_tree_add_item(ninep_tree, hf_9P_tag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1262 offset += 2;
1264 switch(ninemsg) {
1265 case _9P_RVERSION:
1266 case _9P_TVERSION:
1267 proto_tree_add_item(ninep_tree, hf_9P_maxsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1268 offset +=4;
1270 _9p_len = tvb_get_letohs(tvb, offset);
1271 ti = proto_tree_add_item(ninep_tree, hf_9P_version, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1272 sub_tree = proto_item_add_subtree(ti, ett_9P_version);
1273 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1275 if (firstpass) {
1276 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1278 if (!strncmp(tvb_s, "9P2000.L", _9p_len)) {
1279 u32 = _9P2000_L;
1280 } else if (!strncmp(tvb_s, "9P2000", _9p_len)) {
1281 u32 = _9P2000;
1282 } else if (!strncmp(tvb_s, "9P2000.u", _9p_len)) {
1283 u32 = _9P2000_u;
1284 } else {
1285 u32 = _9P;
1288 conv_set_version(pinfo, (enum _9p_version)u32);
1289 g_free(tvb_s);
1292 /* don't set tag for tversion/free it for rversion,
1293 we need that for the actual version number */
1294 break;
1296 case _9P_TAUTH:
1297 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1298 fid = tvb_get_letohl(tvb, offset);
1299 conv_set_fid_nocopy(pinfo, fid, afid_str);
1300 offset +=4;
1302 _9p_len = tvb_get_letohs(tvb, offset);
1303 ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1304 sub_tree = proto_item_add_subtree(ti, ett_9P_uname);
1305 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1306 offset += _9p_len+2;
1308 _9p_len = tvb_get_letohs(tvb, offset);
1309 ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1310 sub_tree = proto_item_add_subtree(ti, ett_9P_aname);
1311 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1312 offset +=2;
1314 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1315 break;
1317 case _9P_RERROR:
1318 if (_9p_version == _9P2000_L) {
1319 u32 = tvb_get_letohl(tvb, offset);
1320 ti = proto_tree_add_item(ninep_tree, hf_9P_enum, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1321 proto_item_append_text(ti, " (%s)", g_strerror(u32));
1322 offset += 4;
1323 } else {
1324 _9p_len = tvb_get_letohs(tvb, offset);
1325 ti = proto_tree_add_item(ninep_tree, hf_9P_ename, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1326 sub_tree = proto_item_add_subtree(ti, ett_9P_ename);
1327 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1328 offset += 2 + _9p_len;
1331 /* conv_get_tag checks we're in first pass */
1332 taginfo = conv_get_tag(pinfo, tag);
1333 if (taginfo && (taginfo->msgtype == _9P_TWALK || taginfo->msgtype == _9P_TATTACH))
1334 conv_free_fid(pinfo, taginfo->fid);
1336 conv_free_tag(pinfo, tag);
1337 break;
1339 case _9P_TFLUSH:
1340 u16 = tvb_get_letohs(tvb, offset);
1341 proto_tree_add_item(ninep_tree, hf_9P_oldtag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1342 conv_free_tag(pinfo, u16);
1344 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1345 break;
1347 case _9P_TATTACH:
1348 fid = tvb_get_letohl(tvb, offset);
1349 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1350 offset +=4;
1352 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1353 offset +=4;
1355 _9p_len = tvb_get_letohs(tvb, offset);
1356 ti = proto_tree_add_item(ninep_tree, hf_9P_uname, tvb, offset+2, _9p_len, ENC_ASCII|ENC_NA);
1357 sub_tree = proto_item_add_subtree(ti, ett_9P_uname);
1358 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1359 offset += _9p_len + 2;
1361 _9p_len = tvb_get_letohs(tvb, offset);
1362 ti = proto_tree_add_item(ninep_tree, hf_9P_aname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1363 sub_tree = proto_item_add_subtree(ti, ett_9P_aname);
1364 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1365 if(firstpass) {
1366 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1367 conv_set_fid(pinfo, fid, tvb_s, _9p_len+1);
1368 g_free(tvb_s);
1370 offset += _9p_len+2;
1372 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1374 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1375 break;
1377 case _9P_TWALK:
1378 fid = tvb_get_letohl(tvb, offset);
1379 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1380 fid_path = conv_get_fid(pinfo, fid);
1381 proto_item_append_text(ti, " (%s)", fid_path);
1382 if (firstpass) {
1383 tmppath = wmem_strbuf_sized_new(wmem_packet_scope(), 0, MAXPATHLEN);
1384 wmem_strbuf_append(tmppath, fid_path);
1386 offset +=4;
1388 fid = tvb_get_letohl(tvb, offset);
1389 proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1390 offset +=4;
1392 u16 = tvb_get_letohs(tvb, offset);
1393 proto_tree_add_item(ninep_tree, hf_9P_nwalk, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1394 offset +=2;
1395 /* I can't imagine anyone having a directory depth more than 25,
1396 Limit to 10 times that to be sure, 2^16 is too much */
1397 if(u16 > 250) {
1398 sub_tree = proto_tree_add_text(ninep_tree, tvb, 0, 0, "Only first 250 items shown");
1399 PROTO_ITEM_SET_GENERATED(sub_tree);
1402 for(i = 0 ; i < u16; i++) {
1403 _9p_len = tvb_get_letohs(tvb, offset);
1405 if (i < 250) {
1406 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1407 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1408 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1411 if (firstpass) {
1412 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1413 wmem_strbuf_append_c(tmppath, '/');
1414 wmem_strbuf_append(tmppath, tvb_s);
1415 g_free(tvb_s);
1418 offset += _9p_len + 2;
1421 if (firstpass) {
1422 conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1425 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1426 break;
1428 case _9P_RWALK:
1429 u16 = tvb_get_letohs(tvb, offset);
1430 proto_tree_add_item(ninep_tree, hf_9P_nqid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1431 offset +=2;
1432 /* I can't imagine anyone having a directory depth more than 25,
1433 Limit to 10 times that to be sure, 2^16 is too much */
1434 if(u16 > 250) {
1435 u16 = 250;
1436 sub_tree = proto_tree_add_text(ninep_tree, tvb, 0, 0, "Only first 250 items shown");
1437 PROTO_ITEM_SET_GENERATED(sub_tree);
1440 for(i = 0; i < u16; i++) {
1441 dissect_9P_qid(tvb, ninep_tree, offset);
1442 offset += 13;
1445 conv_free_tag(pinfo, tag);
1446 break;
1447 case _9P_TLOPEN:
1448 fid = tvb_get_letohl(tvb, offset);
1449 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1450 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1451 offset +=4;
1453 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1454 dissect_9P_lflags(tvb, ti, offset);
1455 offset += 4;
1456 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1457 break;
1459 case _9P_TOPEN:
1460 fid = tvb_get_letohl(tvb, offset);
1461 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1462 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1463 offset +=4;
1465 ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1466 dissect_9P_mode(tvb, ti, offset);
1467 offset += 1;
1469 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1470 break;
1472 case _9P_TCREATE:
1473 fid = tvb_get_letohl(tvb, offset);
1474 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1475 fid_path = conv_get_fid(pinfo, fid);
1476 proto_item_append_text(ti, " (%s)", fid_path);
1477 offset +=4;
1479 _9p_len = tvb_get_letohs(tvb, offset);
1480 ti = proto_tree_add_item(ninep_tree, hf_9P_name, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1481 sub_tree = proto_item_add_subtree(ti, ett_9P_filename);
1482 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1483 if (firstpass) {
1484 tmppath = wmem_strbuf_sized_new(wmem_packet_scope(), 0, MAXPATHLEN);
1485 wmem_strbuf_append(tmppath, fid_path);
1486 wmem_strbuf_append_c(tmppath, '/');
1487 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1488 wmem_strbuf_append(tmppath, tvb_s);
1489 g_free(tvb_s);
1491 offset += _9p_len + 2;
1493 ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1494 dissect_9P_dm(tvb, ti, offset, 1);
1495 offset +=4;
1497 ti = proto_tree_add_item(ninep_tree, hf_9P_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1498 dissect_9P_mode(tvb, ti, offset);
1499 offset +=1;
1501 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1502 offset += 4;
1504 conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1505 break;
1507 case _9P_TLCREATE:
1508 fid = tvb_get_letohl(tvb, offset);
1509 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1510 fid_path = conv_get_fid(pinfo, fid);
1511 proto_item_append_text(ti, " (%s)", fid_path);
1512 offset +=4;
1514 _9p_len = tvb_get_letohs(tvb, offset);
1515 ti = proto_tree_add_item(ninep_tree, hf_9P_name, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1516 sub_tree = proto_item_add_subtree(ti, ett_9P_filename);
1517 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1518 if (firstpass) {
1519 tmppath = wmem_strbuf_sized_new(wmem_packet_scope(), 0, MAXPATHLEN);
1520 wmem_strbuf_append(tmppath, fid_path);
1521 wmem_strbuf_append_c(tmppath, '/');
1522 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1523 wmem_strbuf_append(tmppath, tvb_s);
1524 g_free(tvb_s);
1526 offset += _9p_len + 2;
1528 ti = proto_tree_add_item(ninep_tree, hf_9P_lflags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1529 dissect_9P_lflags(tvb, ti, offset);
1530 offset += 4;
1532 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1533 dissect_9P_dm(tvb, ti, offset, 0);
1534 offset += 4;
1536 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1537 offset += 4;
1539 conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1540 break;
1542 case _9P_TREAD:
1543 case _9P_TREADDIR:
1544 fid = tvb_get_letohl(tvb, offset);
1545 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1546 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1547 offset +=4;
1549 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1550 offset +=8;
1552 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1553 offset +=4;
1555 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1556 break;
1558 case _9P_RREAD:
1559 case _9P_RREADDIR:
1560 u32 = tvb_get_letohl(tvb, offset);
1561 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1562 offset += 4;
1564 len = tvb_reported_length_remaining(tvb, offset);
1565 reportedlen = ((gint)u32&0xffff) > len ? len : (gint)u32&0xffff;
1566 next_tvb = tvb_new_subset(tvb, offset, len, reportedlen);
1567 call_dissector(data_handle, next_tvb, pinfo, tree);
1569 conv_free_tag(pinfo, tag);
1570 break;
1572 case _9P_TWRITE:
1573 fid = tvb_get_letohl(tvb, offset);
1574 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1575 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1576 offset +=4;
1578 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1579 offset +=8;
1581 u32 = tvb_get_letohl(tvb, offset);
1582 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1583 offset += 4;
1584 len = tvb_reported_length_remaining(tvb, offset);
1585 reportedlen = ((gint)u32&0xffff) > len ? len : (gint)u32&0xffff;
1586 next_tvb = tvb_new_subset(tvb, offset, len, reportedlen);
1587 call_dissector(data_handle, next_tvb, pinfo, tree);
1589 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1590 break;
1592 case _9P_RWRITE:
1593 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1595 conv_free_tag(pinfo, tag);
1596 break;
1598 case _9P_RSTAT:
1599 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1600 offset +=2;
1602 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1603 offset +=2;
1605 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1606 offset +=2;
1608 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1609 offset +=4;
1611 dissect_9P_qid(tvb, ninep_tree, offset);
1612 offset += 13;
1614 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1615 dissect_9P_dm(tvb, ti, offset, 0);
1616 offset +=4;
1618 tv.secs = tvb_get_letohl(tvb, offset);
1619 tv.nsecs = 0;
1620 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
1621 offset +=4;
1623 tv.secs = tvb_get_letohl(tvb, offset);
1624 tv.nsecs = 0;
1625 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 4, &tv);
1626 offset +=4;
1628 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1629 offset +=8;
1631 _9p_len = tvb_get_letohs(tvb, offset);
1632 ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1633 sub_tree = proto_item_add_subtree(ti, ett_9P_filename);
1634 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1635 offset += _9p_len+2;
1637 _9p_len = tvb_get_letohs(tvb, offset);
1638 ti = proto_tree_add_item(ninep_tree, hf_9P_user, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1639 sub_tree = proto_item_add_subtree(ti, ett_9P_user);
1640 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1641 offset += _9p_len+2;
1643 _9p_len = tvb_get_letohs(tvb, offset);
1644 ti = proto_tree_add_item(ninep_tree, hf_9P_group, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1645 sub_tree = proto_item_add_subtree(ti, ett_9P_group);
1646 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1647 offset += _9p_len+2;
1649 _9p_len = tvb_get_letohs(tvb, offset);
1650 ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1651 sub_tree = proto_item_add_subtree(ti, ett_9P_muid);
1652 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1653 offset += _9p_len+2;
1655 conv_free_tag(pinfo, tag);
1656 break;
1658 case _9P_TWSTAT:
1659 fid = tvb_get_letohl(tvb, offset);
1660 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1661 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1662 offset += 4;
1664 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1665 offset +=2;
1667 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1668 offset +=2;
1670 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1671 offset +=2;
1673 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1674 offset +=4;
1676 dissect_9P_qid(tvb, ninep_tree, offset);
1677 offset += 13;
1679 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1680 dissect_9P_dm(tvb, ti, offset, 0);
1681 offset +=4;
1683 tv.secs = tvb_get_letohl(tvb, offset);
1684 tv.nsecs = 0;
1685 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 4, &tv);
1686 offset +=4;
1688 tv.secs = tvb_get_letohl(tvb, offset);
1689 tv.nsecs = 0;
1690 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 4, &tv);
1691 offset +=4;
1693 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1694 offset +=8;
1696 _9p_len = tvb_get_letohs(tvb, offset);
1697 ti = proto_tree_add_item(ninep_tree, hf_9P_filename, tvb, offset+2, _9p_len, ENC_ASCII|ENC_NA);
1698 sub_tree = proto_item_add_subtree(ti, ett_9P_filename);
1699 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1700 offset += _9p_len+2;
1702 _9p_len = tvb_get_letohs(tvb, offset);
1703 ti = proto_tree_add_item(ninep_tree, hf_9P_user, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1704 sub_tree = proto_item_add_subtree(ti, ett_9P_user);
1705 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1706 offset += _9p_len+2;
1708 _9p_len = tvb_get_letohs(tvb, offset);
1709 ti = proto_tree_add_item(ninep_tree, hf_9P_group, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1710 sub_tree = proto_item_add_subtree(ti, ett_9P_group);
1711 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1712 offset += _9p_len+2;
1714 _9p_len = tvb_get_letohs(tvb, offset);
1715 ti = proto_tree_add_item(ninep_tree, hf_9P_muid, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1716 sub_tree = proto_item_add_subtree(ti, ett_9P_muid);
1717 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1718 offset += _9p_len+2;
1720 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1721 break;
1723 case _9P_TGETATTR:
1724 fid = tvb_get_letohl(tvb, offset);
1725 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1726 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1727 offset += 4;
1729 ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1730 dissect_9P_getattrflags(tvb, ti, offset);
1731 offset += 8;
1733 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1734 break;
1736 case _9P_RGETATTR:
1737 ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1738 dissect_9P_getattrflags(tvb, ti, offset);
1739 offset += 8;
1741 dissect_9P_qid(tvb, ninep_tree, offset);
1742 offset += 13;
1744 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1745 dissect_9P_dm(tvb, ti, offset, 0);
1746 offset += 4;
1748 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1749 offset += 4;
1751 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1752 offset += 4;
1754 proto_tree_add_item(ninep_tree, hf_9P_nlink, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1755 offset += 8;
1757 proto_tree_add_item(ninep_tree, hf_9P_rdev, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1758 offset += 8;
1760 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1761 offset += 8;
1763 proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1764 offset += 8;
1766 proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1767 offset += 8;
1769 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1770 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1771 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 16, &tv);
1772 offset += 16;
1774 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1775 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1776 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 16, &tv);
1777 offset += 16;
1779 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1780 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1781 proto_tree_add_time(ninep_tree, hf_9P_ctime, tvb, offset, 16, &tv);
1782 offset += 16;
1784 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1785 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1786 proto_tree_add_time(ninep_tree, hf_9P_btime, tvb, offset, 16, &tv);
1787 offset += 16;
1789 proto_tree_add_item(ninep_tree, hf_9P_gen, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1790 offset += 8;
1792 proto_tree_add_item(ninep_tree, hf_9P_dataversion, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1793 offset += 8;
1795 conv_free_tag(pinfo, tag);
1796 break;
1798 case _9P_TSETATTR:
1799 fid = tvb_get_letohl(tvb, offset);
1800 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1801 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1802 offset += 4;
1804 ti = proto_tree_add_item(ninep_tree, hf_9P_setattr_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1805 dissect_9P_setattrflags(tvb, ti, offset);
1806 offset += 4;
1808 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1809 dissect_9P_dm(tvb, ti, offset, 0);
1810 offset += 4;
1812 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1813 offset += 4;
1815 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1816 offset += 4;
1818 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1819 offset += 8;
1821 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1822 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1823 proto_tree_add_time(ninep_tree, hf_9P_atime, tvb, offset, 16, &tv);
1824 offset += 16;
1826 tv.secs = (time_t)tvb_get_letoh64(tvb, offset);
1827 tv.nsecs = (guint32)tvb_get_letoh64(tvb, offset+8);
1828 proto_tree_add_time(ninep_tree, hf_9P_mtime, tvb, offset, 16, &tv);
1829 offset += 16;
1831 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1832 break;
1834 case _9P_RSTATFS:
1835 proto_tree_add_item(ninep_tree, hf_9P_fstype, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1836 offset += 4;
1838 proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1839 offset += 4;
1841 proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1842 offset += 8;
1844 proto_tree_add_item(ninep_tree, hf_9P_bfree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1845 offset += 8;
1847 proto_tree_add_item(ninep_tree, hf_9P_bavail, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1848 offset += 8;
1850 proto_tree_add_item(ninep_tree, hf_9P_files, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1851 offset += 8;
1853 proto_tree_add_item(ninep_tree, hf_9P_ffree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1854 offset += 8;
1856 proto_tree_add_item(ninep_tree, hf_9P_fsid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1857 offset += 8;
1859 proto_tree_add_item(ninep_tree, hf_9P_namelen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1860 offset += 4;
1862 conv_free_tag(pinfo, tag);
1863 break;
1865 case _9P_TSYMLINK:
1866 fid = tvb_get_letohl(tvb, offset);
1867 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1868 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1869 offset += 4;
1871 _9p_len = tvb_get_letohs(tvb, offset);
1872 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1873 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1874 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1875 offset += _9p_len + 2;
1877 _9p_len = tvb_get_letohs(tvb, offset);
1878 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1879 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1880 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1881 offset += _9p_len + 2;
1883 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1884 offset += 4;
1886 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1887 break;
1889 case _9P_TMKNOD:
1890 fid = tvb_get_letohl(tvb, offset);
1891 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1892 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1893 offset += 4;
1895 _9p_len = tvb_get_letohs(tvb, offset);
1896 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1897 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1898 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1899 offset += _9p_len + 2;
1901 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1902 dissect_9P_dm(tvb, ti, offset, 0);
1903 offset += 4;
1905 proto_tree_add_item(ninep_tree, hf_9P_mknod_major, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1906 offset += 4;
1908 proto_tree_add_item(ninep_tree, hf_9P_mknod_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1909 offset += 4;
1911 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1912 offset += 4;
1914 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1915 break;
1917 case _9P_TRENAME:
1918 fid = tvb_get_letohl(tvb, offset);
1919 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1920 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1921 offset += 4;
1923 dfid = tvb_get_letohl(tvb, offset);
1924 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1925 fid_path = conv_get_fid(pinfo, dfid);
1926 proto_item_append_text(ti, " (%s)", fid_path);
1927 offset += 4;
1929 _9p_len = tvb_get_letohs(tvb, offset);
1930 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1931 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1932 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1933 if (firstpass) {
1934 tmppath = wmem_strbuf_sized_new(wmem_packet_scope(), 0, MAXPATHLEN);
1935 wmem_strbuf_append(tmppath, conv_get_fid(pinfo, dfid));
1936 wmem_strbuf_append_c(tmppath, '/');
1938 tvb_s = tvb_get_string(NULL, tvb, offset+2, _9p_len);
1939 wmem_strbuf_append(tmppath, tvb_s);
1940 g_free(tvb_s);
1942 conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1944 offset += _9p_len + 2;
1946 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1947 break;
1949 case _9P_RREADLINK:
1950 _9p_len = tvb_get_letohs(tvb, offset);
1951 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1952 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1953 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1954 offset += _9p_len + 2;
1956 conv_free_tag(pinfo, tag);
1957 break;
1959 case _9P_TXATTRWALK:
1960 fid = tvb_get_letohl(tvb, offset);
1961 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1962 fid_path = conv_get_fid(pinfo, fid);
1963 proto_item_append_text(ti, " (%s)", fid_path);
1964 offset +=4;
1966 newfid = tvb_get_letohl(tvb, offset);
1967 proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1968 conv_set_fid_nocopy(pinfo, newfid, fid_path);
1969 offset +=4;
1971 _9p_len = tvb_get_letohs(tvb, offset);
1972 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1973 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1974 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1975 offset += _9p_len + 2;
1977 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1978 break;
1980 case _9P_RXATTRWALK:
1981 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1982 offset += 8;
1984 conv_free_tag(pinfo, tag);
1985 break;
1987 case _9P_TXATTRCREATE:
1988 fid = tvb_get_letohl(tvb, offset);
1989 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1990 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1991 offset +=4;
1993 _9p_len = tvb_get_letohs(tvb, offset);
1994 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1995 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
1996 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1997 offset += _9p_len + 2;
1999 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2000 offset += 8;
2002 proto_tree_add_item(ninep_tree, hf_9P_xattr_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2003 offset += 4;
2005 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2006 break;
2008 case _9P_TLOCK:
2009 case _9P_TGETLOCK:
2010 fid = tvb_get_letohl(tvb, offset);
2011 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2012 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2013 offset += 4;
2015 proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2016 offset += 1;
2018 proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2019 offset += 4;
2021 proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2022 offset += 8;
2024 proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2025 offset += 8;
2027 proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2028 offset += 4;
2030 _9p_len = tvb_get_letohs(tvb, offset);
2031 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2032 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2033 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2034 offset += _9p_len + 2;
2036 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2037 break;
2039 case _9P_RLOCK:
2040 proto_tree_add_item(ninep_tree, hf_9P_lock_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2041 offset += 1;
2043 conv_free_tag(pinfo, tag);
2044 break;
2046 case _9P_RGETLOCK:
2047 proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2048 offset += 1;
2050 proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2051 offset += 4;
2053 proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2054 offset += 8;
2056 proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2057 offset += 8;
2059 proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2060 offset += 4;
2062 _9p_len = tvb_get_letohs(tvb, offset);
2063 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2064 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2065 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2066 offset += _9p_len + 2;
2068 conv_free_tag(pinfo, tag);
2069 break;
2071 case _9P_TLINK:
2072 fid = tvb_get_letohl(tvb, offset);
2073 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2074 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2075 offset += 4;
2077 fid = tvb_get_letohl(tvb, offset);
2078 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2079 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2080 offset += 4;
2082 _9p_len = tvb_get_letohs(tvb, offset);
2083 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2084 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2085 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2086 offset += _9p_len + 2;
2088 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2089 break;
2091 case _9P_TMKDIR:
2092 fid = tvb_get_letohl(tvb, offset);
2093 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2094 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2095 offset += 4;
2097 _9p_len = tvb_get_letohs(tvb, offset);
2098 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2099 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2100 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2101 offset += _9p_len + 2;
2103 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2104 dissect_9P_dm(tvb, ti, offset, 0);
2105 offset += 4;
2107 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2108 offset += 4;
2110 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2111 break;
2113 case _9P_TRENAMEAT:
2114 fid = tvb_get_letohl(tvb, offset);
2115 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2116 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2117 offset += 4;
2119 _9p_len = tvb_get_letohs(tvb, offset);
2120 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2121 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2122 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2123 offset += _9p_len + 2;
2125 fid = tvb_get_letohl(tvb, offset);
2126 ti = proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2127 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2128 offset += 4;
2130 _9p_len = tvb_get_letohs(tvb, offset);
2131 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2132 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2133 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2134 offset += _9p_len + 2;
2135 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2136 break;
2138 case _9P_TUNLINKAT:
2139 fid = tvb_get_letohl(tvb, offset);
2140 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2141 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2142 offset += 4;
2144 _9p_len = tvb_get_letohs(tvb, offset);
2145 ti = proto_tree_add_item(ninep_tree, hf_9P_wname, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
2146 sub_tree = proto_item_add_subtree(ti, ett_9P_wname);
2147 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
2148 offset += _9p_len + 2;
2150 /* missing 32bit flag, no clue what meaning it has */
2152 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2153 break;
2155 case _9P_TREMOVE:
2156 case _9P_TCLUNK:
2157 fid = tvb_get_letohl(tvb, offset);
2158 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2159 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2160 conv_free_fid(pinfo, fid);
2162 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
2163 break;
2165 /* Request with only fid */
2166 case _9P_TSTATFS:
2167 case _9P_TREADLINK:
2168 case _9P_TFSYNC:
2169 case _9P_TSTAT:
2170 fid = tvb_get_letohl(tvb, offset);
2171 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2172 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2174 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2175 break;
2177 /* Reply with qid and ionuit */
2178 case _9P_RCREATE:
2179 case _9P_RLCREATE:
2180 dissect_9P_qid(tvb, ninep_tree, offset);
2181 offset += 13;
2182 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2183 offset += 4;
2185 taginfo = conv_get_tag(pinfo, tag);
2186 if (taginfo && taginfo->fid_path) {
2187 conv_set_fid_nocopy(pinfo, taginfo->fid, taginfo->fid_path);
2190 conv_free_tag(pinfo, tag);
2191 break;
2193 case _9P_ROPEN:
2194 case _9P_RLOPEN:
2195 dissect_9P_qid(tvb, ninep_tree, offset);
2196 offset += 13;
2197 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2198 offset += 4;
2200 conv_free_tag(pinfo, tag);
2201 break;
2203 /* Reply with only qid */
2204 case _9P_RSYMLINK:
2205 case _9P_RMKNOD:
2206 case _9P_RMKDIR:
2207 case _9P_RAUTH:
2208 case _9P_RATTACH:
2209 dissect_9P_qid(tvb, ninep_tree, offset);
2210 offset += 13;
2212 conv_free_tag(pinfo, tag);
2213 break;
2215 /* Empty reply */
2216 case _9P_RRENAME:
2217 case _9P_RSETATTR:
2218 case _9P_RXATTRCREATE:
2219 case _9P_RFSYNC:
2220 case _9P_RLINK:
2221 case _9P_RRENAMEAT:
2222 case _9P_RUNLINKAT:
2223 case _9P_RFLUSH:
2224 case _9P_RCLUNK:
2225 case _9P_RREMOVE:
2226 /* Unhandled reply */
2227 case _9P_RWSTAT:
2228 case _9P_RLERROR:
2229 conv_free_tag(pinfo, tag);
2230 break;
2232 /* Should-not-happen query */
2233 case _9P_TLERROR:
2234 case _9P_TERROR:
2235 default:
2236 proto_tree_add_text(ninep_tree, tvb, 0, 0, "This message type should not happen");
2237 break;
2239 return offset;
2241 /* dissect 9P open mode flags */
2242 static void dissect_9P_mode(tvbuff_t *tvb, proto_item *item, int offset)
2244 proto_item *mode_tree;
2245 guint8 mode;
2247 mode = tvb_get_guint8(tvb, offset);
2248 mode_tree = proto_item_add_subtree(item, ett_9P_omode);
2249 if(!mode_tree)
2250 return;
2251 proto_tree_add_boolean(mode_tree, hf_9P_mode_c, tvb, offset, 1, mode);
2252 proto_tree_add_boolean(mode_tree, hf_9P_mode_t, tvb, offset, 1, mode);
2253 proto_tree_add_uint(mode_tree, hf_9P_mode_rwx, tvb, offset, 1, mode);
2256 /* dissect 9P Qid */
2257 static void dissect_9P_qid(tvbuff_t *tvb, proto_tree *tree, int offset)
2259 proto_item *qid_item,*qidtype_item;
2260 proto_tree *qid_tree,*qidtype_tree;
2261 guint64 path;
2262 guint32 vers;
2263 guint8 type;
2265 if(!tree)
2266 return;
2268 type = tvb_get_guint8(tvb, offset);
2269 vers = tvb_get_letohs(tvb, offset+1);
2270 path = tvb_get_letoh64(tvb, offset+1+4);
2272 qid_item = proto_tree_add_text(tree, tvb, offset, 13, "Qid type=0x%02x vers=%d path=%" G_GINT64_MODIFIER "u", type, vers, path);
2273 qid_tree = proto_item_add_subtree(qid_item, ett_9P_qid);
2275 qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2276 qidtype_tree = proto_item_add_subtree(qidtype_item, ett_9P_qidtype);
2278 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2279 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_append, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2280 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_exclusive, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2281 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_mount, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2282 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_auth_file, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2283 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_temp_file, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2285 proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, ENC_LITTLE_ENDIAN);
2286 proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, ENC_LITTLE_ENDIAN);
2289 /*dissect 9P stat mode and create perm flags */
2290 static void dissect_9P_dm(tvbuff_t *tvb, proto_item *item, int offset, int iscreate)
2292 proto_item *mode_tree;
2295 mode_tree = proto_item_add_subtree(item, ett_9P_dm);
2296 if(!mode_tree)
2297 return;
2299 proto_tree_add_item(mode_tree, hf_9P_dm_dir, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2300 if(!iscreate) { /* Not applicable to Tcreate (?) */
2301 proto_tree_add_item(mode_tree, hf_9P_dm_append, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2302 proto_tree_add_item(mode_tree, hf_9P_dm_exclusive, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2303 proto_tree_add_item(mode_tree, hf_9P_dm_mount, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2304 proto_tree_add_item(mode_tree, hf_9P_dm_auth_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2305 proto_tree_add_item(mode_tree, hf_9P_dm_temp_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2308 proto_tree_add_item(mode_tree, hf_9P_dm_read_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2309 proto_tree_add_item(mode_tree, hf_9P_dm_write_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2310 proto_tree_add_item(mode_tree, hf_9P_dm_exec_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2311 proto_tree_add_item(mode_tree, hf_9P_dm_read_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2312 proto_tree_add_item(mode_tree, hf_9P_dm_write_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2313 proto_tree_add_item(mode_tree, hf_9P_dm_exec_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2314 proto_tree_add_item(mode_tree, hf_9P_dm_read_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2315 proto_tree_add_item(mode_tree, hf_9P_dm_write_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2316 proto_tree_add_item(mode_tree, hf_9P_dm_exec_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2319 /* Dissect 9P getattr_flags */
2320 static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_item *item, int offset)
2322 proto_item *attrmask_tree;
2324 attrmask_tree = proto_item_add_subtree(item, ett_9P_getattr_flags);
2325 if(!attrmask_tree)
2326 return;
2328 /* fixme: This is actually 8 bytes (64bit) long, but masks have to fit on 32bit. */
2329 proto_tree_add_item(attrmask_tree, hf_9P_getattr_mode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2330 proto_tree_add_item(attrmask_tree, hf_9P_getattr_nlink, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2331 proto_tree_add_item(attrmask_tree, hf_9P_getattr_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2332 proto_tree_add_item(attrmask_tree, hf_9P_getattr_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2333 proto_tree_add_item(attrmask_tree, hf_9P_getattr_rdev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2334 proto_tree_add_item(attrmask_tree, hf_9P_getattr_atime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2335 proto_tree_add_item(attrmask_tree, hf_9P_getattr_mtime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2336 proto_tree_add_item(attrmask_tree, hf_9P_getattr_ctime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2337 proto_tree_add_item(attrmask_tree, hf_9P_getattr_ino, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2338 proto_tree_add_item(attrmask_tree, hf_9P_getattr_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2339 proto_tree_add_item(attrmask_tree, hf_9P_getattr_blocks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2340 proto_tree_add_item(attrmask_tree, hf_9P_getattr_btime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2341 proto_tree_add_item(attrmask_tree, hf_9P_getattr_gen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2342 proto_tree_add_item(attrmask_tree, hf_9P_getattr_dataversion, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2345 /* Dissect 9P setattr_flags */
2346 static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_item *item, int offset)
2348 proto_item *attrmask_tree;
2350 attrmask_tree = proto_item_add_subtree(item, ett_9P_setattr_flags);
2351 if(!attrmask_tree)
2352 return;
2354 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2355 proto_tree_add_item(attrmask_tree, hf_9P_setattr_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2356 proto_tree_add_item(attrmask_tree, hf_9P_setattr_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2357 proto_tree_add_item(attrmask_tree, hf_9P_setattr_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2358 proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2359 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2360 proto_tree_add_item(attrmask_tree, hf_9P_setattr_ctime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2361 proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2362 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2365 /* Dissect 9P lflags */
2366 static void dissect_9P_lflags(tvbuff_t *tvb, proto_item *item, int offset)
2368 proto_item *attrmask_tree;
2370 attrmask_tree = proto_item_add_subtree(item, ett_9P_lflags);
2371 if(!attrmask_tree)
2372 return;
2374 proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdonly, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2375 proto_tree_add_item(attrmask_tree, hf_9P_lflags_wronly, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2376 proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdwr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2377 proto_tree_add_item(attrmask_tree, hf_9P_lflags_create, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2378 proto_tree_add_item(attrmask_tree, hf_9P_lflags_excl, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2379 proto_tree_add_item(attrmask_tree, hf_9P_lflags_noctty, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2380 proto_tree_add_item(attrmask_tree, hf_9P_lflags_trunc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2381 proto_tree_add_item(attrmask_tree, hf_9P_lflags_append, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2382 proto_tree_add_item(attrmask_tree, hf_9P_lflags_nonblock, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2383 proto_tree_add_item(attrmask_tree, hf_9P_lflags_dsync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2384 proto_tree_add_item(attrmask_tree, hf_9P_lflags_fasync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2385 proto_tree_add_item(attrmask_tree, hf_9P_lflags_direct, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2386 proto_tree_add_item(attrmask_tree, hf_9P_lflags_largefile, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2387 proto_tree_add_item(attrmask_tree, hf_9P_lflags_directory, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2388 proto_tree_add_item(attrmask_tree, hf_9P_lflags_nofollow, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2389 proto_tree_add_item(attrmask_tree, hf_9P_lflags_noatime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2390 proto_tree_add_item(attrmask_tree, hf_9P_lflags_cloexec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2391 proto_tree_add_item(attrmask_tree, hf_9P_lflags_sync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2395 /* Register 9P with Wireshark */
2396 void proto_register_9P(void)
2398 static hf_register_info hf[] = {
2399 {&hf_9P_msgsz,
2400 {"Msg length", "9p.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
2401 "9P Message Length", HFILL}},
2402 {&hf_9P_msgtype,
2403 {"Msg Type", "9p.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ninep_msg_type_ext, 0x0,
2404 "Message Type", HFILL}},
2405 {&hf_9P_tag,
2406 {"Tag", "9p.tag", FT_UINT16, BASE_DEC, NULL, 0x0,
2407 "9P Tag", HFILL}},
2408 {&hf_9P_oldtag,
2409 {"Old tag", "9p.oldtag", FT_UINT16, BASE_DEC, NULL, 0x0,
2410 NULL, HFILL}},
2411 {&hf_9P_parmsz,
2412 {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
2413 "Parameter length", HFILL}},
2414 {&hf_9P_maxsize,
2415 {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
2416 "Max message size", HFILL}},
2417 {&hf_9P_fid,
2418 {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
2419 "File ID", HFILL}},
2420 {&hf_9P_nqid,
2421 {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
2422 "Number of Qid results", HFILL}},
2423 {&hf_9P_mode,
2424 {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
2425 NULL, HFILL}},
2426 {&hf_9P_mode_rwx,
2427 {"Open/Create Mode", "9p.mode.rwx", FT_UINT8, BASE_OCT | BASE_EXT_STRING, &ninep_mode_vals_ext, _9P_MODEMASK,
2428 NULL, HFILL}},
2429 {&hf_9P_mode_t,
2430 {"Trunc", "9p.mode.trunc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_OTRUNC,
2431 "Truncate", HFILL}},
2432 {&hf_9P_mode_c,
2433 {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_ORCLOSE,
2434 NULL, HFILL}},
2435 {&hf_9P_iounit,
2436 {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
2437 NULL, HFILL}},
2438 {&hf_9P_count,
2439 {"Count", "9p.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2440 NULL, HFILL}},
2441 {&hf_9P_offset,
2442 {"Offset", "9p.offset", FT_UINT64, BASE_DEC, NULL, 0x0,
2443 NULL, HFILL}},
2444 {&hf_9P_perm,
2445 {"Permissions", "9p.perm", FT_UINT32, BASE_OCT, NULL, 0x0,
2446 "Permission bits", HFILL}},
2447 {&hf_9P_qidpath,
2448 {"Qid path", "9p.qidpath", FT_UINT64, BASE_DEC, NULL, 0x0,
2449 NULL, HFILL}},
2450 {&hf_9P_dm_dir,
2451 {"Directory", "9p.dm.dir", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x80000000,
2452 NULL, HFILL}},
2453 {&hf_9P_dm_append,
2454 {"Append only", "9p.dm.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x40000000,
2455 NULL, HFILL}},
2456 {&hf_9P_dm_exclusive,
2457 {"Exclusive use", "9p.dm.exclusive", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x20000000,
2458 NULL, HFILL}},
2459 {&hf_9P_dm_mount,
2460 {"Mounted channel", "9p.dm.mount", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x10000000,
2461 NULL, HFILL}},
2462 {&hf_9P_dm_auth_file,
2463 {"Authentication file", "9p.dm.auth_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x08000000,
2464 NULL, HFILL}},
2465 {&hf_9P_dm_temp_file,
2466 {"Temporary file (not backed up)", "9p.dm.temp_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x04000000,
2467 NULL, HFILL}},
2468 {&hf_9P_dm_read_owner,
2469 {"Read permission for owner", "9p.dm.read_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000400,
2470 NULL, HFILL}},
2471 {&hf_9P_dm_write_owner,
2472 {"Write permission for owner", "9p.dm.write_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000200,
2473 NULL, HFILL}},
2474 {&hf_9P_dm_exec_owner,
2475 {"Execute permission for owner", "9p.dm.exec_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000100,
2476 NULL, HFILL}},
2477 {&hf_9P_dm_read_group,
2478 {"Read permission for group", "9p.dm.read_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000040,
2479 NULL, HFILL}},
2480 {&hf_9P_dm_write_group,
2481 {"Write permission for group", "9p.dm.write_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000020,
2482 NULL, HFILL}},
2483 {&hf_9P_dm_exec_group,
2484 {"Execute permission for group", "9p.dm.exec_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000010,
2485 NULL, HFILL}},
2486 {&hf_9P_dm_read_others,
2487 {"Read permission for others", "9p.dm.read_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
2488 NULL, HFILL}},
2489 {&hf_9P_dm_write_others,
2490 {"Write permission for others", "9p.dm.write_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
2491 NULL, HFILL}},
2492 {&hf_9P_dm_exec_others,
2493 {"Execute permission for others", "9p.dm.exec_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
2494 NULL, HFILL}},
2495 {&hf_9P_qidvers,
2496 {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
2497 NULL, HFILL}},
2498 {&hf_9P_qidtype,
2499 {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
2500 NULL, HFILL}},
2501 {&hf_9P_qidtype_dir,
2502 {"Directory", "9p.qidtype.dir", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
2503 NULL, HFILL}},
2504 {&hf_9P_qidtype_append,
2505 {"Append only", "9p.qidtype.append", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
2506 NULL, HFILL}},
2507 {&hf_9P_qidtype_exclusive,
2508 {"Exclusive use", "9p.qidtype.exclusive", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2509 NULL, HFILL}},
2510 {&hf_9P_qidtype_mount,
2511 {"Mounted channel", "9p.qidtype.mount", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
2512 NULL, HFILL}},
2513 {&hf_9P_qidtype_auth_file,
2514 {"Authentication file", "9p.qidtype.auth_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
2515 NULL, HFILL}},
2516 {&hf_9P_qidtype_temp_file,
2517 {"Temporary file (not backed up)", "9p.qidtype.temp_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2518 NULL, HFILL}},
2519 {&hf_9P_statmode,
2520 {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
2521 "File mode flags", HFILL}},
2522 {&hf_9P_stattype,
2523 {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
2524 NULL, HFILL}},
2525 {&hf_9P_atime,
2526 {"Atime", "9p.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2527 "Access Time", HFILL}},
2528 {&hf_9P_mtime,
2529 {"Mtime", "9p.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2530 "Modified Time", HFILL}},
2531 {&hf_9P_ctime,
2532 {"Ctime", "9p.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2533 "Creation Time", HFILL}},
2534 {&hf_9P_btime,
2535 {"Btime", "9p.btime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2536 "Btime (Synchronization information)", HFILL}},
2537 {&hf_9P_length,
2538 {"Length", "9p.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2539 "File Length", HFILL}},
2540 {&hf_9P_dev,
2541 {"Dev", "9p.dev", FT_UINT32, BASE_DEC, NULL, 0x0,
2542 NULL, HFILL}},
2543 {&hf_9P_wname,
2544 {"Wname", "9p.wname", FT_STRING, BASE_NONE, NULL, 0x0,
2545 "Path Name Element", HFILL}},
2546 {&hf_9P_version,
2547 {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
2548 NULL, HFILL}},
2549 {&hf_9P_afid,
2550 {"Afid", "9p.afid", FT_UINT32, BASE_DEC, NULL, 0x0,
2551 "Authenticating FID", HFILL}},
2552 {&hf_9P_uname,
2553 {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
2554 "User Name", HFILL}},
2555 {&hf_9P_aname,
2556 {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
2557 "Access Name", HFILL}},
2558 {&hf_9P_ename,
2559 {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
2560 "Error", HFILL}},
2561 {&hf_9P_enum,
2562 {"Enum", "9p.enum", FT_UINT32, BASE_DEC, NULL, 0x0,
2563 "Error", HFILL}},
2564 {&hf_9P_name,
2565 {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
2566 "Name of file", HFILL}},
2567 {&hf_9P_sdlen,
2568 {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
2569 NULL, HFILL}},
2570 {&hf_9P_filename,
2571 {"File name", "9p.filename", FT_STRING, BASE_NONE, NULL, 0x0,
2572 NULL, HFILL}},
2573 {&hf_9P_user,
2574 {"User", "9p.user", FT_STRING, BASE_NONE, NULL, 0x0,
2575 "User name", HFILL}},
2576 {&hf_9P_group,
2577 {"Group", "9p.group", FT_STRING, BASE_NONE, NULL, 0x0,
2578 "Group name", HFILL}},
2579 {&hf_9P_uid,
2580 {"Uid", "9p.uid", FT_UINT32, BASE_DEC, NULL, 0x0,
2581 "User id", HFILL}},
2582 {&hf_9P_gid,
2583 {"Gid", "9p.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
2584 "Group id", HFILL}},
2585 {&hf_9P_muid,
2586 {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
2587 "Last modifiers uid", HFILL}},
2588 {&hf_9P_newfid,
2589 {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2590 "New file ID", HFILL}},
2591 {&hf_9P_dfid,
2592 {"Directory fid", "9p.dfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2593 "Directory ID", HFILL}},
2594 {&hf_9P_nwalk,
2595 {"Nr Walks", "9p.nwalk", FT_UINT32, BASE_DEC, NULL, 0x0,
2596 "Nr of walk items", HFILL}},
2597 {&hf_9P_nlink,
2598 {"nlink", "9p.nlink", FT_UINT64, BASE_DEC, NULL, 0x0,
2599 "Number of links", HFILL}},
2600 {&hf_9P_getattr_flags,
2601 {"getattr_flags", "9p.getattr.flags", FT_UINT64, BASE_HEX, NULL, _9P_GETATTR_ALL,
2602 "Getattr flags", HFILL}},
2603 {&hf_9P_getattr_mode,
2604 {"Mode", "9p.getattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MODE,
2605 NULL, HFILL}},
2606 {&hf_9P_getattr_nlink,
2607 {"Nlink", "9p.getattr.nlink", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_NLINK,
2608 NULL, HFILL}},
2609 {&hf_9P_getattr_uid,
2610 {"UID", "9p.getattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_UID,
2611 NULL, HFILL}},
2612 {&hf_9P_getattr_gid,
2613 {"GID", "9p.getattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GID,
2614 NULL, HFILL}},
2615 {&hf_9P_getattr_rdev,
2616 {"Rdev", "9p.getattr.rdev", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_RDEV,
2617 NULL, HFILL}},
2618 {&hf_9P_getattr_atime,
2619 {"Atime", "9p.getattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_ATIME,
2620 NULL, HFILL}},
2621 {&hf_9P_getattr_mtime,
2622 {"Mtime", "9p.getattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MTIME,
2623 NULL, HFILL}},
2624 {&hf_9P_getattr_ctime,
2625 {"Ctime", "9p.getattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_CTIME,
2626 NULL, HFILL}},
2627 {&hf_9P_getattr_ino,
2628 {"Inode", "9p.getattr.inode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_INO,
2629 NULL, HFILL}},
2630 {&hf_9P_getattr_size,
2631 {"Size", "9p.getattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_SIZE,
2632 NULL, HFILL}},
2633 {&hf_9P_getattr_blocks,
2634 {"Blocks", "9p.getattr.blocks", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BLOCKS,
2635 NULL, HFILL}},
2636 {&hf_9P_getattr_btime,
2637 {"Btime", "9p.getattr.btime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BTIME,
2638 NULL, HFILL}},
2639 {&hf_9P_getattr_gen,
2640 {"Gen", "9p.getattr.gen", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GEN,
2641 NULL, HFILL}},
2642 {&hf_9P_getattr_dataversion,
2643 {"Data version", "9p.getattr.dataversion", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_DATA_VERSION,
2644 NULL, HFILL}},
2645 {&hf_9P_setattr_flags,
2646 {"setattr_flags", "9p.setattr.flags", FT_UINT32, BASE_HEX, NULL, _9P_SETATTR_ALL,
2647 "Setattr flags", HFILL}},
2648 {&hf_9P_setattr_mode,
2649 {"Mode", "9p.setattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MODE,
2650 NULL, HFILL}},
2651 {&hf_9P_setattr_uid,
2652 {"UID", "9p.setattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_UID,
2653 NULL, HFILL}},
2654 {&hf_9P_setattr_gid,
2655 {"GID", "9p.setattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_GID,
2656 NULL, HFILL}},
2657 {&hf_9P_setattr_size,
2658 {"Size", "9p.setattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_SIZE,
2659 NULL, HFILL}},
2660 {&hf_9P_setattr_atime,
2661 {"Atime", "9p.setattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME,
2662 NULL, HFILL}},
2663 {&hf_9P_setattr_mtime,
2664 {"Mtime", "9p.setattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME,
2665 NULL, HFILL}},
2666 {&hf_9P_setattr_ctime,
2667 {"Ctime", "9p.setattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_CTIME,
2668 NULL, HFILL}},
2669 {&hf_9P_setattr_atime_set,
2670 {"Atime set", "9p.setattr.atimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME_SET,
2671 NULL, HFILL}},
2672 {&hf_9P_setattr_mtime_set,
2673 {"Mtime set", "9p.setattr.mtimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME_SET,
2674 NULL, HFILL}},
2675 {&hf_9P_rdev,
2676 {"rdev", "9p.rdev", FT_UINT64, BASE_DEC, NULL, 0x0,
2677 "Device associated with file", HFILL}},
2678 {&hf_9P_size,
2679 {"Size", "9p.size", FT_UINT64, BASE_DEC, NULL, 0x0,
2680 NULL, HFILL}},
2681 {&hf_9P_blksize,
2682 {"Blksize", "9p.blksize", FT_UINT64, BASE_DEC, NULL, 0x0,
2683 "Block size", HFILL}},
2684 {&hf_9P_blocks,
2685 {"Blocks", "9p.blocks", FT_UINT64, BASE_DEC, NULL, 0x0,
2686 NULL, HFILL}},
2687 {&hf_9P_gen,
2688 {"Gen", "9p.gen", FT_UINT64, BASE_DEC, NULL, 0x0,
2689 "inode generation number", HFILL}},
2690 {&hf_9P_dataversion,
2691 {"Dataversion", "9p.dataversion", FT_UINT64, BASE_DEC, NULL, 0x0,
2692 "Data version", HFILL}},
2693 {&hf_9P_fstype,
2694 {"fstype", "9p.fstype", FT_UINT32, BASE_HEX, NULL, 0x0,
2695 "Filesystem type", HFILL}},
2696 {&hf_9P_bfree,
2697 {"bfree", "9p.bfree", FT_UINT64, BASE_DEC, NULL, 0x0,
2698 "Free blocks", HFILL}},
2699 {&hf_9P_bavail,
2700 {"bavail", "9p.bavail", FT_UINT64, BASE_DEC, NULL, 0x0,
2701 "Available blocks", HFILL}},
2702 {&hf_9P_files,
2703 {"files", "9p.files", FT_UINT64, BASE_DEC, NULL, 0x0,
2704 "Total files", HFILL}},
2705 {&hf_9P_ffree,
2706 {"ffree", "9p.ffree", FT_UINT64, BASE_DEC, NULL, 0x0,
2707 "Free files", HFILL}},
2708 {&hf_9P_fsid,
2709 {"fsid", "9p.fsid", FT_UINT64, BASE_DEC, NULL, 0x0,
2710 "Filesystem id", HFILL}},
2711 {&hf_9P_namelen,
2712 {"namelen", "9p.namelen", FT_UINT32, BASE_DEC, NULL, 0x0,
2713 "Max name length", HFILL}},
2714 {&hf_9P_mknod_major,
2715 {"mknod_major", "9p.mknod.major", FT_UINT32, BASE_DEC, NULL, 0x0,
2716 "Major node number", HFILL}},
2717 {&hf_9P_mknod_minor,
2718 {"mknod_minor", "9p.mknod.minor", FT_UINT32, BASE_DEC, NULL, 0x0,
2719 "Minor node number", HFILL}},
2720 {&hf_9P_lflags,
2721 {"lflags", "9p.lcreate.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
2722 "Lcreate flags", HFILL}},
2723 /* rdonly is 0x00, check instead that we are neither wronly nor rdwrite */
2724 {&hf_9P_lflags_rdonly,
2725 {"Read only", "9p.lflags.rdonly", FT_BOOLEAN, 32, TFS(&tfs_no_yes), _9P_DOTL_WRONLY|_9P_DOTL_RDWR,
2726 NULL, HFILL}},
2727 {&hf_9P_lflags_wronly,
2728 {"Write only", "9p.lflags.wronly", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_WRONLY,
2729 NULL, HFILL}},
2730 {&hf_9P_lflags_rdwr,
2731 {"Read Write", "9p.lflags.rdwr", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_RDWR,
2732 NULL, HFILL}},
2733 {&hf_9P_lflags_create,
2734 {"Create", "9p.lflags.create", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CREATE,
2735 NULL, HFILL}},
2736 {&hf_9P_lflags_excl,
2737 {"Exclusive", "9p.lflags.excl", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_EXCL,
2738 NULL, HFILL}},
2739 {&hf_9P_lflags_noctty,
2740 {"noctty", "9p.lflags.noctty", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOCTTY,
2741 NULL, HFILL}},
2742 {&hf_9P_lflags_trunc,
2743 {"Truncate", "9p.lflags.trunc", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_TRUNC,
2744 NULL, HFILL}},
2745 {&hf_9P_lflags_append,
2746 {"Append", "9p.lflags.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_APPEND,
2747 NULL, HFILL}},
2748 {&hf_9P_lflags_nonblock,
2749 {"Nonblock", "9p.lflags.nonblock", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NONBLOCK,
2750 NULL, HFILL}},
2751 {&hf_9P_lflags_dsync,
2752 {"dsync", "9p.lflags.dsync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DSYNC,
2753 NULL, HFILL}},
2754 {&hf_9P_lflags_fasync,
2755 {"fasync", "9p.lflags.fasync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_FASYNC,
2756 NULL, HFILL}},
2757 {&hf_9P_lflags_direct,
2758 {"Direct", "9p.lflags.direct", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECT,
2759 NULL, HFILL}},
2760 {&hf_9P_lflags_largefile,
2761 {"Large File", "9p.lflags.largefile", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_LARGEFILE,
2762 NULL, HFILL}},
2763 {&hf_9P_lflags_directory,
2764 {"Directory", "9p.lflags.directory", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECTORY,
2765 NULL, HFILL}},
2766 {&hf_9P_lflags_nofollow,
2767 {"No follow", "9p.lflags.nofollow", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOFOLLOW,
2768 NULL, HFILL}},
2769 {&hf_9P_lflags_noatime,
2770 {"No atime", "9p.lflags.noatime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOATIME,
2771 NULL, HFILL}},
2772 {&hf_9P_lflags_cloexec,
2773 {"cloexec", "9p.lflags.cloexec", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CLOEXEC,
2774 NULL, HFILL}},
2775 {&hf_9P_lflags_sync,
2776 {"Sync", "9p.lflags.sync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_SYNC,
2777 NULL, HFILL}},
2778 {&hf_9P_xattr_flag,
2779 {"xattr_flag", "9p.xattr.flag", FT_UINT32, BASE_HEX, NULL, 0x0,
2780 "Xattr flag", HFILL}},
2781 {&hf_9P_lock_type,
2782 {"lock_type", "9p.lock.type", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_type_ext, 0x0,
2783 "Lock type", HFILL}},
2784 {&hf_9P_lock_flag,
2785 {"lock_flag", "9p.lock.flag", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_flag_ext, 0x0,
2786 "Lock flag", HFILL}},
2787 {&hf_9P_lock_start,
2788 {"lock_start", "9p.lock.start", FT_UINT64, BASE_DEC, NULL, 0x0,
2789 "Lock start", HFILL}},
2790 {&hf_9P_lock_length,
2791 {"lock_length", "9p.lock.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2792 "Lock length", HFILL}},
2793 {&hf_9P_lock_procid,
2794 {"lock_procid", "9p.lock.procid", FT_UINT32, BASE_HEX, NULL, 0x0,
2795 "Lock procid", HFILL}},
2796 {&hf_9P_lock_status,
2797 {"lock_status", "9p.lock.status", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ninep_lock_status_ext, 0x0,
2798 "Lock status", HFILL}}
2801 static gint *ett[] = {
2802 &ett_9P,
2803 &ett_9P_omode,
2804 &ett_9P_dm,
2805 &ett_9P_wname,
2806 &ett_9P_aname,
2807 &ett_9P_ename,
2808 &ett_9P_uname,
2809 &ett_9P_user,
2810 &ett_9P_group,
2811 &ett_9P_muid,
2812 &ett_9P_filename,
2813 &ett_9P_version,
2814 &ett_9P_qid,
2815 &ett_9P_qidtype,
2816 &ett_9P_getattr_flags,
2817 &ett_9P_setattr_flags,
2818 &ett_9P_lflags,
2821 proto_9P = proto_register_protocol("Plan 9", "9P", "9p");
2823 proto_register_field_array(proto_9P, hf, array_length(hf));
2825 proto_register_subtree_array(ett, array_length(ett));
2827 register_init_routine(_9p_hash_init);
2830 void proto_reg_handoff_9P(void)
2832 dissector_handle_t ninep_handle;
2834 data_handle = find_dissector("data");
2836 ninep_handle = new_create_dissector_handle(dissect_9P, proto_9P);
2838 dissector_add_uint("tcp.port", NINEPORT, ninep_handle);