For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-dlm3.c
1 /* packet-dlm3.c
2  * Routines for dlm3 dissection
3  * Copyright 2007, Masatake YAMATO <jet@gyve.org>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25
26 /* This dissector supports version 3.0 of the dlm(Distributed Lock Manager)
27    protocol
28
29    Actual implementation for the protocol is in linux kernel.
30    See files under linux/fs/dlm/ */
31
32 /*
33  * #defines are mostly copied from
34  * *.[ch] files in linux/fs/dlm/ and linux/include/linux/dlm.h
35  *
36  * dlm_internal.h:
37  * -----------------------------------------------------------------------
38  **  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
39  **  Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
40  **
41  **  This copyrighted material is made available to anyone wishing to use,
42  **  modify, copy, or redistribute it subject to the terms and conditions
43  **  of the GNU General Public License v.2.
44  * -----------------------------------------------------------------------
45  */
46
47
48 #ifdef HAVE_CONFIG_H
49 # include "config.h"
50 #endif
51
52 #include <glib.h>
53
54 #include <epan/packet.h>
55 #include <epan/prefs.h>
56
57
58
59 #define TCP_PORT_DLM3           21064
60 #define SCTP_PORT_DLM3          TCP_PORT_DLM3
61
62 #define DLM3_MAJOR_VERSION      0x00030000
63 #define DLM3_MINOR_VERSION      0x00000000
64
65 #define DLM3_MSG                1
66 #define DLM3_RCOM               2
67
68 #define DLM3_MSG_REQUEST        1
69 #define DLM3_MSG_CONVERT        2
70 #define DLM3_MSG_UNLOCK         3
71 #define DLM3_MSG_CANCEL         4
72 #define DLM3_MSG_REQUEST_REPLY  5
73 #define DLM3_MSG_CONVERT_REPLY  6
74 #define DLM3_MSG_UNLOCK_REPLY   7
75 #define DLM3_MSG_CANCEL_REPLY   8
76 #define DLM3_MSG_GRANT          9
77 #define DLM3_MSG_BAST           10
78 #define DLM3_MSG_LOOKUP         11
79 #define DLM3_MSG_REMOVE         12
80 #define DLM3_MSG_LOOKUP_REPLY   13
81 #define DLM3_MSG_PURGE          14
82
83 #define DLM3_LKF_NOQUEUE        0x00000001
84 #define DLM3_LKF_CANCEL         0x00000002
85 #define DLM3_LKF_CONVERT        0x00000004
86 #define DLM3_LKF_VALBLK         0x00000008
87 #define DLM3_LKF_QUECVT         0x00000010
88 #define DLM3_LKF_IVVALBLK       0x00000020
89 #define DLM3_LKF_CONVDEADLK     0x00000040
90 #define DLM3_LKF_PERSISTENT     0x00000080
91 #define DLM3_LKF_NODLCKWT       0x00000100
92 #define DLM3_LKF_NODLCKBLK      0x00000200
93 #define DLM3_LKF_EXPEDITE       0x00000400
94 #define DLM3_LKF_NOQUEUEBAST    0x00000800
95 #define DLM3_LKF_HEADQUE        0x00001000
96 #define DLM3_LKF_NOORDER        0x00002000
97 #define DLM3_LKF_ORPHAN         0x00004000
98 #define DLM3_LKF_ALTPR          0x00008000
99 #define DLM3_LKF_ALTCW          0x00010000
100 #define DLM3_LKF_FORCEUNLOCK    0x00020000
101 #define DLM3_LKF_TIMEOUT        0x00040000
102
103 #define DLM3_SBF_DEMOTED        0x01
104 #define DLM3_SBF_VALNOTVALID    0x02
105 #define DLM3_SBF_ALTMODE        0x04
106
107 #define DLM3_IFL_USER           0x00000001
108 #define DLM3_IFL_ORPHAN         0x00000002
109 /* They may not be used in receiver side.
110    --------------------------------------
111    #define DLM3_IFL_MSTCPY          0x00010000
112    #define DLM3_IFL_RESEND          0x00020000
113    #define DLM3_IFL_DEAD            0x00040000
114    #define DLM3_IFL_OVERLAP_UNLOCK  0x00080000
115    #define DLM3_IFL_OVERLAP_CANCEL  0x00100000
116    #define DLM3_IFL_ENDOFLIFE       0x00200000
117    #define DLM3_IFL_WATCH_TIMEWARN  0x00400000
118    #define DLM3_IFL_TIMEOUT_CANCEL  0x00800000
119    #define DLM3_IFL_DEADLOCK_CANCEL 0x01000000 */
120
121 #define DLM3_LKSTS_WAITING      1
122 #define DLM3_LKSTS_GRANTED      2
123 #define DLM3_LKSTS_CONVERT      3
124
125 #define DLM3_LOCK_IV            -1
126 #define DLM3_LOCK_NL            0
127 #define DLM3_LOCK_CR            1
128 #define DLM3_LOCK_CW            2
129 #define DLM3_LOCK_PR            3
130 #define DLM3_LOCK_PW            4
131 #define DLM3_LOCK_EX            5
132
133 #define DLM3_AST_COMP           1
134 #define DLM3_AST_BAST           2
135
136
137 /* see asm-generic/errno-base.h about LINUX_*  */
138 #define LINUX_EAGAIN            11
139 #define LINUX_ENOMEM            12
140 #define LINUX_INVAL             22
141
142 #define DLM3_ERRNO_EDEADLK       35
143 #define DLM3_ERRNO_EBADR         53
144 #define DLM3_ERRNO_EBADSLT       57
145 #define DLM3_ERRNO_EPROTO        71
146 #define DLM3_ERRNO_EOPNOTSUPP    95
147 #define DLM3_ERRNO_ETIMEDOUT    110
148 #define DLM3_ERRNO_EINPROGRESS  115
149
150 #define DLM3_ECANCEL            0x10001
151 #define DLM3_EUNLOCK            0x10002
152
153
154 #define DLM3_RCOM_STATUS        1
155 #define DLM3_RCOM_NAMES         2
156 #define DLM3_RCOM_LOOKUP        3
157 #define DLM3_RCOM_LOCK          4
158 #define DLM3_RCOM_STATUS_REPLY  5
159 #define DLM3_RCOM_NAMES_REPLY   6
160 #define DLM3_RCOM_LOOKUP_REPLY  7
161 #define DLM3_RCOM_LOCK_REPLY    8
162
163 #define DLM3_RS_NODES           0x00000001
164 #define DLM3_RS_NODES_ALL       0x00000002
165 #define DLM3_RS_DIR             0x00000004
166 #define DLM3_RS_DIR_ALL         0x00000008
167 #define DLM3_RS_LOCKS           0x00000010
168 #define DLM3_RS_LOCKS_ALL       0x00000020
169 #define DLM3_RS_DONE            0x00000040
170 #define DLM3_RS_DONE_ALL        0x00000080
171
172 #define DLM3_RESNAME_MAXLEN     64
173
174 /* Forward declaration we need below */
175 void proto_reg_handoff_dlm3(void);
176
177
178 /* Initialize the protocol and registered fields */
179 static int proto_dlm3 = -1;
180
181 /* fields for struct dlm_header(h) */
182 static int hf_dlm3_h_version   = -1;
183 static int hf_dlm3_h_major_version = -1;
184 static int hf_dlm3_h_minor_version = -1;
185 static int hf_dlm3_h_lockspace = -1;
186 static int hf_dlm3_h_nodeid    = -1;
187 static int hf_dlm3_h_length    = -1;
188 static int hf_dlm3_h_cmd       = -1;
189 static int hf_dlm3_h_pad       = -1;
190
191 /* fields for struct dlm_message(m) */
192 static int hf_dlm3_m_type         = -1;
193 static int hf_dlm3_m_nodeid       = -1;
194 static int hf_dlm3_m_pid          = -1;
195 static int hf_dlm3_m_lkid         = -1;
196 static int hf_dlm3_m_remid        = -1;
197 static int hf_dlm3_m_parent_lkid  = -1;
198 static int hf_dlm3_m_parent_remid = -1;
199
200 /* bit fields for dlm_message::exflags */
201 #define DLM3_DEFINE_HF_EXFLAGS(NAME)            \
202   static int hf_dlm3_##NAME      = -1;          \
203   static int hf_dlm3_##NAME##_noqueue     = -1; \
204   static int hf_dlm3_##NAME##_cancel      = -1; \
205   static int hf_dlm3_##NAME##_convert     = -1; \
206   static int hf_dlm3_##NAME##_valblk      = -1; \
207   static int hf_dlm3_##NAME##_quecvt      = -1; \
208   static int hf_dlm3_##NAME##_ivvalblk    = -1; \
209   static int hf_dlm3_##NAME##_convdeadlk  = -1; \
210   static int hf_dlm3_##NAME##_persistent  = -1; \
211   static int hf_dlm3_##NAME##_nodlckwt    = -1; \
212   static int hf_dlm3_##NAME##_nodlckblk   = -1; \
213   static int hf_dlm3_##NAME##_expedite    = -1; \
214   static int hf_dlm3_##NAME##_noqueuebast = -1; \
215   static int hf_dlm3_##NAME##_headque     = -1; \
216   static int hf_dlm3_##NAME##_noorder     = -1; \
217   static int hf_dlm3_##NAME##_orphan      = -1; \
218   static int hf_dlm3_##NAME##_altpr       = -1; \
219   static int hf_dlm3_##NAME##_altcw       = -1; \
220   static int hf_dlm3_##NAME##_forceunlock = -1; \
221   static int hf_dlm3_##NAME##_timeout     = -1
222 DLM3_DEFINE_HF_EXFLAGS(m_exflags);
223
224 /* bit fields for dlm_message::sbflags */
225 static int hf_dlm3_m_sbflags             = -1;
226 static int hf_dlm3_m_sbflags_demoted     = -1;
227 static int hf_dlm3_m_sbflags_valnotvalid = -1;
228 static int hf_dlm3_m_sbflags_altmode     = -1;
229
230 /* bit fields for dlm_message::flags */
231 #define DLM3_DEFINE_HF_FLAGS(NAME)              \
232   static int hf_dlm3_##NAME          = -1;      \
233   static int hf_dlm3_##NAME##_user   = -1;      \
234   static int hf_dlm3_##NAME##_orphan = -1
235 DLM3_DEFINE_HF_FLAGS(m_flags);
236
237 static int hf_dlm3_m_lvbseq       = -1;
238 static int hf_dlm3_m_hash         = -1;
239 static int hf_dlm3_m_status       = -1;
240 static int hf_dlm3_m_grmode       = -1;
241 static int hf_dlm3_m_rqmode       = -1;
242 static int hf_dlm3_m_bastmode     = -1;
243
244 /* bit fields for dlm_message::asts */
245 #define DLM3_DEFINE_HF_ASTS(NAME)                       \
246   static int hf_dlm3_##NAME##_asts         = -1;        \
247   static int hf_dlm3_##NAME##_asts_comp    = -1;        \
248   static int hf_dlm3_##NAME##_asts_bast    = -1
249 DLM3_DEFINE_HF_ASTS(m);
250
251 static int hf_dlm3_m_result       = -1;
252 static int hf_dlm3_m_extra        = -1;
253
254 /* fields for struct dlm_rcom(rc) */
255 static int hf_dlm3_rc_type      = -1;
256 static int hf_dlm3_rc_result    = -1;
257 static int hf_dlm3_rc_id        = -1;
258 static int hf_dlm3_rc_seq       = -1;
259 static int hf_dlm3_rc_seq_reply = -1;
260 static int hf_dlm3_rc_buf       = -1;
261
262 /* fields for struct rcom_config(rf) */
263 static int hf_dlm3_rf_lvblen    = -1;
264 DLM3_DEFINE_HF_EXFLAGS(rf_lsflags);
265 static int hf_dlm3_rf_unused    = -1;
266
267 /* fields for struct rcom_lock(rl) */
268 static int hf_dlm3_rl_ownpid        = -1;
269 static int hf_dlm3_rl_lkid          = -1;
270 static int hf_dlm3_rl_remid         = -1;
271 static int hf_dlm3_rl_parent_lkid   = -1;
272 static int hf_dlm3_rl_parent_remid  = -1;
273 DLM3_DEFINE_HF_EXFLAGS(rl_exflags);
274 DLM3_DEFINE_HF_FLAGS(rl_flags);
275 static int hf_dlm3_rl_lvbseq        = -1;
276 static int hf_dlm3_rl_result        = -1;
277 static int hf_dlm3_rl_rqmode        = -1;
278 static int hf_dlm3_rl_grmode        = -1;
279 static int hf_dlm3_rl_status        = -1;
280 DLM3_DEFINE_HF_ASTS(rl);
281 static int hf_dlm3_rl_wait_type     = -1;
282 static int hf_dlm3_rl_namelen       = -1;
283 static int hf_dlm3_rl_name          = -1;
284 static int hf_dlm3_rl_name_contents = -1;
285 static int hf_dlm3_rl_name_padding  = -1;
286 static int hf_dlm3_rl_lvb           = -1;
287
288 /* Initialize the subtree pointers */
289 static gint ett_dlm3         = -1;
290 static gint ett_dlm3_version = -1;
291
292 static gint ett_dlm3_msg       = -1;
293 static gint ett_dlm3_m_exflags = -1;
294 static gint ett_dlm3_sbflags   = -1;
295 static gint ett_dlm3_m_flags   = -1;
296 static gint ett_dlm3_m_asts    = -1;
297
298 static gint ett_dlm3_rcom        = -1;
299 static gint ett_dlm3_rcom_lock   = -1;
300 static gint ett_dlm3_rcom_config = -1;
301
302 static gint ett_dlm3_rf_lsflags  = -1;
303 static gint ett_dlm3_rl_exflags  = -1;
304 static gint ett_dlm3_rl_flags    = -1;
305 static gint ett_dlm3_rl_asts     = -1;
306 static gint ett_dlm3_rl_name     = -1;
307
308
309 /* configurable parameters */
310 static guint dlm3_tcp_port  = TCP_PORT_DLM3;
311 static guint dlm3_sctp_port = SCTP_PORT_DLM3;
312
313 /*
314  * Value strings
315  */
316 static const value_string dlm3_cmd[] = {
317   { DLM3_MSG,  "message"          },
318   { DLM3_RCOM, "recovery command" },
319   { 0,         NULL               }
320 };
321
322 static const value_string dlm3_msg[] = {
323   { DLM3_MSG_REQUEST,       "request message"    },
324   { DLM3_MSG_CONVERT,       "conversion message" },
325   { DLM3_MSG_UNLOCK,        "unlock message"     },
326   { DLM3_MSG_CANCEL,        "cancel message"     },
327   { DLM3_MSG_REQUEST_REPLY, "request reply"      },
328   { DLM3_MSG_CONVERT_REPLY, "conversion reply"   },
329   { DLM3_MSG_UNLOCK_REPLY,  "unlock reply"       },
330   { DLM3_MSG_CANCEL_REPLY,  "cancel reply"       },
331   { DLM3_MSG_GRANT,         "grant message"      },
332   { DLM3_MSG_BAST,          "bast message"       },
333   { DLM3_MSG_LOOKUP,        "lookup message"     },
334   { DLM3_MSG_REMOVE,        "remove message"     },
335   { DLM3_MSG_LOOKUP_REPLY,  "lookup reply"       },
336   { DLM3_MSG_PURGE,         "purge orphans"      },
337   { 0,                      NULL                 }
338 };
339
340 static const value_string dlm3_status[] = {
341   { DLM3_LKSTS_WAITING, "waiting"  },
342   { DLM3_LKSTS_GRANTED, "granted"  },
343   { DLM3_LKSTS_CONVERT, "convert"  },
344   { 0,                  NULL       }
345 };
346
347 static const value_string dlm3_mode[] = {
348   { DLM3_LOCK_IV, "invalid"          },
349   { DLM3_LOCK_NL, "null"             },
350   { DLM3_LOCK_CR, "concurrent read"  },
351   { DLM3_LOCK_CW, "concurrent write" },
352   { DLM3_LOCK_PR, "protected read"   },
353   { DLM3_LOCK_PW, "protected write"  },
354   { DLM3_LOCK_EX, "exclusive"        },
355   { 0,            NULL               }
356 };
357
358 static const value_string dlm3_result[] = {
359   { -LINUX_EAGAIN, "blocked"                       },
360   { -LINUX_ENOMEM, "no memory"                     },
361   { -LINUX_INVAL,  "invalid parameters"            },
362   { -DLM3_ERRNO_EDEADLK,     "Resource deadlock avoided"  },
363   { -DLM3_ERRNO_EBADR,       "Invalid request descriptor" },
364   { -DLM3_ERRNO_EBADSLT,     "Invalid slot"               },
365   { -DLM3_ERRNO_EPROTO,      "Protocol error"             },
366   { -DLM3_ERRNO_EOPNOTSUPP,  "Operation not supported"    },
367   { -DLM3_ERRNO_ETIMEDOUT,   "Connection timed out"       },
368   { -DLM3_ERRNO_EINPROGRESS, "Operation now in progress"  },
369   { -DLM3_ECANCEL, "cancel completed successfully" },
370   { -DLM3_EUNLOCK, "unlock request was successful" },
371   { 0,             "successful"                    },
372   { 0,             NULL                            }
373 };
374
375 static const value_string dlm3_rcom[] = {
376   { DLM3_RCOM_STATUS,       "status command" },
377   { DLM3_RCOM_NAMES,        "names command"  },
378   { DLM3_RCOM_LOOKUP,       "lookup command" },
379   { DLM3_RCOM_LOCK,         "lock command"   },
380   { DLM3_RCOM_STATUS_REPLY, "status reply"   },
381   { DLM3_RCOM_NAMES_REPLY,  "names reply"    },
382   { DLM3_RCOM_LOOKUP_REPLY, "lookup reply"   },
383   { DLM3_RCOM_LOCK_REPLY,   "lock reply"     },
384   { 0,                      NULL             }
385 };
386
387 static const value_string dlm3_rs[] = {
388   { DLM3_RS_NODES,     "recovering nodes"                    },
389   { DLM3_RS_NODES_ALL, "recovering all nodes"                },
390   { DLM3_RS_DIR,       "recovering resource directory"       },
391   { DLM3_RS_DIR_ALL,   "recovering all resource directories" },
392   { DLM3_RS_LOCKS,     "recovering lock"                     },
393   { DLM3_RS_LOCKS_ALL, "recovering all locks"                },
394   { DLM3_RS_DONE,      "recovering is done"                  },
395   { DLM3_RS_DONE_ALL,  "all recovering is done"              },
396   { 0,                 NULL                                  }
397 };
398
399 /*
400  * Fields
401  */
402 #define DLM3_DEFINE_EXFLAGS_FIELDS(NAME)        \
403   static const int* NAME##_fields[] = {         \
404     &hf_dlm3_##NAME##_timeout ,                 \
405     &hf_dlm3_##NAME##_forceunlock ,             \
406     &hf_dlm3_##NAME##_altcw       ,             \
407     &hf_dlm3_##NAME##_altpr       ,             \
408     &hf_dlm3_##NAME##_orphan      ,             \
409     &hf_dlm3_##NAME##_noorder     ,             \
410     &hf_dlm3_##NAME##_headque     ,             \
411     &hf_dlm3_##NAME##_noqueuebast ,             \
412     &hf_dlm3_##NAME##_expedite    ,             \
413     &hf_dlm3_##NAME##_nodlckblk   ,             \
414     &hf_dlm3_##NAME##_nodlckwt    ,             \
415     &hf_dlm3_##NAME##_persistent  ,             \
416     &hf_dlm3_##NAME##_convdeadlk  ,             \
417     &hf_dlm3_##NAME##_ivvalblk    ,             \
418     &hf_dlm3_##NAME##_quecvt      ,             \
419     &hf_dlm3_##NAME##_valblk      ,             \
420     &hf_dlm3_##NAME##_convert     ,             \
421     &hf_dlm3_##NAME##_cancel      ,             \
422     &hf_dlm3_##NAME##_noqueue     ,             \
423     NULL                                        \
424   }
425 DLM3_DEFINE_EXFLAGS_FIELDS(m_exflags);
426
427 static const int *m_sbflags_fields[] = {
428   &hf_dlm3_m_sbflags_altmode     ,
429   &hf_dlm3_m_sbflags_valnotvalid ,
430   &hf_dlm3_m_sbflags_demoted     ,
431   NULL
432 };
433
434 #define DLM3_DEFINE_FLAGS_FIELDS(NAME)          \
435   static const int* NAME##_fields[] = {         \
436     &hf_dlm3_##NAME##_orphan        ,           \
437     &hf_dlm3_##NAME##_user          ,           \
438     NULL                                        \
439   }
440 DLM3_DEFINE_FLAGS_FIELDS(m_flags);
441
442 #define DLM3_DEFINE_ASTS_FIELDS(NAME)           \
443   static const int* NAME##_asts_fields[] = {    \
444     &hf_dlm3_##NAME##_asts_bast           ,     \
445     &hf_dlm3_##NAME##_asts_comp           ,     \
446     NULL                                        \
447   }
448 DLM3_DEFINE_ASTS_FIELDS(m);
449
450 DLM3_DEFINE_EXFLAGS_FIELDS(rf_lsflags);
451
452 DLM3_DEFINE_EXFLAGS_FIELDS(rl_exflags);
453 DLM3_DEFINE_FLAGS_FIELDS(rl_flags);
454 DLM3_DEFINE_ASTS_FIELDS(rl);
455
456 /* Code to actually dissect the packets */
457 static void
458 dissect_dlm3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
459                  guint length, int offset)
460 {
461   guint32     m_type;
462
463   m_type   = tvb_get_letohl(tvb, offset);
464   proto_tree_add_uint(tree,
465                       hf_dlm3_m_type, tvb, offset, 4, m_type);
466   col_append_fstr(pinfo->cinfo, COL_INFO,
467                 ": %s",
468                 val_to_str(m_type,
469                            dlm3_msg,
470                            "Unknown"));
471
472   offset += 4;
473   proto_tree_add_item(tree,
474                       hf_dlm3_m_nodeid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
475
476   offset += 4;
477   proto_tree_add_item(tree,
478                       hf_dlm3_m_pid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
479
480   offset += 4;
481   proto_tree_add_item(tree,
482                       hf_dlm3_m_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
483   /* TODO: See `create_lkb'
484      lkid has some structure. We dissect more. */
485
486   offset += 4;
487   proto_tree_add_item(tree,
488                       hf_dlm3_m_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
489
490   offset += 4;
491   proto_tree_add_item(tree,
492                       hf_dlm3_m_parent_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
493
494   offset += 4;
495   proto_tree_add_item(tree,
496                       hf_dlm3_m_parent_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
497
498   offset += 4;
499   proto_tree_add_bitmask(tree, tvb, offset,
500                          hf_dlm3_m_exflags, ett_dlm3_m_exflags,
501                          m_exflags_fields, ENC_LITTLE_ENDIAN);
502
503   offset += 4;
504   proto_tree_add_bitmask(tree, tvb, offset,
505                          hf_dlm3_m_sbflags, ett_dlm3_sbflags,
506                          m_sbflags_fields, ENC_LITTLE_ENDIAN);
507
508   offset += 4;
509   proto_tree_add_bitmask(tree, tvb, offset,
510                          hf_dlm3_m_flags, ett_dlm3_m_flags,
511                          m_flags_fields, ENC_LITTLE_ENDIAN);
512
513   offset += 4;
514   proto_tree_add_item(tree,
515                       hf_dlm3_m_lvbseq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
516
517   offset += 4;
518   proto_tree_add_item(tree,
519                       hf_dlm3_m_hash, tvb, offset, 4, ENC_LITTLE_ENDIAN);
520
521   offset += 4;
522   proto_tree_add_item(tree,
523                       hf_dlm3_m_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
524
525   offset += 4;
526   proto_tree_add_item(tree,
527                       hf_dlm3_m_grmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
528
529   offset += 4;
530   proto_tree_add_item(tree,
531                       hf_dlm3_m_rqmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
532
533   offset += 4;
534   proto_tree_add_item(tree,
535                       hf_dlm3_m_bastmode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
536
537
538   offset += 4;
539   proto_tree_add_bitmask(tree, tvb, offset,
540                          hf_dlm3_m_asts, ett_dlm3_m_asts,
541                          m_asts_fields, ENC_LITTLE_ENDIAN);
542   offset += 4;
543   proto_tree_add_item(tree,
544                       hf_dlm3_m_result, tvb, offset, 4, ENC_LITTLE_ENDIAN);
545
546   offset += 4;
547   if ((length - offset) > 0) {
548     proto_tree_add_item(tree,
549                         hf_dlm3_m_extra,
550                         tvb,
551                         offset,
552                         -1,
553                         ENC_NA);
554   }
555 }
556
557
558
559 static void
560 dissect_dlm3_rcom_lock(tvbuff_t *tvb, proto_tree *tree,
561                        guint length, int offset)
562 {
563   proto_item *sub_item;
564   proto_tree *sub_tree;
565   int         sub_offset;
566   guint16     namelen;
567   guint32     exflags;
568
569
570   if ((length - offset) < ( 4 * 8 + 4 + 1 * 4 + 2 * 2
571                             + DLM3_RESNAME_MAXLEN ))
572     return;
573
574
575   proto_tree_add_item(tree,
576                       hf_dlm3_rl_ownpid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
577
578   offset += 4;
579   proto_tree_add_item(tree,
580                       hf_dlm3_rl_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
581
582   offset += 4;
583   proto_tree_add_item(tree,
584                       hf_dlm3_rl_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
585
586   offset += 4;
587   proto_tree_add_item(tree,
588                       hf_dlm3_rl_parent_lkid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
589
590   offset += 4;
591   proto_tree_add_item(tree,
592                       hf_dlm3_rl_parent_remid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
593
594   offset += 4;
595   proto_tree_add_bitmask(tree, tvb, offset,
596                          hf_dlm3_rl_exflags, ett_dlm3_rl_exflags,
597                          rl_exflags_fields, ENC_LITTLE_ENDIAN);
598   exflags = tvb_get_letohl(tvb, offset);
599
600
601   offset += 4;
602   proto_tree_add_bitmask(tree, tvb, offset,
603                          hf_dlm3_rl_flags, ett_dlm3_rl_flags,
604                          rl_flags_fields, ENC_LITTLE_ENDIAN);
605
606   offset += 4;
607   proto_tree_add_item(tree,
608                       hf_dlm3_rl_lvbseq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
609
610   offset += 4;
611   proto_tree_add_item(tree,
612                       hf_dlm3_rl_result, tvb, offset, 4, ENC_LITTLE_ENDIAN);
613
614   offset += 4;
615   proto_tree_add_item(tree,
616                       hf_dlm3_rl_rqmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
617
618   offset += 1;
619   proto_tree_add_item(tree,
620                       hf_dlm3_rl_grmode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
621
622   offset += 1;
623   proto_tree_add_item(tree,
624                       hf_dlm3_rl_status, tvb, offset, 1, ENC_LITTLE_ENDIAN);
625
626   offset += 1;
627   proto_tree_add_bitmask(tree, tvb, offset,
628                          hf_dlm3_rl_asts, ett_dlm3_rl_asts,
629                          rl_asts_fields, ENC_LITTLE_ENDIAN);
630
631   offset += 1;
632   proto_tree_add_item(tree,
633                       hf_dlm3_rl_wait_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
634
635   offset += 2;
636   namelen = tvb_get_letohs(tvb, offset);
637   proto_tree_add_uint(tree,
638                       hf_dlm3_rl_namelen, tvb, offset, 2,
639                       namelen);
640
641   offset += 2;
642   sub_item = proto_tree_add_item(tree,
643                                  hf_dlm3_rl_name, tvb, offset,
644                                  DLM3_RESNAME_MAXLEN, ENC_NA);
645
646   sub_tree = proto_item_add_subtree(sub_item,
647                                     ett_dlm3_rl_name);
648   sub_offset = offset;
649   proto_tree_add_item(sub_tree,
650                       hf_dlm3_rl_name_contents, tvb, sub_offset,
651                       namelen, ENC_ASCII|ENC_NA);
652
653   sub_offset += namelen;
654   proto_tree_add_item(sub_tree,
655                       hf_dlm3_rl_name_padding, tvb, sub_offset,
656                       DLM3_RESNAME_MAXLEN - namelen, ENC_NA);
657
658   offset += DLM3_RESNAME_MAXLEN;
659   if (((length - offset) > 0) && (exflags & DLM3_LKF_VALBLK))
660     proto_tree_add_item(tree,
661                         hf_dlm3_rl_lvb, tvb, offset,
662                         -1,
663                         ENC_NA);
664 }
665
666
667 static void
668 dissect_dlm3_rcom_config(tvbuff_t *tvb, proto_tree *tree,
669                          guint length, int offset)
670 {
671   if ((length - offset) < ( 4 + 4 + 8 ))
672     return;
673
674   proto_tree_add_item(tree,
675                       hf_dlm3_rf_lvblen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
676
677   offset += 4;
678   proto_tree_add_bitmask(tree, tvb, offset,
679                          hf_dlm3_rf_lsflags, ett_dlm3_rf_lsflags,
680                          rf_lsflags_fields, ENC_LITTLE_ENDIAN);
681
682   offset += 4;
683   proto_tree_add_item(tree,
684                       hf_dlm3_rf_unused, tvb, offset, 8, ENC_LITTLE_ENDIAN);
685
686
687   offset += 8;
688   /* END */
689 }
690
691 static void
692 dissect_dlm3_rcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
693                   guint length, int offset)
694 {
695   guint32     rc_type;
696
697   proto_item *sub_item;
698   proto_tree *sub_tree;
699
700
701   rc_type  = tvb_get_letohl(tvb, offset);
702   proto_tree_add_uint(tree,
703                       hf_dlm3_rc_type, tvb, offset, 4, rc_type);
704   col_append_fstr(pinfo->cinfo, COL_INFO,
705                   ": %s",
706                   val_to_str(rc_type,
707                              dlm3_rcom,
708                              "Unknown"));
709
710   offset += 4;
711   proto_tree_add_item(tree,
712                       hf_dlm3_rc_result, tvb, offset, 4, ENC_LITTLE_ENDIAN);
713
714   offset += 4;
715   proto_tree_add_item(tree,
716                       hf_dlm3_rc_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
717
718   offset += 8;
719   proto_tree_add_item(tree,
720                       hf_dlm3_rc_seq, tvb, offset, 8, ENC_LITTLE_ENDIAN);
721
722   offset += 8;
723   proto_tree_add_item(tree,
724                       hf_dlm3_rc_seq_reply, tvb, offset, 8, ENC_LITTLE_ENDIAN);
725
726   offset += 8;
727   if ((length - offset) == 0) {
728     /* No rc_buf: Just return */
729     return;
730   }
731
732   /* Decode rc_buf */
733   sub_item = proto_tree_add_item(tree,
734                                  hf_dlm3_rc_buf,
735                                  tvb,
736                                  offset,
737                                  -1,
738                                  ENC_NA);
739
740   offset += 0;
741   if (rc_type == DLM3_RCOM_LOCK) {
742     sub_tree = proto_item_add_subtree(sub_item,
743                                       ett_dlm3_rcom_lock);
744     dissect_dlm3_rcom_lock(tvb, sub_tree, length, offset);
745   } else if (rc_type == DLM3_RCOM_STATUS_REPLY) {
746     sub_tree = proto_item_add_subtree(sub_item,
747                                       ett_dlm3_rcom_config);
748     dissect_dlm3_rcom_config(tvb, sub_tree, length, offset);
749   }
750
751 }
752
753 static int
754 dissect_dlm3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
755 {
756   proto_item *item, *sub_item;
757   proto_tree *tree, *sub_tree;
758
759   int        offset;
760   guint      length;
761   guint32    h_version;
762   guint8     h_cmd;
763
764
765   /* Check that there's enough data */
766   length = tvb_length(tvb);
767   if (length < 4 + 4 + 4 + 2 + 1 + 1)
768     return 0;
769
770   /* Check the protocol version  */
771   h_version = tvb_get_letohl(tvb, 0);
772   if (h_version != (DLM3_MAJOR_VERSION|DLM3_MINOR_VERSION))
773     return 0;
774
775   /* Check the command */
776   h_cmd = tvb_get_guint8(tvb, 4 + 4 + 4 + 2) ;
777   if ((h_cmd != DLM3_MSG) && (h_cmd != DLM3_RCOM))
778     return 0;
779
780   if ((h_cmd == DLM3_MSG) && (length < ((4 + 4 + 4 + 2 + 1 + 1)
781                                         + (4 * 12 + 4 * 6))))
782     return 0;
783   else if ((h_cmd == DLM3_RCOM) && (length < 4 + 4 + 8 + 8 + 8))
784     return 0;
785
786
787   col_set_str(pinfo->cinfo, COL_PROTOCOL, "DLM3");
788
789
790   col_set_str(pinfo->cinfo, COL_INFO, "DLM3");
791
792   col_set_str(pinfo->cinfo, COL_INFO,
793                 val_to_str_const(h_cmd,
794                            dlm3_cmd,
795                            "packet-dlm3.c internal bug"));
796
797   if (parent_tree) {
798     offset = 0;
799
800     item = proto_tree_add_item(parent_tree, proto_dlm3, tvb, offset,
801                                -1, ENC_NA);
802     tree = proto_item_add_subtree(item, ett_dlm3);
803
804     sub_item = proto_tree_add_uint(tree,
805                                    hf_dlm3_h_version, tvb, offset, 4,
806                                    h_version);
807     sub_tree = proto_item_add_subtree(sub_item, ett_dlm3_version);
808     proto_tree_add_uint(sub_tree,
809                         hf_dlm3_h_major_version, tvb, offset + 0, 2,
810                         (h_version & 0xFFFF0000) >> 16);
811     proto_tree_add_uint(sub_tree,
812                         hf_dlm3_h_minor_version, tvb, offset + 2, 2,
813                         (h_version & 0x0000FFFF));
814
815
816     offset += 4;
817     proto_tree_add_item(tree,
818                         hf_dlm3_h_lockspace, tvb, offset, 4, ENC_LITTLE_ENDIAN);
819
820     offset += 4;
821     proto_tree_add_item(tree,
822                         hf_dlm3_h_nodeid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
823     offset += 4;
824     proto_tree_add_item(tree,
825                         hf_dlm3_h_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
826
827     offset += 2;
828     sub_item = proto_tree_add_uint(tree,
829                                    hf_dlm3_h_cmd, tvb, offset, 1, h_cmd);
830
831     offset += 1;
832     proto_tree_add_item(tree,
833                         hf_dlm3_h_pad, tvb, offset, 1, ENC_LITTLE_ENDIAN);
834
835
836     offset += 1;
837     if (h_cmd == DLM3_MSG) {
838       sub_tree = proto_item_add_subtree(sub_item, ett_dlm3_msg);
839       dissect_dlm3_msg(tvb, pinfo, sub_tree, length, offset);
840     } else if (h_cmd== DLM3_RCOM) {
841       sub_tree = proto_item_add_subtree(sub_item, ett_dlm3_rcom);
842       dissect_dlm3_rcom(tvb, pinfo, sub_tree, length, offset);
843     }
844   }
845   return tvb_length(tvb);
846 }
847
848
849 /* Register the protocol with Wireshark */
850
851 #define DLM3_REGISTER_HF_LOCKID(NAME)                                   \
852   { &hf_dlm3_##NAME##_lkid,                                             \
853       { "Lock ID on Sender", "dlm3." #NAME ".lkid",                     \
854           FT_UINT32, BASE_DEC_HEX, NULL, 0x0,                           \
855           NULL, HFILL}},                                                \
856 { &hf_dlm3_##NAME##_remid,                                              \
857     { "Lock ID on Receiver", "dlm3." #NAME ".remid",                    \
858         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,                             \
859         NULL, HFILL}},                                                  \
860 { &hf_dlm3_##NAME##_parent_lkid,                                        \
861     { "Parent Lock ID on Sender", "dlm3." #NAME ".parent_lkid",         \
862         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,                             \
863         NULL, HFILL}},                                                  \
864 { &hf_dlm3_##NAME##_parent_remid,                                       \
865     { "Parent Lock ID on Receiver", "dlm3." #NAME ".parent_remid",      \
866         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,                             \
867         NULL, HFILL}}
868
869 #define DLM3_REGISTER_HF_EXFLAGS(SYMNAME,STRNAME)                       \
870 { &hf_dlm3_##SYMNAME,                                                   \
871   { "External Flags", "dlm3." STRNAME "",                               \
872     FT_UINT32, BASE_HEX, NULL, 0x0,                                     \
873     NULL, HFILL}},                                                      \
874 { &hf_dlm3_##SYMNAME##_noqueue,                                         \
875   { "Don't queue", "dlm3." STRNAME ".noqueue",                          \
876     FT_BOOLEAN, 32, NULL, DLM3_LKF_NOQUEUE,                             \
877     NULL, HFILL}},                                                      \
878 { &hf_dlm3_##SYMNAME##_cancel,                                          \
879   { "Cancel", "dlm3." STRNAME ".cancel",                                \
880     FT_BOOLEAN, 32, NULL, DLM3_LKF_CANCEL,                              \
881     NULL, HFILL}},                                                      \
882 { &hf_dlm3_##SYMNAME##_convert,                                         \
883   { "Convert", "dlm3." STRNAME ".convert",                              \
884     FT_BOOLEAN, 32, NULL, DLM3_LKF_CONVERT,                             \
885     NULL, HFILL}},                                                      \
886 { &hf_dlm3_##SYMNAME##_valblk,                                          \
887   { "Return the contents of the lock value block", "dlm3." STRNAME ".valblk", \
888     FT_BOOLEAN, 32, NULL, DLM3_LKF_VALBLK,                              \
889     NULL, HFILL}},                                                      \
890 { &hf_dlm3_##SYMNAME##_quecvt,                                          \
891   { "Force a conversion request to be queued", "dlm3." STRNAME ".quecvt", \
892     FT_BOOLEAN, 32, NULL, DLM3_LKF_QUECVT,                              \
893     NULL, HFILL}},                                                      \
894 { &hf_dlm3_##SYMNAME##_ivvalblk,                                        \
895   { "Invalidate the lock value block", "dlm3." STRNAME ".ivvalblk",     \
896     FT_BOOLEAN, 32, NULL, DLM3_LKF_IVVALBLK,                            \
897     NULL, HFILL}},                                                      \
898 { &hf_dlm3_##SYMNAME##_convdeadlk,                                      \
899   { "Forced down to NL to resolve a conversion deadlock", "dlm3." STRNAME ".convdeadlk", \
900     FT_BOOLEAN, 32, NULL, DLM3_LKF_CONVDEADLK,                          \
901     NULL, HFILL}},                                                      \
902 { &hf_dlm3_##SYMNAME##_persistent,                                      \
903   { "Persistent", "dlm3." STRNAME ".persistent",                        \
904     FT_BOOLEAN, 32, NULL, DLM3_LKF_PERSISTENT,                          \
905     NULL, HFILL}},                                                      \
906 { &hf_dlm3_##SYMNAME##_nodlckwt,                                        \
907   { "Don't cancel the lock if it gets into conversion deadlock", "dlm3." STRNAME ".nodlckwt", \
908     FT_BOOLEAN, 32, NULL, DLM3_LKF_NODLCKWT,                            \
909     NULL, HFILL}},                                                      \
910 { &hf_dlm3_##SYMNAME##_nodlckblk,                                       \
911   { "Nodlckblk", "dlm3." STRNAME ".nodlckblk",                          \
912     FT_BOOLEAN, 32, NULL, DLM3_LKF_NODLCKBLK,                           \
913     NULL, HFILL}},                                                      \
914 { &hf_dlm3_##SYMNAME##_expedite,                                        \
915   { "Grant a NL lock immediately", "dlm3." STRNAME ".expedite",         \
916     FT_BOOLEAN, 32, NULL, DLM3_LKF_EXPEDITE,                            \
917     NULL, HFILL}},                                                      \
918 { &hf_dlm3_##SYMNAME##_noqueuebast,                                     \
919   { "Send blocking ASTs even for NOQUEUE operations", "dlm3." STRNAME ".noqueuebast", \
920     FT_BOOLEAN, 32, NULL, DLM3_LKF_NOQUEUEBAST,                         \
921     NULL, HFILL}},                                                      \
922 { &hf_dlm3_##SYMNAME##_headque,                                         \
923   { "Add a lock to the head of the queue", "dlm3." STRNAME ".headque",  \
924     FT_BOOLEAN, 32, NULL, DLM3_LKF_HEADQUE,                             \
925     NULL, HFILL}},                                                      \
926 { &hf_dlm3_##SYMNAME##_noorder,                                         \
927   { "Disregard the standard grant order rules", "dlm3." STRNAME ".noorder", \
928     FT_BOOLEAN, 32, NULL, DLM3_LKF_NOORDER,                             \
929     NULL, HFILL}},                                                      \
930 { &hf_dlm3_##SYMNAME##_orphan,                                          \
931   { "Orphan", "dlm3." STRNAME ".orphan",                                \
932     FT_BOOLEAN, 32, NULL, DLM3_LKF_ORPHAN,                              \
933     NULL, HFILL}},                                                      \
934 { &hf_dlm3_##SYMNAME##_altpr,                                           \
935   { "Try to grant the lock in `protected read' mode", "dlm3." STRNAME ".altpr", \
936     FT_BOOLEAN, 32, NULL, DLM3_LKF_ALTPR,                               \
937     NULL, HFILL}},                                                      \
938 { &hf_dlm3_##SYMNAME##_altcw,                                           \
939   { "Try to grant the lock in `concurrent read' mode", "dlm3." STRNAME ".altcw", \
940     FT_BOOLEAN, 32, NULL, DLM3_LKF_ALTCW,                               \
941     NULL, HFILL}},                                                      \
942 { &hf_dlm3_##SYMNAME##_forceunlock,                                     \
943   { "Force unlock", "dlm3." STRNAME ".forceunlock",                     \
944     FT_BOOLEAN, 32, NULL, DLM3_LKF_FORCEUNLOCK,                         \
945     NULL, HFILL}},                                                      \
946 { &hf_dlm3_##SYMNAME##_timeout,                                         \
947   { "Timeout", "dlm3." STRNAME ".timeout",                              \
948     FT_BOOLEAN, 32, NULL, DLM3_LKF_TIMEOUT,                             \
949     NULL, HFILL}}
950
951
952 #define DLM3_REGISTER_HF_FLAGS(SYMNAME,STRNAME)         \
953 { &hf_dlm3_##SYMNAME,                                   \
954   { "Internal Flags", "dlm3." STRNAME,                  \
955     FT_UINT32, BASE_HEX, NULL, 0x0,                     \
956     NULL, HFILL}},                                      \
957 { &hf_dlm3_##SYMNAME##_user,                            \
958   { "User space lock realted", "dlm3." STRNAME ".user", \
959     FT_BOOLEAN, 32, NULL, DLM3_IFL_USER,                \
960     NULL, HFILL}},                                      \
961 { &hf_dlm3_##SYMNAME##_orphan,                          \
962   { "Orphaned lock", "dlm3." STRNAME ".orphan",         \
963     FT_BOOLEAN, 32, NULL, DLM3_IFL_ORPHAN,              \
964     NULL, HFILL}}
965
966 #define DLM3_REGISTER_HF_ASTS(NAME,SIZE)         \
967 { &hf_dlm3_##NAME##_asts,                        \
968   { "Asynchronous Traps", "dlm3." #NAME ".asts", \
969     FT_UINT##SIZE, BASE_HEX, NULL, 0x0,           \
970     NULL, HFILL}},                               \
971 { &hf_dlm3_##NAME##_asts_comp,                   \
972   { "Completion", "dlm3." #NAME ".asts.comp",    \
973     FT_BOOLEAN, SIZE, NULL, DLM3_AST_COMP,       \
974     NULL, HFILL }},                              \
975 { &hf_dlm3_##NAME##_asts_bast,                   \
976   { "Blocking", "dlm3." #NAME ".asts.bast",      \
977     FT_BOOLEAN, SIZE, NULL, DLM3_AST_BAST,       \
978     NULL, HFILL }}
979
980 void
981 proto_register_dlm3(void)
982 {
983   module_t *dlm3_module;
984
985
986   static hf_register_info hf[] = {
987     /* dlm_header */
988     { &hf_dlm3_h_version,
989       { "Version", "dlm3.h.version",
990         FT_UINT32, BASE_HEX, NULL, 0x0,
991         NULL, HFILL }},
992     { &hf_dlm3_h_major_version,
993       { "Major Version", "dlm3.h.major_version",
994         FT_UINT16, BASE_HEX, NULL, 0x0,
995         NULL, HFILL }},
996     { &hf_dlm3_h_minor_version,
997       { "Minor Version", "dlm3.h.minor_version",
998         FT_UINT16, BASE_HEX, NULL, 0x0,
999         NULL, HFILL }},
1000     { &hf_dlm3_h_lockspace,
1001       { "Lockspace Global ID", "dlm3.h.lockspac",
1002         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1003         NULL, HFILL }},
1004     { &hf_dlm3_h_nodeid,
1005       { "Sender Node ID", "dlm3.h.nodeid",
1006         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1007         NULL, HFILL }},
1008     { &hf_dlm3_h_length,
1009       { "Length", "dlm3.h.length",
1010         FT_UINT16, BASE_DEC, NULL, 0x0,
1011         NULL, HFILL }},
1012     { &hf_dlm3_h_cmd,
1013       { "Command", "dlm3.h.cmd",
1014         FT_UINT8, BASE_DEC, VALS(dlm3_cmd), 0x0,
1015         NULL, HFILL }},
1016     { &hf_dlm3_h_pad,
1017       { "Padding", "dlm3.h.pad",
1018         FT_UINT8, BASE_DEC, NULL, 0x0,
1019         NULL, HFILL }},
1020
1021     /* dlm_message */
1022     { &hf_dlm3_m_type,
1023       { "Message Type", "dlm3.m.type",
1024         FT_UINT32, BASE_DEC, VALS(dlm3_msg), 0x0,
1025         NULL, HFILL }},
1026     { &hf_dlm3_m_nodeid,
1027       { "Receiver Node ID", "dlm3.m.nodeid",
1028         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1029         NULL, HFILL }},
1030     { &hf_dlm3_m_pid,
1031       { "Process ID of Lock Owner", "dlm3.m.pid",
1032         FT_UINT32, BASE_DEC, NULL, 0x0,
1033         NULL, HFILL }},
1034     DLM3_REGISTER_HF_LOCKID(m),
1035
1036     /* dlm_message::exflags */
1037     DLM3_REGISTER_HF_EXFLAGS(m_exflags, "m.exflags"),
1038
1039     /* dlm_message::sbflags */
1040     { &hf_dlm3_m_sbflags,
1041       { "Status Block Flags", "dlm3.m.sbflags",
1042         FT_UINT32, BASE_HEX, NULL, 0x0,
1043         NULL, HFILL}},
1044     { &hf_dlm3_m_sbflags_demoted,
1045       { "Demoted for deadlock resolution", "dlm3.m.sbflags.demoted",
1046         FT_BOOLEAN, 32, NULL, DLM3_SBF_DEMOTED,
1047         NULL, HFILL}},
1048     { &hf_dlm3_m_sbflags_valnotvalid,
1049       { "Lock Value Block Is Invalid", "dlm3.m.sbflags.valnotvalid",
1050         FT_BOOLEAN, 32, NULL, DLM3_SBF_VALNOTVALID,
1051         NULL, HFILL}},
1052     { &hf_dlm3_m_sbflags_altmode,
1053       { "Try to Grant in Alternative Mode", "dlm3.m.sbflags.altmode",
1054         FT_BOOLEAN, 32, NULL, DLM3_SBF_ALTMODE,
1055         NULL, HFILL}},
1056
1057     /* dlm_message::flags */
1058     DLM3_REGISTER_HF_FLAGS(m_flags, "m.flags"),
1059
1060     { &hf_dlm3_m_lvbseq,
1061       { "Lock Value Block Sequence Number", "dlm3.m.lvbseq",
1062         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1063         NULL, HFILL}},
1064
1065     { &hf_dlm3_m_hash,
1066       { "Hash value", "dlm3.m.hash",
1067         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1068         NULL, HFILL}},
1069
1070     { &hf_dlm3_m_status,
1071       { "Status", "dlm3.m.status",
1072         FT_INT32, BASE_DEC, VALS(dlm3_status), 0x0,
1073         NULL, HFILL}},
1074
1075     { &hf_dlm3_m_grmode,
1076       { "Granted Mode", "dlm3.m.grmode",
1077         FT_INT32, BASE_DEC, VALS(dlm3_mode), 0x0,
1078         NULL, HFILL}},
1079     { &hf_dlm3_m_rqmode,
1080       { "Request Mode", "dlm3.m.rqmode",
1081         FT_INT32, BASE_DEC, VALS(dlm3_mode), 0x0,
1082         NULL, HFILL}},
1083     { &hf_dlm3_m_bastmode,
1084       { "Mode requested by another node", "dlm3.m.bastmode",
1085         FT_INT32, BASE_DEC, VALS(dlm3_mode), 0x0,
1086         NULL, HFILL}},
1087
1088     /* dlm_message::asts */
1089     DLM3_REGISTER_HF_ASTS(m, 32),
1090
1091     { &hf_dlm3_m_result,
1092       { "Message Result(errno)", "dlm3.m.result",
1093         FT_INT32, BASE_DEC, VALS(dlm3_result), 0x0,
1094         NULL, HFILL}},
1095     { &hf_dlm3_m_extra,
1096       { "Extra Message", "dlm3.m.extra",
1097         FT_BYTES, BASE_NONE, NULL, 0x0,
1098         NULL, HFILL}},
1099
1100     /* dlm_rcom */
1101     { &hf_dlm3_rc_type,
1102       { "Recovery Command Type", "dlm3.rc.type",
1103         FT_UINT32, BASE_DEC, VALS(dlm3_rcom), 0x0,
1104         NULL, HFILL}},
1105     { &hf_dlm3_rc_result,
1106       { "Recovery Command Result", "dlm3.rc.result",
1107         FT_INT32, BASE_DEC, NULL, 0x0,
1108         NULL, HFILL}},
1109     { &hf_dlm3_rc_id,
1110       { "Recovery Command ID", "dlm3.rc.id",
1111         FT_UINT64, BASE_DEC, NULL, 0x0,
1112         NULL, HFILL}},
1113     { &hf_dlm3_rc_seq,
1114       { "Recovery Command Sequence Number of Sender", "dlm3.rc.seq",
1115         FT_UINT64, BASE_DEC, NULL, 0x0,
1116         NULL, HFILL}},
1117     { &hf_dlm3_rc_seq_reply,
1118       { "Recovery Command Sequence Number of Receiver", "dlm3.rc.seq_reply",
1119         FT_UINT64, BASE_DEC, NULL, 0x0,
1120         NULL, HFILL}},
1121     { &hf_dlm3_rc_buf,
1122       { "Recovery Buffer", "dlm3.rc.buf",
1123         FT_BYTES, BASE_NONE, NULL, 0x0,
1124         NULL, HFILL}},
1125
1126     /* rcom_config */
1127     { &hf_dlm3_rf_lvblen,
1128       { "Lock Value Block Length", "dlm3.rf.lvblen",
1129         FT_UINT32, BASE_DEC, NULL, 0x0,
1130         NULL, HFILL}},
1131
1132     /* rcom_config::rf_lsflags */
1133     DLM3_REGISTER_HF_EXFLAGS(rf_lsflags, "rf.lsflags"),
1134
1135     { &hf_dlm3_rf_unused,
1136       { "Unsed area", "dlm3.rf.lsflags.unused",
1137         FT_UINT64, BASE_HEX, NULL, 0x0,
1138         NULL, HFILL}},
1139
1140     /* rcom_lock */
1141     { &hf_dlm3_rl_ownpid,
1142       { "Process ID of Lock Owner", "dlm3.rl.ownpid",
1143         FT_UINT32, BASE_DEC, NULL, 0x0,
1144         NULL, HFILL}},
1145
1146     DLM3_REGISTER_HF_LOCKID(rl),
1147     DLM3_REGISTER_HF_EXFLAGS(rl_exflags, "rl.exflags"),
1148     DLM3_REGISTER_HF_FLAGS(rl_flags, "rl.flags"),
1149
1150     { &hf_dlm3_rl_lvbseq,
1151       { "Lock Value Block Sequence Number", "dlm3.rl.lvbseq",
1152         FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
1153         NULL, HFILL}},
1154     { &hf_dlm3_rl_result,
1155       { "Result of Recovering master copy", "dlm3.rl.result",
1156         FT_INT32, BASE_DEC, VALS(dlm3_result), 0x0,
1157         NULL, HFILL}},
1158     { &hf_dlm3_rl_rqmode,
1159       { "Request Mode", "dlm3.rl.rqmode",
1160         FT_INT8, BASE_DEC, VALS(dlm3_mode), 0x0,
1161         NULL, HFILL}},
1162     { &hf_dlm3_rl_grmode,
1163       { "Granted Mode", "dlm3.rl.grmode",
1164         FT_INT8, BASE_DEC, VALS(dlm3_mode), 0x0,
1165         NULL, HFILL}},
1166     { &hf_dlm3_rl_status,
1167       { "Status", "dlm3.rl.status",
1168         FT_INT8, BASE_DEC, VALS(dlm3_rs), 0x0,
1169         NULL, HFILL}},
1170     DLM3_REGISTER_HF_ASTS(rl, 8),
1171
1172     { &hf_dlm3_rl_wait_type,
1173       { "Message Type the waiter is waiting for", "dlm3.rl.wait_type",
1174         FT_UINT16, BASE_DEC, VALS(dlm3_msg), 0x0,
1175         NULL, HFILL }},
1176
1177     { &hf_dlm3_rl_namelen,
1178       { "Length of `name' field", "dlm3.rl.namelen",
1179         FT_UINT16, BASE_DEC, NULL, 0x0,
1180         NULL, HFILL }},
1181     { &hf_dlm3_rl_name,
1182       { "Name of Resource", "dlm3.rl.name",
1183         FT_BYTES, BASE_NONE, NULL, 0x0,
1184         NULL, HFILL }},
1185     { &hf_dlm3_rl_name_contents,
1186       { "Contents actually occupying `name' field", "dlm3.rl.name_contents",
1187         FT_STRING, BASE_NONE, NULL, 0x0,
1188         NULL, HFILL }},
1189     { &hf_dlm3_rl_name_padding,
1190       { "Padding", "dlm3.rl.name_padding",
1191         FT_BYTES, BASE_NONE, NULL, 0x0,
1192         NULL, HFILL }},
1193     { &hf_dlm3_rl_lvb,
1194       { "Lock Value Block", "dlm3.rl.lvb",
1195         FT_BYTES, BASE_NONE, NULL, 0x0,
1196         NULL, HFILL }}
1197   };
1198
1199   static gint *ett[] = {
1200     &ett_dlm3,
1201     &ett_dlm3_version,
1202
1203     &ett_dlm3_msg,
1204     &ett_dlm3_m_exflags,
1205     &ett_dlm3_sbflags,
1206     &ett_dlm3_m_flags,
1207     &ett_dlm3_m_asts,
1208
1209     &ett_dlm3_rcom,
1210     &ett_dlm3_rcom_lock,
1211     &ett_dlm3_rcom_config,
1212
1213     &ett_dlm3_rf_lsflags,
1214     &ett_dlm3_rl_exflags,
1215     &ett_dlm3_rl_flags,
1216     &ett_dlm3_rl_asts,
1217     &ett_dlm3_rl_name
1218   };
1219
1220   proto_dlm3 = proto_register_protocol("Distributed Lock Manager",
1221                                        "DLM3", "dlm3");
1222   proto_register_field_array(proto_dlm3, hf, array_length(hf));
1223   proto_register_subtree_array(ett, array_length(ett));
1224
1225   dlm3_module = prefs_register_protocol(proto_dlm3,
1226                                         proto_reg_handoff_dlm3);
1227
1228   prefs_register_uint_preference(dlm3_module, "tcp.port",
1229                                  "DLM3 TCP Port",
1230                                  "Set the TCP port for Distributed Lock Manager",
1231                                  10,
1232                                  &dlm3_tcp_port);
1233   prefs_register_uint_preference(dlm3_module, "sctp.port",
1234                                  "DLM3 SCTP Port",
1235                                  "Set the SCTP port for Distributed Lock Manager",
1236                                  10,
1237                                  &dlm3_sctp_port);
1238 }
1239
1240
1241 void
1242 proto_reg_handoff_dlm3(void)
1243 {
1244   static gboolean dissector_registered = FALSE;
1245
1246   static guint tcp_port;
1247   static guint sctp_port;
1248
1249   static dissector_handle_t dlm3_tcp_handle;
1250   static dissector_handle_t dlm3_sctp_handle;
1251
1252   if (!dissector_registered) {
1253     dlm3_sctp_handle = new_create_dissector_handle(dissect_dlm3, proto_dlm3);
1254     dlm3_tcp_handle = new_create_dissector_handle(dissect_dlm3, proto_dlm3);
1255     dissector_registered = TRUE;
1256   } else {
1257     dissector_delete_uint("tcp.port",  tcp_port,  dlm3_tcp_handle);
1258     dissector_delete_uint("sctp.port", sctp_port, dlm3_sctp_handle);
1259   }
1260
1261   tcp_port  = dlm3_tcp_port;
1262   sctp_port = dlm3_sctp_port;
1263   dissector_add_uint("tcp.port",  tcp_port,  dlm3_tcp_handle);
1264   dissector_add_uint("sctp.port", sctp_port, dlm3_sctp_handle);
1265 }
1266
1267 /* packet-dlm3.c ends here. */