Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-9p.c
blob80c46985a0e2a9b219b57ff7073aa8a2acf599ab
1 /* packet-9p.c
2 * Routines for 9P dissection
3 * Copyright 2005, Nils O. Selaasdal
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * File permission bits decoding taken from packet-nfs.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/tfs.h>
21 #include "packet-tcp.h"
24 * Protocol specifications:
26 * 9P2000: http://ericvh.github.io/9p-rfc/rfc9p2000.html
27 * 9P2000.L: https://github.com/chaos/diod/blob/master/protocol.md
28 * 9P2000.u: https://ericvh.github.io/9p-rfc/rfc9p2000.u.html
31 /**
32 * enum _9p_msg_t - 9P message types
33 * @_9P_TLERROR: not used
34 * @_9P_RLERROR: response for any failed request for 9P2000.L
35 * @_9P_TSTATFS: file system status request
36 * @_9P_RSTATFS: file system status response
37 * @_9P_TSYMLINK: make symlink request
38 * @_9P_RSYMLINK: make symlink response
39 * @_9P_TMKNOD: create a special file object request
40 * @_9P_RMKNOD: create a special file object response
41 * @_9P_TLCREATE: prepare a handle for I/O on an new file for 9P2000.L
42 * @_9P_RLCREATE: response with file access information for 9P2000.L
43 * @_9P_TRENAME: rename request
44 * @_9P_RRENAME: rename response
45 * @_9P_TMKDIR: create a directory request
46 * @_9P_RMKDIR: create a directory response
47 * @_9P_TVERSION: version handshake request
48 * @_9P_RVERSION: version handshake response
49 * @_9P_TAUTH: request to establish authentication channel
50 * @_9P_RAUTH: response with authentication information
51 * @_9P_TATTACH: establish user access to file service
52 * @_9P_RATTACH: response with top level handle to file hierarchy
53 * @_9P_TERROR: not used
54 * @_9P_RERROR: response for any failed request
55 * @_9P_TFLUSH: request to abort a previous request
56 * @_9P_RFLUSH: response when previous request has been cancelled
57 * @_9P_TWALK: descend a directory hierarchy
58 * @_9P_RWALK: response with new handle for position within hierarchy
59 * @_9P_TOPEN: prepare a handle for I/O on an existing file
60 * @_9P_ROPEN: response with file access information
61 * @_9P_TCREATE: prepare a handle for I/O on a new file
62 * @_9P_RCREATE: response with file access information
63 * @_9P_TREAD: request to transfer data from a file or directory
64 * @_9P_RREAD: response with data requested
65 * @_9P_TWRITE: request to transfer data to a file
66 * @_9P_RWRITE: response with out much data was transferred to file
67 * @_9P_TCLUNK: forget about a handle to an entity within the file system
68 * @_9P_RCLUNK: response when server has forgotten about the handle
69 * @_9P_TREMOVE: request to remove an entity from the hierarchy
70 * @_9P_RREMOVE: response when server has removed the entity
71 * @_9P_TSTAT: request file entity attributes
72 * @_9P_RSTAT: response with file entity attributes
73 * @_9P_TWSTAT: request to update file entity attributes
74 * @_9P_RWSTAT: response when file entity attributes are updated
76 * There are 14 basic operations in 9P2000, paired as
77 * requests and responses. The one special case is ERROR
78 * as there is no @_9P_TERROR request for clients to transmit to
79 * the server, but the server may respond to any other request
80 * with an @_9P_RERROR.
82 * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
85 static dissector_handle_t ninep_handle;
87 enum _9p_msg_t {
88 _9P_TLERROR = 6,
89 _9P_RLERROR,
90 _9P_TSTATFS = 8,
91 _9P_RSTATFS,
92 _9P_TLOPEN = 12,
93 _9P_RLOPEN,
94 _9P_TLCREATE = 14,
95 _9P_RLCREATE,
96 _9P_TSYMLINK = 16,
97 _9P_RSYMLINK,
98 _9P_TMKNOD = 18,
99 _9P_RMKNOD,
100 _9P_TRENAME = 20,
101 _9P_RRENAME,
102 _9P_TREADLINK = 22,
103 _9P_RREADLINK,
104 _9P_TGETATTR = 24,
105 _9P_RGETATTR,
106 _9P_TSETATTR = 26,
107 _9P_RSETATTR,
108 _9P_TXATTRWALK = 30,
109 _9P_RXATTRWALK,
110 _9P_TXATTRCREATE = 32,
111 _9P_RXATTRCREATE,
112 _9P_TREADDIR = 40,
113 _9P_RREADDIR,
114 _9P_TFSYNC = 50,
115 _9P_RFSYNC,
116 _9P_TLOCK = 52,
117 _9P_RLOCK,
118 _9P_TGETLOCK = 54,
119 _9P_RGETLOCK,
120 _9P_TLINK = 70,
121 _9P_RLINK,
122 _9P_TMKDIR = 72,
123 _9P_RMKDIR,
124 _9P_TRENAMEAT = 74,
125 _9P_RRENAMEAT,
126 _9P_TUNLINKAT = 76,
127 _9P_RUNLINKAT,
128 _9P_TVERSION = 100,
129 _9P_RVERSION,
130 _9P_TAUTH = 102,
131 _9P_RAUTH,
132 _9P_TATTACH = 104,
133 _9P_RATTACH,
134 _9P_TERROR = 106,
135 _9P_RERROR,
136 _9P_TFLUSH = 108,
137 _9P_RFLUSH,
138 _9P_TWALK = 110,
139 _9P_RWALK,
140 _9P_TOPEN = 112,
141 _9P_ROPEN,
142 _9P_TCREATE = 114,
143 _9P_RCREATE,
144 _9P_TREAD = 116,
145 _9P_RREAD,
146 _9P_TWRITE = 118,
147 _9P_RWRITE,
148 _9P_TCLUNK = 120,
149 _9P_RCLUNK,
150 _9P_TREMOVE = 122,
151 _9P_RREMOVE,
152 _9P_TSTAT = 124,
153 _9P_RSTAT,
154 _9P_TWSTAT = 126,
155 _9P_RWSTAT
158 /* 9P Msg types to name mapping */
159 static const value_string ninep_msg_type[] =
161 {_9P_TLERROR, "Tlerror"},
162 {_9P_RLERROR, "Rlerror"},
163 {_9P_TSTATFS, "Tstatfs"},
164 {_9P_RSTATFS, "Rstatfs"},
165 {_9P_TLOPEN, "Tlopen"},
166 {_9P_RLOPEN, "Rlopen"},
167 {_9P_TLCREATE, "Tlcreate"},
168 {_9P_RLCREATE, "Rlcreate"},
169 {_9P_TSYMLINK, "Tsymlink"},
170 {_9P_RSYMLINK, "Rsymlink"},
171 {_9P_TMKNOD, "Tmknod"},
172 {_9P_RMKNOD, "Rmknod"},
173 {_9P_TRENAME, "Trename"},
174 {_9P_RRENAME, "Rrename"},
175 {_9P_TREADLINK, "Treadlink"},
176 {_9P_RREADLINK, "Rreadlink"},
177 {_9P_TGETATTR, "Tgetattr"},
178 {_9P_RGETATTR, "Rgetattr"},
179 {_9P_TSETATTR, "Tsetattr"},
180 {_9P_RSETATTR, "Rsetattr"},
181 {_9P_TXATTRWALK, "Txattrwalk"},
182 {_9P_RXATTRWALK, "Rxattrwalk"},
183 {_9P_TXATTRCREATE, "Txattrcreate"},
184 {_9P_RXATTRCREATE, "Rxattrcreate"},
185 {_9P_TREADDIR, "Treaddir"},
186 {_9P_RREADDIR, "Rreaddir"},
187 {_9P_TFSYNC, "Tfsync"},
188 {_9P_RFSYNC, "Rfsync"},
189 {_9P_TLOCK, "Tlock"},
190 {_9P_RLOCK, "Rlock"},
191 {_9P_TGETLOCK, "Tgetlock"},
192 {_9P_RGETLOCK, "Rgetlock"},
193 {_9P_TLINK, "Tlink"},
194 {_9P_RLINK, "Rlink"},
195 {_9P_TMKDIR, "Tmkdir"},
196 {_9P_RMKDIR, "Rmkdir"},
197 {_9P_TRENAMEAT, "Trenameat"},
198 {_9P_RRENAMEAT, "Rrenameat"},
199 {_9P_TUNLINKAT, "Tunlinkat"},
200 {_9P_RUNLINKAT, "Runlinkat"},
201 {_9P_TVERSION, "Tversion"},
202 {_9P_RVERSION, "Rversion"},
203 {_9P_TAUTH, "Tauth"},
204 {_9P_RAUTH, "Rauth"},
205 {_9P_TATTACH, "Tattach"},
206 {_9P_RATTACH, "Rattach"},
207 {_9P_TERROR, "Terror"},
208 {_9P_RERROR, "Rerror"},
209 {_9P_TFLUSH, "Tflush"},
210 {_9P_RFLUSH, "Rflush"},
211 {_9P_TWALK, "Twalk"},
212 {_9P_RWALK, "Rwalk"},
213 {_9P_TOPEN, "Topen"},
214 {_9P_ROPEN, "Ropen"},
215 {_9P_TCREATE, "Tcreate"},
216 {_9P_RCREATE, "Rcreate"},
217 {_9P_TREAD, "Tread"},
218 {_9P_RREAD, "Rread"},
219 {_9P_TWRITE, "Twrite"},
220 {_9P_RWRITE, "Rwrite"},
221 {_9P_TCLUNK, "Tclunk"},
222 {_9P_RCLUNK, "Rclunk"},
223 {_9P_TREMOVE, "Tremove"},
224 {_9P_RREMOVE, "Rremove"},
225 {_9P_TSTAT, "Tstat"},
226 {_9P_RSTAT, "Rstat"},
227 {_9P_TWSTAT, "Twstat"},
228 {_9P_RWSTAT, "Rwstat"},
229 {0, NULL},
231 static value_string_ext ninep_msg_type_ext = VALUE_STRING_EXT_INIT(ninep_msg_type);
233 enum _9p_version {
234 _9P = 1,
235 _9P2000,
236 _9P2000_L,
237 _9P2000_u
240 static const value_string ninep_version[] =
242 {_9P, "9P"},
243 {_9P2000, "9P2000"},
244 {_9P2000_L, "9P2000.L"},
245 {_9P2000_u, "9P2000.u"},
246 {0, NULL},
248 static value_string_ext ninep_version_ext = VALUE_STRING_EXT_INIT(ninep_version);
251 /* File open modes */
252 #define _9P_OREAD 0x0
253 #define _9P_OWRITE 0x1
254 #define _9P_ORDWR 0x2
255 #define _9P_OEXEC 0x3
256 #define _9P_MODEMASK 0x3
257 #define _9P_OTRUNC 0x10
258 #define _9P_ORCLOSE 0x40
260 /* Open/Create modes */
261 static const value_string ninep_mode_vals[] =
263 {_9P_OREAD, "Read Access"},
264 {_9P_OWRITE, "Write Access"},
265 {_9P_ORDWR, "Read/Write Access "},
266 {_9P_OEXEC, "Execute Access"},
267 {0, NULL},
269 static value_string_ext ninep_mode_vals_ext = VALUE_STRING_EXT_INIT(ninep_mode_vals);
272 /* stat mode flags */
273 #define DMDIR 0x80000000 /* Directory */
274 #define DMAPPEND 0x40000000 /* Append only */
275 #define DMEXCL 0x20000000 /* Exclusive use */
276 #define DMMOUNT 0x10000000 /* Mounted channel */
277 #define DMAUTH 0x08000000 /* Authentication */
278 #define DMTMP 0x04000000 /* Temporary */
282 * enum _9p_qid_t - QID types
283 * @_9P_QTDIR: directory
284 * @_9P_QTAPPEND: append-only
285 * @_9P_QTEXCL: excluse use (only one open handle allowed)
286 * @_9P_QTMOUNT: mount points
287 * @_9P_QTAUTH: authentication file
288 * @_9P_QTTMP: non-backed-up files
289 * @_9P_QTSYMLINK: symbolic links (9P2000.u)
290 * @_9P_QTLINK: hard-link (9P2000.u)
291 * @_9P_QTFILE: normal files
293 * QID types are a subset of permissions - they are primarily
294 * used to differentiate semantics for a file system entity via
295 * a jump-table. Their value is also the most significant 16 bits
296 * of the permission_t
298 * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
300 enum _9p_qid_t {
301 _9P_QTDIR = 0x80,
302 _9P_QTAPPEND = 0x40,
303 _9P_QTEXCL = 0x20,
304 _9P_QTMOUNT = 0x10,
305 _9P_QTAUTH = 0x08,
306 _9P_QTTMP = 0x04,
307 _9P_QTSYMLINK = 0x02,
308 _9P_QTLINK = 0x01,
309 _9P_QTFILE = 0x00
312 /* 9P Magic Numbers */
313 #define _9P_NOTAG (uint16_t)(~0)
314 #define _9P_NOFID (uint32_t)(~0)
315 #define _9P_NONUNAME (uint32_t)(~0)
316 #define _9P_MAXWELEM 16
320 * @brief Length prefixed string type
322 * The protocol uses length prefixed strings for all
323 * string data, so we replicate that for our internal
324 * string members.
327 struct _9p_str {
328 uint16_t len; /* Length of the string */
329 char *str; /* The string */
333 * @brief file system entity information
335 * qids are /identifiers used by 9P servers to track file system
336 * entities. The type is used to differentiate semantics for operations
337 * on the entity (ie. read means something different on a directory than
338 * on a file). The path provides a server unique index for an entity
339 * (roughly analogous to an inode number), while the version is updated
340 * every time a file is modified and can be used to maintain cache
341 * coherency between clients and serves.
342 * Servers will often differentiate purely synthetic entities by setting
343 * their version to 0, signaling that they should never be cached and
344 * should be accessed synchronously.
346 * See Also://plan9.bell-labs.com/magic/man2html/2/stat
349 struct _9p_qid {
350 uint8_t type; /* Type */
351 uint32_t version; /* Monotonically incrementing version number */
352 uint64_t path; /* Per-server-unique ID for a file system element */
356 /* Bit values for getattr valid field.
358 #define _9P_GETATTR_MODE 0x00000001U
359 #define _9P_GETATTR_NLINK 0x00000002U
360 #define _9P_GETATTR_UID 0x00000004U
361 #define _9P_GETATTR_GID 0x00000008U
362 #define _9P_GETATTR_RDEV 0x00000010U
363 #define _9P_GETATTR_ATIME 0x00000020U
364 #define _9P_GETATTR_MTIME 0x00000040U
365 #define _9P_GETATTR_CTIME 0x00000080U
366 #define _9P_GETATTR_INO 0x00000100U
367 #define _9P_GETATTR_SIZE 0x00000200U
368 #define _9P_GETATTR_BLOCKS 0x00000400U
370 #define _9P_GETATTR_BTIME 0x00000800U
371 #define _9P_GETATTR_GEN 0x00001000U
372 #define _9P_GETATTR_DATA_VERSION 0x00002000U
374 #if 0
375 #define _9P_GETATTR_BASIC 0x000007ffU /* Mask for fields up to BLOCKS */
376 #endif
377 #define _9P_GETATTR_ALL 0x00003fffU /* Mask for All fields above */
380 /* Bit values for setattr valid field from <linux/fs.h>.
382 #define _9P_SETATTR_MODE 0x00000001U
383 #define _9P_SETATTR_UID 0x00000002U
384 #define _9P_SETATTR_GID 0x00000004U
385 #define _9P_SETATTR_SIZE 0x00000008U
386 #define _9P_SETATTR_ATIME 0x00000010U
387 #define _9P_SETATTR_MTIME 0x00000020U
388 #define _9P_SETATTR_CTIME 0x00000040U
389 #define _9P_SETATTR_ATIME_SET 0x00000080U
390 #define _9P_SETATTR_MTIME_SET 0x00000100U
392 #define _9P_SETATTR_ALL 0x000001FFU
394 /* 9p2000.L open flags */
395 #define _9P_DOTL_RDONLY 00000000
396 #define _9P_DOTL_WRONLY 00000001
397 #define _9P_DOTL_RDWR 00000002
398 #define _9P_DOTL_NOACCESS 00000003
399 #define _9P_DOTL_CREATE 00000100
400 #define _9P_DOTL_EXCL 00000200
401 #define _9P_DOTL_NOCTTY 00000400
402 #define _9P_DOTL_TRUNC 00001000
403 #define _9P_DOTL_APPEND 00002000
404 #define _9P_DOTL_NONBLOCK 00004000
405 #define _9P_DOTL_DSYNC 00010000
406 #define _9P_DOTL_FASYNC 00020000
407 #define _9P_DOTL_DIRECT 00040000
408 #define _9P_DOTL_LARGEFILE 00100000
409 #define _9P_DOTL_DIRECTORY 00200000
410 #define _9P_DOTL_NOFOLLOW 00400000
411 #define _9P_DOTL_NOATIME 01000000
412 #define _9P_DOTL_CLOEXEC 02000000
413 #define _9P_DOTL_SYNC 04000000
416 /* Bit values for lock type.
418 #define _9P_LOCK_TYPE_RDLCK 0
419 #define _9P_LOCK_TYPE_WRLCK 1
420 #define _9P_LOCK_TYPE_UNLCK 2
422 /* 9P lock type to string table */
423 static const value_string ninep_lock_type[] =
425 {_9P_LOCK_TYPE_RDLCK, "Read lock"},
426 {_9P_LOCK_TYPE_WRLCK, "Write lock"},
427 {_9P_LOCK_TYPE_UNLCK, "Unlock"},
428 { 0, NULL},
430 static value_string_ext ninep_lock_type_ext = VALUE_STRING_EXT_INIT(ninep_lock_type);
432 /* Bit values for lock status.
434 #define _9P_LOCK_SUCCESS 0
435 #define _9P_LOCK_BLOCKED 1
436 #define _9P_LOCK_ERROR 2
437 #define _9P_LOCK_GRACE 3
439 /* 9P lock status to string table */
440 static const value_string ninep_lock_status[] =
442 {_9P_LOCK_SUCCESS, "Success"},
443 {_9P_LOCK_BLOCKED, "Blocked"},
444 {_9P_LOCK_ERROR, "Error"},
445 {_9P_LOCK_GRACE, "Grace"},
446 { 0, NULL},
448 static value_string_ext ninep_lock_status_ext = VALUE_STRING_EXT_INIT(ninep_lock_status);
450 /* Bit values for lock flags.
452 #define _9P_LOCK_FLAGS_NONE 0
453 #define _9P_LOCK_FLAGS_BLOCK 1
454 #define _9P_LOCK_FLAGS_RECLAIM 2
456 /* 9P lock flag to string table */
457 static const value_string ninep_lock_flag[] =
459 {_9P_LOCK_FLAGS_NONE, "No flag"},
460 {_9P_LOCK_FLAGS_BLOCK, "Block"},
461 {_9P_LOCK_FLAGS_RECLAIM,"Reclaim"},
462 { 0, NULL},
464 static value_string_ext ninep_lock_flag_ext = VALUE_STRING_EXT_INIT(ninep_lock_flag);
467 * Linux error code values to descriptions table.
468 * Note that the error code values on Linux are platform-dependent;
469 * Linux, on some platforms, tried to match the values of existing UN*Xes
470 * on the platform in question.
472 * The platforms in question appear to be:
474 * 32-bit PowerPC (AIX?)
475 * 32-bit and 64-bit SPARC (SunOS - pre-5, or 5?)
476 * PA-RISC (HP-UX)
477 * Alpha (Tru64 UNIX)
478 * 32-bit MIPS (IRIX?)
479 * 64-bit MIPS (IRIX?)
481 * For now, we don't worry about this, and use the errno values used
482 * on most Linux platforms.
484 static const value_string linux_errno[] =
486 {1, "Operation not permitted"}, /* EPERM */
487 {2, "No such file or directory"}, /* ENOENT */
488 {3, "No such process"}, /* ESRCH */
489 {4, "Interrupted system call"}, /* EINTR */
490 {5, "I/O error"}, /* EIO */
491 {6, "No such device or address"}, /* ENXIO */
492 {7, "Argument list too long"}, /* E2BIG */
493 {8, "Exec format error"}, /* ENOEXEC */
494 {9, "Bad file number"}, /* EBADF */
495 {10, "No child processes"}, /* ECHILD */
496 {11, "Try again"}, /* EAGAIN */
497 {12, "Out of memory"}, /* ENOMEM */
498 {13, "Permission denied"}, /* EACCES */
499 {14, "Bad address"}, /* EFAULT */
500 {15, "Block device required"}, /* ENOTBLK */
501 {16, "Device or resource busy"}, /* EBUSY */
502 {17, "File exists"}, /* EEXIST */
503 {18, "Cross-device link"}, /* EXDEV */
504 {19, "No such device"}, /* ENODEV */
505 {20, "Not a directory"}, /* ENOTDIR */
506 {21, "Is a directory"}, /* EISDIR */
507 {22, "Invalid argument"}, /* EINVAL */
508 {23, "File table overflow"}, /* ENFILE */
509 {24, "Too many open files"}, /* EMFILE */
510 {25, "Not a typewriter"}, /* ENOTTY */
511 {26, "Text file busy"}, /* ETXTBSY */
512 {27, "File too large"}, /* EFBIG */
513 {28, "No space left on device"}, /* ENOSPC */
514 {29, "Illegal seek"}, /* ESPIPE */
515 {30, "Read-only file system"}, /* EROFS */
516 {31, "Too many links"}, /* EMLINK */
517 {32, "Broken pipe"}, /* EPIPE */
518 {33, "Math argument out of domain of func"}, /* EDOM */
519 {34, "Math result not representable"}, /* ERANGE */
520 {35, "Resource deadlock would occur"}, /* EDEADLK */
521 {36, "File name too long"}, /* ENAMETOOLONG */
522 {37, "No record locks available"}, /* ENOLCK */
523 {38, "Function not implemented"}, /* ENOSYS */
524 {39, "Directory not empty"}, /* ENOTEMPTY */
525 {40, "Too many symbolic links encountered"}, /* ELOOP */
526 {41, "Operation would block"}, /* EWOULDBLOCK */
527 {42, "No message of desired type"}, /* ENOMSG */
528 {43, "Identifier removed"}, /* EIDRM */
529 {44, "Channel number out of range"}, /* ECHRNG */
530 {45, "Level 2 not synchronized"}, /* EL2NSYNC */
531 {46, "Level 3 halted"}, /* EL3HLT */
532 {47, "Level 3 reset"}, /* EL3RST */
533 {48, "Link number out of range"}, /* ELNRNG */
534 {49, "Protocol driver not attached"}, /* EUNATCH */
535 {50, "No CSI structure available"}, /* ENOCSI */
536 {51, "Level 2 halted"}, /* EL2HLT */
537 {52, "Invalid exchange"}, /* EBADE */
538 {53, "Invalid request descriptor"}, /* EBADR */
539 {54, "Exchange full"}, /* EXFULL */
540 {55, "No anode"}, /* ENOANO */
541 {56, "Invalid request code"}, /* EBADRQC */
542 {57, "Invalid slot"}, /* EBADSLT */
543 {58, "File locking deadlock error"}, /* EDEADLOCK */
544 {59, "Bad font file format"}, /* EBFONT */
545 {60, "Device not a stream"}, /* ENOSTR */
546 {61, "No data available"}, /* ENODATA */
547 {62, "Timer expired"}, /* ETIME */
548 {63, "Out of streams resources"}, /* ENOSR */
549 {64, "Machine is not on the network"}, /* ENONET */
550 {65, "Package not installed"}, /* ENOPKG */
551 {66, "Object is remote"}, /* EREMOTE */
552 {67, "Link has been severed"}, /* ENOLINK */
553 {68, "Advertise error"}, /* EADV */
554 {69, "Srmount error"}, /* ESRMNT */
555 {70, "Communication error on send"}, /* ECOMM */
556 {71, "Protocol error"}, /* EPROTO */
557 {72, "Multihop attempted"}, /* EMULTIHOP */
558 {73, "RFS specific error"}, /* EDOTDOT */
559 {74, "Not a data message"}, /* EBADMSG */
560 {75, "Value too large for defined data type"}, /* EOVERFLOW */
561 {76, "Name not unique on network"}, /* ENOTUNIQ */
562 {77, "File descriptor in bad state"}, /* EBADFD */
563 {78, "Remote address changed"}, /* EREMCHG */
564 {79, "Can not access a needed shared library"}, /* ELIBACC */
565 {80, "Accessing a corrupted shared library"}, /* ELIBBAD */
566 {81, ".lib section in a.out corrupted"}, /* ELIBSCN */
567 {82, "Attempting to link in too many shared libraries"}, /* ELIBMAX */
568 {83, "Cannot exec a shared library directly"}, /* ELIBEXEC */
569 {84, "Illegal byte sequence"}, /* EILSEQ */
570 {85, "Interrupted system call should be restarted"}, /* ERESTART */
571 {86, "Streams pipe error"}, /* ESTRPIPE */
572 {87, "Too many users"}, /* EUSERS */
573 {88, "Socket operation on non-socket"}, /* ENOTSOCK */
574 {89, "Destination address required"}, /* EDESTADDRREQ */
575 {90, "Message too long"}, /* EMSGSIZE */
576 {91, "Protocol wrong type for socket"}, /* EPROTOTYPE */
577 {92, "Protocol not available"}, /* ENOPROTOOPT */
578 {93, "Protocol not supported"}, /* EPROTONOSUPPORT */
579 {94, "Socket type not supported"}, /* ESOCKTNOSUPPORT */
580 {95, "Operation not supported on transport endpoint"}, /* EOPNOTSUPP */
581 {96, "Protocol family not supported"}, /* EPFNOSUPPORT */
582 {97, "Address family not supported by protocol"}, /* EAFNOSUPPORT */
583 {98, "Address already in use"}, /* EADDRINUSE */
584 {99, "Cannot assign requested address"}, /* EADDRNOTAVAIL */
585 {100, "Network is down"}, /* ENETDOWN */
586 {101, "Network is unreachable"}, /* ENETUNREACH */
587 {102, "Network dropped connection because of reset"}, /* ENETRESET */
588 {103, "Software caused connection abort"}, /* ECONNABORTED */
589 {104, "Connection reset by peer"}, /* ECONNRESET */
590 {105, "No buffer space available"}, /* ENOBUFS */
591 {106, "Transport endpoint is already connected"}, /* EISCONN */
592 {107, "Transport endpoint is not connected"}, /* ENOTCONN */
593 {108, "Cannot send after transport endpoint shutdown"}, /* ESHUTDOWN */
594 {109, "Too many references: cannot splice"}, /* ETOOMANYREFS */
595 {110, "Connection timed out"}, /* ETIMEDOUT */
596 {111, "Connection refused"}, /* ECONNREFUSED */
597 {112, "Host is down"}, /* EHOSTDOWN */
598 {113, "No route to host"}, /* EHOSTUNREACH */
599 {114, "Operation already in progress"}, /* EALREADY */
600 {115, "Operation now in progress"}, /* EINPROGRESS */
601 {116, "Stale NFS file handle"}, /* ESTALE */
602 {117, "Structure needs cleaning"}, /* EUCLEAN */
603 {118, "Not a XENIX named type file"}, /* ENOTNAM */
604 {119, "No XENIX semaphores available"}, /* ENAVAIL */
605 {120, "Is a named type file"}, /* EISNAM */
606 {121, "Remote I/O error"}, /* EREMOTEIO */
607 {122, "Quota exceeded"}, /* EDQUOT */
608 {123, "No medium found"}, /* ENOMEDIUM */
609 {124, "Wrong medium type"}, /* EMEDIUMTYPE */
610 {125, "Operation Canceled"}, /* ECANCELED */
611 {126, "Required key not available"}, /* ENOKEY */
612 {127, "Key has expired"}, /* EKEYEXPIRED */
613 {128, "Key has been revoked"}, /* EKEYREVOKED */
614 {129, "Key was rejected by service"}, /* EKEYREJECTED */
615 {130, "Owner died"}, /* EOWNERDEAD */
616 {131, "State not recoverable"}, /* ENOTRECOVERABLE */
617 {132, "Operation not possible due to RF-kill"}, /* ERFKILL */
618 {133, "Memory page has hardware error"}, /* EHWPOISON */
619 {0, NULL}
621 static value_string_ext linux_errno_ext = VALUE_STRING_EXT_INIT(linux_errno);
623 static const char *const invalid_fid_str = "<invalid fid>";
624 static const char *const afid_str = "<afid>";
626 /* Structures for Protocol Operations */
627 struct _9p_rlerror {
628 uint32_t ecode;
630 struct _9p_tstatfs {
631 uint32_t fid;
633 struct _9p_rstatfs {
634 uint32_t type;
635 uint32_t bsize;
636 uint64_t blocks;
637 uint64_t bfree;
638 uint64_t bavail;
639 uint64_t files;
640 uint64_t ffree;
641 uint64_t fsid;
642 uint32_t namelen;
644 struct _9p_tlopen {
645 uint32_t fid;
646 uint32_t flags;
648 struct _9p_rlopen {
649 struct _9p_qid qid;
650 uint32_t iounit;
652 struct _9p_tlcreate {
653 uint32_t fid;
654 struct _9p_str name;
655 uint32_t flags;
656 uint32_t mode;
657 uint32_t gid;
659 struct _9p_rlcreate {
660 struct _9p_qid qid;
661 uint32_t iounit;
663 struct _9p_tsymlink {
664 uint32_t fid;
665 struct _9p_str name;
666 struct _9p_str symtgt;
667 uint32_t gid;
669 struct _9p_rsymlink {
670 struct _9p_qid qid;
672 struct _9p_tmknod {
673 uint32_t fid;
674 struct _9p_str name;
675 uint32_t mode;
676 uint32_t major;
677 uint32_t minor;
678 uint32_t gid;
680 struct _9p_rmknod {
681 struct _9p_qid qid;
683 struct _9p_trename {
684 uint32_t fid;
685 uint32_t dfid;
686 struct _9p_str name;
688 #if 0
689 struct _9p_rrename {
691 #endif
692 struct _9p_treadlink {
693 uint32_t fid;
695 struct _9p_rreadlink {
696 struct _9p_str target;
698 struct _9p_tgetattr {
699 uint32_t fid;
700 uint64_t request_mask;
702 struct _9p_rgetattr {
703 uint64_t valid;
704 struct _9p_qid qid;
705 uint32_t mode;
706 uint32_t uid;
707 uint32_t gid;
708 uint64_t nlink;
709 uint64_t rdev;
710 uint64_t size;
711 uint64_t blksize;
712 uint64_t blocks;
713 uint64_t atime_sec;
714 uint64_t atime_nsec;
715 uint64_t mtime_sec;
716 uint64_t mtime_nsec;
717 uint64_t ctime_sec;
718 uint64_t ctime_nsec;
719 uint64_t btime_sec;
720 uint64_t btime_nsec;
721 uint64_t gen;
722 uint64_t data_version;
724 struct _9p_tsetattr {
725 uint32_t fid;
726 uint32_t valid;
727 uint32_t mode;
728 uint32_t uid;
729 uint32_t gid;
730 uint64_t size;
731 uint64_t atime_sec;
732 uint64_t atime_nsec;
733 uint64_t mtime_sec;
734 uint64_t mtime_nsec;
736 #if 0
737 struct _9p_rsetattr {
739 #endif
740 struct _9p_txattrwalk {
741 uint32_t fid;
742 uint32_t attrfid;
743 struct _9p_str name;
745 struct _9p_rxattrwalk {
746 uint64_t size;
748 struct _9p_txattrcreate {
749 uint32_t fid;
750 struct _9p_str name;
751 uint64_t size;
752 uint32_t flag;
754 #if 0
755 struct _9p_rxattrcreate {
757 #endif
758 struct _9p_treaddir {
759 uint32_t fid;
760 uint64_t offset;
761 uint32_t count;
763 struct _9p_rreaddir {
764 uint32_t count;
765 uint8_t *data;
767 struct _9p_tfsync {
768 uint32_t fid;
770 #if 0
771 struct _9p_rfsync {
773 #endif
774 struct _9p_tlock {
775 uint32_t fid;
776 uint8_t type;
777 uint32_t flags;
778 uint64_t start;
779 uint64_t length;
780 uint32_t proc_id;
781 struct _9p_str client_id;
783 struct _9p_rlock {
784 uint8_t status;
786 struct _9p_tgetlock {
787 uint32_t fid;
788 uint8_t type;
789 uint64_t start;
790 uint64_t length;
791 uint32_t proc_id;
792 struct _9p_str client_id;
794 struct _9p_rgetlock {
795 uint8_t type;
796 uint64_t start;
797 uint64_t length;
798 uint32_t proc_id;
799 struct _9p_str client_id;
801 struct _9p_tlink {
802 uint32_t dfid;
803 uint32_t fid;
804 struct _9p_str name;
806 #if 0
807 struct _9p_rlink {
809 #endif
810 struct _9p_tmkdir {
811 uint32_t fid;
812 struct _9p_str name;
813 uint32_t mode;
814 uint32_t gid;
816 struct _9p_rmkdir {
817 struct _9p_qid qid;
819 struct _9p_trenameat {
820 uint32_t olddirfid;
821 struct _9p_str oldname;
822 uint32_t newdirfid;
823 struct _9p_str newname;
825 #if 0
826 struct _9p_rrenameat {
828 #endif
829 struct _9p_tunlinkat {
830 uint32_t dirfid;
831 struct _9p_str name;
832 uint32_t flags;
834 #if 0
835 struct _9p_runlinkat {
837 #endif
838 struct _9p_tawrite {
839 uint32_t fid;
840 uint8_t datacheck;
841 uint64_t offset;
842 uint32_t count;
843 uint32_t rsize;
844 uint8_t *data;
845 uint32_t check;
847 struct _9p_rawrite {
848 uint32_t count;
850 struct _9p_tversion {
851 uint32_t msize ;
852 struct _9p_str version ;
854 struct _9p_rversion {
855 uint32_t msize;
856 struct _9p_str version;
858 struct _9p_tauth {
859 uint32_t afid;
860 struct _9p_str uname;
861 struct _9p_str aname;
862 uint32_t n_uname; /* 9P2000.u extensions */
864 struct _9p_rauth {
865 struct _9p_qid qid;
867 struct _9p_rerror {
868 struct _9p_str error;
869 uint32_t errnum; /* 9p2000.u extension */
871 struct _9p_tflush {
872 uint16_t oldtag;
874 #if 0
875 struct _9p_rflush {
877 #endif
878 struct _9p_tattach {
879 uint32_t fid;
880 uint32_t afid;
881 struct _9p_str uname;
882 struct _9p_str aname;
883 uint32_t n_uname; /* 9P2000.u extensions */
885 struct _9p_rattach {
886 struct _9p_qid qid;
888 struct _9p_twalk {
889 uint32_t fid;
890 uint32_t newfid;
891 uint16_t nwname;
892 struct _9p_str wnames[_9P_MAXWELEM];
894 struct _9p_rwalk {
895 uint16_t nwqid;
896 struct _9p_qid wqids[_9P_MAXWELEM];
898 struct _9p_topen {
899 uint32_t fid;
900 uint8_t mode;
902 struct _9p_ropen {
903 struct _9p_qid qid;
904 uint32_t iounit;
906 struct _9p_tcreate {
907 uint32_t fid;
908 struct _9p_str name;
909 uint32_t perm;
910 uint8_t mode;
911 struct _9p_str extension;
913 struct _9p_rcreate {
914 struct _9p_qid qid;
915 uint32_t iounit;
917 struct _9p_tread {
918 uint32_t fid;
919 uint64_t offset;
920 uint32_t count;
922 struct _9p_rread {
923 uint32_t count;
924 uint8_t *data;
926 struct _9p_twrite {
927 uint32_t fid;
928 uint64_t offset;
929 uint32_t count;
930 uint8_t *data;
932 struct _9p_rwrite {
933 uint32_t count;
935 struct _9p_tclunk {
936 uint32_t fid;
938 #if 0
939 struct _9p_rclunk {
941 #endif
942 struct _9p_tremove {
943 uint32_t fid;
945 #if 0
946 struct _9p_rremove {
949 union _9p_tmsg {
951 #endif
952 #define NINEPORT 564
954 /* Forward declarations */
955 void proto_register_9P(void);
956 void proto_reg_handoff_9P(void);
958 /* Initialize the protocol and registered fields */
959 static int proto_9P;
960 static int hf_9P_msgsz;
961 static int hf_9P_msgtype;
962 static int hf_9P_tag;
963 static int hf_9P_oldtag;
964 static int hf_9P_parmsz;
965 static int hf_9P_maxsize;
966 static int hf_9P_fid;
967 static int hf_9P_nqid;
968 static int hf_9P_mode;
969 static int hf_9P_mode_rwx;
970 static int hf_9P_mode_t;
971 static int hf_9P_mode_c;
972 static int hf_9P_extension;
973 static int hf_9P_iounit;
974 static int hf_9P_count;
975 static int hf_9P_offset;
976 static int hf_9P_perm;
977 static int hf_9P_qidtype;
978 static int hf_9P_qidtype_dir;
979 static int hf_9P_qidtype_append;
980 static int hf_9P_qidtype_exclusive;
981 static int hf_9P_qidtype_mount;
982 static int hf_9P_qidtype_auth_file;
983 static int hf_9P_qidtype_temp_file;
984 static int hf_9P_qidvers;
985 static int hf_9P_qidpath;
986 static int hf_9P_dm_dir;
987 static int hf_9P_dm_append;
988 static int hf_9P_dm_exclusive;
989 static int hf_9P_dm_mount;
990 static int hf_9P_dm_auth_file;
991 static int hf_9P_dm_temp_file;
992 static int hf_9P_dm_read_owner;
993 static int hf_9P_dm_write_owner;
994 static int hf_9P_dm_exec_owner;
995 static int hf_9P_dm_read_group;
996 static int hf_9P_dm_write_group;
997 static int hf_9P_dm_exec_group;
998 static int hf_9P_dm_read_others;
999 static int hf_9P_dm_write_others;
1000 static int hf_9P_dm_exec_others;
1001 static int hf_9P_stattype;
1002 static int hf_9P_statmode;
1003 static int hf_9P_atime;
1004 static int hf_9P_mtime;
1005 static int hf_9P_ctime;
1006 static int hf_9P_btime;
1007 static int hf_9P_length;
1008 static int hf_9P_dev;
1009 static int hf_9P_wname;
1010 static int hf_9P_version;
1011 static int hf_9P_afid;
1012 static int hf_9P_uname;
1013 static int hf_9P_aname;
1014 static int hf_9P_ename;
1015 static int hf_9P_enum;
1016 /* static int hf_9P_name; */
1017 static int hf_9P_filename;
1018 static int hf_9P_sdlen;
1019 static int hf_9P_user;
1020 static int hf_9P_group;
1021 static int hf_9P_uid;
1022 static int hf_9P_gid;
1023 static int hf_9P_muid;
1024 static int hf_9P_nwalk;
1025 static int hf_9P_newfid;
1026 static int hf_9P_dfid;
1027 static int hf_9P_getattr_flags;
1028 static int hf_9P_getattr_mode;
1029 static int hf_9P_getattr_nlink;
1030 static int hf_9P_getattr_uid;
1031 static int hf_9P_getattr_gid;
1032 static int hf_9P_getattr_rdev;
1033 static int hf_9P_getattr_atime;
1034 static int hf_9P_getattr_mtime;
1035 static int hf_9P_getattr_ctime;
1036 static int hf_9P_getattr_ino;
1037 static int hf_9P_getattr_size;
1038 static int hf_9P_getattr_blocks;
1039 static int hf_9P_getattr_btime;
1040 static int hf_9P_getattr_gen;
1041 static int hf_9P_getattr_dataversion;
1042 static int hf_9P_setattr_flags;
1043 static int hf_9P_setattr_mode;
1044 static int hf_9P_setattr_uid;
1045 static int hf_9P_setattr_gid;
1046 static int hf_9P_setattr_size;
1047 static int hf_9P_setattr_atime;
1048 static int hf_9P_setattr_mtime;
1049 static int hf_9P_setattr_ctime;
1050 static int hf_9P_setattr_atime_set;
1051 static int hf_9P_setattr_mtime_set;
1052 static int hf_9P_unlinkat_flags;
1053 static int hf_9P_nlink;
1054 static int hf_9P_rdev;
1055 static int hf_9P_size;
1056 static int hf_9P_blksize;
1057 static int hf_9P_blocks;
1058 static int hf_9P_gen;
1059 static int hf_9P_dataversion;
1060 static int hf_9P_fstype;
1061 static int hf_9P_bfree;
1062 static int hf_9P_bavail;
1063 static int hf_9P_files;
1064 static int hf_9P_ffree;
1065 static int hf_9P_fsid;
1066 static int hf_9P_namelen;
1067 static int hf_9P_mknod_major;
1068 static int hf_9P_mknod_minor;
1069 static int hf_9P_lflags;
1070 static int hf_9P_lflags_rdonly;
1071 static int hf_9P_lflags_wronly;
1072 static int hf_9P_lflags_rdwr;
1073 static int hf_9P_lflags_create;
1074 static int hf_9P_lflags_excl;
1075 static int hf_9P_lflags_noctty;
1076 static int hf_9P_lflags_trunc;
1077 static int hf_9P_lflags_append;
1078 static int hf_9P_lflags_nonblock;
1079 static int hf_9P_lflags_dsync;
1080 static int hf_9P_lflags_fasync;
1081 static int hf_9P_lflags_direct;
1082 static int hf_9P_lflags_largefile;
1083 static int hf_9P_lflags_directory;
1084 static int hf_9P_lflags_nofollow;
1085 static int hf_9P_lflags_noatime;
1086 static int hf_9P_lflags_cloexec;
1087 static int hf_9P_lflags_sync;
1088 static int hf_9P_xattr_flag;
1089 static int hf_9P_lock_type;
1090 static int hf_9P_lock_flag;
1091 static int hf_9P_lock_start;
1092 static int hf_9P_lock_length;
1093 static int hf_9P_lock_procid;
1094 static int hf_9P_lock_status;
1095 static int hf_9P_unknown_message;
1097 /* subtree pointers */
1098 static int ett_9P;
1099 static int ett_9P_omode;
1100 static int ett_9P_dm;
1101 static int ett_9P_wname;
1102 static int ett_9P_aname;
1103 static int ett_9P_ename;
1104 static int ett_9P_uname;
1105 static int ett_9P_user;
1106 static int ett_9P_group;
1107 static int ett_9P_muid;
1108 static int ett_9P_filename;
1109 static int ett_9P_version;
1110 static int ett_9P_qid;
1111 static int ett_9P_qidtype;
1112 static int ett_9P_getattr_flags;
1113 static int ett_9P_setattr_flags;
1114 static int ett_9P_lflags;
1116 static expert_field ei_9P_first_250;
1117 static expert_field ei_9P_msgtype;
1119 static wmem_map_t *_9p_hashtable;
1121 static void dissect_9P_dm(tvbuff_t *tvb, proto_item *tree, int offset, int iscreate);
1122 static void dissect_9P_qid(tvbuff_t *tvb, proto_tree *tree, int offset);
1123 static void dissect_9P_lflags(tvbuff_t *tvb, proto_tree *tree, int offset);
1124 static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_tree *tree, int offset);
1125 static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_tree *tree, int offset);
1127 static int * const _9P_modes[] = {
1128 &hf_9P_mode_c,
1129 &hf_9P_mode_t,
1130 &hf_9P_mode_rwx,
1131 NULL
1134 struct _9p_hashkey {
1135 uint32_t conv_index;
1136 uint16_t tag;
1137 uint32_t fid;
1140 struct _9p_hashval {
1141 size_t len;
1142 void *data;
1145 struct _9p_taginfo {
1146 enum _9p_msg_t msgtype;
1147 uint32_t fid;
1148 /* fid path used for create and lcreate */
1149 char *fid_path;
1152 static int _9p_hash_equal(const void *k1, const void *k2) {
1153 const struct _9p_hashkey *key1 = (const struct _9p_hashkey *)k1, *key2 = (const struct _9p_hashkey *)k2;
1155 return ((key1->conv_index == key2->conv_index) && (key1->tag == key2->tag) && (key1->fid == key2->fid));
1158 static unsigned _9p_hash_hash(const void *k)
1160 const struct _9p_hashkey *key = (const struct _9p_hashkey *)k;
1162 return (key->conv_index ^ key->tag ^ key->fid);
1165 static struct _9p_hashval *_9p_hash_new_val(size_t len)
1167 struct _9p_hashval *val;
1168 val = wmem_new(wmem_file_scope(), struct _9p_hashval);
1170 val->data = wmem_alloc(wmem_file_scope(), len);
1171 val->len = len;
1173 return val;
1176 static void _9p_hash_set(packet_info *pinfo, uint16_t tag, uint32_t fid, struct _9p_hashval *val)
1178 struct _9p_hashkey *key;
1179 struct _9p_hashval *oldval;
1180 conversation_t *conv;
1182 conv = find_or_create_conversation(pinfo);
1184 key = wmem_new(wmem_file_scope(), struct _9p_hashkey);
1186 key->conv_index = conv->conv_index;
1187 key->tag = tag;
1188 key->fid = fid;
1190 /* remove eventual old entry */
1191 oldval = (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, key);
1192 if (oldval) {
1193 wmem_map_remove(_9p_hashtable, key);
1195 wmem_map_insert(_9p_hashtable, key, val);
1198 static struct _9p_hashval *_9p_hash_get(packet_info *pinfo, uint16_t tag, uint32_t fid)
1200 struct _9p_hashkey key;
1201 conversation_t *conv;
1203 conv = find_or_create_conversation(pinfo);
1205 key.conv_index = conv->conv_index;
1206 key.tag = tag;
1207 key.fid = fid;
1209 return (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, &key);
1212 static void _9p_hash_free(packet_info *pinfo, uint16_t tag, uint32_t fid)
1214 struct _9p_hashkey key;
1215 conversation_t *conv;
1217 conv = find_or_create_conversation(pinfo);
1219 key.conv_index = conv->conv_index;
1220 key.tag = tag;
1221 key.fid = fid;
1223 wmem_map_remove(_9p_hashtable, &key);
1226 static void conv_set_version(packet_info *pinfo, enum _9p_version version)
1228 struct _9p_hashval *val;
1230 val = _9p_hash_new_val(sizeof(enum _9p_version));
1233 *(enum _9p_version*)val->data = version;
1235 _9p_hash_set(pinfo, _9P_NOTAG, _9P_NOFID, val);
1238 static enum _9p_version conv_get_version(packet_info *pinfo)
1240 struct _9p_hashval *val;
1242 val = _9p_hash_get(pinfo, _9P_NOTAG, _9P_NOFID);
1244 return val ? *(enum _9p_version*)val->data : _9P;
1247 static void conv_set_fid_nocopy(packet_info *pinfo, uint32_t fid, const char *path)
1249 struct _9p_hashval *val;
1251 if (pinfo->fd->visited || fid == _9P_NOFID)
1252 return;
1254 /* get or create&insert fid tree */
1255 val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1256 if (!val) {
1257 val = _9p_hash_new_val(0);
1258 val->data = wmem_tree_new(wmem_file_scope());
1259 /* val->len is intentionally left to 0 so the tree won't be freed */
1260 _9p_hash_set(pinfo, _9P_NOTAG, fid, val);
1263 /* fill it */
1264 wmem_tree_insert32((wmem_tree_t *)val->data, pinfo->num, (void *)path);
1267 static void conv_set_fid(packet_info *pinfo, uint32_t fid, const char *path, size_t len)
1269 char *str;
1271 if (pinfo->fd->visited || fid == _9P_NOFID || len == 0)
1272 return;
1274 str = (char*)wmem_alloc(wmem_file_scope(), len);
1275 (void) g_strlcpy(str, path, len);
1276 conv_set_fid_nocopy(pinfo, fid, str);
1279 static const char *conv_get_fid(packet_info *pinfo, uint32_t fid)
1281 struct _9p_hashval *val;
1283 if (fid == _9P_NOFID)
1284 return invalid_fid_str;
1286 val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1287 if (!val)
1288 return invalid_fid_str;
1290 /* -1 because the fid needs to have been set on a previous message.
1291 Let's ignore the possibility of num == 0... */
1292 return (char*)wmem_tree_lookup32_le((wmem_tree_t*)val->data, pinfo->num-1);
1295 static inline void conv_free_fid(packet_info *pinfo, uint32_t fid)
1297 conv_set_fid_nocopy(pinfo, fid, invalid_fid_str);
1300 static void conv_set_tag(packet_info *pinfo, uint16_t tag, enum _9p_msg_t msgtype, uint32_t fid, wmem_strbuf_t *fid_path)
1302 struct _9p_hashval *val;
1303 struct _9p_taginfo *taginfo;
1305 if (pinfo->fd->visited || tag == _9P_NOTAG)
1306 return;
1308 val = _9p_hash_new_val(sizeof(struct _9p_taginfo));
1309 taginfo = (struct _9p_taginfo*)val->data;
1311 taginfo->msgtype = msgtype;
1312 taginfo->fid = fid;
1313 if (fid_path) {
1314 taginfo->fid_path = (char*)wmem_alloc(wmem_file_scope(), wmem_strbuf_get_len(fid_path)+1);
1315 (void) g_strlcpy(taginfo->fid_path, wmem_strbuf_get_str(fid_path), wmem_strbuf_get_len(fid_path)+1);
1316 } else {
1317 taginfo->fid_path = NULL;
1320 _9p_hash_set(pinfo, tag, _9P_NOFID, val);
1323 static inline struct _9p_taginfo *conv_get_tag(packet_info *pinfo, uint16_t tag)
1325 struct _9p_hashval *val;
1327 /* get tag only makes sense on first pass, as tree isn't built like fid */
1328 if (pinfo->fd->visited || tag == _9P_NOTAG)
1329 return NULL;
1331 /* check that length matches? */
1332 val = _9p_hash_get(pinfo, tag, _9P_NOFID);
1334 return val ? (struct _9p_taginfo*)val->data : NULL;
1337 static inline void conv_free_tag(packet_info *pinfo, uint16_t tag)
1339 if (pinfo->fd->visited || tag == _9P_NOTAG)
1340 return;
1342 _9p_hash_free(pinfo, tag, _9P_NOFID);
1345 /* dissects a string[s] (2 bytes followed by UTF-8 string) */
1346 static unsigned _9p_dissect_string(tvbuff_t *tvb, proto_tree *ninep_tree,
1347 unsigned offset, int hf_string, int ett_string)
1349 uint16_t _9p_len;
1350 proto_item *ti;
1351 proto_tree *sub_tree;
1353 _9p_len = tvb_get_letohs(tvb, offset);
1354 ti = proto_tree_add_item(ninep_tree, hf_string, tvb, offset + 2,
1355 _9p_len, ENC_UTF_8|ENC_NA);
1356 sub_tree = proto_item_add_subtree(ti, ett_string);
1357 proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1359 return 2 + _9p_len;
1362 /* Dissect 9P messages*/
1363 static int dissect_9P_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1365 uint32_t u32, i, fid, dfid, newfid;
1366 uint16_t u16, tag, _9p_len;
1367 enum _9p_msg_t ninemsg;
1368 unsigned offset = 0;
1369 const char *mname, *fid_path;
1370 char *tvb_s;
1371 wmem_strbuf_t *tmppath = NULL;
1372 int len, reportedlen;
1373 tvbuff_t *next_tvb;
1374 proto_item *ti, *msg_item;
1375 proto_tree *ninep_tree;
1376 struct _9p_taginfo *taginfo;
1377 int _9p_version;
1379 _9p_version = conv_get_version(pinfo);
1380 col_set_str(pinfo->cinfo, COL_PROTOCOL, val_to_str_ext_const(_9p_version, &ninep_version_ext, "9P"));
1382 col_clear(pinfo->cinfo, COL_INFO);
1384 /*ninesz = tvb_get_letohl(tvb, offset);*/
1385 ninemsg = (enum _9p_msg_t)tvb_get_uint8(tvb, offset + 4);
1387 mname = val_to_str_ext_const(ninemsg, &ninep_msg_type_ext, "Unknown");
1389 if(strcmp(mname, "Unknown") == 0) {
1390 col_add_fstr(pinfo->cinfo, COL_INFO, "9P Data (Message type %u)", (unsigned)ninemsg);
1391 return 0;
1394 tag = tvb_get_letohs(tvb, offset+5);
1395 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Tag=%u", mname, (unsigned)tag);
1397 ti = proto_tree_add_item(tree, proto_9P, tvb, 0, -1, ENC_NA);
1398 ninep_tree = proto_item_add_subtree(ti, ett_9P);
1399 proto_tree_add_item(ninep_tree, hf_9P_msgsz, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1400 offset+= 4;
1402 msg_item = proto_tree_add_item(ninep_tree, hf_9P_msgtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1403 ++offset;
1404 proto_tree_add_item(ninep_tree, hf_9P_tag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1405 offset += 2;
1407 switch(ninemsg) {
1408 case _9P_RVERSION:
1409 case _9P_TVERSION:
1410 proto_tree_add_item(ninep_tree, hf_9P_maxsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1411 offset += 4;
1413 if (!pinfo->fd->visited) {
1414 _9p_len = tvb_get_letohs(tvb, offset);
1415 tvb_s = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1417 if (!strcmp(tvb_s, "9P2000.L")) {
1418 u32 = _9P2000_L;
1419 } else if (!strcmp(tvb_s, "9P2000")) {
1420 u32 = _9P2000;
1421 } else if (!strcmp(tvb_s, "9P2000.u")) {
1422 u32 = _9P2000_u;
1423 } else {
1424 u32 = _9P;
1427 conv_set_version(pinfo, (enum _9p_version)u32);
1429 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_version, ett_9P_version);
1431 /* don't set tag for tversion/free it for rversion,
1432 we need that for the actual version number */
1433 break;
1435 case _9P_TAUTH:
1436 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1437 fid = tvb_get_letohl(tvb, offset);
1438 conv_set_fid_nocopy(pinfo, fid, afid_str);
1439 offset += 4;
1441 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_uname, ett_9P_uname);
1442 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_aname, ett_9P_aname);
1444 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1445 break;
1447 case _9P_RERROR:
1448 if (_9p_version == _9P2000_L) {
1449 u32 = tvb_get_letohl(tvb, offset);
1450 ti = proto_tree_add_item(ninep_tree, hf_9P_enum, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1451 proto_item_append_text(ti, " (%s)", val_to_str_ext_const(u32, &linux_errno_ext, "Unknown"));
1452 offset += 4;
1453 } else {
1454 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_ename, ett_9P_ename);
1457 /* conv_get_tag checks we're in first pass */
1458 taginfo = conv_get_tag(pinfo, tag);
1459 if (taginfo && (taginfo->msgtype == _9P_TWALK || taginfo->msgtype == _9P_TATTACH))
1460 conv_free_fid(pinfo, taginfo->fid);
1462 conv_free_tag(pinfo, tag);
1463 break;
1465 case _9P_TFLUSH:
1466 u16 = tvb_get_letohs(tvb, offset);
1467 proto_tree_add_item(ninep_tree, hf_9P_oldtag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1468 conv_free_tag(pinfo, u16);
1470 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1471 break;
1473 case _9P_TATTACH:
1474 fid = tvb_get_letohl(tvb, offset);
1475 proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1476 offset += 4;
1478 proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1479 offset += 4;
1481 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_uname, ett_9P_uname);
1483 if(!pinfo->fd->visited) {
1484 _9p_len = tvb_get_letohs(tvb, offset);
1485 tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1486 conv_set_fid(pinfo, fid, tvb_s, strlen(tvb_s)+1);
1488 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_aname, ett_9P_aname);
1490 if (_9p_version == _9P2000_u || _9p_version == _9P2000_L) {
1491 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1492 offset += 4;
1495 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1496 break;
1498 case _9P_TWALK:
1499 fid = tvb_get_letohl(tvb, offset);
1500 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1501 fid_path = conv_get_fid(pinfo, fid);
1502 proto_item_append_text(ti, " (%s)", fid_path);
1503 if (!pinfo->fd->visited) {
1504 tmppath = wmem_strbuf_create(pinfo->pool);
1505 wmem_strbuf_append(tmppath, fid_path);
1507 offset += 4;
1509 fid = tvb_get_letohl(tvb, offset);
1510 proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1511 offset += 4;
1513 u16 = tvb_get_letohs(tvb, offset);
1514 proto_tree_add_item(ninep_tree, hf_9P_nwalk, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1515 offset += 2;
1517 for(i = 0 ; i < u16; i++) {
1518 if (!pinfo->fd->visited) {
1519 _9p_len = tvb_get_letohs(tvb, offset);
1520 tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1521 wmem_strbuf_append_c(tmppath, '/');
1522 wmem_strbuf_append(tmppath, tvb_s);
1525 if (i < 250) {
1526 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1530 /* I can't imagine anyone having a directory depth more than 25,
1531 Limit to 10 times that to be sure, 2^16 is too much */
1532 if(u16 > 250) {
1533 expert_add_info(pinfo, ti, &ei_9P_first_250);
1536 if (!pinfo->fd->visited) {
1537 conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1540 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1541 break;
1543 case _9P_RWALK:
1544 u16 = tvb_get_letohs(tvb, offset);
1545 ti = proto_tree_add_item(ninep_tree, hf_9P_nqid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1546 offset += 2;
1547 /* I can't imagine anyone having a directory depth more than 25,
1548 Limit to 10 times that to be sure, 2^16 is too much */
1549 if(u16 > 250) {
1550 u16 = 250;
1553 for(i = 0; i < u16; i++) {
1554 dissect_9P_qid(tvb, ninep_tree, offset);
1555 offset += 13;
1558 if (i >= 250) {
1559 expert_add_info(pinfo, ti, &ei_9P_first_250);
1562 conv_free_tag(pinfo, tag);
1563 break;
1564 case _9P_TLOPEN:
1565 fid = tvb_get_letohl(tvb, offset);
1566 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1567 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1568 offset += 4;
1570 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1571 dissect_9P_lflags(tvb, ti, offset);
1572 offset += 4;
1573 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1574 break;
1576 case _9P_TOPEN:
1577 fid = tvb_get_letohl(tvb, offset);
1578 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1579 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1580 offset += 4;
1582 proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1583 offset += 1;
1585 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1586 break;
1588 case _9P_TCREATE:
1589 fid = tvb_get_letohl(tvb, offset);
1590 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1591 fid_path = conv_get_fid(pinfo, fid);
1592 proto_item_append_text(ti, " (%s)", fid_path);
1593 offset += 4;
1595 if (!pinfo->fd->visited) {
1596 _9p_len = tvb_get_letohs(tvb, offset);
1597 tmppath = wmem_strbuf_create(pinfo->pool);
1598 wmem_strbuf_append(tmppath, fid_path);
1599 wmem_strbuf_append_c(tmppath, '/');
1600 tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1601 wmem_strbuf_append(tmppath, tvb_s);
1603 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1605 ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1606 dissect_9P_dm(tvb, ti, offset, 1);
1607 offset += 4;
1609 proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1610 offset += 1;
1612 if (_9p_version == _9P2000_u) {
1613 _9p_len = tvb_get_letohs(tvb, offset);
1614 proto_tree_add_item(ninep_tree, hf_9P_extension, tvb, offset+2, 4, ENC_ASCII);
1615 offset += 2 + _9p_len;
1618 conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1619 break;
1621 case _9P_TLCREATE:
1622 fid = tvb_get_letohl(tvb, offset);
1623 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1624 fid_path = conv_get_fid(pinfo, fid);
1625 proto_item_append_text(ti, " (%s)", fid_path);
1626 offset += 4;
1628 if (!pinfo->fd->visited) {
1629 _9p_len = tvb_get_letohs(tvb, offset);
1630 tmppath = wmem_strbuf_create(pinfo->pool);
1631 wmem_strbuf_append(tmppath, fid_path);
1632 wmem_strbuf_append_c(tmppath, '/');
1633 tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1634 wmem_strbuf_append(tmppath, tvb_s);
1636 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1638 ti = proto_tree_add_item(ninep_tree, hf_9P_lflags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1639 dissect_9P_lflags(tvb, ti, offset);
1640 offset += 4;
1642 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1643 dissect_9P_dm(tvb, ti, offset, 0);
1644 offset += 4;
1646 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1647 offset += 4;
1649 conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1650 break;
1652 case _9P_TREAD:
1653 case _9P_TREADDIR:
1654 fid = tvb_get_letohl(tvb, offset);
1655 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1656 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1657 offset += 4;
1659 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1660 offset += 8;
1662 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1663 offset += 4;
1665 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1666 break;
1668 case _9P_RREAD:
1669 case _9P_RREADDIR:
1670 u32 = tvb_get_letohl(tvb, offset);
1671 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1672 offset += 4;
1674 len = tvb_reported_length_remaining(tvb, offset);
1675 reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1676 next_tvb = tvb_new_subset_length_caplen(tvb, offset, len, reportedlen);
1677 call_data_dissector(next_tvb, pinfo, tree);
1678 offset += len;
1680 conv_free_tag(pinfo, tag);
1681 break;
1683 case _9P_TWRITE:
1684 fid = tvb_get_letohl(tvb, offset);
1685 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1686 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1687 offset += 4;
1689 proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1690 offset += 8;
1692 u32 = tvb_get_letohl(tvb, offset);
1693 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1694 offset += 4;
1695 len = tvb_reported_length_remaining(tvb, offset);
1696 reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1697 next_tvb = tvb_new_subset_length_caplen(tvb, offset, len, reportedlen);
1698 call_data_dissector(next_tvb, pinfo, tree);
1699 offset += len;
1701 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1702 break;
1704 case _9P_RWRITE:
1705 proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1706 offset += 4;
1708 conv_free_tag(pinfo, tag);
1709 break;
1711 case _9P_RSTAT:
1712 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1713 offset += 2;
1715 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1716 offset += 2;
1718 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1719 offset += 2;
1721 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1722 offset += 4;
1724 dissect_9P_qid(tvb, ninep_tree, offset);
1725 offset += 13;
1727 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1728 dissect_9P_dm(tvb, ti, offset, 0);
1729 offset += 4;
1731 proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1732 offset += 4;
1734 proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1735 offset += 4;
1737 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1738 offset += 8;
1740 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1741 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1742 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1743 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1745 conv_free_tag(pinfo, tag);
1746 break;
1748 case _9P_TWSTAT:
1749 fid = tvb_get_letohl(tvb, offset);
1750 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1751 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1752 offset += 4;
1754 proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1755 offset += 2;
1757 proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1758 offset += 2;
1760 proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1761 offset += 2;
1763 proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1764 offset += 4;
1766 dissect_9P_qid(tvb, ninep_tree, offset);
1767 offset += 13;
1769 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1770 dissect_9P_dm(tvb, ti, offset, 0);
1771 offset += 4;
1773 proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1774 offset += 4;
1776 proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1777 offset += 4;
1779 proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1780 offset += 8;
1782 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1783 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1784 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1785 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1787 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1788 break;
1790 case _9P_TGETATTR:
1791 fid = tvb_get_letohl(tvb, offset);
1792 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1793 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1794 offset += 4;
1796 ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1797 dissect_9P_getattrflags(tvb, ti, offset);
1798 offset += 8;
1800 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1801 break;
1803 case _9P_RGETATTR:
1804 ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1805 dissect_9P_getattrflags(tvb, ti, offset);
1806 offset += 8;
1808 dissect_9P_qid(tvb, ninep_tree, offset);
1809 offset += 13;
1811 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1812 dissect_9P_dm(tvb, ti, offset, 0);
1813 offset += 4;
1815 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1816 offset += 4;
1818 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1819 offset += 4;
1821 proto_tree_add_item(ninep_tree, hf_9P_nlink, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1822 offset += 8;
1824 proto_tree_add_item(ninep_tree, hf_9P_rdev, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1825 offset += 8;
1827 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1828 offset += 8;
1830 proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1831 offset += 8;
1833 proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1834 offset += 8;
1836 proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1837 offset += 16;
1839 proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1840 offset += 16;
1842 proto_tree_add_item(ninep_tree, hf_9P_ctime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1843 offset += 16;
1845 proto_tree_add_item(ninep_tree, hf_9P_btime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1846 offset += 16;
1848 proto_tree_add_item(ninep_tree, hf_9P_gen, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1849 offset += 8;
1851 proto_tree_add_item(ninep_tree, hf_9P_dataversion, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1852 offset += 8;
1854 conv_free_tag(pinfo, tag);
1855 break;
1857 case _9P_TSETATTR:
1858 fid = tvb_get_letohl(tvb, offset);
1859 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1860 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1861 offset += 4;
1863 ti = proto_tree_add_item(ninep_tree, hf_9P_setattr_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1864 dissect_9P_setattrflags(tvb, ti, offset);
1865 offset += 4;
1867 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1868 dissect_9P_dm(tvb, ti, offset, 0);
1869 offset += 4;
1871 proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1872 offset += 4;
1874 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1875 offset += 4;
1877 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1878 offset += 8;
1880 proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1881 offset += 16;
1883 proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1884 offset += 16;
1886 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1887 break;
1889 case _9P_RSTATFS:
1890 proto_tree_add_item(ninep_tree, hf_9P_fstype, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1891 offset += 4;
1893 proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1894 offset += 4;
1896 proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1897 offset += 8;
1899 proto_tree_add_item(ninep_tree, hf_9P_bfree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1900 offset += 8;
1902 proto_tree_add_item(ninep_tree, hf_9P_bavail, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1903 offset += 8;
1905 proto_tree_add_item(ninep_tree, hf_9P_files, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1906 offset += 8;
1908 proto_tree_add_item(ninep_tree, hf_9P_ffree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1909 offset += 8;
1911 proto_tree_add_item(ninep_tree, hf_9P_fsid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1912 offset += 8;
1914 proto_tree_add_item(ninep_tree, hf_9P_namelen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1915 offset += 4;
1917 conv_free_tag(pinfo, tag);
1918 break;
1920 case _9P_TSYMLINK:
1921 fid = tvb_get_letohl(tvb, offset);
1922 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1923 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1924 offset += 4;
1926 /* name */
1927 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1928 /* XXX: maybe use a new field for symtgt? */
1929 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1931 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1932 offset += 4;
1934 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1935 break;
1937 case _9P_TMKNOD:
1938 fid = tvb_get_letohl(tvb, offset);
1939 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1940 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1941 offset += 4;
1943 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1945 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1946 dissect_9P_dm(tvb, ti, offset, 0);
1947 offset += 4;
1949 proto_tree_add_item(ninep_tree, hf_9P_mknod_major, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1950 offset += 4;
1952 proto_tree_add_item(ninep_tree, hf_9P_mknod_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1953 offset += 4;
1955 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1956 offset += 4;
1958 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1959 break;
1961 case _9P_TRENAME:
1962 fid = tvb_get_letohl(tvb, offset);
1963 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1964 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1965 offset += 4;
1967 dfid = tvb_get_letohl(tvb, offset);
1968 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1969 fid_path = conv_get_fid(pinfo, dfid);
1970 proto_item_append_text(ti, " (%s)", fid_path);
1971 offset += 4;
1973 if (!pinfo->fd->visited) {
1974 _9p_len = tvb_get_letohs(tvb, offset);
1975 tmppath = wmem_strbuf_create(pinfo->pool);
1976 wmem_strbuf_append(tmppath, conv_get_fid(pinfo, dfid));
1977 wmem_strbuf_append_c(tmppath, '/');
1979 tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1980 wmem_strbuf_append(tmppath, tvb_s);
1982 conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1984 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1986 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1987 break;
1989 case _9P_RREADLINK:
1990 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1992 conv_free_tag(pinfo, tag);
1993 break;
1995 case _9P_TXATTRWALK:
1996 fid = tvb_get_letohl(tvb, offset);
1997 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1998 fid_path = conv_get_fid(pinfo, fid);
1999 proto_item_append_text(ti, " (%s)", fid_path);
2000 offset += 4;
2002 newfid = tvb_get_letohl(tvb, offset);
2003 proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2004 conv_set_fid_nocopy(pinfo, newfid, fid_path);
2005 offset += 4;
2007 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2009 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2010 break;
2012 case _9P_RXATTRWALK:
2013 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2014 offset += 8;
2016 conv_free_tag(pinfo, tag);
2017 break;
2019 case _9P_TXATTRCREATE:
2020 fid = tvb_get_letohl(tvb, offset);
2021 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2022 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2023 offset += 4;
2025 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2027 proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2028 offset += 8;
2030 proto_tree_add_item(ninep_tree, hf_9P_xattr_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2031 offset += 4;
2033 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2034 break;
2036 case _9P_TLOCK:
2037 case _9P_TGETLOCK:
2038 fid = tvb_get_letohl(tvb, offset);
2039 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2040 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2041 offset += 4;
2043 proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2044 offset += 1;
2046 proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2047 offset += 4;
2049 proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2050 offset += 8;
2052 proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2053 offset += 8;
2055 proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2056 offset += 4;
2058 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2060 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2061 break;
2063 case _9P_RLOCK:
2064 proto_tree_add_item(ninep_tree, hf_9P_lock_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2065 offset += 1;
2067 conv_free_tag(pinfo, tag);
2068 break;
2070 case _9P_RGETLOCK:
2071 proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2072 offset += 1;
2074 proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2075 offset += 4;
2077 proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2078 offset += 8;
2080 proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2081 offset += 8;
2083 proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2084 offset += 4;
2086 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2088 conv_free_tag(pinfo, tag);
2089 break;
2091 case _9P_TLINK:
2092 fid = tvb_get_letohl(tvb, offset);
2093 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2094 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2095 offset += 4;
2097 fid = tvb_get_letohl(tvb, offset);
2098 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2099 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2100 offset += 4;
2102 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2104 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2105 break;
2107 case _9P_TMKDIR:
2108 fid = tvb_get_letohl(tvb, offset);
2109 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2110 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2111 offset += 4;
2113 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2115 ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2116 dissect_9P_dm(tvb, ti, offset, 0);
2117 offset += 4;
2119 proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2120 offset += 4;
2122 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2123 break;
2125 case _9P_TRENAMEAT:
2126 fid = tvb_get_letohl(tvb, offset);
2127 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2128 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2129 offset += 4;
2131 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2133 fid = tvb_get_letohl(tvb, offset);
2134 ti = proto_tree_add_item(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2135 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2136 offset += 4;
2138 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2140 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2141 break;
2143 case _9P_TUNLINKAT:
2144 fid = tvb_get_letohl(tvb, offset);
2145 ti = proto_tree_add_item(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2146 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2147 offset += 4;
2149 offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2151 proto_tree_add_item(ninep_tree, hf_9P_unlinkat_flags, tvb,
2152 offset, 4, ENC_LITTLE_ENDIAN);
2153 offset += 4;
2155 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2156 break;
2158 case _9P_TREMOVE:
2159 case _9P_TCLUNK:
2160 fid = tvb_get_letohl(tvb, offset);
2161 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2162 offset += 4;
2163 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2164 conv_free_fid(pinfo, fid);
2166 conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
2167 break;
2169 /* Request with only fid */
2170 case _9P_TSTATFS:
2171 case _9P_TREADLINK:
2172 case _9P_TFSYNC:
2173 case _9P_TSTAT:
2174 fid = tvb_get_letohl(tvb, offset);
2175 ti = proto_tree_add_item(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2176 offset += 4;
2177 proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2179 conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2180 break;
2182 /* Reply with qid and ionuit */
2183 case _9P_RCREATE:
2184 case _9P_RLCREATE:
2185 dissect_9P_qid(tvb, ninep_tree, offset);
2186 offset += 13;
2187 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2188 offset += 4;
2190 taginfo = conv_get_tag(pinfo, tag);
2191 if (taginfo && taginfo->fid_path) {
2192 conv_set_fid_nocopy(pinfo, taginfo->fid, taginfo->fid_path);
2195 conv_free_tag(pinfo, tag);
2196 break;
2198 case _9P_ROPEN:
2199 case _9P_RLOPEN:
2200 dissect_9P_qid(tvb, ninep_tree, offset);
2201 offset += 13;
2202 proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2203 offset += 4;
2205 conv_free_tag(pinfo, tag);
2206 break;
2208 /* Reply with only qid */
2209 case _9P_RSYMLINK:
2210 case _9P_RMKNOD:
2211 case _9P_RMKDIR:
2212 case _9P_RAUTH:
2213 case _9P_RATTACH:
2214 dissect_9P_qid(tvb, ninep_tree, offset);
2215 offset += 13;
2217 conv_free_tag(pinfo, tag);
2218 break;
2220 /* Empty reply */
2221 case _9P_RRENAME:
2222 case _9P_RSETATTR:
2223 case _9P_RXATTRCREATE:
2224 case _9P_RFSYNC:
2225 case _9P_RLINK:
2226 case _9P_RRENAMEAT:
2227 case _9P_RUNLINKAT:
2228 case _9P_RFLUSH:
2229 case _9P_RCLUNK:
2230 case _9P_RREMOVE:
2231 /* Unhandled reply */
2232 case _9P_RWSTAT:
2233 case _9P_RLERROR:
2234 conv_free_tag(pinfo, tag);
2235 break;
2237 /* Should-not-happen query */
2238 case _9P_TLERROR:
2239 case _9P_TERROR:
2240 default:
2241 expert_add_info(pinfo, msg_item, &ei_9P_msgtype);
2242 break;
2245 /* Show any extra data at the end of the message (but only
2246 if it was captured) */
2247 if (offset != tvb_captured_length(tvb))
2248 proto_tree_add_item(ninep_tree, hf_9P_unknown_message, tvb, offset, -1, ENC_NA);
2249 return tvb_captured_length(tvb);
2252 static unsigned get_9P_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
2253 int offset, void *data _U_)
2255 return (unsigned) tvb_get_letohl(tvb, offset);
2258 static int dissect_9P(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2260 tcp_dissect_pdus(tvb, pinfo, tree, true, 4,
2261 get_9P_message_len, dissect_9P_message, data);
2262 return tvb_captured_length(tvb);
2265 /* dissect 9P Qid */
2266 static void dissect_9P_qid(tvbuff_t *tvb, proto_tree *tree, int offset)
2268 proto_item *qidtype_item;
2269 proto_tree *qid_tree,*qidtype_tree;
2270 uint64_t path;
2271 uint32_t vers;
2272 uint8_t type;
2274 if(!tree)
2275 return;
2277 type = tvb_get_uint8(tvb, offset);
2278 vers = tvb_get_letohs(tvb, offset+1);
2279 path = tvb_get_letoh64(tvb, offset+1+4);
2281 qid_tree = proto_tree_add_subtree_format(tree, tvb, offset, 13, ett_9P_qid, NULL,
2282 "Qid type=0x%02x vers=%d path=%" PRIu64, type, vers, path);
2284 qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2285 qidtype_tree = proto_item_add_subtree(qidtype_item, ett_9P_qidtype);
2287 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_dir, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2288 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_append, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2289 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_exclusive, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2290 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_mount, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2291 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_auth_file, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2292 proto_tree_add_item(qidtype_tree, hf_9P_qidtype_temp_file, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2294 proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, ENC_LITTLE_ENDIAN);
2295 proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, ENC_LITTLE_ENDIAN);
2298 /*dissect 9P stat mode and create perm flags */
2299 static void dissect_9P_dm(tvbuff_t *tvb, proto_item *item, int offset, int iscreate)
2301 proto_item *mode_tree;
2304 mode_tree = proto_item_add_subtree(item, ett_9P_dm);
2305 if(!mode_tree)
2306 return;
2308 proto_tree_add_item(mode_tree, hf_9P_dm_dir, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2309 if(!iscreate) { /* Not applicable to Tcreate (?) */
2310 proto_tree_add_item(mode_tree, hf_9P_dm_append, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2311 proto_tree_add_item(mode_tree, hf_9P_dm_exclusive, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2312 proto_tree_add_item(mode_tree, hf_9P_dm_mount, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2313 proto_tree_add_item(mode_tree, hf_9P_dm_auth_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2314 proto_tree_add_item(mode_tree, hf_9P_dm_temp_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2317 proto_tree_add_item(mode_tree, hf_9P_dm_read_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2318 proto_tree_add_item(mode_tree, hf_9P_dm_write_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2319 proto_tree_add_item(mode_tree, hf_9P_dm_exec_owner, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2320 proto_tree_add_item(mode_tree, hf_9P_dm_read_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2321 proto_tree_add_item(mode_tree, hf_9P_dm_write_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2322 proto_tree_add_item(mode_tree, hf_9P_dm_exec_group, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2323 proto_tree_add_item(mode_tree, hf_9P_dm_read_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2324 proto_tree_add_item(mode_tree, hf_9P_dm_write_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2325 proto_tree_add_item(mode_tree, hf_9P_dm_exec_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2328 /* Dissect 9P getattr_flags */
2329 static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_item *item, int offset)
2331 proto_item *attrmask_tree;
2333 attrmask_tree = proto_item_add_subtree(item, ett_9P_getattr_flags);
2334 if(!attrmask_tree)
2335 return;
2337 /* fixme: This is actually 8 bytes (64bit) long, but masks have to fit on 32bit. */
2338 proto_tree_add_item(attrmask_tree, hf_9P_getattr_mode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2339 proto_tree_add_item(attrmask_tree, hf_9P_getattr_nlink, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2340 proto_tree_add_item(attrmask_tree, hf_9P_getattr_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2341 proto_tree_add_item(attrmask_tree, hf_9P_getattr_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2342 proto_tree_add_item(attrmask_tree, hf_9P_getattr_rdev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2343 proto_tree_add_item(attrmask_tree, hf_9P_getattr_atime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2344 proto_tree_add_item(attrmask_tree, hf_9P_getattr_mtime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2345 proto_tree_add_item(attrmask_tree, hf_9P_getattr_ctime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2346 proto_tree_add_item(attrmask_tree, hf_9P_getattr_ino, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2347 proto_tree_add_item(attrmask_tree, hf_9P_getattr_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2348 proto_tree_add_item(attrmask_tree, hf_9P_getattr_blocks, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2349 proto_tree_add_item(attrmask_tree, hf_9P_getattr_btime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2350 proto_tree_add_item(attrmask_tree, hf_9P_getattr_gen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2351 proto_tree_add_item(attrmask_tree, hf_9P_getattr_dataversion, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2354 /* Dissect 9P setattr_flags */
2355 static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_item *item, int offset)
2357 proto_item *attrmask_tree;
2359 attrmask_tree = proto_item_add_subtree(item, ett_9P_setattr_flags);
2360 if(!attrmask_tree)
2361 return;
2363 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2364 proto_tree_add_item(attrmask_tree, hf_9P_setattr_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2365 proto_tree_add_item(attrmask_tree, hf_9P_setattr_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2366 proto_tree_add_item(attrmask_tree, hf_9P_setattr_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2367 proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2368 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2369 proto_tree_add_item(attrmask_tree, hf_9P_setattr_ctime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2370 proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2371 proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2374 /* Dissect 9P lflags */
2375 static void dissect_9P_lflags(tvbuff_t *tvb, proto_item *item, int offset)
2377 proto_item *attrmask_tree;
2379 attrmask_tree = proto_item_add_subtree(item, ett_9P_lflags);
2380 if(!attrmask_tree)
2381 return;
2383 proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdonly, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2384 proto_tree_add_item(attrmask_tree, hf_9P_lflags_wronly, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2385 proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdwr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2386 proto_tree_add_item(attrmask_tree, hf_9P_lflags_create, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2387 proto_tree_add_item(attrmask_tree, hf_9P_lflags_excl, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2388 proto_tree_add_item(attrmask_tree, hf_9P_lflags_noctty, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2389 proto_tree_add_item(attrmask_tree, hf_9P_lflags_trunc, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2390 proto_tree_add_item(attrmask_tree, hf_9P_lflags_append, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2391 proto_tree_add_item(attrmask_tree, hf_9P_lflags_nonblock, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2392 proto_tree_add_item(attrmask_tree, hf_9P_lflags_dsync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2393 proto_tree_add_item(attrmask_tree, hf_9P_lflags_fasync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2394 proto_tree_add_item(attrmask_tree, hf_9P_lflags_direct, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2395 proto_tree_add_item(attrmask_tree, hf_9P_lflags_largefile, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2396 proto_tree_add_item(attrmask_tree, hf_9P_lflags_directory, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2397 proto_tree_add_item(attrmask_tree, hf_9P_lflags_nofollow, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2398 proto_tree_add_item(attrmask_tree, hf_9P_lflags_noatime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2399 proto_tree_add_item(attrmask_tree, hf_9P_lflags_cloexec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2400 proto_tree_add_item(attrmask_tree, hf_9P_lflags_sync, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2404 /* Register 9P with Wireshark */
2405 void proto_register_9P(void)
2407 static hf_register_info hf[] = {
2408 {&hf_9P_msgsz,
2409 {"Msg length", "9p.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
2410 "9P Message Length", HFILL}},
2411 {&hf_9P_msgtype,
2412 {"Msg Type", "9p.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ninep_msg_type_ext, 0x0,
2413 "Message Type", HFILL}},
2414 {&hf_9P_tag,
2415 {"Tag", "9p.tag", FT_UINT16, BASE_DEC, NULL, 0x0,
2416 "9P Tag", HFILL}},
2417 {&hf_9P_oldtag,
2418 {"Old tag", "9p.oldtag", FT_UINT16, BASE_DEC, NULL, 0x0,
2419 NULL, HFILL}},
2420 {&hf_9P_parmsz,
2421 {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
2422 "Parameter length", HFILL}},
2423 {&hf_9P_maxsize,
2424 {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
2425 "Max message size", HFILL}},
2426 {&hf_9P_fid,
2427 {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
2428 "File ID", HFILL}},
2429 {&hf_9P_nqid,
2430 {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
2431 "Number of Qid results", HFILL}},
2432 {&hf_9P_mode,
2433 {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
2434 NULL, HFILL}},
2435 {&hf_9P_mode_rwx,
2436 {"Open/Create Mode", "9p.mode.rwx", FT_UINT8, BASE_OCT | BASE_EXT_STRING, &ninep_mode_vals_ext, _9P_MODEMASK,
2437 NULL, HFILL}},
2438 {&hf_9P_mode_t,
2439 {"Trunc", "9p.mode.trunc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_OTRUNC,
2440 "Truncate", HFILL}},
2441 {&hf_9P_mode_c,
2442 {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_ORCLOSE,
2443 NULL, HFILL}},
2444 {&hf_9P_extension,
2445 {"Extension string", "9p.extension", FT_STRING, BASE_NONE, NULL, 0x0,
2446 "Link target for DSYMLINK mode, major+minor for DMDEVICE, empty for normal files", HFILL}},
2447 {&hf_9P_iounit,
2448 {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
2449 NULL, HFILL}},
2450 {&hf_9P_count,
2451 {"Count", "9p.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2452 NULL, HFILL}},
2453 {&hf_9P_offset,
2454 {"Offset", "9p.offset", FT_UINT64, BASE_DEC, NULL, 0x0,
2455 NULL, HFILL}},
2456 {&hf_9P_perm,
2457 {"Permissions", "9p.perm", FT_UINT32, BASE_OCT, NULL, 0x0,
2458 "Permission bits", HFILL}},
2459 {&hf_9P_qidpath,
2460 {"Qid path", "9p.qidpath", FT_UINT64, BASE_DEC, NULL, 0x0,
2461 NULL, HFILL}},
2462 {&hf_9P_dm_dir,
2463 {"Directory", "9p.dm.dir", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x80000000,
2464 NULL, HFILL}},
2465 {&hf_9P_dm_append,
2466 {"Append only", "9p.dm.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x40000000,
2467 NULL, HFILL}},
2468 {&hf_9P_dm_exclusive,
2469 {"Exclusive use", "9p.dm.exclusive", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x20000000,
2470 NULL, HFILL}},
2471 {&hf_9P_dm_mount,
2472 {"Mounted channel", "9p.dm.mount", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x10000000,
2473 NULL, HFILL}},
2474 {&hf_9P_dm_auth_file,
2475 {"Authentication file", "9p.dm.auth_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x08000000,
2476 NULL, HFILL}},
2477 {&hf_9P_dm_temp_file,
2478 {"Temporary file (not backed up)", "9p.dm.temp_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x04000000,
2479 NULL, HFILL}},
2480 {&hf_9P_dm_read_owner,
2481 {"Read permission for owner", "9p.dm.read_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000100,
2482 NULL, HFILL}},
2483 {&hf_9P_dm_write_owner,
2484 {"Write permission for owner", "9p.dm.write_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000080,
2485 NULL, HFILL}},
2486 {&hf_9P_dm_exec_owner,
2487 {"Execute permission for owner", "9p.dm.exec_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000040,
2488 NULL, HFILL}},
2489 {&hf_9P_dm_read_group,
2490 {"Read permission for group", "9p.dm.read_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000020,
2491 NULL, HFILL}},
2492 {&hf_9P_dm_write_group,
2493 {"Write permission for group", "9p.dm.write_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000010,
2494 NULL, HFILL}},
2495 {&hf_9P_dm_exec_group,
2496 {"Execute permission for group", "9p.dm.exec_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000008,
2497 NULL, HFILL}},
2498 {&hf_9P_dm_read_others,
2499 {"Read permission for others", "9p.dm.read_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
2500 NULL, HFILL}},
2501 {&hf_9P_dm_write_others,
2502 {"Write permission for others", "9p.dm.write_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
2503 NULL, HFILL}},
2504 {&hf_9P_dm_exec_others,
2505 {"Execute permission for others", "9p.dm.exec_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
2506 NULL, HFILL}},
2507 {&hf_9P_qidvers,
2508 {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
2509 NULL, HFILL}},
2510 {&hf_9P_qidtype,
2511 {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
2512 NULL, HFILL}},
2513 {&hf_9P_qidtype_dir,
2514 {"Directory", "9p.qidtype.dir", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
2515 NULL, HFILL}},
2516 {&hf_9P_qidtype_append,
2517 {"Append only", "9p.qidtype.append", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
2518 NULL, HFILL}},
2519 {&hf_9P_qidtype_exclusive,
2520 {"Exclusive use", "9p.qidtype.exclusive", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2521 NULL, HFILL}},
2522 {&hf_9P_qidtype_mount,
2523 {"Mounted channel", "9p.qidtype.mount", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
2524 NULL, HFILL}},
2525 {&hf_9P_qidtype_auth_file,
2526 {"Authentication file", "9p.qidtype.auth_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
2527 NULL, HFILL}},
2528 {&hf_9P_qidtype_temp_file,
2529 {"Temporary file (not backed up)", "9p.qidtype.temp_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2530 NULL, HFILL}},
2531 {&hf_9P_statmode,
2532 {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
2533 "File mode flags", HFILL}},
2534 {&hf_9P_stattype,
2535 {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
2536 NULL, HFILL}},
2537 {&hf_9P_atime,
2538 {"Atime", "9p.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2539 "Access Time", HFILL}},
2540 {&hf_9P_mtime,
2541 {"Mtime", "9p.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2542 "Modified Time", HFILL}},
2543 {&hf_9P_ctime,
2544 {"Ctime", "9p.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2545 "Creation Time", HFILL}},
2546 {&hf_9P_btime,
2547 {"Btime", "9p.btime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2548 "Btime (Synchronization information)", HFILL}},
2549 {&hf_9P_length,
2550 {"Length", "9p.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2551 "File Length", HFILL}},
2552 {&hf_9P_dev,
2553 {"Dev", "9p.dev", FT_UINT32, BASE_DEC, NULL, 0x0,
2554 NULL, HFILL}},
2555 {&hf_9P_wname,
2556 {"Wname", "9p.wname", FT_STRING, BASE_NONE, NULL, 0x0,
2557 "Path Name Element", HFILL}},
2558 {&hf_9P_version,
2559 {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
2560 NULL, HFILL}},
2561 {&hf_9P_afid,
2562 {"Afid", "9p.afid", FT_UINT32, BASE_DEC, NULL, 0x0,
2563 "Authenticating FID", HFILL}},
2564 {&hf_9P_uname,
2565 {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
2566 "User Name", HFILL}},
2567 {&hf_9P_aname,
2568 {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
2569 "Access Name", HFILL}},
2570 {&hf_9P_ename,
2571 {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
2572 "Error", HFILL}},
2573 {&hf_9P_enum,
2574 {"Enum", "9p.enum", FT_UINT32, BASE_DEC, NULL, 0x0,
2575 "Error", HFILL}},
2576 #if 0
2577 {&hf_9P_name,
2578 {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
2579 "Name of file", HFILL}},
2580 #endif
2581 {&hf_9P_sdlen,
2582 {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
2583 NULL, HFILL}},
2584 {&hf_9P_filename,
2585 {"File name", "9p.filename", FT_STRING, BASE_NONE, NULL, 0x0,
2586 NULL, HFILL}},
2587 {&hf_9P_user,
2588 {"User", "9p.user", FT_STRING, BASE_NONE, NULL, 0x0,
2589 "User name", HFILL}},
2590 {&hf_9P_group,
2591 {"Group", "9p.group", FT_STRING, BASE_NONE, NULL, 0x0,
2592 "Group name", HFILL}},
2593 {&hf_9P_uid,
2594 {"Uid", "9p.uid", FT_UINT32, BASE_DEC, NULL, 0x0,
2595 "User id", HFILL}},
2596 {&hf_9P_gid,
2597 {"Gid", "9p.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
2598 "Group id", HFILL}},
2599 {&hf_9P_muid,
2600 {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
2601 "Last modifiers uid", HFILL}},
2602 {&hf_9P_newfid,
2603 {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2604 "New file ID", HFILL}},
2605 {&hf_9P_dfid,
2606 {"Directory fid", "9p.dfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2607 "Directory ID", HFILL}},
2608 {&hf_9P_nwalk,
2609 {"Nr Walks", "9p.nwalk", FT_UINT32, BASE_DEC, NULL, 0x0,
2610 "Nr of walk items", HFILL}},
2611 {&hf_9P_nlink,
2612 {"nlink", "9p.nlink", FT_UINT64, BASE_DEC, NULL, 0x0,
2613 "Number of links", HFILL}},
2614 {&hf_9P_getattr_flags,
2615 {"getattr_flags", "9p.getattr.flags", FT_UINT64, BASE_HEX, NULL, _9P_GETATTR_ALL,
2616 "Getattr flags", HFILL}},
2617 {&hf_9P_getattr_mode,
2618 {"Mode", "9p.getattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MODE,
2619 NULL, HFILL}},
2620 {&hf_9P_getattr_nlink,
2621 {"Nlink", "9p.getattr.nlink", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_NLINK,
2622 NULL, HFILL}},
2623 {&hf_9P_getattr_uid,
2624 {"UID", "9p.getattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_UID,
2625 NULL, HFILL}},
2626 {&hf_9P_getattr_gid,
2627 {"GID", "9p.getattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GID,
2628 NULL, HFILL}},
2629 {&hf_9P_getattr_rdev,
2630 {"Rdev", "9p.getattr.rdev", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_RDEV,
2631 NULL, HFILL}},
2632 {&hf_9P_getattr_atime,
2633 {"Atime", "9p.getattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_ATIME,
2634 NULL, HFILL}},
2635 {&hf_9P_getattr_mtime,
2636 {"Mtime", "9p.getattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MTIME,
2637 NULL, HFILL}},
2638 {&hf_9P_getattr_ctime,
2639 {"Ctime", "9p.getattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_CTIME,
2640 NULL, HFILL}},
2641 {&hf_9P_getattr_ino,
2642 {"Inode", "9p.getattr.inode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_INO,
2643 NULL, HFILL}},
2644 {&hf_9P_getattr_size,
2645 {"Size", "9p.getattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_SIZE,
2646 NULL, HFILL}},
2647 {&hf_9P_getattr_blocks,
2648 {"Blocks", "9p.getattr.blocks", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BLOCKS,
2649 NULL, HFILL}},
2650 {&hf_9P_getattr_btime,
2651 {"Btime", "9p.getattr.btime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BTIME,
2652 NULL, HFILL}},
2653 {&hf_9P_getattr_gen,
2654 {"Gen", "9p.getattr.gen", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GEN,
2655 NULL, HFILL}},
2656 {&hf_9P_getattr_dataversion,
2657 {"Data version", "9p.getattr.dataversion", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_DATA_VERSION,
2658 NULL, HFILL}},
2659 {&hf_9P_setattr_flags,
2660 {"setattr_flags", "9p.setattr.flags", FT_UINT32, BASE_HEX, NULL, _9P_SETATTR_ALL,
2661 "Setattr flags", HFILL}},
2662 {&hf_9P_setattr_mode,
2663 {"Mode", "9p.setattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MODE,
2664 NULL, HFILL}},
2665 {&hf_9P_setattr_uid,
2666 {"UID", "9p.setattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_UID,
2667 NULL, HFILL}},
2668 {&hf_9P_setattr_gid,
2669 {"GID", "9p.setattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_GID,
2670 NULL, HFILL}},
2671 {&hf_9P_setattr_size,
2672 {"Size", "9p.setattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_SIZE,
2673 NULL, HFILL}},
2674 {&hf_9P_setattr_atime,
2675 {"Atime", "9p.setattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME,
2676 NULL, HFILL}},
2677 {&hf_9P_setattr_mtime,
2678 {"Mtime", "9p.setattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME,
2679 NULL, HFILL}},
2680 {&hf_9P_setattr_ctime,
2681 {"Ctime", "9p.setattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_CTIME,
2682 NULL, HFILL}},
2683 {&hf_9P_setattr_atime_set,
2684 {"Atime set", "9p.setattr.atimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME_SET,
2685 NULL, HFILL}},
2686 {&hf_9P_setattr_mtime_set,
2687 {"Mtime set", "9p.setattr.mtimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME_SET,
2688 NULL, HFILL}},
2689 {&hf_9P_unlinkat_flags,
2690 {"unlinkat flags", "9p.unlinkat.flags", FT_UINT32, BASE_HEX, NULL, 0,
2691 NULL, HFILL}},
2692 {&hf_9P_rdev,
2693 {"rdev", "9p.rdev", FT_UINT64, BASE_DEC, NULL, 0x0,
2694 "Device associated with file", HFILL}},
2695 {&hf_9P_size,
2696 {"Size", "9p.size", FT_UINT64, BASE_DEC, NULL, 0x0,
2697 NULL, HFILL}},
2698 {&hf_9P_blksize,
2699 {"Blksize", "9p.blksize", FT_UINT64, BASE_DEC, NULL, 0x0,
2700 "Block size", HFILL}},
2701 {&hf_9P_blocks,
2702 {"Blocks", "9p.blocks", FT_UINT64, BASE_DEC, NULL, 0x0,
2703 NULL, HFILL}},
2704 {&hf_9P_gen,
2705 {"Gen", "9p.gen", FT_UINT64, BASE_DEC, NULL, 0x0,
2706 "inode generation number", HFILL}},
2707 {&hf_9P_dataversion,
2708 {"Dataversion", "9p.dataversion", FT_UINT64, BASE_DEC, NULL, 0x0,
2709 "Data version", HFILL}},
2710 {&hf_9P_fstype,
2711 {"fstype", "9p.fstype", FT_UINT32, BASE_HEX, NULL, 0x0,
2712 "Filesystem type", HFILL}},
2713 {&hf_9P_bfree,
2714 {"bfree", "9p.bfree", FT_UINT64, BASE_DEC, NULL, 0x0,
2715 "Free blocks", HFILL}},
2716 {&hf_9P_bavail,
2717 {"bavail", "9p.bavail", FT_UINT64, BASE_DEC, NULL, 0x0,
2718 "Available blocks", HFILL}},
2719 {&hf_9P_files,
2720 {"files", "9p.files", FT_UINT64, BASE_DEC, NULL, 0x0,
2721 "Total files", HFILL}},
2722 {&hf_9P_ffree,
2723 {"ffree", "9p.ffree", FT_UINT64, BASE_DEC, NULL, 0x0,
2724 "Free files", HFILL}},
2725 {&hf_9P_fsid,
2726 {"fsid", "9p.fsid", FT_UINT64, BASE_DEC, NULL, 0x0,
2727 "Filesystem id", HFILL}},
2728 {&hf_9P_namelen,
2729 {"namelen", "9p.namelen", FT_UINT32, BASE_DEC, NULL, 0x0,
2730 "Max name length", HFILL}},
2731 {&hf_9P_mknod_major,
2732 {"mknod_major", "9p.mknod.major", FT_UINT32, BASE_DEC, NULL, 0x0,
2733 "Major node number", HFILL}},
2734 {&hf_9P_mknod_minor,
2735 {"mknod_minor", "9p.mknod.minor", FT_UINT32, BASE_DEC, NULL, 0x0,
2736 "Minor node number", HFILL}},
2737 {&hf_9P_lflags,
2738 {"lflags", "9p.lcreate.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
2739 "Lcreate flags", HFILL}},
2740 /* rdonly is 0x00, check instead that we are neither wronly nor rdwrite */
2741 {&hf_9P_lflags_rdonly,
2742 {"Read only", "9p.lflags.rdonly", FT_BOOLEAN, 32, TFS(&tfs_no_yes), _9P_DOTL_WRONLY|_9P_DOTL_RDWR,
2743 NULL, HFILL}},
2744 {&hf_9P_lflags_wronly,
2745 {"Write only", "9p.lflags.wronly", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_WRONLY,
2746 NULL, HFILL}},
2747 {&hf_9P_lflags_rdwr,
2748 {"Read Write", "9p.lflags.rdwr", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_RDWR,
2749 NULL, HFILL}},
2750 {&hf_9P_lflags_create,
2751 {"Create", "9p.lflags.create", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CREATE,
2752 NULL, HFILL}},
2753 {&hf_9P_lflags_excl,
2754 {"Exclusive", "9p.lflags.excl", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_EXCL,
2755 NULL, HFILL}},
2756 {&hf_9P_lflags_noctty,
2757 {"noctty", "9p.lflags.noctty", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOCTTY,
2758 NULL, HFILL}},
2759 {&hf_9P_lflags_trunc,
2760 {"Truncate", "9p.lflags.trunc", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_TRUNC,
2761 NULL, HFILL}},
2762 {&hf_9P_lflags_append,
2763 {"Append", "9p.lflags.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_APPEND,
2764 NULL, HFILL}},
2765 {&hf_9P_lflags_nonblock,
2766 {"Nonblock", "9p.lflags.nonblock", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NONBLOCK,
2767 NULL, HFILL}},
2768 {&hf_9P_lflags_dsync,
2769 {"dsync", "9p.lflags.dsync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DSYNC,
2770 NULL, HFILL}},
2771 {&hf_9P_lflags_fasync,
2772 {"fasync", "9p.lflags.fasync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_FASYNC,
2773 NULL, HFILL}},
2774 {&hf_9P_lflags_direct,
2775 {"Direct", "9p.lflags.direct", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECT,
2776 NULL, HFILL}},
2777 {&hf_9P_lflags_largefile,
2778 {"Large File", "9p.lflags.largefile", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_LARGEFILE,
2779 NULL, HFILL}},
2780 {&hf_9P_lflags_directory,
2781 {"Directory", "9p.lflags.directory", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECTORY,
2782 NULL, HFILL}},
2783 {&hf_9P_lflags_nofollow,
2784 {"No follow", "9p.lflags.nofollow", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOFOLLOW,
2785 NULL, HFILL}},
2786 {&hf_9P_lflags_noatime,
2787 {"No atime", "9p.lflags.noatime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOATIME,
2788 NULL, HFILL}},
2789 {&hf_9P_lflags_cloexec,
2790 {"cloexec", "9p.lflags.cloexec", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CLOEXEC,
2791 NULL, HFILL}},
2792 {&hf_9P_lflags_sync,
2793 {"Sync", "9p.lflags.sync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_SYNC,
2794 NULL, HFILL}},
2795 {&hf_9P_xattr_flag,
2796 {"xattr_flag", "9p.xattr.flag", FT_UINT32, BASE_HEX, NULL, 0x0,
2797 "Xattr flag", HFILL}},
2798 {&hf_9P_lock_type,
2799 {"lock_type", "9p.lock.type", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_type_ext, 0x0,
2800 "Lock type", HFILL}},
2801 {&hf_9P_lock_flag,
2802 {"lock_flag", "9p.lock.flag", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_flag_ext, 0x0,
2803 "Lock flag", HFILL}},
2804 {&hf_9P_lock_start,
2805 {"lock_start", "9p.lock.start", FT_UINT64, BASE_DEC, NULL, 0x0,
2806 "Lock start", HFILL}},
2807 {&hf_9P_lock_length,
2808 {"lock_length", "9p.lock.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2809 "Lock length", HFILL}},
2810 {&hf_9P_lock_procid,
2811 {"lock_procid", "9p.lock.procid", FT_UINT32, BASE_HEX, NULL, 0x0,
2812 "Lock procid", HFILL}},
2813 {&hf_9P_lock_status,
2814 {"lock_status", "9p.lock.status", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ninep_lock_status_ext, 0x0,
2815 "Lock status", HFILL}},
2816 {&hf_9P_unknown_message,
2817 {"Message data", "9p.message_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2818 NULL, HFILL}}
2821 static int *ett[] = {
2822 &ett_9P,
2823 &ett_9P_omode,
2824 &ett_9P_dm,
2825 &ett_9P_wname,
2826 &ett_9P_aname,
2827 &ett_9P_ename,
2828 &ett_9P_uname,
2829 &ett_9P_user,
2830 &ett_9P_group,
2831 &ett_9P_muid,
2832 &ett_9P_filename,
2833 &ett_9P_version,
2834 &ett_9P_qid,
2835 &ett_9P_qidtype,
2836 &ett_9P_getattr_flags,
2837 &ett_9P_setattr_flags,
2838 &ett_9P_lflags,
2841 expert_module_t* expert_9P;
2843 static ei_register_info ei[] = {
2844 { &ei_9P_first_250, { "9p.first_250", PI_PROTOCOL, PI_NOTE, "Only first 250 items shown", EXPFILL }},
2845 { &ei_9P_msgtype, { "9p.msgtype.unknown", PI_PROTOCOL, PI_WARN, "This message type should not happen", EXPFILL }},
2848 proto_9P = proto_register_protocol("Plan 9", "9P", "9p");
2850 proto_register_field_array(proto_9P, hf, array_length(hf));
2851 proto_register_subtree_array(ett, array_length(ett));
2852 expert_9P = expert_register_protocol(proto_9P);
2853 expert_register_field_array(expert_9P, ei, array_length(ei));
2855 _9p_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), _9p_hash_hash, _9p_hash_equal);
2857 ninep_handle = register_dissector("9p", dissect_9P, proto_9P);
2860 void proto_reg_handoff_9P(void)
2862 dissector_add_uint_with_preference("tcp.port", NINEPORT, ninep_handle);
2867 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2869 * Local variables:
2870 * c-basic-offset: 8
2871 * tab-width: 8
2872 * indent-tabs-mode: t
2873 * End:
2875 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2876 * :indentSize=8:tabSize=8:noTabs=false: