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