Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-9p.c
Line
Count
Source
1
/* packet-9p.c
2
 * Routines for 9P dissection
3
 * Copyright 2005, Nils O. Selaasdal
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * File permission bits decoding taken from packet-nfs.c
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
17
#include <epan/packet.h>
18
#include <epan/expert.h>
19
#include <epan/tfs.h>
20
21
#include "packet-tcp.h"
22
23
/*
24
 * Protocol specifications:
25
 *
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
29
 */
30
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
75
 *
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.
81
 *
82
 * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html
83
 */
84
85
static dissector_handle_t ninep_handle;
86
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
156
};
157
158
/* 9P Msg types to name mapping */
159
static const value_string ninep_msg_type[] =
160
{
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},
230
};
231
static value_string_ext ninep_msg_type_ext = VALUE_STRING_EXT_INIT(ninep_msg_type);
232
233
enum _9p_version {
234
  _9P = 1,
235
  _9P2000,
236
  _9P2000_L,
237
  _9P2000_u
238
};
239
240
static const value_string ninep_version[] =
241
{
242
  {_9P,   "9P"},
243
  {_9P2000, "9P2000"},
244
  {_9P2000_L, "9P2000.L"},
245
  {_9P2000_u, "9P2000.u"},
246
  {0,   NULL},
247
};
248
static value_string_ext ninep_version_ext = VALUE_STRING_EXT_INIT(ninep_version);
249
250
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
16
#define _9P_MODEMASK        0x3
257
16
#define _9P_OTRUNC         0x10
258
16
#define _9P_ORCLOSE        0x40
259
260
/* Open/Create modes */
261
static const value_string ninep_mode_vals[] =
262
{
263
  {_9P_OREAD, "Read Access"},
264
  {_9P_OWRITE,  "Write Access"},
265
  {_9P_ORDWR, "Read/Write Access "},
266
  {_9P_OEXEC, "Execute Access"},
267
  {0,   NULL},
268
};
269
static value_string_ext ninep_mode_vals_ext = VALUE_STRING_EXT_INIT(ninep_mode_vals);
270
271
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 */
279
280
281
/**
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
292
 *
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
297
 *
298
 * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat
299
 */
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
310
};
311
312
/* 9P Magic Numbers */
313
333
#define _9P_NOTAG (uint16_t)(~0)
314
388
#define _9P_NOFID (uint32_t)(~0)
315
#define _9P_NONUNAME  (uint32_t)(~0)
316
#define _9P_MAXWELEM  16
317
318
319
/**
320
 * @brief Length prefixed string type
321
 *
322
 * The protocol uses length prefixed strings for all
323
 * string data, so we replicate that for our internal
324
 * string members.
325
 */
326
327
struct _9p_str {
328
  uint16_t len; /* Length of the string */
329
  char *str; /* The string */
330
};
331
332
/**
333
 * @brief file system entity information
334
 *
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.
345
 *
346
 * See Also://plan9.bell-labs.com/magic/man2html/2/stat
347
 */
348
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 */
353
};
354
355
356
/* Bit values for getattr valid field.
357
 */
358
16
#define _9P_GETATTR_MODE         0x00000001U
359
16
#define _9P_GETATTR_NLINK        0x00000002U
360
16
#define _9P_GETATTR_UID          0x00000004U
361
16
#define _9P_GETATTR_GID          0x00000008U
362
16
#define _9P_GETATTR_RDEV         0x00000010U
363
16
#define _9P_GETATTR_ATIME        0x00000020U
364
16
#define _9P_GETATTR_MTIME        0x00000040U
365
16
#define _9P_GETATTR_CTIME        0x00000080U
366
16
#define _9P_GETATTR_INO          0x00000100U
367
16
#define _9P_GETATTR_SIZE         0x00000200U
368
16
#define _9P_GETATTR_BLOCKS       0x00000400U
369
370
16
#define _9P_GETATTR_BTIME        0x00000800U
371
16
#define _9P_GETATTR_GEN          0x00001000U
372
16
#define _9P_GETATTR_DATA_VERSION 0x00002000U
373
374
#if 0
375
#define _9P_GETATTR_BASIC        0x000007ffU  /* Mask for fields up to BLOCKS */
376
#endif
377
16
#define _9P_GETATTR_ALL          0x00003fffU  /* Mask for All fields above */
378
379
380
/* Bit values for setattr valid field from <linux/fs.h>.
381
 */
382
16
#define _9P_SETATTR_MODE         0x00000001U
383
16
#define _9P_SETATTR_UID          0x00000002U
384
16
#define _9P_SETATTR_GID          0x00000004U
385
16
#define _9P_SETATTR_SIZE         0x00000008U
386
16
#define _9P_SETATTR_ATIME        0x00000010U
387
16
#define _9P_SETATTR_MTIME        0x00000020U
388
16
#define _9P_SETATTR_CTIME        0x00000040U
389
16
#define _9P_SETATTR_ATIME_SET    0x00000080U
390
16
#define _9P_SETATTR_MTIME_SET    0x00000100U
391
392
16
#define _9P_SETATTR_ALL 0x000001FFU
393
394
/* 9p2000.L open flags */
395
#define _9P_DOTL_RDONLY   00000000
396
32
#define _9P_DOTL_WRONLY   00000001
397
32
#define _9P_DOTL_RDWR   00000002
398
#define _9P_DOTL_NOACCESS 00000003
399
16
#define _9P_DOTL_CREATE   00000100
400
16
#define _9P_DOTL_EXCL   00000200
401
16
#define _9P_DOTL_NOCTTY   00000400
402
16
#define _9P_DOTL_TRUNC    00001000
403
16
#define _9P_DOTL_APPEND   00002000
404
16
#define _9P_DOTL_NONBLOCK 00004000
405
16
#define _9P_DOTL_DSYNC    00010000
406
16
#define _9P_DOTL_FASYNC   00020000
407
16
#define _9P_DOTL_DIRECT   00040000
408
16
#define _9P_DOTL_LARGEFILE  00100000
409
16
#define _9P_DOTL_DIRECTORY  00200000
410
16
#define _9P_DOTL_NOFOLLOW 00400000
411
16
#define _9P_DOTL_NOATIME  01000000
412
16
#define _9P_DOTL_CLOEXEC  02000000
413
16
#define _9P_DOTL_SYNC   04000000
414
415
416
/* Bit values for lock type.
417
 */
418
#define _9P_LOCK_TYPE_RDLCK 0
419
#define _9P_LOCK_TYPE_WRLCK 1
420
#define _9P_LOCK_TYPE_UNLCK 2
421
422
/* 9P lock type to string table */
423
static const value_string ninep_lock_type[] =
424
{
425
  {_9P_LOCK_TYPE_RDLCK, "Read lock"},
426
  {_9P_LOCK_TYPE_WRLCK, "Write lock"},
427
  {_9P_LOCK_TYPE_UNLCK, "Unlock"},
428
  { 0,      NULL},
429
};
430
static value_string_ext ninep_lock_type_ext = VALUE_STRING_EXT_INIT(ninep_lock_type);
431
432
/* Bit values for lock status.
433
 */
434
#define _9P_LOCK_SUCCESS 0
435
#define _9P_LOCK_BLOCKED 1
436
#define _9P_LOCK_ERROR   2
437
#define _9P_LOCK_GRACE   3
438
439
/* 9P lock status to string table */
440
static const value_string ninep_lock_status[] =
441
{
442
  {_9P_LOCK_SUCCESS,  "Success"},
443
  {_9P_LOCK_BLOCKED,  "Blocked"},
444
  {_9P_LOCK_ERROR,  "Error"},
445
  {_9P_LOCK_GRACE,  "Grace"},
446
  { 0,      NULL},
447
};
448
static value_string_ext ninep_lock_status_ext = VALUE_STRING_EXT_INIT(ninep_lock_status);
449
450
/* Bit values for lock flags.
451
 */
452
#define _9P_LOCK_FLAGS_NONE    0
453
#define _9P_LOCK_FLAGS_BLOCK   1
454
#define _9P_LOCK_FLAGS_RECLAIM 2
455
456
/* 9P lock flag to string table */
457
static const value_string ninep_lock_flag[] =
458
{
459
  {_9P_LOCK_FLAGS_NONE,   "No flag"},
460
  {_9P_LOCK_FLAGS_BLOCK,  "Block"},
461
  {_9P_LOCK_FLAGS_RECLAIM,"Reclaim"},
462
  { 0,      NULL},
463
};
464
static value_string_ext ninep_lock_flag_ext = VALUE_STRING_EXT_INIT(ninep_lock_flag);
465
466
/*
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.
471
 *
472
 * The platforms in question appear to be:
473
 *
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?)
480
 *
481
 * For now, we don't worry about this, and use the errno values used
482
 * on most Linux platforms.
483
 */
