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