Coverage Report

Created: 2026-11-12 07:01

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
155
#define _9P_NOTAG (uint16_t)(~0)
314
180
#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
13
static int _9p_hash_equal(const void *k1, const void *k2) {
1153
13
  const struct _9p_hashkey *key1 = (const struct _9p_hashkey *)k1, *key2 = (const struct _9p_hashkey *)k2;
1154
1155
13
  return ((key1->conv_index == key2->conv_index) && (key1->tag == key2->tag) && (key1->fid == key2->fid));
1156
13
}
1157
1158
static unsigned _9p_hash_hash(const void *k)
1159
160
{
1160
160
  const struct _9p_hashkey *key = (const struct _9p_hashkey *)k;
1161
1162
160
  return (key->conv_index ^ key->tag ^ key->fid);
1163
160
}
1164
1165
static struct _9p_hashval *_9p_hash_new_val(size_t len)
1166
16
{
1167
16
  struct _9p_hashval *val;
1168
16
  val = wmem_new(wmem_file_scope(), struct _9p_hashval);
1169
1170
16
  val->data = wmem_alloc(wmem_file_scope(), len);
1171
16
  val->len = len;
1172
1173
16
  return val;
1174
16
}
1175
1176
static void _9p_hash_set(packet_info *pinfo, uint16_t tag, uint32_t fid, struct _9p_hashval *val)
1177
16
{
1178
16
  struct _9p_hashkey *key;
1179
16
  struct _9p_hashval *oldval;
1180
16
  conversation_t *conv;
1181
1182
16
  conv = find_or_create_conversation(pinfo);
1183
1184
16
  key = wmem_new(wmem_file_scope(), struct _9p_hashkey);
1185
1186
16
  key->conv_index = conv->conv_index;
1187
16
  key->tag = tag;
1188
16
  key->fid = fid;
1189
1190
  /* remove eventual old entry */
1191
16
  oldval = (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, key);
1192
16
  if (oldval) {
1193
4
    wmem_map_remove(_9p_hashtable, key);
1194
4
  }
1195
16
  wmem_map_insert(_9p_hashtable, key, val);
1196
16
}
1197
1198
static struct _9p_hashval *_9p_hash_get(packet_info *pinfo, uint16_t tag, uint32_t fid)
1199
113
{
1200
113
  struct _9p_hashkey key;
1201
113
  conversation_t *conv;
1202
1203
113
  conv = find_or_create_conversation(pinfo);
1204
1205
113
  key.conv_index = conv->conv_index;
1206
113
  key.tag = tag;
1207
113
  key.fid = fid;
1208
1209
113
  return (struct _9p_hashval *)wmem_map_lookup(_9p_hashtable, &key);
1210
113
}
1211
1212
static void _9p_hash_free(packet_info *pinfo, uint16_t tag, uint32_t fid)
1213
23
{
1214
23
  struct _9p_hashkey key;
1215
23
  conversation_t *conv;
1216
1217
23
  conv = find_or_create_conversation(pinfo);
1218
1219
23
  key.conv_index = conv->conv_index;
1220
23
  key.tag = tag;
1221
23
  key.fid = fid;
1222
1223
23
  wmem_map_remove(_9p_hashtable, &key);
1224
23
}
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
77
{
1240
77
  struct _9p_hashval *val;
1241
1242
77
  val = _9p_hash_get(pinfo, _9P_NOTAG, _9P_NOFID);
1243
1244
77
  return val ? *(enum _9p_version*)val->data : _9P;
1245
77
}
1246
1247
static void conv_set_fid_nocopy(packet_info *pinfo, uint32_t fid, const char *path)
1248
4
{
1249
4
  struct _9p_hashval *val;
1250
1251
4
  if (pinfo->fd->visited || fid == _9P_NOFID)
1252
1
    return;
1253
1254
  /* get or create&insert fid tree */
1255
3
  val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1256
3
  if (!val) {
1257
2
    val = _9p_hash_new_val(0);
1258
2
    val->data = wmem_tree_new(wmem_file_scope());
1259
    /* val->len is intentionally left to 0 so the tree won't be freed */
1260
2
    _9p_hash_set(pinfo, _9P_NOTAG, fid, val);
1261
2
  }
1262
1263
  /* fill it */
1264
3
  wmem_tree_insert32((wmem_tree_t *)val->data, pinfo->num, (void *)path);
1265
3
}
1266
1267
static void conv_set_fid(packet_info *pinfo, uint32_t fid, const char *path, size_t len)
1268
2
{
1269
2
  char *str;
1270
1271
2
  if (pinfo->fd->visited || fid == _9P_NOFID || len == 0)
1272
0
    return;
1273
1274
2
  str = (char*)wmem_alloc(wmem_file_scope(), len);
1275
2
  (void) g_strlcpy(str, path, len);
1276
2
  conv_set_fid_nocopy(pinfo, fid, str);
1277
2
}
1278
1279
static const char *conv_get_fid(packet_info *pinfo, uint32_t fid)
1280
35
{
1281
35
  struct _9p_hashval *val;
1282
1283
35
  if (fid == _9P_NOFID)
1284
2
    return invalid_fid_str;
1285
1286
33
  val = _9p_hash_get(pinfo, _9P_NOTAG, fid);
1287
33
  if (!val)
1288
32
    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
1
  return (char*)wmem_tree_lookup32_le((wmem_tree_t*)val->data, pinfo->num-1);
1293
33
}
1294
1295
static inline void conv_free_fid(packet_info *pinfo, uint32_t fid)
1296
0
{
1297
0
  conv_set_fid_nocopy(pinfo, fid, invalid_fid_str);
1298
0
}
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
15
{
1302
15
  struct _9p_hashval *val;
1303
15
  struct _9p_taginfo *taginfo;
1304
1305
15
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1306
2
    return;
1307
1308
13
  val = _9p_hash_new_val(sizeof(struct _9p_taginfo));
1309
13
  taginfo = (struct _9p_taginfo*)val->data;
1310
1311
13
  taginfo->msgtype = msgtype;
1312
13
  taginfo->fid = fid;
1313
13
  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
12
  } else {
1317
12
    taginfo->fid_path = NULL;
1318
12
  }
1319
1320
13
  _9p_hash_set(pinfo, tag, _9P_NOFID, val);
