Jerry Talkington's changes to support, in the packet list and protocol
[obnox/wireshark/wip.git] / packet-afs.c
1 /* packet-rx.c
2  * Routines for RX packet dissection
3  * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
4  * Based on routines from tcpdump patches by
5  *   Ken Hornstein <kenh@cmf.nrl.navy.mil>
6  * Portions based on information retrieved from the RX definitions
7  *   in Arla, the free AFS client at http://www.stacken.kth.se/project/arla/
8  *
9  * $Id: packet-afs.c,v 1.9 2000/01/15 04:17:36 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@zing.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * Copied from packet-tftp.c
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <stdio.h>
37
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
40 #endif
41
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
44 #endif
45
46 #include <string.h>
47 #include <glib.h>
48 #include "packet.h"
49 #include "conversation.h"
50 #include "packet-rx.h"
51 #include "packet-afs.h"
52 #include "resolv.h"
53
54 static const value_string fs_req[] = {
55         { 130,          "fetch-data" },
56         { 131,          "fetch-acl" },
57         { 132,          "fetch-status" },
58         { 133,          "store-data" },
59         { 134,          "store-acl" },
60         { 135,          "store-status" },
61         { 136,          "remove-file" },
62         { 137,          "create-file" },
63         { 138,          "rename" },
64         { 139,          "symlink" },
65         { 140,          "link" },
66         { 141,          "makedir" },
67         { 142,          "rmdir" },
68         { 143,          "oldsetlock" },
69         { 144,          "oldextlock" },
70         { 145,          "oldrellock" },
71         { 146,          "get-stats" },
72         { 147,          "give-cbs" },
73         { 148,          "get-vlinfo" },
74         { 149,          "get-vlstats" },
75         { 150,          "set-vlstats" },
76         { 151,          "get-rootvl" },
77         { 152,          "check-token" },
78         { 153,          "get-time" },
79         { 154,          "nget-vlinfo" },
80         { 155,          "bulk-stat" },
81         { 156,          "setlock" },
82         { 157,          "extlock" },
83         { 158,          "rellock" },
84         { 159,          "xstat-ver" },
85         { 160,          "get-xstat" },
86         { 161,          "dfs-lookup" },
87         { 162,          "dfs-flushcps" },
88         { 163,          "dfs-symlink" },
89         { 0,            NULL },
90 };
91
92 static const value_string cb_req[] = {
93         { 204,          "callback" },
94         { 205,          "initcb" },
95         { 206,          "probe" },
96         { 207,          "getlock" },
97         { 208,          "getce" },
98         { 209,          "xstatver" },
99         { 210,          "getxstat" },
100         { 211,          "initcb2" },
101         { 212,          "whoareyou" },
102         { 213,          "initcb3" },
103         { 214,          "probeuuid" },
104         { 0,            NULL },
105 };
106
107 static const value_string prot_req[] = {
108         { 500,          "new-user" },
109         { 501,          "where-is-it" },
110         { 502,          "dump-entry" },
111         { 503,          "add-to-group" },
112         { 504,          "name-to-id" },
113         { 505,          "id-to-name" },
114         { 506,          "delete" },
115         { 507,          "remove-from-group" },
116         { 508,          "get-cps" },
117         { 509,          "new-entry" },
118         { 510,          "list-max" },
119         { 511,          "set-max" },
120         { 512,          "list-entry" },
121         { 513,          "change-entry" },
122         { 514,          "list-elements" },
123         { 515,          "same-mbr-of" },
124         { 516,          "set-fld-sentry" },
125         { 517,          "list-owned" },
126         { 518,          "get-cps2" },
127         { 519,          "get-host-cps" },
128         { 520,          "update-entry" },
129         { 0,            NULL },
130 };
131
132 static const value_string vldb_req[] = {
133         { 501,          "create-entry" },
134         { 502,          "delete-entry" },
135         { 503,          "get-entry-by-id" },
136         { 504,          "get-entry-by-name" },
137         { 505,          "get-new-volume-id" },
138         { 506,          "replace-entry" },
139         { 507,          "update-entry" },
140         { 508,          "setlock" },
141         { 509,          "releaselock" },
142         { 510,          "list-entry" },
143         { 511,          "list-attrib" },
144         { 512,          "linked-list" },
145         { 513,          "get-stats" },
146         { 514,          "probe" },
147         { 515,          "get-addrs" },
148         { 516,          "change-addr" },
149         { 517,          "create-entry-n" },
150         { 518,          "get-entry-by-id-n" },
151         { 519,          "get-entry-by-name-n" },
152         { 520,          "replace-entry-n" },
153         { 521,          "list-entry-n" },
154         { 522,          "list-attrib-n" },
155         { 523,          "linked-list-n" },
156         { 524,          "update-entry-by-name" },
157         { 525,          "create-entry-u" },
158         { 526,          "get-entry-by-id-u" },
159         { 527,          "get-entry-by-name-u" },
160         { 528,          "replace-entry-u" },
161         { 529,          "list-entry-u" },
162         { 530,          "list-attrib-u" },
163         { 531,          "linked-list-u" },
164         { 532,          "regaddr" },
165         { 533,          "get-addrs-u" },
166         { 0,            NULL },
167 };
168
169 static const value_string kauth_req[] = {
170         { 1,            "auth-old" },
171         { 21,           "authenticate" },
172         { 22,           "authenticate-v2" },
173         { 2,            "change-pw" },
174         { 3,            "get-ticket-old" },
175         { 23,           "get-ticket" },
176         { 4,            "set-pw" },
177         { 5,            "set-fields" },
178         { 6,            "create-user" },
179         { 7,            "delete-user" },
180         { 8,            "get-entry" },
181         { 9,            "list-entry" },
182         { 10,           "get-stats" },
183         { 11,           "debug" },
184         { 12,           "get-pw" },
185         { 13,           "get-random-key" },
186         { 14,           "unlock" },
187         { 15,           "lock-status" },
188         { 0,            NULL },
189 };
190
191 static const value_string vol_req[] = {
192         { 100,          "create-volume" },
193         { 101,          "delete-volume" },
194         { 102,          "restore" },
195         { 103,          "forward" },
196         { 104,          "end-trans" },
197         { 105,          "clone" },
198         { 106,          "set-flags" },
199         { 107,          "get-flags" },
200         { 108,          "trans-create" },
201         { 109,          "dump" },
202         { 110,          "get-nth-volume" },
203         { 111,          "set-forwarding" },
204         { 112,          "get-name" },
205         { 113,          "get-status" },
206         { 114,          "sig-restore" },
207         { 115,          "list-partitions" },
208         { 116,          "list-volumes" },
209         { 117,          "set-id-types" },
210         { 118,          "monitor" },
211         { 119,          "partition-info" },
212         { 120,          "reclone" },
213         { 121,          "list-one-volume" },
214         { 122,          "nuke" },
215         { 123,          "set-date" },
216         { 124,          "x-list-volumes" },
217         { 125,          "x-list-one-volume" },
218         { 126,          "set-info" },
219         { 127,          "x-list-partitions" },
220         { 128,          "forward-multiple" },
221         { 0,            NULL },
222 };
223
224 static const value_string bos_req[] = {
225         { 80,           "create-bnode" },
226         { 81,           "delete-bnode" },
227         { 82,           "set-status" },
228         { 83,           "get-status" },
229         { 84,           "enumerate-instance" },
230         { 85,           "get-instance-info" },
231         { 86,           "get-instance-parm" },
232         { 87,           "add-superuser" },
233         { 88,           "delete-superuser" },
234         { 89,           "list-superusers" },
235         { 90,           "list-keys" },
236         { 91,           "add-key" },
237         { 92,           "delete-key" },
238         { 93,           "set-cell-name" },
239         { 94,           "get-cell-name" },
240         { 95,           "get-cell-host" },
241         { 96,           "add-cell-host" },
242         { 97,           "delete-cell-host" },
243         { 98,           "set-t-status" },
244         { 99,           "shutdown-all" },
245         { 100,          "restart-all" },
246         { 101,          "startup-all" },
247         { 102,          "set-noauth-flag" },
248         { 103,          "re-bozo" },
249         { 104,          "restart" },
250         { 105,          "start-bozo-install" },
251         { 106,          "uninstall" },
252         { 107,          "get-dates" },
253         { 108,          "exec" },
254         { 109,          "prune" },
255         { 110,          "set-restart-time" },
256         { 111,          "get-restart-time" },
257         { 112,          "start-bozo-log" },
258         { 113,          "wait-all" },
259         { 114,          "get-instance-strings" },
260         { 0,            NULL },
261 };
262
263 static const value_string ubik_req[] = {
264         { 10000,        "vote-beacon" },
265         { 10001,        "vote-debug-old" },
266         { 10002,        "vote-sdebug-old" },
267         { 10003,        "vote-getsyncsite" },
268         { 10004,        "vote-debug" },
269         { 10005,        "vote-sdebug" },
270         { 20000,        "disk-begin" },
271         { 20001,        "disk-commit" },
272         { 20002,        "disk-lock" },
273         { 20003,        "disk-write" },
274         { 20004,        "disk-getversion" },
275         { 20005,        "disk-getfile" },
276         { 20006,        "disk-sendfile" },
277         { 20007,        "disk-abort" },
278         { 20008,        "disk-releaselocks" },
279         { 20009,        "disk-truncate" },
280         { 20010,        "disk-probe" },
281         { 20011,        "disk-writev" },
282         { 20012,        "disk-interfaceaddr" },
283         { 20013,        "disk-setversion" },
284         { 0,            NULL },
285 };
286
287 static const value_string cb_types[] = {
288         { CB_TYPE_EXCLUSIVE, "exclusive" },
289         { CB_TYPE_SHARED, "shared" },
290         { CB_TYPE_DROPPED, "dropped" },
291         { 0, NULL },
292 };
293
294 static const value_string afs_errors[] = {
295         /* VOL Errors */
296         { 363520, "ID Exists"},
297         { 363521, "IO Error"},
298         { 363522, "Name Exists"},
299         { 363523, "Create Failed"},
300         { 363524, "Entry Not Found"},
301         { 363525, "Empty"},
302         { 363526, "Entry Deleted"},
303         { 363527, "Bad Name"},
304         { 363528, "Bad Index"},
305         { 363529, "Bad Volume Type"},
306         { 363530, "Bad Partition"},
307         { 363531, "Bad Server"},
308         { 363532, "Bad Replicate Server"},
309         { 363533, "No Replicate Server"},
310         { 363534, "Duplicate Replicate Server"},
311         { 363535, "ReadWrite Volume Not Found"},
312         { 363536, "Bad Reference Count"},
313         { 363537, "Size Exceeded"},
314         { 363538, "Bad Entry"},
315         { 363539, "Bad Volume ID Bump"},
316         { 363540, "Already has edit"},
317         { 363541, "Entry Locked"},
318         { 363542, "Bad Volume Operation"},
319         { 363543, "Bad Rel Lock Type"},
320         { 363544, "Rerelease"},
321         { 363545, "Bad Server"},
322         { 363546, "Permission Denied"},
323         { 363547, "Out of Memory"},
324
325         /* KAUTH Errors */
326         { 180480, "Database Inconsistent"},
327         { 180481, "Exists"},
328         { 180482, "IO"},
329         { 180483, "Create Failed"},
330         { 180484, "noent"},
331         { 180485, "Empty"},
332         { 180486, "Bad Name"},
333         { 180487, "Bad Index"},
334         { 180488, "No auth"},
335         { 180489, "Answer too long"},
336         { 180490, "Bad Request"},
337         { 180491, "Old Interface"},
338         { 180492, "Bad Argument"},
339         { 180493, "Bad Command"},
340         { 180494, "No keys"},
341         { 180495, "Read PW"},
342         { 180496, "Bad key"},
343         { 180497, "Ubik Init"},
344         { 180498, "Ubik Call"},
345         { 180499, "Bad Protocol"},
346         { 180500, "No cells"},
347         { 180501, "No cell"},
348         { 180502, "Too many ubiks"},
349         { 180503, "Too many keys"},
350         { 180504, "Bad ticket"},
351         { 180505, "Unknown Key"},
352         { 180506, "Key Cache Invalid"},
353         { 180507, "Bad Server"},
354         { 180508, "Bad User"},
355         { 180509, "Bad CPW"},
356         { 180510, "Bad Create"},
357         { 180511, "No ticket"},
358         { 180512, "Assoc user"},
359         { 180513, "Not special"},
360         { 180514, "Clock skew too great"},
361         { 180515, "No recursion"},
362         { 180516, "RX failed"},
363         { 180517, "Null password"},
364         { 180518, "Internal error"},
365         { 180519, "Password expired"},
366         { 180520, "Reused"},
367         { 180521, "Too soon"},
368         { 180522, "Locked"},
369
370         /* PT Errors */
371         { 267264, "Exists"},
372         { 267265, "ID Exists"},
373         { 267266, "No IDs"},
374         { 267267, "DB Failed"},
375         { 267268, "No such entry"},
376         { 267269, "Permission denied"},
377         { 267270, "Not group"},
378         { 267271, "Not user"},
379         { 267272, "Bad name"},
380         { 267273, "Bad argument"},
381         { 267274, "No more"},
382         { 267275, "Bad DB"},
383         { 267276, "Group empty"},
384         { 267277, "Inconsistent"},
385         { 267278, "DB Address"},
386         { 267279, "Too many"},
387         { 267280, "No memory"},
388
389         /* Volume server errors */
390         { 1492325120, "Release error"},
391         { 1492325121, "No op"},
392         { 1492325122, "Read dump error"},
393         { 1492325123, "Dump error"},
394         { 1492325124, "Attach error"},
395         { 1492325125, "Illegal partition"},
396         { 1492325126, "Detach error"},
397         { 1492325127, "Bad access"},
398         { 1492325128, "VLDB error"},
399         { 1492325129, "Bad Name"},
400         { 1492325130, "Volume moved"},
401         { 1492325131, "Bad operation"},
402         { 1492325132, "Bad release"},
403         { 1492325133, "Volume busy"},
404         { 1492325134, "No memory"},
405         { 1492325135, "No volume"},
406         { 1492325136, "Multiple RW volumes"},
407         { 1492325137, "Failed operation"},
408         
409         /* add more of these errors to decode the errcode responses */
410         { 0, NULL },
411 };
412
413 static const value_string port_types[] = {
414         { AFS_PORT_FS, "File Server" },
415         { AFS_PORT_CB, "Callback Server" },
416         { AFS_PORT_BOS, "BOS Server" },
417         { AFS_PORT_PROT, "Protection Server" },
418         { AFS_PORT_VLDB, "Volume Location Database Server" },
419         { AFS_PORT_KAUTH, "Kerberos Authentication Server" },
420         { AFS_PORT_ERROR, "Error Server" },
421         { AFS_PORT_VOL, "Volume Server" },
422         { AFS_PORT_RMTSYS, "Rmtsys? Server" },
423         { AFS_PORT_UPDATE, "Update? Server" },
424         { AFS_PORT_BACKUP, "Backup Server" },
425         { 0, NULL }
426 };
427
428 static const value_string port_types_short[] = {
429         { AFS_PORT_FS, "FS" },
430         { AFS_PORT_CB, "CB" },
431         { AFS_PORT_BOS, "BOS" },
432         { AFS_PORT_PROT, "PROT" },
433         { AFS_PORT_VLDB, "VLDB" },
434         { AFS_PORT_KAUTH, "KAUTH" },
435         { AFS_PORT_ERROR, "ERR" },
436         { AFS_PORT_VOL, "VOL" },
437         { AFS_PORT_RMTSYS, "RMT" },
438         { AFS_PORT_UPDATE, "UPD" },
439         { AFS_PORT_BACKUP, "BKUP" },
440         { 0, NULL }
441 };
442
443 static const value_string ubik_lock_types[] = {
444         { 1,            "read" },
445         { 2,            "write" },
446         { 3,            "wait" },
447         { 0,            NULL },
448 };
449
450 static const value_string volume_types[] = {
451         { 0,            "read-write" },
452         { 1,            "read-only" },
453         { 2,            "backup" },
454         { 0,            NULL },
455 };
456
457 int afs_packet_init_count = 100;
458
459 struct afs_request_key {
460   guint32 conversation, callnumber;
461   guint16 service;
462 };
463
464 struct afs_request_val {
465   guint32 opcode;
466 };
467
468 GHashTable *afs_request_hash = NULL;
469 GMemChunk *afs_request_keys = NULL;
470 GMemChunk *afs_request_vals = NULL;
471
472 static int proto_afs = -1;
473 static int hf_afs_fs = -1;
474 static int hf_afs_cb = -1;
475 static int hf_afs_prot = -1;
476 static int hf_afs_vldb = -1;
477 static int hf_afs_kauth = -1;
478 static int hf_afs_vol = -1;
479 static int hf_afs_error = -1;
480 static int hf_afs_bos = -1;
481 static int hf_afs_update = -1;
482 static int hf_afs_rmtsys = -1;
483 static int hf_afs_ubik = -1;
484 static int hf_afs_backup = -1;
485
486 static int hf_afs_fs_opcode = -1;
487 static int hf_afs_cb_opcode = -1;
488 static int hf_afs_prot_opcode = -1;
489 static int hf_afs_vldb_opcode = -1;
490 static int hf_afs_kauth_opcode = -1;
491 static int hf_afs_vol_opcode = -1;
492 static int hf_afs_error_opcode = -1;
493 static int hf_afs_bos_opcode = -1;
494 static int hf_afs_update_opcode = -1;
495 static int hf_afs_rmtsys_opcode = -1;
496 static int hf_afs_ubik_opcode = -1;
497 static int hf_afs_backup_opcode = -1;
498
499 static int hf_afs_fs_fid_volume = -1;
500 static int hf_afs_fs_fid_vnode = -1;
501 static int hf_afs_fs_fid_uniqifier = -1;
502 static int hf_afs_fs_offset = -1;
503 static int hf_afs_fs_length = -1;
504 static int hf_afs_fs_flength = -1;
505 static int hf_afs_fs_errcode = -1;
506 static int hf_afs_fs_data = -1;
507 static int hf_afs_fs_name = -1;
508 static int hf_afs_fs_oldname = -1;
509 static int hf_afs_fs_newname = -1;
510 static int hf_afs_fs_symlink_name = -1;
511 static int hf_afs_fs_symlink_content = -1;
512 static int hf_afs_fs_volid = -1;
513 static int hf_afs_fs_volname = -1;
514 static int hf_afs_fs_timestamp = -1;
515
516 static int hf_afs_fs_acl_datasize = -1;
517 static int hf_afs_fs_acl_count_negative = -1;
518 static int hf_afs_fs_acl_count_positive = -1;
519 static int hf_afs_fs_acl_entity = -1;
520 static int hf_afs_fs_acl_r = -1;
521 static int hf_afs_fs_acl_l = -1;
522 static int hf_afs_fs_acl_i = -1;
523 static int hf_afs_fs_acl_d = -1;
524 static int hf_afs_fs_acl_w = -1;
525 static int hf_afs_fs_acl_k = -1;
526 static int hf_afs_fs_acl_a = -1;
527
528 static int hf_afs_fs_callback_version = -1;
529 static int hf_afs_fs_callback_expires = -1;
530 static int hf_afs_fs_callback_type = -1;
531
532 static int hf_afs_bos_errcode = -1;
533 static int hf_afs_bos_type = -1;
534 static int hf_afs_bos_instance = -1;
535 static int hf_afs_bos_status = -1;
536 static int hf_afs_bos_num = -1;
537 static int hf_afs_bos_size = -1;
538 static int hf_afs_bos_flags = -1;
539 static int hf_afs_bos_date = -1;
540 static int hf_afs_bos_content = -1;
541
542 static int hf_afs_vldb_errcode = -1;
543 static int hf_afs_vldb_name = -1;
544 static int hf_afs_vldb_id = -1;
545 static int hf_afs_vldb_type = -1;
546 static int hf_afs_vldb_bump = -1;
547 static int hf_afs_vldb_index = -1;
548 static int hf_afs_vldb_nextindex = -1;
549 static int hf_afs_vldb_count = -1;
550 static int hf_afs_vldb_numservers = -1;
551 static int hf_afs_vldb_server = -1;
552 static int hf_afs_vldb_serveruuid = -1;
553 static int hf_afs_vldb_partition = -1;
554 static int hf_afs_vldb_rovol = -1;
555 static int hf_afs_vldb_rwvol = -1;
556 static int hf_afs_vldb_bkvol = -1;
557
558 static int hf_afs_kauth_errcode = -1;
559 static int hf_afs_kauth_princ = -1;
560 static int hf_afs_kauth_realm = -1;
561 static int hf_afs_kauth_domain = -1;
562 static int hf_afs_kauth_kvno = -1;
563 static int hf_afs_kauth_name = -1;
564 static int hf_afs_kauth_data = -1;
565
566 static int hf_afs_vol_errcode = -1;
567 static int hf_afs_vol_count = -1;
568 static int hf_afs_vol_id = -1;
569 static int hf_afs_vol_name = -1;
570
571 static int hf_afs_cb_errcode = -1;
572 static int hf_afs_cb_callback_version = -1;
573 static int hf_afs_cb_callback_type = -1;
574 static int hf_afs_cb_callback_expires = -1;
575 static int hf_afs_cb_fid_volume = -1;
576 static int hf_afs_cb_fid_vnode = -1;
577 static int hf_afs_cb_fid_uniqifier = -1;
578
579 static int hf_afs_prot_errcode = -1;
580 static int hf_afs_prot_name = -1;
581 static int hf_afs_prot_id = -1;
582 static int hf_afs_prot_count = -1;
583 static int hf_afs_prot_oldid = -1;
584 static int hf_afs_prot_newid = -1;
585 static int hf_afs_prot_pos = -1;
586 static int hf_afs_prot_flag = -1;
587 static int hf_afs_prot_uid = -1;
588 static int hf_afs_prot_gid = -1;
589 static int hf_afs_prot_maxuid = -1;
590 static int hf_afs_prot_maxgid = -1;
591
592 static int hf_afs_backup_errcode = -1;
593
594 static int hf_afs_ubik_errcode = -1;
595 static int hf_afs_ubik_version_epoch = -1;
596 static int hf_afs_ubik_version_counter = -1;
597 static int hf_afs_ubik_votestart = -1;
598 static int hf_afs_ubik_syncsite = -1;
599 static int hf_afs_ubik_site = -1;
600 static int hf_afs_ubik_file = -1;
601 static int hf_afs_ubik_pos = -1;
602 static int hf_afs_ubik_length = -1;
603 static int hf_afs_ubik_locktype = -1;
604 static int hf_afs_ubik_voteend = -1;
605 static int hf_afs_ubik_votetype = -1;
606
607 static gint ett_afs = -1;
608 static gint ett_afs_op = -1;
609 static gint ett_afs_acl = -1;
610 static gint ett_afs_fid = -1;
611 static gint ett_afs_callback = -1;
612 static gint ett_afs_ubikver = -1;
613
614 /*
615  * Dissector prototypes
616  */
617 static void dissect_fs_request(const u_char *pd,
618         int offset, frame_data *fd, proto_tree *tree, int opcode);
619 static void dissect_fs_reply(const u_char *pd,
620         int offset, frame_data *fd, proto_tree *tree, int opcode);
621 static void dissect_cb_request(const u_char *pd,
622         int offset, frame_data *fd, proto_tree *tree, int opcode);
623 static void dissect_cb_reply(const u_char *pd,
624         int offset, frame_data *fd, proto_tree *tree, int opcode);
625 static void dissect_bos_request(const u_char *pd,
626         int offset, frame_data *fd, proto_tree *tree, int opcode);
627 static void dissect_bos_reply(const u_char *pd,
628         int offset, frame_data *fd, proto_tree *tree, int opcode);
629 static void dissect_vol_request(const u_char *pd,
630         int offset, frame_data *fd, proto_tree *tree, int opcode);
631 static void dissect_vol_reply(const u_char *pd,
632         int offset, frame_data *fd, proto_tree *tree, int opcode);
633 static void dissect_ubik_request(const u_char *pd,
634         int offset, frame_data *fd, proto_tree *tree, int opcode);
635 static void dissect_ubik_reply(const u_char *pd,
636         int offset, frame_data *fd, proto_tree *tree, int opcode);
637 static void dissect_kauth_request(const u_char *pd,
638         int offset, frame_data *fd, proto_tree *tree, int opcode);
639 static void dissect_kauth_reply(const u_char *pd,
640         int offset, frame_data *fd, proto_tree *tree, int opcode);
641 static void dissect_prot_request(const u_char *pd,
642         int offset, frame_data *fd, proto_tree *tree, int opcode);
643 static void dissect_prot_reply(const u_char *pd,
644         int offset, frame_data *fd, proto_tree *tree, int opcode);
645 static void dissect_vldb_request(const u_char *pd,
646         int offset, frame_data *fd, proto_tree *tree, int opcode);
647 static void dissect_vldb_reply(const u_char *pd,
648         int offset, frame_data *fd, proto_tree *tree, int opcode);
649 static void dissect_backup_request(const u_char *pd,
650         int offset, frame_data *fd, proto_tree *tree, int opcode);
651 static void dissect_backup_reply(const u_char *pd,
652         int offset, frame_data *fd, proto_tree *tree, int opcode);
653
654
655 /*
656  * Hash Functions - copied from packet-afs.c
657  */
658 gint
659 afs_equal(gconstpointer v, gconstpointer w)
660 {
661   struct afs_request_key *v1 = (struct afs_request_key *)v;
662   struct afs_request_key *v2 = (struct afs_request_key *)w;
663
664   if (v1 -> conversation == v2 -> conversation &&
665       v1 -> service == v2 -> service &&
666       v1 -> callnumber == v2 -> callnumber ) {
667
668     return 1;
669   }
670
671   return 0;
672 }
673
674 guint
675 afs_hash (gconstpointer v)
676 {
677         struct afs_request_key *key = (struct afs_request_key *)v;
678         guint val;
679
680         val = key -> conversation + key -> service + key -> callnumber;
681
682         return val;
683 }
684
685 /*
686  * Protocol initialization
687  */
688 static void
689 afs_init_protocol(void)
690 {
691         if (afs_request_hash)
692                 g_hash_table_destroy(afs_request_hash);
693         if (afs_request_keys)
694                 g_mem_chunk_destroy(afs_request_keys);
695         if (afs_request_vals)
696                 g_mem_chunk_destroy(afs_request_vals);
697
698         afs_request_hash = g_hash_table_new(afs_hash, afs_equal);
699         afs_request_keys = g_mem_chunk_new("afs_request_keys",
700                 sizeof(struct afs_request_key),
701                 afs_packet_init_count * sizeof(struct afs_request_key),
702                 G_ALLOC_AND_FREE);
703         afs_request_vals = g_mem_chunk_new("afs_request_vals",
704                 sizeof(struct afs_request_val),
705                 afs_packet_init_count * sizeof(struct afs_request_val),
706                 G_ALLOC_AND_FREE);
707 }
708
709
710
711 /*
712  * Dissection routines
713  */
714
715 void
716 dissect_afs(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
717 {
718         proto_tree      *afs_tree, *afs_op_tree, *ti;
719         struct rx_header *rxh;
720         struct afs_header *afsh;
721         int port, node, typenode, opcode;
722         value_string const *vals;
723         int reply = 0;
724         int doffset = 0;
725         conversation_t *conversation;
726         struct afs_request_key request_key, *new_request_key;
727         struct afs_request_val *request_val;
728         void (*dissector)(const u_char *pd, int offset,
729                 frame_data *fd, proto_tree *tree, int opcode);
730
731         rxh = (struct rx_header *) &pd[offset];
732         doffset = offset + sizeof(struct rx_header);
733         afsh = (struct afs_header *) &pd[doffset];
734
735         /* get at least a full packet structure */
736         if ( !BYTES_ARE_IN_FRAME(offset, sizeof(struct rx_header)) )
737                 return;
738
739         if (check_col(fd, COL_PROTOCOL))
740                 col_add_str(fd, COL_PROTOCOL, "AFS (RX)");
741
742         reply = (rxh->flags & RX_CLIENT_INITIATED) == 0;
743         port = ((reply == 0) ? pi.destport : pi.srcport );
744
745         /*
746          * Find out what conversation this packet is part of.
747          * XXX - this should really be done by the transport-layer protocol,
748          * although for connectionless transports, we may not want to do that
749          * unless we know some higher-level protocol will want it - or we
750          * may want to do it, so you can say e.g. "show only the packets in
751          * this UDP 'connection'".
752          *
753          * Note that we don't have to worry about the direction this packet
754          * was going - the conversation code handles that for us, treating
755          * packets from A:X to B:Y as being part of the same conversation as
756          * packets from B:Y to A:X.
757          */
758         conversation = find_conversation(&pi.src, &pi.dst, pi.ptype,
759             pi.srcport, pi.destport);
760         if (conversation == NULL) {
761                 /* It's not part of any conversation - create a new one. */
762                 conversation = conversation_new(&pi.src, &pi.dst, pi.ptype,
763                     pi.srcport, pi.destport, NULL);
764         }
765
766         request_key.conversation = conversation->index; 
767         request_key.service = pntohs(&rxh->serviceId);
768         request_key.callnumber = pntohl(&rxh->callNumber);
769
770         request_val = (struct afs_request_val *) g_hash_table_lookup(
771                 afs_request_hash, &request_key);
772
773         /* only allocate a new hash element when it's a request */
774         opcode = 0;
775         if ( !request_val && !reply)
776         {
777                 new_request_key = g_mem_chunk_alloc(afs_request_keys);
778                 *new_request_key = request_key;
779
780                 request_val = g_mem_chunk_alloc(afs_request_vals);
781                 request_val -> opcode = pntohl(&afsh->opcode);
782                 opcode = request_val->opcode;
783
784                 g_hash_table_insert(afs_request_hash, new_request_key,
785                         request_val);
786         }
787
788         if ( request_val )
789         {
790                 opcode = request_val->opcode;
791         }
792
793         node = 0;
794         typenode = 0;
795         vals = NULL;
796         dissector = NULL;
797         switch (port)
798         {
799                 case AFS_PORT_FS:
800                         typenode = hf_afs_fs;
801                         node = hf_afs_fs_opcode;
802                         vals = fs_req;
803                         dissector = reply ? dissect_fs_reply : dissect_fs_request;
804                         break;
805                 case AFS_PORT_CB:
806                         typenode = hf_afs_cb;
807                         node = hf_afs_cb_opcode;
808                         vals = cb_req;
809                         dissector = reply ? dissect_cb_reply : dissect_cb_request;
810                         break;
811                 case AFS_PORT_PROT:
812                         typenode = hf_afs_prot;
813                         node = hf_afs_prot_opcode;
814                         vals = prot_req;
815                         dissector = reply ? dissect_prot_reply : dissect_prot_request;
816                         break;
817                 case AFS_PORT_VLDB:
818                         typenode = hf_afs_vldb;
819                         node = hf_afs_vldb_opcode;
820                         vals = vldb_req;
821                         dissector = reply ? dissect_vldb_reply : dissect_vldb_request;
822                         break;
823                 case AFS_PORT_KAUTH:
824                         typenode = hf_afs_kauth;
825                         node = hf_afs_kauth_opcode;
826                         vals = kauth_req;
827                         dissector = reply ? dissect_kauth_reply : dissect_kauth_request;
828                         break;
829                 case AFS_PORT_VOL:
830                         typenode = hf_afs_vol;
831                         node = hf_afs_vol_opcode;
832                         vals = vol_req;
833                         dissector = reply ? dissect_vol_reply : dissect_vol_request;
834                         break;
835                 case AFS_PORT_ERROR:
836                         typenode = hf_afs_error;
837                         node = hf_afs_error_opcode;
838                         /* dissector = reply ? dissect_error_reply : dissect_error_request; */
839                         break;
840                 case AFS_PORT_BOS:
841                         typenode = hf_afs_bos;
842                         node = hf_afs_bos_opcode;
843                         vals = bos_req;
844                         dissector = reply ? dissect_bos_reply : dissect_bos_request;
845                         break;
846                 case AFS_PORT_UPDATE:
847                         typenode = hf_afs_update;
848                         node = hf_afs_update_opcode;
849                         /* dissector = reply ? dissect_update_reply : dissect_update_request; */
850                         break;
851                 case AFS_PORT_RMTSYS:
852                         typenode = hf_afs_rmtsys;
853                         node = hf_afs_rmtsys_opcode;
854                         /* dissector = reply ? dissect_rmtsys_reply : dissect_rmtsys_request; */
855                         break;
856                 case AFS_PORT_BACKUP:
857                         typenode = hf_afs_backup;
858                         node = hf_afs_backup_opcode;
859                         dissector = reply ? dissect_backup_reply : dissect_backup_request;
860                         break;
861         }
862         if ( (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
863                 (opcode >= DISK_LOW && opcode <= DISK_HIGH) )
864         {
865                 typenode = hf_afs_ubik;
866                 node = hf_afs_ubik_opcode;
867                 vals = ubik_req;
868                 dissector = reply ? dissect_ubik_reply : dissect_ubik_request;
869         }
870
871         if ( vals )
872         {
873                 if (check_col(fd, COL_INFO))
874                         col_add_fstr(fd, COL_INFO, "%s %s: %s (%d)",
875                         val_to_str(port, port_types_short, "Unknown(%d)"),
876                         reply ? "Reply" : "Request",
877                         val_to_str(opcode, vals, "Unknown(%d)"), opcode);
878         }
879         else
880         {
881                 if (check_col(fd, COL_INFO))
882                         col_add_fstr(fd, COL_INFO, "%s %s: Unknown(%d)",
883                         val_to_str(port, port_types_short, "Unknown(%d)"),
884                         reply ? "Reply" : "Request",
885                         opcode);
886         }
887
888         if (tree) {
889                 ti = proto_tree_add_item(tree, proto_afs, doffset, END_OF_FRAME);
890                 afs_tree = proto_item_add_subtree(ti, ett_afs);
891
892                 if ( !BYTES_ARE_IN_FRAME(offset, sizeof(struct rx_header) +
893                         sizeof(struct afs_header)) )
894                 {
895                         proto_tree_add_text(afs_tree, doffset, END_OF_FRAME,
896                                 "Service: %s %s (Truncated)",
897                                 val_to_str(port, port_types, "Unknown(%d)"),
898                                 reply ? "Reply" : "Request");
899                                 return;
900                 }
901                 else
902                 {
903                         proto_tree_add_text(afs_tree, doffset, END_OF_FRAME,
904                                 "Service: %s %s",
905                                 val_to_str(port, port_types, "Unknown(%d)"),
906                                 reply ? "Reply" : "Request");
907                 }
908
909                 /* until we do cache, can't handle replies */
910                 ti = NULL;
911                 if ( !reply && node != 0 )
912                 {
913                         ti = proto_tree_add_item(afs_tree,
914                                 node, doffset, 4, opcode);
915                 }
916                 else if ( reply && node != 0 )
917                 {
918                         /* the opcode isn't in this packet */
919                         ti = proto_tree_add_item(afs_tree,
920                                 node, doffset, 0, opcode);
921                 }
922                 else
923                 {
924                         ti = proto_tree_add_text(afs_tree,
925                                 doffset, 0, "Operation: Unknown");
926                 }
927
928                 /* Add the subtree for this particular service */
929                 afs_op_tree = proto_item_add_subtree(ti, ett_afs_op);
930
931                 if ( typenode != 0 )
932                 {
933                         /* indicate the type of request */
934                         proto_tree_add_item_hidden(afs_tree, typenode, doffset, 0, 1);
935                 }
936
937                 /* Process the packet according to what service it is */
938                 if ( dissector )
939                 {
940                         (*dissector)(pd,offset,fd,afs_op_tree,opcode);
941                 }
942         }
943
944         /* if it's the last packet, and it's a reply, remove opcode
945                 from hash */
946         /* ignoring for now, I'm not sure how the chunk deallocation works */
947         if ( rxh->flags & RX_LAST_PACKET && reply )
948         {
949
950         }
951 }
952
953 /*
954  * Macros for helper dissection routines
955  *
956  * The macros are here to save on coding. They assume that
957  * the current offset is in 'curoffset', and that the offset
958  * should be incremented after performing the macro's operation.
959  */
960
961 /* Get the next available integer, be sure and call TRUNC beforehand */
962 #define GETINT() (pntohl(&pd[curoffset]))
963
964 /* Check if enough bytes are present, if not, return to caller
965    after adding a 'Truncated' message to tree */
966 #define TRUNC(bytes) \
967         if(!BYTES_ARE_IN_FRAME(curoffset,(bytes))) \
968         { proto_tree_add_text(tree,curoffset,END_OF_FRAME,"Truncated"); \
969         return; }
970
971 /* Output a unsigned integer, stored into field 'field'
972    Assumes it is in network byte order, converts to host before using */
973 #define UINTOUT(field) \
974         TRUNC(sizeof(guint32)) \
975         proto_tree_add_item(tree,field,curoffset,sizeof(guint32), GETINT()); \
976         curoffset += 4;
977
978 /* Output a unsigned integer, stored into field 'field'
979    Assumes it is in network byte order, converts to host before using */
980 #define IPOUT(field) \
981         TRUNC(sizeof(gint32)) \
982         proto_tree_add_item(tree,field,curoffset,sizeof(gint32),\
983                 *((int*)&pd[curoffset]));\
984         curoffset += 4;
985
986 /* Output a unix timestamp, after converting to a timeval */
987 #define BIGDATEOUT(field) \
988         { struct timeval tv; \
989         TRUNC(2*sizeof(guint32)); \
990         tv.tv_sec = GETINT(); \
991         tv.tv_usec = GETINT(); \
992         proto_tree_add_item(tree,field,curoffset,2*sizeof(guint32),&tv); \
993         curoffset += 8; \
994         }
995
996 /* Output a unix timestamp, after converting to a timeval */
997 #define DATEOUT(field) \
998         { struct timeval tv; \
999         TRUNC(sizeof(guint32)); \
1000         tv.tv_sec = GETINT(); \
1001         tv.tv_usec = 0; \
1002         proto_tree_add_item(tree,field,curoffset,sizeof(guint32),&tv); \
1003         curoffset += 4; \
1004         }
1005
1006 /* Output a callback */
1007 #define FS_CALLBACKOUT() \
1008         {       proto_tree *save, *ti; \
1009                 ti = proto_tree_add_text(tree, curoffset, 3*4, "Callback"); \
1010                 save = tree; \
1011                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
1012                 TRUNC(3*sizeof(guint32)); \
1013                 UINTOUT(hf_afs_fs_callback_version); \
1014                 BIGDATEOUT(hf_afs_fs_callback_expires); \
1015                 UINTOUT(hf_afs_fs_callback_type); \
1016                 tree = save; \
1017         }
1018
1019 /* Output a callback */
1020 #define CB_CALLBACKOUT() \
1021         {       proto_tree *save, *ti; \
1022                 ti = proto_tree_add_text(tree, curoffset, 3*4, "Callback"); \
1023                 save = tree; \
1024                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
1025                 TRUNC(3*sizeof(guint32)); \
1026                 UINTOUT(hf_afs_cb_callback_version); \
1027                 DATEOUT(hf_afs_cb_callback_expires); \
1028                 UINTOUT(hf_afs_cb_callback_type); \
1029                 tree = save; \
1030         }
1031
1032
1033 /* Output a File ID */
1034 #define FS_FIDOUT(label) \
1035         {       proto_tree *save, *ti; \
1036                 ti = proto_tree_add_text(tree, curoffset, 3*4, \
1037                         "FileID (%s)", label); \
1038                 save = tree; \
1039                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
1040                 UINTOUT(hf_afs_fs_fid_volume); \
1041                 UINTOUT(hf_afs_fs_fid_vnode); \
1042                 UINTOUT(hf_afs_fs_fid_uniqifier); \
1043                 tree = save; \
1044         }
1045
1046 /* Output a File ID */
1047 #define CB_FIDOUT(label) \
1048         {       proto_tree *save, *ti; \
1049                 ti = proto_tree_add_text(tree, curoffset, 3*4, \
1050                         "FileID (%s)", label); \
1051                 save = tree; \
1052                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
1053                 UINTOUT(hf_afs_cb_fid_volume); \
1054                 UINTOUT(hf_afs_cb_fid_vnode); \
1055                 UINTOUT(hf_afs_cb_fid_uniqifier); \
1056                 tree = save; \
1057         }
1058
1059 /* Output a AFS acl */
1060 #define ACLOUT(who, positive, acl, bytes) \
1061         {       proto_tree *save, *ti; \
1062                 int tmpoffset; \
1063                 int acllen; \
1064                 char tmp[10]; \
1065                 tmp[0] = 0; \
1066                 if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
1067                 if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
1068                 if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
1069                 if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
1070                 if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
1071                 if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
1072                 if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
1073                 ti = proto_tree_add_text(tree, curoffset, bytes, \
1074                         "ACL:  %s %s%s", \
1075                         who, tmp, positive ? "" : " (negative)"); \
1076                 save = tree; \
1077                 tree = proto_item_add_subtree(ti, ett_afs_acl); \
1078                 proto_tree_add_item(tree,hf_afs_fs_acl_entity,curoffset,strlen(who), who);\
1079                 tmpoffset = curoffset + strlen(who) + 1; \
1080                 acllen = bytes - strlen(who) - 1; \
1081                 proto_tree_add_item(tree,hf_afs_fs_acl_r,tmpoffset,acllen,acl);\
1082                 proto_tree_add_item(tree,hf_afs_fs_acl_l,tmpoffset,acllen,acl);\
1083                 proto_tree_add_item(tree,hf_afs_fs_acl_i,tmpoffset,acllen,acl);\
1084                 proto_tree_add_item(tree,hf_afs_fs_acl_d,tmpoffset,acllen,acl);\
1085                 proto_tree_add_item(tree,hf_afs_fs_acl_w,tmpoffset,acllen,acl);\
1086                 proto_tree_add_item(tree,hf_afs_fs_acl_k,tmpoffset,acllen,acl);\
1087                 proto_tree_add_item(tree,hf_afs_fs_acl_a,tmpoffset,acllen,acl);\
1088                 tree = save; \
1089         }
1090
1091 /* Skip a certain number of bytes */
1092 #define SKIP(bytes) \
1093         TRUNC(bytes) \
1094         curoffset += bytes;
1095
1096 /* Raw data - to end of frame */
1097 #define RAWOUT(field) BYTESOUT(field, offset+END_OF_FRAME-curoffset)
1098
1099 /* Raw data */
1100 #define BYTESOUT(field, bytes) \
1101         TRUNC(bytes); \
1102         proto_tree_add_item(tree,field,curoffset,bytes,\
1103                 (void *)&pd[curoffset]); \
1104         curoffset += bytes;
1105
1106 /* Output a rx style string, up to a maximum length first 
1107    4 bytes - length, then char data */
1108 #define STROUT(field) \
1109         {       int i; \
1110                 TRUNC(4); \
1111                 i = pntohl(&pd[curoffset]); \
1112                 curoffset += 4; \
1113                 TRUNC(i); \
1114                 if ( i > 0 ) { \
1115                         proto_tree_add_item(tree, field, curoffset-4, i+4, \
1116                         (void *)&pd[curoffset]); \
1117                 } else { \
1118                         proto_tree_add_item(tree, field, curoffset-4, 4, \
1119                         ""); \
1120                 } \
1121                 curoffset += i; \
1122         }
1123
1124 /* Output a fixed length vectorized string (each char is a 32 bit int) */
1125 #define VECOUT(field, length) \
1126         {       char tmp[length+1]; \
1127                 int i,soff; \
1128                 soff = curoffset;\
1129                 TRUNC(length * sizeof(guint32));\
1130                 for (i=0; i<length; i++)\
1131                 {\
1132                         tmp[i] = (char) GETINT();\
1133                         curoffset += sizeof(guint32);\
1134                 }\
1135                 tmp[length] = '\0';\
1136                 proto_tree_add_item(tree, field, soff, length, tmp);\
1137         }
1138
1139 /* Output a UBIK version code */
1140 #define UBIK_VERSIONOUT(label) \
1141         {       proto_tree *save, *ti; \
1142                 unsigned int epoch,counter; \
1143                 struct timeval tv; \
1144                 TRUNC(8); \
1145                 epoch = GETINT(); \
1146                 curoffset += 4; \
1147                 counter = GETINT(); \
1148                 curoffset += 4; \
1149                 tv.tv_sec = epoch; \
1150                 tv.tv_usec = 0; \
1151                 ti = proto_tree_add_text(tree, curoffset, 3*4, \
1152                         "UBIK Version (%s): %u.%u", label, epoch, counter ); \
1153                 save = tree; \
1154                 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
1155                 proto_tree_add_item(tree,hf_afs_ubik_version_epoch,curoffset-8, \
1156                         sizeof(guint32),&tv); \
1157                 proto_tree_add_item(tree,hf_afs_ubik_version_counter,curoffset-4, \
1158                         sizeof(guint32),counter); \
1159                 tree = save; \
1160         }
1161
1162 /*
1163  * Here is a helper routine for adding an AFS acl to the proto tree
1164  * This is to be used with FS packets only
1165  *
1166  * An AFS ACL is a string that has the following format:
1167  *
1168  * <positive> <negative>
1169  * <uid1> <aclbits1>
1170  * ....
1171  *
1172  * "positive" and "negative" are integers which contain the number of
1173  * positive and negative ACL's in the string.  The uid/aclbits pair are
1174  * ASCII strings containing the UID/PTS record and and a ascii number
1175  * representing a logical OR of all the ACL permission bits
1176  */
1177
1178 static void dissect_acl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1179 {
1180         int pos, neg, acl;
1181         int n, i, bytes;
1182         u_char const *s;
1183         u_char const *end;
1184         char user[128];
1185         int curoffset;
1186         int soff,eoff;
1187
1188         curoffset = offset;
1189
1190         TRUNC(sizeof(guint32));
1191         bytes = pntohl(&pd[curoffset]);
1192         UINTOUT(hf_afs_fs_acl_datasize);
1193
1194         TRUNC(bytes);
1195
1196         soff = curoffset;
1197         eoff = curoffset+bytes;
1198
1199         s = &pd[soff];
1200         end = &pd[eoff];
1201
1202         if (sscanf((char *) s, "%d %n", &pos, &n) != 1)
1203                 return;
1204         s += n;
1205         TRUNC(1);
1206         proto_tree_add_item(tree, hf_afs_fs_acl_count_positive, curoffset, n, pos);
1207         curoffset += n;
1208
1209         if (sscanf((char *) s, "%d %n", &neg, &n) != 1)
1210                 return;
1211         s += n;
1212         TRUNC(1);
1213         proto_tree_add_item(tree, hf_afs_fs_acl_count_negative, curoffset, n, neg);
1214         curoffset += n;
1215
1216
1217         /*
1218          * This wacky order preserves the order used by the "fs" command
1219          */
1220
1221         for (i = 0; i < pos; i++) {
1222                 if (sscanf((char *) s, "%s %d %n", user, &acl, &n) != 2)
1223                         return;
1224                 s += n;
1225                 ACLOUT(user,1,acl,n);
1226                 curoffset += n;
1227                 TRUNC(1);
1228         }
1229
1230         for (i = 0; i < neg; i++) {
1231                 if (sscanf((char *) s, "%s %d %n", user, &acl, &n) != 2)
1232                         return;
1233                 s += n;
1234                 ACLOUT(user,0,acl,n);
1235                 curoffset += n;
1236                 if (s > end)
1237                         return;
1238         }
1239 }
1240
1241 /*
1242  * Here are the helper dissection routines
1243  */
1244
1245 static void
1246 dissect_fs_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1247 {
1248         struct rx_header *rxh;
1249         unsigned char *data;
1250         int doffset, curoffset;
1251
1252         rxh = (struct rx_header *) &pd[offset];
1253         data = (char *)rxh + sizeof(struct rx_header);
1254         doffset = offset + sizeof(struct rx_header);
1255         curoffset = doffset;
1256
1257         if ( rxh->type == RX_PACKET_TYPE_DATA )
1258         {
1259                 switch ( opcode )
1260                 {
1261                         case 130: /* fetch data */
1262                                 RAWOUT(hf_afs_fs_data);
1263                                 break;
1264                         case 131: /* fetch acl */
1265                                 dissect_acl(pd,curoffset,fd,tree);
1266                                 break;
1267                         case 137: /* create file */
1268                                 FS_FIDOUT("New File");
1269                                 break;
1270                         case 141: /* make dir */
1271                                 FS_FIDOUT("New Directory");
1272                                 break;
1273                         case 151: /* root volume */
1274                                 STROUT(hf_afs_fs_volname);
1275                                 break;
1276                         case 153: /* get time */
1277                                 BIGDATEOUT(hf_afs_fs_timestamp);
1278                                 break;
1279                 }
1280         }
1281         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1282         {
1283                 UINTOUT(hf_afs_fs_errcode);
1284         }
1285 }
1286
1287 static void
1288 dissect_fs_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1289 {
1290         struct rx_header *rxh;
1291         unsigned char *data;
1292         int doffset, curoffset;
1293
1294         rxh = (struct rx_header *) &pd[offset];
1295         data = (char *)rxh + sizeof(struct rx_header);
1296         doffset = offset + sizeof(struct rx_header);
1297         curoffset = doffset;
1298
1299         /* skip opcode */
1300         SKIP(sizeof(guint32));
1301
1302         switch ( opcode )
1303         {
1304                 case 130: /* Fetch data */
1305                         FS_FIDOUT("Source");
1306                         UINTOUT(hf_afs_fs_offset);
1307                         UINTOUT(hf_afs_fs_length);
1308                         break;
1309                 case 131: /* Fetch ACL */
1310                 case 132: /* Fetch Status */
1311                 case 135: /* Store Status */
1312                 case 143: /* Old Set Lock */
1313                 case 144: /* Old Extend Lock */
1314                 case 145: /* Old Release Lock */
1315                 case 156: /* Set Lock */
1316                 case 157: /* Extend Lock */
1317                 case 158: /* Release Lock */
1318                         FS_FIDOUT("Target");
1319                         break;
1320                 case 133: /* Store Data */
1321                         FS_FIDOUT("Destination");
1322                         SKIP(6*sizeof(guint32));
1323                         UINTOUT(hf_afs_fs_offset);
1324                         UINTOUT(hf_afs_fs_length);
1325                         UINTOUT(hf_afs_fs_flength);
1326                         break;
1327                 case 134: /* Store ACL */
1328                         FS_FIDOUT("Target");
1329                         dissect_acl(pd,curoffset,fd,tree);
1330                         /* print acl */
1331                         break;
1332                 case 136: /* Remove File */
1333                 case 137: /* Create File */
1334                 case 141: /* Make dir */
1335                 case 142: /* Remove dir */
1336                         FS_FIDOUT("Target");
1337                         STROUT(hf_afs_fs_name);
1338                         break;
1339                 case 138: /* Rename file */
1340                         FS_FIDOUT("Old");
1341                         STROUT(hf_afs_fs_oldname);
1342                         FS_FIDOUT("New");
1343                         STROUT(hf_afs_fs_newname);
1344                         break;
1345                 case 139: /* Symlink */
1346                         FS_FIDOUT("File");
1347                         STROUT(hf_afs_fs_symlink_name);
1348                         STROUT(hf_afs_fs_symlink_content);
1349                         break;
1350                 case 140: /* Link */
1351                         FS_FIDOUT("Link From (Old File)");
1352                         STROUT(hf_afs_fs_name);
1353                         FS_FIDOUT("Link To (New File)");
1354                         break;
1355                 case 148: /* Get vol info */
1356                         STROUT(hf_afs_fs_volname);
1357                         break;
1358                 case 149: /* Get vol stats */
1359                 case 150: /* Set vol stats */
1360                         UINTOUT(hf_afs_fs_volid);
1361                         break;
1362                 case 154: /* new get vol info */
1363                         STROUT(hf_afs_fs_volname);
1364                         break;
1365                 case 155: /* bulk stat */
1366                 {
1367                         unsigned int j,i;
1368                         TRUNC(1);
1369
1370                         j = pntohl(&pd[curoffset]);
1371                         curoffset += 1;
1372                         for (i=0; i<j; i++)
1373                         {
1374                                 FS_FIDOUT("Target");
1375                         }
1376                         break;
1377                 }
1378         }
1379 }
1380
1381 /*
1382  * BOS Helpers
1383  */
1384 static void
1385 dissect_bos_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1386 {
1387         struct rx_header *rxh;
1388         unsigned char *data;
1389         int doffset, curoffset;
1390
1391         rxh = (struct rx_header *) &pd[offset];
1392         data = (char *)rxh + sizeof(struct rx_header);
1393         doffset = offset + sizeof(struct rx_header);
1394         curoffset = doffset;
1395
1396         if ( rxh->type == RX_PACKET_TYPE_DATA )
1397         {
1398                 switch ( opcode )
1399                 {
1400                         case 85: /* get instance info */
1401                                 STROUT(hf_afs_bos_type);
1402                                 break;
1403                 }
1404         }
1405         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1406         {
1407                 UINTOUT(hf_afs_bos_errcode);
1408         }
1409 }
1410
1411 static void
1412 dissect_bos_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1413 {
1414         struct rx_header *rxh;
1415         unsigned char *data;
1416         int doffset, curoffset;
1417
1418         rxh = (struct rx_header *) &pd[offset];
1419         data = (char *)rxh + sizeof(struct rx_header);
1420         doffset = offset + sizeof(struct rx_header);
1421         curoffset = doffset;
1422
1423         /* skip opcode */
1424         SKIP(sizeof(guint32));
1425
1426         switch ( opcode )
1427         {
1428                 case 80: /* create b node */
1429                         STROUT(hf_afs_bos_type);
1430                         STROUT(hf_afs_bos_instance);
1431                         break;
1432                 case 81: /* delete b node */
1433                 case 83: /* get status */
1434                 case 85: /* get instance info */
1435                 case 87: /* add super user */
1436                 case 88: /* delete super user */
1437                 case 93: /* set cell name */
1438                 case 96: /* add cell host */
1439                 case 97: /* delete cell host */
1440                 case 104: /* restart */
1441                 case 106: /* uninstall */
1442                 case 108: /* exec */
1443                 case 112: /* get log */
1444                 case 114: /* get instance strings */
1445                         STROUT(hf_afs_bos_content);
1446                         break;
1447                 case 82: /* set status */
1448                 case 98: /* set t status */
1449                         STROUT(hf_afs_bos_content);
1450                         UINTOUT(hf_afs_bos_status);
1451                         break;
1452                 case 86: /* get instance parm */
1453                         STROUT(hf_afs_bos_instance);
1454                         UINTOUT(hf_afs_bos_num);
1455                         break;
1456                 case 84: /* enumerate instance */
1457                 case 89: /* list super users */
1458                 case 90: /* list keys */
1459                 case 91: /* add key */
1460                 case 92: /* delete key */
1461                 case 95: /* set cell host */
1462                         UINTOUT(hf_afs_bos_num);
1463                         break;
1464                 case 105: /* install */
1465                         STROUT(hf_afs_bos_content);
1466                         UINTOUT(hf_afs_bos_size);
1467                         UINTOUT(hf_afs_bos_flags);
1468                         UINTOUT(hf_afs_bos_date);
1469                         break;
1470         }
1471 }
1472
1473 /*
1474  * VOL Helpers
1475  */
1476 static void
1477 dissect_vol_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1478 {
1479         struct rx_header *rxh;
1480         unsigned char *data;
1481         int doffset, curoffset;
1482
1483         rxh = (struct rx_header *) &pd[offset];
1484         data = (char *)rxh + sizeof(struct rx_header);
1485         doffset = offset + sizeof(struct rx_header);
1486         curoffset = doffset;
1487
1488         if ( rxh->type == RX_PACKET_TYPE_DATA )
1489         {
1490                 switch ( opcode )
1491                 {
1492                         case 121:
1493                                 /* should loop here maybe */
1494                                 UINTOUT(hf_afs_vol_count);
1495                                 VECOUT(hf_afs_vol_name, 32); /* not sure on  */
1496                                 break;
1497                 }
1498         }
1499         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1500         {
1501                 UINTOUT(hf_afs_vol_errcode);
1502         }
1503 }
1504
1505 static void
1506 dissect_vol_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1507 {
1508         struct rx_header *rxh;
1509         unsigned char *data;
1510         int doffset, curoffset;
1511
1512         rxh = (struct rx_header *) &pd[offset];
1513         data = (char *)rxh + sizeof(struct rx_header);
1514         doffset = offset + sizeof(struct rx_header);
1515         curoffset = doffset;
1516
1517         /* skip opcode */
1518         SKIP(sizeof(guint32));
1519
1520         switch ( opcode )
1521         {
1522                 case 121: /* list one vol */
1523                         UINTOUT(hf_afs_vol_count);
1524                         UINTOUT(hf_afs_vol_id);
1525                         break;
1526         }
1527 }
1528
1529 /*
1530  * KAUTH Helpers
1531  */
1532 static void
1533 dissect_kauth_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1534 {
1535         struct rx_header *rxh;
1536         unsigned char *data;
1537         int doffset, curoffset;
1538
1539         rxh = (struct rx_header *) &pd[offset];
1540         data = (char *)rxh + sizeof(struct rx_header);
1541         doffset = offset + sizeof(struct rx_header);
1542         curoffset = doffset;
1543
1544         if ( rxh->type == RX_PACKET_TYPE_DATA )
1545         {
1546                 switch ( opcode )
1547                 {
1548                 }
1549         }
1550         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1551         {
1552                 UINTOUT(hf_afs_kauth_errcode);
1553         }
1554 }
1555
1556 static void
1557 dissect_kauth_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1558 {
1559         struct rx_header *rxh;
1560         unsigned char *data;
1561         int doffset, curoffset;
1562
1563         rxh = (struct rx_header *) &pd[offset];
1564         data = (char *)rxh + sizeof(struct rx_header);
1565         doffset = offset + sizeof(struct rx_header);
1566         curoffset = doffset;
1567
1568         /* skip opcode */
1569         SKIP(sizeof(guint32));
1570
1571         switch ( opcode )
1572         {
1573                 case 1: /* authenticate old */
1574                 case 21: /* authenticate */
1575                 case 22: /* authenticate v2 */
1576                 case 2: /* change pw */
1577                 case 5: /* set fields */
1578                 case 6: /* create user */
1579                 case 7: /* delete user */
1580                 case 8: /* get entry */
1581                 case 14: /* unlock */
1582                 case 15: /* lock status */
1583                         STROUT(hf_afs_kauth_princ);
1584                         STROUT(hf_afs_kauth_realm);
1585                         RAWOUT(hf_afs_kauth_data);
1586                         break;
1587                 case 3: /* getticket-old */
1588                 case 23: /* getticket */
1589                         UINTOUT(hf_afs_kauth_kvno);
1590                         STROUT(hf_afs_kauth_domain);
1591                         STROUT(hf_afs_kauth_data);
1592                         STROUT(hf_afs_kauth_princ);
1593                         STROUT(hf_afs_kauth_realm);
1594                         break;
1595                 case 4: /* set pass */
1596                         STROUT(hf_afs_kauth_princ);
1597                         STROUT(hf_afs_kauth_realm);
1598                         UINTOUT(hf_afs_kauth_kvno);
1599                         break;
1600                 case 12: /* get pass */
1601                         STROUT(hf_afs_kauth_name);
1602                         break;
1603         }
1604 }
1605
1606 /*
1607  * CB Helpers
1608  */
1609 static void
1610 dissect_cb_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1611 {
1612         struct rx_header *rxh;
1613         unsigned char *data;
1614         int doffset, curoffset;
1615
1616         rxh = (struct rx_header *) &pd[offset];
1617         data = (char *)rxh + sizeof(struct rx_header);
1618         doffset = offset + sizeof(struct rx_header);
1619         curoffset = doffset;
1620
1621         if ( rxh->type == RX_PACKET_TYPE_DATA )
1622         {
1623                 switch ( opcode )
1624                 {
1625                 }
1626         }
1627         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1628         {
1629                 UINTOUT(hf_afs_cb_errcode);
1630         }
1631 }
1632
1633 static void
1634 dissect_cb_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1635 {
1636         struct rx_header *rxh;
1637         unsigned char *data;
1638         int doffset, curoffset;
1639
1640         rxh = (struct rx_header *) &pd[offset];
1641         data = (char *)rxh + sizeof(struct rx_header);
1642         doffset = offset + sizeof(struct rx_header);
1643         curoffset = doffset;
1644
1645         /* skip opcode */
1646         SKIP(sizeof(guint32));
1647
1648         switch ( opcode )
1649         {
1650                 case 204: /* callback */
1651                 {
1652                         unsigned int i,j;
1653
1654                         TRUNC(4);
1655                         j = GETINT();
1656
1657                         for (i=0; i<j; i++)
1658                         {
1659                                 CB_FIDOUT("Target");
1660                         }
1661
1662                         TRUNC(4);
1663                         j = GETINT();
1664                         for (i=0; i<j; i++)
1665                         {
1666                                 CB_CALLBACKOUT();
1667                         }
1668                 }
1669         }
1670 }
1671
1672 /*
1673  * PROT Helpers
1674  */
1675 static void
1676 dissect_prot_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1677 {
1678         struct rx_header *rxh;
1679         unsigned char *data;
1680         int doffset, curoffset;
1681
1682         rxh = (struct rx_header *) &pd[offset];
1683         data = (char *)rxh + sizeof(struct rx_header);
1684         doffset = offset + sizeof(struct rx_header);
1685         curoffset = doffset;
1686
1687         if ( rxh->type == RX_PACKET_TYPE_DATA )
1688         {
1689                 switch ( opcode )
1690                 {
1691                         case 504: /* name to id */
1692                                 {
1693                                         unsigned int i, j;
1694
1695                                         TRUNC(4);
1696                                         j = GETINT();
1697                                         UINTOUT(hf_afs_prot_count);
1698
1699                                         for (i=0; i<j; i++)
1700                                         {
1701                                                 UINTOUT(hf_afs_prot_id);
1702                                         }
1703                                 }
1704                                 break;
1705                         case 505: /* id to name */
1706                                 {
1707                                         unsigned int i, j;
1708
1709                                         TRUNC(4);
1710                                         j = GETINT();
1711                                         UINTOUT(hf_afs_prot_count);
1712
1713                                         for (i=0; i<j; i++)
1714                                         {
1715                                                 VECOUT(hf_afs_prot_name, PRNAMEMAX);
1716                                         }
1717                                 }
1718                                 break;
1719                         case 508: /* get cps */
1720                         case 514: /* list elements */
1721                         case 517: /* list owned */
1722                         case 518: /* get cps2 */
1723                         case 519: /* get host cps */
1724                                 {
1725                                         unsigned int i, j;
1726
1727                                         TRUNC(4);
1728                                         j = GETINT();
1729                                         UINTOUT(hf_afs_prot_count);
1730
1731                                         for (i=0; i<j; i++)
1732                                         {
1733                                                 UINTOUT(hf_afs_prot_id);
1734                                         }
1735                                 }
1736                                 break;
1737                         case 510: /* list max */
1738                                 UINTOUT(hf_afs_prot_maxuid);
1739                                 UINTOUT(hf_afs_prot_maxgid);
1740                                 break;
1741                 }
1742         }
1743         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1744         {
1745                 UINTOUT(hf_afs_prot_errcode);
1746         }
1747 }
1748
1749 static void
1750 dissect_prot_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1751 {
1752         struct rx_header *rxh;
1753         unsigned char *data;
1754         int doffset, curoffset;
1755
1756         rxh = (struct rx_header *) &pd[offset];
1757         data = (char *)rxh + sizeof(struct rx_header);
1758         doffset = offset + sizeof(struct rx_header);
1759         curoffset = doffset;
1760
1761         /* skip opcode */
1762         SKIP(sizeof(guint32));
1763
1764         switch ( opcode )
1765         {
1766                 case 500: /* new user */
1767                         STROUT(hf_afs_prot_name);
1768                         UINTOUT(hf_afs_prot_id);
1769                         UINTOUT(hf_afs_prot_oldid);
1770                         break;
1771                 case 501: /* where is it */
1772                 case 506: /* delete */
1773                 case 508: /* get cps */
1774                 case 512: /* list entry */
1775                 case 514: /* list elements */
1776                 case 517: /* list owned */
1777                 case 519: /* get host cps */
1778                         UINTOUT(hf_afs_prot_id);
1779                         break;
1780                 case 502: /* dump entry */
1781                         UINTOUT(hf_afs_prot_pos);
1782                         break;
1783                 case 503: /* add to group */
1784                 case 507: /* remove from group */
1785                 case 515: /* is a member of? */
1786                         UINTOUT(hf_afs_prot_uid);
1787                         UINTOUT(hf_afs_prot_gid);
1788                         break;
1789                 case 504: /* name to id */
1790                         {
1791                                 unsigned int i, j;
1792
1793                                 TRUNC(4);
1794                                 j = GETINT();
1795                                 UINTOUT(hf_afs_prot_count);
1796
1797                                 for (i=0; i<j; i++)
1798                                 {
1799                                         VECOUT(hf_afs_prot_name,PRNAMEMAX);
1800                                 }
1801                         }
1802                         break;
1803                 case 505: /* id to name */
1804                         {
1805                                 unsigned int i, j;
1806
1807                                 TRUNC(4);
1808                                 j = GETINT();
1809                                 UINTOUT(hf_afs_prot_count);
1810
1811                                 for (i=0; i<j; i++)
1812                                 {
1813                                         UINTOUT(hf_afs_prot_id);
1814                                 }
1815                         }
1816                         break;
1817                 case 509: /* new entry */
1818                         STROUT(hf_afs_prot_name);
1819                         UINTOUT(hf_afs_prot_flag);
1820                         UINTOUT(hf_afs_prot_oldid);
1821                         break;
1822                 case 511: /* set max */
1823                         UINTOUT(hf_afs_prot_id);
1824                         UINTOUT(hf_afs_prot_flag);
1825                         break;
1826                 case 513: /* change entry */
1827                         UINTOUT(hf_afs_prot_id);
1828                         STROUT(hf_afs_prot_name);
1829                         UINTOUT(hf_afs_prot_oldid);
1830                         UINTOUT(hf_afs_prot_newid);
1831                         break;
1832                 case 520: /* update entry */
1833                         UINTOUT(hf_afs_prot_id);
1834                         STROUT(hf_afs_prot_name);
1835                         break;
1836         }
1837 }
1838
1839 /*
1840  * VLDB Helpers
1841  */
1842 static void
1843 dissect_vldb_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1844 {
1845         struct rx_header *rxh;
1846         unsigned char *data;
1847         int doffset, curoffset;
1848
1849         rxh = (struct rx_header *) &pd[offset];
1850         data = (char *)rxh + sizeof(struct rx_header);
1851         doffset = offset + sizeof(struct rx_header);
1852         curoffset = doffset;
1853
1854         if ( rxh->type == RX_PACKET_TYPE_DATA )
1855         {
1856                 switch ( opcode )
1857                 {
1858                         case 510: /* list entry */
1859                                 UINTOUT(hf_afs_vldb_count);
1860                                 UINTOUT(hf_afs_vldb_nextindex);
1861                                 break;
1862                         case 503: /* get entry by id */
1863                         case 504: /* get entry by name */
1864                                 {
1865                                         int nservers,i,j;
1866                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1867                                         TRUNC(4);
1868                                         nservers = GETINT();
1869                                         UINTOUT(hf_afs_vldb_numservers);
1870                                         for (i=0; i<8; i++)
1871                                         {
1872                                                 if ( i<nservers )
1873                                                 {
1874                                                         IPOUT(hf_afs_vldb_server);
1875                                                 }
1876                                                 else
1877                                                 {
1878                                                         SKIP(4);
1879                                                 }
1880                                         }
1881                                         for (i=0; i<8; i++)
1882                                         {
1883                                                 char part[8];
1884                                                 TRUNC(4);
1885                                                 j = GETINT();
1886                                                 strcpy(part, "/vicepa");
1887                                                 if ( i<nservers && j<=26 )
1888                                                 {
1889                                                         part[6] = (char) j;
1890                                                         proto_tree_add_item(tree, hf_afs_vldb_partition,
1891                                                                 curoffset, 4, part);
1892                                                 }
1893                                                 SKIP(4);
1894                                         }
1895                                         SKIP(8 * sizeof(guint32));
1896                                         UINTOUT(hf_afs_vldb_rwvol);
1897                                         UINTOUT(hf_afs_vldb_rovol);
1898                                         UINTOUT(hf_afs_vldb_bkvol);
1899                                 }
1900                                 break;
1901                         case 505: /* get new volume id */
1902                                 UINTOUT(hf_afs_vldb_id);
1903                                 break;
1904                         case 521: /* list entry */
1905                         case 529: /* list entry U */
1906                                 UINTOUT(hf_afs_vldb_count);
1907                                 UINTOUT(hf_afs_vldb_nextindex);
1908                                 break;
1909                         case 518: /* get entry by id n */
1910                         case 519: /* get entry by name N */
1911                                 {
1912                                         int nservers,i,j;
1913                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1914                                         TRUNC(4);
1915                                         nservers = GETINT();
1916                                         UINTOUT(hf_afs_vldb_numservers);
1917                                         for (i=0; i<13; i++)
1918                                         {
1919                                                 if ( i<nservers )
1920                                                 {
1921                                                         IPOUT(hf_afs_vldb_server);
1922                                                 }
1923                                                 else
1924                                                 {
1925                                                         SKIP(4);
1926                                                 }
1927                                         }
1928                                         for (i=0; i<13; i++)
1929                                         {
1930                                                 char part[8];
1931                                                 TRUNC(4);
1932                                                 j = GETINT();
1933                                                 strcpy(part, "/vicepa");
1934                                                 if ( i<nservers && j<=26 )
1935                                                 {
1936                                                         part[6] = (char) j;
1937                                                         proto_tree_add_item(tree, hf_afs_vldb_partition,
1938                                                                 curoffset, 4, part);
1939                                                 }
1940                                                 SKIP(4);
1941                                         }
1942                                         SKIP(13 * sizeof(guint32));
1943                                         UINTOUT(hf_afs_vldb_rwvol);
1944                                         UINTOUT(hf_afs_vldb_rovol);
1945                                         UINTOUT(hf_afs_vldb_bkvol);
1946                                 }
1947                                 break;
1948                         case 526: /* get entry by id u */
1949                         case 527: /* get entry by name u */
1950                                 {
1951                                         int nservers,i,j;
1952                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1953                                         TRUNC(4);
1954                                         nservers = GETINT();
1955                                         UINTOUT(hf_afs_vldb_numservers);
1956                                         for (i=0; i<13; i++)
1957                                         {
1958                                                 if ( i<nservers )
1959                                                 {
1960                                                         BYTESOUT(hf_afs_vldb_serveruuid, 11*sizeof(guint32));
1961                                                 }
1962                                                 else
1963                                                 {
1964                                                         SKIP(11*sizeof(guint32));
1965                                                 }
1966                                         }
1967                                         for (i=0; i<13; i++)
1968                                         {
1969                                                 char part[8];
1970                                                 TRUNC(4);
1971                                                 j = GETINT();
1972                                                 strcpy(part, "/vicepa");
1973                                                 if ( i<nservers && j<=26 )
1974                                                 {
1975                                                         part[6] = (char) j;
1976                                                         proto_tree_add_item(tree, hf_afs_vldb_partition,
1977                                                                 curoffset, 4, part);
1978                                                 }
1979                                                 SKIP(4);
1980                                         }
1981                                         SKIP(13 * sizeof(guint32));
1982                                         UINTOUT(hf_afs_vldb_rwvol);
1983                                         UINTOUT(hf_afs_vldb_rovol);
1984                                         UINTOUT(hf_afs_vldb_bkvol);
1985                                 }
1986                                 break;
1987                 }
1988         }
1989         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1990         {
1991                 UINTOUT(hf_afs_vldb_errcode);
1992         }
1993 }
1994
1995 static void
1996 dissect_vldb_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1997 {
1998         struct rx_header *rxh;
1999         unsigned char *data;
2000         int doffset, curoffset;
2001
2002         rxh = (struct rx_header *) &pd[offset];
2003         data = (char *)rxh + sizeof(struct rx_header);
2004         doffset = offset + sizeof(struct rx_header);
2005         curoffset = doffset;
2006
2007         /* skip opcode */
2008         SKIP(sizeof(guint32));
2009
2010         switch ( opcode )
2011         {
2012                 case 501: /* create new volume */
2013                 case 517: /* create entry N */
2014                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
2015                         break;
2016                 case 502: /* delete entry */
2017                 case 503: /* get entry by id */
2018                 case 507: /* update entry */
2019                 case 508: /* set lock */
2020                 case 509: /* release lock */
2021                 case 518: /* get entry by id */
2022                         UINTOUT(hf_afs_vldb_id);
2023                         UINTOUT(hf_afs_vldb_type);
2024                         break;
2025                 case 504: /* get entry by name */
2026                 case 519: /* get entry by name N */
2027                 case 524: /* update entry by name */
2028                 case 527: /* get entry by name U */
2029                         STROUT(hf_afs_vldb_name);
2030                         break;
2031                 case 505: /* get new vol id */
2032                         UINTOUT(hf_afs_vldb_bump);
2033                         break;
2034                 case 506: /* replace entry */
2035                 case 520: /* replace entry N */
2036                         UINTOUT(hf_afs_vldb_id);
2037                         UINTOUT(hf_afs_vldb_type);
2038                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
2039                         break;
2040                 case 510: /* list entry */
2041                 case 521: /* list entry N */
2042                         UINTOUT(hf_afs_vldb_index);
2043                         break;
2044         }
2045 }
2046
2047 /*
2048  * UBIK Helpers
2049  */
2050 static void
2051 dissect_ubik_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2052 {
2053         struct rx_header *rxh;
2054         unsigned char *data;
2055         int doffset, curoffset;
2056
2057         rxh = (struct rx_header *) &pd[offset];
2058         data = (char *)rxh + sizeof(struct rx_header);
2059         doffset = offset + sizeof(struct rx_header);
2060         curoffset = doffset;
2061
2062         if ( rxh->type == RX_PACKET_TYPE_DATA )
2063         {
2064                 switch ( opcode )
2065                 {
2066                         case 10000: /* beacon */
2067                                 proto_tree_add_item(tree,hf_afs_ubik_votetype,0,0,0);
2068                                 break;
2069                         case 20004: /* get version */
2070                                 UBIK_VERSIONOUT("DB Version");
2071                                 break;
2072                 }
2073         }
2074         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
2075         {
2076                 switch ( opcode )
2077                 {
2078                         case 10000:
2079                                 proto_tree_add_item(tree,hf_afs_ubik_votetype,0,0,1);
2080                                 DATEOUT(hf_afs_ubik_voteend);
2081                                 break;
2082                         default:
2083                                 UINTOUT(hf_afs_ubik_errcode);
2084                                 break;
2085                 }
2086         }
2087 }
2088
2089 static void
2090 dissect_ubik_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2091 {
2092         struct rx_header *rxh;
2093         unsigned char *data;
2094         int doffset, curoffset;
2095
2096         rxh = (struct rx_header *) &pd[offset];
2097         data = (char *)rxh + sizeof(struct rx_header);
2098         doffset = offset + sizeof(struct rx_header);
2099         curoffset = doffset;
2100
2101         /* skip opcode */
2102         SKIP(sizeof(guint32));
2103
2104         switch ( opcode )
2105         {
2106                 case 10000: /* beacon */
2107                         UINTOUT(hf_afs_ubik_syncsite);
2108                         DATEOUT(hf_afs_ubik_votestart);
2109                         UBIK_VERSIONOUT("DB Version");
2110                         UBIK_VERSIONOUT("TID");
2111                         break;
2112                 case 10003: /* get sync site */
2113                         IPOUT(hf_afs_ubik_site);
2114                         break;
2115                 case 20000: /* begin */
2116                 case 20001: /* commit */
2117                 case 20007: /* abort */
2118                 case 20008: /* release locks */
2119                 case 20010: /* writev */
2120                         UBIK_VERSIONOUT("TID");
2121                         break;
2122                 case 20002: /* lock */
2123                         UBIK_VERSIONOUT("TID");
2124                         UINTOUT(hf_afs_ubik_file);
2125                         UINTOUT(hf_afs_ubik_pos);
2126                         UINTOUT(hf_afs_ubik_length);
2127                         UINTOUT(hf_afs_ubik_locktype);
2128                         break;
2129                 case 20003: /* write */
2130                         UBIK_VERSIONOUT("TID");
2131                         UINTOUT(hf_afs_ubik_file);
2132                         UINTOUT(hf_afs_ubik_pos);
2133                         break;
2134                 case 20005: /* get file */
2135                         UINTOUT(hf_afs_ubik_file);
2136                         break;
2137                 case 20006: /* send file */
2138                         UINTOUT(hf_afs_ubik_file);
2139                         UINTOUT(hf_afs_ubik_length);
2140                         UBIK_VERSIONOUT("DB Version");
2141                         break;
2142                 case 20009: /* truncate */
2143                         UBIK_VERSIONOUT("TID");
2144                         UINTOUT(hf_afs_ubik_file);
2145                         UINTOUT(hf_afs_ubik_length);
2146                         break;
2147                 case 20012: /* set version */
2148                         UBIK_VERSIONOUT("TID");
2149                         UBIK_VERSIONOUT("Old DB Version");
2150                         UBIK_VERSIONOUT("New DB Version");
2151                         break;
2152         }
2153 }
2154
2155 /*
2156  * BACKUP Helpers
2157  */
2158 static void
2159 dissect_backup_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2160 {
2161         struct rx_header *rxh;
2162         unsigned char *data;
2163         int doffset, curoffset;
2164
2165         rxh = (struct rx_header *) &pd[offset];
2166         data = (char *)rxh + sizeof(struct rx_header);
2167         doffset = offset + sizeof(struct rx_header);
2168         curoffset = doffset;
2169
2170         if ( rxh->type == RX_PACKET_TYPE_DATA )
2171         {
2172                 switch ( opcode )
2173                 {
2174                 }
2175         }
2176         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
2177         {
2178                 UINTOUT(hf_afs_backup_errcode);
2179         }
2180 }
2181
2182 static void
2183 dissect_backup_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2184 {
2185         struct rx_header *rxh;
2186         unsigned char *data;
2187         int doffset, curoffset;
2188
2189         rxh = (struct rx_header *) &pd[offset];
2190         data = (char *)rxh + sizeof(struct rx_header);
2191         doffset = offset + sizeof(struct rx_header);
2192         curoffset = doffset;
2193
2194         /* skip opcode */
2195         SKIP(sizeof(guint32));
2196
2197         switch ( opcode )
2198         {
2199         }
2200 }
2201
2202 /*
2203  * Registration code for registering the protocol and fields
2204  */
2205
2206 void
2207 proto_register_afs(void)
2208 {
2209         static hf_register_info hf[] = {
2210
2211                 { &hf_afs_fs, {
2212                         "File Server", "afs.fs", FT_BOOLEAN, BASE_NONE,
2213                         0, 0, "File Server" }},
2214                 { &hf_afs_cb, {
2215                         "Callback", "afs.cb", FT_BOOLEAN, BASE_NONE,
2216                         0, 0, "Callback" }},
2217                 { &hf_afs_prot, {
2218                         "Protection", "afs.prot", FT_BOOLEAN, BASE_NONE,
2219                         0, 0, "Protection" }},
2220                 { &hf_afs_vldb, {
2221                         "VLDB", "afs.vldb", FT_BOOLEAN, BASE_NONE,
2222                         0, 0, "VLDB" }},
2223                 { &hf_afs_kauth, {
2224                         "Kauth", "afs.kauth", FT_BOOLEAN, BASE_NONE,
2225                         0, 0, "Kauth" }},
2226                 { &hf_afs_vol, {
2227                         "Volume Server", "afs.vol", FT_BOOLEAN, BASE_NONE,
2228                         0, 0, "Volume Server" }},
2229                 { &hf_afs_error, {
2230                         "Error", "afs.error", FT_BOOLEAN, BASE_NONE,
2231                         0, 0, "Error" }},
2232                 { &hf_afs_bos, {
2233                         "BOS", "afs.bos", FT_BOOLEAN, BASE_NONE,
2234                         0, 0, "BOS" }},
2235                 { &hf_afs_update, {
2236                         "Update", "afs.update", FT_BOOLEAN, BASE_NONE,
2237                         0, 0, "Update" }},
2238                 { &hf_afs_rmtsys, {
2239                         "Rmtsys", "afs.rmtsys", FT_BOOLEAN, BASE_NONE,
2240                         0, 0, "Rmtsys" }},
2241                 { &hf_afs_ubik, {
2242                         "Ubik", "afs.ubik", FT_BOOLEAN, BASE_NONE,
2243                         0, 0, "Ubik" }},
2244                 { &hf_afs_backup, {
2245                         "Backup", "afs.backup", FT_BOOLEAN, BASE_NONE,
2246                         0, 0, "Backup" }},
2247
2248                 { &hf_afs_fs_opcode, {
2249                         "Operation", "afs.fs.opcode", FT_UINT32, BASE_DEC,
2250                         VALS(fs_req), 0, "Operation" }},
2251                 { &hf_afs_cb_opcode, {
2252                         "Operation", "afs.cb.opcode", FT_UINT32, BASE_DEC,
2253                         VALS(cb_req), 0, "Operation" }},
2254                 { &hf_afs_prot_opcode, {
2255                         "Operation", "afs.prot.opcode", FT_UINT32, BASE_DEC,
2256                         VALS(prot_req), 0, "Operation" }},
2257                 { &hf_afs_vldb_opcode, {
2258                         "Operation", "afs.vldb.opcode", FT_UINT32, BASE_DEC,
2259                         VALS(vldb_req), 0, "Operation" }},
2260                 { &hf_afs_kauth_opcode, {
2261                         "Operation", "afs.kauth.opcode", FT_UINT32, BASE_DEC,
2262                         VALS(kauth_req), 0, "Operation" }},
2263                 { &hf_afs_vol_opcode, {
2264                         "Operation", "afs.vol.opcode", FT_UINT32, BASE_DEC,
2265                         VALS(vol_req), 0, "Operation" }},
2266                 { &hf_afs_bos_opcode, {
2267                         "Operation", "afs.bos.opcode", FT_UINT32, BASE_DEC,
2268                         VALS(bos_req), 0, "Operation" }},
2269                 { &hf_afs_update_opcode, {
2270                         "Operation", "afs.update.opcode", FT_UINT32, BASE_DEC,
2271                         0, 0, "Operation" }},
2272                 { &hf_afs_rmtsys_opcode, {
2273                         "Operation", "afs.rmtsys.opcode", FT_UINT32, BASE_DEC,
2274                         0, 0, "Operation" }},
2275                 { &hf_afs_error_opcode, {
2276                         "Operation", "afs.error.opcode", FT_UINT32, BASE_DEC,
2277                         0, 0, "Operation" }},
2278                 { &hf_afs_backup_opcode, {
2279                         "Operation", "afs.backup.opcode", FT_UINT32, BASE_DEC,
2280                         0, 0, "Operation" }},
2281                 { &hf_afs_ubik_opcode, {
2282                         "Operation", "afs.ubik.opcode", FT_UINT32, BASE_DEC,
2283                         VALS(ubik_req), 0, "Operation" }},
2284
2285
2286                 /* File Server Fields */
2287                 { &hf_afs_fs_fid_volume, {
2288                         "FileID (Volume)", "afs.fs.fid.volume", FT_UINT32, BASE_DEC,
2289                         0, 0, "File ID (Volume)" }},
2290                 { &hf_afs_fs_fid_vnode, {
2291                         "FileID (VNode)", "afs.fs.fid.vnode", FT_UINT32, BASE_DEC,
2292                         0, 0, "File ID (VNode)" }},
2293                 { &hf_afs_fs_fid_uniqifier, {
2294                         "FileID (Uniqifier)", "afs.fs.fid.uniq", FT_UINT32, BASE_DEC,
2295                         0, 0, "File ID (Uniqifier)" }},
2296                 { &hf_afs_fs_offset, {
2297                         "Offset", "afs.fs.offset", FT_UINT32, BASE_DEC,
2298                         0, 0, "Offset" }},
2299                 { &hf_afs_fs_length, {
2300                         "Length", "afs.fs.length", FT_UINT32, BASE_DEC,
2301                         0, 0, "Length" }},
2302                 { &hf_afs_fs_flength, {
2303                         "FLength", "afs.fs.flength", FT_UINT32, BASE_DEC,
2304                         0, 0, "FLength" }},
2305                 { &hf_afs_fs_errcode, {
2306                         "Error Code", "afs.fs.errcode", FT_UINT32, BASE_DEC,
2307                         VALS(afs_errors), 0, "Error Code" }},
2308                 { &hf_afs_fs_data, {
2309                         "Data", "afs.fs.data", FT_BYTES, BASE_HEX,
2310                         0, 0, "Data" }},
2311                 { &hf_afs_fs_oldname, {
2312                         "Old Name", "afs.fs.oldname", FT_STRING, BASE_HEX,
2313                         0, 0, "Old Name" }},
2314                 { &hf_afs_fs_newname, {
2315                         "New Name", "afs.fs.newname", FT_STRING, BASE_HEX,
2316                         0, 0, "New Name" }},
2317                 { &hf_afs_fs_name, {
2318                         "Name", "afs.fs.name", FT_STRING, BASE_HEX,
2319                         0, 0, "Name" }},
2320                 { &hf_afs_fs_symlink_name, {
2321                         "Symlink Name", "afs.fs.symlink.name", FT_STRING, BASE_HEX,
2322                         0, 0, "Symlink Name" }},
2323                 { &hf_afs_fs_symlink_content, {
2324                         "Symlink Content", "afs.fs.symlink.content", FT_STRING, BASE_HEX,
2325                         0, 0, "Symlink Content" }},
2326                 { &hf_afs_fs_volid, {
2327                         "Volume ID", "afs.fs.volid", FT_UINT32, BASE_DEC,
2328                         0, 0, "Volume ID" }},
2329                 { &hf_afs_fs_volname, {
2330                         "Volume Name", "afs.fs.volname", FT_STRING, BASE_HEX,
2331                         0, 0, "Volume Name" }},
2332                 { &hf_afs_fs_timestamp, {
2333                         "Timestamp", "afs.fs.timestamp", FT_ABSOLUTE_TIME, BASE_DEC,
2334                         0, 0, "Timestamp" }},
2335
2336                 { &hf_afs_fs_acl_count_positive, {
2337                         "ACL Count (Positive)", "afs.fs.acl.count.positive", FT_UINT32, BASE_DEC,
2338                         0, 0, "Number of Positive ACLs" }},
2339                 { &hf_afs_fs_acl_count_negative, {
2340                         "ACL Count (Negative)", "afs.fs.acl.count.negative", FT_UINT32, BASE_DEC,
2341                         0, 0, "Number of Negative ACLs" }},
2342                 { &hf_afs_fs_acl_datasize, {
2343                         "ACL Size", "afs.fs.acl.datasize", FT_UINT32, BASE_DEC,
2344                         0, 0, "ACL Data Size" }},
2345                 { &hf_afs_fs_acl_entity, {
2346                         "Entity (User/Group)", "afs.fs.acl.entity", FT_STRING, BASE_HEX,
2347                         0, 0, "ACL Entity (User/Group)" }},
2348                 { &hf_afs_fs_acl_r, {
2349                         "_R_ead", "afs.fs.acl.r", FT_UINT8, BASE_BIN,
2350                         0, PRSFS_READ, "Read" }},
2351                 { &hf_afs_fs_acl_l, {
2352                         "_L_ookup", "afs.fs.acl.l", FT_UINT8, BASE_BIN,
2353                         0, PRSFS_LOOKUP, "Lookup" }},
2354                 { &hf_afs_fs_acl_i, {
2355                         "_I_nsert", "afs.fs.acl.i", FT_UINT8, BASE_BIN,
2356                         0, PRSFS_INSERT, "Insert" }},
2357                 { &hf_afs_fs_acl_d, {
2358                         "_D_elete", "afs.fs.acl.d", FT_UINT8, BASE_BIN,
2359                         0, PRSFS_DELETE, "Delete" }},
2360                 { &hf_afs_fs_acl_w, {
2361                         "_W_rite", "afs.fs.acl.w", FT_UINT8, BASE_BIN,
2362                         0, PRSFS_WRITE, "Write" }},
2363                 { &hf_afs_fs_acl_k, {
2364                         "_L_ock", "afs.fs.acl.k", FT_UINT8, BASE_BIN,
2365                         0, PRSFS_LOCK, "Lock" }},
2366                 { &hf_afs_fs_acl_a, {
2367                         "_A_dminister", "afs.fs.acl.a", FT_UINT8, BASE_BIN,
2368                         0, PRSFS_ADMINISTER, "Administer" }},
2369
2370                 { &hf_afs_fs_callback_version, {
2371                         "Version", "afs.fs.callback.version", FT_UINT32, BASE_DEC,
2372                         0, 0, "Version" }},
2373                 { &hf_afs_fs_callback_expires, {
2374                         "Expires", "afs.fs.callback.expires", FT_ABSOLUTE_TIME, BASE_DEC,
2375                         0, 0, "Expires" }},
2376                 { &hf_afs_fs_callback_type, {
2377                         "Type", "afs.fs.callback.type", FT_UINT32, BASE_DEC,
2378                         VALS(cb_types), 0, "Type" }},
2379
2380                 /* BOS Server Fields */
2381                 { &hf_afs_bos_errcode, {
2382                         "Error Code", "afs.bos.errcode", FT_UINT32, BASE_DEC,
2383                         VALS(afs_errors), 0, "Error Code" }},
2384                 { &hf_afs_bos_type, {
2385                         "Type", "afs.bos.type", FT_STRING, BASE_HEX,
2386                         0, 0, "Type" }},
2387                 { &hf_afs_bos_content, {
2388                         "Content", "afs.bos.content", FT_STRING, BASE_HEX,
2389                         0, 0, "Content" }},
2390                 { &hf_afs_bos_instance, {
2391                         "Instance", "afs.bos.instance", FT_STRING, BASE_HEX,
2392                         0, 0, "Instance" }},
2393                 { &hf_afs_bos_status, {
2394                         "Status", "afs.bos.status", FT_INT32, BASE_DEC,
2395                         0, 0, "Status" }},
2396                 { &hf_afs_bos_num, {
2397                         "Number", "afs.bos.number", FT_UINT32, BASE_DEC,
2398                         0, 0, "Number" }},
2399                 { &hf_afs_bos_size, {
2400                         "Size", "afs.bos.size", FT_UINT32, BASE_DEC,
2401                         0, 0, "Size" }},
2402                 { &hf_afs_bos_flags, {
2403                         "Flags", "afs.bos.flags", FT_UINT32, BASE_DEC,
2404                         0, 0, "Flags" }},
2405                 { &hf_afs_bos_date, {
2406                         "Date", "afs.bos.date", FT_UINT32, BASE_DEC,
2407                         0, 0, "Date" }},
2408
2409                 /* KAUTH Server Fields */
2410                 { &hf_afs_kauth_errcode, {
2411                         "Error Code", "afs.kauth.errcode", FT_UINT32, BASE_DEC,
2412                         VALS(afs_errors), 0, "Error Code" }},
2413                 { &hf_afs_kauth_princ, {
2414                         "Principal", "afs.kauth.princ", FT_STRING, BASE_HEX,
2415                         0, 0, "Principal" }},
2416                 { &hf_afs_kauth_realm, {
2417                         "Realm", "afs.kauth.realm", FT_STRING, BASE_HEX,
2418                         0, 0, "Realm" }},
2419                 { &hf_afs_kauth_domain, {
2420                         "Domain", "afs.kauth.domain", FT_STRING, BASE_HEX,
2421                         0, 0, "Domain" }},
2422                 { &hf_afs_kauth_name, {
2423                         "Name", "afs.kauth.name", FT_STRING, BASE_HEX,
2424                         0, 0, "Name" }},
2425                 { &hf_afs_kauth_data, {
2426                         "Data", "afs.kauth.data", FT_BYTES, BASE_HEX,
2427                         0, 0, "Data" }},
2428                 { &hf_afs_kauth_kvno, {
2429                         "Key Version Number", "afs.kauth.kvno", FT_UINT32, BASE_DEC,
2430                         0, 0, "Key Version Number" }},
2431
2432                 /* VOL Server Fields */
2433                 { &hf_afs_vol_errcode, {
2434                         "Error Code", "afs.vol.errcode", FT_UINT32, BASE_DEC,
2435                         VALS(afs_errors), 0, "Error Code" }},
2436                 { &hf_afs_vol_id, {
2437                         "Volume ID", "afs.vol.id", FT_UINT32, BASE_DEC,
2438                         0, 0, "Volume ID" }},
2439                 { &hf_afs_vol_count, {
2440                         "Volume Count", "afs.vol.count", FT_UINT32, BASE_DEC,
2441                         0, 0, "Volume Count" }},
2442                 { &hf_afs_vol_name, {
2443                         "Volume Name", "afs.vol.name", FT_STRING, BASE_HEX,
2444                         0, 0, "Volume Name" }},
2445
2446                 /* VLDB Server Fields */
2447                 { &hf_afs_vldb_errcode, {
2448                         "Error Code", "afs.vldb.errcode", FT_UINT32, BASE_DEC,
2449                         VALS(afs_errors), 0, "Error Code" }},
2450                 { &hf_afs_vldb_type, {
2451                         "Volume Type", "afs.vldb.type", FT_UINT32, BASE_DEC,
2452                         VALS(volume_types), 0, "Volume Type" }},
2453                 { &hf_afs_vldb_id, {
2454                         "Volume ID", "afs.vldb.id", FT_UINT32, BASE_DEC,
2455                         0, 0, "Volume ID" }},
2456                 { &hf_afs_vldb_bump, {
2457                         "Bumped Volume ID", "afs.vldb.bump", FT_UINT32, BASE_DEC,
2458                         0, 0, "Bumped Volume ID" }},
2459                 { &hf_afs_vldb_index, {
2460                         "Volume Index", "afs.vldb.index", FT_UINT32, BASE_DEC,
2461                         0, 0, "Volume Index" }},
2462                 { &hf_afs_vldb_count, {
2463                         "Volume Count", "afs.vldb.count", FT_UINT32, BASE_DEC,
2464                         0, 0, "Volume Count" }},
2465                 { &hf_afs_vldb_numservers, {
2466                         "Number of Servers", "afs.vldb.numservers", FT_UINT32, BASE_DEC,
2467                         0, 0, "Number of Servers" }},
2468                 { &hf_afs_vldb_nextindex, {
2469                         "Next Volume Index", "afs.vldb.nextindex", FT_UINT32, BASE_DEC,
2470                         0, 0, "Next Volume Index" }},
2471                 { &hf_afs_vldb_rovol, {
2472                         "Read-Only Volume ID", "afs.vldb.rovol", FT_UINT32, BASE_DEC,
2473                         0, 0, "Read-Only Volume ID" }},
2474                 { &hf_afs_vldb_rwvol, {
2475                         "Read-Write Volume ID", "afs.vldb.rwvol", FT_UINT32, BASE_DEC,
2476                         0, 0, "Read-Only Volume ID" }},
2477                 { &hf_afs_vldb_bkvol, {
2478                         "Backup Volume ID", "afs.vldb.bkvol", FT_UINT32, BASE_DEC,
2479                         0, 0, "Read-Only Volume ID" }},
2480                 { &hf_afs_vldb_name, {
2481                         "Volume Name", "afs.vldb.name", FT_STRING, BASE_HEX,
2482                         0, 0, "Volume Name" }},
2483                 { &hf_afs_vldb_partition, {
2484                         "Partition", "afs.vldb.partition", FT_STRING, BASE_HEX,
2485                         0, 0, "Partition" }},
2486                 { &hf_afs_vldb_server, {
2487                         "Server", "afs.vldb.server", FT_IPv4, BASE_HEX,
2488                         0, 0, "Server" }},
2489                 { &hf_afs_vldb_serveruuid, {
2490                         "Server UUID", "afs.vldb.serveruuid", FT_BYTES, BASE_HEX,
2491                         0, 0, "Server UUID" }},
2492
2493                 /* BACKUP Server Fields */
2494                 { &hf_afs_backup_errcode, {
2495                         "Error Code", "afs.backup.errcode", FT_UINT32, BASE_DEC,
2496                         VALS(afs_errors), 0, "Error Code" }},
2497
2498                 /* CB Server Fields */
2499                 { &hf_afs_cb_errcode, {
2500                         "Error Code", "afs.cb.errcode", FT_UINT32, BASE_DEC,
2501                         VALS(afs_errors), 0, "Error Code" }},
2502                 { &hf_afs_cb_callback_version, {
2503                         "Version", "afs.cb.callback.version", FT_UINT32, BASE_DEC,
2504                         0, 0, "Version" }},
2505                 { &hf_afs_cb_callback_expires, {
2506                         "Expires", "afs.cb.callback.expires", FT_ABSOLUTE_TIME, BASE_DEC,
2507                         0, 0, "Expires" }},
2508                 { &hf_afs_cb_callback_type, {
2509                         "Type", "afs.cb.callback.type", FT_UINT32, BASE_DEC,
2510                         VALS(cb_types), 0, "Type" }},
2511                 { &hf_afs_cb_fid_volume, {
2512                         "FileID (Volume)", "afs.cb.fid.volume", FT_UINT32, BASE_DEC,
2513                         0, 0, "File ID (Volume)" }},
2514                 { &hf_afs_cb_fid_vnode, {
2515                         "FileID (VNode)", "afs.cb.fid.vnode", FT_UINT32, BASE_DEC,
2516                         0, 0, "File ID (VNode)" }},
2517                 { &hf_afs_cb_fid_uniqifier, {
2518                         "FileID (Uniqifier)", "afs.cb.fid.uniq", FT_UINT32, BASE_DEC,
2519                         0, 0, "File ID (Uniqifier)" }},
2520
2521                 /* PROT Server Fields */
2522                 { &hf_afs_prot_errcode, {
2523                         "Error Code", "afs.prot.errcode", FT_UINT32, BASE_DEC,
2524                         VALS(afs_errors), 0, "Error Code" }},
2525                 { &hf_afs_prot_name, {
2526                         "Name", "afs.prot.name", FT_STRING, BASE_HEX,
2527                         0, 0, "Name" }},
2528                 { &hf_afs_prot_id, {
2529                         "ID", "afs.prot.id", FT_UINT32, BASE_DEC,
2530                         0, 0, "ID" }},
2531                 { &hf_afs_prot_oldid, {
2532                         "Old ID", "afs.prot.oldid", FT_UINT32, BASE_DEC,
2533                         0, 0, "Old ID" }},
2534                 { &hf_afs_prot_newid, {
2535                         "New ID", "afs.prot.newid", FT_UINT32, BASE_DEC,
2536                         0, 0, "New ID" }},
2537                 { &hf_afs_prot_gid, {
2538                         "Group ID", "afs.prot.gid", FT_UINT32, BASE_DEC,
2539                         0, 0, "Group ID" }},
2540                 { &hf_afs_prot_uid, {
2541                         "User ID", "afs.prot.uid", FT_UINT32, BASE_DEC,
2542                         0, 0, "User ID" }},
2543                 { &hf_afs_prot_count, {
2544                         "Count", "afs.prot.count", FT_UINT32, BASE_DEC,
2545                         0, 0, "Count" }},
2546                 { &hf_afs_prot_maxgid, {
2547                         "Maximum Group ID", "afs.prot.maxgid", FT_UINT32, BASE_DEC,
2548                         0, 0, "Maximum Group ID" }},
2549                 { &hf_afs_prot_maxuid, {
2550                         "Maximum User ID", "afs.prot.maxuid", FT_UINT32, BASE_DEC,
2551                         0, 0, "Maximum User ID" }},
2552                 { &hf_afs_prot_pos, {
2553                         "Position", "afs.prot.pos", FT_UINT32, BASE_DEC,
2554                         0, 0, "Position" }},
2555                 { &hf_afs_prot_flag, {
2556                         "Flag", "afs.prot.flag", FT_UINT32, BASE_HEX,
2557                         0, 0, "Flag" }},
2558
2559                 /* UBIK Fields */
2560                 { &hf_afs_ubik_errcode, {
2561                         "Error Code", "afs.ubik.errcode", FT_UINT32, BASE_DEC,
2562                         VALS(afs_errors), 0, "Error Code" }},
2563                 { &hf_afs_ubik_version_epoch, {
2564                         "Epoch", "afs.ubik.version.epoch", FT_ABSOLUTE_TIME, BASE_DEC,
2565                         0, 0, "Epoch" }},
2566                 { &hf_afs_ubik_votestart, {
2567                         "Vote Started", "afs.ubik.votestart", FT_ABSOLUTE_TIME, BASE_DEC,
2568                         0, 0, "Vote Started" }},
2569                 { &hf_afs_ubik_voteend, {
2570                         "Vote Ends", "afs.ubik.voteend", FT_ABSOLUTE_TIME, BASE_DEC,
2571                         0, 0, "Vote Ends" }},
2572                 { &hf_afs_ubik_version_counter, {
2573                         "Counter", "afs.ubik.version.counter", FT_UINT32, BASE_DEC,
2574                         0, 0, "Counter" }},
2575                 { &hf_afs_ubik_file, {
2576                         "File", "afs.ubik.file", FT_UINT32, BASE_DEC,
2577                         0, 0, "File" }},
2578                 { &hf_afs_ubik_pos, {
2579                         "Position", "afs.ubik.position", FT_UINT32, BASE_DEC,
2580                         0, 0, "Position" }},
2581                 { &hf_afs_ubik_length, {
2582                         "Length", "afs.ubik.length", FT_UINT32, BASE_DEC,
2583                         0, 0, "Length" }},
2584                 { &hf_afs_ubik_locktype, {
2585                         "Lock Type", "afs.ubik.locktype", FT_UINT32, BASE_DEC,
2586                         VALS(ubik_lock_types), 0, "Lock Type" }},
2587                 { &hf_afs_ubik_votetype, {
2588                         "Vote Type", "afs.ubik.votetype", FT_BOOLEAN, BASE_HEX,
2589                         0, 0, "Vote Type" }},
2590                 { &hf_afs_ubik_syncsite, {
2591                         "Syncsite", "afs.ubik.syncsite", FT_BOOLEAN, BASE_HEX,
2592                         0, 0, "Syncsite" }},
2593                 { &hf_afs_ubik_site, {
2594                         "Site", "afs.ubik.site", FT_IPv4, BASE_HEX,
2595                         0, 0, "Site" }},
2596
2597         };
2598         static gint *ett[] = {
2599                 &ett_afs,
2600                 &ett_afs_op,
2601                 &ett_afs_acl,
2602                 &ett_afs_fid,
2603                 &ett_afs_callback,
2604                 &ett_afs_ubikver,
2605         };
2606
2607         proto_afs = proto_register_protocol("Andrew File System (AFS)", "afs");
2608         proto_register_field_array(proto_afs, hf, array_length(hf));
2609         proto_register_subtree_array(ett, array_length(ett));
2610         register_init_routine(&afs_init_protocol);
2611 }