- Decode some more annex C fields
[obnox/wireshark/wip.git] / epan / dissectors / packet-nlm.c
1 /* packet-nlm.c
2  * Routines for nlm dissection
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * Copied from packet-mount.c
11  *
12  * 2001-JAN  Ronnie Sahlberg <See AUTHORS for email>
13  *  Updates to version 1 of the protocol.
14  *  Added version 3 of the protocol.
15  *  Added version 4 of the protocol.
16  *
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
31  */
32
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38
39
40 #include "packet-rpc.h"
41 #include "packet-nfs.h"
42 #include "packet-nlm.h"
43 #include <epan/prefs.h>
44 #include <string.h>
45
46 /*
47  * NFS Lock Manager protocol specs can only be found in actual
48  * implementations or in the nice book:
49  * Brent Callaghan: "NFS Illustrated", Addison-Wesley, ISBN 0-201-32570-5
50  * which I use here as reference (BC).
51  *
52  * They can also be found if you go to
53  *
54  *      http://www.opengroup.org/publications/catalog/c702.htm
55  *
56  * and follow the links to the HTML version of the document.
57  */
58
59 static int proto_nlm = -1;
60 static int hf_nlm_procedure_v1 = -1;
61 static int hf_nlm_procedure_v2 = -1;
62 static int hf_nlm_procedure_v3 = -1;
63 static int hf_nlm_procedure_v4 = -1;
64 static int hf_nlm_cookie = -1;
65 static int hf_nlm_block = -1;
66 static int hf_nlm_exclusive = -1;
67 static int hf_nlm_lock = -1;
68 static int hf_nlm_lock_caller_name = -1;
69 static int hf_nlm_lock_owner = -1;
70 static int hf_nlm_lock_svid = -1;
71 static int hf_nlm_lock_l_offset = -1;
72 static int hf_nlm_lock_l_offset64 = -1;
73 static int hf_nlm_lock_l_len = -1;
74 static int hf_nlm_lock_l_len64 = -1;
75 static int hf_nlm_reclaim = -1;
76 static int hf_nlm_stat = -1;
77 static int hf_nlm_state = -1;
78 static int hf_nlm_test_stat = -1;
79 static int hf_nlm_test_stat_stat = -1;
80 static int hf_nlm_holder = -1;
81 static int hf_nlm_share = -1;
82 static int hf_nlm_share_mode = -1;
83 static int hf_nlm_share_access = -1;
84 static int hf_nlm_share_name = -1;
85 static int hf_nlm_sequence = -1;
86 static int hf_nlm_request_in = -1;
87 static int hf_nlm_reply_in = -1;
88 static int hf_nlm_time = -1;
89
90 static gint ett_nlm = -1;
91 static gint ett_nlm_lock = -1;
92
93
94
95 /*
96  * stuff to match MSG and RES packets for async NLM
97  */
98
99 static gboolean nlm_match_msgres = FALSE;
100 static GHashTable *nlm_msg_res_unmatched = NULL;
101 static GHashTable *nlm_msg_res_matched = NULL;
102
103 /* XXX  when matching the packets we should really check the conversation (only address
104         NOT ports) and command type as well. I am lazy and thinks the cookie itself is
105         good enough for now
106 */
107 typedef struct _nlm_msg_res_unmatched_data {
108         int req_frame;
109         nstime_t ns;
110         int cookie_len;
111         const guint8 *cookie;
112 } nlm_msg_res_unmatched_data;
113
114 typedef struct _nlm_msg_res_matched_data {
115         int req_frame;
116         int rep_frame;
117         nstime_t ns;
118 } nlm_msg_res_matched_data;
119
120 static gboolean
121 nlm_msg_res_unmatched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
122 {
123         nlm_msg_res_unmatched_data *umd = (nlm_msg_res_unmatched_data *)value;
124
125         g_free((gpointer)umd->cookie);
126         g_free(umd);
127
128         return TRUE;
129 }
130 static gboolean
131 nlm_msg_res_matched_free_all(gpointer key_arg _U_, gpointer value, gpointer user_data _U_)
132 {
133         nlm_msg_res_matched_data *md = (nlm_msg_res_matched_data *)value;
134
135         g_free(md);
136
137         return TRUE;
138 }
139
140 static guint
141 nlm_msg_res_unmatched_hash(gconstpointer k)
142 {
143         const nlm_msg_res_unmatched_data *umd = (const nlm_msg_res_unmatched_data *)k;
144         guint8 hash=0;
145         int i;
146
147         for(i=0;i<umd->cookie_len;i++){
148                 hash^=umd->cookie[i];
149         }
150
151         return hash;
152 }
153 static guint
154 nlm_msg_res_matched_hash(gconstpointer k)
155 {
156         guint hash = GPOINTER_TO_UINT(k);
157
158         return hash;
159 }
160
161 static gint
162 nlm_msg_res_unmatched_equal(gconstpointer k1, gconstpointer k2)
163 {
164         const nlm_msg_res_unmatched_data *umd1 = (const nlm_msg_res_unmatched_data *)k1;
165         const nlm_msg_res_unmatched_data *umd2 = (const nlm_msg_res_unmatched_data *)k2;
166
167         if(umd1->cookie_len!=umd2->cookie_len){
168                 return 0;
169         }
170
171         return( memcmp(umd1->cookie, umd2->cookie, umd1->cookie_len) == 0);
172 }
173 static gint
174 nlm_msg_res_matched_equal(gconstpointer k1, gconstpointer k2)
175 {
176         guint mk1 = GPOINTER_TO_UINT(k1);
177         guint mk2 = GPOINTER_TO_UINT(k2);
178
179         return( mk1==mk2 );
180 }
181
182 static void
183 nlm_msg_res_match_init(void)
184 {
185         if(nlm_msg_res_unmatched != NULL){
186                 g_hash_table_foreach_remove(nlm_msg_res_unmatched,
187                                 nlm_msg_res_unmatched_free_all, NULL);
188         } else {
189                 nlm_msg_res_unmatched=g_hash_table_new(nlm_msg_res_unmatched_hash,
190                         nlm_msg_res_unmatched_equal);
191         }
192
193         if(nlm_msg_res_matched != NULL){
194                 g_hash_table_foreach_remove(nlm_msg_res_matched,
195                                 nlm_msg_res_matched_free_all, NULL);
196         } else {
197                 nlm_msg_res_matched=g_hash_table_new(nlm_msg_res_matched_hash,
198                         nlm_msg_res_matched_equal);
199         }
200 }
201
202 static void
203 nlm_print_msgres_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
204 {
205         nlm_msg_res_matched_data *md;
206
207         md=g_hash_table_lookup(nlm_msg_res_matched, GINT_TO_POINTER(pinfo->fd->num));
208         if(md){
209                 nstime_t ns;
210                 proto_tree_add_uint(tree, hf_nlm_request_in, tvb, 0, 0, md->req_frame);
211                 nstime_delta(&ns, &pinfo->fd->abs_ts, &md->ns);
212                 proto_tree_add_time(tree, hf_nlm_time, tvb, 0, 0, &ns);
213         }
214 }
215
216 static void
217 nlm_print_msgres_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
218 {
219         nlm_msg_res_matched_data *md;
220
221         md=g_hash_table_lookup(nlm_msg_res_matched, GINT_TO_POINTER(pinfo->fd->num));
222         if(md){
223                 proto_tree_add_uint(tree, hf_nlm_reply_in, tvb, 0, 0, md->rep_frame);
224         }
225 }
226 static void
227 nlm_match_fhandle_reply(packet_info *pinfo, proto_tree *tree)
228 {
229         nlm_msg_res_matched_data *md;
230
231         md=g_hash_table_lookup(nlm_msg_res_matched, GINT_TO_POINTER(pinfo->fd->num));
232         if(md && md->rep_frame){
233                 nfs_fhandle_data_t *fhd;
234                 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
235                         nfs_fhandle_frame_table,
236                         GINT_TO_POINTER(md->req_frame));
237                 if(fhd){
238                         dissect_fhandle_hidden(pinfo,
239                                 tree, fhd);
240                 }
241         }
242 }
243 static void
244 nlm_match_fhandle_request(packet_info *pinfo, proto_tree *tree)
245 {
246         nlm_msg_res_matched_data *md;
247
248         md=g_hash_table_lookup(nlm_msg_res_matched, GINT_TO_POINTER(pinfo->fd->num));
249         if(md && md->rep_frame){
250                 nfs_fhandle_data_t *fhd;
251                 fhd=(nfs_fhandle_data_t *)g_hash_table_lookup(
252                         nfs_fhandle_frame_table,
253                         GINT_TO_POINTER(md->rep_frame));
254                 if(fhd){
255                         dissect_fhandle_hidden(pinfo,
256                                 tree, fhd);
257                 }
258         }
259 }
260
261 static void
262 nlm_register_unmatched_res(packet_info *pinfo, tvbuff_t *tvb, int offset)
263 {
264         nlm_msg_res_unmatched_data umd;
265         nlm_msg_res_unmatched_data *old_umd;
266
267         umd.cookie_len=tvb_get_ntohl(tvb, offset);
268         umd.cookie=tvb_get_ptr(tvb, offset+4, -1);
269
270         /* have we seen this cookie before? */
271         old_umd=g_hash_table_lookup(nlm_msg_res_unmatched, (gconstpointer)&umd);
272         if(old_umd){
273                 nlm_msg_res_matched_data *md;
274
275                 md=g_malloc(sizeof(nlm_msg_res_matched_data));
276                 md->req_frame=old_umd->req_frame;
277                 md->rep_frame=pinfo->fd->num;
278                 md->ns=old_umd->ns;
279                 g_hash_table_insert(nlm_msg_res_matched, GINT_TO_POINTER(md->req_frame), (gpointer)md);
280                 g_hash_table_insert(nlm_msg_res_matched, GINT_TO_POINTER(md->rep_frame), (gpointer)md);
281
282                 g_hash_table_remove(nlm_msg_res_unmatched, (gconstpointer)old_umd);
283                 g_free((gpointer)old_umd->cookie);
284                 g_free(old_umd);
285         }
286 }
287
288 static void
289 nlm_register_unmatched_msg(packet_info *pinfo, tvbuff_t *tvb, int offset)
290 {
291         nlm_msg_res_unmatched_data *umd;
292         nlm_msg_res_unmatched_data *old_umd;
293
294         /* allocate and build the unmatched structure for this request */
295         umd=g_malloc(sizeof(nlm_msg_res_unmatched_data));
296         umd->req_frame=pinfo->fd->num;
297         umd->ns=pinfo->fd->abs_ts;
298         umd->cookie_len=tvb_get_ntohl(tvb, offset);
299         umd->cookie=tvb_memdup(tvb, offset+4, umd->cookie_len);
300
301         /* remove any old duplicates */
302         old_umd=g_hash_table_lookup(nlm_msg_res_unmatched, (gconstpointer)umd);
303         if(old_umd){
304                 g_hash_table_remove(nlm_msg_res_unmatched, (gconstpointer)old_umd);
305                 g_free((gpointer)old_umd->cookie);
306                 g_free(old_umd);
307         }
308
309         /* add new one */
310         g_hash_table_insert(nlm_msg_res_unmatched, (gpointer)umd, (gpointer)umd);
311 }
312
313
314
315
316 static const value_string names_nlm_stats[] =
317 {
318         /* NLM_GRANTED is the function number 5 and the state code 0.
319          * So we use for the state the postfix _S.
320          */
321 #define NLM_GRANTED_S           0
322                 {       NLM_GRANTED_S,  "NLM_GRANTED"   },
323 #define NLM_DENIED              1
324                 {       NLM_DENIED,     "NLM_DENIED"    },
325 #define NLM_DENIED_NOLOCKS      2
326                 {       NLM_DENIED_NOLOCKS,     "NLM_DENIED_NOLOCKS"    },
327 #define NLM_BLOCKED             3
328                 {       NLM_BLOCKED,    "NLM_BLOCKED"           },
329 #define NLM_DENIED_GRACE_PERIOD 4
330                 {       NLM_DENIED_GRACE_PERIOD,        "NLM_DENIED_GRACE_PERIOD"       },
331 #define NLM_DEADLCK             5
332                 {       NLM_DEADLCK,    "NLM_DEADLCK"   },
333 #define NLM_ROFS                6
334                 {       NLM_ROFS,       "NLM_ROFS"      },
335 #define NLM_STALE_FH            7
336                 {       NLM_STALE_FH,   "NLM_STALE_FH"  },
337 #define NLM_BIG                 8
338                 {       NLM_BIG,        "NLM_BIG"       },
339 #define NLM_FAILED              9
340                 {       NLM_FAILED,     "NLM_FAILED"    },
341                 {       0,              NULL            }
342 };
343
344
345 static const value_string names_fsh_mode[] =
346 {
347 #define FSM_DN  0
348                 {       FSM_DN,         "deny none"     },
349 #define FSM_DR  1
350                 {       FSM_DR,         "deny read"     },
351 #define FSM_DW  2
352                 {       FSM_DW,         "deny write"    },
353 #define FSM_DRW 3
354                 {       FSM_DRW,        "deny read/write"       },
355
356                 {       0,              NULL    }
357 };
358
359
360 static const value_string names_fsh_access[] =
361 {
362 #define FSA_NONE        0
363                 {       FSA_NONE,       "no access"     },
364 #define FSA_R   1
365                 {       FSA_R,          "read-only"     },
366 #define FSA_W   2
367                 {       FSA_W,          "write-only"    },
368 #define FSA_RW  3
369                 {       FSA_RW,         "read/write"    },
370                 {       0,              NULL    }
371 };
372
373
374
375
376
377
378 /* **************************** */
379 /* generic dissecting functions */
380 /* **************************** */
381 static int
382 dissect_lock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int version, int offset)
383 {
384         proto_item* lock_item = NULL;
385         proto_tree* lock_tree = NULL;
386         guint32 fh_hash, svid, start_offset=0, end_offset=0;
387
388         if (tree) {
389                 lock_item = proto_tree_add_item(tree, hf_nlm_lock, tvb,
390                                 offset, -1, FALSE);
391                 if (lock_item)
392                         lock_tree = proto_item_add_subtree(lock_item, ett_nlm_lock);
393         }
394
395         offset = dissect_rpc_string(tvb,lock_tree,
396                         hf_nlm_lock_caller_name, offset, NULL);
397         offset = dissect_nfs_fh3(tvb, offset, pinfo, lock_tree, "fh", &fh_hash);
398         if (check_col(pinfo->cinfo, COL_INFO)) {
399                 col_append_fstr(pinfo->cinfo, COL_INFO, " FH:0x%08x", fh_hash);
400         }
401
402         offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner, offset);
403
404         svid = tvb_get_ntohl(tvb, offset);
405         offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_svid, offset);
406         if (check_col(pinfo->cinfo, COL_INFO)) {
407                 col_append_fstr(pinfo->cinfo, COL_INFO, " svid:%d", svid);
408         }
409
410         if (version == 4) {
411                 start_offset = tvb_get_ntohl(tvb, offset);
412                 offset = dissect_rpc_uint64(tvb, lock_tree, hf_nlm_lock_l_offset64, offset);
413                 end_offset = tvb_get_ntohl(tvb, offset);
414                 offset = dissect_rpc_uint64(tvb, lock_tree, hf_nlm_lock_l_len64, offset);
415         }
416         else {
417                 start_offset = tvb_get_ntohl(tvb, offset);
418                 offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_l_offset, offset);
419                 end_offset = tvb_get_ntohl(tvb, offset);
420                 offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_l_len, offset);
421         }
422
423         if (check_col(pinfo->cinfo, COL_INFO)) {
424                 col_append_fstr(pinfo->cinfo, COL_INFO, " pos:%d-%d", start_offset, end_offset);
425         }
426
427         return offset;
428 }
429
430
431 static int
432 dissect_nlm_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
433     proto_tree *tree, int version)
434 {
435         if(nlm_match_msgres){
436                 rpc_call_info_value *rpc_call=pinfo->private_data;
437                 if(rpc_call->proc==6){  /* NLM_TEST_MSG */
438                         if( (!pinfo->fd->flags.visited) ){
439                                 nlm_register_unmatched_msg(pinfo, tvb, offset);
440                         } else {
441                                 nlm_print_msgres_request(pinfo, tree, tvb);
442                         }
443                         /* for the fhandle matching that finds both request and
444                            response packet */
445                         if(nfs_fhandle_reqrep_matching){
446                                 nlm_match_fhandle_request(pinfo, tree);
447                         }
448                 }
449         }
450
451         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
452         dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
453         offset += 4;
454         offset = dissect_lock(tvb, pinfo, tree, version, offset);
455         return offset;
456 }
457
458 static int
459 dissect_nlm_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
460     proto_tree *tree,int version)
461 {
462         if(nlm_match_msgres){
463                 rpc_call_info_value *rpc_call=pinfo->private_data;
464                 if(rpc_call->proc==7){  /* NLM_LOCK_MSG */
465                         if( (!pinfo->fd->flags.visited) ){
466                                 nlm_register_unmatched_msg(pinfo, tvb, offset);
467                         } else {
468                                 nlm_print_msgres_request(pinfo, tree, tvb);
469                         }
470                         /* for the fhandle matching that finds both request and
471                            response packet */
472                         if(nfs_fhandle_reqrep_matching){
473                                 nlm_match_fhandle_request(pinfo, tree);
474                         }
475                 }
476         }
477
478         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
479         offset = dissect_rpc_bool(tvb, tree, hf_nlm_block, offset);
480         offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
481         offset = dissect_lock(tvb, pinfo, tree, version, offset);
482         offset = dissect_rpc_bool(tvb, tree, hf_nlm_reclaim, offset);
483         offset = dissect_rpc_uint32(tvb, tree, hf_nlm_state, offset);
484         return offset;
485 }
486
487 static int
488 dissect_nlm_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
489     proto_tree *tree,int version)
490 {
491         if(nlm_match_msgres){
492                 rpc_call_info_value *rpc_call=pinfo->private_data;
493                 if(rpc_call->proc==8){  /* NLM_CANCEL_MSG */
494                         if( (!pinfo->fd->flags.visited) ){
495                                 nlm_register_unmatched_msg(pinfo, tvb, offset);
496                         } else {
497                                 nlm_print_msgres_request(pinfo, tree, tvb);
498                         }
499                         /* for the fhandle matching that finds both request and
500                            response packet */
501                         if(nfs_fhandle_reqrep_matching){
502                                 nlm_match_fhandle_request(pinfo, tree);
503                         }
504                 }
505         }
506
507         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
508         offset = dissect_rpc_bool(tvb, tree, hf_nlm_block, offset);
509         offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
510         offset = dissect_lock(tvb, pinfo, tree, version, offset);
511         return offset;
512 }
513
514 static int
515 dissect_nlm_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
516     proto_tree *tree,int version)
517 {
518         if(nlm_match_msgres){
519                 rpc_call_info_value *rpc_call=pinfo->private_data;
520                 if(rpc_call->proc==9){  /* NLM_UNLOCK_MSG */
521                         if( (!pinfo->fd->flags.visited) ){
522                                 nlm_register_unmatched_msg(pinfo, tvb, offset);
523                         } else {
524                                 nlm_print_msgres_request(pinfo, tree, tvb);
525                         }
526                         /* for the fhandle matching that finds both request and
527                            response packet */
528                         if(nfs_fhandle_reqrep_matching){
529                                 nlm_match_fhandle_request(pinfo, tree);
530                         }
531                 }
532         }
533
534         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
535         offset = dissect_lock(tvb, pinfo, tree, version, offset);
536         return offset;
537 }
538
539 static int
540 dissect_nlm_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
541     proto_tree *tree,int version)
542 {
543         if(nlm_match_msgres){
544                 rpc_call_info_value *rpc_call=pinfo->private_data;
545                 if(rpc_call->proc==10){ /* NLM_GRANTED_MSG */
546                         if( (!pinfo->fd->flags.visited) ){
547                                 nlm_register_unmatched_msg(pinfo, tvb, offset);
548                         } else {
549                                 nlm_print_msgres_request(pinfo, tree, tvb);
550                         }
551                         /* for the fhandle matching that finds both request and
552                            response packet */
553                         if(nfs_fhandle_reqrep_matching){
554                                 nlm_match_fhandle_request(pinfo, tree);
555                         }
556                 }
557         }
558
559         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
560         offset = dissect_rpc_bool(tvb, tree, hf_nlm_exclusive, offset);
561         offset = dissect_lock(tvb, pinfo, tree, version, offset);
562         return offset;
563 }
564
565
566 static int
567 dissect_nlm_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
568     proto_tree *tree,int version)
569 {
570         proto_item* lock_item = NULL;
571         proto_tree* lock_tree = NULL;
572
573         if(nlm_match_msgres){
574                 rpc_call_info_value *rpc_call=pinfo->private_data;
575                 if(rpc_call->proc==11){ /* NLM_TEST_RES */
576                         if( (!pinfo->fd->flags.visited) ){
577                                 nlm_register_unmatched_res(pinfo, tvb, offset);
578                         } else {
579                                 nlm_print_msgres_reply(pinfo, tree, tvb);
580                         }
581                         /* for the fhandle matching that finds both request and
582                            response packet */
583                         if(nfs_fhandle_reqrep_matching){
584                                 nlm_match_fhandle_reply(pinfo, tree);
585                         }
586                 }
587         }
588
589         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
590
591         if (tree) {
592                 lock_item = proto_tree_add_item(tree, hf_nlm_test_stat, tvb,
593                                 offset, -1, FALSE);
594                 if (lock_item)
595                         lock_tree = proto_item_add_subtree(lock_item,
596                                 ett_nlm_lock);
597         }
598
599         offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_test_stat_stat,
600             offset);
601
602         /* last structure is optional, only supplied for stat==1 (LOCKED) */
603         if(tvb_reported_length_remaining(tvb, offset) == 0){
604                 return offset;
605         }
606
607         if (tree) {
608                 lock_item = proto_tree_add_item(lock_tree, hf_nlm_holder, tvb,
609                                 offset, -1, FALSE);
610                 if (lock_item)
611                         lock_tree = proto_item_add_subtree(lock_item,
612                                 ett_nlm_lock);
613         }
614
615         offset = dissect_rpc_bool(tvb, lock_tree, hf_nlm_exclusive,
616             offset);
617         offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_lock_svid,
618             offset);
619         offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner,
620             offset);
621
622         if (version == 4) {
623                 offset = dissect_rpc_uint64(tvb, lock_tree,
624                     hf_nlm_lock_l_offset64, offset);
625                 offset = dissect_rpc_uint64(tvb, lock_tree,
626                     hf_nlm_lock_l_len64, offset);
627         }
628         else {
629                 offset = dissect_rpc_uint32(tvb, lock_tree,
630                     hf_nlm_lock_l_offset, offset);
631                 offset = dissect_rpc_uint32(tvb, lock_tree,
632                     hf_nlm_lock_l_len, offset);
633         }
634
635         return offset;
636 }
637
638
639 static int
640 dissect_nlm_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
641     proto_tree *tree,int version _U_)
642 {
643         proto_item* lock_item = NULL;
644         proto_tree* lock_tree = NULL;
645         guint32 fh_hash;
646
647         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
648
649         if (tree) {
650                 lock_item = proto_tree_add_item(tree, hf_nlm_share, tvb,
651                                 offset, -1, FALSE);
652                 if (lock_item)
653                         lock_tree = proto_item_add_subtree(lock_item,
654                                 ett_nlm_lock);
655         }
656
657         offset = dissect_rpc_string(tvb,lock_tree,
658                         hf_nlm_lock_caller_name, offset, NULL);
659
660         offset = dissect_nfs_fh3(tvb, offset, pinfo, lock_tree, "fh", &fh_hash);
661         if (check_col(pinfo->cinfo, COL_INFO)) {
662                 col_append_fstr(pinfo->cinfo, COL_INFO, " FH:0x%08x", fh_hash);
663         }
664
665         offset = dissect_rpc_data(tvb, lock_tree, hf_nlm_lock_owner, offset);
666
667         offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_share_mode, offset);
668         offset = dissect_rpc_uint32(tvb, lock_tree, hf_nlm_share_access, offset);
669
670
671         offset = dissect_rpc_bool(tvb, tree, hf_nlm_reclaim, offset);
672         return offset;
673 }
674
675 static int
676 dissect_nlm_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
677     proto_tree *tree, int version _U_)
678 {
679         guint32 nlm_stat;
680
681         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
682         nlm_stat = tvb_get_ntohl(tvb, offset);
683         if (nlm_stat && check_col(pinfo->cinfo, COL_INFO)) {
684                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
685                     val_to_str(nlm_stat, names_nlm_stats, "Unknown Status (%u)"));
686         }
687         offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
688         offset = dissect_rpc_uint32(tvb, tree, hf_nlm_sequence, offset);
689         return offset;
690 }
691
692 static int
693 dissect_nlm_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
694     proto_tree *tree,int version _U_)
695 {
696         guint32 nlm_stat;
697
698         offset = dissect_rpc_string(tvb,tree,
699                         hf_nlm_share_name, offset, NULL);
700
701         nlm_stat = tvb_get_ntohl(tvb, offset);
702         if (nlm_stat && check_col(pinfo->cinfo, COL_INFO)) {
703                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
704                     val_to_str(nlm_stat, names_nlm_stats, "Unknown Status (%u)"));
705         }
706         offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
707
708         return offset;
709 }
710
711
712 /* RPC functions */
713
714
715 /* This function is identical for all NLM protocol versions (1-4)*/
716 static int
717 dissect_nlm_gen_reply(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
718     proto_tree *tree)
719 {
720         guint32 nlm_stat;
721
722         if(nlm_match_msgres){
723                 rpc_call_info_value *rpc_call=pinfo->private_data;
724                 if((rpc_call->proc==12)  /* NLM_LOCK_RES */
725                 || (rpc_call->proc==13)  /* NLM_CANCEL_RES */
726                 || (rpc_call->proc==14)  /* NLM_UNLOCK_RES */
727                 || (rpc_call->proc==15) ){      /* NLM_GRENTED_RES */
728                         if( (!pinfo->fd->flags.visited) ){
729                                 nlm_register_unmatched_res(pinfo, tvb, offset);
730                         } else {
731                                 nlm_print_msgres_reply(pinfo, tree, tvb);
732                         }
733                         /* for the fhandle matching that finds both request and
734                            response packet */
735                         if(nfs_fhandle_reqrep_matching){
736                                 nlm_match_fhandle_reply(pinfo, tree);
737                         }
738                 }
739         }
740
741         offset = dissect_rpc_data(tvb, tree, hf_nlm_cookie, offset);
742
743         nlm_stat = tvb_get_ntohl(tvb, offset);
744         if (nlm_stat && check_col(pinfo->cinfo, COL_INFO)) {
745                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
746                     val_to_str(nlm_stat, names_nlm_stats, "Unknown Status (%u)"));
747         }
748         offset = dissect_rpc_uint32(tvb, tree, hf_nlm_stat, offset);
749         return offset;
750 }
751
752 static int
753 dissect_nlm1_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
754     proto_tree *tree)
755 {
756         return dissect_nlm_test(tvb,offset,pinfo,tree,1);
757 }
758
759 static int
760 dissect_nlm4_test(tvbuff_t *tvb, int offset, packet_info *pinfo,
761     proto_tree *tree)
762 {
763         return dissect_nlm_test(tvb,offset,pinfo,tree,4);
764 }
765
766
767 static int
768 dissect_nlm1_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
769     proto_tree *tree)
770 {
771         return dissect_nlm_lock(tvb,offset,pinfo,tree,1);
772 }
773
774 static int
775 dissect_nlm4_lock(tvbuff_t *tvb, int offset, packet_info *pinfo,
776     proto_tree *tree)
777 {
778         return dissect_nlm_lock(tvb,offset,pinfo,tree,4);
779 }
780
781
782 static int
783 dissect_nlm1_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
784     proto_tree *tree)
785 {
786         return dissect_nlm_cancel(tvb,offset,pinfo,tree,1);
787 }
788
789 static int
790 dissect_nlm4_cancel(tvbuff_t *tvb, int offset, packet_info *pinfo,
791     proto_tree *tree)
792 {
793         return dissect_nlm_cancel(tvb,offset,pinfo,tree,4);
794 }
795
796
797 static int
798 dissect_nlm1_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
799     proto_tree *tree)
800 {
801         return dissect_nlm_unlock(tvb,offset,pinfo,tree,1);
802 }
803
804 static int
805 dissect_nlm4_unlock(tvbuff_t *tvb, int offset, packet_info *pinfo,
806     proto_tree *tree)
807 {
808         return dissect_nlm_unlock(tvb,offset,pinfo,tree,4);
809 }
810
811
812 static int
813 dissect_nlm1_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
814     proto_tree *tree)
815 {
816         return dissect_nlm_granted(tvb,offset,pinfo,tree,1);
817 }
818
819 static int
820 dissect_nlm4_granted(tvbuff_t *tvb, int offset, packet_info *pinfo,
821     proto_tree *tree)
822 {
823         return dissect_nlm_granted(tvb,offset,pinfo,tree,4);
824 }
825
826
827 static int
828 dissect_nlm1_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo,
829     proto_tree *tree)
830 {
831         return dissect_nlm_test_res(tvb,offset,pinfo,tree,1);
832 }
833
834 static int
835 dissect_nlm4_test_res(tvbuff_t *tvb, int offset, packet_info *pinfo,
836     proto_tree *tree)
837 {
838         return dissect_nlm_test_res(tvb,offset,pinfo,tree,4);
839 }
840
841 static int
842 dissect_nlm3_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
843     proto_tree *tree)
844 {
845         return dissect_nlm_share(tvb,offset,pinfo,tree,3);
846 }
847
848 static int
849 dissect_nlm4_share(tvbuff_t *tvb, int offset, packet_info *pinfo,
850     proto_tree *tree)
851 {
852         return dissect_nlm_share(tvb,offset,pinfo,tree,4);
853 }
854
855 static int
856 dissect_nlm3_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo,
857     proto_tree *tree)
858 {
859         return dissect_nlm_shareres(tvb,offset,pinfo,tree,3);
860 }
861
862 static int
863 dissect_nlm4_shareres(tvbuff_t *tvb, int offset, packet_info *pinfo,
864     proto_tree *tree)
865 {
866         return dissect_nlm_shareres(tvb,offset,pinfo,tree,4);
867 }
868
869 static int
870 dissect_nlm3_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo,
871     proto_tree *tree)
872 {
873         return dissect_nlm_freeall(tvb,offset,pinfo,tree,3);
874 }
875
876 static int
877 dissect_nlm4_freeall(tvbuff_t *tvb, int offset, packet_info *pinfo,
878     proto_tree *tree)
879 {
880         return dissect_nlm_freeall(tvb,offset,pinfo,tree,4);
881 }
882
883
884
885
886 /* proc number, "proc name", dissect_request, dissect_reply */
887 /* NULL as function pointer means: type of arguments is "void". */
888 /* NLM protocol version 1 */
889 static const vsff nlm1_proc[] = {
890         { NLM_NULL,             "NULL",
891                 NULL,                           NULL },
892         { NLM_TEST,             "TEST",
893                 dissect_nlm1_test,              dissect_nlm1_test_res },
894         { NLM_LOCK,             "LOCK",
895                 dissect_nlm1_lock,              dissect_nlm_gen_reply },
896         { NLM_CANCEL,           "CANCEL",
897                 dissect_nlm1_cancel,            dissect_nlm_gen_reply },
898         { NLM_UNLOCK,           "UNLOCK",
899                 dissect_nlm1_unlock,            dissect_nlm_gen_reply },
900         { NLM_GRANTED,          "GRANTED",
901                 dissect_nlm1_granted,           dissect_nlm_gen_reply },
902         { NLM_TEST_MSG,         "TEST_MSG",
903                 dissect_nlm1_test,              NULL },
904         { NLM_LOCK_MSG,         "LOCK_MSG",
905                 dissect_nlm1_lock,              NULL },
906         { NLM_CANCEL_MSG,       "CANCEL_MSG",
907                 dissect_nlm1_cancel,            NULL },
908         { NLM_UNLOCK_MSG,       "UNLOCK_MSG",
909                 dissect_nlm1_unlock,            NULL },
910         { NLM_GRANTED_MSG,      "GRANTED_MSG",
911                 dissect_nlm1_granted,           NULL },
912         { NLM_TEST_RES,         "TEST_RES",
913                 dissect_nlm1_test_res,          NULL },
914         { NLM_LOCK_RES,         "LOCK_RES",
915                 dissect_nlm_gen_reply,          NULL },
916         { NLM_CANCEL_RES,       "CANCEL_RES",
917                 dissect_nlm_gen_reply,          NULL },
918         { NLM_UNLOCK_RES,       "UNLOCK_RES",
919                 dissect_nlm_gen_reply,          NULL },
920         { NLM_GRANTED_RES,      "GRANTED_RES",
921                 dissect_nlm_gen_reply,          NULL },
922         { 0,                    NULL,
923                 NULL,                           NULL }
924 };
925 static const value_string nlm1_proc_vals[] = {
926         { NLM_NULL,             "NULL" },
927         { NLM_TEST,             "TEST" },
928         { NLM_LOCK,             "LOCK" },
929         { NLM_CANCEL,           "CANCEL" },
930         { NLM_UNLOCK,           "UNLOCK" },
931         { NLM_GRANTED,          "GRANTED" },
932         { NLM_TEST_MSG,         "TEST_MSG" },
933         { NLM_LOCK_MSG,         "LOCK_MSG" },
934         { NLM_CANCEL_MSG,       "CANCEL_MSG" },
935         { NLM_UNLOCK_MSG,       "UNLOCK_MSG" },
936         { NLM_GRANTED_MSG,      "GRANTED_MSG" },
937         { NLM_TEST_RES,         "TEST_RES" },
938         { NLM_LOCK_RES,         "LOCK_RES" },
939         { NLM_CANCEL_RES,       "CANCEL_RES" },
940         { NLM_UNLOCK_RES,       "UNLOCK_RES" },
941         { NLM_GRANTED_RES,      "GRANTED_RES" },
942         { 0,                    NULL }
943 };
944 /* end of NLM protocol version 1 */
945
946 /* NLM protocol version 2 */
947 static const vsff nlm2_proc[] = {
948         { NLM_NULL,             "NULL",
949                 NULL,                           NULL },
950         { NLM_TEST,             "TEST",
951                 dissect_nlm1_test,              dissect_nlm1_test_res },
952         { NLM_LOCK,             "LOCK",
953                 dissect_nlm1_lock,              dissect_nlm_gen_reply },
954         { NLM_CANCEL,           "CANCEL",
955                 dissect_nlm1_cancel,            dissect_nlm_gen_reply },
956         { NLM_UNLOCK,           "UNLOCK",
957                 dissect_nlm1_unlock,            dissect_nlm_gen_reply },
958         { NLM_GRANTED,          "GRANTED",
959                 dissect_nlm1_granted,           dissect_nlm_gen_reply },
960         { NLM_TEST_MSG,         "TEST_MSG",
961                 dissect_nlm1_test,              NULL },
962         { NLM_LOCK_MSG,         "LOCK_MSG",
963                 dissect_nlm1_lock,              NULL },
964         { NLM_CANCEL_MSG,       "CANCEL_MSG",
965                 dissect_nlm1_cancel,            NULL },
966         { NLM_UNLOCK_MSG,       "UNLOCK_MSG",
967                 dissect_nlm1_unlock,            NULL },
968         { NLM_GRANTED_MSG,      "GRANTED_MSG",
969                 dissect_nlm1_granted,           NULL },
970         { NLM_TEST_RES,         "TEST_RES",
971                 dissect_nlm1_test_res,          NULL },
972         { NLM_LOCK_RES,         "LOCK_RES",
973                 dissect_nlm_gen_reply,          NULL },
974         { NLM_CANCEL_RES,       "CANCEL_RES",
975                 dissect_nlm_gen_reply,          NULL },
976         { NLM_UNLOCK_RES,       "UNLOCK_RES",
977                 dissect_nlm_gen_reply,          NULL },
978         { NLM_GRANTED_RES,      "GRANTED_RES",
979                 dissect_nlm_gen_reply,          NULL },
980         { 0,                    NULL,
981                 NULL,                           NULL }
982 };
983 static const value_string nlm2_proc_vals[] = {
984         { NLM_NULL,             "NULL" },
985         { NLM_TEST,             "TEST" },
986         { NLM_LOCK,             "LOCK" },
987         { NLM_CANCEL,           "CANCEL" },
988         { NLM_UNLOCK,           "UNLOCK" },
989         { NLM_GRANTED,          "GRANTED" },
990         { NLM_TEST_MSG,         "TEST_MSG" },
991         { NLM_LOCK_MSG,         "LOCK_MSG" },
992         { NLM_CANCEL_MSG,       "CANCEL_MSG" },
993         { NLM_UNLOCK_MSG,       "UNLOCK_MSG" },
994         { NLM_GRANTED_MSG,      "GRANTED_MSG" },
995         { NLM_TEST_RES,         "TEST_RES" },
996         { NLM_LOCK_RES,         "LOCK_RES" },
997         { NLM_CANCEL_RES,       "CANCEL_RES" },
998         { NLM_UNLOCK_RES,       "UNLOCK_RES" },
999         { NLM_GRANTED_RES,      "GRANTED_RES" },
1000         { 0,                    NULL }
1001 };
1002 /* end of NLM protocol version 2 */
1003
1004 /* NLM protocol version 3 */
1005 static const vsff nlm3_proc[] = {
1006         { NLM_NULL,             "NULL",
1007                 NULL,                           NULL },
1008         { NLM_TEST,             "TEST",
1009                 dissect_nlm1_test,              dissect_nlm1_test_res },
1010         { NLM_LOCK,             "LOCK",
1011                 dissect_nlm1_lock,              dissect_nlm_gen_reply },
1012         { NLM_CANCEL,           "CANCEL",
1013                 dissect_nlm1_cancel,            dissect_nlm_gen_reply },
1014         { NLM_UNLOCK,           "UNLOCK",
1015                 dissect_nlm1_unlock,            dissect_nlm_gen_reply },
1016         { NLM_GRANTED,          "GRANTED",
1017                 dissect_nlm1_granted,           dissect_nlm_gen_reply },
1018         { NLM_TEST_MSG,         "TEST_MSG",
1019                 dissect_nlm1_test,              NULL },
1020         { NLM_LOCK_MSG,         "LOCK_MSG",
1021                 dissect_nlm1_lock,              NULL },
1022         { NLM_CANCEL_MSG,       "CANCEL_MSG",
1023                 dissect_nlm1_cancel,            NULL },
1024         { NLM_UNLOCK_MSG,       "UNLOCK_MSG",
1025                 dissect_nlm1_unlock,            NULL },
1026         { NLM_GRANTED_MSG,      "GRANTED_MSG",
1027                 dissect_nlm1_granted,           NULL },
1028         { NLM_TEST_RES,         "TEST_RES",
1029                 dissect_nlm1_test_res,          NULL },
1030         { NLM_LOCK_RES,         "LOCK_RES",
1031                 dissect_nlm_gen_reply,          NULL },
1032         { NLM_CANCEL_RES,       "CANCEL_RES",
1033                 dissect_nlm_gen_reply,          NULL },
1034         { NLM_UNLOCK_RES,       "UNLOCK_RES",
1035                 dissect_nlm_gen_reply,          NULL },
1036         { NLM_GRANTED_RES,      "GRANTED_RES",
1037                 dissect_nlm_gen_reply,          NULL },
1038         { NLM_SHARE,            "SHARE",
1039                 dissect_nlm3_share,             dissect_nlm3_shareres },
1040         { NLM_UNSHARE,          "UNSHARE",
1041                 dissect_nlm3_share,             dissect_nlm3_shareres },
1042         { NLM_NM_LOCK,          "NM_LOCK",
1043                 dissect_nlm1_lock,              dissect_nlm_gen_reply },
1044         { NLM_FREE_ALL,         "FREE_ALL",
1045                 dissect_nlm3_freeall,           NULL },
1046         { 0,                    NULL,
1047                 NULL,                           NULL }
1048 };
1049 static const value_string nlm3_proc_vals[] = {
1050         { NLM_NULL,             "NULL" },
1051         { NLM_TEST,             "TEST" },
1052         { NLM_LOCK,             "LOCK" },
1053         { NLM_CANCEL,           "CANCEL" },
1054         { NLM_UNLOCK,           "UNLOCK" },
1055         { NLM_GRANTED,          "GRANTED" },
1056         { NLM_TEST_MSG,         "TEST_MSG" },
1057         { NLM_LOCK_MSG,         "LOCK_MSG" },
1058         { NLM_CANCEL_MSG,       "CANCEL_MSG" },
1059         { NLM_UNLOCK_MSG,       "UNLOCK_MSG" },
1060         { NLM_GRANTED_MSG,      "GRANTED_MSG" },
1061         { NLM_TEST_RES,         "TEST_RES" },
1062         { NLM_LOCK_RES,         "LOCK_RES" },
1063         { NLM_CANCEL_RES,       "CANCEL_RES" },
1064         { NLM_UNLOCK_RES,       "UNLOCK_RES" },
1065         { NLM_GRANTED_RES,      "GRANTED_RES" },
1066         { NLM_SHARE,            "SHARE" },
1067         { NLM_UNSHARE,          "UNSHARE" },
1068         { NLM_NM_LOCK,          "NM_LOCK" },
1069         { NLM_FREE_ALL,         "FREE_ALL" },
1070         { 0,                    NULL }
1071 };
1072 /* end of NLM protocol version 3 */
1073
1074
1075 /* NLM protocol version 4 */
1076 static const vsff nlm4_proc[] = {
1077         { NLM_NULL,             "NULL",
1078                 NULL,                           NULL },
1079         { NLM_TEST,             "TEST",
1080                 dissect_nlm4_test,              dissect_nlm4_test_res },
1081         { NLM_LOCK,             "LOCK",
1082                 dissect_nlm4_lock,              dissect_nlm_gen_reply },
1083         { NLM_CANCEL,           "CANCEL",
1084                 dissect_nlm4_cancel,            dissect_nlm_gen_reply },
1085         { NLM_UNLOCK,           "UNLOCK",
1086                 dissect_nlm4_unlock,            dissect_nlm_gen_reply },
1087         { NLM_GRANTED,          "GRANTED",
1088                 dissect_nlm4_granted,           dissect_nlm_gen_reply },
1089         { NLM_TEST_MSG,         "TEST_MSG",
1090                 dissect_nlm4_test,              NULL },
1091         { NLM_LOCK_MSG,         "LOCK_MSG",
1092                 dissect_nlm4_lock,              NULL },
1093         { NLM_CANCEL_MSG,       "CANCEL_MSG",
1094                 dissect_nlm4_cancel,            NULL },
1095         { NLM_UNLOCK_MSG,       "UNLOCK_MSG",
1096                 dissect_nlm4_unlock,            NULL },
1097         { NLM_GRANTED_MSG,      "GRANTED_MSG",
1098                 dissect_nlm4_granted,           NULL },
1099         { NLM_TEST_RES,         "TEST_RES",
1100                 dissect_nlm4_test_res,          NULL },
1101         { NLM_LOCK_RES,         "LOCK_RES",
1102                 dissect_nlm_gen_reply,          NULL },
1103         { NLM_CANCEL_RES,       "CANCEL_RES",
1104                 dissect_nlm_gen_reply,          NULL },
1105         { NLM_UNLOCK_RES,       "UNLOCK_RES",
1106                 dissect_nlm_gen_reply,          NULL },
1107         { NLM_GRANTED_RES,      "GRANTED_RES",
1108                 dissect_nlm_gen_reply,          NULL },
1109         { NLM_SHARE,            "SHARE",
1110                 dissect_nlm4_share,             dissect_nlm4_shareres },
1111         { NLM_UNSHARE,          "UNSHARE",
1112                 dissect_nlm4_share,             dissect_nlm4_shareres },
1113         { NLM_NM_LOCK,          "NM_LOCK",
1114                 dissect_nlm4_lock,              dissect_nlm_gen_reply },
1115         { NLM_FREE_ALL,         "FREE_ALL",
1116                 dissect_nlm4_freeall,           NULL },
1117         { 0,                    NULL,
1118                 NULL,                           NULL }
1119 };
1120 static const value_string nlm4_proc_vals[] = {
1121         { NLM_NULL,             "NULL" },
1122         { NLM_TEST,             "TEST" },
1123         { NLM_LOCK,             "LOCK" },
1124         { NLM_CANCEL,           "CANCEL" },
1125         { NLM_UNLOCK,           "UNLOCK" },
1126         { NLM_GRANTED,          "GRANTED" },
1127         { NLM_TEST_MSG,         "TEST_MSG" },
1128         { NLM_LOCK_MSG,         "LOCK_MSG" },
1129         { NLM_CANCEL_MSG,       "CANCEL_MSG" },
1130         { NLM_UNLOCK_MSG,       "UNLOCK_MSG" },
1131         { NLM_GRANTED_MSG,      "GRANTED_MSG" },
1132         { NLM_TEST_RES,         "TEST_RES" },
1133         { NLM_LOCK_RES,         "LOCK_RES" },
1134         { NLM_CANCEL_RES,       "CANCEL_RES" },
1135         { NLM_UNLOCK_RES,       "UNLOCK_RES" },
1136         { NLM_GRANTED_RES,      "GRANTED_RES" },
1137         { NLM_SHARE,            "SHARE" },
1138         { NLM_UNSHARE,          "UNSHARE" },
1139         { NLM_NM_LOCK,          "NM_LOCK" },
1140         { NLM_FREE_ALL,         "FREE_ALL" },
1141         { 0,                    NULL }
1142 };
1143 /* end of NLM protocol version 4 */
1144
1145
1146 static struct true_false_string yesno = { "Yes", "No" };
1147
1148
1149 void
1150 proto_register_nlm(void)
1151 {
1152         static hf_register_info hf[] = {
1153                 { &hf_nlm_procedure_v1, {
1154                         "V1 Procedure", "nlm.procedure_v1", FT_UINT32, BASE_DEC,
1155                         VALS(nlm1_proc_vals), 0, "V1 Procedure", HFILL }},
1156                 { &hf_nlm_procedure_v2, {
1157                         "V2 Procedure", "nlm.procedure_v2", FT_UINT32, BASE_DEC,
1158                         VALS(nlm2_proc_vals), 0, "V2 Procedure", HFILL }},
1159                 { &hf_nlm_procedure_v3, {
1160                         "V3 Procedure", "nlm.procedure_v3", FT_UINT32, BASE_DEC,
1161                         VALS(nlm3_proc_vals), 0, "V3 Procedure", HFILL }},
1162                 { &hf_nlm_procedure_v4, {
1163                         "V4 Procedure", "nlm.procedure_v4", FT_UINT32, BASE_DEC,
1164                         VALS(nlm4_proc_vals), 0, "V4 Procedure", HFILL }},
1165                 { &hf_nlm_cookie, {
1166                         "cookie", "nlm.cookie", FT_BYTES, BASE_DEC,
1167                         NULL, 0, "cookie", HFILL }},
1168                 { &hf_nlm_block, {
1169                         "block", "nlm.block", FT_BOOLEAN, BASE_NONE,
1170                         &yesno, 0, "block", HFILL }},
1171                 { &hf_nlm_exclusive, {
1172                         "exclusive", "nlm.exclusive", FT_BOOLEAN, BASE_NONE,
1173                         &yesno, 0, "exclusive", HFILL }},
1174                 { &hf_nlm_lock, {
1175                         "lock", "nlm.lock", FT_NONE, 0,
1176                         NULL, 0, "lock", HFILL }},
1177                 { &hf_nlm_lock_caller_name, {
1178                         "caller_name", "nlm.lock.caller_name", FT_STRING, BASE_NONE,
1179                         NULL, 0, "caller_name", HFILL }},
1180                 { &hf_nlm_lock_owner, {
1181                         "owner", "nlm.lock.owner", FT_BYTES, BASE_DEC,
1182                         NULL, 0, "owner", HFILL }},
1183                 { &hf_nlm_lock_svid, {
1184                         "svid", "nlm.lock.svid", FT_UINT32, BASE_DEC,
1185                         NULL, 0, "svid", HFILL }},
1186                 { &hf_nlm_lock_l_offset64, {
1187                         "l_offset", "nlm.lock.l_offset", FT_UINT64, BASE_DEC,
1188                         NULL, 0, "l_offset", HFILL }},
1189                 { &hf_nlm_lock_l_offset, {
1190                         "l_offset", "nlm.lock.l_offset", FT_UINT32, BASE_DEC,
1191                         NULL, 0, "l_offset", HFILL }},
1192                 { &hf_nlm_lock_l_len64, {
1193                         "l_len", "nlm.lock.l_len", FT_UINT64, BASE_DEC,
1194                         NULL, 0, "l_len", HFILL }},
1195                 { &hf_nlm_lock_l_len, {
1196                         "l_len", "nlm.lock.l_len", FT_UINT32, BASE_DEC,
1197                         NULL, 0, "l_len", HFILL }},
1198                 { &hf_nlm_reclaim, {
1199                         "reclaim", "nlm.reclaim", FT_BOOLEAN, BASE_NONE,
1200                         &yesno, 0, "reclaim", HFILL }},
1201                 { &hf_nlm_state, {
1202                         "state", "nlm.state", FT_UINT32, BASE_DEC,
1203                         NULL, 0, "STATD state", HFILL }},
1204                 { &hf_nlm_stat, {
1205                         "stat", "nlm.stat", FT_UINT32, BASE_DEC,
1206                         VALS(names_nlm_stats), 0, "stat", HFILL }},
1207                 { &hf_nlm_test_stat, {
1208                         "test_stat", "nlm.test_stat", FT_NONE, 0,
1209                         NULL, 0, "test_stat", HFILL }},
1210                 { &hf_nlm_test_stat_stat, {
1211                         "stat", "nlm.test_stat.stat", FT_UINT32, BASE_DEC,
1212                         VALS(names_nlm_stats), 0, "stat", HFILL }},
1213                 { &hf_nlm_holder, {
1214                         "holder", "nlm.holder", FT_NONE, 0,
1215                         NULL, 0, "holder", HFILL }},
1216                 { &hf_nlm_share, {
1217                         "share", "nlm.share", FT_NONE, 0,
1218                         NULL, 0, "share", HFILL }},
1219                 { &hf_nlm_share_mode, {
1220                         "mode", "nlm.share.mode", FT_UINT32, BASE_DEC,
1221                         VALS(names_fsh_mode), 0, "mode", HFILL }},
1222                 { &hf_nlm_share_access, {
1223                         "access", "nlm.share.access", FT_UINT32, BASE_DEC,
1224                         VALS(names_fsh_access), 0, "access", HFILL }},
1225                 { &hf_nlm_share_name, {
1226                         "name", "nlm.share.name", FT_STRING, BASE_NONE,
1227                         NULL, 0, "name", HFILL }},
1228                 { &hf_nlm_sequence, {
1229                         "sequence", "nlm.sequence", FT_INT32, BASE_DEC,
1230                         NULL, 0, "sequence", HFILL }},
1231                 { &hf_nlm_request_in, {
1232                         "Request MSG in", "nlm.msg_in", FT_UINT32, BASE_DEC,
1233                         NULL, 0, "The RES packet is a response to the MSG in this packet", HFILL }},
1234                 { &hf_nlm_reply_in, {
1235                         "Reply RES in", "nlm.res_in", FT_UINT32, BASE_DEC,
1236                         NULL, 0, "The response to this MSG packet is in this packet", HFILL }},
1237                 { &hf_nlm_time, {
1238                         "Time from request", "nlm.time", FT_RELATIVE_TIME, BASE_NONE,
1239                         NULL, 0, "Time between Request and Reply for async NLM calls", HFILL }},
1240
1241                 };
1242
1243         static gint *ett[] = {
1244                 &ett_nlm,
1245                 &ett_nlm_lock,
1246         };
1247         module_t *nlm_module;
1248
1249         proto_nlm = proto_register_protocol("Network Lock Manager Protocol",
1250             "NLM", "nlm");
1251         proto_register_field_array(proto_nlm, hf, array_length(hf));
1252         proto_register_subtree_array(ett, array_length(ett));
1253
1254         nlm_module = prefs_register_protocol(proto_nlm, NULL);
1255         prefs_register_bool_preference(nlm_module, "msg_res_matching",
1256                 "Match MSG/RES packets for async NLM",
1257                 "Whether the dissector will track and match MSG and RES calls for asynchronous NLM",
1258                 &nlm_match_msgres);
1259         register_init_routine(nlm_msg_res_match_init);
1260 }
1261
1262 void
1263 proto_reg_handoff_nlm(void)
1264 {
1265         /* Register the protocol as RPC */
1266         rpc_init_prog(proto_nlm, NLM_PROGRAM, ett_nlm);
1267         /* Register the procedure tables */
1268         rpc_init_proc_table(NLM_PROGRAM, 1, nlm1_proc, hf_nlm_procedure_v1);
1269         rpc_init_proc_table(NLM_PROGRAM, 2, nlm2_proc, hf_nlm_procedure_v2);
1270         rpc_init_proc_table(NLM_PROGRAM, 3, nlm3_proc, hf_nlm_procedure_v3);
1271         rpc_init_proc_table(NLM_PROGRAM, 4, nlm4_proc, hf_nlm_procedure_v4);
1272 }