1321
13
}
1322
1323
static inline struct _9p_taginfo *conv_get_tag(packet_info *pinfo, uint16_t tag)
1324
0
{
1325
0
  struct _9p_hashval *val;
1326
1327
  /* get tag only makes sense on first pass, as tree isn't built like fid */
1328
0
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1329
0
    return NULL;
1330
1331
  /* check that length matches? */
1332
0
  val = _9p_hash_get(pinfo, tag, _9P_NOFID);
1333
1334
0
  return val ? (struct _9p_taginfo*)val->data : NULL;
1335
0
}
1336
1337
static inline void conv_free_tag(packet_info *pinfo, uint16_t tag)
1338
24
{
1339
24
  if (pinfo->fd->visited || tag == _9P_NOTAG)
1340
1
    return;
1341
1342
23
  _9p_hash_free(pinfo, tag, _9P_NOFID);
1343
23
}
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
38
{
1349
38
  uint16_t             _9p_len;
1350
38
  proto_item          *ti;
1351
38
  proto_tree          *sub_tree;
1352
1353
38
  _9p_len = tvb_get_letohs(tvb, offset);
1354
38
  ti = proto_tree_add_item(ninep_tree, hf_string, tvb, offset + 2,
1355
38
      _9p_len, ENC_UTF_8|ENC_NA);
1356
38
  sub_tree = proto_item_add_subtree(ti, ett_string);
1357
38
  proto_tree_add_item(sub_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1358
1359
38
  return 2 + _9p_len;
1360
38
}
1361
1362
/* Dissect 9P messages*/
1363
static int dissect_9P_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1364
77
{
1365
77
  uint32_t            u32, i, fid, dfid, newfid;
1366
77
  uint16_t            u16, tag, _9p_len;
1367
77
  enum _9p_msg_t      ninemsg;
1368
77
  unsigned            offset    = 0;
1369
77
  const char         *mname, *fid_path;
1370
77
  char               *tvb_s;
1371
77
  wmem_strbuf_t      *tmppath   = NULL;
1372
77
  int                 len, reportedlen;
1373
77
  tvbuff_t           *next_tvb;
1374
77
  proto_item         *ti, *msg_item;
1375
77
  proto_tree         *ninep_tree;
1376
77
  struct _9p_taginfo *taginfo;
1377
77
  int                 _9p_version;
1378
1379
77
  _9p_version = conv_get_version(pinfo);
1380
77
  col_set_str(pinfo->cinfo, COL_PROTOCOL, val_to_str_ext_const(_9p_version, &ninep_version_ext, "9P"));
1381
1382
77
  col_clear(pinfo->cinfo, COL_INFO);
1383
1384
  /*ninesz = tvb_get_letohl(tvb, offset);*/
1385
77
  ninemsg = (enum _9p_msg_t)tvb_get_uint8(tvb, offset + 4);
1386
1387
77
  mname = val_to_str_ext_const(ninemsg, &ninep_msg_type_ext, "Unknown");
1388
1389
77
  if(strcmp(mname, "Unknown") == 0) {
1390
12
    col_add_fstr(pinfo->cinfo, COL_INFO, "9P Data (Message type %u)", (unsigned)ninemsg);
1391
12
    return 0;
1392
12
  }
1393
1394
65
  tag = tvb_get_letohs(tvb, offset+5);
1395
65
  col_append_fstr(pinfo->cinfo, COL_INFO, "%s Tag=%u", mname, (unsigned)tag);
1396
1397
65
  ti = proto_tree_add_item(tree, proto_9P, tvb, 0, -1, ENC_NA);
1398
65
  ninep_tree = proto_item_add_subtree(ti, ett_9P);
1399
65
  proto_tree_add_item(ninep_tree, hf_9P_msgsz, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1400
65
  offset+= 4;
1401
1402
65
  msg_item = proto_tree_add_item(ninep_tree, hf_9P_msgtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1403
65
  ++offset;
1404
65
  proto_tree_add_item(ninep_tree, hf_9P_tag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1405
65
  offset += 2;
1406
1407
65
  switch(ninemsg) {
1408
1
  case _9P_RVERSION:
1409
1
  case _9P_TVERSION:
1410
1
    proto_tree_add_item(ninep_tree, hf_9P_maxsize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1411
1
    offset += 4;
1412
1413
1
    if (!pinfo->fd->visited) {
1414
1
      _9p_len = tvb_get_letohs(tvb, offset);
1415
1
      tvb_s = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1416
1417
1
      if (!strcmp(tvb_s, "9P2000.L")) {
1418
0
        u32 = _9P2000_L;
1419
1
      } else if (!strcmp(tvb_s, "9P2000")) {
1420
0
        u32 = _9P2000;
1421
1
      } else if (!strcmp(tvb_s, "9P2000.u")) {
1422
0
        u32 = _9P2000_u;
1423
1
      } else {
1424
1
        u32 = _9P;
1425
1
      }
1426
1427
1
      conv_set_version(pinfo, (enum _9p_version)u32);
1428
1
    }
1429
1
    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
1
    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
1
  case _9P_RERROR:
1447
1
    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
1
    } else {
1453
1
      offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_ename, ett_9P_ename);
1454
1
    }
1455
1456
    /* conv_get_tag checks we're in first pass */
1457
1
    taginfo = conv_get_tag(pinfo, tag);
1458
1
    if (taginfo && (taginfo->msgtype == _9P_TWALK || taginfo->msgtype == _9P_TATTACH))
1459
0
      conv_free_fid(pinfo, taginfo->fid);
1460
1461
1
    conv_free_tag(pinfo, tag);
1462
1
    break;
1463
1464
0
  case _9P_TFLUSH:
1465
0
    u16 = tvb_get_letohs(tvb, offset);
1466
0
    proto_tree_add_item(ninep_tree, hf_9P_oldtag, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1467
0
    conv_free_tag(pinfo, u16);
1468
1469
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1470
0
    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
5
  case _9P_TWALK:
1497
5
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1498
5
    fid_path = conv_get_fid(pinfo, fid);
1499
5
    proto_item_append_text(ti, " (%s)", fid_path);
1500
5
    if (!pinfo->fd->visited) {
1501
5
      tmppath = wmem_strbuf_create(pinfo->pool);
1502
5
      wmem_strbuf_append(tmppath, fid_path);
1503
5
    }
1504
5
    offset += 4;
1505
1506
5
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1507
5
    offset += 4;
1508
1509
5
    proto_tree_add_item_ret_uint16(ninep_tree, hf_9P_nwalk, tvb, offset, 2, ENC_LITTLE_ENDIAN, &u16);
1510
5
    offset += 2;
1511
1512
    /* I can't imagine anyone having a directory depth more than 25,
1513
       Limit to 10 times that to be sure, 2^16 is too much */
1514
26
    for(i = 0 ; i < u16 && i < 250; i++) {
1515
21
      if (!pinfo->fd->visited) {
1516
21
        _9p_len = tvb_get_letohs(tvb, offset);
1517
21
        tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1518
21
        wmem_strbuf_append_c(tmppath, '/');
1519
21
        wmem_strbuf_append(tmppath, tvb_s);
1520
21
      }
1521
1522
21
      offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1523
21
    }
1524
1525
5
    if(u16 > 250) {
1526
0
      expert_add_info(pinfo, ti, &ei_9P_first_250);
1527
0
    }
1528
1529
5
    if (!pinfo->fd->visited) {
1530
0
      conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1531
0
    }
1532
1533
5
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
1534
5
    break;
1535
1536
6
  case _9P_RWALK:
1537
6
    u16 = tvb_get_letohs(tvb, offset);
1538
6
    ti = proto_tree_add_item(ninep_tree, hf_9P_nqid, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1539
6
    offset += 2;
1540
    /* I can't imagine anyone having a directory depth more than 25,
1541
       Limit to 10 times that to be sure, 2^16 is too much */
1542
6
    if(u16 > 250) {
1543
4
      u16 = 250;
1544
4
    }
1545
1546
48
    for(i = 0; i < u16; i++) {
1547
42
      dissect_9P_qid(tvb, ninep_tree, offset);
1548
42
      offset += 13;
1549
42
    }
1550
1551
6
    if (i >= 250) {
1552
0
      expert_add_info(pinfo, ti, &ei_9P_first_250);
1553
0
    }
1554
1555
6
    conv_free_tag(pinfo, tag);
1556
6
    break;
1557
1
  case _9P_TLOPEN:
1558
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1559
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1560
1
    offset += 4;
1561
1562
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1563
1
    dissect_9P_lflags(tvb, ti, offset);
1564
1
    offset += 4;
1565
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1566
1
    break;
1567
1568
0
  case _9P_TOPEN:
1569
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1570
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1571
0
    offset += 4;
1572
1573
0
    proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1574
0
    offset += 1;
1575
1576
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1577
0
    break;
1578
1579
1
  case _9P_TCREATE:
1580
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1581
1
    fid_path = conv_get_fid(pinfo, fid);
1582
1
    proto_item_append_text(ti, " (%s)", fid_path);
1583
1
    offset += 4;
1584
1585
1
    if (!pinfo->fd->visited) {
1586
1
      _9p_len = tvb_get_letohs(tvb, offset);
1587
1
      tmppath = wmem_strbuf_create(pinfo->pool);
1588
1
      wmem_strbuf_append(tmppath, fid_path);
1589
1
      wmem_strbuf_append_c(tmppath, '/');
1590
1
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1591
1
      wmem_strbuf_append(tmppath, tvb_s);
1592
1
    }
1593
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1594
1595
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_perm, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1596
1
    dissect_9P_dm(tvb, ti, offset, 1);
1597
1
    offset += 4;
1598
1599
1
    proto_tree_add_bitmask(ninep_tree, tvb, offset, hf_9P_mode, ett_9P_omode, _9P_modes, ENC_LITTLE_ENDIAN);
1600
1
    offset += 1;
1601
1602
1
    if (_9p_version == _9P2000_u) {
1603
0
      _9p_len = tvb_get_letohs(tvb, offset);
1604
0
      proto_tree_add_item(ninep_tree, hf_9P_extension, tvb, offset+2, 4, ENC_ASCII);
1605
0
      offset += 2 + _9p_len;
1606
0
    }
1607
1608
1
    conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1609
1
    break;
1610
1611
0
  case _9P_TLCREATE:
1612
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1613
0
    fid_path = conv_get_fid(pinfo, fid);
1614
0
    proto_item_append_text(ti, " (%s)", fid_path);
1615
0
    offset += 4;
1616
1617
0
    if (!pinfo->fd->visited) {
1618
0
      _9p_len = tvb_get_letohs(tvb, offset);
1619
0
      tmppath = wmem_strbuf_create(pinfo->pool);
1620
0
      wmem_strbuf_append(tmppath, fid_path);
1621
0
      wmem_strbuf_append_c(tmppath, '/');
1622
0
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1623
0
      wmem_strbuf_append(tmppath, tvb_s);
1624
0
    }
1625
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1626
1627
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_lflags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1628
0
    dissect_9P_lflags(tvb, ti, offset);
1629
0
    offset += 4;
1630
1631
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1632
0
    dissect_9P_dm(tvb, ti, offset, 0);
1633
0
    offset += 4;
1634
1635
0
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1636
0
    offset += 4;
1637
1638
0
    conv_set_tag(pinfo, tag, ninemsg, fid, tmppath);
1639
0
    break;
1640
1641
1
  case _9P_TREAD:
1642
1
  case _9P_TREADDIR:
1643
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1644
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1645
1
    offset += 4;
1646
1647
1
    proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1648
1
    offset += 8;
1649
1650
1
    proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1651
1
    offset += 4;
1652
1653
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1654
1
    break;
1655
1656
1
  case _9P_RREAD:
1657
2
  case _9P_RREADDIR:
1658
2
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &u32);
1659
2
    offset += 4;
1660
1661
2
    len = tvb_reported_length_remaining(tvb, offset);
1662
2
    reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1663
2
    next_tvb = tvb_new_subset_length(tvb, offset, reportedlen);
1664
2
    call_data_dissector(next_tvb, pinfo, tree);
1665
2
    offset += len;
1666
1667
2
    conv_free_tag(pinfo, tag);
1668
2
    break;
1669
1670
0
  case _9P_TWRITE:
1671
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1672
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1673
0
    offset += 4;
1674
1675
0
    proto_tree_add_item(ninep_tree, hf_9P_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1676
0
    offset += 8;
1677
1678
0
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &u32);
1679
0
    offset += 4;
1680
0
    len = tvb_reported_length_remaining(tvb, offset);
1681
0
    reportedlen = ((int)u32&0xffff) > len ? len : (int)u32&0xffff;
1682
0
    next_tvb = tvb_new_subset_length(tvb, offset, reportedlen);
1683
0
    call_data_dissector(next_tvb, pinfo, tree);
1684
0
    offset += len;
1685
1686
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1687
0
    break;
1688
1689
1
  case _9P_RWRITE:
1690
1
    proto_tree_add_item(ninep_tree, hf_9P_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1691
1
    offset += 4;
1692
1693
1
    conv_free_tag(pinfo, tag);
1694
1
    break;
1695
1696
1
  case _9P_RSTAT:
1697
1
    proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1698
1
    offset += 2;
1699
1700
1
    proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1701
1
    offset += 2;
1702
1703
1
    proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1704
1
    offset += 2;
1705
1706
1
    proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1707
1
    offset += 4;
1708
1709
1
    dissect_9P_qid(tvb, ninep_tree, offset);
1710
1
    offset += 13;
1711
1712
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1713
1
    dissect_9P_dm(tvb, ti, offset, 0);
1714
1
    offset += 4;
1715
1716
1
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1717
1
    offset += 4;
1718
1719
1
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1720
1
    offset += 4;
1721
1722
1
    proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1723
1
    offset += 8;
1724
1725
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1726
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1727
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1728
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1729
1730
1
    conv_free_tag(pinfo, tag);
1731
1
    break;
1732
1733
0
  case _9P_TWSTAT:
1734
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1735
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1736
0
    offset += 4;
1737
1738
0
    proto_tree_add_item(ninep_tree, hf_9P_parmsz, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1739
0
    offset += 2;
1740
1741
0
    proto_tree_add_item(ninep_tree, hf_9P_sdlen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1742
0
    offset += 2;
1743
1744
0
    proto_tree_add_item(ninep_tree, hf_9P_stattype, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1745
0
    offset += 2;
1746
1747
0
    proto_tree_add_item(ninep_tree, hf_9P_dev, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1748
0
    offset += 4;
1749
1750
0
    dissect_9P_qid(tvb, ninep_tree, offset);
1751
0
    offset += 13;
1752
1753
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1754
0
    dissect_9P_dm(tvb, ti, offset, 0);
1755
0
    offset += 4;
1756
1757
0
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1758
0
    offset += 4;
1759
1760
0
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN);
1761
0
    offset += 4;
1762
1763
0
    proto_tree_add_item(ninep_tree, hf_9P_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1764
0
    offset += 8;
1765
1766
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_filename, ett_9P_filename);
1767
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_user, ett_9P_user);
1768
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_group, ett_9P_group);
1769
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_muid, ett_9P_muid);
1770
1771
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1772
0
    break;
1773
1774
0
  case _9P_TGETATTR:
1775
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1776
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1777
0
    offset += 4;
1778
1779
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1780
0
    dissect_9P_getattrflags(tvb, ti, offset);
1781
0
    offset += 8;
1782
1783
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1784
0
    break;
1785
1786
0
  case _9P_RGETATTR:
1787
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_getattr_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1788
0
    dissect_9P_getattrflags(tvb, ti, offset);
1789
0
    offset += 8;
1790
1791
0
    dissect_9P_qid(tvb, ninep_tree, offset);
1792
0
    offset += 13;
1793
1794
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1795
0
    dissect_9P_dm(tvb, ti, offset, 0);
1796
0
    offset += 4;
1797
1798
0
    proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1799
0
    offset += 4;
1800
1801
0
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1802
0
    offset += 4;
1803
1804
0
    proto_tree_add_item(ninep_tree, hf_9P_nlink, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1805
0
    offset += 8;
1806
1807
0
    proto_tree_add_item(ninep_tree, hf_9P_rdev, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1808
0
    offset += 8;
1809
1810
0
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1811
0
    offset += 8;
1812
1813
0
    proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1814
0
    offset += 8;
1815
1816
0
    proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1817
0
    offset += 8;
1818
1819
0
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1820
0
    offset += 16;
1821
1822
0
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1823
0
    offset += 16;
1824
1825
0
    proto_tree_add_item(ninep_tree, hf_9P_ctime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1826
0
    offset += 16;
1827
1828
0
    proto_tree_add_item(ninep_tree, hf_9P_btime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1829
0
    offset += 16;
1830
1831
0
    proto_tree_add_item(ninep_tree, hf_9P_gen, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1832
0
    offset += 8;
1833
1834
0
    proto_tree_add_item(ninep_tree, hf_9P_dataversion, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1835
0
    offset += 8;
1836
1837
0
    conv_free_tag(pinfo, tag);
1838
0
    break;
1839
1840
1
  case _9P_TSETATTR:
1841
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1842
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1843
1
    offset += 4;
1844
1845
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_setattr_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1846
1
    dissect_9P_setattrflags(tvb, ti, offset);
1847
1
    offset += 4;
1848
1849
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1850
1
    dissect_9P_dm(tvb, ti, offset, 0);
1851
1
    offset += 4;
1852
1853
1
    proto_tree_add_item(ninep_tree, hf_9P_uid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1854
1
    offset += 4;
1855
1856
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1857
1
    offset += 4;
1858
1859
1
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1860
1
    offset += 8;
1861
1862
1
    proto_tree_add_item(ninep_tree, hf_9P_atime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1863
1
    offset += 16;
1864
1865
1
    proto_tree_add_item(ninep_tree, hf_9P_mtime, tvb, offset, 16, ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN);
1866
1
    offset += 16;
1867
1868
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1869
1
    break;
1870
1871
1
  case _9P_RSTATFS:
1872
1
    proto_tree_add_item(ninep_tree, hf_9P_fstype, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1873
1
    offset += 4;
1874
1875
1
    proto_tree_add_item(ninep_tree, hf_9P_blksize, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1876
1
    offset += 4;
1877
1878
1
    proto_tree_add_item(ninep_tree, hf_9P_blocks, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1879
1
    offset += 8;
1880
1881
1
    proto_tree_add_item(ninep_tree, hf_9P_bfree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1882
1
    offset += 8;
1883
1884
1
    proto_tree_add_item(ninep_tree, hf_9P_bavail, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1885
1
    offset += 8;
1886
1887
1
    proto_tree_add_item(ninep_tree, hf_9P_files, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1888
1
    offset += 8;
1889
1890
1
    proto_tree_add_item(ninep_tree, hf_9P_ffree, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1891
1
    offset += 8;
1892
1893
1
    proto_tree_add_item(ninep_tree, hf_9P_fsid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1894
1
    offset += 8;
1895
1896
1
    proto_tree_add_item(ninep_tree, hf_9P_namelen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1897
1
    offset += 4;
1898
1899
1
    conv_free_tag(pinfo, tag);
1900
1
    break;
1901
1902
1
  case _9P_TSYMLINK:
1903
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1904
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1905
1
    offset += 4;
1906
1907
    /* name */
1908
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1909
    /* XXX: maybe use a new field for symtgt? */
1910
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1911
1912
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1913
1
    offset += 4;
1914
1915
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1916
1
    break;
1917
1918
0
  case _9P_TMKNOD:
1919
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1920
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1921
0
    offset += 4;
1922
1923
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1924
1925
0
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1926
0
    dissect_9P_dm(tvb, ti, offset, 0);
1927
0
    offset += 4;
1928
1929
0
    proto_tree_add_item(ninep_tree, hf_9P_mknod_major, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1930
0
    offset += 4;
1931
1932
0
    proto_tree_add_item(ninep_tree, hf_9P_mknod_minor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1933
0
    offset += 4;
1934
1935
0
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1936
0
    offset += 4;
1937
1938
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1939
0
    break;
1940
1941
3
  case _9P_TRENAME:
1942
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1943
3
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1944
3
    offset += 4;
1945
1946
3
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &dfid);
1947
3
    fid_path = conv_get_fid(pinfo, dfid);
1948
3
    proto_item_append_text(ti, " (%s)", fid_path);
1949
3
    offset += 4;
1950
1951
3
    if (!pinfo->fd->visited) {
1952
3
      _9p_len = tvb_get_letohs(tvb, offset);
1953
3
      tmppath = wmem_strbuf_create(pinfo->pool);
1954
3
      wmem_strbuf_append(tmppath, conv_get_fid(pinfo, dfid));
1955
3
      wmem_strbuf_append_c(tmppath, '/');
1956
1957
3
      tvb_s = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset+2, _9p_len, ENC_UTF_8|ENC_NA);
1958
3
      wmem_strbuf_append(tmppath, tvb_s);
1959
1960
3
      conv_set_fid(pinfo, fid, wmem_strbuf_get_str(tmppath), wmem_strbuf_get_len(tmppath)+1);
1961
3
    }
1962
3
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1963
1964
3
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1965
3
    break;
1966
1967
0
  case _9P_RREADLINK:
1968
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1969
1970
0
    conv_free_tag(pinfo, tag);
1971
0
    break;
1972
1973
1
  case _9P_TXATTRWALK:
1974
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1975
1
    fid_path = conv_get_fid(pinfo, fid);
1976
1
    proto_item_append_text(ti, " (%s)", fid_path);
1977
1
    offset += 4;
1978
1979
1
    proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &newfid);
1980
1
    conv_set_fid_nocopy(pinfo, newfid, fid_path);
1981
1
    offset += 4;
1982
1983
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
1984
1985
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
1986
1
    break;
1987
1988
0
  case _9P_RXATTRWALK:
1989
0
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1990
0
    offset += 8;
1991
1992
0
    conv_free_tag(pinfo, tag);
1993
0
    break;
1994
1995
9
  case _9P_TXATTRCREATE:
1996
9
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
1997
9
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
1998
9
    offset += 4;
1999
2000
9
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2001
2002
9
    proto_tree_add_item(ninep_tree, hf_9P_size, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2003
9
    offset += 8;
2004
2005
9
    proto_tree_add_item(ninep_tree, hf_9P_xattr_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2006
9
    offset += 4;
2007
2008
9
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2009
9
    break;
2010
2011
1
  case _9P_TLOCK:
2012
2
  case _9P_TGETLOCK:
2013
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2014
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2015
2
    offset += 4;
2016
2017
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2018
2
    offset += 1;
2019
2020
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2021
2
    offset += 4;
2022
2023
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2024
2
    offset += 8;
2025
2026
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2027
2
    offset += 8;
2028
2029
2
    proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2030
2
    offset += 4;
2031
2032
2
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2033
2034
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2035
2
    break;
2036
2037
1
  case _9P_RLOCK:
2038
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2039
1
    offset += 1;
2040
2041
1
    conv_free_tag(pinfo, tag);
2042
1
    break;
2043
2044
1
  case _9P_RGETLOCK:
2045
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2046
1
    offset += 1;
2047
2048
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_flag, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2049
1
    offset += 4;
2050
2051
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_start, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2052
1
    offset += 8;
2053
2054
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
2055
1
    offset += 8;
2056
2057
1
    proto_tree_add_item(ninep_tree, hf_9P_lock_procid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2058
1
    offset += 4;
2059
2060
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2061
2062
1
    conv_free_tag(pinfo, tag);
2063
1
    break;
2064
2065
0
  case _9P_TLINK:
2066
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2067
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2068
0
    offset += 4;
2069
2070
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2071
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2072
0
    offset += 4;
2073
2074
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2075
2076
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2077
0
    break;
2078
2079
1
  case _9P_TMKDIR:
2080
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2081
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2082
1
    offset += 4;
2083
2084
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2085
2086
1
    ti = proto_tree_add_item(ninep_tree, hf_9P_statmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2087
1
    dissect_9P_dm(tvb, ti, offset, 0);
2088
1
    offset += 4;
2089
2090
1
    proto_tree_add_item(ninep_tree, hf_9P_gid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2091
1
    offset += 4;
2092
2093
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2094
1
    break;
2095
2096
1
  case _9P_TRENAMEAT:
2097
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2098
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2099
1
    offset += 4;
2100
2101
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2102
2103
1
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_newfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2104
1
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2105
1
    offset += 4;
2106
2107
1
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2108
2109
1
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2110
1
    break;
2111
2112
0
  case _9P_TUNLINKAT:
2113
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_dfid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2114
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2115
0
    offset += 4;
2116
2117
0
    offset += _9p_dissect_string(tvb, ninep_tree, offset, hf_9P_wname, ett_9P_wname);
2118
2119
0
    proto_tree_add_item(ninep_tree, hf_9P_unlinkat_flags, tvb,
2120
0
        offset, 4, ENC_LITTLE_ENDIAN);
2121
0
    offset += 4;
2122
2123
0
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2124
0
    break;
2125
2126
0
  case _9P_TREMOVE:
2127
0
  case _9P_TCLUNK:
2128
0
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2129
0
    offset += 4;
2130
0
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2131
0
    conv_free_fid(pinfo, fid);
2132
2133
0
    conv_set_tag(pinfo, tag, ninemsg, fid, NULL);
2134
0
    break;
2135
2136
  /* Request with only fid */
2137
1
  case _9P_TSTATFS:
2138
1
  case _9P_TREADLINK:
2139
2
  case _9P_TFSYNC:
2140
2
  case _9P_TSTAT:
2141
2
    fid = tvb_get_letohl(tvb, offset);
2142
2
    ti = proto_tree_add_item_ret_uint(ninep_tree, hf_9P_fid, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fid);
2143
2
    offset += 4;
2144
2
    proto_item_append_text(ti, " (%s)", conv_get_fid(pinfo, fid));
2145
2146
2
    conv_set_tag(pinfo, tag, ninemsg, _9P_NOFID, NULL);
2147
2
    break;
2148
2149
  /* Reply with qid and ionuit */
2150
0
  case _9P_RCREATE:
2151
0
  case _9P_RLCREATE:
2152
0
    dissect_9P_qid(tvb, ninep_tree, offset);
2153
0
    offset += 13;
2154
0
    proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2155
0
    offset += 4;
2156
2157
0
    taginfo = conv_get_tag(pinfo, tag);
2158
0
    if (taginfo && taginfo->fid_path) {
2159
0
      conv_set_fid_nocopy(pinfo, taginfo->fid, taginfo->fid_path);
2160
0
    }
2161
2162
0
    conv_free_tag(pinfo, tag);
2163
0
    break;
2164
2165
1
  case _9P_ROPEN:
2166
1
  case _9P_RLOPEN:
2167
1
    dissect_9P_qid(tvb, ninep_tree, offset);
2168
1
    offset += 13;
2169
1
    proto_tree_add_item(ninep_tree, hf_9P_iounit, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2170
1
    offset += 4;
2171
2172
1
    conv_free_tag(pinfo, tag);
2173
1
    break;
2174
2175
  /* Reply with only qid */
2176
0
  case _9P_RSYMLINK:
2177
1
  case _9P_RMKNOD:
2178
2
  case _9P_RMKDIR:
2179
3
  case _9P_RAUTH:
2180
5
  case _9P_RATTACH:
2181
5
    dissect_9P_qid(tvb, ninep_tree, offset);
2182
5
    offset += 13;
2183
2184
5
    conv_free_tag(pinfo, tag);
2185
5
    break;
2186
2187
  /* Empty reply */
2188
0
  case _9P_RRENAME:
2189
1
  case _9P_RSETATTR:
2190
2
  case _9P_RXATTRCREATE:
2191
2
  case _9P_RFSYNC:
2192
8
  case _9P_RLINK:
2193
8
  case _9P_RRENAMEAT:
2194
9
  case _9P_RUNLINKAT:
2195
10
  case _9P_RFLUSH:
2196
10
  case _9P_RCLUNK:
2197
11
  case _9P_RREMOVE:
2198
  /* Unhandled reply */
2199
13
  case _9P_RWSTAT:
2200
13
  case _9P_RLERROR:
2201
13
    conv_free_tag(pinfo, tag);
2202
13
    break;
2203
2204
  /* Should-not-happen query */
2205
1
  case _9P_TLERROR:
2206
1
  case _9P_TERROR:
2207
1
  default:
2208
1
    expert_add_info(pinfo, msg_item, &ei_9P_msgtype);
2209
1
    break;
2210
65
  }
2211
2212
  /* Show any extra data at the end of the message (but only
2213
     if it was captured) */
2214
41
  if (offset != tvb_captured_length(tvb))
2215
41
    proto_tree_add_item(ninep_tree, hf_9P_unknown_message, tvb, offset, -1, ENC_NA);
2216
41
  return tvb_captured_length(tvb);
2217
65
}
2218
2219
static unsigned get_9P_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
2220
                                int offset, void *data _U_)
2221
77
{
2222
77
  return (unsigned) tvb_get_letohl(tvb, offset);
2223
77
}
2224
2225
static int dissect_9P(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2226
51
{
2227
51
  tcp_dissect_pdus(tvb, pinfo, tree, true, 4,
2228
51
      get_9P_message_len, dissect_9P_message, data);
2229
51
  return tvb_captured_length(tvb);
2230
51
}
2231
2232
/* dissect 9P Qid */
2233
static void dissect_9P_qid(tvbuff_t *tvb,  proto_tree *tree, unsigned offset)
2234
48
{
2235
48
  proto_item *qidtype_item;
2236
48
  proto_tree *qid_tree,*qidtype_tree;
2237
48
  uint64_t path;
2238
48
  uint32_t vers;
2239
48
  uint8_t type;
2240
2241
48
  if(!tree)
2242
0
    return;
2243
2244
48
  type = tvb_get_uint8(tvb, offset);
2245
48
  vers = tvb_get_letohs(tvb, offset+1);
2246
48
  path = tvb_get_letoh64(tvb, offset+1+4);
2247
2248
48
  qid_tree = proto_tree_add_subtree_format(tree, tvb, offset, 13, ett_9P_qid, NULL,
2249
48
        "Qid type=0x%02x vers=%d path=%" PRIu64, type, vers, path);
2250
2251
48
  qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, ENC_LITTLE_ENDIAN);
2252
48
  qidtype_tree = proto_item_add_subtree(qidtype_item, ett_9P_qidtype);
2253
2254
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_dir,       tvb, offset,     1, ENC_LITTLE_ENDIAN);
2255
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_append,    tvb, offset,     1, ENC_LITTLE_ENDIAN);
2256
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_exclusive, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2257
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_mount,     tvb, offset,     1, ENC_LITTLE_ENDIAN);
2258
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_auth_file, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2259
48
  proto_tree_add_item(qidtype_tree, hf_9P_qidtype_temp_file, tvb, offset,     1, ENC_LITTLE_ENDIAN);
2260
2261
48
  proto_tree_add_item(qid_tree, hf_9P_qidvers,               tvb, offset+1,   4, ENC_LITTLE_ENDIAN);
2262
48
  proto_tree_add_item(qid_tree, hf_9P_qidpath,               tvb, offset+1+4, 8, ENC_LITTLE_ENDIAN);
2263
48
}
2264
2265
/*dissect 9P stat mode and create perm flags */
2266
static void dissect_9P_dm(tvbuff_t *tvb,  proto_item *item, unsigned offset, int iscreate)
2267
2
{
2268
2
  proto_item *mode_tree;
2269
2270
2271
2
  mode_tree = proto_item_add_subtree(item, ett_9P_dm);
2272
2
  if(!mode_tree)
2273
0
    return;
2274
2275
2
  proto_tree_add_item(mode_tree, hf_9P_dm_dir, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2276
2
  if(!iscreate) { /* Not applicable to Tcreate (?) */
2277
1
    proto_tree_add_item(mode_tree, hf_9P_dm_append,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2278
1
    proto_tree_add_item(mode_tree, hf_9P_dm_exclusive, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2279
1
    proto_tree_add_item(mode_tree, hf_9P_dm_mount,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2280
1
    proto_tree_add_item(mode_tree, hf_9P_dm_auth_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2281
1
    proto_tree_add_item(mode_tree, hf_9P_dm_temp_file, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2282
1
  }
2283
2284
2
  proto_tree_add_item(mode_tree, hf_9P_dm_read_owner,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2285
2
  proto_tree_add_item(mode_tree, hf_9P_dm_write_owner,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2286
2
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_owner,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2287
2
  proto_tree_add_item(mode_tree, hf_9P_dm_read_group,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2288
2
  proto_tree_add_item(mode_tree, hf_9P_dm_write_group,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2289
2
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_group,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2290
2
  proto_tree_add_item(mode_tree, hf_9P_dm_read_others,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2291
2
  proto_tree_add_item(mode_tree, hf_9P_dm_write_others, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2292
2
  proto_tree_add_item(mode_tree, hf_9P_dm_exec_others,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2293
2
}
2294
2295
/* Dissect 9P getattr_flags */
2296
static void dissect_9P_getattrflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2297
0
{
2298
0
  proto_item *attrmask_tree;
2299
2300
0
  attrmask_tree = proto_item_add_subtree(item, ett_9P_getattr_flags);
2301
0
  if(!attrmask_tree)
2302
0
    return;
2303
2304
  /* fixme: This is actually 8 bytes (64bit) long, but masks have to fit on 32bit. */
2305
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_mode,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2306
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_nlink,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2307
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_uid,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2308
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_gid,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2309
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_rdev,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2310
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_atime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2311
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_mtime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2312
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_ctime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2313
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_ino,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2314
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_size,        tvb, offset, 4, ENC_LITTLE_ENDIAN);
2315
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_blocks,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2316
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_btime,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2317
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_gen,         tvb, offset, 4, ENC_LITTLE_ENDIAN);
2318
0
  proto_tree_add_item(attrmask_tree, hf_9P_getattr_dataversion, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2319
0
}
2320
2321
/* Dissect 9P setattr_flags */
2322
static void dissect_9P_setattrflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2323
1
{
2324
1
  proto_item *attrmask_tree;
2325
2326
1
  attrmask_tree = proto_item_add_subtree(item, ett_9P_setattr_flags);
2327
1
  if(!attrmask_tree)
2328
0
    return;
2329
2330
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mode,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2331
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_uid,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2332
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_gid,       tvb, offset, 4, ENC_LITTLE_ENDIAN);
2333
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_size,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2334
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2335
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2336
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_ctime,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2337
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_atime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2338
1
  proto_tree_add_item(attrmask_tree, hf_9P_setattr_mtime_set, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2339
1
}
2340
2341
/* Dissect 9P lflags */
2342
static void dissect_9P_lflags(tvbuff_t *tvb, proto_item *item, unsigned offset)
2343
1
{
2344
1
  proto_item *attrmask_tree;
2345
2346
1
  attrmask_tree = proto_item_add_subtree(item, ett_9P_lflags);
2347
1
  if(!attrmask_tree)
2348
0
    return;
2349
2350
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdonly,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2351
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_wronly,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2352
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_rdwr,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2353
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_create,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2354
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_excl,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2355
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_noctty,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2356
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_trunc,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2357
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_append,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2358
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_nonblock,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2359
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_dsync,     tvb, offset, 4, ENC_LITTLE_ENDIAN);
2360
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_fasync,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2361
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_direct,    tvb, offset, 4, ENC_LITTLE_ENDIAN);
2362
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_largefile, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2363
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_directory, tvb, offset, 4, ENC_LITTLE_ENDIAN);
2364
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_nofollow,  tvb, offset, 4, ENC_LITTLE_ENDIAN);
2365
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_noatime,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2366
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_cloexec,   tvb, offset, 4, ENC_LITTLE_ENDIAN);
2367
1
  proto_tree_add_item(attrmask_tree, hf_9P_lflags_sync,      tvb, offset, 4, ENC_LITTLE_ENDIAN);
2368
1
}
2369
2370
2371
/* Register 9P with Wireshark */
2372
void proto_register_9P(void)
2373
16
{
2374
16
  static hf_register_info hf[] = {
2375
16
    {&hf_9P_msgsz,
2376
16
     {"Msg length", "9p.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
2377
16
      "9P Message Length", HFILL}},
2378
16
    {&hf_9P_msgtype,
2379
16
     {"Msg Type", "9p.msgtype", FT_UINT8, BASE_DEC | BASE_EXT_STRING, &ninep_msg_type_ext, 0x0,
2380
16
      "Message Type", HFILL}},
2381
16
    {&hf_9P_tag,
2382
16
     {"Tag", "9p.tag", FT_UINT16, BASE_DEC, NULL, 0x0,
2383
16
      "9P Tag", HFILL}},
2384
16
    {&hf_9P_oldtag,
2385
16
     {"Old tag", "9p.oldtag", FT_UINT16, BASE_DEC, NULL, 0x0,
2386
16
      NULL, HFILL}},
2387
16
    {&hf_9P_parmsz,
2388
16
     {"Param length", "9p.paramsz", FT_UINT16, BASE_DEC, NULL, 0x0,
2389
16
      "Parameter length", HFILL}},
2390
16
    {&hf_9P_maxsize,
2391
16
     {"Max msg size", "9p.maxsize", FT_UINT32, BASE_DEC, NULL, 0x0,
2392
16
      "Max message size", HFILL}},
2393
16
    {&hf_9P_fid,
2394
16
     {"Fid", "9p.fid", FT_UINT32, BASE_DEC, NULL, 0x0,
2395
16
      "File ID", HFILL}},
2396
16
    {&hf_9P_nqid,
2397
16
     {"Nr Qids", "9p.nqid", FT_UINT16, BASE_DEC, NULL, 0x0,
2398
16
      "Number of Qid results", HFILL}},
2399
16
    {&hf_9P_mode,
2400
16
     {"Mode", "9p.mode", FT_UINT8, BASE_HEX, NULL, 0x0,
2401
16
      NULL, HFILL}},
2402
16
    {&hf_9P_mode_rwx,
2403
16
     {"Open/Create Mode", "9p.mode.rwx", FT_UINT8, BASE_OCT | BASE_EXT_STRING, &ninep_mode_vals_ext, _9P_MODEMASK,
2404
16
      NULL, HFILL}},
2405
16
    {&hf_9P_mode_t,
2406
16
     {"Trunc", "9p.mode.trunc", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_OTRUNC,
2407
16
      "Truncate", HFILL}},
2408
16
    {&hf_9P_mode_c,
2409
16
     {"Remove on close", "9p.mode.orclose", FT_BOOLEAN, 8, TFS(&tfs_set_notset), _9P_ORCLOSE,
2410
16
      NULL, HFILL}},
2411
16
    {&hf_9P_extension,
2412
16
     {"Extension string", "9p.extension", FT_STRING, BASE_NONE, NULL, 0x0,
2413
16
      "Link target for DSYMLINK mode, major+minor for DMDEVICE, empty for normal files", HFILL}},
2414
16
    {&hf_9P_iounit,
2415
16
     {"I/O Unit", "9p.iounit", FT_UINT32, BASE_DEC, NULL, 0x0,
2416
16
      NULL, HFILL}},
2417
16
    {&hf_9P_count,
2418
16
     {"Count", "9p.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2419
16
      NULL, HFILL}},
2420
16
    {&hf_9P_offset,
2421
16
     {"Offset", "9p.offset", FT_UINT64, BASE_DEC, NULL, 0x0,
2422
16
      NULL, HFILL}},
2423
16
    {&hf_9P_perm,
2424
16
     {"Permissions", "9p.perm", FT_UINT32, BASE_OCT, NULL, 0x0,
2425
16
      "Permission bits", HFILL}},
2426
16
    {&hf_9P_qidpath,
2427
16
     {"Qid path", "9p.qidpath", FT_UINT64, BASE_DEC, NULL, 0x0,
2428
16
      NULL, HFILL}},
2429
16
    {&hf_9P_dm_dir,
2430
16
     {"Directory", "9p.dm.dir", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x80000000,
2431
16
      NULL, HFILL}},
2432
16
    {&hf_9P_dm_append,
2433
16
     {"Append only", "9p.dm.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x40000000,
2434
16
      NULL, HFILL}},
2435
16
    {&hf_9P_dm_exclusive,
2436
16
     {"Exclusive use", "9p.dm.exclusive", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x20000000,
2437
16
      NULL, HFILL}},
2438
16
    {&hf_9P_dm_mount,
2439
16
     {"Mounted channel", "9p.dm.mount", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x10000000,
2440
16
      NULL, HFILL}},
2441
16
    {&hf_9P_dm_auth_file,
2442
16
     {"Authentication file", "9p.dm.auth_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x08000000,
2443
16
      NULL, HFILL}},
2444
16
    {&hf_9P_dm_temp_file,
2445
16
     {"Temporary file (not backed up)", "9p.dm.temp_file", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x04000000,
2446
16
      NULL, HFILL}},
2447
16
    {&hf_9P_dm_read_owner,
2448
16
     {"Read permission for owner", "9p.dm.read_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000100,
2449
16
      NULL, HFILL}},
2450
16
    {&hf_9P_dm_write_owner,
2451
16
     {"Write permission for owner", "9p.dm.write_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000080,
2452
16
      NULL, HFILL}},
2453
16
    {&hf_9P_dm_exec_owner,
2454
16
     {"Execute permission for owner", "9p.dm.exec_owner", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000040,
2455
16
      NULL, HFILL}},
2456
16
    {&hf_9P_dm_read_group,
2457
16
     {"Read permission for group", "9p.dm.read_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000020,
2458
16
      NULL, HFILL}},
2459
16
    {&hf_9P_dm_write_group,
2460
16
     {"Write permission for group", "9p.dm.write_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000010,
2461
16
      NULL, HFILL}},
2462
16
    {&hf_9P_dm_exec_group,
2463
16
     {"Execute permission for group", "9p.dm.exec_group", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000008,
2464
16
      NULL, HFILL}},
2465
16
    {&hf_9P_dm_read_others,
2466
16
     {"Read permission for others", "9p.dm.read_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000004,
2467
16
      NULL, HFILL}},
2468
16
    {&hf_9P_dm_write_others,
2469
16
     {"Write permission for others", "9p.dm.write_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000002,
2470
16
      NULL, HFILL}},
2471
16
    {&hf_9P_dm_exec_others,
2472
16
     {"Execute permission for others", "9p.dm.exec_others", FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x00000001,
2473
16
      NULL, HFILL}},
2474
16
    {&hf_9P_qidvers,
2475
16
     {"Qid version", "9p.qidvers", FT_UINT32, BASE_DEC, NULL, 0x0,
2476
16
      NULL, HFILL}},
2477
16
    {&hf_9P_qidtype,
2478
16
     {"Qid type", "9p.qidtype", FT_UINT8, BASE_HEX, NULL, 0x0,
2479
16
      NULL, HFILL}},
2480
16
    {&hf_9P_qidtype_dir,
2481
16
     {"Directory", "9p.qidtype.dir", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
2482
16
      NULL, HFILL}},
2483
16
    {&hf_9P_qidtype_append,
2484
16
     {"Append only", "9p.qidtype.append", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
2485
16
      NULL, HFILL}},
2486
16
    {&hf_9P_qidtype_exclusive,
2487
16
     {"Exclusive use", "9p.qidtype.exclusive", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
2488
16
      NULL, HFILL}},
2489
16
    {&hf_9P_qidtype_mount,
2490
16
     {"Mounted channel", "9p.qidtype.mount", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
2491
16
      NULL, HFILL}},
2492
16
    {&hf_9P_qidtype_auth_file,
2493
16
     {"Authentication file", "9p.qidtype.auth_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
2494
16
      NULL, HFILL}},
2495
16
    {&hf_9P_qidtype_temp_file,
2496
16
     {"Temporary file (not backed up)", "9p.qidtype.temp_file", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
2497
16
      NULL, HFILL}},
2498
16
    {&hf_9P_statmode,
2499
16
     {"Mode", "9p.statmode", FT_UINT32, BASE_OCT, NULL, 0x0,
2500
16
      "File mode flags", HFILL}},
2501
16
    {&hf_9P_stattype,
2502
16
     {"Type", "9p.stattype", FT_UINT16, BASE_DEC, NULL, 0x0,
2503
16
      NULL, HFILL}},
2504
16
    {&hf_9P_atime,
2505
16
     {"Atime", "9p.atime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2506
16
      "Access Time", HFILL}},
2507
16
    {&hf_9P_mtime,
2508
16
     {"Mtime", "9p.mtime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2509
16
      "Modified Time", HFILL}},
2510
16
    {&hf_9P_ctime,
2511
16
     {"Ctime", "9p.ctime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2512
16
      "Creation Time", HFILL}},
2513
16
    {&hf_9P_btime,
2514
16
     {"Btime", "9p.btime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
2515
16
      "Btime (Synchronization information)", HFILL}},
2516
16
    {&hf_9P_length,
2517
16
     {"Length", "9p.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2518
16
      "File Length", HFILL}},
2519
16
    {&hf_9P_dev,
2520
16
     {"Dev", "9p.dev", FT_UINT32, BASE_DEC, NULL, 0x0,
2521
16
      NULL, HFILL}},
2522
16
    {&hf_9P_wname,
2523
16
     {"Wname", "9p.wname", FT_STRING, BASE_NONE, NULL, 0x0,
2524
16
      "Path Name Element", HFILL}},
2525
16
    {&hf_9P_version,
2526
16
     {"Version", "9p.version", FT_STRING, BASE_NONE, NULL, 0x0,
2527
16
      NULL, HFILL}},
2528
16
    {&hf_9P_afid,
2529
16
     {"Afid", "9p.afid", FT_UINT32, BASE_DEC, NULL, 0x0,
2530
16
      "Authenticating FID", HFILL}},
2531
16
    {&hf_9P_uname,
2532
16
     {"Uname", "9p.uname", FT_STRING, BASE_NONE, NULL, 0x0,
2533
16
      "User Name", HFILL}},
2534
16
    {&hf_9P_aname,
2535
16
     {"Aname", "9p.aname", FT_STRING, BASE_NONE, NULL, 0x0,
2536
16
      "Access Name", HFILL}},
2537
16
    {&hf_9P_ename,
2538
16
     {"Ename", "9p.ename", FT_STRING, BASE_NONE, NULL, 0x0,
2539
16
      "Error", HFILL}},
2540
16
    {&hf_9P_enum,
2541
16
     {"Enum", "9p.enum", FT_UINT32, BASE_DEC, NULL, 0x0,
2542
16
      "Error", HFILL}},
2543
#if 0
2544
    {&hf_9P_name,
2545
     {"Name", "9p.name", FT_STRING, BASE_NONE, NULL, 0x0,
2546
      "Name of file", HFILL}},
2547
#endif
2548
16
    {&hf_9P_sdlen,
2549
16
     {"Stat data length", "9p.sdlen", FT_UINT16, BASE_DEC, NULL, 0x0,
2550
16
      NULL, HFILL}},
2551
16
    {&hf_9P_filename,
2552
16
     {"File name", "9p.filename", FT_STRING, BASE_NONE, NULL, 0x0,
2553
16
      NULL, HFILL}},
2554
16
    {&hf_9P_user,
2555
16
     {"User", "9p.user", FT_STRING, BASE_NONE, NULL, 0x0,
2556
16
      "User name", HFILL}},
2557
16
    {&hf_9P_group,
2558
16
     {"Group", "9p.group", FT_STRING, BASE_NONE, NULL, 0x0,
2559
16
      "Group name", HFILL}},
2560
16
    {&hf_9P_uid,
2561
16
     {"Uid", "9p.uid", FT_UINT32, BASE_DEC, NULL, 0x0,
2562
16
      "User id", HFILL}},
2563
16
    {&hf_9P_gid,
2564
16
     {"Gid", "9p.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
2565
16
      "Group id", HFILL}},
2566
16
    {&hf_9P_muid,
2567
16
     {"Muid", "9p.muid", FT_STRING, BASE_NONE, NULL, 0x0,
2568
16
      "Last modifiers uid", HFILL}},
2569
16
    {&hf_9P_newfid,
2570
16
     {"New fid", "9p.newfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2571
16
      "New file ID", HFILL}},
2572
16
    {&hf_9P_dfid,
2573
16
     {"Directory fid", "9p.dfid", FT_UINT32, BASE_DEC, NULL, 0x0,
2574
16
      "Directory ID", HFILL}},
2575
16
    {&hf_9P_nwalk,
2576
16
     {"Nr Walks", "9p.nwalk", FT_UINT16, BASE_DEC, NULL, 0x0,
2577
16
      "Nr of walk items", HFILL}},
2578
16
    {&hf_9P_nlink,
2579
16
     {"nlink", "9p.nlink", FT_UINT64, BASE_DEC, NULL, 0x0,
2580
16
      "Number of links", HFILL}},
2581
16
    {&hf_9P_getattr_flags,
2582
16
     {"getattr_flags", "9p.getattr.flags", FT_UINT64, BASE_HEX, NULL, _9P_GETATTR_ALL,
2583
16
      "Getattr flags", HFILL}},
2584
16
    {&hf_9P_getattr_mode,
2585
16
     {"Mode", "9p.getattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MODE,
2586
16
      NULL, HFILL}},
2587
16
    {&hf_9P_getattr_nlink,
2588
16
     {"Nlink", "9p.getattr.nlink", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_NLINK,
2589
16
      NULL, HFILL}},
2590
16
    {&hf_9P_getattr_uid,
2591
16
     {"UID", "9p.getattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_UID,
2592
16
      NULL, HFILL}},
2593
16
    {&hf_9P_getattr_gid,
2594
16
     {"GID", "9p.getattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GID,
2595
16
      NULL, HFILL}},
2596
16
    {&hf_9P_getattr_rdev,
2597
16
     {"Rdev", "9p.getattr.rdev", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_RDEV,
2598
16
      NULL, HFILL}},
2599
16
    {&hf_9P_getattr_atime,
2600
16
     {"Atime", "9p.getattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_ATIME,
2601
16
      NULL, HFILL}},
2602
16
    {&hf_9P_getattr_mtime,
2603
16
     {"Mtime", "9p.getattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_MTIME,
2604
16
      NULL, HFILL}},
2605
16
    {&hf_9P_getattr_ctime,
2606
16
     {"Ctime", "9p.getattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_CTIME,
2607
16
      NULL, HFILL}},
2608
16
    {&hf_9P_getattr_ino,
2609
16
     {"Inode", "9p.getattr.inode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_INO,
2610
16
      NULL, HFILL}},
2611
16
    {&hf_9P_getattr_size,
2612
16
     {"Size", "9p.getattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_SIZE,
2613
16
      NULL, HFILL}},
2614
16
    {&hf_9P_getattr_blocks,
2615
16
     {"Blocks", "9p.getattr.blocks", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BLOCKS,
2616
16
      NULL, HFILL}},
2617
16
    {&hf_9P_getattr_btime,
2618
16
     {"Btime", "9p.getattr.btime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_BTIME,
2619
16
      NULL, HFILL}},
2620
16
    {&hf_9P_getattr_gen,
2621
16
     {"Gen", "9p.getattr.gen", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_GEN,
2622
16
      NULL, HFILL}},
2623
16
    {&hf_9P_getattr_dataversion,
2624
16
     {"Data version", "9p.getattr.dataversion", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_GETATTR_DATA_VERSION,
2625
16
      NULL, HFILL}},
2626
16
    {&hf_9P_setattr_flags,
2627
16
     {"setattr_flags", "9p.setattr.flags", FT_UINT32, BASE_HEX, NULL, _9P_SETATTR_ALL,
2628
16
      "Setattr flags", HFILL}},
2629
16
    {&hf_9P_setattr_mode,
2630
16
     {"Mode", "9p.setattr.mode", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MODE,
2631
16
      NULL, HFILL}},
2632
16
    {&hf_9P_setattr_uid,
2633
16
     {"UID", "9p.setattr.uid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_UID,
2634
16
      NULL, HFILL}},
2635
16
    {&hf_9P_setattr_gid,
2636
16
     {"GID", "9p.setattr.gid", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_GID,
2637
16
      NULL, HFILL}},
2638
16
    {&hf_9P_setattr_size,
2639
16
     {"Size", "9p.setattr.size", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_SIZE,
2640
16
      NULL, HFILL}},
2641
16
    {&hf_9P_setattr_atime,
2642
16
     {"Atime", "9p.setattr.atime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME,
2643
16
      NULL, HFILL}},
2644
16
    {&hf_9P_setattr_mtime,
2645
16
     {"Mtime", "9p.setattr.mtime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME,
2646
16
      NULL, HFILL}},
2647
16
    {&hf_9P_setattr_ctime,
2648
16
     {"Ctime", "9p.setattr.ctime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_CTIME,
2649
16
      NULL, HFILL}},
2650
16
    {&hf_9P_setattr_atime_set,
2651
16
     {"Atime set", "9p.setattr.atimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_ATIME_SET,
2652
16
      NULL, HFILL}},
2653
16
    {&hf_9P_setattr_mtime_set,
2654
16
     {"Mtime set", "9p.setattr.mtimeset", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_SETATTR_MTIME_SET,
2655
16
      NULL, HFILL}},
2656
16
    {&hf_9P_unlinkat_flags,
2657
16
     {"unlinkat flags", "9p.unlinkat.flags", FT_UINT32, BASE_HEX, NULL, 0,
2658
16
      NULL, HFILL}},
2659
16
    {&hf_9P_rdev,
2660
16
     {"rdev", "9p.rdev", FT_UINT64, BASE_DEC, NULL, 0x0,
2661
16
      "Device associated with file", HFILL}},
2662
16
    {&hf_9P_size,
2663
16
     {"Size", "9p.size", FT_UINT64, BASE_DEC, NULL, 0x0,
2664
16
      NULL, HFILL}},
2665
16
    {&hf_9P_blksize,
2666
16
     {"Blksize", "9p.blksize", FT_UINT64, BASE_DEC, NULL, 0x0,
2667
16
      "Block size", HFILL}},
2668
16
    {&hf_9P_blocks,
2669
16
     {"Blocks", "9p.blocks", FT_UINT64, BASE_DEC, NULL, 0x0,
2670
16
      NULL, HFILL}},
2671
16
    {&hf_9P_gen,
2672
16
     {"Gen", "9p.gen", FT_UINT64, BASE_DEC, NULL, 0x0,
2673
16
      "inode generation number", HFILL}},
2674
16
    {&hf_9P_dataversion,
2675
16
     {"Dataversion", "9p.dataversion", FT_UINT64, BASE_DEC, NULL, 0x0,
2676
16
      "Data version", HFILL}},
2677
16
    {&hf_9P_fstype,
2678
16
     {"fstype", "9p.fstype", FT_UINT32, BASE_HEX, NULL, 0x0,
2679
16
      "Filesystem type", HFILL}},
2680
16
    {&hf_9P_bfree,
2681
16
     {"bfree", "9p.bfree", FT_UINT64, BASE_DEC, NULL, 0x0,
2682
16
      "Free blocks", HFILL}},
2683
16
    {&hf_9P_bavail,
2684
16
     {"bavail", "9p.bavail", FT_UINT64, BASE_DEC, NULL, 0x0,
2685
16
      "Available blocks", HFILL}},
2686
16
    {&hf_9P_files,
2687
16
     {"files", "9p.files", FT_UINT64, BASE_DEC, NULL, 0x0,
2688
16
      "Total files", HFILL}},
2689
16
    {&hf_9P_ffree,
2690
16
     {"ffree", "9p.ffree", FT_UINT64, BASE_DEC, NULL, 0x0,
2691
16
      "Free files", HFILL}},
2692
16
    {&hf_9P_fsid,
2693
16
     {"fsid", "9p.fsid", FT_UINT64, BASE_DEC, NULL, 0x0,
2694
16
      "Filesystem id", HFILL}},
2695
16
    {&hf_9P_namelen,
2696
16
     {"namelen", "9p.namelen", FT_UINT32, BASE_DEC, NULL, 0x0,
2697
16
      "Max name length", HFILL}},
2698
16
    {&hf_9P_mknod_major,
2699
16
     {"mknod_major", "9p.mknod.major", FT_UINT32, BASE_DEC, NULL, 0x0,
2700
16
      "Major node number", HFILL}},
2701
16
    {&hf_9P_mknod_minor,
2702
16
     {"mknod_minor", "9p.mknod.minor", FT_UINT32, BASE_DEC, NULL, 0x0,
2703
16
      "Minor node number", HFILL}},
2704
16
    {&hf_9P_lflags,
2705
16
     {"lflags", "9p.lcreate.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
2706
16
      "Lcreate flags", HFILL}},
2707
    /* rdonly is 0x00, check instead that we are neither wronly nor rdwrite */
2708
16
    {&hf_9P_lflags_rdonly,
2709
16
     {"Read only", "9p.lflags.rdonly", FT_BOOLEAN, 32, TFS(&tfs_no_yes), _9P_DOTL_WRONLY|_9P_DOTL_RDWR,
2710
16
      NULL, HFILL}},
2711
16
    {&hf_9P_lflags_wronly,
2712
16
     {"Write only", "9p.lflags.wronly", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_WRONLY,
2713
16
      NULL, HFILL}},
2714
16
    {&hf_9P_lflags_rdwr,
2715
16
     {"Read Write", "9p.lflags.rdwr", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_RDWR,
2716
16
      NULL, HFILL}},
2717
16
    {&hf_9P_lflags_create,
2718
16
     {"Create", "9p.lflags.create", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CREATE,
2719
16
      NULL, HFILL}},
2720
16
    {&hf_9P_lflags_excl,
2721
16
     {"Exclusive", "9p.lflags.excl", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_EXCL,
2722
16
      NULL, HFILL}},
2723
16
    {&hf_9P_lflags_noctty,
2724
16
     {"noctty", "9p.lflags.noctty", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOCTTY,
2725
16
      NULL, HFILL}},
2726
16
    {&hf_9P_lflags_trunc,
2727
16
     {"Truncate", "9p.lflags.trunc", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_TRUNC,
2728
16
      NULL, HFILL}},
2729
16
    {&hf_9P_lflags_append,
2730
16
     {"Append", "9p.lflags.append", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_APPEND,
2731
16
      NULL, HFILL}},
2732
16
    {&hf_9P_lflags_nonblock,
2733
16
     {"Nonblock", "9p.lflags.nonblock", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NONBLOCK,
2734
16
      NULL, HFILL}},
2735
16
    {&hf_9P_lflags_dsync,
2736
16
     {"dsync", "9p.lflags.dsync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DSYNC,
2737
16
      NULL, HFILL}},
2738
16
    {&hf_9P_lflags_fasync,
2739
16
     {"fasync", "9p.lflags.fasync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_FASYNC,
2740
16
      NULL, HFILL}},
2741
16
    {&hf_9P_lflags_direct,
2742
16
     {"Direct", "9p.lflags.direct", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECT,
2743
16
      NULL, HFILL}},
2744
16
    {&hf_9P_lflags_largefile,
2745
16
     {"Large File", "9p.lflags.largefile", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_LARGEFILE,
2746
16
      NULL, HFILL}},
2747
16
    {&hf_9P_lflags_directory,
2748
16
     {"Directory", "9p.lflags.directory", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_DIRECTORY,
2749
16
      NULL, HFILL}},
2750
16
    {&hf_9P_lflags_nofollow,
2751
16
     {"No follow", "9p.lflags.nofollow", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOFOLLOW,
2752
16
      NULL, HFILL}},
2753
16
    {&hf_9P_lflags_noatime,
2754
16
     {"No atime", "9p.lflags.noatime", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_NOATIME,
2755
16
      NULL, HFILL}},
2756
16
    {&hf_9P_lflags_cloexec,
2757
16
     {"cloexec", "9p.lflags.cloexec", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_CLOEXEC,
2758
16
      NULL, HFILL}},
2759
16
    {&hf_9P_lflags_sync,
2760
16
     {"Sync", "9p.lflags.sync", FT_BOOLEAN, 32, TFS(&tfs_yes_no), _9P_DOTL_SYNC,
2761
16
      NULL, HFILL}},
2762
16
    {&hf_9P_xattr_flag,
2763
16
     {"xattr_flag", "9p.xattr.flag", FT_UINT32, BASE_HEX, NULL, 0x0,
2764
16
      "Xattr flag", HFILL}},
2765
16
    {&hf_9P_lock_type,
2766
16
     {"lock_type", "9p.lock.type", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_type_ext, 0x0,
2767
16
      "Lock type", HFILL}},
2768
16
    {&hf_9P_lock_flag,
2769
16
     {"lock_flag", "9p.lock.flag", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &ninep_lock_flag_ext, 0x0,
2770
16
      "Lock flag", HFILL}},
2771
16
    {&hf_9P_lock_start,
2772
16
     {"lock_start", "9p.lock.start", FT_UINT64, BASE_DEC, NULL, 0x0,
2773
16
      "Lock start", HFILL}},
2774
16
    {&hf_9P_lock_length,
2775
16
     {"lock_length", "9p.lock.length", FT_UINT64, BASE_DEC, NULL, 0x0,
2776
16
      "Lock length", HFILL}},
2777
16
    {&hf_9P_lock_procid,
2778
16
     {"lock_procid", "9p.lock.procid", FT_UINT32, BASE_HEX, NULL, 0x0,
2779
16
      "Lock procid", HFILL}},
2780
16
    {&hf_9P_lock_status,
2781
16
     {"lock_status", "9p.lock.status", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &ninep_lock_status_ext, 0x0,
2782
16
      "Lock status", HFILL}},
2783
16
    {&hf_9P_unknown_message,
2784
16
     {"Message data", "9p.message_data", FT_BYTES, BASE_NONE, NULL, 0x0,
2785
16
      NULL, HFILL}}
2786
16
  };
2787
2788
16
  static int *ett[] = {
2789
16
    &ett_9P,
2790
16
    &ett_9P_omode,
2791
16
    &ett_9P_dm,
2792
16
    &ett_9P_wname,
2793
16
    &ett_9P_aname,
2794
16
    &ett_9P_ename,
2795
16
    &ett_9P_uname,
2796
16
    &ett_9P_user,
2797
16
    &ett_9P_group,
2798
16
    &ett_9P_muid,
2799
16
    &ett_9P_filename,
2800
16
    &ett_9P_version,
2801
16
    &ett_9P_qid,
2802
16
    &ett_9P_qidtype,
2803
16
    &ett_9P_getattr_flags,
2804
16
    &ett_9P_setattr_flags,
2805
16
    &ett_9P_lflags,
2806
16
  };
2807
2808
16
  expert_module_t* expert_9P;
2809
2810
16
  static ei_register_info ei[] = {
2811
16
    { &ei_9P_first_250, { "9p.first_250", PI_PROTOCOL, PI_NOTE, "Only first 250 items shown", EXPFILL }},
2812
16
    { &ei_9P_msgtype, { "9p.msgtype.unknown", PI_PROTOCOL, PI_WARN, "This message type should not happen", EXPFILL }},
2813
16
  };
2814
2815
16
  proto_9P = proto_register_protocol("Plan 9", "9P", "9p");
2816
2817
16
  proto_register_field_array(proto_9P, hf, array_length(hf));
2818
16
  proto_register_subtree_array(ett, array_length(ett));
2819
16
  expert_9P = expert_register_protocol(proto_9P);
2820
16
  expert_register_field_array(expert_9P, ei, array_length(ei));
2821
2822
16
  _9p_hashtable = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), _9p_hash_hash, _9p_hash_equal);
2823
2824
16
  ninep_handle = register_dissector("9p", dissect_9P, proto_9P);
2825
16
}
2826
2827
void proto_reg_handoff_9P(void)
2828
16
{
2829
16
  dissector_add_uint_with_preference("tcp.port", NINEPORT, ninep_handle);
2830
16
}
2831
2832
2833
/*
2834
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2835
 *
2836
 * Local variables:
2837
 * c-basic-offset: 8
2838
 * tab-width: 8
2839
 * indent-tabs-mode: t
2840
 * End:
2841
 *
2842
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2843
 * :indentSize=8:tabSize=8:noTabs=false:
2844
 */