Make the routines used for the hash table static - they're not used
[obnox/wireshark/wip.git] / packet-afs.c
1 /* packet-afs.c
2  * Routines for AFS 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.15 2000/10/23 04:26:55 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
657  */
658 static 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 static 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         OLD_CHECK_DISPLAY_AS_DATA(proto_afs, pd, offset, fd, tree);
732
733         rxh = (struct rx_header *) &pd[offset];
734         doffset = offset + sizeof(struct rx_header);
735         afsh = (struct afs_header *) &pd[doffset];
736
737         /* get at least a full packet structure */
738         if ( !BYTES_ARE_IN_FRAME(offset, sizeof(struct rx_header)) )
739                 return;
740
741         if (check_col(fd, COL_PROTOCOL))
742                 col_add_str(fd, COL_PROTOCOL, "AFS (RX)");
743
744         reply = (rxh->flags & RX_CLIENT_INITIATED) == 0;
745         port = ((reply == 0) ? pi.destport : pi.srcport );
746
747         /*
748          * Find out what conversation this packet is part of.
749          * XXX - this should really be done by the transport-layer protocol,
750          * although for connectionless transports, we may not want to do that
751          * unless we know some higher-level protocol will want it - or we
752          * may want to do it, so you can say e.g. "show only the packets in
753          * this UDP 'connection'".
754          *
755          * Note that we don't have to worry about the direction this packet
756          * was going - the conversation code handles that for us, treating
757          * packets from A:X to B:Y as being part of the same conversation as
758          * packets from B:Y to A:X.
759          */
760         conversation = find_conversation(&pi.src, &pi.dst, pi.ptype,
761             pi.srcport, pi.destport, 0);
762         if (conversation == NULL) {
763                 /* It's not part of any conversation - create a new one. */
764                 conversation = conversation_new(&pi.src, &pi.dst, pi.ptype,
765                     pi.srcport, pi.destport, NULL, 0);
766         }
767
768         request_key.conversation = conversation->index; 
769         request_key.service = pntohs(&rxh->serviceId);
770         request_key.callnumber = pntohl(&rxh->callNumber);
771
772         request_val = (struct afs_request_val *) g_hash_table_lookup(
773                 afs_request_hash, &request_key);
774
775         /* only allocate a new hash element when it's a request */
776         opcode = 0;
777         if ( !request_val && !reply)
778         {
779                 new_request_key = g_mem_chunk_alloc(afs_request_keys);
780                 *new_request_key = request_key;
781
782                 request_val = g_mem_chunk_alloc(afs_request_vals);
783                 request_val -> opcode = pntohl(&afsh->opcode);
784                 opcode = request_val->opcode;
785
786                 g_hash_table_insert(afs_request_hash, new_request_key,
787                         request_val);
788         }
789
790         if ( request_val )
791         {
792                 opcode = request_val->opcode;
793         }
794
795         node = 0;
796         typenode = 0;
797         vals = NULL;
798         dissector = NULL;
799         switch (port)
800         {
801                 case AFS_PORT_FS:
802                         typenode = hf_afs_fs;
803                         node = hf_afs_fs_opcode;
804                         vals = fs_req;
805                         dissector = reply ? dissect_fs_reply : dissect_fs_request;
806                         break;
807                 case AFS_PORT_CB:
808                         typenode = hf_afs_cb;
809                         node = hf_afs_cb_opcode;
810                         vals = cb_req;
811                         dissector = reply ? dissect_cb_reply : dissect_cb_request;
812                         break;
813                 case AFS_PORT_PROT:
814                         typenode = hf_afs_prot;
815                         node = hf_afs_prot_opcode;
816                         vals = prot_req;
817                         dissector = reply ? dissect_prot_reply : dissect_prot_request;
818                         break;
819                 case AFS_PORT_VLDB:
820                         typenode = hf_afs_vldb;
821                         node = hf_afs_vldb_opcode;
822                         vals = vldb_req;
823                         dissector = reply ? dissect_vldb_reply : dissect_vldb_request;
824                         break;
825                 case AFS_PORT_KAUTH:
826                         typenode = hf_afs_kauth;
827                         node = hf_afs_kauth_opcode;
828                         vals = kauth_req;
829                         dissector = reply ? dissect_kauth_reply : dissect_kauth_request;
830                         break;
831                 case AFS_PORT_VOL:
832                         typenode = hf_afs_vol;
833                         node = hf_afs_vol_opcode;
834                         vals = vol_req;
835                         dissector = reply ? dissect_vol_reply : dissect_vol_request;
836                         break;
837                 case AFS_PORT_ERROR:
838                         typenode = hf_afs_error;
839                         node = hf_afs_error_opcode;
840                         /* dissector = reply ? dissect_error_reply : dissect_error_request; */
841                         break;
842                 case AFS_PORT_BOS:
843                         typenode = hf_afs_bos;
844                         node = hf_afs_bos_opcode;
845                         vals = bos_req;
846                         dissector = reply ? dissect_bos_reply : dissect_bos_request;
847                         break;
848                 case AFS_PORT_UPDATE:
849                         typenode = hf_afs_update;
850                         node = hf_afs_update_opcode;
851                         /* dissector = reply ? dissect_update_reply : dissect_update_request; */
852                         break;
853                 case AFS_PORT_RMTSYS:
854                         typenode = hf_afs_rmtsys;
855                         node = hf_afs_rmtsys_opcode;
856                         /* dissector = reply ? dissect_rmtsys_reply : dissect_rmtsys_request; */
857                         break;
858                 case AFS_PORT_BACKUP:
859                         typenode = hf_afs_backup;
860                         node = hf_afs_backup_opcode;
861                         dissector = reply ? dissect_backup_reply : dissect_backup_request;
862                         break;
863         }
864         if ( (opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
865                 (opcode >= DISK_LOW && opcode <= DISK_HIGH) )
866         {
867                 typenode = hf_afs_ubik;
868                 node = hf_afs_ubik_opcode;
869                 vals = ubik_req;
870                 dissector = reply ? dissect_ubik_reply : dissect_ubik_request;
871         }
872
873         if ( vals )
874         {
875                 if (check_col(fd, COL_INFO))
876                         col_add_fstr(fd, COL_INFO, "%s %s: %s (%d)",
877                         val_to_str(port, port_types_short, "Unknown(%d)"),
878                         reply ? "Reply" : "Request",
879                         val_to_str(opcode, vals, "Unknown(%d)"), opcode);
880         }
881         else
882         {
883                 if (check_col(fd, COL_INFO))
884                         col_add_fstr(fd, COL_INFO, "%s %s: Unknown(%d)",
885                         val_to_str(port, port_types_short, "Unknown(%d)"),
886                         reply ? "Reply" : "Request",
887                         opcode);
888         }
889
890         if (tree) {
891                 ti = proto_tree_add_item(tree, proto_afs, NullTVB, doffset, END_OF_FRAME, FALSE);
892                 afs_tree = proto_item_add_subtree(ti, ett_afs);
893
894                 if ( !BYTES_ARE_IN_FRAME(offset, sizeof(struct rx_header) +
895                         sizeof(struct afs_header)) )
896                 {
897                         proto_tree_add_text(afs_tree, NullTVB, doffset, END_OF_FRAME,
898                                 "Service: %s %s (Truncated)",
899                                 val_to_str(port, port_types, "Unknown(%d)"),
900                                 reply ? "Reply" : "Request");
901                                 return;
902                 }
903                 else
904                 {
905                         proto_tree_add_text(afs_tree, NullTVB, doffset, END_OF_FRAME,
906                                 "Service: %s %s",
907                                 val_to_str(port, port_types, "Unknown(%d)"),
908                                 reply ? "Reply" : "Request");
909                 }
910
911                 /* until we do cache, can't handle replies */
912                 ti = NULL;
913                 if ( !reply && node != 0 )
914                 {
915                         ti = proto_tree_add_uint(afs_tree,
916                                 node, NullTVB, doffset, 4, opcode);
917                 }
918                 else if ( reply && node != 0 )
919                 {
920                         /* the opcode isn't in this packet */
921                         ti = proto_tree_add_uint(afs_tree,
922                                 node, NullTVB, doffset, 0, opcode);
923                 }
924                 else
925                 {
926                         ti = proto_tree_add_text(afs_tree, NullTVB,
927                                 doffset, 0, "Operation: Unknown");
928                 }
929
930                 /* Add the subtree for this particular service */
931                 afs_op_tree = proto_item_add_subtree(ti, ett_afs_op);
932
933                 if ( typenode != 0 )
934                 {
935                         /* indicate the type of request */
936                         proto_tree_add_boolean_hidden(afs_tree, typenode, NullTVB, doffset, 0, 1);
937                 }
938
939                 /* Process the packet according to what service it is */
940                 if ( dissector )
941                 {
942                         (*dissector)(pd,offset,fd,afs_op_tree,opcode);
943                 }
944         }
945
946         /* if it's the last packet, and it's a reply, remove opcode
947                 from hash */
948         /* ignoring for now, I'm not sure how the chunk deallocation works */
949         if ( rxh->flags & RX_LAST_PACKET && reply )
950         {
951
952         }
953 }
954
955 /*
956  * Macros for helper dissection routines
957  *
958  * The macros are here to save on coding. They assume that
959  * the current offset is in 'curoffset', and that the offset
960  * should be incremented after performing the macro's operation.
961  */
962
963 /* Get the next available integer, be sure and call TRUNC beforehand */
964 #define GETINT() (pntohl(&pd[curoffset]))
965
966 /* Check if enough bytes are present, if not, return to caller
967    after adding a 'Truncated' message to tree */
968 #define TRUNC(bytes) \
969         if(!BYTES_ARE_IN_FRAME(curoffset,(bytes))) \
970         { proto_tree_add_text(tree, NullTVB,curoffset,END_OF_FRAME,"Truncated"); \
971         return; }
972
973 /* Output a unsigned integer, stored into field 'field'
974    Assumes it is in network byte order, converts to host before using */
975 #define UINTOUT(field) \
976         TRUNC(sizeof(guint32)) \
977         proto_tree_add_uint(tree,field, NullTVB,curoffset,sizeof(guint32), GETINT()); \
978         curoffset += 4;
979
980 /* Output an IPv4 address, stored into field 'field' */
981 #define IPOUT(field) \
982         TRUNC(sizeof(gint32)) \
983         proto_tree_add_ipv4(tree,field, NullTVB,curoffset,sizeof(gint32),\
984                 *((int*)&pd[curoffset]));\
985         curoffset += 4;
986
987 /* Output a UNIX seconds/microseconds timestamp, after converting to a timeval */
988 #define BIGDATEOUT(field) \
989         { struct timeval tv; \
990         TRUNC(2*sizeof(guint32)); \
991         tv.tv_sec = GETINT(); \
992         tv.tv_usec = GETINT(); \
993         proto_tree_add_time(tree,field, NullTVB,curoffset,2*sizeof(guint32),&tv); \
994         curoffset += 8; \
995         }
996
997 /* Output a UNIX seconds-only timestamp, after converting to a timeval */
998 #define DATEOUT(field) \
999         { struct timeval tv; \
1000         TRUNC(sizeof(guint32)); \
1001         tv.tv_sec = GETINT(); \
1002         tv.tv_usec = 0; \
1003         proto_tree_add_time(tree,field, NullTVB,curoffset,sizeof(guint32),&tv); \
1004         curoffset += 4; \
1005         }
1006
1007 /* Output a callback */
1008 #define FS_CALLBACKOUT() \
1009         {       proto_tree *save, *ti; \
1010                 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, "Callback"); \
1011                 save = tree; \
1012                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
1013                 TRUNC(3*sizeof(guint32)); \
1014                 UINTOUT(hf_afs_fs_callback_version); \
1015                 BIGDATEOUT(hf_afs_fs_callback_expires); \
1016                 UINTOUT(hf_afs_fs_callback_type); \
1017                 tree = save; \
1018         }
1019
1020 /* Output a callback */
1021 #define CB_CALLBACKOUT() \
1022         {       proto_tree *save, *ti; \
1023                 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, "Callback"); \
1024                 save = tree; \
1025                 tree = proto_item_add_subtree(ti, ett_afs_callback); \
1026                 TRUNC(3*sizeof(guint32)); \
1027                 UINTOUT(hf_afs_cb_callback_version); \
1028                 DATEOUT(hf_afs_cb_callback_expires); \
1029                 UINTOUT(hf_afs_cb_callback_type); \
1030                 tree = save; \
1031         }
1032
1033
1034 /* Output a File ID */
1035 #define FS_FIDOUT(label) \
1036         {       proto_tree *save, *ti; \
1037                 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
1038                         "FileID (%s)", label); \
1039                 save = tree; \
1040                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
1041                 UINTOUT(hf_afs_fs_fid_volume); \
1042                 UINTOUT(hf_afs_fs_fid_vnode); \
1043                 UINTOUT(hf_afs_fs_fid_uniqifier); \
1044                 tree = save; \
1045         }
1046
1047 /* Output a File ID */
1048 #define CB_FIDOUT(label) \
1049         {       proto_tree *save, *ti; \
1050                 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
1051                         "FileID (%s)", label); \
1052                 save = tree; \
1053                 tree = proto_item_add_subtree(ti, ett_afs_fid); \
1054                 UINTOUT(hf_afs_cb_fid_volume); \
1055                 UINTOUT(hf_afs_cb_fid_vnode); \
1056                 UINTOUT(hf_afs_cb_fid_uniqifier); \
1057                 tree = save; \
1058         }
1059
1060 /* Output a AFS acl */
1061 #define ACLOUT(who, positive, acl, bytes) \
1062         {       proto_tree *save, *ti; \
1063                 int tmpoffset; \
1064                 int acllen; \
1065                 char tmp[10]; \
1066                 tmp[0] = 0; \
1067                 if ( acl & PRSFS_READ ) strcat(tmp, "r"); \
1068                 if ( acl & PRSFS_LOOKUP ) strcat(tmp, "l"); \
1069                 if ( acl & PRSFS_INSERT ) strcat(tmp, "i"); \
1070                 if ( acl & PRSFS_DELETE ) strcat(tmp, "d"); \
1071                 if ( acl & PRSFS_WRITE ) strcat(tmp, "w"); \
1072                 if ( acl & PRSFS_LOCK ) strcat(tmp, "k"); \
1073                 if ( acl & PRSFS_ADMINISTER ) strcat(tmp, "a"); \
1074                 ti = proto_tree_add_text(tree, NullTVB, curoffset, bytes, \
1075                         "ACL:  %s %s%s", \
1076                         who, tmp, positive ? "" : " (negative)"); \
1077                 save = tree; \
1078                 tree = proto_item_add_subtree(ti, ett_afs_acl); \
1079                 proto_tree_add_string(tree,hf_afs_fs_acl_entity, NullTVB,curoffset,strlen(who), who);\
1080                 tmpoffset = curoffset + strlen(who) + 1; \
1081                 acllen = bytes - strlen(who) - 1; \
1082                 proto_tree_add_uint(tree,hf_afs_fs_acl_r, NullTVB,tmpoffset,acllen,acl);\
1083                 proto_tree_add_uint(tree,hf_afs_fs_acl_l, NullTVB,tmpoffset,acllen,acl);\
1084                 proto_tree_add_uint(tree,hf_afs_fs_acl_i, NullTVB,tmpoffset,acllen,acl);\
1085                 proto_tree_add_uint(tree,hf_afs_fs_acl_d, NullTVB,tmpoffset,acllen,acl);\
1086                 proto_tree_add_uint(tree,hf_afs_fs_acl_w, NullTVB,tmpoffset,acllen,acl);\
1087                 proto_tree_add_uint(tree,hf_afs_fs_acl_k, NullTVB,tmpoffset,acllen,acl);\
1088                 proto_tree_add_uint(tree,hf_afs_fs_acl_a, NullTVB,tmpoffset,acllen,acl);\
1089                 tree = save; \
1090         }
1091
1092 /* Skip a certain number of bytes */
1093 #define SKIP(bytes) \
1094         TRUNC(bytes) \
1095         curoffset += bytes;
1096
1097 /* Raw data - to end of frame */
1098 #define RAWOUT(field) BYTESOUT(field, offset+END_OF_FRAME-curoffset)
1099
1100 /* Raw data */
1101 #define BYTESOUT(field, bytes) \
1102         TRUNC(bytes); \
1103         proto_tree_add_bytes(tree,field, NullTVB,curoffset,bytes,\
1104                 (void *)&pd[curoffset]); \
1105         curoffset += bytes;
1106
1107 /* Output a rx style string, up to a maximum length first 
1108    4 bytes - length, then char data */
1109 #define STROUT(field) \
1110         {       int i; \
1111                 TRUNC(4); \
1112                 i = pntohl(&pd[curoffset]); \
1113                 curoffset += 4; \
1114                 TRUNC(i); \
1115                 if ( i > 0 ) { \
1116                         proto_tree_add_string(tree, field, NullTVB, curoffset-4, i+4, \
1117                         (void *)&pd[curoffset]); \
1118                 } else { \
1119                         proto_tree_add_string(tree, field, NullTVB, curoffset-4, 4, \
1120                         ""); \
1121                 } \
1122                 curoffset += i; \
1123         }
1124
1125 /* Output a fixed length vectorized string (each char is a 32 bit int) */
1126 #define VECOUT(field, length) \
1127         {       char tmp[length+1]; \
1128                 int i,soff; \
1129                 soff = curoffset;\
1130                 TRUNC(length * sizeof(guint32));\
1131                 for (i=0; i<length; i++)\
1132                 {\
1133                         tmp[i] = (char) GETINT();\
1134                         curoffset += sizeof(guint32);\
1135                 }\
1136                 tmp[length] = '\0';\
1137                 proto_tree_add_string(tree, field, NullTVB, soff, length, tmp);\
1138         }
1139
1140 /* Output a UBIK version code */
1141 #define UBIK_VERSIONOUT(label) \
1142         {       proto_tree *save, *ti; \
1143                 unsigned int epoch,counter; \
1144                 struct timeval tv; \
1145                 TRUNC(8); \
1146                 epoch = GETINT(); \
1147                 curoffset += 4; \
1148                 counter = GETINT(); \
1149                 curoffset += 4; \
1150                 tv.tv_sec = epoch; \
1151                 tv.tv_usec = 0; \
1152                 ti = proto_tree_add_text(tree, NullTVB, curoffset, 3*4, \
1153                         "UBIK Version (%s): %u.%u", label, epoch, counter ); \
1154                 save = tree; \
1155                 tree = proto_item_add_subtree(ti, ett_afs_ubikver); \
1156                 proto_tree_add_time(tree,hf_afs_ubik_version_epoch, NullTVB,curoffset-8, \
1157                         sizeof(guint32),&tv); \
1158                 proto_tree_add_uint(tree,hf_afs_ubik_version_counter, NullTVB,curoffset-4, \
1159                         sizeof(guint32),counter); \
1160                 tree = save; \
1161         }
1162
1163 /*
1164  * Here is a helper routine for adding an AFS acl to the proto tree
1165  * This is to be used with FS packets only
1166  *
1167  * An AFS ACL is a string that has the following format:
1168  *
1169  * <positive> <negative>
1170  * <uid1> <aclbits1>
1171  * ....
1172  *
1173  * "positive" and "negative" are integers which contain the number of
1174  * positive and negative ACL's in the string.  The uid/aclbits pair are
1175  * ASCII strings containing the UID/PTS record and and a ascii number
1176  * representing a logical OR of all the ACL permission bits
1177  */
1178
1179 static void dissect_acl(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
1180 {
1181         int pos, neg, acl;
1182         int n, i, bytes;
1183         u_char const *s;
1184         u_char const *end;
1185         char user[128];
1186         int curoffset;
1187         int soff,eoff;
1188
1189         curoffset = offset;
1190
1191         TRUNC(sizeof(guint32));
1192         bytes = pntohl(&pd[curoffset]);
1193         UINTOUT(hf_afs_fs_acl_datasize);
1194
1195         TRUNC(bytes);
1196
1197         soff = curoffset;
1198         eoff = curoffset+bytes;
1199
1200         s = &pd[soff];
1201         end = &pd[eoff];
1202
1203         if (sscanf((char *) s, "%d %n", &pos, &n) != 1)
1204                 return;
1205         s += n;
1206         TRUNC(1);
1207         proto_tree_add_uint(tree, hf_afs_fs_acl_count_positive, NullTVB, curoffset, n, pos);
1208         curoffset += n;
1209
1210         if (sscanf((char *) s, "%d %n", &neg, &n) != 1)
1211                 return;
1212         s += n;
1213         TRUNC(1);
1214         proto_tree_add_uint(tree, hf_afs_fs_acl_count_negative, NullTVB, curoffset, n, neg);
1215         curoffset += n;
1216
1217
1218         /*
1219          * This wacky order preserves the order used by the "fs" command
1220          */
1221
1222         for (i = 0; i < pos; i++) {
1223                 if (sscanf((char *) s, "%s %d %n", user, &acl, &n) != 2)
1224                         return;
1225                 s += n;
1226                 ACLOUT(user,1,acl,n);
1227                 curoffset += n;
1228                 TRUNC(1);
1229         }
1230
1231         for (i = 0; i < neg; i++) {
1232                 if (sscanf((char *) s, "%s %d %n", user, &acl, &n) != 2)
1233                         return;
1234                 s += n;
1235                 ACLOUT(user,0,acl,n);
1236                 curoffset += n;
1237                 if (s > end)
1238                         return;
1239         }
1240 }
1241
1242 /*
1243  * Here are the helper dissection routines
1244  */
1245
1246 static void
1247 dissect_fs_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1248 {
1249         struct rx_header *rxh;
1250         unsigned char *data;
1251         int doffset, curoffset;
1252
1253         rxh = (struct rx_header *) &pd[offset];
1254         data = (char *)rxh + sizeof(struct rx_header);
1255         doffset = offset + sizeof(struct rx_header);
1256         curoffset = doffset;
1257
1258         if ( rxh->type == RX_PACKET_TYPE_DATA )
1259         {
1260                 switch ( opcode )
1261                 {
1262                         case 130: /* fetch data */
1263                                 RAWOUT(hf_afs_fs_data);
1264                                 break;
1265                         case 131: /* fetch acl */
1266                                 dissect_acl(pd,curoffset,fd,tree);
1267                                 break;
1268                         case 137: /* create file */
1269                                 FS_FIDOUT("New File");
1270                                 break;
1271                         case 141: /* make dir */
1272                                 FS_FIDOUT("New Directory");
1273                                 break;
1274                         case 151: /* root volume */
1275                                 STROUT(hf_afs_fs_volname);
1276                                 break;
1277                         case 153: /* get time */
1278                                 BIGDATEOUT(hf_afs_fs_timestamp);
1279                                 break;
1280                 }
1281         }
1282         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1283         {
1284                 UINTOUT(hf_afs_fs_errcode);
1285         }
1286 }
1287
1288 static void
1289 dissect_fs_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1290 {
1291         struct rx_header *rxh;
1292         unsigned char *data;
1293         int doffset, curoffset;
1294
1295         rxh = (struct rx_header *) &pd[offset];
1296         data = (char *)rxh + sizeof(struct rx_header);
1297         doffset = offset + sizeof(struct rx_header);
1298         curoffset = doffset;
1299
1300         /* skip opcode */
1301         SKIP(sizeof(guint32));
1302
1303         switch ( opcode )
1304         {
1305                 case 130: /* Fetch data */
1306                         FS_FIDOUT("Source");
1307                         UINTOUT(hf_afs_fs_offset);
1308                         UINTOUT(hf_afs_fs_length);
1309                         break;
1310                 case 131: /* Fetch ACL */
1311                 case 132: /* Fetch Status */
1312                 case 135: /* Store Status */
1313                 case 143: /* Old Set Lock */
1314                 case 144: /* Old Extend Lock */
1315                 case 145: /* Old Release Lock */
1316                 case 156: /* Set Lock */
1317                 case 157: /* Extend Lock */
1318                 case 158: /* Release Lock */
1319                         FS_FIDOUT("Target");
1320                         break;
1321                 case 133: /* Store Data */
1322                         FS_FIDOUT("Destination");
1323                         SKIP(6*sizeof(guint32));
1324                         UINTOUT(hf_afs_fs_offset);
1325                         UINTOUT(hf_afs_fs_length);
1326                         UINTOUT(hf_afs_fs_flength);
1327                         break;
1328                 case 134: /* Store ACL */
1329                         FS_FIDOUT("Target");
1330                         dissect_acl(pd,curoffset,fd,tree);
1331                         /* print acl */
1332                         break;
1333                 case 136: /* Remove File */
1334                 case 137: /* Create File */
1335                 case 141: /* Make dir */
1336                 case 142: /* Remove dir */
1337                         FS_FIDOUT("Target");
1338                         STROUT(hf_afs_fs_name);
1339                         break;
1340                 case 138: /* Rename file */
1341                         FS_FIDOUT("Old");
1342                         STROUT(hf_afs_fs_oldname);
1343                         FS_FIDOUT("New");
1344                         STROUT(hf_afs_fs_newname);
1345                         break;
1346                 case 139: /* Symlink */
1347                         FS_FIDOUT("File");
1348                         STROUT(hf_afs_fs_symlink_name);
1349                         STROUT(hf_afs_fs_symlink_content);
1350                         break;
1351                 case 140: /* Link */
1352                         FS_FIDOUT("Link From (Old File)");
1353                         STROUT(hf_afs_fs_name);
1354                         FS_FIDOUT("Link To (New File)");
1355                         break;
1356                 case 148: /* Get vol info */
1357                         STROUT(hf_afs_fs_volname);
1358                         break;
1359                 case 149: /* Get vol stats */
1360                 case 150: /* Set vol stats */
1361                         UINTOUT(hf_afs_fs_volid);
1362                         break;
1363                 case 154: /* new get vol info */
1364                         STROUT(hf_afs_fs_volname);
1365                         break;
1366                 case 155: /* bulk stat */
1367                 {
1368                         unsigned int j,i;
1369                         TRUNC(1);
1370
1371                         j = pntohl(&pd[curoffset]);
1372                         curoffset += 1;
1373                         for (i=0; i<j; i++)
1374                         {
1375                                 FS_FIDOUT("Target");
1376                         }
1377                         break;
1378                 }
1379         }
1380 }
1381
1382 /*
1383  * BOS Helpers
1384  */
1385 static void
1386 dissect_bos_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1387 {
1388         struct rx_header *rxh;
1389         unsigned char *data;
1390         int doffset, curoffset;
1391
1392         rxh = (struct rx_header *) &pd[offset];
1393         data = (char *)rxh + sizeof(struct rx_header);
1394         doffset = offset + sizeof(struct rx_header);
1395         curoffset = doffset;
1396
1397         if ( rxh->type == RX_PACKET_TYPE_DATA )
1398         {
1399                 switch ( opcode )
1400                 {
1401                         case 85: /* get instance info */
1402                                 STROUT(hf_afs_bos_type);
1403                                 break;
1404                 }
1405         }
1406         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1407         {
1408                 UINTOUT(hf_afs_bos_errcode);
1409         }
1410 }
1411
1412 static void
1413 dissect_bos_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1414 {
1415         struct rx_header *rxh;
1416         unsigned char *data;
1417         int doffset, curoffset;
1418
1419         rxh = (struct rx_header *) &pd[offset];
1420         data = (char *)rxh + sizeof(struct rx_header);
1421         doffset = offset + sizeof(struct rx_header);
1422         curoffset = doffset;
1423
1424         /* skip opcode */
1425         SKIP(sizeof(guint32));
1426
1427         switch ( opcode )
1428         {
1429                 case 80: /* create b node */
1430                         STROUT(hf_afs_bos_type);
1431                         STROUT(hf_afs_bos_instance);
1432                         break;
1433                 case 81: /* delete b node */
1434                 case 83: /* get status */
1435                 case 85: /* get instance info */
1436                 case 87: /* add super user */
1437                 case 88: /* delete super user */
1438                 case 93: /* set cell name */
1439                 case 96: /* add cell host */
1440                 case 97: /* delete cell host */
1441                 case 104: /* restart */
1442                 case 106: /* uninstall */
1443                 case 108: /* exec */
1444                 case 112: /* get log */
1445                 case 114: /* get instance strings */
1446                         STROUT(hf_afs_bos_content);
1447                         break;
1448                 case 82: /* set status */
1449                 case 98: /* set t status */
1450                         STROUT(hf_afs_bos_content);
1451                         UINTOUT(hf_afs_bos_status);
1452                         break;
1453                 case 86: /* get instance parm */
1454                         STROUT(hf_afs_bos_instance);
1455                         UINTOUT(hf_afs_bos_num);
1456                         break;
1457                 case 84: /* enumerate instance */
1458                 case 89: /* list super users */
1459                 case 90: /* list keys */
1460                 case 91: /* add key */
1461                 case 92: /* delete key */
1462                 case 95: /* set cell host */
1463                         UINTOUT(hf_afs_bos_num);
1464                         break;
1465                 case 105: /* install */
1466                         STROUT(hf_afs_bos_content);
1467                         UINTOUT(hf_afs_bos_size);
1468                         UINTOUT(hf_afs_bos_flags);
1469                         UINTOUT(hf_afs_bos_date);
1470                         break;
1471         }
1472 }
1473
1474 /*
1475  * VOL Helpers
1476  */
1477 static void
1478 dissect_vol_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1479 {
1480         struct rx_header *rxh;
1481         unsigned char *data;
1482         int doffset, curoffset;
1483
1484         rxh = (struct rx_header *) &pd[offset];
1485         data = (char *)rxh + sizeof(struct rx_header);
1486         doffset = offset + sizeof(struct rx_header);
1487         curoffset = doffset;
1488
1489         if ( rxh->type == RX_PACKET_TYPE_DATA )
1490         {
1491                 switch ( opcode )
1492                 {
1493                         case 121:
1494                                 /* should loop here maybe */
1495                                 UINTOUT(hf_afs_vol_count);
1496                                 VECOUT(hf_afs_vol_name, 32); /* not sure on  */
1497                                 break;
1498                 }
1499         }
1500         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1501         {
1502                 UINTOUT(hf_afs_vol_errcode);
1503         }
1504 }
1505
1506 static void
1507 dissect_vol_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1508 {
1509         struct rx_header *rxh;
1510         unsigned char *data;
1511         int doffset, curoffset;
1512
1513         rxh = (struct rx_header *) &pd[offset];
1514         data = (char *)rxh + sizeof(struct rx_header);
1515         doffset = offset + sizeof(struct rx_header);
1516         curoffset = doffset;
1517
1518         /* skip opcode */
1519         SKIP(sizeof(guint32));
1520
1521         switch ( opcode )
1522         {
1523                 case 121: /* list one vol */
1524                         UINTOUT(hf_afs_vol_count);
1525                         UINTOUT(hf_afs_vol_id);
1526                         break;
1527         }
1528 }
1529
1530 /*
1531  * KAUTH Helpers
1532  */
1533 static void
1534 dissect_kauth_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1535 {
1536         struct rx_header *rxh;
1537         unsigned char *data;
1538         int doffset, curoffset;
1539
1540         rxh = (struct rx_header *) &pd[offset];
1541         data = (char *)rxh + sizeof(struct rx_header);
1542         doffset = offset + sizeof(struct rx_header);
1543         curoffset = doffset;
1544
1545         if ( rxh->type == RX_PACKET_TYPE_DATA )
1546         {
1547                 switch ( opcode )
1548                 {
1549                 }
1550         }
1551         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1552         {
1553                 UINTOUT(hf_afs_kauth_errcode);
1554         }
1555 }
1556
1557 static void
1558 dissect_kauth_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1559 {
1560         struct rx_header *rxh;
1561         unsigned char *data;
1562         int doffset, curoffset;
1563
1564         rxh = (struct rx_header *) &pd[offset];
1565         data = (char *)rxh + sizeof(struct rx_header);
1566         doffset = offset + sizeof(struct rx_header);
1567         curoffset = doffset;
1568
1569         /* skip opcode */
1570         SKIP(sizeof(guint32));
1571
1572         switch ( opcode )
1573         {
1574                 case 1: /* authenticate old */
1575                 case 21: /* authenticate */
1576                 case 22: /* authenticate v2 */
1577                 case 2: /* change pw */
1578                 case 5: /* set fields */
1579                 case 6: /* create user */
1580                 case 7: /* delete user */
1581                 case 8: /* get entry */
1582                 case 14: /* unlock */
1583                 case 15: /* lock status */
1584                         STROUT(hf_afs_kauth_princ);
1585                         STROUT(hf_afs_kauth_realm);
1586                         RAWOUT(hf_afs_kauth_data);
1587                         break;
1588                 case 3: /* getticket-old */
1589                 case 23: /* getticket */
1590                         UINTOUT(hf_afs_kauth_kvno);
1591                         STROUT(hf_afs_kauth_domain);
1592                         STROUT(hf_afs_kauth_data);
1593                         STROUT(hf_afs_kauth_princ);
1594                         STROUT(hf_afs_kauth_realm);
1595                         break;
1596                 case 4: /* set pass */
1597                         STROUT(hf_afs_kauth_princ);
1598                         STROUT(hf_afs_kauth_realm);
1599                         UINTOUT(hf_afs_kauth_kvno);
1600                         break;
1601                 case 12: /* get pass */
1602                         STROUT(hf_afs_kauth_name);
1603                         break;
1604         }
1605 }
1606
1607 /*
1608  * CB Helpers
1609  */
1610 static void
1611 dissect_cb_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1612 {
1613         struct rx_header *rxh;
1614         unsigned char *data;
1615         int doffset, curoffset;
1616
1617         rxh = (struct rx_header *) &pd[offset];
1618         data = (char *)rxh + sizeof(struct rx_header);
1619         doffset = offset + sizeof(struct rx_header);
1620         curoffset = doffset;
1621
1622         if ( rxh->type == RX_PACKET_TYPE_DATA )
1623         {
1624                 switch ( opcode )
1625                 {
1626                 }
1627         }
1628         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1629         {
1630                 UINTOUT(hf_afs_cb_errcode);
1631         }
1632 }
1633
1634 static void
1635 dissect_cb_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1636 {
1637         struct rx_header *rxh;
1638         unsigned char *data;
1639         int doffset, curoffset;
1640
1641         rxh = (struct rx_header *) &pd[offset];
1642         data = (char *)rxh + sizeof(struct rx_header);
1643         doffset = offset + sizeof(struct rx_header);
1644         curoffset = doffset;
1645
1646         /* skip opcode */
1647         SKIP(sizeof(guint32));
1648
1649         switch ( opcode )
1650         {
1651                 case 204: /* callback */
1652                 {
1653                         unsigned int i,j;
1654
1655                         TRUNC(4);
1656                         j = GETINT();
1657
1658                         for (i=0; i<j; i++)
1659                         {
1660                                 CB_FIDOUT("Target");
1661                         }
1662
1663                         TRUNC(4);
1664                         j = GETINT();
1665                         for (i=0; i<j; i++)
1666                         {
1667                                 CB_CALLBACKOUT();
1668                         }
1669                 }
1670         }
1671 }
1672
1673 /*
1674  * PROT Helpers
1675  */
1676 static void
1677 dissect_prot_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1678 {
1679         struct rx_header *rxh;
1680         unsigned char *data;
1681         int doffset, curoffset;
1682
1683         rxh = (struct rx_header *) &pd[offset];
1684         data = (char *)rxh + sizeof(struct rx_header);
1685         doffset = offset + sizeof(struct rx_header);
1686         curoffset = doffset;
1687
1688         if ( rxh->type == RX_PACKET_TYPE_DATA )
1689         {
1690                 switch ( opcode )
1691                 {
1692                         case 504: /* name to id */
1693                                 {
1694                                         unsigned int i, j;
1695
1696                                         TRUNC(4);
1697                                         j = GETINT();
1698                                         UINTOUT(hf_afs_prot_count);
1699
1700                                         for (i=0; i<j; i++)
1701                                         {
1702                                                 UINTOUT(hf_afs_prot_id);
1703                                         }
1704                                 }
1705                                 break;
1706                         case 505: /* id to name */
1707                                 {
1708                                         unsigned int i, j;
1709
1710                                         TRUNC(4);
1711                                         j = GETINT();
1712                                         UINTOUT(hf_afs_prot_count);
1713
1714                                         for (i=0; i<j; i++)
1715                                         {
1716                                                 VECOUT(hf_afs_prot_name, PRNAMEMAX);
1717                                         }
1718                                 }
1719                                 break;
1720                         case 508: /* get cps */
1721                         case 514: /* list elements */
1722                         case 517: /* list owned */
1723                         case 518: /* get cps2 */
1724                         case 519: /* get host cps */
1725                                 {
1726                                         unsigned int i, j;
1727
1728                                         TRUNC(4);
1729                                         j = GETINT();
1730                                         UINTOUT(hf_afs_prot_count);
1731
1732                                         for (i=0; i<j; i++)
1733                                         {
1734                                                 UINTOUT(hf_afs_prot_id);
1735                                         }
1736                                 }
1737                                 break;
1738                         case 510: /* list max */
1739                                 UINTOUT(hf_afs_prot_maxuid);
1740                                 UINTOUT(hf_afs_prot_maxgid);
1741                                 break;
1742                 }
1743         }
1744         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1745         {
1746                 UINTOUT(hf_afs_prot_errcode);
1747         }
1748 }
1749
1750 static void
1751 dissect_prot_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1752 {
1753         struct rx_header *rxh;
1754         unsigned char *data;
1755         int doffset, curoffset;
1756
1757         rxh = (struct rx_header *) &pd[offset];
1758         data = (char *)rxh + sizeof(struct rx_header);
1759         doffset = offset + sizeof(struct rx_header);
1760         curoffset = doffset;
1761
1762         /* skip opcode */
1763         SKIP(sizeof(guint32));
1764
1765         switch ( opcode )
1766         {
1767                 case 500: /* new user */
1768                         STROUT(hf_afs_prot_name);
1769                         UINTOUT(hf_afs_prot_id);
1770                         UINTOUT(hf_afs_prot_oldid);
1771                         break;
1772                 case 501: /* where is it */
1773                 case 506: /* delete */
1774                 case 508: /* get cps */
1775                 case 512: /* list entry */
1776                 case 514: /* list elements */
1777                 case 517: /* list owned */
1778                 case 519: /* get host cps */
1779                         UINTOUT(hf_afs_prot_id);
1780                         break;
1781                 case 502: /* dump entry */
1782                         UINTOUT(hf_afs_prot_pos);
1783                         break;
1784                 case 503: /* add to group */
1785                 case 507: /* remove from group */
1786                 case 515: /* is a member of? */
1787                         UINTOUT(hf_afs_prot_uid);
1788                         UINTOUT(hf_afs_prot_gid);
1789                         break;
1790                 case 504: /* name to id */
1791                         {
1792                                 unsigned int i, j;
1793
1794                                 TRUNC(4);
1795                                 j = GETINT();
1796                                 UINTOUT(hf_afs_prot_count);
1797
1798                                 for (i=0; i<j; i++)
1799                                 {
1800                                         VECOUT(hf_afs_prot_name,PRNAMEMAX);
1801                                 }
1802                         }
1803                         break;
1804                 case 505: /* id to name */
1805                         {
1806                                 unsigned int i, j;
1807
1808                                 TRUNC(4);
1809                                 j = GETINT();
1810                                 UINTOUT(hf_afs_prot_count);
1811
1812                                 for (i=0; i<j; i++)
1813                                 {
1814                                         UINTOUT(hf_afs_prot_id);
1815                                 }
1816                         }
1817                         break;
1818                 case 509: /* new entry */
1819                         STROUT(hf_afs_prot_name);
1820                         UINTOUT(hf_afs_prot_flag);
1821                         UINTOUT(hf_afs_prot_oldid);
1822                         break;
1823                 case 511: /* set max */
1824                         UINTOUT(hf_afs_prot_id);
1825                         UINTOUT(hf_afs_prot_flag);
1826                         break;
1827                 case 513: /* change entry */
1828                         UINTOUT(hf_afs_prot_id);
1829                         STROUT(hf_afs_prot_name);
1830                         UINTOUT(hf_afs_prot_oldid);
1831                         UINTOUT(hf_afs_prot_newid);
1832                         break;
1833                 case 520: /* update entry */
1834                         UINTOUT(hf_afs_prot_id);
1835                         STROUT(hf_afs_prot_name);
1836                         break;
1837         }
1838 }
1839
1840 /*
1841  * VLDB Helpers
1842  */
1843 static void
1844 dissect_vldb_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1845 {
1846         struct rx_header *rxh;
1847         unsigned char *data;
1848         int doffset, curoffset;
1849
1850         rxh = (struct rx_header *) &pd[offset];
1851         data = (char *)rxh + sizeof(struct rx_header);
1852         doffset = offset + sizeof(struct rx_header);
1853         curoffset = doffset;
1854
1855         if ( rxh->type == RX_PACKET_TYPE_DATA )
1856         {
1857                 switch ( opcode )
1858                 {
1859                         case 510: /* list entry */
1860                                 UINTOUT(hf_afs_vldb_count);
1861                                 UINTOUT(hf_afs_vldb_nextindex);
1862                                 break;
1863                         case 503: /* get entry by id */
1864                         case 504: /* get entry by name */
1865                                 {
1866                                         int nservers,i,j;
1867                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1868                                         TRUNC(4);
1869                                         nservers = GETINT();
1870                                         UINTOUT(hf_afs_vldb_numservers);
1871                                         for (i=0; i<8; i++)
1872                                         {
1873                                                 if ( i<nservers )
1874                                                 {
1875                                                         IPOUT(hf_afs_vldb_server);
1876                                                 }
1877                                                 else
1878                                                 {
1879                                                         SKIP(4);
1880                                                 }
1881                                         }
1882                                         for (i=0; i<8; i++)
1883                                         {
1884                                                 char part[8];
1885                                                 TRUNC(4);
1886                                                 j = GETINT();
1887                                                 strcpy(part, "/vicepa");
1888                                                 if ( i<nservers && j<=25 )
1889                                                 {
1890                                                         part[6] = 'a' + (char) j;
1891                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, NullTVB,
1892                                                                 curoffset, 4, part);
1893                                                 }
1894                                                 SKIP(4);
1895                                         }
1896                                         SKIP(8 * sizeof(guint32));
1897                                         UINTOUT(hf_afs_vldb_rwvol);
1898                                         UINTOUT(hf_afs_vldb_rovol);
1899                                         UINTOUT(hf_afs_vldb_bkvol);
1900                                 }
1901                                 break;
1902                         case 505: /* get new volume id */
1903                                 UINTOUT(hf_afs_vldb_id);
1904                                 break;
1905                         case 521: /* list entry */
1906                         case 529: /* list entry U */
1907                                 UINTOUT(hf_afs_vldb_count);
1908                                 UINTOUT(hf_afs_vldb_nextindex);
1909                                 break;
1910                         case 518: /* get entry by id n */
1911                         case 519: /* get entry by name N */
1912                                 {
1913                                         int nservers,i,j;
1914                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1915                                         TRUNC(4);
1916                                         nservers = GETINT();
1917                                         UINTOUT(hf_afs_vldb_numservers);
1918                                         for (i=0; i<13; i++)
1919                                         {
1920                                                 if ( i<nservers )
1921                                                 {
1922                                                         IPOUT(hf_afs_vldb_server);
1923                                                 }
1924                                                 else
1925                                                 {
1926                                                         SKIP(4);
1927                                                 }
1928                                         }
1929                                         for (i=0; i<13; i++)
1930                                         {
1931                                                 char part[8];
1932                                                 TRUNC(4);
1933                                                 j = GETINT();
1934                                                 strcpy(part, "/vicepa");
1935                                                 if ( i<nservers && j<=25 )
1936                                                 {
1937                                                         part[6] = 'a' + (char) j;
1938                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, NullTVB,
1939                                                                 curoffset, 4, part);
1940                                                 }
1941                                                 SKIP(4);
1942                                         }
1943                                         SKIP(13 * sizeof(guint32));
1944                                         UINTOUT(hf_afs_vldb_rwvol);
1945                                         UINTOUT(hf_afs_vldb_rovol);
1946                                         UINTOUT(hf_afs_vldb_bkvol);
1947                                 }
1948                                 break;
1949                         case 526: /* get entry by id u */
1950                         case 527: /* get entry by name u */
1951                                 {
1952                                         int nservers,i,j;
1953                                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
1954                                         TRUNC(4);
1955                                         nservers = GETINT();
1956                                         UINTOUT(hf_afs_vldb_numservers);
1957                                         for (i=0; i<13; i++)
1958                                         {
1959                                                 if ( i<nservers )
1960                                                 {
1961                                                         BYTESOUT(hf_afs_vldb_serveruuid, 11*sizeof(guint32));
1962                                                 }
1963                                                 else
1964                                                 {
1965                                                         SKIP(11*sizeof(guint32));
1966                                                 }
1967                                         }
1968                                         for (i=0; i<13; i++)
1969                                         {
1970                                                 char part[8];
1971                                                 TRUNC(4);
1972                                                 j = GETINT();
1973                                                 strcpy(part, "/vicepa");
1974                                                 if ( i<nservers && j<=25 )
1975                                                 {
1976                                                         part[6] = 'a' + (char) j;
1977                                                         proto_tree_add_string(tree, hf_afs_vldb_partition, NullTVB,
1978                                                                 curoffset, 4, part);
1979                                                 }
1980                                                 SKIP(4);
1981                                         }
1982                                         SKIP(13 * sizeof(guint32));
1983                                         UINTOUT(hf_afs_vldb_rwvol);
1984                                         UINTOUT(hf_afs_vldb_rovol);
1985                                         UINTOUT(hf_afs_vldb_bkvol);
1986                                 }
1987                                 break;
1988                 }
1989         }
1990         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
1991         {
1992                 UINTOUT(hf_afs_vldb_errcode);
1993         }
1994 }
1995
1996 static void
1997 dissect_vldb_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
1998 {
1999         struct rx_header *rxh;
2000         unsigned char *data;
2001         int doffset, curoffset;
2002
2003         rxh = (struct rx_header *) &pd[offset];
2004         data = (char *)rxh + sizeof(struct rx_header);
2005         doffset = offset + sizeof(struct rx_header);
2006         curoffset = doffset;
2007
2008         /* skip opcode */
2009         SKIP(sizeof(guint32));
2010
2011         switch ( opcode )
2012         {
2013                 case 501: /* create new volume */
2014                 case 517: /* create entry N */
2015                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
2016                         break;
2017                 case 502: /* delete entry */
2018                 case 503: /* get entry by id */
2019                 case 507: /* update entry */
2020                 case 508: /* set lock */
2021                 case 509: /* release lock */
2022                 case 518: /* get entry by id */
2023                         UINTOUT(hf_afs_vldb_id);
2024                         UINTOUT(hf_afs_vldb_type);
2025                         break;
2026                 case 504: /* get entry by name */
2027                 case 519: /* get entry by name N */
2028                 case 524: /* update entry by name */
2029                 case 527: /* get entry by name U */
2030                         STROUT(hf_afs_vldb_name);
2031                         break;
2032                 case 505: /* get new vol id */
2033                         UINTOUT(hf_afs_vldb_bump);
2034                         break;
2035                 case 506: /* replace entry */
2036                 case 520: /* replace entry N */
2037                         UINTOUT(hf_afs_vldb_id);
2038                         UINTOUT(hf_afs_vldb_type);
2039                         VECOUT(hf_afs_vldb_name, VLNAMEMAX);
2040                         break;
2041                 case 510: /* list entry */
2042                 case 521: /* list entry N */
2043                         UINTOUT(hf_afs_vldb_index);
2044                         break;
2045         }
2046 }
2047
2048 /*
2049  * UBIK Helpers
2050  */
2051 static void
2052 dissect_ubik_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2053 {
2054         struct rx_header *rxh;
2055         unsigned char *data;
2056         int doffset, curoffset;
2057
2058         rxh = (struct rx_header *) &pd[offset];
2059         data = (char *)rxh + sizeof(struct rx_header);
2060         doffset = offset + sizeof(struct rx_header);
2061         curoffset = doffset;
2062
2063         if ( rxh->type == RX_PACKET_TYPE_DATA )
2064         {
2065                 switch ( opcode )
2066                 {
2067                         case 10000: /* beacon */
2068                                 proto_tree_add_boolean(tree,hf_afs_ubik_votetype, NullTVB,0,0,0);
2069                                 break;
2070                         case 20004: /* get version */
2071                                 UBIK_VERSIONOUT("DB Version");
2072                                 break;
2073                 }
2074         }
2075         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
2076         {
2077                 switch ( opcode )
2078                 {
2079                         case 10000:
2080                                 proto_tree_add_boolean(tree,hf_afs_ubik_votetype, NullTVB,0,0,1);
2081                                 DATEOUT(hf_afs_ubik_voteend);
2082                                 break;
2083                         default:
2084                                 UINTOUT(hf_afs_ubik_errcode);
2085                                 break;
2086                 }
2087         }
2088 }
2089
2090 static void
2091 dissect_ubik_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2092 {
2093         struct rx_header *rxh;
2094         unsigned char *data;
2095         int doffset, curoffset;
2096
2097         rxh = (struct rx_header *) &pd[offset];
2098         data = (char *)rxh + sizeof(struct rx_header);
2099         doffset = offset + sizeof(struct rx_header);
2100         curoffset = doffset;
2101
2102         /* skip opcode */
2103         SKIP(sizeof(guint32));
2104
2105         switch ( opcode )
2106         {
2107                 case 10000: /* beacon */
2108                         UINTOUT(hf_afs_ubik_syncsite);
2109                         DATEOUT(hf_afs_ubik_votestart);
2110                         UBIK_VERSIONOUT("DB Version");
2111                         UBIK_VERSIONOUT("TID");
2112                         break;
2113                 case 10003: /* get sync site */
2114                         IPOUT(hf_afs_ubik_site);
2115                         break;
2116                 case 20000: /* begin */
2117                 case 20001: /* commit */
2118                 case 20007: /* abort */
2119                 case 20008: /* release locks */
2120                 case 20010: /* writev */
2121                         UBIK_VERSIONOUT("TID");
2122                         break;
2123                 case 20002: /* lock */
2124                         UBIK_VERSIONOUT("TID");
2125                         UINTOUT(hf_afs_ubik_file);
2126                         UINTOUT(hf_afs_ubik_pos);
2127                         UINTOUT(hf_afs_ubik_length);
2128                         UINTOUT(hf_afs_ubik_locktype);
2129                         break;
2130                 case 20003: /* write */
2131                         UBIK_VERSIONOUT("TID");
2132                         UINTOUT(hf_afs_ubik_file);
2133                         UINTOUT(hf_afs_ubik_pos);
2134                         break;
2135                 case 20005: /* get file */
2136                         UINTOUT(hf_afs_ubik_file);
2137                         break;
2138                 case 20006: /* send file */
2139                         UINTOUT(hf_afs_ubik_file);
2140                         UINTOUT(hf_afs_ubik_length);
2141                         UBIK_VERSIONOUT("DB Version");
2142                         break;
2143                 case 20009: /* truncate */
2144                         UBIK_VERSIONOUT("TID");
2145                         UINTOUT(hf_afs_ubik_file);
2146                         UINTOUT(hf_afs_ubik_length);
2147                         break;
2148                 case 20012: /* set version */
2149                         UBIK_VERSIONOUT("TID");
2150                         UBIK_VERSIONOUT("Old DB Version");
2151                         UBIK_VERSIONOUT("New DB Version");
2152                         break;
2153         }
2154 }
2155
2156 /*
2157  * BACKUP Helpers
2158  */
2159 static void
2160 dissect_backup_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2161 {
2162         struct rx_header *rxh;
2163         unsigned char *data;
2164         int doffset, curoffset;
2165
2166         rxh = (struct rx_header *) &pd[offset];
2167         data = (char *)rxh + sizeof(struct rx_header);
2168         doffset = offset + sizeof(struct rx_header);
2169         curoffset = doffset;
2170
2171         if ( rxh->type == RX_PACKET_TYPE_DATA )
2172         {
2173                 switch ( opcode )
2174                 {
2175                 }
2176         }
2177         else if ( rxh->type == RX_PACKET_TYPE_ABORT )
2178         {
2179                 UINTOUT(hf_afs_backup_errcode);
2180         }
2181 }
2182
2183 static void
2184 dissect_backup_request(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int opcode)
2185 {
2186         struct rx_header *rxh;
2187         unsigned char *data;
2188         int doffset, curoffset;
2189
2190         rxh = (struct rx_header *) &pd[offset];
2191         data = (char *)rxh + sizeof(struct rx_header);
2192         doffset = offset + sizeof(struct rx_header);
2193         curoffset = doffset;
2194
2195         /* skip opcode */
2196         SKIP(sizeof(guint32));
2197
2198         switch ( opcode )
2199         {
2200         }
2201 }
2202
2203 /*
2204  * Registration code for registering the protocol and fields
2205  */
2206
2207 void
2208 proto_register_afs(void)
2209 {
2210         static hf_register_info hf[] = {
2211
2212                 { &hf_afs_fs, {
2213                         "File Server", "afs.fs", FT_BOOLEAN, BASE_NONE,
2214                         0, 0, "File Server" }},
2215                 { &hf_afs_cb, {
2216                         "Callback", "afs.cb", FT_BOOLEAN, BASE_NONE,
2217                         0, 0, "Callback" }},
2218                 { &hf_afs_prot, {
2219                         "Protection", "afs.prot", FT_BOOLEAN, BASE_NONE,
2220                         0, 0, "Protection" }},
2221                 { &hf_afs_vldb, {
2222                         "VLDB", "afs.vldb", FT_BOOLEAN, BASE_NONE,
2223                         0, 0, "VLDB" }},
2224                 { &hf_afs_kauth, {
2225                         "Kauth", "afs.kauth", FT_BOOLEAN, BASE_NONE,
2226                         0, 0, "Kauth" }},
2227                 { &hf_afs_vol, {
2228                         "Volume Server", "afs.vol", FT_BOOLEAN, BASE_NONE,
2229                         0, 0, "Volume Server" }},
2230                 { &hf_afs_error, {
2231                         "Error", "afs.error", FT_BOOLEAN, BASE_NONE,
2232                         0, 0, "Error" }},
2233                 { &hf_afs_bos, {
2234                         "BOS", "afs.bos", FT_BOOLEAN, BASE_NONE,
2235                         0, 0, "BOS" }},
2236                 { &hf_afs_update, {
2237                         "Update", "afs.update", FT_BOOLEAN, BASE_NONE,
2238                         0, 0, "Update" }},
2239                 { &hf_afs_rmtsys, {
2240                         "Rmtsys", "afs.rmtsys", FT_BOOLEAN, BASE_NONE,
2241                         0, 0, "Rmtsys" }},
2242                 { &hf_afs_ubik, {
2243                         "Ubik", "afs.ubik", FT_BOOLEAN, BASE_NONE,
2244                         0, 0, "Ubik" }},
2245                 { &hf_afs_backup, {
2246                         "Backup", "afs.backup", FT_BOOLEAN, BASE_NONE,
2247                         0, 0, "Backup" }},
2248
2249                 { &hf_afs_fs_opcode, {
2250                         "Operation", "afs.fs.opcode", FT_UINT32, BASE_DEC,
2251                         VALS(fs_req), 0, "Operation" }},
2252                 { &hf_afs_cb_opcode, {
2253                         "Operation", "afs.cb.opcode", FT_UINT32, BASE_DEC,
2254                         VALS(cb_req), 0, "Operation" }},
2255                 { &hf_afs_prot_opcode, {
2256                         "Operation", "afs.prot.opcode", FT_UINT32, BASE_DEC,
2257                         VALS(prot_req), 0, "Operation" }},
2258                 { &hf_afs_vldb_opcode, {
2259                         "Operation", "afs.vldb.opcode", FT_UINT32, BASE_DEC,
2260                         VALS(vldb_req), 0, "Operation" }},
2261                 { &hf_afs_kauth_opcode, {
2262                         "Operation", "afs.kauth.opcode", FT_UINT32, BASE_DEC,
2263                         VALS(kauth_req), 0, "Operation" }},
2264                 { &hf_afs_vol_opcode, {
2265                         "Operation", "afs.vol.opcode", FT_UINT32, BASE_DEC,
2266                         VALS(vol_req), 0, "Operation" }},
2267                 { &hf_afs_bos_opcode, {
2268                         "Operation", "afs.bos.opcode", FT_UINT32, BASE_DEC,
2269                         VALS(bos_req), 0, "Operation" }},
2270                 { &hf_afs_update_opcode, {
2271                         "Operation", "afs.update.opcode", FT_UINT32, BASE_DEC,
2272                         0, 0, "Operation" }},
2273                 { &hf_afs_rmtsys_opcode, {
2274                         "Operation", "afs.rmtsys.opcode", FT_UINT32, BASE_DEC,
2275                         0, 0, "Operation" }},
2276                 { &hf_afs_error_opcode, {
2277                         "Operation", "afs.error.opcode", FT_UINT32, BASE_DEC,
2278                         0, 0, "Operation" }},
2279                 { &hf_afs_backup_opcode, {
2280                         "Operation", "afs.backup.opcode", FT_UINT32, BASE_DEC,
2281                         0, 0, "Operation" }},
2282                 { &hf_afs_ubik_opcode, {
2283                         "Operation", "afs.ubik.opcode", FT_UINT32, BASE_DEC,
2284                         VALS(ubik_req), 0, "Operation" }},
2285
2286
2287                 /* File Server Fields */
2288                 { &hf_afs_fs_fid_volume, {
2289                         "FileID (Volume)", "afs.fs.fid.volume", FT_UINT32, BASE_DEC,
2290                         0, 0, "File ID (Volume)" }},
2291                 { &hf_afs_fs_fid_vnode, {
2292                         "FileID (VNode)", "afs.fs.fid.vnode", FT_UINT32, BASE_DEC,
2293                         0, 0, "File ID (VNode)" }},
2294                 { &hf_afs_fs_fid_uniqifier, {
2295                         "FileID (Uniqifier)", "afs.fs.fid.uniq", FT_UINT32, BASE_DEC,
2296                         0, 0, "File ID (Uniqifier)" }},
2297                 { &hf_afs_fs_offset, {
2298                         "Offset", "afs.fs.offset", FT_UINT32, BASE_DEC,
2299                         0, 0, "Offset" }},
2300                 { &hf_afs_fs_length, {
2301                         "Length", "afs.fs.length", FT_UINT32, BASE_DEC,
2302                         0, 0, "Length" }},
2303                 { &hf_afs_fs_flength, {
2304                         "FLength", "afs.fs.flength", FT_UINT32, BASE_DEC,
2305                         0, 0, "FLength" }},
2306                 { &hf_afs_fs_errcode, {
2307                         "Error Code", "afs.fs.errcode", FT_UINT32, BASE_DEC,
2308                         VALS(afs_errors), 0, "Error Code" }},
2309                 { &hf_afs_fs_data, {
2310                         "Data", "afs.fs.data", FT_BYTES, BASE_HEX,
2311                         0, 0, "Data" }},
2312                 { &hf_afs_fs_oldname, {
2313                         "Old Name", "afs.fs.oldname", FT_STRING, BASE_HEX,
2314                         0, 0, "Old Name" }},
2315                 { &hf_afs_fs_newname, {
2316                         "New Name", "afs.fs.newname", FT_STRING, BASE_HEX,
2317                         0, 0, "New Name" }},
2318                 { &hf_afs_fs_name, {
2319                         "Name", "afs.fs.name", FT_STRING, BASE_HEX,
2320                         0, 0, "Name" }},
2321                 { &hf_afs_fs_symlink_name, {
2322                         "Symlink Name", "afs.fs.symlink.name", FT_STRING, BASE_HEX,
2323                         0, 0, "Symlink Name" }},
2324                 { &hf_afs_fs_symlink_content, {
2325                         "Symlink Content", "afs.fs.symlink.content", FT_STRING, BASE_HEX,
2326                         0, 0, "Symlink Content" }},
2327                 { &hf_afs_fs_volid, {
2328                         "Volume ID", "afs.fs.volid", FT_UINT32, BASE_DEC,
2329                         0, 0, "Volume ID" }},
2330                 { &hf_afs_fs_volname, {
2331                         "Volume Name", "afs.fs.volname", FT_STRING, BASE_HEX,
2332                         0, 0, "Volume Name" }},
2333                 { &hf_afs_fs_timestamp, {
2334                         "Timestamp", "afs.fs.timestamp", FT_ABSOLUTE_TIME, BASE_DEC,
2335                         0, 0, "Timestamp" }},
2336
2337                 { &hf_afs_fs_acl_count_positive, {
2338                         "ACL Count (Positive)", "afs.fs.acl.count.positive", FT_UINT32, BASE_DEC,
2339                         0, 0, "Number of Positive ACLs" }},
2340                 { &hf_afs_fs_acl_count_negative, {
2341                         "ACL Count (Negative)", "afs.fs.acl.count.negative", FT_UINT32, BASE_DEC,
2342                         0, 0, "Number of Negative ACLs" }},
2343                 { &hf_afs_fs_acl_datasize, {
2344                         "ACL Size", "afs.fs.acl.datasize", FT_UINT32, BASE_DEC,
2345                         0, 0, "ACL Data Size" }},
2346                 { &hf_afs_fs_acl_entity, {
2347                         "Entity (User/Group)", "afs.fs.acl.entity", FT_STRING, BASE_HEX,
2348                         0, 0, "ACL Entity (User/Group)" }},
2349                 { &hf_afs_fs_acl_r, {
2350                         "_R_ead", "afs.fs.acl.r", FT_UINT8, BASE_BIN,
2351                         0, PRSFS_READ, "Read" }},
2352                 { &hf_afs_fs_acl_l, {
2353                         "_L_ookup", "afs.fs.acl.l", FT_UINT8, BASE_BIN,
2354                         0, PRSFS_LOOKUP, "Lookup" }},
2355                 { &hf_afs_fs_acl_i, {
2356                         "_I_nsert", "afs.fs.acl.i", FT_UINT8, BASE_BIN,
2357                         0, PRSFS_INSERT, "Insert" }},
2358                 { &hf_afs_fs_acl_d, {
2359                         "_D_elete", "afs.fs.acl.d", FT_UINT8, BASE_BIN,
2360                         0, PRSFS_DELETE, "Delete" }},
2361                 { &hf_afs_fs_acl_w, {
2362                         "_W_rite", "afs.fs.acl.w", FT_UINT8, BASE_BIN,
2363                         0, PRSFS_WRITE, "Write" }},
2364                 { &hf_afs_fs_acl_k, {
2365                         "_L_ock", "afs.fs.acl.k", FT_UINT8, BASE_BIN,
2366                         0, PRSFS_LOCK, "Lock" }},
2367                 { &hf_afs_fs_acl_a, {
2368                         "_A_dminister", "afs.fs.acl.a", FT_UINT8, BASE_BIN,
2369                         0, PRSFS_ADMINISTER, "Administer" }},
2370
2371                 { &hf_afs_fs_callback_version, {
2372                         "Version", "afs.fs.callback.version", FT_UINT32, BASE_DEC,
2373                         0, 0, "Version" }},
2374                 { &hf_afs_fs_callback_expires, {
2375                         "Expires", "afs.fs.callback.expires", FT_ABSOLUTE_TIME, BASE_DEC,
2376                         0, 0, "Expires" }},
2377                 { &hf_afs_fs_callback_type, {
2378                         "Type", "afs.fs.callback.type", FT_UINT32, BASE_DEC,
2379                         VALS(cb_types), 0, "Type" }},
2380
2381                 /* BOS Server Fields */
2382                 { &hf_afs_bos_errcode, {
2383                         "Error Code", "afs.bos.errcode", FT_UINT32, BASE_DEC,
2384                         VALS(afs_errors), 0, "Error Code" }},
2385                 { &hf_afs_bos_type, {
2386                         "Type", "afs.bos.type", FT_STRING, BASE_HEX,
2387                         0, 0, "Type" }},
2388                 { &hf_afs_bos_content, {
2389                         "Content", "afs.bos.content", FT_STRING, BASE_HEX,
2390                         0, 0, "Content" }},
2391                 { &hf_afs_bos_instance, {
2392                         "Instance", "afs.bos.instance", FT_STRING, BASE_HEX,
2393                         0, 0, "Instance" }},
2394                 { &hf_afs_bos_status, {
2395                         "Status", "afs.bos.status", FT_INT32, BASE_DEC,
2396                         0, 0, "Status" }},
2397                 { &hf_afs_bos_num, {
2398                         "Number", "afs.bos.number", FT_UINT32, BASE_DEC,
2399                         0, 0, "Number" }},
2400                 { &hf_afs_bos_size, {
2401                         "Size", "afs.bos.size", FT_UINT32, BASE_DEC,
2402                         0, 0, "Size" }},
2403                 { &hf_afs_bos_flags, {
2404                         "Flags", "afs.bos.flags", FT_UINT32, BASE_DEC,
2405                         0, 0, "Flags" }},
2406                 { &hf_afs_bos_date, {
2407                         "Date", "afs.bos.date", FT_UINT32, BASE_DEC,
2408                         0, 0, "Date" }},
2409
2410                 /* KAUTH Server Fields */
2411                 { &hf_afs_kauth_errcode, {
2412                         "Error Code", "afs.kauth.errcode", FT_UINT32, BASE_DEC,
2413                         VALS(afs_errors), 0, "Error Code" }},
2414                 { &hf_afs_kauth_princ, {
2415                         "Principal", "afs.kauth.princ", FT_STRING, BASE_HEX,
2416                         0, 0, "Principal" }},
2417                 { &hf_afs_kauth_realm, {
2418                         "Realm", "afs.kauth.realm", FT_STRING, BASE_HEX,
2419                         0, 0, "Realm" }},
2420                 { &hf_afs_kauth_domain, {
2421                         "Domain", "afs.kauth.domain", FT_STRING, BASE_HEX,
2422                         0, 0, "Domain" }},
2423                 { &hf_afs_kauth_name, {
2424                         "Name", "afs.kauth.name", FT_STRING, BASE_HEX,
2425                         0, 0, "Name" }},
2426                 { &hf_afs_kauth_data, {
2427                         "Data", "afs.kauth.data", FT_BYTES, BASE_HEX,
2428                         0, 0, "Data" }},
2429                 { &hf_afs_kauth_kvno, {
2430                         "Key Version Number", "afs.kauth.kvno", FT_UINT32, BASE_DEC,
2431                         0, 0, "Key Version Number" }},
2432
2433                 /* VOL Server Fields */
2434                 { &hf_afs_vol_errcode, {
2435                         "Error Code", "afs.vol.errcode", FT_UINT32, BASE_DEC,
2436                         VALS(afs_errors), 0, "Error Code" }},
2437                 { &hf_afs_vol_id, {
2438                         "Volume ID", "afs.vol.id", FT_UINT32, BASE_DEC,
2439                         0, 0, "Volume ID" }},
2440                 { &hf_afs_vol_count, {
2441                         "Volume Count", "afs.vol.count", FT_UINT32, BASE_DEC,
2442                         0, 0, "Volume Count" }},
2443                 { &hf_afs_vol_name, {
2444                         "Volume Name", "afs.vol.name", FT_STRING, BASE_HEX,
2445                         0, 0, "Volume Name" }},
2446
2447                 /* VLDB Server Fields */
2448                 { &hf_afs_vldb_errcode, {
2449                         "Error Code", "afs.vldb.errcode", FT_UINT32, BASE_DEC,
2450                         VALS(afs_errors), 0, "Error Code" }},
2451                 { &hf_afs_vldb_type, {
2452                         "Volume Type", "afs.vldb.type", FT_UINT32, BASE_DEC,
2453                         VALS(volume_types), 0, "Volume Type" }},
2454                 { &hf_afs_vldb_id, {
2455                         "Volume ID", "afs.vldb.id", FT_UINT32, BASE_DEC,
2456                         0, 0, "Volume ID" }},
2457                 { &hf_afs_vldb_bump, {
2458                         "Bumped Volume ID", "afs.vldb.bump", FT_UINT32, BASE_DEC,
2459                         0, 0, "Bumped Volume ID" }},
2460                 { &hf_afs_vldb_index, {
2461                         "Volume Index", "afs.vldb.index", FT_UINT32, BASE_DEC,
2462                         0, 0, "Volume Index" }},
2463                 { &hf_afs_vldb_count, {
2464                         "Volume Count", "afs.vldb.count", FT_UINT32, BASE_DEC,
2465                         0, 0, "Volume Count" }},
2466                 { &hf_afs_vldb_numservers, {
2467                         "Number of Servers", "afs.vldb.numservers", FT_UINT32, BASE_DEC,
2468                         0, 0, "Number of Servers" }},
2469                 { &hf_afs_vldb_nextindex, {
2470                         "Next Volume Index", "afs.vldb.nextindex", FT_UINT32, BASE_DEC,
2471                         0, 0, "Next Volume Index" }},
2472                 { &hf_afs_vldb_rovol, {
2473                         "Read-Only Volume ID", "afs.vldb.rovol", FT_UINT32, BASE_DEC,
2474                         0, 0, "Read-Only Volume ID" }},
2475                 { &hf_afs_vldb_rwvol, {
2476                         "Read-Write Volume ID", "afs.vldb.rwvol", FT_UINT32, BASE_DEC,
2477                         0, 0, "Read-Only Volume ID" }},
2478                 { &hf_afs_vldb_bkvol, {
2479                         "Backup Volume ID", "afs.vldb.bkvol", FT_UINT32, BASE_DEC,
2480                         0, 0, "Read-Only Volume ID" }},
2481                 { &hf_afs_vldb_name, {
2482                         "Volume Name", "afs.vldb.name", FT_STRING, BASE_HEX,
2483                         0, 0, "Volume Name" }},
2484                 { &hf_afs_vldb_partition, {
2485                         "Partition", "afs.vldb.partition", FT_STRING, BASE_HEX,
2486                         0, 0, "Partition" }},
2487                 { &hf_afs_vldb_server, {
2488                         "Server", "afs.vldb.server", FT_IPv4, BASE_HEX,
2489                         0, 0, "Server" }},
2490                 { &hf_afs_vldb_serveruuid, {
2491                         "Server UUID", "afs.vldb.serveruuid", FT_BYTES, BASE_HEX,
2492                         0, 0, "Server UUID" }},
2493
2494                 /* BACKUP Server Fields */
2495                 { &hf_afs_backup_errcode, {
2496                         "Error Code", "afs.backup.errcode", FT_UINT32, BASE_DEC,
2497                         VALS(afs_errors), 0, "Error Code" }},
2498
2499                 /* CB Server Fields */
2500                 { &hf_afs_cb_errcode, {
2501                         "Error Code", "afs.cb.errcode", FT_UINT32, BASE_DEC,
2502                         VALS(afs_errors), 0, "Error Code" }},
2503                 { &hf_afs_cb_callback_version, {
2504                         "Version", "afs.cb.callback.version", FT_UINT32, BASE_DEC,
2505                         0, 0, "Version" }},
2506                 { &hf_afs_cb_callback_expires, {
2507                         "Expires", "afs.cb.callback.expires", FT_ABSOLUTE_TIME, BASE_DEC,
2508                         0, 0, "Expires" }},
2509                 { &hf_afs_cb_callback_type, {
2510                         "Type", "afs.cb.callback.type", FT_UINT32, BASE_DEC,
2511                         VALS(cb_types), 0, "Type" }},
2512                 { &hf_afs_cb_fid_volume, {
2513                         "FileID (Volume)", "afs.cb.fid.volume", FT_UINT32, BASE_DEC,
2514                         0, 0, "File ID (Volume)" }},
2515                 { &hf_afs_cb_fid_vnode, {
2516                         "FileID (VNode)", "afs.cb.fid.vnode", FT_UINT32, BASE_DEC,
2517                         0, 0, "File ID (VNode)" }},
2518                 { &hf_afs_cb_fid_uniqifier, {
2519                         "FileID (Uniqifier)", "afs.cb.fid.uniq", FT_UINT32, BASE_DEC,
2520                         0, 0, "File ID (Uniqifier)" }},
2521
2522                 /* PROT Server Fields */
2523                 { &hf_afs_prot_errcode, {
2524                         "Error Code", "afs.prot.errcode", FT_UINT32, BASE_DEC,
2525                         VALS(afs_errors), 0, "Error Code" }},
2526                 { &hf_afs_prot_name, {
2527                         "Name", "afs.prot.name", FT_STRING, BASE_HEX,
2528                         0, 0, "Name" }},
2529                 { &hf_afs_prot_id, {
2530                         "ID", "afs.prot.id", FT_UINT32, BASE_DEC,
2531                         0, 0, "ID" }},
2532                 { &hf_afs_prot_oldid, {
2533                         "Old ID", "afs.prot.oldid", FT_UINT32, BASE_DEC,
2534                         0, 0, "Old ID" }},
2535                 { &hf_afs_prot_newid, {
2536                         "New ID", "afs.prot.newid", FT_UINT32, BASE_DEC,
2537                         0, 0, "New ID" }},
2538                 { &hf_afs_prot_gid, {
2539                         "Group ID", "afs.prot.gid", FT_UINT32, BASE_DEC,
2540                         0, 0, "Group ID" }},
2541                 { &hf_afs_prot_uid, {
2542                         "User ID", "afs.prot.uid", FT_UINT32, BASE_DEC,
2543                         0, 0, "User ID" }},
2544                 { &hf_afs_prot_count, {
2545                         "Count", "afs.prot.count", FT_UINT32, BASE_DEC,
2546                         0, 0, "Count" }},
2547                 { &hf_afs_prot_maxgid, {
2548                         "Maximum Group ID", "afs.prot.maxgid", FT_UINT32, BASE_DEC,
2549                         0, 0, "Maximum Group ID" }},
2550                 { &hf_afs_prot_maxuid, {
2551                         "Maximum User ID", "afs.prot.maxuid", FT_UINT32, BASE_DEC,
2552                         0, 0, "Maximum User ID" }},
2553                 { &hf_afs_prot_pos, {
2554                         "Position", "afs.prot.pos", FT_UINT32, BASE_DEC,
2555                         0, 0, "Position" }},
2556                 { &hf_afs_prot_flag, {
2557                         "Flag", "afs.prot.flag", FT_UINT32, BASE_HEX,
2558                         0, 0, "Flag" }},
2559
2560                 /* UBIK Fields */
2561                 { &hf_afs_ubik_errcode, {
2562                         "Error Code", "afs.ubik.errcode", FT_UINT32, BASE_DEC,
2563                         VALS(afs_errors), 0, "Error Code" }},
2564                 { &hf_afs_ubik_version_epoch, {
2565                         "Epoch", "afs.ubik.version.epoch", FT_ABSOLUTE_TIME, BASE_DEC,
2566                         0, 0, "Epoch" }},
2567                 { &hf_afs_ubik_votestart, {
2568                         "Vote Started", "afs.ubik.votestart", FT_ABSOLUTE_TIME, BASE_DEC,
2569                         0, 0, "Vote Started" }},
2570                 { &hf_afs_ubik_voteend, {
2571                         "Vote Ends", "afs.ubik.voteend", FT_ABSOLUTE_TIME, BASE_DEC,
2572                         0, 0, "Vote Ends" }},
2573                 { &hf_afs_ubik_version_counter, {
2574                         "Counter", "afs.ubik.version.counter", FT_UINT32, BASE_DEC,
2575                         0, 0, "Counter" }},
2576                 { &hf_afs_ubik_file, {
2577                         "File", "afs.ubik.file", FT_UINT32, BASE_DEC,
2578                         0, 0, "File" }},
2579                 { &hf_afs_ubik_pos, {
2580                         "Position", "afs.ubik.position", FT_UINT32, BASE_DEC,
2581                         0, 0, "Position" }},
2582                 { &hf_afs_ubik_length, {
2583                         "Length", "afs.ubik.length", FT_UINT32, BASE_DEC,
2584                         0, 0, "Length" }},
2585                 { &hf_afs_ubik_locktype, {
2586                         "Lock Type", "afs.ubik.locktype", FT_UINT32, BASE_DEC,
2587                         VALS(ubik_lock_types), 0, "Lock Type" }},
2588                 { &hf_afs_ubik_votetype, {
2589                         "Vote Type", "afs.ubik.votetype", FT_BOOLEAN, BASE_HEX,
2590                         0, 0, "Vote Type" }},
2591                 { &hf_afs_ubik_syncsite, {
2592                         "Syncsite", "afs.ubik.syncsite", FT_BOOLEAN, BASE_HEX,
2593                         0, 0, "Syncsite" }},
2594                 { &hf_afs_ubik_site, {
2595                         "Site", "afs.ubik.site", FT_IPv4, BASE_HEX,
2596                         0, 0, "Site" }},
2597
2598         };
2599         static gint *ett[] = {
2600                 &ett_afs,
2601                 &ett_afs_op,
2602                 &ett_afs_acl,
2603                 &ett_afs_fid,
2604                 &ett_afs_callback,
2605                 &ett_afs_ubikver,
2606         };
2607
2608         proto_afs = proto_register_protocol("Andrew File System (AFS)", "afs");
2609         proto_register_field_array(proto_afs, hf, array_length(hf));
2610         proto_register_subtree_array(ett, array_length(ett));
2611         register_init_routine(&afs_init_protocol);
2612 }