Fix for bug 5422:
[obnox/wireshark/wip.git] / epan / dissectors / packet-fmp_notify.c
1 /* packet-fmp_notify.c
2  * Routines for fmp dissection
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.  
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33
34 #include <glib.h>
35 #include <gmodule.h>
36
37 #include <epan/strutil.h>
38
39 #include "packet-rpc.h"
40 #include "packet-fmp.h"
41
42 #define FMP_NOTIFY_PROG         1001912
43 #define FMP_NOTIFY_VERSION_2    2
44
45 /*
46  * FMP/NOTIFY Procedures
47  */
48 #define FMP_NOTIFY_DownGrade            1
49 #define FMP_NOTIFY_RevokeList           2
50 #define FMP_NOTIFY_RevokeAll            3
51 #define FMP_NOTIFY_FileSetEof           4
52 #define FMP_NOTIFY_RequestDone          5
53 #define FMP_NOTIFY_volFreeze            6
54 #define FMP_NOTIFY_revokeHandleList     7
55
56 typedef enum {
57         FMP_LIST_USER_QUOTA_EXCEEDED = 0,
58         FMP_LIST_GROUP_QUOTA_EXCEEDED = 1,
59         FMP_LIST_SERVER_RESOURCE_LOW = 2
60 } revokeHandleListReason;
61
62 static int proto_fmp_notify = -1;
63 static int hf_fmp_handleListLen = -1;
64 static int hf_fmp_notify_procedure = -1;
65 static int hf_fmp_fsID = -1;
66 static int hf_fmp_fsBlkSz = -1;
67 static int hf_fmp_sessionHandle = -1;
68 static int hf_fmp_fmpFHandle = -1;
69 static int hf_fmp_msgNum = -1;
70 static int hf_fmp_fileSize = -1;
71 static int hf_fmp_cookie = -1;
72 static int hf_fmp_firstLogBlk = -1;
73 static int hf_fmp_numBlksReq = -1;
74 static int hf_fmp_status = -1;
75
76 static int ett_fmp_notify = -1;
77 static int ett_fmp_notify_hlist = -1;
78
79 static gint ett_fmp_extList = -1;
80 static int hf_fmp_extentList_len = -1;
81 static gint ett_fmp_ext = -1;
82 static int hf_fmp_numBlks = -1;
83 static int hf_fmp_volID = -1;
84 static int hf_fmp_startOffset = -1;
85 static int hf_fmp_extent_state = -1;
86
87
88 int dissect_fmp_notify_extentList(tvbuff_t *, int, packet_info *, proto_tree *);
89
90 int
91 dissect_fmp_notify_status(tvbuff_t *tvb, int offset, proto_tree *tree, int *rval)
92 {
93         fmpStat status;
94
95         if (!tree) {
96                 return offset;
97         }
98
99         status = tvb_get_ntohl(tvb, offset);
100
101         switch (status) {
102         case FMP_OK:
103                 *rval = 0;
104                 break;
105         case FMP_IOERROR:
106                 *rval = 1;
107                 break;
108         case FMP_NOMEM:
109                 *rval = 1;
110                 break;
111         case FMP_NOACCESS:
112                 *rval = 1;
113                 break;
114          case FMP_INVALIDARG:
115                 *rval = 1;
116                 break;
117         case FMP_FSFULL:
118                 *rval = 0;
119                 break;
120         case FMP_QUEUE_FULL:
121                 *rval = 1;
122                 break;
123         case FMP_WRONG_MSG_NUM:
124                 *rval = 1;
125                 break;
126         case FMP_SESSION_LOST:
127                 *rval = 1;
128                 break;
129         case FMP_HOT_SESSION:
130                 *rval = 0;
131                 break;
132
133         case FMP_COLD_SESSION:
134                 *rval = 0;
135                 break;
136         case FMP_CLIENT_TERMINATED:
137                 *rval = 0;
138                 break;
139         case FMP_WRITER_LOST_BLK:
140                 *rval = 1;
141                 break;
142         case FMP_REQUEST_QUEUED:
143                 *rval = 0;
144                 break;
145         case FMP_FALL_BACK:
146                 *rval = 0;
147                 break;
148         case FMP_REQUEST_CANCELLED:
149                 *rval = 1;
150                 break;
151         
152                case FMP_WRITER_ZEROED_BLK:
153                 *rval = 0;
154                 break;
155         case FMP_NOTIFY_ERROR:
156                 *rval = 1;
157                 break;
158         case FMP_WRONG_HANDLE:
159                 *rval = 0;
160                 break;
161         case FMP_DUPLICATE_OPEN:
162                 *rval = 1;
163                 break;
164         case FMP_PLUGIN_NOFUNC:
165                 *rval = 1;
166                 break;
167         default:
168                 *rval = 1;
169                 break;
170         }
171
172         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_status , offset);
173         return offset;
174                                                
175 }
176
177 static int
178 dissect_revokeHandleListReason(tvbuff_t *tvb, int offset, proto_tree *tree)
179 {
180         revokeHandleListReason reason;
181
182         if (!tree) {
183                 return offset;
184         }
185
186         reason  = tvb_get_ntohl(tvb, offset);
187
188         switch (reason) {
189         case FMP_LIST_USER_QUOTA_EXCEEDED:
190                 proto_tree_add_text(tree, tvb, offset, 4, "Reason: %s",
191                                     "LIST_USER_QUOTA_EXCEEDED");
192                 break;
193
194         case FMP_LIST_GROUP_QUOTA_EXCEEDED:
195                 proto_tree_add_text(tree, tvb, offset, 4, "Reason: %s",
196                                     "LIST_GROUP_QUOTA_EXCEEDED");
197                 break;
198
199         case FMP_LIST_SERVER_RESOURCE_LOW:
200                 proto_tree_add_text(tree, tvb, offset, 4, "Reason: %s",
201                                     "LIST_SERVER_RESOURCE_LOW");
202                 break;
203
204         default:
205                 proto_tree_add_text(tree, tvb, offset, 4, "Reason: %s",
206                                     "Unknown Reason");
207                 break;
208         }
209         offset += 4;
210         return offset;
211 }
212
213 static int
214 dissect_handleList(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
215                    proto_tree *tree)
216 {
217       
218         int numHandles;
219         int listLength;
220         int i;
221         proto_item *handleListItem;
222         proto_tree *handleListTree;
223
224         if (!tree) {
225                 return offset;
226         }
227
228         numHandles = tvb_get_ntohl(tvb, offset);
229         listLength = 4; 
230
231         for (i = 0; i < numHandles; i++) {
232                 listLength += (4 + tvb_get_ntohl(tvb, offset + listLength));
233         }
234
235         handleListItem =  proto_tree_add_text(tree, tvb, offset, listLength,
236                                               "Handle List");
237         handleListTree = proto_item_add_subtree(handleListItem,
238                                                 ett_fmp_notify_hlist);
239
240         offset = dissect_rpc_uint32(tvb,  handleListTree,
241                                     hf_fmp_handleListLen, offset);
242
243         for (i = 0; i <= numHandles; i++) { 
244                 offset = dissect_rpc_data(tvb, handleListTree,
245                                           hf_fmp_fmpFHandle, offset);/*  changed */
246         }
247
248         return offset;
249
250
251 static int
252 dissect_FMP_NOTIFY_DownGrade_request(tvbuff_t *tvb, int offset,
253                                      packet_info *pinfo _U_, proto_tree *tree)
254 {
255
256
257         offset = dissect_rpc_data(tvb,  tree, hf_fmp_sessionHandle,
258                                   offset);
259         offset = dissect_rpc_data(tvb,  tree, hf_fmp_fmpFHandle, offset);
260         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_msgNum, offset);
261         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_firstLogBlk,
262                                     offset);
263         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_numBlksReq, offset);
264         return offset;
265 }
266
267 static int
268 dissect_FMP_NOTIFY_DownGrade_reply(tvbuff_t *tvb, int offset,
269                                    packet_info *pinfo _U_, proto_tree *tree)
270 {
271         int rval;
272
273         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
274         return offset;
275 }
276
277 static int
278 dissect_FMP_NOTIFY_RevokeList_request(tvbuff_t *tvb, int offset,
279                                       packet_info *pinfo _U_, proto_tree *tree)
280 {
281
282         offset = dissect_rpc_data(tvb,  tree, hf_fmp_sessionHandle,
283                                   offset);
284         offset = dissect_rpc_data(tvb, tree, hf_fmp_fmpFHandle, offset);
285         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_msgNum, offset);
286         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_firstLogBlk,
287                                     offset);
288         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_numBlksReq, offset);
289         return offset;
290 }
291
292 static int
293 dissect_FMP_NOTIFY_RevokeList_reply(tvbuff_t *tvb, int offset,
294                                     packet_info *pinfo _U_, proto_tree *tree)
295 {
296         int rval;
297
298         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
299         return offset;
300 }
301
302 static int
303 dissect_FMP_NOTIFY_RevokeAll_request(tvbuff_t *tvb, int offset,
304                                      packet_info *pinfo _U_, proto_tree *tree)
305 {
306         offset = dissect_rpc_data(tvb, tree, hf_fmp_sessionHandle,
307                                   offset);
308         offset = dissect_rpc_data(tvb, tree, hf_fmp_fmpFHandle, offset);
309         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_msgNum, offset);
310         return offset;
311 }
312
313 static int
314 dissect_FMP_NOTIFY_RevokeAll_reply(tvbuff_t *tvb, int offset,
315                                    packet_info *pinfo _U_, proto_tree *tree)
316 {
317         int rval;
318
319         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
320         return offset;
321 }
322
323 static int
324 dissect_FMP_NOTIFY_FileSetEof_request(tvbuff_t *tvb, int offset,
325                                       packet_info *pinfo _U_, proto_tree *tree)
326 {
327         offset = dissect_rpc_data(tvb, tree, hf_fmp_sessionHandle,
328                                   offset);
329         offset = dissect_rpc_data(tvb, tree, hf_fmp_fmpFHandle, offset);
330         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_msgNum, offset);
331         offset = dissect_rpc_uint64(tvb, tree, hf_fmp_fileSize, offset);
332         return offset;
333 }
334
335 static int
336 dissect_FMP_NOTIFY_FileSetEof_reply(tvbuff_t *tvb, int offset,
337                                     packet_info *pinfo _U_, proto_tree *tree)
338 {
339         int rval;
340
341         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
342         return offset;
343 }
344
345 static int
346 dissect_FMP_NOTIFY_RequestDone_request(tvbuff_t *tvb, int offset,
347                                        packet_info *pinfo, proto_tree *tree)
348 {
349         int rval;
350
351         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
352         if (rval == 0) {
353                 offset = dissect_rpc_data(tvb,  tree,
354                                           hf_fmp_sessionHandle, offset);
355                 offset = dissect_rpc_data(tvb, tree, hf_fmp_fmpFHandle,
356                                           offset);
357                 offset = dissect_rpc_uint32(tvb, tree, hf_fmp_msgNum,
358                                             offset);
359                 offset = dissect_rpc_uint32(tvb, tree, hf_fmp_cookie,
360                                             offset);
361                 offset = dissect_fmp_notify_extentList(tvb, offset, pinfo, tree);
362         }
363         return offset;
364 }
365
366 static int
367 dissect_FMP_NOTIFY_RequestDone_reply(tvbuff_t *tvb, int offset,
368                                      packet_info *pinfo _U_, proto_tree *tree)
369 {
370         int rval;
371
372         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
373         return offset;
374 }
375
376 static int
377 dissect_FMP_NOTIFY_volFreeze_request(tvbuff_t *tvb, int offset,
378                                      packet_info *pinfo _U_, proto_tree *tree)
379 {
380         offset = dissect_rpc_data(tvb, tree, hf_fmp_sessionHandle,
381                                   offset);
382         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_fsID, offset);
383         return offset;
384 }
385
386 static int
387 dissect_FMP_NOTIFY_volFreeze_reply(tvbuff_t *tvb, int offset,
388                                    packet_info *pinfo _U_, proto_tree *tree)
389 {
390         int rval;
391
392         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
393         return offset;
394 }
395
396 static int
397 dissect_FMP_NOTIFY_revokeHandleList_request(tvbuff_t *tvb, int offset,
398                                             packet_info *pinfo,
399                                             proto_tree *tree)
400 {
401         offset = dissect_rpc_data(tvb, tree, hf_fmp_sessionHandle,
402                                                                                   offset);
403         offset = dissect_revokeHandleListReason(tvb, offset, tree);
404         offset = dissect_handleList(tvb, offset, pinfo, tree);
405         return offset;
406 }
407
408 static int
409 dissect_FMP_NOTIFY_revokeHandleList_reply(tvbuff_t *tvb, int offset,
410                                           packet_info *pinfo _U_, proto_tree *tree)
411 {
412         int rval;
413         
414         offset = dissect_fmp_notify_status(tvb, offset,tree, &rval);
415         return offset;
416 }
417
418 /*
419  * proc number, "proc name", dissect_request, dissect_reply 
420  * NULL as function pointer means: type of arguments is "void".
421  */
422 static const vsff fmp_notify2_proc[] = {
423
424         { FMP_NOTIFY_DownGrade,                         "DownGrade",
425           dissect_FMP_NOTIFY_DownGrade_request,
426           dissect_FMP_NOTIFY_DownGrade_reply },
427
428         { FMP_NOTIFY_RevokeList,                        "RevokeList",
429           dissect_FMP_NOTIFY_RevokeList_request,
430           dissect_FMP_NOTIFY_RevokeList_reply },
431
432         { FMP_NOTIFY_RevokeAll,                         "RevokeAll",
433           dissect_FMP_NOTIFY_RevokeAll_request,
434           dissect_FMP_NOTIFY_RevokeAll_reply },
435
436         { FMP_NOTIFY_FileSetEof,                        "FileSetEof",
437           dissect_FMP_NOTIFY_FileSetEof_request,
438           dissect_FMP_NOTIFY_FileSetEof_reply },
439
440         { FMP_NOTIFY_RequestDone,                       "RequestDone",
441           dissect_FMP_NOTIFY_RequestDone_request,
442           dissect_FMP_NOTIFY_RequestDone_reply },
443
444         { FMP_NOTIFY_volFreeze,                         "volFreeze",
445           dissect_FMP_NOTIFY_volFreeze_request,
446           dissect_FMP_NOTIFY_volFreeze_reply },
447
448         { FMP_NOTIFY_revokeHandleList,                  "revokeHandleList",
449           dissect_FMP_NOTIFY_revokeHandleList_request,
450           dissect_FMP_NOTIFY_revokeHandleList_reply },
451
452         { 0,            NULL,           NULL,           NULL }
453 };
454
455 static const value_string fmp_notify_proc_vals[] = {
456         { 1,    "DownGrade" },
457         { 2,    "RevokeList" },
458         { 3,    "RevokeAll" },
459         { 4,    "FileSetEof" },
460         { 5,    "RequestDone" },
461         { 6,    "VolFreeze" },
462         { 7,    "RevokeHandleList" },
463         { 0,    "NULL" },
464         { 0,NULL}
465 };
466
467
468 static const value_string fmp_status_vals[] = {
469         {0,"OK"},
470         {5,"IOERROR"},
471         {12,"NOMEM"},
472         {13,"NOACCESS"},
473         {22,"INVALIDARG"},
474         {28,"FSFULL"},
475         {79,"QUEUE_FULL"},
476         {500,"WRONG_MSG_NUM"},
477         {501,"SESSION_LOST"},
478         {502,"HOT_SESSION"},
479         {503,"COLD_SESSION"},
480         {504,"CLIENT_TERMINATED"},
481         {505,"WRITER_LOST_BLK"},
482         {506,"FMP_REQUEST_QUEUED"},
483         {507,"FMP_FALL_BACK"},
484         {508,"REQUEST_CANCELLED"},
485         {509,"WRITER_ZEROED_BLK"},
486         {510,"NOTIFY_ERROR"},
487         {511,"FMP_WRONG_HANDLE"},
488         {512,"DUPLICATE_OPEN"},
489         {600,"PLUGIN_NOFUNC"},
490         {0,NULL}
491
492 };
493
494
495 void
496 proto_register_fmp_notify(void)
497 {
498         static hf_register_info hf[] = {
499                 { &hf_fmp_notify_procedure, {
500                         "Procedure", "fmp_notify.fmp_notify_procedure", FT_UINT32, BASE_DEC,
501                         VALS(fmp_notify_proc_vals) , 0, NULL, HFILL }},        /* New addition */
502         
503                 { &hf_fmp_status, {
504                         "Status", "fmp_notify.status", FT_UINT32, BASE_DEC,
505                         VALS(fmp_status_vals), 0, "Reply Status", HFILL }},
506
507
508                 { &hf_fmp_handleListLen, {
509                         "Number File Handles", "fmp_notify.handleListLength",
510                         FT_UINT32, BASE_DEC, NULL, 0,
511                         "Number of File Handles", HFILL }},
512
513
514                 { &hf_fmp_sessionHandle, {
515                         "Session Handle", "fmp_notify.sessHandle", FT_BYTES, BASE_NONE,
516                         NULL, 0, "FMP Session Handle", HFILL }},
517
518
519                 { &hf_fmp_fsID, {
520                         "File System ID", "fmp_notify.fsID", FT_UINT32, BASE_HEX,
521                         NULL, 0, NULL, HFILL }},
522
523                 { &hf_fmp_fsBlkSz, {
524                         "FS Block Size", "fmp_notify.fsBlkSz", FT_UINT32, BASE_DEC,
525                         NULL, 0, "File System Block Size", HFILL }},
526
527
528                 { &hf_fmp_numBlksReq, {
529                         "Number Blocks Requested", "fmp_notify.numBlksReq", FT_UINT32,
530                         BASE_DEC, NULL, 0, NULL, HFILL }},
531         
532
533                 { &hf_fmp_msgNum, {
534                         "Message Number", "fmp_notify.msgNum", FT_UINT32, BASE_DEC,
535                         NULL, 0, "FMP Message Number", HFILL }},
536
537                 { &hf_fmp_cookie, {
538                         "Cookie", "fmp_notify.cookie", FT_UINT32, BASE_HEX,
539                         NULL, 0, "Cookie for FMP_REQUEST_QUEUED Resp", HFILL }},
540
541
542                 { &hf_fmp_firstLogBlk, {
543                         "First Logical Block", "fmp_notify.firstLogBlk", FT_UINT32,
544                         BASE_DEC, NULL, 0, "First Logical File Block", HFILL }},
545
546                 
547                 { &hf_fmp_fileSize, {
548                         "File Size", "fmp_notify.fileSize", FT_UINT64, BASE_DEC,
549                         NULL, 0, NULL, HFILL }},
550
551                  { &hf_fmp_fmpFHandle, {
552                         "FMP File Handle", "fmp_notify.fmpFHandle",
553                         FT_BYTES, BASE_NONE, NULL, 0, NULL,
554                         HFILL }},
555
556
557
558         };
559
560         static gint *ett[] = {
561                 &ett_fmp_notify,
562                 &ett_fmp_notify_hlist,
563         };
564
565         proto_fmp_notify = 
566                 proto_register_protocol("File Mapping Protocol Nofity",
567                                         "FMP/NOTIFY", "fmp_notify");
568         proto_register_field_array(proto_fmp_notify, hf, array_length(hf));
569         proto_register_subtree_array(ett, array_length(ett));
570
571 }
572
573 void
574 proto_reg_handoff_fmp_notify(void)
575 {
576         /* Register the protocol as RPC */
577         rpc_init_prog(proto_fmp_notify, FMP_NOTIFY_PROG, ett_fmp_notify);
578
579         /* Register the procedure tables */
580         rpc_init_proc_table(FMP_NOTIFY_PROG, FMP_NOTIFY_VERSION_2,
581                             fmp_notify2_proc,hf_fmp_notify_procedure);
582 }
583
584
585 int
586 dissect_fmp_notify_extentState(tvbuff_t *tvb, int offset, proto_tree *tree)
587 {
588         extentState state;
589
590         if (!tree) {
591                 return offset;
592         }
593
594         state = tvb_get_ntohl(tvb, offset);
595         offset = dissect_rpc_uint32(tvb, tree, hf_fmp_extent_state,
596                                     offset);
597
598         return offset;
599 }
600
601 int
602 dissect_fmp_notify_extent(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
603                    proto_tree *tree, guint32 ext_num)
604 {
605         proto_item *extItem;
606         proto_tree *extTree;
607
608         if (!tree) {
609                 return offset;
610         }
611
612         extItem = proto_tree_add_text(tree, tvb, offset, 20 ,
613                                       "Extent (%u)", (guint32) ext_num);
614
615         
616         extTree = proto_item_add_subtree(extItem, ett_fmp_ext);
617
618         offset = dissect_rpc_uint32(tvb,  extTree, hf_fmp_firstLogBlk,
619                                     offset);
620         offset = dissect_rpc_uint32(tvb, extTree, hf_fmp_numBlks,
621                                     offset);
622         offset = dissect_rpc_uint32(tvb, extTree, hf_fmp_volID, offset);
623         offset = dissect_rpc_uint32(tvb, extTree, hf_fmp_startOffset,
624                                     offset);
625         offset = dissect_fmp_notify_extentState(tvb, offset, extTree);
626
627         return offset;
628 }
629
630
631 int
632 dissect_fmp_notify_extentList(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
633                        proto_tree *tree)
634 {
635         guint32 numExtents;
636         guint32 totalLength;
637         proto_item *extListItem;
638         proto_tree *extListTree;
639         guint32 i;
640
641         if (!tree) {
642                 return offset;
643         }
644
645         numExtents = tvb_get_ntohl(tvb, offset);
646         totalLength = 4 + (20 * numExtents); 
647
648         extListItem =  proto_tree_add_text(tree, tvb, offset, totalLength,
649                                            "Extent List");
650         extListTree = proto_item_add_subtree(extListItem, ett_fmp_extList);
651
652         offset = dissect_rpc_uint32(tvb, extListTree,
653                                     hf_fmp_extentList_len, offset);
654
655         for (i = 1; i <= numExtents; i++) {
656                 offset = dissect_fmp_notify_extent(tvb, offset, pinfo, extListTree, i);
657         }
658
659         return offset;
660 }