484
static const value_string linux_errno[] =
485
{
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}
620
};
621
static value_string_ext linux_errno_ext = VALUE_STRING_EXT_INIT(linux_errno);
622
623
static const char *const invalid_fid_str = "<invalid fid>";
624
static const char *const afid_str = "<afid>";
625
626
/* Structures for Protocol Operations */
627
struct _9p_rlerror {
628
  uint32_t ecode;
629
};
630
struct _9p_tstatfs {
631
  uint32_t fid;
632
};
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;
643
};
644
struct _9p_tlopen {
645
  uint32_t fid;
646
  uint32_t flags;
647
};
648
struct _9p_rlopen {
649
  struct _9p_qid qid;
650
  uint32_t iounit;
651
};
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;
658
};
659
struct _9p_rlcreate {
660
  struct _9p_qid qid;
661
  uint32_t iounit;
662
};
663
struct _9p_tsymlink {
664
  uint32_t fid;
665
  struct _9p_str name;
666
  struct _9p_str symtgt;
667
  uint32_t gid;
668
};
669
struct _9p_rsymlink {
670
  struct _9p_qid qid;
671
};
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;
679
};
680
struct _9p_rmknod {
681
  struct _9p_qid qid;
682
};
683
struct _9p_trename {
684
  uint32_t fid;
685
  uint32_t dfid;
686
  struct _9p_str name;
687
};
688
#if 0
689
struct _9p_rrename {
690
};
691
#endif
692
struct _9p_treadlink {
693
  uint32_t fid;
694
};
695
struct _9p_rreadlink {
696
  struct _9p_str target;
697
};
698
struct _9p_tgetattr {
699
  uint32_t fid;
700
  uint64_t request_mask;
701
};
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;
723
};
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;
735
};
736
#if 0
737
struct _9p_rsetattr {
738
};
739
#endif
740
struct _9p_txattrwalk {
741
  uint32_t fid;
742
  uint32_t attrfid;
743
  struct _9p_str name;
744
};
745
struct _9p_rxattrwalk {
746
  uint64_t size;
747
};
748
struct _9p_txattrcreate {
749
  uint32_t fid;
750
  struct _9p_str name;
751
  uint64_t size;
752
  uint32_t flag;
753
};
754
#if 0
755
struct _9p_rxattrcreate {
756
};
757
#endif
758
struct _9p_treaddir {
759
  uint32_t fid;
760
  uint64_t offset;
761
  uint32_t count;
762
};
763
struct _9p_rreaddir {
764
  uint32_t count;
765
  uint8_t *data;
766
};
767
struct _9p_tfsync {
768
  uint32_t fid;
769
};
770
#if 0
771
struct _9p_rfsync {
772
};
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;
782
};
783
struct _9p_rlock {
784
  uint8_t status;
785
};
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;
793
};
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;
800
};
801
struct _9p_tlink {
802
  uint32_t dfid;
803
  uint32_t fid;
804
  struct _9p_str name;
805
};
806
#if 0
807
struct _9p_rlink {
808
};
809
#endif
810
struct _9p_tmkdir {
811
  uint32_t fid;
812
  struct _9p_str name;
813
  uint32_t mode;
814
  uint32_t gid;
815
};
816
struct _9p_rmkdir {
817
  struct _9p_qid qid;
818
};
819
struct _9p_trenameat {
820
  uint32_t olddirfid;
821
  struct _9p_str oldname;
822
  uint32_t newdirfid;
823
  struct _9p_str newname;
824
};
825
#if 0
826
struct _9p_rrenameat {
827
};
828
#endif
829
struct _9p_tunlinkat {
830
  uint32_t dirfid;
831
  struct _9p_str name;
832
  uint32_t flags;
833
};
834
#if 0
835
struct _9p_runlinkat {
836
};
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;
846
};
847
struct _9p_rawrite {
848
  uint32_t count;
849
};
850
struct _9p_tversion {
851
  uint32_t msize              ;
852
  struct _9p_str version ;
853
};
854
struct _9p_rversion {
855
  uint32_t msize;
856
  struct _9p_str version;
857
};
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 */
863
};
864
struct _9p_rauth {
865
  struct _9p_qid qid;
866
};
867
struct _9p_rerror {
868
  struct _9p_str error;
869
  uint32_t errnum;    /* 9p2000.u extension */
870
};
871
struct _9p_tflush {
872
  uint16_t oldtag;
873
};
874
#if 0
875
struct _9p_rflush {
876
};
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 */
884
};
885
struct _9p_rattach {
886
  struct _9p_qid qid;
887
};
888
struct _9p_twalk {
889
  uint32_t fid;
890
  uint32_t newfid;
891
  uint16_t nwname;
892
  struct _9p_str wnames[_9P_MAXWELEM];
893
};
894
struct _9p_rwalk {
895
  uint16_t nwqid;
896
  struct _9p_qid wqids[_9P_MAXWELEM];
897
};
898
struct _9p_topen {
899
  uint32_t fid;
900
  uint8_t mode;
901
};
902
struct _9p_ropen {
903
  struct _9p_qid qid;
904
  uint32_t iounit;
905
};
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;
912
};
913
struct _9p_rcreate {
914
  struct _9p_qid qid;
915
  uint32_t iounit;
916
};
917
struct _9p_tread {
918
  uint32_t fid;
919
  uint64_t offset;
920
  uint32_t count;
921
};
922
struct _9p_rread {
923
  uint32_t count;
924
  uint8_t *data;
925
};
926
struct _9p_twrite {
927
  uint32_t fid;
928
  uint64_t offset;
929
  uint32_t count;
930
  uint8_t *data;
931
};
932
struct _9p_rwrite {
933
  uint32_t count;
934
};
935
struct _9p_tclunk {
936
  uint32_t fid;
937
};
938
#if 0
939
struct _9p_rclunk {
940
};
941
#endif
942
struct _9p_tremove {
943
  uint32_t fid;
944
};
945
#if 0
946
struct _9p_rremove {
947
};
948
949
union _9p_tmsg {
950
} ;
951
#endif
952
16
#define NINEPORT 564
953
954
/* Forward declarations */
955
void proto_register_9P(void);
956
void proto_reg_handoff_9P(void);
957
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;
1096
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;
1115
1116
static expert_field ei_9P_first_250;
1117
static expert_field ei_9P_msgtype;
1118
1119
static wmem_map_t *_9p_hashtable;
1120
1121
static void dissect_9P_dm(tvbuff_t *tvb,  proto_item *tree, unsigned offset, int iscreate);
1122
static void dissect_9P_qid(tvbuff_t *tvb,  proto_tree *tree, unsigned offset);
1123
static void dissect_9P_lflags(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1124
static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1125
static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_tree *tree, unsigned offset);
1126
1127
static int * const _9P_modes[] = {
1128
  &hf_9P_mode_c,
1129
  &hf_9P_mode_t,
1130
  &hf_9P_mode_rwx,
1131
  NULL
1132
};
1133
1134
struct _9p_hashkey {
1135
  uint32_t conv_index;
1136
  uint16_t tag;
1137
  uint32_t fid;
1138
};
1139
1140
struct _9p_hashval {
1141
  size_t len;
1142
  void *data;
1143
};
1144
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;
1150
};
1151
1152
20
static int _9p_hash_equal(const void *k1, const void *k2) {
1153
20
  const struct _9p_hashkey *key1 = (const struct _9p_hashkey *)k1, *key2 = (const struct _9p_hashkey *)k2;
1154
1155
20
  return ((key1->conv_index == key2->conv_index) && (key1->tag == key2->tag) && (key1->fid == key2->fid));
1156
20
}
1157
1158
static unsigned _9p_hash_hash(const void *k)
1159
363
{
1160
363
  const struct _9p_hashkey *key = (const struct _9p_hashkey *)k;
1161
1162
363
  return (key->conv_index ^ key->tag ^ key->fid);
1163
363
}
1164
1165
static struct _9p_hashval *_9p_hash_new_val(size_t len)
1166
41
{
1167
41
  struct _9p_hashval *val;
1168
41
  val = wmem_new(wmem_file_scope(), struct _9p_hashval);
1169
1170
41
  val->data = wmem_alloc(wmem_file_scope(), len);
1171
41
  val->len = len;
1172
1173
41
  return val;
1174
41
}
1175
1176
static void _9p_hash_set(packet_info *pinfo, uint16_t tag, uint32_t fid, struct _9p_hashval *val)
1177
41
{
1178
41
  struct _9p_hashkey *key;
1179
41
  struct _9p_hashval *oldval;
1180
41
  conversation_t *conv;
1181
1182
41
  conv = find_or_create_conversation(pinfo);
1183
1184
41
  key = wmem_new(wmem_file_scope(), struct _9p_hashkey);
1185
1186
41
  key->conv_index = conv->conv_index;
1187
41
  key->tag = tag;
1188
41
  key->fid = fid;
1189
1190
  /* remove eventual old entry */
1191
41
  oldval = (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, key);
1192
41
  if (oldval) {
1193
8
    wmem_map_remove(_9p_hashtable, key);
1194
8
  }
1195
41
  wmem_map_insert(_9p_hashtable, key, val);
1196
41
}
1197
1198
static struct _9p_hashval *_9p_hash_get(packet_info *pinfo, uint16_t tag, uint32_t fid)
1199
245
{
1200
245
  struct _9p_hashkey key;
1201
245
  conversation_t *conv;
1202
1203
245
  conv = find_or_create_conversation(pinfo);
1204
1205
245
  key.conv_index = conv->conv_index;
1206
245
  key.tag = tag;
1207
245
  key.fid = fid;
1208
1209
245
  return (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, &key);
1210
245
}
1211
1212
static void _9p_hash_free(packet_info *pinfo, uint16_t tag, uint32_t fid)
1213
47
{
1214
47
  struct _9p_hashkey key;
1215
47
  conversation_t *conv;
1216
1217
47
  conv = find_or_create_conversation(pinfo);
1218
1219
47
  key.conv_index = conv->conv_index;
1220
47
  key.tag = tag;
1221
47
  key.fid = fid;
1222
1223
47
  wmem_map_remove(_9p_hashtable, &key);
1224
47
}
1225
1226
static void conv_set_version(packet_info *pinfo, enum _9p_version version)
1227
1
{
1228
1
  struct _9p_hashval *val;
1229
1230
1
  val = _9p_hash_new_val(sizeof(enum _9p_version));
1231
1232
1233
1
  *(enum _9p_version*)val->data = version;
1234
1235
1
  _9p_hash_set(pinfo, _9P_NOTAG, _9P_NOFID, val);
1236
1
}
1237
1238
static enum _9p_version conv_get_version(packet_info *pinfo)
1239
167
{
1240
167
  struct _9p_hashval *val;
1241
1242
167
  val = _9p_hash_get(pinfo, _9P_NOTAG, _9P_NOFID);
1243
1244
167
  return val ? *(enum _9p_version*)val->data : _9P;
1245
167
}
1246
1247
static void conv_set_fid_nocopy(packet_info *pinfo, uint32_t fid, const char *path)
1248
6
{
1249
6
  struct _9p_hashval *val;
1250
1251
6
  if (pinfo->fd->visited || fid == _9P_NOFID)
1252
1
    return;
1253
1254
  /* get or create&insert fid tree */
1255
5
  val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1256
5
  if (!val) {
1257
4
    val = _9p_hash_new_val(0);
1258
4
    val->data = wmem_tree_new(wmem_file_scope());
1259
    /* val->len is intentionally left to 0 so the tree won't be freed */
1260
4
    _9p_hash_set(pinfo, _9P_NOTAG, fid, val);
1261
4
  }
1262
1263
  /* fill it */
1264
5
  wmem_tree_insert32((wmem_tree_t *)val->data, pinfo->num, (void *)path);
1265
5
}
1266
1267
static void conv_set_fid(packet_info *pinfo, uint32_t fid, const char *path, size_t len)
1268
3
{
1269
3
  char *str;
1270
1271
3
  if (pinfo->fd->visited || fid == _9P_NOFID || len == 0)
1272
0
    return;
1273
1274
3
  str = (char*)wmem_alloc(wmem_file_scope(), len);
1275
3
  (void) g_strlcpy(str, path, len);
1276
3
  conv_set_fid_nocopy(pinfo, fid, str);
1277
3
}
1278
1279
static const char *conv_get_fid(packet_info *pinfo, uint32_t fid)
1280
71
{
1281
71
  struct _9p_hashval *val;
1282
1283
71
  if (fid == _9P_NOFID)
1284
2
    return invalid_fid_str;
1285
1286
69
  val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1287
69
  if (!val)
1288
67
    return invalid_fid_str;
1289
1290
  /* -1 because the fid needs to have been set on a previous message.
1291
     Let's ignore the possibility of num == 0... */
1292
2
  return (char*)wmem_tree_lookup32_le((wmem_tree_t*)val->data, pinfo->num-1);
1293
69
}
1294
1295
static inline void conv_free_fid(packet_info *pinfo, uint32_t fid)
1296
1
{
1297
1
  conv_set_fid_nocopy(pinfo, fid, invalid_fid_str);
1298
1
}
1299
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)
1301
36
{
1302
36
  struct _9p_hashval *val;
1303
36
  struct _9p_taginfo *taginfo;
1304
1305
36
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1306
0
    return;
1307
1308
36
  val = _9p_hash_new_val(sizeof(struct _9p_taginfo));
1309
36
  taginfo = (struct _9p_taginfo*)val->data;
1310
1311
36
  taginfo->msgtype = msgtype;
1312
36
  taginfo->fid = fid;
1313
36
  if (fid_path) {
1314
1
    taginfo->fid_path = (char*)wmem_alloc(wmem_file_scope(), wmem_strbuf_get_len(fid_path)+1);
1315
1
    (void) g_strlcpy(taginfo->fid_path, wmem_strbuf_get_str(fid_path), wmem_strbuf_get_len(fid_path)+1);
1316
35
  } else {
1317
35
    taginfo->fid_path = NULL;
1318
35
  }
1319
1320
36
  _9p_hash_set(pinfo, tag, _9P_NOFID, val);
1321
36
}
1322
1323
static inline struct _9p_taginfo *conv_get_tag(packet_info *pinfo, uint16_t tag)
1324
4
{
1325
4
  struct _9p_hashval *val;
1326
1327
  /* get tag only makes sense on first pass, as tree isn't built like fid */
1328
4
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1329
0
    return NULL;
1330
1331
  /* check that length matches? */
1332
4
  val = _9p_hash_get(pinfo, tag, _9P_NOFID);
1333
1334
4
  return val ? (struct _9p_taginfo*)val->data : NULL;
1335
4
}
1336
1337
static inline void conv_free_tag(packet_info *pinfo, uint16_t tag)
1338
47
{
1339
47
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1340
0
    return;
1341
1342
47
  _9p_hash_free(pinfo, tag, _9P_NOFID);
1343
47
}
1344
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)
1348
138
{
1349
138
  uint16_t             _9p_len;
1350
138
  proto_item          *ti;
1351
138
  proto_tree          *sub_tree;
1352
1353
138
  _9p_len = tvb_get_letohs(tvb, offset);
1354
138
  ti = proto_tree_add_item(ninep_tree, hf_string, tvb, offset + 2,
1355
138
      _9p_len, ENC_UTF_8|ENC_NA);
1356
138
  sub_tree = proto_item_add_subtree(ti, ett_string);
1357
138
  proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1358
1359
138
  return 2 + _9p_len;
1360
138
}
1361
1362
/* Dissect 9P messages*/
1363
static int dissect_9P_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1364
167
{
1365
167
  uint32_t            u32, i, fid, dfid, newfid;
1366
167
  uint16_t            u16, tag, _9p_len;
1367
167
  enum _9p_msg_t      ninemsg;
1368
167
  unsigned            offset    = 0;
1369
167
  const char         *mname, *fid_path;
1370
167
  char               *tvb_s;
1371
167
  wmem_strbuf_t      *tmppath   = NULL;
1372
167
  int                 len, reportedlen;
1373
167
  tvbuff_t           *next_tvb;
1374
167
  proto_item         *ti, *msg_item;
1375
167
  proto_tree         *ninep_tree;
1376
167
  struct _9p_taginfo *taginfo;
1377
167
  int                 _9p_version;
1378
1379
167
  _9p_version = conv_get_version(pinfo);
1380
167
  col_set_str(pinfo->cinfo, COL_PROTOCOL, val_to_str_ext_const(_9p_version, &ninep_version_ext, "9P"));
1381
1382
167
  col_clear(pinfo->cinfo, COL_INFO);
1383
1384
  /*ninesz = tvb_get_letohl(tvb, offset);*/
1385
167
  ninemsg = (enum _9p_msg_t)tvb_get_uint8(tvb, offset + 4);
1386
1387
167
  mname = val_to_str_ext_const(ninemsg, &ninep_msg_type_ext, "Unknown");
1388
1389
167
  if(strcmp(mname, "Unknown") == 0) {
1390
35
    col_add_fstr(pinfo->cinfo, COL_INFO, "9P Data (Message type %u)", (unsigned)ninemsg);
1391
35
    return 0;
1392
35
  }
1393
1394
132
  tag = tvb_get_letohs(tvb, offset+5);
1395
132
  col_append_fstr(pinfo->cinfo, COL_INFO, "%s Tag=%u", mname, (unsigned)tag);
1396
1397
132
  ti = proto_tree_add_item(tree, proto_9P, tvb, 0, -1, ENC_NA);
1398
132
  ninep_tree = proto_item_add_subtree(ti, ett_9P);
1399
132
  proto_tree_add_item(ninep_tree, hf_9P_msgsz, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1400
132
  offset+= 4;
1401
1402
132
  msg_item = proto_tree_add_item(ninep_tree, hf_9P_msgtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1403
132
  ++offset;
1404
132
  proto_tree_add_item(ninep_tree, hf_9P_tag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1405
132
  offset += 2;
1406
1407
132
  switch(ninemsg) {
1408
2
  case _9P_RVERSION:
1409
3
  case _9P_TVERSION:
1410
3
    proto_tree_add_item(ninep_tree, hf_9P_maxsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1411
3
    offset += 4;
1412
1413
3
    if (!pinfo->fd->visited) {
1414
3
      _9p_len = tvb_get_letohs(tvb, offset);
1415
3
      tvb_s = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1416
1417
3
      if (!strcmp(tvb_s, "9P2000.L")) {
1418
0
        u32 = _9P2000_L;
1419
3
      } else if (!strcmp(tvb_s, "9P2000")) {
1420
0
        u32 = _9P2000;
1421
3
      } else if (!strcmp(tvb_s, "9P2000.u")) {
1422
0
        u32 = _9P2000_u;
1423
3
      } else {
1424
3
        u32 = _9P;
1425
3
      }
1426
1427
3
      conv_set_version(pinfo, (enum _9p_version)u32);
1428
3
    }
1429
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_version, ett_9P_version);
1430
1431
    /* don't set tag for tversion/free it for rversion,
1432
       we need that for the actual version number */
1433
3
    break;
1434
1435
1
  case _9P_TAUTH:
1436
1
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1437
1
    conv_set_fid_nocopy(pinfo, fid, afid_str);
1438
1
    offset += 4;
1439
1440
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_uname, ett_9P_uname);
1441
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_aname, ett_9P_aname);
1442
1443
1
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1444
1
    break;
1445
1446
2
  case _9P_RERROR:
1447
2
    if (_9p_version == _9P2000_L) {
1448
0
      u32 = tvb_get_letohl(tvb, offset);
1449
0
      ti = proto_tree_add_item(ninep_tree, hf_9P_enum, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1450
0
      proto_item_append_text(ti, " (%s)", val_to_str_ext_const(u32, &linux_errno_ext, "Unknown"));
1451
0
      offset += 4;
1452
2
    } else {
1453
2
      offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_ename, ett_9P_ename);
1454
2
    }
1455
1456
    /* conv_get_tag checks we're in first pass */
1457
2
    taginfo = conv_get_tag(pinfo, tag);
1458
2
    if (taginfo && (taginfo->msgtype == _9P_TWALK || taginfo->msgtype == _9P_TATTACH))
1459
0
      conv_free_fid(pinfo, taginfo->fid);
1460
1461
2
    conv_free_tag(pinfo, tag);
1462
2
    break;
1463
1464
2
  case _9P_TFLUSH:
1465
2
    u16 = tvb_get_letohs(tvb, offset);
1466
2
    proto_tree_add_item(ninep_tree, hf_9P_oldtag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1467
2
    conv_free_tag(pinfo, u16);
1468
1469
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1470
2
    break;
1471
1472
0
  case _9P_TATTACH:
1473
0
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1474
0
    offset += 4;
1475
1476
0
    proto_tree_add_item(ninep_tree, hf_9P_afid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1477
0
    offset += 4;
1478
1479
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_uname, ett_9P_uname);
1480
1481
0
    if(!pinfo->fd->visited) {
1482
0
      _9p_len = tvb_get_letohs(tvb, offset);
1483
0
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1484
0
      conv_set_fid(pinfo, fid, tvb_s, strlen(tvb_s)+1);
1485
0
    }
1486
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_aname, ett_9P_aname);
1487
1488
0
    if (_9p_version == _9P2000_u || _9p_version == _9P2000_L) {
1489
0
      proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1490
0
      offset += 4;
1491
0
    }
1492
1493
0
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1494
0
    break;
1495
1496
11
  case _9P_TWALK:
1497
11
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1498
11
    fid_path = conv_get_fid(pinfo, fid);
1499
11
    proto_item_append_text(ti, " (%s)", fid_path);
1500
11
    if (!pinfo->fd->visited) {
1501
11
      tmppath = wmem_strbuf_create(pinfo->pool);
1502
11
      wmem_strbuf_append(tmppath, fid_path);
1503
11
    }
1504
11
    offset += 4;
1505
1506
11
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1507
11
    offset += 4;
1508
1509
11
    proto_tree_add_item_ret_uint16(ninep_tree, hf_9P_nwalk, tvb, offset, 2, ENC_LITTLE_ENDIAN, &u16);
1510
11
    offset += 2;
1511
1512
115
    for(i = 0 ; i < u16; i++) {
1513
104
      if (!pinfo->fd->visited) {
1514
104
        _9p_len = tvb_get_letohs(tvb, offset);
1515
104
        tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1516
104
        wmem_strbuf_append_c(tmppath, '/');
1517
104
        wmem_strbuf_append(tmppath, tvb_s);
1518
104
      }
1519
1520
104
      if (i < 250) {
1521
94
        offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1522
94
      }
1523
104
    }
1524
1525
    /* I can't imagine anyone having a directory depth more than 25,
1526
       Limit to 10 times that to be sure, 2^16 is too much */
1527
11
    if(u16 > 250) {
1528
0
      expert_add_info(pinfo, ti, &ei_9P_first_250);
1529
0
    }
1530
1531
11
    if (!pinfo->fd->visited) {
1532
1
      conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1533
1
    }
1534
1535
11
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1536
11
    break;
1537
1538
9
  case _9P_RWALK:
1539
9
    u16 = tvb_get_letohs(tvb, offset);
1540
9
    ti = proto_tree_add_item(ninep_tree, hf_9P_nqid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1541
9
    offset += 2;
1542
    /* I can't imagine anyone having a directory depth more than 25,
1543
       Limit to 10 times that to be sure, 2^16 is too much */
1544
9
    if(u16 > 250) {
1545
7
      u16 = 250;
1546
7
    }
1547
1548
143
    for(i = 0; i < u16; i++) {
1549
134
      dissect_9P_qid(tvb, ninep_tree, offset);
1550
134
      offset += 13;
1551
134
    }
1552
1553
9
    if (i >= 250) {
1554
0
      expert_add_info(pinfo, ti, &ei_9P_first_250);
1555
0
    }
1556
1557
9
    conv_free_tag(pinfo, tag);
1558
9
    break;
1559
1
  case _9P_TLOPEN:
1560
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1561
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1562
1
    offset += 4;
1563
1564
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1565
1
    dissect_9P_lflags(tvb, ti, offset);
1566
1
    offset += 4;
1567
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1568
1
    break;
1569
1570
1
  case _9P_TOPEN:
1571
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1572
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1573
1
    offset += 4;
1574
1575
1
    proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1576
1
    offset += 1;
1577
1578
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1579
1
    break;
1580
1581
3
  case _9P_TCREATE:
1582
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1583
3
    fid_path = conv_get_fid(pinfo, fid);
1584
3
    proto_item_append_text(ti, " (%s)", fid_path);
1585
3
    offset += 4;
1586
1587
3
    if (!pinfo->fd->visited) {
1588
3
      _9p_len = tvb_get_letohs(tvb, offset);
1589
3
      tmppath = wmem_strbuf_create(pinfo->pool);
1590
3
      wmem_strbuf_append(tmppath, fid_path);
1591
3
      wmem_strbuf_append_c(tmppath, '/');
1592
3
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1593
3
      wmem_strbuf_append(tmppath, tvb_s);
1594
3
    }
1595
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1596
1597
3
    ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1598
3
    dissect_9P_dm(tvb, ti, offset, 1);
1599
3
    offset += 4;
1600
1601
3
    proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1602
3
    offset += 1;
1603
1604
3
    if (_9p_version == _9P2000_u) {
1605
0
      _9p_len = tvb_get_letohs(tvb, offset);
1606
0
      proto_tree_add_item(ninep_tree, hf_9P_extension, tvb, offset+2, 4, ENC_ASCII);
1607
0
      offset += 2 + _9p_len;
1608
0
    }
1609
1610
3
    conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1611
3
    break;
1612
1613
1
  case _9P_TLCREATE:
1614
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1615
1
    fid_path = conv_get_fid(pinfo, fid);
1616
1
    proto_item_append_text(ti, " (%s)", fid_path);
1617
1
    offset += 4;
1618
1619
1
    if (!pinfo->fd->visited) {
1620
1
      _9p_len = tvb_get_letohs(tvb, offset);
1621
1
      tmppath = wmem_strbuf_create(pinfo->pool);
1622
1
      wmem_strbuf_append(tmppath, fid_path);
1623
1
      wmem_strbuf_append_c(tmppath, '/');
1624
1
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1625
1
      wmem_strbuf_append(tmppath, tvb_s);
1626
1
    }
1627
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1628
1629
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_lflags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1630
1
    dissect_9P_lflags(tvb, ti, offset);
1631
1
    offset += 4;
1632
1633
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1634
1
    dissect_9P_dm(tvb, ti, offset, 0);
1635
1
    offset += 4;
1636
1637
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1638
1
    offset += 4;
1639
1640
1
    conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1641
1
    break;
1642
1643
3
  case _9P_TREAD:
1644
4
  case _9P_TREADDIR:
1645
4
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1646
4
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1647
4
    offset += 4;
1648
1649
4
    proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1650
4
    offset += 8;
1651
1652
4
    proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1653
4
    offset += 4;
1654
1655
4
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1656
4
    break;
1657
1658
2
  case _9P_RREAD:
1659
3
  case _9P_RREADDIR:
1660
3
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &u32);
1661
3
    offset += 4;
1662
1663
3
    len = tvb_reported_length_remaining(tvb, offset);
1664
3
    reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1665
3
    next_tvb = tvb_new_subset_length(tvb, offset, reportedlen);
1666
3
    call_data_dissector(next_tvb, pinfo, tree);
1667
3
    offset += len;
1668
1669
3
    conv_free_tag(pinfo, tag);
1670
3
    break;
1671
1672
2
  case _9P_TWRITE:
1673
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1674
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1675
2
    offset += 4;
1676
1677
2
    proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1678
2
    offset += 8;
1679
1680
2
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &u32);
1681
2
    offset += 4;
1682
2
    len = tvb_reported_length_remaining(tvb, offset);
1683
2
    reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1684
2
    next_tvb = tvb_new_subset_length(tvb, offset, reportedlen);
1685
2
    call_data_dissector(next_tvb, pinfo, tree);
1686
2
    offset += len;
1687
1688
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1689
2
    break;
1690
1691
1
  case _9P_RWRITE:
1692
1
    proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1693
1
    offset += 4;
1694
1695
1
    conv_free_tag(pinfo, tag);
1696
1
    break;
1697
1698
1
  case _9P_RSTAT:
1699
1
    proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1700
1
    offset += 2;
1701
1702
1
    proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1703
1
    offset += 2;
1704
1705
1
    proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1706
1
    offset += 2;
1707
1708
1
    proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1709
1
    offset += 4;
1710
1711
1
    dissect_9P_qid(tvb, ninep_tree, offset);
1712
1
    offset += 13;
1713
1714
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1715
1
    dissect_9P_dm(tvb, ti, offset, 0);
1716
1
    offset += 4;
1717
1718
1
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1719
1
    offset += 4;
1720
1721
1
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1722
1
    offset += 4;
1723
1724
1
    proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1725
1
    offset += 8;
1726
1727
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1728
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1729
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1730
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1731
1732
1
    conv_free_tag(pinfo, tag);
1733
1
    break;
1734
1735
3
  case _9P_TWSTAT:
1736
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1737
3
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1738
3
    offset += 4;
1739
1740
3
    proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1741
3
    offset += 2;
1742
1743
3
    proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1744
3
    offset += 2;
1745
1746
3
    proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1747
3
    offset += 2;
1748
1749
3
    proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1750
3
    offset += 4;
1751
1752
3
    dissect_9P_qid(tvb, ninep_tree, offset);
1753
3
    offset += 13;
1754
1755
3
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1756
3
    dissect_9P_dm(tvb, ti, offset, 0);
1757
3
    offset += 4;
1758
1759
3
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1760
3
    offset += 4;
1761
1762
3
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1763
3
    offset += 4;
1764
1765
3
    proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1766
3
    offset += 8;
1767
1768
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1769
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1770
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1771
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1772
1773
3
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1774
3
    break;
1775
1776
2
  case _9P_TGETATTR:
1777
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1778
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1779
2
    offset += 4;
1780
1781
2
    ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1782
2
    dissect_9P_getattrflags(tvb, ti, offset);
1783
2
    offset += 8;
1784
1785
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1786
2
    break;
1787
1788
3
  case _9P_RGETATTR:
1789
3
    ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1790
3
    dissect_9P_getattrflags(tvb, ti, offset);
1791
3
    offset += 8;
1792
1793
3
    dissect_9P_qid(tvb, ninep_tree, offset);
1794
3
    offset += 13;
1795
1796
3
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1797
3
    dissect_9P_dm(tvb, ti, offset, 0);
1798
3
    offset += 4;
1799
1800
3
    proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1801
3
    offset += 4;
1802
1803
3
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1804
3
    offset += 4;
1805
1806
3
    proto_tree_add_item(ninep_tree, hf_9P_nlink, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1807
3
    offset += 8;
1808
1809
3
    proto_tree_add_item(ninep_tree, hf_9P_rdev, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1810
3
    offset += 8;
1811
1812
3
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1813
3
    offset += 8;
1814
1815
3
    proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1816
3
    offset += 8;
1817
1818
3
    proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1819
3
    offset += 8;
1820
1821
3
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1822
3
    offset += 16;
1823
1824
3
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1825
3
    offset += 16;
1826
1827
3
    proto_tree_add_item(ninep_tree, hf_9P_ctime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1828
3
    offset += 16;
1829
1830
3
    proto_tree_add_item(ninep_tree, hf_9P_btime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1831
3
    offset += 16;
1832
1833
3
    proto_tree_add_item(ninep_tree, hf_9P_gen, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1834
3
    offset += 8;
1835
1836
3
    proto_tree_add_item(ninep_tree, hf_9P_dataversion, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1837
3
    offset += 8;
1838
1839
3
    conv_free_tag(pinfo, tag);
1840
3
    break;
1841
1842
1
  case _9P_TSETATTR:
1843
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1844
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1845
1
    offset += 4;
1846
1847
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_setattr_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1848
1
    dissect_9P_setattrflags(tvb, ti, offset);
1849
1
    offset += 4;
1850
1851
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1852
1
    dissect_9P_dm(tvb, ti, offset, 0);
1853
1
    offset += 4;
1854
1855
1
    proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1856
1
    offset += 4;
1857
1858
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1859
1
    offset += 4;
1860
1861
1
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1862
1
    offset += 8;
1863
1864
1
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1865
1
    offset += 16;
1866
1867
1
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1868
1
    offset += 16;
1869
1870
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1871
1
    break;
1872
1873
1
  case _9P_RSTATFS:
1874
1
    proto_tree_add_item(ninep_tree, hf_9P_fstype, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1875
1
    offset += 4;
1876
1877
1
    proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1878
1
    offset += 4;
1879
1880
1
    proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1881
1
    offset += 8;
1882
1883
1
    proto_tree_add_item(ninep_tree, hf_9P_bfree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1884
1
    offset += 8;
1885
1886
1
    proto_tree_add_item(ninep_tree, hf_9P_bavail, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1887
1
    offset += 8;
1888
1889
1
    proto_tree_add_item(ninep_tree, hf_9P_files, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1890
1
    offset += 8;
1891
1892
1
    proto_tree_add_item(ninep_tree, hf_9P_ffree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1893
1
    offset += 8;
1894
1895
1
    proto_tree_add_item(ninep_tree, hf_9P_fsid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1896
1
    offset += 8;
1897
1898
1
    proto_tree_add_item(ninep_tree, hf_9P_namelen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1899
1
    offset += 4;
1900
1901
1
    conv_free_tag(pinfo, tag);
1902
1
    break;
1903
1904
2
  case _9P_TSYMLINK:
1905
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1906
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1907
2
    offset += 4;
1908
1909
    /* name */
1910
2
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1911
    /* XXX: maybe use a new field for symtgt? */
1912
2
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1913
1914
2
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1915
2
    offset += 4;
1916
1917
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1918
2
    break;
1919
1920
0
  case _9P_TMKNOD:
1921
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1922
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1923
0
    offset += 4;
1924
1925
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1926
1927
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1928
0
    dissect_9P_dm(tvb, ti, offset, 0);
1929
0
    offset += 4;
1930
1931
0
    proto_tree_add_item(ninep_tree, hf_9P_mknod_major, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1932
0
    offset += 4;
1933
1934
0
    proto_tree_add_item(ninep_tree, hf_9P_mknod_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1935
0
    offset += 4;
1936
1937
0
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1938
0
    offset += 4;
1939
1940
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1941
0
    break;
1942
1943
3
  case _9P_TRENAME:
1944
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1945
3
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1946
3
    offset += 4;
1947
1948
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &dfid);
1949
3
    fid_path = conv_get_fid(pinfo, dfid);
1950
3
    proto_item_append_text(ti, " (%s)", fid_path);
1951
3
    offset += 4;
1952
1953
3
    if (!pinfo->fd->visited) {
1954
3
      _9p_len = tvb_get_letohs(tvb, offset);
1955
3
      tmppath = wmem_strbuf_create(pinfo->pool);
1956
3
      wmem_strbuf_append(tmppath, conv_get_fid(pinfo, dfid));
1957
3
      wmem_strbuf_append_c(tmppath, '/');
1958
1959
3
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1960
3
      wmem_strbuf_append(tmppath, tvb_s);
1961
1962
3
      conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1963
3
    }
1964
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1965
1966
3
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1967
3
    break;
1968
1969
1
  case _9P_RREADLINK:
1970
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1971
1972
1
    conv_free_tag(pinfo, tag);
1973
1
    break;
1974
1975
1
  case _9P_TXATTRWALK:
1976
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1977
1
    fid_path = conv_get_fid(pinfo, fid);
1978
1
    proto_item_append_text(ti, " (%s)", fid_path);
1979
1
    offset += 4;
1980
1981
1
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &newfid);
1982
1
    conv_set_fid_nocopy(pinfo, newfid, fid_path);
1983
1
    offset += 4;
1984
1985
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1986
1987
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1988
1
    break;
1989
1990
0
  case _9P_RXATTRWALK:
1991
0
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1992
0
    offset += 8;
1993
1994
0
    conv_free_tag(pinfo, tag);
1995
0
    break;
1996
1997
18
  case _9P_TXATTRCREATE:
1998
18
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1999
18
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2000
18
    offset += 4;
2001
2002
18
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2003
2004
18
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2005
18
    offset += 8;
2006
2007
18
    proto_tree_add_item(ninep_tree, hf_9P_xattr_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2008
18
    offset += 4;
2009
2010
18
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2011
18
    break;
2012
2013
1
  case _9P_TLOCK:
2014
2
  case _9P_TGETLOCK:
2015
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2016
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2017
2
    offset += 4;
2018
2019
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2020
2
    offset += 1;
2021
2022
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2023
2
    offset += 4;
2024
2025
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2026
2
    offset += 8;
2027
2028
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2029
2
    offset += 8;
2030
2031
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2032
2
    offset += 4;
2033
2034
2
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2035
2036
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2037
2
    break;
2038
2039
0
  case _9P_RLOCK:
2040
0
    proto_tree_add_item(ninep_tree, hf_9P_lock_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2041
0
    offset += 1;
2042
2043
0
    conv_free_tag(pinfo, tag);
2044
0
    break;
2045
2046
1
  case _9P_RGETLOCK:
2047
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2048
1
    offset += 1;
2049
2050
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2051
1
    offset += 4;
2052
2053
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2054
1
    offset += 8;
2055
2056
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2057
1
    offset += 8;
2058
2059
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2060
1
    offset += 4;
2061
2062
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2063
2064
1
    conv_free_tag(pinfo, tag);
2065
1
    break;
2066
2067
1
  case _9P_TLINK:
2068
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2069
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2070
1
    offset += 4;
2071
2072
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2073
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2074
1
    offset += 4;
2075
2076
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2077
2078
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2079
1
    break;
2080
2081
1
  case _9P_TMKDIR:
2082
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2083
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2084
1
    offset += 4;
2085
2086
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2087
2088
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2089
1
    dissect_9P_dm(tvb, ti, offset, 0);
2090
1
    offset += 4;
2091
2092
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2093
1
    offset += 4;
2094
2095
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2096
1
    break;
2097
2098
1
  case _9P_TRENAMEAT:
2099
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2100
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2101
1
    offset += 4;
2102
2103
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2104
2105
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2106
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2107
1
    offset += 4;
2108
2109
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2110
2111
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2112
1
    break;
2113
2114
1
  case _9P_TUNLINKAT:
2115
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2116
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2117
1
    offset += 4;
2118
2119
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2120
2121
1
    proto_tree_add_item(ninep_tree, hf_9P_unlinkat_flags, tvb,
2122
1
        offset, 4, ENC_LITTLE_ENDIAN);
2123
1
    offset += 4;
2124
2125
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2126
1
    break;
2127
2128
1
  case _9P_TREMOVE:
2129
1
  case _9P_TCLUNK:
2130
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2131
1
    offset += 4;
2132
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2133
1
    conv_free_fid(pinfo, fid);
2134
2135
1
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
2136
1
    break;
2137
2138
  /* Request with only fid */
2139
2
  case _9P_TSTATFS:
2140
3
  case _9P_TREADLINK:
2141
4
  case _9P_TFSYNC:
2142
4
  case _9P_TSTAT:
2143
4
    fid = tvb_get_letohl(tvb, offset);
2144
4
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2145
4
    offset += 4;
2146
4
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2147
2148
4
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2149
4
    break;
2150
2151
  /* Reply with qid and ionuit */
2152
3
  case _9P_RCREATE:
2153
4
  case _9P_RLCREATE:
2154
4
    dissect_9P_qid(tvb, ninep_tree, offset);
2155
4
    offset += 13;
2156
4
    proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2157
4
    offset += 4;
2158
2159
4
    taginfo = conv_get_tag(pinfo, tag);
2160
4
    if (taginfo && taginfo->fid_path) {
2161
0
      conv_set_fid_nocopy(pinfo, taginfo->fid, taginfo->fid_path);
2162
0
    }
2163
2164
4
    conv_free_tag(pinfo, tag);
2165
4
    break;
2166
2167
1
  case _9P_ROPEN:
2168
2
  case _9P_RLOPEN:
2169
2
    dissect_9P_qid(tvb, ninep_tree, offset);
2170
2
    offset += 13;
2171
2
    proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2172
2
    offset += 4;
2173
2174
2
    conv_free_tag(pinfo, tag);
2175
2
    break;
2176
2177
  /* Reply with only qid */
2178
1
  case _9P_RSYMLINK:
2179
3
  case _9P_RMKNOD:
2180
5
  case _9P_RMKDIR:
2181
6
  case _9P_RAUTH:
2182
7
  case _9P_RATTACH:
2183
7
    dissect_9P_qid(tvb, ninep_tree, offset);
2184
7
    offset += 13;
2185
2186
7
    conv_free_tag(pinfo, tag);
2187
7
    break;
2188
2189
  /* Empty reply */
2190
2
  case _9P_RRENAME:
2191
2
  case _9P_RSETATTR:
2192
3
  case _9P_RXATTRCREATE:
2193
3
  case _9P_RFSYNC:
2194
13
  case _9P_RLINK:
2195
14
  case _9P_RRENAMEAT:
2196
15
  case _9P_RUNLINKAT:
2197
20
  case _9P_RFLUSH:
2198
20
  case _9P_RCLUNK:
2199
22
  case _9P_RREMOVE:
2200
  /* Unhandled reply */
2201
23
  case _9P_RWSTAT:
2202
24
  case _9P_RLERROR:
2203
24
    conv_free_tag(pinfo, tag);
2204
24
    break;
2205
2206
  /* Should-not-happen query */
2207
3
  case _9P_TLERROR:
2208
3
  case _9P_TERROR:
2209
3
  default:
2210
3
    expert_add_info(pinfo, msg_item, &ei_9P_msgtype);
2211
3
    break;
2212
132
  }
2213
2214
  /* Show any extra data at the end of the message (but only
2215
     if it was captured) */
2216
85
  if (offset != tvb_captured_length(tvb))
2217
84
    proto_tree_add_item(ninep_tree, hf_9P_unknown_message, tvb, offset, -1, ENC_NA);
2218
85
  return tvb_captured_length(tvb);
2219
132
}
2220
2221
static unsigned get_9P_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
2222
                                int offset, void *data _U_)
2223
167
{
2224
167
  return (unsigned) tvb_get_letohl(tvb, offset);
2225
167
}
2226
2227
static int dissect_9P(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2228
107
{
2229
107
  tcp_dissect_pdus(tvb, pinfo, tree, true, 4,
2230
107
      get_9P_message_len, dissect_9P_message, data);
2231
107
  return tvb_captured_length(tvb);
2232
107
}
2233
2234
/* dissect 9P Qid */
2235
static void dissect_9P_qid(tvbuff_t *tvb,  proto_tree *tree, unsigned offset)
2236
153
{
2237
153
  proto_item *qidtype_item;
2238
153
  proto_tree *qid_tree,*qidtype_tree;
2239
153
  uint64_t path;
2240
153
  uint32_t vers;
2241
153
  uint8_t type;
2242
2243
153
  if(!tree)
2244
0
    return;
2245
2246
153
  type = tvb_get_uint8(tvb, offset);
2247
153
  vers = tvb_get_letohs(tvb, offset+1);
2248
153
  path = tvb_get_letoh64(tvb, offset+1+4);
2249
2250
153
  qid_tree = proto_tree_add_subtree_format(tree, tvb, offset, 13, ett_9P_qid, NULL,
2251
153
        "Qid type=0x%02x vers=%d path=%" PRIu64, type, vers, path);
2252
2253
153
  qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2254
153
  qidtype_tree = proto_item_add_subtree(qidtype_item, ett_9P_qidtype);
2255
2256
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_dir,       tvb, offset,     1, ENC_LITTLE_ENDIAN);
2257
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_append,    tvb, offset,     1, ENC_LITTLE_ENDIAN);
2258
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_exclusive, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2259
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_mount,     tvb, offset,     1, ENC_LITTLE_ENDIAN);
2260
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_auth_file, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2261
153
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_temp_file, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2262
2263
153
  proto_tree_add_item(qid_tree, hf_9P_qidvers,               tvb, offset+1,   4, ENC_LITTLE_ENDIAN);
2264
153
  proto_tree_add_item(qid_tree, hf_9P_qidpath,               tvb, offset+1+4, 8, ENC_LITTLE_ENDIAN);
2265
153
}
2266
2267
/*dissect 9P stat mode and create perm flags */
2268
static void dissect_9P_dm(tvbuff_t *tvb,  proto_item *item, unsigned offset, int iscreate)
2269
7
{
2270
7
  proto_item *mode_tree;
2271
2272
2273
7
  mode_tree = proto_item_add_subtree(item, ett_9P_dm);
2274
7
  if(!mode_tree)
2275
0
    return;
2276
2277
7
  proto_tree_add_item(mode_tree, hf_9P_dm_dir, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2278
7
  if(!iscreate) { /* Not applicable to Tcreate (?) */
2279
6
    proto_tree_add_item(mode_tree, hf_9P_dm_append,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2280
6
    proto_tree_add_item(mode_tree, hf_9P_dm_exclusive, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2281
6
    proto_tree_add_item(mode_tree, hf_9P_dm_mount,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2282
6
    proto_tree_add_item(mode_tree, hf_9P_dm_auth_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2283
6
    proto_tree_add_item(mode_tree, hf_9P_dm_temp_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2284
6
  }
2285
2286
7
  proto_tree_add_item(mode_tree, hf_9P_dm_read_owner,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2287
7
  proto_tree_add_item(mode_tree, hf_9P_dm_write_owner,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2288
7
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_owner,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2289
7
  proto_tree_add_item(mode_tree, hf_9P_dm_read_group,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2290
7
  proto_tree_add_item(mode_tree, hf_9P_dm_write_group,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2291
7
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_group,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2292
7
  proto_tree_add_item(mode_tree, hf_9P_dm_read_others,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2293
7
  proto_tree_add_item(mode_tree, hf_9P_dm_write_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2294
7
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_others,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2295
7
}
2296
2297
/* Dissect 9P getattr_flags */
2298
static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2299
5
{
2300
5
  proto_item *attrmask_tree;
2301
2302
5
  attrmask_tree = proto_item_add_subtree(item, ett_9P_getattr_flags);
2303
5
  if(!attrmask_tree)
2304
0
    return;
2305
2306
  /* fixme: This is actually 8 bytes (64bit) long, but masks have to fit on 32bit. */
2307
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_mode,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2308
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_nlink,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2309
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_uid,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2310
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_gid,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2311
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_rdev,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2312
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_atime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2313
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_mtime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2314
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_ctime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2315
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_ino,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2316
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_size,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2317
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_blocks,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2318
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_btime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2319
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_gen,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2320
5
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_dataversion, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2321
5
}
2322
2323
/* Dissect 9P setattr_flags */
2324
static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2325
1
{
2326
1
  proto_item *attrmask_tree;
2327
2328
1
  attrmask_tree = proto_item_add_subtree(item, ett_9P_setattr_flags);
2329
1
  if(!attrmask_tree)
2330
0
    return;
2331
2332
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mode,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2333
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_uid,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2334
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_gid,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2335
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_size,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2336
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2337
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2338
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_ctime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2339
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2340
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2341
1
}
2342
2343
/* Dissect 9P lflags */
2344
static void dissect_9P_lflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2345
1
{
2346
1
  proto_item *attrmask_tree;
2347
2348
1
  attrmask_tree = proto_item_add_subtree(item, ett_9P_lflags);
2349
1
  if(!attrmask_tree)
2350
0
    return;
2351
2352
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdonly,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2353
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_wronly,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2354
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdwr,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2355
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_create,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2356
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_excl,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2357
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_noctty,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2358
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_trunc,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2359
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_append,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2360
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_nonblock,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2361
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_dsync,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2362
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_fasync,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2363
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_direct,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2364
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_largefile, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2365
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_directory, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2366
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_nofollow,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2367
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_noatime,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2368
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_cloexec,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2369
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_sync,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2370
1
}
2371
2372
2373
/* Register 9P with Wireshark */
2374
void proto_register_9P(void)
2375
16
{
2376
16
  static hf_register_info hf[] = {
2377
16
    {&hf_9P_msgsz,
2378
16
     {"Msg length", "9p.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
2379
16
      "9P Message Length", HFILL}},
2380
16
    {&hf_9P_msgtype,
2381
16
     {"Msg Type", "9p.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ninep_msg_type_ext, 0x0,
2382
16
      "Message Type", HFILL}},
2383
16
    {&hf_9P_tag,
2384
16
     {"Tag", "9p.tag", FT_UINT16, BASE_DEC, NULL, 0x0,
2385
16
      "9P Tag", HFILL}},
2386
16
    {&hf_9P_oldtag,
2387
16
     {"Old tag", "9p.oldtag", FT_UINT16, BASE_DEC, NULL, 0x0,
2388
16
      NULL, HFILL}},
2389
16
    {&hf_9P_parmsz,
2390
16
     {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
2391
16
      "Parameter length", HFILL}},
2392
16
    {&hf_9P_maxsize,
2393
16
     {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
2394
16
      "Max message size", HFILL}},
2395
16
    {&hf_9P_fid,
2396
16
     {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
2397
16
      "File ID", HFILL}},
2398
16
    {&hf_9P_nqid,
2399
16
     {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
2400
16
      "Number of Qid results", HFILL}},
2401
16
    {&hf_9P_mode,
2402
16
     {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
2403
16
      NULL, HFILL}},
2404
16
    {&hf_9P_mode_rwx,
2405
16
     {"Open/Create Mode", "9p.mode.rwx", FT_UINT8, BASE_OCT | BASE_EXT_STRING, &ninep_mode_vals_ext, _9P_MODEMASK,
2406
16
      NULL, HFILL}},
2407
16
    {&hf_9P_mode_t,
2408
16
     {"Trunc", "9p.mode.trunc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_OTRUNC,
2409
16
      "Truncate", HFILL}},
2410
16
    {&hf_9P_mode_c,
2411
16
     {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_ORCLOSE,
2412
16
      NULL, HFILL}},
2413
16
    {&hf_9P_extension,
2414
16
     {"Extension string", "9p.extension", FT_STRING, BASE_NONE, NULL, 0x0,
2415
16
      "Link target for DSYMLINK mode, major+minor for DMDEVICE, empty for normal files", HFILL}},
2416
16
    {&hf_9P_iounit,
2417
16
     {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
2418
16
      NULL, HFILL}},
2419
16
    {&hf_9P_count,
2420
16
     {"Count", "9p.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2421
16
      NULL, HFILL}},
2422
16
    {&hf_9P_offset,
2423
16
     {"Offset", "9p.offset", FT_UINT64, BASE_DEC, NULL, 0x0,
2424
16
      NULL, HFILL}},
2425
16
    {&hf_9P_perm,
2426
16
     {"Permissions", "9p.perm", FT_UINT32, BASE_OCT, NULL, 0x0,
2427
16
      "Permission bits", HFILL}},
2428
16
    {&hf_9P_qidpath,
2429
16
     {"Qid path", "9p.qidpath", FT_UINT64, BASE_DEC, NULL, 0x0,
2430
16
      NULL, HFILL}},
2431
16
    {&hf_9P_dm_dir,
2432
16
     {"Directory", "9p.dm.dir", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x80000000,
2433
16
      NULL, HFILL}},
2434
16
    {&hf_9P_dm_append,
2435
16
     {"Append only", "9p.dm.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x40000000,
2436
16
      NULL, HFILL}},
2437
16
    {&hf_9P_dm_exclusive,
2438
16
     {"Exclusive use", "9p.dm.exclusive", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x20000000,
2439
16
      NULL, HFILL}},
2440
16
    {&hf_9P_dm_mount,
2441
16
     {"Mounted channel", "9p.dm.mount", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x10000000,
2442
16
      NULL, HFILL}},
2443
16
    {&hf_9P_dm_auth_file,
2444
16
     {"Authentication file", "9p.dm.auth_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x08000000,
2445
16
      NULL, HFILL}},
2446
16
    {&hf_9P_dm_temp_file,
2447
16
     {"Temporary file (not backed up)", "9p.dm.temp_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x04000000,
2448
16
      NULL, HFILL}},
2449
16
    {&hf_9P_dm_read_owner,
2450
16
     {"Read permission for owner", "9p.dm.read_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000100,
2451
16
      NULL, HFILL}},
2452
16
    {&hf_9P_dm_write_owner,
2453
16
     {"Write permission for owner", "9p.dm.write_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000080,
2454
16
      NULL, HFILL}},
2455
16
    {&hf_9P_dm_exec_owner,
2456
16
     {"Execute permission for owner", "9p.dm.exec_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000040,
2457
16
      NULL, HFILL}},
2458
16
    {&hf_9P_dm_read_group,
2459
16
     {"Read permission for group", "9p.dm.read_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000020,
2460
16
      NULL, HFILL}},
2461
16
    {&hf_9P_dm_write_group,
2462
16
     {"Write permission for group", "9p.dm.write_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000010,
2463
16
      NULL, HFILL}},
2464
16
    {&hf_9P_dm_exec_group,
2465
16
     {"Execute permission for group", "9p.dm.exec_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000008,
2466
16
      NULL, HFILL}},
2467
16
    {&hf_9P_dm_read_others,
2468
16
     {"Read permission for others", "9p.dm.read_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
2469
16
      NULL, HFILL}},
2470
16
    {&hf_9P_dm_write_others,
2471
16
     {"Write permission for others", "9p.dm.write_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
2472
16
      NULL, HFILL}},
2473
16
    {&hf_9P_dm_exec_others,
2474
16
     {"Execute permission for others", "9p.dm.exec_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
2475
16
      NULL, HFILL}},
2476
16
    {&hf_9P_qidvers,
2477
16
     {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
2478
16
      NULL, HFILL}},
2479
16
    {&hf_9P_qidtype,
2480
16
     {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
2481
16
      NULL, HFILL}},
2482
16
    {&hf_9P_qidtype_dir,
2483
16
     {"Directory", "9p.qidtype.dir", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
2484
16
      NULL, HFILL}},
2485
16
    {&hf_9P_qidtype_append,
2486
16
     {"Append only", "9p.qidtype.append", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
2487
16
      NULL, HFILL}},
2488
16
    {&hf_9P_qidtype_exclusive,
2489
16
     {"Exclusive use", "9p.qidtype.exclusive", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2490
16
      NULL, HFILL}},
2491
16
    {&hf_9P_qidtype_mount,
2492
16
     {"Mounted channel", "9p.qidtype.mount", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
2493
16
      NULL, HFILL}},
2494
16
    {&hf_9P_qidtype_auth_file,
2495
16
     {"Authentication file", "9p.qidtype.auth_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
2496
16
      NULL, HFILL}},
2497
16
    {&hf_9P_qidtype_temp_file,
2498
16
     {"Temporary file (not backed up)", "9p.qidtype.temp_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2499
16
      NULL, HFILL}},
2500
16
    {&hf_9P_statmode,
2501
16
     {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
2502
16
      "File mode flags", HFILL}},
2503
16
    {&hf_9P_stattype,
2504
16
     {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
2505
16
      NULL, HFILL}},
2506
16
    {&hf_9P_atime,
2507
16
     {"Atime", "9p.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2508
16
      "Access Time", HFILL}},
2509
16
    {&hf_9P_mtime,
2510
16
     {"Mtime", "9p.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2511
16
      "Modified Time", HFILL}},
2512
16
    {&hf_9P_ctime,
2513
16
     {"Ctime", "9p.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2514
16
      "Creation Time", HFILL}},
2515
16
    {&hf_9P_btime,
2516
16
     {"Btime", "9p.btime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2517
16
      "Btime (Synchronization information)", HFILL}},
2518
16
    {&hf_9P_length,
2519
16
     {"Length", "9p.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2520
16
      "File Length", HFILL}},
2521
16
    {&hf_9P_dev,
2522
16
     {"Dev", "9p.dev", FT_UINT32, BASE_DEC, NULL, 0x0,
2523
16
      NULL, HFILL}},
2524
16
    {&hf_9P_wname,
2525
16
     {"Wname", "9p.wname", FT_STRING, BASE_NONE, NULL, 0x0,
2526
16
      "Path Name Element", HFILL}},
2527
16
    {&hf_9P_version,
2528
16
     {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
2529
16
      NULL, HFILL}},
2530
16
    {&hf_9P_afid,
2531
16
     {"Afid", "9p.afid", FT_UINT32, BASE_DEC, NULL, 0x0,
2532
16
      "Authenticating FID", HFILL}},
2533
16
    {&hf_9P_uname,
2534
16
     {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
2535
16
      "User Name", HFILL}},
2536
16
    {&hf_9P_aname,
2537
16
     {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
2538
16
      "Access Name", HFILL}},
2539
16
    {&hf_9P_ename,
2540
16
     {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
2541
16
      "Error", HFILL}},
2542
16
    {&hf_9P_enum,
2543
16
     {"Enum", "9p.enum", FT_UINT32, BASE_DEC, NULL, 0x0,
2544
16
      "Error", HFILL}},
2545
#if 0
2546
    {&hf_9P_name,
2547
     {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
2548
      "Name of file", HFILL}},
2549
#endif
2550
16
    {&hf_9P_sdlen,
2551
16
     {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
2552
16
      NULL, HFILL}},
2553
16
    {&hf_9P_filename,
2554
16
     {"File name", "9p.filename", FT_STRING, BASE_NONE, NULL, 0x0,
2555
16
      NULL, HFILL}},
2556
16
    {&hf_9P_user,
2557
16
     {"User", "9p.user", FT_STRING, BASE_NONE, NULL, 0x0,
2558
16
      "User name", HFILL}},
2559
16
    {&hf_9P_group,
2560
16
     {"Group", "9p.group", FT_STRING, BASE_NONE, NULL, 0x0,
2561
16
      "Group name", HFILL}},
2562
16
    {&hf_9P_uid,
2563
16
     {"Uid", "9p.uid", FT_UINT32, BASE_DEC, NULL, 0x0,
2564
16
      "User id", HFILL}},
2565
16
    {&hf_9P_gid,
2566
16
     {"Gid", "9p.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
2567
16
      "Group id", HFILL}},
2568
16
    {&hf_9P_muid,
2569
16
     {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
2570
16
      "Last modifiers uid", HFILL}},
2571
16
    {&hf_9P_newfid,
2572
16
     {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2573
16
      "New file ID", HFILL}},
2574
16
    {&hf_9P_dfid,
2575
16
     {"Directory fid", "9p.dfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2576
16
      "Directory ID", HFILL}},
2577
16
    {&hf_9P_nwalk,
2578
16
     {"Nr Walks", "9p.nwalk", FT_UINT16, BASE_DEC, NULL, 0x0,
2579
16
      "Nr of walk items", HFILL}},
2580
16
    {&hf_9P_nlink,
2581
16
     {"nlink", "9p.nlink", FT_UINT64, BASE_DEC, NULL, 0x0,
2582
16
      "Number of links", HFILL}},
2583
16
    {&hf_9P_getattr_flags,
2584
16
     {"getattr_flags", "9p.getattr.flags", FT_UINT64, BASE_HEX, NULL, _9P_GETATTR_ALL,
2585
16
      "Getattr flags", HFILL}},
2586
16
    {&hf_9P_getattr_mode,
2587
16
     {"Mode", "9p.getattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MODE,
2588
16
      NULL, HFILL}},
2589
16
    {&hf_9P_getattr_nlink,
2590
16
     {"Nlink", "9p.getattr.nlink", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_NLINK,
2591
16
      NULL, HFILL}},
2592
16
    {&hf_9P_getattr_uid,
2593
16
     {"UID", "9p.getattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_UID,
2594
16
      NULL, HFILL}},
2595
16
    {&hf_9P_getattr_gid,
2596
16
     {"GID", "9p.getattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GID,
2597
16
      NULL, HFILL}},
2598
16
    {&hf_9P_getattr_rdev,
2599
16
     {"Rdev", "9p.getattr.rdev", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_RDEV,
2600
16
      NULL, HFILL}},
2601
16
    {&hf_9P_getattr_atime,
2602
16
     {"Atime", "9p.getattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_ATIME,
2603
16
      NULL, HFILL}},
2604
16
    {&hf_9P_getattr_mtime,
2605
16
     {"Mtime", "9p.getattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MTIME,
2606
16
      NULL, HFILL}},
2607
16
    {&hf_9P_getattr_ctime,
2608
16
     {"Ctime", "9p.getattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_CTIME,
2609
16
      NULL, HFILL}},
2610
16
    {&hf_9P_getattr_ino,
2611
16
     {"Inode", "9p.getattr.inode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_INO,
2612
16
      NULL, HFILL}},
2613
16
    {&hf_9P_getattr_size,
2614
16
     {"Size", "9p.getattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_SIZE,
2615
16
      NULL, HFILL}},
2616
16
    {&hf_9P_getattr_blocks,
2617
16
     {"Blocks", "9p.getattr.blocks", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BLOCKS,
2618
16
      NULL, HFILL}},
2619
16
    {&hf_9P_getattr_btime,
2620
16
     {"Btime", "9p.getattr.btime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BTIME,
2621
16
      NULL, HFILL}},
2622
16
    {&hf_9P_getattr_gen,
2623
16
     {"Gen", "9p.getattr.gen", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GEN,
2624
16
      NULL, HFILL}},
2625
16
    {&hf_9P_getattr_dataversion,
2626
16
     {"Data version", "9p.getattr.dataversion", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_DATA_VERSION,
2627
16
      NULL, HFILL}},
2628
16
    {&hf_9P_setattr_flags,
2629
16
     {"setattr_flags", "9p.setattr.flags", FT_UINT32, BASE_HEX, NULL, _9P_SETATTR_ALL,
2630
16
      "Setattr flags", HFILL}},
2631
16
    {&hf_9P_setattr_mode,
2632
16
     {"Mode", "9p.setattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MODE,
2633
16
      NULL, HFILL}},
2634
16
    {&hf_9P_setattr_uid,
2635
16
     {"UID", "9p.setattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_UID,
2636
16
      NULL, HFILL}},
2637
16
    {&hf_9P_setattr_gid,
2638
16
     {"GID", "9p.setattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_GID,
2639
16
      NULL, HFILL}},
2640
16
    {&hf_9P_setattr_size,
2641
16
     {"Size", "9p.setattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_SIZE,
2642
16
      NULL, HFILL}},
2643
16
    {&hf_9P_setattr_atime,
2644
16
     {"Atime", "9p.setattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME,
2645
16
      NULL, HFILL}},
2646
16
    {&hf_9P_setattr_mtime,
2647
16
     {"Mtime", "9p.setattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME,
2648
16
      NULL, HFILL}},
2649
16
    {&hf_9P_setattr_ctime,
2650
16
     {"Ctime", "9p.setattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_CTIME,
2651
16
      NULL, HFILL}},
2652
16
    {&hf_9P_setattr_atime_set,
2653
16
     {"Atime set", "9p.setattr.atimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME_SET,
2654
16
      NULL, HFILL}},
2655
16
    {&hf_9P_setattr_mtime_set,
2656
16
     {"Mtime set", "9p.setattr.mtimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME_SET,
2657
16
      NULL, HFILL}},
2658
16
    {&hf_9P_unlinkat_flags,
2659
16
     {"unlinkat flags", "9p.unlinkat.flags", FT_UINT32, BASE_HEX, NULL, 0,
2660
16
      NULL, HFILL}},
2661
16
    {&hf_9P_rdev,
2662
16
     {"rdev", "9p.rdev", FT_UINT64, BASE_DEC, NULL, 0x0,
2663
16
      "Device associated with file", HFILL}},
2664
16
    {&hf_9P_size,
2665
16
     {"Size", "9p.size", FT_UINT64, BASE_DEC, NULL, 0x0,
2666
16
      NULL, HFILL}},
2667
16
    {&hf_9P_blksize,
2668
16
     {"Blksize", "9p.blksize", FT_UINT64, BASE_DEC, NULL, 0x0,
2669
16
      "Block size", HFILL}},
2670
16
    {&hf_9P_blocks,
2671
16
     {"Blocks", "9p.blocks", FT_UINT64, BASE_DEC, NULL, 0x0,
2672
16
      NULL, HFILL}},
2673
16
    {&hf_9P_gen,
2674
16
     {"Gen", "9p.gen", FT_UINT64, BASE_DEC, NULL, 0x0,
2675
16
      "inode generation number", HFILL}},
2676
16
    {&hf_9P_dataversion,
2677
16
     {"Dataversion", "9p.dataversion", FT_UINT64, BASE_DEC, NULL, 0x0,
2678
16
      "Data version", HFILL}},
2679
16
    {&hf_9P_fstype,
2680
16
     {"fstype", "9p.fstype", FT_UINT32, BASE_HEX, NULL, 0x0,
2681
16
      "Filesystem type", HFILL}},
2682
16
    {&hf_9P_bfree,
2683
16
     {"bfree", "9p.bfree", FT_UINT64, BASE_DEC, NULL, 0x0,
2684
16
      "Free blocks", HFILL}},
2685
16
    {&hf_9P_bavail,
2686
16
     {"bavail", "9p.bavail", FT_UINT64, BASE_DEC, NULL, 0x0,
2687
16
      "Available blocks", HFILL}},
2688
16
    {&hf_9P_files,
2689
16
     {"files", "9p.files", FT_UINT64, BASE_DEC, NULL, 0x0,
2690
16
      "Total files", HFILL}},
2691
16
    {&hf_9P_ffree,
2692
16
     {"ffree", "9p.ffree", FT_UINT64, BASE_DEC, NULL, 0x0,
2693
16
      "Free files", HFILL}},
2694
16
    {&hf_9P_fsid,
2695
16
     {"fsid", "9p.fsid", FT_UINT64, BASE_DEC, NULL, 0x0,
2696
16
      "Filesystem id", HFILL}},
2697
16
    {&hf_9P_namelen,
2698
16
     {"namelen", "9p.namelen", FT_UINT32, BASE_DEC, NULL, 0x0,
2699
16
      "Max name length", HFILL}},
2700
16
    {&hf_9P_mknod_major,
2701
16
     {"mknod_major", "9p.mknod.major", FT_UINT32, BASE_DEC, NULL, 0x0,
2702
16
      "Major node number", HFILL}},
2703
16
    {&hf_9P_mknod_minor,
2704
16
     {"mknod_minor", "9p.mknod.minor", FT_UINT32, BASE_DEC, NULL, 0x0,
2705
16
      "Minor node number", HFILL}},
2706
16
    {&hf_9P_lflags,
2707
16
     {"lflags", "9p.lcreate.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
2708
16
      "Lcreate flags", HFILL}},
2709
    /* rdonly is 0x00, check instead that we are neither wronly nor rdwrite */
2710
16
    {&hf_9P_lflags_rdonly,
2711
16
     {"Read only", "9p.lflags.rdonly", FT_BOOLEAN, 32, TFS(&tfs_no_yes), _9P_DOTL_WRONLY|_9P_DOTL_RDWR,
2712
16
      NULL, HFILL}},
2713
16
    {&hf_9P_lflags_wronly,
2714
16
     {"Write only", "9p.lflags.wronly", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_WRONLY,
2715
16
      NULL, HFILL}},
2716
16
    {&hf_9P_lflags_rdwr,
2717
16
     {"Read Write", "9p.lflags.rdwr", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_RDWR,
2718
16
      NULL, HFILL}},
2719
16
    {&hf_9P_lflags_create,
2720
16
     {"Create", "9p.lflags.create", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CREATE,
2721
16
      NULL, HFILL}},
2722
16
    {&hf_9P_lflags_excl,
2723
16
     {"Exclusive", "9p.lflags.excl", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_EXCL,
2724
16
      NULL, HFILL}},
2725
16
    {&hf_9P_lflags_noctty,
2726
16
     {"noctty", "9p.lflags.noctty", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOCTTY,
2727
16
      NULL, HFILL}},
2728
16
    {&hf_9P_lflags_trunc,
2729
16
     {"Truncate", "9p.lflags.trunc", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_TRUNC,
2730
16
      NULL, HFILL}},
2731
16
    {&hf_9P_lflags_append,
2732
16
     {"Append", "9p.lflags.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_APPEND,
2733
16
      NULL, HFILL}},
2734
16
    {&hf_9P_lflags_nonblock,
2735
16
     {"Nonblock", "9p.lflags.nonblock", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NONBLOCK,
2736
16
      NULL, HFILL}},
2737
16
    {&hf_9P_lflags_dsync,
2738
16
     {"dsync", "9p.lflags.dsync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DSYNC,
2739
16
      NULL, HFILL}},
2740
16
    {&hf_9P_lflags_fasync,
2741
16
     {"fasync", "9p.lflags.fasync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_FASYNC,
2742
16
      NULL, HFILL}},
2743
16
    {&hf_9P_lflags_direct,
2744
16
     {"Direct", "9p.lflags.direct", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECT,
2745
16
      NULL, HFILL}},
2746
16
    {&hf_9P_lflags_largefile,
2747
16
     {"Large File", "9p.lflags.largefile", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_LARGEFILE,
2748
16
      NULL, HFILL}},
2749
16
    {&hf_9P_lflags_directory,
2750
16
     {"Directory", "9p.lflags.directory", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECTORY,
2751
16
      NULL, HFILL}},
2752
16
    {&hf_9P_lflags_nofollow,
2753
16
     {"No follow", "9p.lflags.nofollow", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOFOLLOW,
2754
16
      NULL, HFILL}},
2755
16
    {&hf_9P_lflags_noatime,
2756
16
     {"No atime", "9p.lflags.noatime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOATIME,
2757
16
      NULL, HFILL}},
2758
16
    {&hf_9P_lflags_cloexec,
2759
16
     {"cloexec", "9p.lflags.cloexec", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CLOEXEC,
2760
16
      NULL, HFILL}},
2761
16
    {&hf_9P_lflags_sync,
2762
16
     {"Sync", "9p.lflags.sync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_SYNC,
2763
16
      NULL, HFILL}},
2764
16
    {&hf_9P_xattr_flag,
2765
16
     {"xattr_flag", "9p.xattr.flag", FT_UINT32, BASE_HEX, NULL, 0x0,
2766
16
      "Xattr flag", HFILL}},
2767
16
    {&hf_9P_lock_type,
2768
16
     {"lock_type", "9p.lock.type", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_type_ext, 0x0,
2769
16
      "Lock type", HFILL}},
2770
16
    {&hf_9P_lock_flag,
2771
16
     {"lock_flag", "9p.lock.flag", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_flag_ext, 0x0,
2772
16
      "Lock flag", HFILL}},
2773
16
    {&hf_9P_lock_start,
2774
16
     {"lock_start", "9p.lock.start", FT_UINT64, BASE_DEC, NULL, 0x0,
2775
16
      "Lock start", HFILL}},
2776
16
    {&hf_9P_lock_length,
2777
16
     {"lock_length", "9p.lock.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2778
16
      "Lock length", HFILL}},
2779
16
    {&hf_9P_lock_procid,
2780
16
     {"lock_procid", "9p.lock.procid", FT_UINT32, BASE_HEX, NULL, 0x0,
2781
16
      "Lock procid", HFILL}},
2782
16
    {&hf_9P_lock_status,
2783
16
     {"lock_status", "9p.lock.status", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ninep_lock_status_ext, 0x0,
2784
16
      "Lock status", HFILL}},
2785
16
    {&hf_9P_unknown_message,
2786
16
     {"Message data", "9p.message_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2787
16
      NULL, HFILL}}
2788
16
  };
2789
2790
16
  static int *ett[] = {
2791
16
    &ett_9P,
2792
16
    &ett_9P_omode,
2793
16
    &ett_9P_dm,
2794
16
    &ett_9P_wname,
2795
16
    &ett_9P_aname,
2796
16
    &ett_9P_ename,
2797
16
    &ett_9P_uname,
2798
16
    &ett_9P_user,
2799
16
    &ett_9P_group,
2800
16
    &ett_9P_muid,
2801
16
    &ett_9P_filename,
2802
16
    &ett_9P_version,
2803
16
    &ett_9P_qid,
2804
16
    &ett_9P_qidtype,
2805
16
    &ett_9P_getattr_flags,
2806
16
    &ett_9P_setattr_flags,
2807
16
    &ett_9P_lflags,
2808
16
  };
2809
2810
16
  expert_module_t* expert_9P;
2811
2812
16
  static ei_register_info ei[] = {
2813
16
    { &ei_9P_first_250, { "9p.first_250", PI_PROTOCOL, PI_NOTE, "Only first 250 items shown", EXPFILL }},
2814
16
    { &ei_9P_msgtype, { "9p.msgtype.unknown", PI_PROTOCOL, PI_WARN, "This message type should not happen", EXPFILL }},
2815
16
  };
2816
2817
16
  proto_9P = proto_register_protocol("Plan 9", "9P", "9p");
2818
2819
16
  proto_register_field_array(proto_9P, hf, array_length(hf));
2820
16
  proto_register_subtree_array(ett, array_length(ett));
2821
16
  expert_9P = expert_register_protocol(proto_9P);
2822
16
  expert_register_field_array(expert_9P, ei, array_length(ei));
2823
2824
16
  _9p_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), _9p_hash_hash, _9p_hash_equal);
2825
2826
16
  ninep_handle = register_dissector("9p", dissect_9P, proto_9P);
2827
16
}
2828
2829
void proto_reg_handoff_9P(void)
2830
16
{
2831
16
  dissector_add_uint_with_preference("tcp.port", NINEPORT, ninep_handle);
2832
16
}
2833
2834
2835
/*
2836
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2837
 *
2838
 * Local variables:
2839
 * c-basic-offset: 8
2840
 * tab-width: 8
2841
 * indent-tabs-mode: t
2842
 * End:
2843
 *
2844
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2845
 * :indentSize=8:tabSize=8:noTabs=false:
2846
 */